flet-datatable2 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flet_datatable2/__init__.py +5 -0
- flet_datatable2/datacolumn2.py +173 -0
- flet_datatable2/datarow2.py +220 -0
- flet_datatable2/datatable2.py +864 -0
- flet_datatable2-0.1.0.dist-info/METADATA +38 -0
- flet_datatable2-0.1.0.dist-info/RECORD +17 -0
- flet_datatable2-0.1.0.dist-info/WHEEL +5 -0
- flet_datatable2-0.1.0.dist-info/top_level.txt +2 -0
- flutter/flet_datatable2/CHANGELOG.md +3 -0
- flutter/flet_datatable2/LICENSE +1 -0
- flutter/flet_datatable2/README.md +6 -0
- flutter/flet_datatable2/lib/flet_datatable2.dart +3 -0
- flutter/flet_datatable2/lib/src/create_control.dart +22 -0
- flutter/flet_datatable2/lib/src/data_sources.dart +692 -0
- flutter/flet_datatable2/lib/src/datatable2.dart +309 -0
- flutter/flet_datatable2/pubspec.lock +751 -0
- flutter/flet_datatable2/pubspec.yaml +17 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import 'dart:convert';
|
|
2
|
+
|
|
3
|
+
import 'package:collection/collection.dart';
|
|
4
|
+
import 'package:data_table_2/data_table_2.dart';
|
|
5
|
+
import 'package:flet/flet.dart' as ft;
|
|
6
|
+
import 'package:flet/flet.dart';
|
|
7
|
+
import 'package:flutter/material.dart';
|
|
8
|
+
|
|
9
|
+
class DataTable2Control extends StatefulWidget {
|
|
10
|
+
final Control? parent;
|
|
11
|
+
final Control control;
|
|
12
|
+
final List<Control> children;
|
|
13
|
+
final bool parentDisabled;
|
|
14
|
+
final FletControlBackend backend;
|
|
15
|
+
|
|
16
|
+
const DataTable2Control(
|
|
17
|
+
{super.key,
|
|
18
|
+
this.parent,
|
|
19
|
+
required this.control,
|
|
20
|
+
required this.children,
|
|
21
|
+
required this.parentDisabled,
|
|
22
|
+
required this.backend});
|
|
23
|
+
|
|
24
|
+
@override
|
|
25
|
+
State<DataTable2Control> createState() => _DataTable2ControlState();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class _DataTable2ControlState extends State<DataTable2Control>
|
|
29
|
+
with FletStoreMixin {
|
|
30
|
+
//final ScrollController _horizontalController = ScrollController();
|
|
31
|
+
//final ScrollController _controller = ScrollController();
|
|
32
|
+
|
|
33
|
+
// @override
|
|
34
|
+
// void dispose() {
|
|
35
|
+
// _horizontalController.dispose();
|
|
36
|
+
// _controller.dispose();
|
|
37
|
+
// super.dispose();
|
|
38
|
+
// }
|
|
39
|
+
|
|
40
|
+
@override
|
|
41
|
+
Widget build(BuildContext context) {
|
|
42
|
+
debugPrint("DataTableControl build: ${widget.control.id}");
|
|
43
|
+
|
|
44
|
+
bool tableDisabled = widget.control.isDisabled || widget.parentDisabled;
|
|
45
|
+
|
|
46
|
+
ColumnSize? parseSize(String? size, [ColumnSize? defValue]) {
|
|
47
|
+
if (size == null) {
|
|
48
|
+
return defValue;
|
|
49
|
+
}
|
|
50
|
+
return ColumnSize.values.firstWhereOrNull(
|
|
51
|
+
(e) => e.name.toLowerCase() == size.toLowerCase()) ??
|
|
52
|
+
defValue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var datatable =
|
|
56
|
+
withControls(widget.children.where((c) => c.isVisible).map((c) => c.id),
|
|
57
|
+
(content, viewModel) {
|
|
58
|
+
var emptyCtrls =
|
|
59
|
+
widget.children.where((c) => c.name == "empty" && c.isVisible);
|
|
60
|
+
Widget? empty = emptyCtrls.isNotEmpty
|
|
61
|
+
? createControl(
|
|
62
|
+
widget.control, emptyCtrls.first.id, widget.control.isDisabled)
|
|
63
|
+
: null;
|
|
64
|
+
IconData? sortArrowIcon =
|
|
65
|
+
parseIcon(widget.control.attrString("sortArrowIcon"));
|
|
66
|
+
var bgColor = widget.control.attrString("bgColor");
|
|
67
|
+
var border = parseBorder(Theme.of(context), widget.control, "border");
|
|
68
|
+
var borderRadius = parseBorderRadius(widget.control, "borderRadius");
|
|
69
|
+
var gradient =
|
|
70
|
+
parseGradient(Theme.of(context), widget.control, "gradient");
|
|
71
|
+
var horizontalLines =
|
|
72
|
+
parseBorderSide(Theme.of(context), widget.control, "horizontalLines");
|
|
73
|
+
var verticalLines =
|
|
74
|
+
parseBorderSide(Theme.of(context), widget.control, "verticalLines");
|
|
75
|
+
var defaultDecoration =
|
|
76
|
+
Theme.of(context).dataTableTheme.decoration ?? const BoxDecoration();
|
|
77
|
+
var checkboxAlignment = parseAlignment(
|
|
78
|
+
widget.control, "checkboxAlignment", Alignment.center)!;
|
|
79
|
+
|
|
80
|
+
BoxDecoration? decoration;
|
|
81
|
+
if (bgColor != null ||
|
|
82
|
+
border != null ||
|
|
83
|
+
borderRadius != null ||
|
|
84
|
+
gradient != null) {
|
|
85
|
+
decoration = (defaultDecoration as BoxDecoration).copyWith(
|
|
86
|
+
color: parseColor(Theme.of(context), bgColor),
|
|
87
|
+
border: border,
|
|
88
|
+
borderRadius: borderRadius,
|
|
89
|
+
gradient: gradient);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
TableBorder? tableBorder;
|
|
93
|
+
if (horizontalLines != null || verticalLines != null) {
|
|
94
|
+
tableBorder = TableBorder(
|
|
95
|
+
horizontalInside: horizontalLines ?? BorderSide.none,
|
|
96
|
+
verticalInside: verticalLines ?? BorderSide.none);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
Clip clipBehavior =
|
|
100
|
+
parseClip(widget.control.attrString("clipBehavior"), Clip.none)!;
|
|
101
|
+
|
|
102
|
+
return withPageArgs((context, pageArgs) {
|
|
103
|
+
return DataTable2(
|
|
104
|
+
bottomMargin: widget.control.attrDouble("bottomMargin"),
|
|
105
|
+
minWidth: widget.control.attrDouble("minWidth"),
|
|
106
|
+
//horizontalScrollController: _horizontalController,
|
|
107
|
+
//scrollController: _controller,
|
|
108
|
+
decoration: decoration,
|
|
109
|
+
border: tableBorder,
|
|
110
|
+
empty: empty,
|
|
111
|
+
isHorizontalScrollBarVisible:
|
|
112
|
+
widget.control.attrBool("isHorizontalScrollBarVisible"),
|
|
113
|
+
isVerticalScrollBarVisible:
|
|
114
|
+
widget.control.attrBool("isVerticalScrollBarVisible"),
|
|
115
|
+
fixedLeftColumns: widget.control.attrInt("fixedLeftColumns") ?? 0,
|
|
116
|
+
fixedTopRows: widget.control.attrInt("fixedTopRows") ?? 1,
|
|
117
|
+
fixedColumnsColor:
|
|
118
|
+
widget.control.attrColor("fixedColumnsColor", context),
|
|
119
|
+
fixedCornerColor:
|
|
120
|
+
widget.control.attrColor("fixedCornerColor", context),
|
|
121
|
+
smRatio: widget.control.attrDouble("smRatio") ?? 0.67,
|
|
122
|
+
lmRatio: widget.control.attrDouble("lmRatio") ?? 1.2,
|
|
123
|
+
clipBehavior: clipBehavior,
|
|
124
|
+
sortArrowIcon: sortArrowIcon ?? Icons.arrow_upward,
|
|
125
|
+
sortArrowAnimationDuration:
|
|
126
|
+
parseDuration(widget.control, "sortArrowAnimationDuration") ??
|
|
127
|
+
Duration(microseconds: 150),
|
|
128
|
+
checkboxHorizontalMargin:
|
|
129
|
+
widget.control.attrDouble("checkboxHorizontalMargin"),
|
|
130
|
+
checkboxAlignment: checkboxAlignment,
|
|
131
|
+
headingCheckboxTheme: parseCheckboxTheme(
|
|
132
|
+
Theme.of(context),
|
|
133
|
+
widget.control.attrString("headingCheckboxTheme") != null
|
|
134
|
+
? json.decode(
|
|
135
|
+
widget.control.attrString("headingCheckboxTheme")!)
|
|
136
|
+
: null),
|
|
137
|
+
datarowCheckboxTheme: parseCheckboxTheme(
|
|
138
|
+
Theme.of(context),
|
|
139
|
+
widget.control.attrString("dataRowCheckboxTheme") != null
|
|
140
|
+
? json.decode(
|
|
141
|
+
widget.control.attrString("dataRowCheckboxTheme")!)
|
|
142
|
+
: null),
|
|
143
|
+
showHeadingCheckBox:
|
|
144
|
+
widget.control.attrBool("showHeadingCheckbox", true)!,
|
|
145
|
+
columnSpacing: widget.control.attrDouble("columnSpacing"),
|
|
146
|
+
dataRowColor: parseWidgetStateColor(
|
|
147
|
+
Theme.of(context), widget.control, "dataRowColor"),
|
|
148
|
+
dataRowHeight: widget.control.attrDouble("dataRowHeight"),
|
|
149
|
+
//dataRowMinHeight: widget.control.attrDouble("dataRowMinHeight"),
|
|
150
|
+
//dataRowMaxHeight: widget.control.attrDouble("dataRowMaxHeight"),
|
|
151
|
+
dataTextStyle: parseTextStyle(
|
|
152
|
+
Theme.of(context), widget.control, "dataTextStyle"),
|
|
153
|
+
headingRowColor: parseWidgetStateColor(
|
|
154
|
+
Theme.of(context), widget.control, "headingRowColor"),
|
|
155
|
+
headingRowHeight: widget.control.attrDouble("headingRowHeight"),
|
|
156
|
+
headingTextStyle: parseTextStyle(
|
|
157
|
+
Theme.of(context), widget.control, "headingTextStyle"),
|
|
158
|
+
headingRowDecoration: parseBoxDecoration(Theme.of(context),
|
|
159
|
+
widget.control, "headingRowDecoration", pageArgs),
|
|
160
|
+
dividerThickness: widget.control.attrDouble("dividerThickness"),
|
|
161
|
+
horizontalMargin: widget.control.attrDouble("horizontalMargin"),
|
|
162
|
+
showBottomBorder:
|
|
163
|
+
widget.control.attrBool("showBottomBorder", false)!,
|
|
164
|
+
showCheckboxColumn:
|
|
165
|
+
widget.control.attrBool("showCheckboxColumn", false)!,
|
|
166
|
+
sortAscending: widget.control.attrBool("sortAscending", false)!,
|
|
167
|
+
sortColumnIndex: widget.control.attrInt("sortColumnIndex"),
|
|
168
|
+
onSelectAll: widget.control.attrBool("onSelectAll", false)!
|
|
169
|
+
? (selected) {
|
|
170
|
+
widget.backend.triggerControlEvent(
|
|
171
|
+
widget.control.id,
|
|
172
|
+
"select_all",
|
|
173
|
+
selected != null ? selected.toString() : "");
|
|
174
|
+
}
|
|
175
|
+
: null,
|
|
176
|
+
columns: viewModel.controlViews
|
|
177
|
+
.where((c) =>
|
|
178
|
+
c.control.type == "datacolumn2" && c.control.isVisible)
|
|
179
|
+
.map((column) {
|
|
180
|
+
var labelCtrls = column.children
|
|
181
|
+
.where((c) => c.name == "label" && c.isVisible);
|
|
182
|
+
return DataColumn2(
|
|
183
|
+
//size: ColumnSize.S,
|
|
184
|
+
size: parseSize(
|
|
185
|
+
column.control.attrString("size"), ColumnSize.S)!,
|
|
186
|
+
fixedWidth: column.control.attrDouble("fixedWidth"),
|
|
187
|
+
numeric: column.control.attrBool("numeric", false)!,
|
|
188
|
+
tooltip: column.control.attrString("tooltip"),
|
|
189
|
+
headingRowAlignment: parseMainAxisAlignment(
|
|
190
|
+
column.control.attrString("headingRowAlignment")),
|
|
191
|
+
//mouseCursor: WidgetStateMouseCursor.clickable,
|
|
192
|
+
onSort: column.control.attrBool("onSort", false)!
|
|
193
|
+
? (columnIndex, ascending) {
|
|
194
|
+
widget.backend.triggerControlEvent(
|
|
195
|
+
column.control.id,
|
|
196
|
+
"sort",
|
|
197
|
+
json.encode({"i": columnIndex, "a": ascending}));
|
|
198
|
+
}
|
|
199
|
+
: null,
|
|
200
|
+
label: ft.createControl(column.control, labelCtrls.first.id,
|
|
201
|
+
column.control.isDisabled || tableDisabled));
|
|
202
|
+
}).toList(),
|
|
203
|
+
rows: viewModel.controlViews
|
|
204
|
+
.where((c) => c.control.type == "datarow2" && c.control.isVisible)
|
|
205
|
+
.map((row) {
|
|
206
|
+
return DataRow2(
|
|
207
|
+
key: ValueKey(row.control.id),
|
|
208
|
+
selected: row.control.attrBool("selected", false)!,
|
|
209
|
+
color: parseWidgetStateColor(
|
|
210
|
+
Theme.of(context), row.control, "color"),
|
|
211
|
+
specificRowHeight:
|
|
212
|
+
row.control.attrDouble("specificRowHeight"),
|
|
213
|
+
decoration: parseBoxDecoration(
|
|
214
|
+
Theme.of(context), row.control, "decoration", pageArgs),
|
|
215
|
+
onSelectChanged:
|
|
216
|
+
row.control.attrBool("onSelectChanged", false)!
|
|
217
|
+
? (selected) {
|
|
218
|
+
widget.backend.triggerControlEvent(
|
|
219
|
+
row.control.id,
|
|
220
|
+
"select_changed",
|
|
221
|
+
selected != null ? selected.toString() : "");
|
|
222
|
+
}
|
|
223
|
+
: null,
|
|
224
|
+
onLongPress: row.control.attrBool("onLongPress", false)!
|
|
225
|
+
? () {
|
|
226
|
+
widget.backend.triggerControlEvent(
|
|
227
|
+
row.control.id, "long_press");
|
|
228
|
+
}
|
|
229
|
+
: null,
|
|
230
|
+
onDoubleTap: row.control.attrBool("onDoubleTap", false)!
|
|
231
|
+
? () {
|
|
232
|
+
widget.backend.triggerControlEvent(
|
|
233
|
+
row.control.id, "double_tap");
|
|
234
|
+
}
|
|
235
|
+
: null,
|
|
236
|
+
onTap: row.control.attrBool("onTap", false)!
|
|
237
|
+
? () {
|
|
238
|
+
widget.backend
|
|
239
|
+
.triggerControlEvent(row.control.id, "tap");
|
|
240
|
+
}
|
|
241
|
+
: null,
|
|
242
|
+
onSecondaryTap: row.control.attrBool("onSecondaryTap", false)!
|
|
243
|
+
? () {
|
|
244
|
+
widget.backend.triggerControlEvent(
|
|
245
|
+
row.control.id, "secondary_tap");
|
|
246
|
+
}
|
|
247
|
+
: null,
|
|
248
|
+
onSecondaryTapDown:
|
|
249
|
+
row.control.attrBool("onSecondaryTapDown", false)!
|
|
250
|
+
? (details) {
|
|
251
|
+
widget.backend.triggerControlEvent(
|
|
252
|
+
row.control.id, "secondary_tap_down");
|
|
253
|
+
}
|
|
254
|
+
: null,
|
|
255
|
+
cells: row.children
|
|
256
|
+
.where((c) => c.type == "datacell" && c.isVisible)
|
|
257
|
+
.map((cell) => DataCell(
|
|
258
|
+
ft.createControl(row.control, cell.childIds.first,
|
|
259
|
+
row.control.isDisabled || tableDisabled),
|
|
260
|
+
placeholder: cell.attrBool("placeholder", false)!,
|
|
261
|
+
showEditIcon: cell.attrBool("showEditIcon", false)!,
|
|
262
|
+
onDoubleTap: cell.attrBool("onDoubleTap", false)!
|
|
263
|
+
? () {
|
|
264
|
+
widget.backend.triggerControlEvent(
|
|
265
|
+
cell.id, "double_tap");
|
|
266
|
+
}
|
|
267
|
+
: null,
|
|
268
|
+
onLongPress: cell.attrBool("onLongPress", false)!
|
|
269
|
+
? () {
|
|
270
|
+
widget.backend.triggerControlEvent(
|
|
271
|
+
cell.id, "long_press");
|
|
272
|
+
}
|
|
273
|
+
: null,
|
|
274
|
+
onTap: cell.attrBool("onTap", false)!
|
|
275
|
+
? () {
|
|
276
|
+
widget.backend
|
|
277
|
+
.triggerControlEvent(cell.id, "tap");
|
|
278
|
+
}
|
|
279
|
+
: null,
|
|
280
|
+
onTapCancel: cell.attrBool("onTapCancel", false)!
|
|
281
|
+
? () {
|
|
282
|
+
widget.backend.triggerControlEvent(
|
|
283
|
+
cell.id, "tap_cancel");
|
|
284
|
+
}
|
|
285
|
+
: null,
|
|
286
|
+
onTapDown: cell.attrBool("onTapDown", false)!
|
|
287
|
+
? (details) {
|
|
288
|
+
widget.backend.triggerControlEvent(
|
|
289
|
+
cell.id,
|
|
290
|
+
"tap_down",
|
|
291
|
+
json.encode({
|
|
292
|
+
"kind": details.kind?.name,
|
|
293
|
+
"lx": details.localPosition.dx,
|
|
294
|
+
"ly": details.localPosition.dy,
|
|
295
|
+
"gx": details.globalPosition.dx,
|
|
296
|
+
"gy": details.globalPosition.dy,
|
|
297
|
+
}));
|
|
298
|
+
}
|
|
299
|
+
: null,
|
|
300
|
+
))
|
|
301
|
+
.toList());
|
|
302
|
+
}).toList());
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
return constrainedControl(
|
|
307
|
+
context, datatable, widget.parent, widget.control);
|
|
308
|
+
}
|
|
309
|
+
}
|