diff --git a/win_text_editor/lib/modules/memory_table/controllers/base_data_source.dart b/win_text_editor/lib/modules/memory_table/controllers/base_data_source.dart new file mode 100644 index 0000000..fa3181b --- /dev/null +++ b/win_text_editor/lib/modules/memory_table/controllers/base_data_source.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + +abstract class SelectableItem { + bool isSelected = false; +} + +abstract class SelectableDataSource extends DataGridSource { + SelectableDataSource(this.items) { + _selectionNotifier = ValueNotifier(false); + } + + List items; + late final ValueNotifier _selectionNotifier; + ValueNotifier get selectionNotifier => _selectionNotifier; + + void toggleAllSelection(bool value) { + for (var item in items) { + item.isSelected = value; + } + _updateSelectionState(); + notifyListeners(); + } + + void toggleRowSelection(int index, bool? value) { + items[index].isSelected = value ?? false; + _updateSelectionState(); + notifyListeners(); + } + + void _updateSelectionState() { + final allSelected = items.isNotEmpty && items.every((item) => item.isSelected); + final someSelected = items.isNotEmpty && items.any((item) => item.isSelected); + _selectionNotifier.value = allSelected || someSelected; + } + + void updateDataGridSource() { + _updateSelectionState(); + notifyListeners(); + } + + void updateData(List newItems) { + items = newItems; + notifyListeners(); + } +} + +class Field implements SelectableItem { + Field(this.id, this.name, this.chineseName, this.type, this.remark, [this.isSelected = false]); + + final String id; + final String name; + final String chineseName; + final String type; + final String remark; + @override + bool isSelected; +} + +// 索引数据模型 +class Index implements SelectableItem { + Index(this.indexName, this.isPrimary, this.indexFields, this.rule, [this.isSelected = false]); + + final String indexName; + final String isPrimary; + final String indexFields; + final String rule; + @override + bool isSelected; +} + +class FieldsDataSource extends SelectableDataSource { + FieldsDataSource(List fields) : super(fields); + + @override + List get rows => + items + .map( + (field) => DataGridRow( + cells: [ + DataGridCell(columnName: 'select', value: field.isSelected), + DataGridCell(columnName: 'id', value: field.id), + DataGridCell(columnName: 'name', value: field.name), + DataGridCell(columnName: 'chineseName', value: field.chineseName), + DataGridCell(columnName: 'type', value: field.type), + DataGridCell(columnName: 'remark', value: field.remark), + ], + ), + ) + .toList(); + + @override + DataGridRowAdapter buildRow(DataGridRow row) { + final rowIndex = effectiveRows.indexOf(row); + return DataGridRowAdapter( + cells: + row.getCells().map((cell) { + if (cell.columnName == 'select') { + return Center( + child: Checkbox( + value: items[rowIndex].isSelected, + onChanged: (value) => toggleRowSelection(rowIndex, value), + ), + ); + } + return Container( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Text(cell.value.toString(), overflow: TextOverflow.ellipsis), + ); + }).toList(), + ); + } +} + +// 索引数据源 +class IndexesDataSource extends SelectableDataSource { + IndexesDataSource(List indexes) : super(indexes); + + @override + List get rows => + items + .map( + (index) => DataGridRow( + cells: [ + DataGridCell(columnName: 'select', value: index.isSelected), + DataGridCell(columnName: 'indexName', value: index.indexName), + DataGridCell(columnName: 'isPrimary', value: index.isPrimary), + DataGridCell(columnName: 'indexFields', value: index.indexFields), + DataGridCell(columnName: 'rule', value: index.rule), + ], + ), + ) + .toList(); + + @override + DataGridRowAdapter buildRow(DataGridRow row) { + final rowIndex = effectiveRows.indexOf(row); + return DataGridRowAdapter( + cells: + row.getCells().map((cell) { + if (cell.columnName == 'select') { + return Center( + child: Checkbox( + value: items[rowIndex].isSelected, + onChanged: (value) => toggleRowSelection(rowIndex, value), + ), + ); + } + return Container( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Text(cell.value.toString(), overflow: TextOverflow.ellipsis), + ); + }).toList(), + ); + } +} diff --git a/win_text_editor/lib/modules/memory_table/controllers/memory_table_controller.dart b/win_text_editor/lib/modules/memory_table/controllers/memory_table_controller.dart index 7ff56d5..b057596 100644 --- a/win_text_editor/lib/modules/memory_table/controllers/memory_table_controller.dart +++ b/win_text_editor/lib/modules/memory_table/controllers/memory_table_controller.dart @@ -1,183 +1,9 @@ -import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:win_text_editor/framework/controllers/logger.dart'; +import 'package:win_text_editor/modules/memory_table/controllers/base_data_source.dart'; import 'package:win_text_editor/modules/memory_table/services/memory_table_service.dart'; import 'package:win_text_editor/shared/base/base_content_controller.dart'; -// 字段数据模型 -class Field { - Field(this.id, this.name, this.chineseName, this.type, this.remark, [this.isSelected = false]); - - final String id; // 序号 - final String name; // 名称 - final String chineseName; // 中文名 - final String type; // 类型 - final String remark; // 备注 - bool isSelected; -} - -// 索引数据模型 -class Index { - Index(this.indexName, this.isPrimary, this.indexFields, this.rule, [this.isSelected = false]); - - final String indexName; // 索引名称 - final String isPrimary; // 是否主键 - final String indexFields; // 索引字段 - final String rule; // 规则 - bool isSelected; -} - -// 字段数据源 -class FieldsDataSource extends DataGridSource { - FieldsDataSource(this.fields) { - _selectionNotifier = ValueNotifier(false); - } - - List fields; - late ValueNotifier _selectionNotifier; - - ValueNotifier get selectionNotifier => _selectionNotifier; - - void toggleAllSelection(bool value) { - for (var field in fields) { - field.isSelected = value; - } - _selectionNotifier.value = !_selectionNotifier.value; // Trigger rebuild - notifyListeners(); - } - - void updateData(List newFields) { - fields = newFields; - notifyListeners(); // 关键:通知DataGrid更新 - } - - @override - List get rows => - fields - .map( - (field) => DataGridRow( - cells: [ - DataGridCell(columnName: 'select', value: field.isSelected), - DataGridCell(columnName: 'id', value: field.id), - DataGridCell(columnName: 'name', value: field.name), - DataGridCell(columnName: 'chineseName', value: field.chineseName), - DataGridCell(columnName: 'type', value: field.type), - DataGridCell(columnName: 'remark', value: field.remark), - ], - ), - ) - .toList(); - - @override - DataGridRowAdapter? buildRow(DataGridRow row) { - final int rowIndex = effectiveRows.indexOf(row); - return DataGridRowAdapter( - cells: - row.getCells().map((dataGridCell) { - if (dataGridCell.columnName == 'select') { - return Center( - child: Checkbox( - value: fields[rowIndex].isSelected, - onChanged: (value) { - toggleRowSelection(rowIndex, value); - }, - ), - ); - } - return Container( - alignment: Alignment.centerLeft, - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Text(dataGridCell.value.toString(), overflow: TextOverflow.ellipsis), - ); - }).toList(), - ); - } - - void toggleRowSelection(int index, bool? value) { - fields[index].isSelected = value ?? false; - notifyListeners(); - } -} - -// 索引数据源 -class IndexesDataSource extends DataGridSource { - IndexesDataSource(this.indexes) { - _selectionNotifier = ValueNotifier(false); - } - - List indexes; - late ValueNotifier _selectionNotifier; - - get selectionNotifier => _selectionNotifier; - - void toggleAllSelection(bool value) { - for (var index in indexes) { - index.isSelected = value; - } - _selectionNotifier.value = !_selectionNotifier.value; // Trigger rebuild - notifyListeners(); - } - - void toggleRowSelection(int index, bool? value) { - indexes[index].isSelected = value ?? false; - notifyListeners(); - } - - void updateData(List newIndexes) { - indexes = newIndexes; - notifyListeners(); // 关键:通知DataGrid更新 - } - - @override - List get rows => - indexes - .map( - (index) => DataGridRow( - cells: [ - DataGridCell(columnName: 'select', value: index.isSelected), - DataGridCell(columnName: 'indexName', value: index.indexName), - DataGridCell(columnName: 'isPrimary', value: index.isPrimary), - DataGridCell(columnName: 'indexFields', value: index.indexFields), - DataGridCell(columnName: 'rule', value: index.rule), - ], - ), - ) - .toList(); - - @override - DataGridRowAdapter? buildRow(DataGridRow row) { - final int rowIndex = effectiveRows.indexOf(row); - return DataGridRowAdapter( - cells: - row.getCells().map((dataGridCell) { - if (dataGridCell.columnName == 'select') { - return Center( - child: Checkbox( - value: indexes[rowIndex].isSelected, - onChanged: (value) { - toggleRowSelection(rowIndex, value); - }, - ), - ); - } - return Container( - alignment: Alignment.centerLeft, - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Text(dataGridCell.value.toString(), overflow: TextOverflow.ellipsis), - ); - }).toList(), - ); - } - - bool _getSelectedValue(DataGridRow row) { - final int rowIndex = rows.indexOf(row); - if (rowIndex == -1) { - return false; - } - return indexes[rowIndex].isSelected; - } -} - class MemoryTableController extends BaseContentController { String? _errorMessage; String tableName = ""; diff --git a/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart b/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart index 3b8eedc..91f2954 100644 --- a/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart +++ b/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart @@ -1,7 +1,7 @@ // memory_table_service.dart import 'dart:io'; -import 'package:win_text_editor/modules/memory_table/controllers/memory_table_controller.dart'; +import 'package:win_text_editor/modules/memory_table/controllers/base_data_source.dart'; import 'package:xml/xml.dart' as xml; import 'package:path/path.dart' as path; import 'package:win_text_editor/framework/controllers/logger.dart'; diff --git a/win_text_editor/lib/modules/memory_table/widgets/memory_table_left_side.dart b/win_text_editor/lib/modules/memory_table/widgets/memory_table_left_side.dart index c32608a..5a1baa2 100644 --- a/win_text_editor/lib/modules/memory_table/widgets/memory_table_left_side.dart +++ b/win_text_editor/lib/modules/memory_table/widgets/memory_table_left_side.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:win_text_editor/modules/memory_table/controllers/base_data_source.dart'; import 'package:win_text_editor/modules/memory_table/controllers/memory_table_controller.dart'; class MemoryTableLeftSide extends StatelessWidget { @@ -55,14 +56,9 @@ class MemoryTableLeftSide extends StatelessWidget { GridColumn( columnName: 'select', label: ValueListenableBuilder( - valueListenable: (fieldsSource).selectionNotifier, - builder: (context, _, __) { - return _buildCheckboxHeader( - context, - fieldsSource, - fieldsSource.fields.length, - ); - }, + valueListenable: fieldsSource.selectionNotifier, + builder: + (context, _, __) => _buildCheckboxHeader(context, fieldsSource), ), width: 60, ), @@ -95,10 +91,10 @@ class MemoryTableLeftSide extends StatelessWidget { onCellTap: (details) { if (details.column.columnName == 'select') { final rowIndex = details.rowColumnIndex.rowIndex - 1; - if (rowIndex >= 0 && rowIndex < fieldsSource.fields.length) { + if (rowIndex >= 0 && rowIndex < fieldsSource.items.length) { fieldsSource.toggleRowSelection( rowIndex, - !fieldsSource.fields[rowIndex].isSelected, + !fieldsSource.items[rowIndex].isSelected, ); } } @@ -114,10 +110,16 @@ class MemoryTableLeftSide extends StatelessWidget { ); } - Widget _buildCheckboxHeader(BuildContext context, FieldsDataSource dataSource, int rowCount) { - final allSelected = rowCount > 0 && dataSource.fields.every((item) => item.isSelected); + Widget _buildCheckboxHeader( + BuildContext context, + SelectableDataSource dataSource, + ) { + final allSelected = + dataSource.items.isNotEmpty && dataSource.items.every((item) => item.isSelected); final someSelected = - rowCount > 0 && dataSource.fields.any((item) => item.isSelected) && !allSelected; + dataSource.items.isNotEmpty && + dataSource.items.any((item) => item.isSelected) && + !allSelected; return Container( alignment: Alignment.center, @@ -125,9 +127,7 @@ class MemoryTableLeftSide extends StatelessWidget { child: Checkbox( value: allSelected, tristate: someSelected, - onChanged: (value) { - dataSource.toggleAllSelection(value ?? false); - }, + onChanged: (value) => dataSource.toggleAllSelection(value ?? false), ), ); } @@ -155,14 +155,9 @@ class MemoryTableLeftSide extends StatelessWidget { GridColumn( columnName: 'select', label: ValueListenableBuilder( - valueListenable: (indexesSource).selectionNotifier, - builder: (context, _, __) { - return _buildCheckboxHeaderForIndexes( - context, - indexesSource, - indexesSource.indexes.length, - ); - }, + valueListenable: indexesSource.selectionNotifier, + builder: + (context, _, __) => _buildCheckboxHeader(context, indexesSource), ), width: 60, ), @@ -190,10 +185,10 @@ class MemoryTableLeftSide extends StatelessWidget { onCellTap: (details) { if (details.column.columnName == 'select') { final rowIndex = details.rowColumnIndex.rowIndex - 1; - if (rowIndex >= 0 && rowIndex < indexesSource.indexes.length) { + if (rowIndex >= 0 && rowIndex < indexesSource.items.length) { indexesSource.toggleRowSelection( rowIndex, - !indexesSource.indexes[rowIndex].isSelected, + !indexesSource.items[rowIndex].isSelected, ); } } @@ -209,28 +204,6 @@ class MemoryTableLeftSide extends StatelessWidget { ); } - Widget _buildCheckboxHeaderForIndexes( - BuildContext context, - IndexesDataSource dataSource, - int rowCount, - ) { - final allSelected = rowCount > 0 && dataSource.indexes.every((item) => item.isSelected); - final someSelected = - rowCount > 0 && dataSource.indexes.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); - }, - ), - ); - } - @override Widget build(BuildContext context) { return Column(