8 changed files with 132 additions and 104 deletions
@ -1,9 +1,6 @@ |
|||||||
import 'package:flutter/material.dart'; |
import 'package:flutter/material.dart'; |
||||||
import 'package:syncfusion_flutter_datagrid/datagrid.dart'; |
import 'package:syncfusion_flutter_datagrid/datagrid.dart'; |
||||||
|
import 'package:win_text_editor/shared/models/memory_table.dart'; |
||||||
abstract class SelectableItem { |
|
||||||
bool isSelected = false; |
|
||||||
} |
|
||||||
|
|
||||||
abstract class SelectableDataSource<T extends SelectableItem> extends DataGridSource { |
abstract class SelectableDataSource<T extends SelectableItem> extends DataGridSource { |
||||||
SelectableDataSource(this.items, {this.onSelectionChanged}) { |
SelectableDataSource(this.items, {this.onSelectionChanged}) { |
@ -1,7 +1,7 @@ |
|||||||
import 'package:flutter/material.dart'; |
import 'package:flutter/material.dart'; |
||||||
import 'package:syncfusion_flutter_datagrid/datagrid.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/shared/base/base_data_source.dart'; |
||||||
import 'package:win_text_editor/modules/memory_table/models/memory_table.dart'; |
import 'package:win_text_editor/shared/models/memory_table.dart'; |
||||||
|
|
||||||
class FieldsDataSource extends SelectableDataSource<Field> { |
class FieldsDataSource extends SelectableDataSource<Field> { |
||||||
FieldsDataSource( |
FieldsDataSource( |
@ -0,0 +1,110 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:syncfusion_flutter_datagrid/datagrid.dart'; |
||||||
|
import 'package:win_text_editor/shared/base/base_data_source.dart'; |
||||||
|
import 'package:win_text_editor/shared/models/memory_table.dart'; |
||||||
|
import 'package:win_text_editor/shared/uft_std_fields/field_data_source.dart'; |
||||||
|
|
||||||
|
class FieldsDataGrid extends StatelessWidget { |
||||||
|
final FieldsDataSource fieldsSource; |
||||||
|
final Function(int index, bool isSelected)? onSelectionChanged; |
||||||
|
|
||||||
|
const FieldsDataGrid({super.key, required this.fieldsSource, this.onSelectionChanged}); |
||||||
|
|
||||||
|
Container _buildGridHeader(String text) { |
||||||
|
return Container( |
||||||
|
alignment: Alignment.center, |
||||||
|
color: Colors.grey[200], |
||||||
|
child: Text(text, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
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), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Card( |
||||||
|
child: Column( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: LayoutBuilder( |
||||||
|
builder: (context, constraints) { |
||||||
|
return SizedBox( |
||||||
|
width: constraints.maxWidth, |
||||||
|
child: SfDataGrid( |
||||||
|
source: fieldsSource, |
||||||
|
gridLinesVisibility: GridLinesVisibility.both, |
||||||
|
headerGridLinesVisibility: GridLinesVisibility.both, |
||||||
|
columnWidthMode: ColumnWidthMode.fitByCellValue, |
||||||
|
selectionMode: SelectionMode.none, |
||||||
|
columns: [ |
||||||
|
GridColumn( |
||||||
|
columnName: 'select', |
||||||
|
label: ValueListenableBuilder<bool>( |
||||||
|
valueListenable: fieldsSource.selectionNotifier, |
||||||
|
builder: (context, _, __) => _buildCheckboxHeader(context, fieldsSource), |
||||||
|
), |
||||||
|
width: 60, |
||||||
|
), |
||||||
|
GridColumn(columnName: 'id', label: _buildGridHeader('序号'), minimumWidth: 80), |
||||||
|
GridColumn( |
||||||
|
columnName: 'name', |
||||||
|
label: _buildGridHeader('名称'), |
||||||
|
minimumWidth: 120, |
||||||
|
), |
||||||
|
GridColumn( |
||||||
|
columnName: 'chineseName', |
||||||
|
label: _buildGridHeader('中文名'), |
||||||
|
minimumWidth: 120, |
||||||
|
), |
||||||
|
GridColumn( |
||||||
|
columnName: 'type', |
||||||
|
label: _buildGridHeader('类型'), |
||||||
|
minimumWidth: 120, |
||||||
|
), |
||||||
|
], |
||||||
|
onCellTap: (details) { |
||||||
|
if (details.column.columnName == 'select') { |
||||||
|
final rowIndex = details.rowColumnIndex.rowIndex - 1; |
||||||
|
if (rowIndex >= 0 && rowIndex < fieldsSource.items.length) { |
||||||
|
fieldsSource.toggleRowSelection( |
||||||
|
rowIndex, |
||||||
|
!fieldsSource.items[rowIndex].isSelected, |
||||||
|
); |
||||||
|
onSelectionChanged?.call( |
||||||
|
rowIndex, |
||||||
|
fieldsSource.items[rowIndex].isSelected, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue