|
|
|
@ -1,15 +1,20 @@
@@ -1,15 +1,20 @@
|
|
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
|
import 'package:syncfusion_flutter_datagrid/datagrid.dart'; |
|
|
|
|
import 'package:win_text_editor/modules/uft_component/controllers/component_source.dart'; |
|
|
|
|
import 'package:win_text_editor/shared/base/base_data_source.dart'; |
|
|
|
|
import 'package:win_text_editor/shared/models/std_filed.dart'; |
|
|
|
|
|
|
|
|
|
class ComponentGrid extends StatelessWidget { |
|
|
|
|
class ComponentGrid extends StatefulWidget { |
|
|
|
|
final ComponentSource componentsSource; |
|
|
|
|
final Function(int index, bool isSelected)? onSelectionChanged; |
|
|
|
|
|
|
|
|
|
const ComponentGrid({super.key, required this.componentsSource, this.onSelectionChanged}); |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
State<ComponentGrid> createState() => ComponentGridState(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class ComponentGridState extends State<ComponentGrid> { |
|
|
|
|
final DataGridController _dataGridController = DataGridController(); |
|
|
|
|
|
|
|
|
|
Container _buildGridHeader(String text) { |
|
|
|
|
return Container( |
|
|
|
|
alignment: Alignment.center, |
|
|
|
@ -18,26 +23,9 @@ class ComponentGrid extends StatelessWidget {
@@ -18,26 +23,9 @@ class ComponentGrid extends StatelessWidget {
|
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Widget _buildCheckboxHeader<T extends SelectableItem>( |
|
|
|
|
BuildContext context, |
|
|
|
|
SelectableDataSource<T> dataSource, |
|
|
|
|
) { |
|
|
|
|
final allSelected = |
|
|
|
|
dataSource.items.isNotEmpty && dataSource.items.every((item) => item.isSelected); |
|
|
|
|
final someSelected = |
|
|
|
|
dataSource.items.isNotEmpty && |
|
|
|
|
dataSource.items.any((item) => item.isSelected) && |
|
|
|
|
!allSelected; |
|
|
|
|
|
|
|
|
|
return Container( |
|
|
|
|
alignment: Alignment.center, |
|
|
|
|
color: Colors.grey[200], |
|
|
|
|
child: Checkbox( |
|
|
|
|
value: allSelected, |
|
|
|
|
tristate: someSelected, |
|
|
|
|
onChanged: (value) => dataSource.toggleAllSelection(value ?? false), |
|
|
|
|
), |
|
|
|
|
); |
|
|
|
|
void scrollToIndex(int index) { |
|
|
|
|
_dataGridController.scrollToRow(index.toDouble()); |
|
|
|
|
_dataGridController.selectedIndex = index; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
@ -52,21 +40,13 @@ class ComponentGrid extends StatelessWidget {
@@ -52,21 +40,13 @@ class ComponentGrid extends StatelessWidget {
|
|
|
|
|
return SizedBox( |
|
|
|
|
width: constraints.maxWidth, |
|
|
|
|
child: SfDataGrid( |
|
|
|
|
source: componentsSource, |
|
|
|
|
controller: _dataGridController, |
|
|
|
|
source: widget.componentsSource, |
|
|
|
|
gridLinesVisibility: GridLinesVisibility.both, |
|
|
|
|
headerGridLinesVisibility: GridLinesVisibility.both, |
|
|
|
|
columnWidthMode: ColumnWidthMode.fitByCellValue, |
|
|
|
|
selectionMode: SelectionMode.none, |
|
|
|
|
selectionMode: SelectionMode.single, |
|
|
|
|
columns: [ |
|
|
|
|
GridColumn( |
|
|
|
|
columnName: 'select', |
|
|
|
|
label: ValueListenableBuilder<bool>( |
|
|
|
|
valueListenable: componentsSource.selectionNotifier, |
|
|
|
|
builder: |
|
|
|
|
(context, _, __) => _buildCheckboxHeader(context, componentsSource), |
|
|
|
|
), |
|
|
|
|
width: 60, |
|
|
|
|
), |
|
|
|
|
GridColumn(columnName: 'id', label: _buildGridHeader('序号'), minimumWidth: 80), |
|
|
|
|
GridColumn( |
|
|
|
|
columnName: 'name', |
|
|
|
@ -79,18 +59,19 @@ class ComponentGrid extends StatelessWidget {
@@ -79,18 +59,19 @@ class ComponentGrid extends StatelessWidget {
|
|
|
|
|
minimumWidth: 120, |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
onCellTap: (details) { |
|
|
|
|
if (details.column.columnName == 'select') { |
|
|
|
|
final rowIndex = details.rowColumnIndex.rowIndex - 1; |
|
|
|
|
if (rowIndex >= 0 && rowIndex < componentsSource.items.length) { |
|
|
|
|
componentsSource.toggleRowSelection( |
|
|
|
|
rowIndex, |
|
|
|
|
!componentsSource.items[rowIndex].isSelected, |
|
|
|
|
); |
|
|
|
|
onSelectionChanged?.call( |
|
|
|
|
rowIndex, |
|
|
|
|
componentsSource.items[rowIndex].isSelected, |
|
|
|
|
); |
|
|
|
|
onSelectionChanged: (addedRows, removedRows) { |
|
|
|
|
if (addedRows.isNotEmpty) { |
|
|
|
|
// 获取选中行的索引 |
|
|
|
|
final rowIndex = widget.componentsSource.effectiveRows |
|
|
|
|
.indexOf(addedRows.first); |
|
|
|
|
|
|
|
|
|
if (rowIndex >= 0 && rowIndex < widget.componentsSource.items.length) { |
|
|
|
|
// 清除所有选择 |
|
|
|
|
for (var i = 0; i < widget.componentsSource.items.length; i++) { |
|
|
|
|
widget.componentsSource.items[i].isSelected = (i == rowIndex); |
|
|
|
|
} |
|
|
|
|
widget.componentsSource.notifyListeners(); |
|
|
|
|
widget.onSelectionChanged?.call(rowIndex, true); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|