From 8ee9857cf23907a71c5192575da5e2c376ab0621 Mon Sep 17 00:00:00 2001 From: Yeikel Uriarte Arteaga Date: Tue, 26 Nov 2024 15:13:00 -0500 Subject: [PATCH 01/22] feat: allow disable row checkbox under a condition --- .fvm/fvm_config.json | 5 ++--- .gitignore | 11 +++++++++-- lib/src/model/pluto_column.dart | 9 ++++++--- lib/src/ui/cells/pluto_default_cell.dart | 5 ++++- lib/src/widgets/pluto_scaled_checkbox.dart | 2 +- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json index 41959e974..722fd1f83 100644 --- a/.fvm/fvm_config.json +++ b/.fvm/fvm_config.json @@ -1,4 +1,3 @@ { - "flutterSdkVersion": "stable", - "flavors": {} -} + "flutterSdkVersion": "3.24.2" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index b28e1b84a..8b7e51baa 100644 --- a/.gitignore +++ b/.gitignore @@ -76,8 +76,15 @@ coverage/ !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -# FVM Support - https://fvm.app/ -.fvm/flutter_sdk example/windows/flutter/generated_plugin_registrant.cc example/windows/flutter/generated_plugin_registrant.h example/windows/flutter/generated_plugins.cmake + +example/windows/flutter/generated_plugin_registrant.cc +example/windows/flutter/generated_plugin_registrant.h +example/windows/flutter/generated_plugins.cmake + +# FVM Support - https://fvm.app/ +.fvm/flutter_sdk +# FVM Version Cache +.fvm/ diff --git a/lib/src/model/pluto_column.dart b/lib/src/model/pluto_column.dart index 5dc568165..b0e382ec3 100644 --- a/lib/src/model/pluto_column.dart +++ b/lib/src/model/pluto_column.dart @@ -147,9 +147,13 @@ class PlutoColumn { /// A checkbox appears in the cell of the column. bool enableRowChecked; - int rowCheckBoxGroupDepth; // + + int rowCheckBoxGroupDepth; + bool enableTitleChecked; + bool Function(PlutoRow row)? disableRowCheckWhen; + /// Sort rows by tapping on the column heading. bool enableSorting; @@ -258,8 +262,7 @@ class PlutoColumn { this.enableAutoEditing = false, this.enableEditingMode = true, this.hide = false, - this.backgroundGradient, - this.filterWidgetBuilder, + this.disableRowCheckWhen, }) : _key = UniqueKey(), _checkReadOnly = checkReadOnly; diff --git a/lib/src/ui/cells/pluto_default_cell.dart b/lib/src/ui/cells/pluto_default_cell.dart index d68b955fd..b93d9d923 100644 --- a/lib/src/ui/cells/pluto_default_cell.dart +++ b/lib/src/ui/cells/pluto_default_cell.dart @@ -410,9 +410,12 @@ class CheckboxSelectionWidgetState @override Widget build(BuildContext context) { + final disable = + widget.column.disableRowCheckWhen?.call(widget.row) ?? false; + return PlutoScaledCheckbox( value: _checked, - handleOnChanged: _handleOnChanged, + handleOnChanged: disable ? null : _handleOnChanged, tristate: _tristate, scale: 0.86, unselectedColor: stateManager.configuration.style.cellUnselectedColor, diff --git a/lib/src/widgets/pluto_scaled_checkbox.dart b/lib/src/widgets/pluto_scaled_checkbox.dart index e98308546..1c3b00362 100644 --- a/lib/src/widgets/pluto_scaled_checkbox.dart +++ b/lib/src/widgets/pluto_scaled_checkbox.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; class PlutoScaledCheckbox extends StatelessWidget { final bool? value; - final Function(bool? changed) handleOnChanged; + final Function(bool? changed)? handleOnChanged; final bool tristate; From 058fec69e4d2ecbb5c7d5ad45f2e3f0ab7d90f53 Mon Sep 17 00:00:00 2001 From: Yeikel Uriarte Arteaga Date: Tue, 26 Nov 2024 16:23:22 -0500 Subject: [PATCH 02/22] fix: handle a pure value for checkbox when is disable --- lib/src/ui/cells/pluto_default_cell.dart | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/src/ui/cells/pluto_default_cell.dart b/lib/src/ui/cells/pluto_default_cell.dart index b93d9d923..a5d7a4b67 100644 --- a/lib/src/ui/cells/pluto_default_cell.dart +++ b/lib/src/ui/cells/pluto_default_cell.dart @@ -100,6 +100,10 @@ class _PlutoDefaultCellState extends PlutoStateWithChange { @override void updateState(PlutoNotifierEvent event) { + final disable = + widget.column.disableRowCheckWhen?.call(widget.row) ?? false; + if (disable) return; + _hasFocus = update( _hasFocus, stateManager.hasFocus, @@ -354,6 +358,7 @@ class CheckboxSelectionWidgetState bool _tristate = false; bool? _checked; + bool _pureValue = false; @override PlutoGridStateManager get stateManager => widget.stateManager; @@ -361,12 +366,19 @@ class CheckboxSelectionWidgetState @override void initState() { super.initState(); - updateState(PlutoNotifierEventForceUpdate.instance); + _pureValue = widget.row.checked ?? false; } @override void updateState(PlutoNotifierEvent event) { + final disable = + widget.column.disableRowCheckWhen?.call(widget.row) ?? false; + if (disable) { + _checked = _pureValue; + return; + } + _tristate = update( _tristate, stateManager.enabledRowGroups && widget.row.type.isGroup, From 2f2df5c3f66e6c0412986884f4f213439e9feb42 Mon Sep 17 00:00:00 2001 From: ArThoX Date: Tue, 3 Dec 2024 22:25:27 +0100 Subject: [PATCH 03/22] feat: continue to _update infinity scroll if screen not filled --- lib/src/plugin/pluto_infinity_scroll_rows.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/src/plugin/pluto_infinity_scroll_rows.dart b/lib/src/plugin/pluto_infinity_scroll_rows.dart index 76acb08ce..060862574 100644 --- a/lib/src/plugin/pluto_infinity_scroll_rows.dart +++ b/lib/src/plugin/pluto_infinity_scroll_rows.dart @@ -199,6 +199,15 @@ class _PlutoInfinityScrollRowsState extends State { _isFetching = false; _isLast = response.isLast; + + if (!_isLast) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (scroll.position.maxScrollExtent == 0) { + var lastRow = stateManager.rows.isNotEmpty ? stateManager.rows.last : null; + _update(lastRow); + } + }); + } }); } From cc4e9f83b883d3e7f890a77f76ecdf31b3451676 Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Wed, 4 Dec 2024 00:12:33 +0100 Subject: [PATCH 04/22] Changed function(Widget child) top WidgetBuilder --- lib/src/manager/pluto_grid_state_manager.dart | 2 +- lib/src/manager/state/row_state.dart | 2 +- lib/src/pluto_grid.dart | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/src/manager/pluto_grid_state_manager.dart b/lib/src/manager/pluto_grid_state_manager.dart index 79a00ea7e..aaff02b94 100644 --- a/lib/src/manager/pluto_grid_state_manager.dart +++ b/lib/src/manager/pluto_grid_state_manager.dart @@ -110,7 +110,7 @@ class PlutoGridStateChangeNotifier extends PlutoChangeNotifier } @override - final Widget Function(Widget rowWidget)? rowWrapper; + final WidgetBuilder? rowWrapper; @override final Widget Function(Widget editCellWidget, PlutoCell cell, diff --git a/lib/src/manager/state/row_state.dart b/lib/src/manager/state/row_state.dart index ab5e9ebbc..82a431aae 100644 --- a/lib/src/manager/state/row_state.dart +++ b/lib/src/manager/state/row_state.dart @@ -41,7 +41,7 @@ abstract class IRowState { /// Row of currently selected cell. PlutoRow? get currentRow; - Widget Function(Widget rowWidget)? get rowWrapper; + WidgetBuilder? get rowWrapper; PlutoRowColorCallback? get rowColorCallback; diff --git a/lib/src/pluto_grid.dart b/lib/src/pluto_grid.dart index 6a02e738d..b6c8aba3e 100644 --- a/lib/src/pluto_grid.dart +++ b/lib/src/pluto_grid.dart @@ -96,7 +96,8 @@ class PlutoGrid extends PlutoStatefulWidget { this.mode = PlutoGridMode.normal, }); - final Widget Function(Widget rowWidget)? rowWrapper; + /// A wrapper that wraps arround each row. + final WidgetBuilder? rowWrapper; final Widget Function(Widget editCellWidget, PlutoCell cell, TextEditingController controller)? editCellWrapper; From 8dfe854809ad12f3903c727752a76394ddbf20f8 Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Wed, 4 Dec 2024 01:29:20 +0100 Subject: [PATCH 05/22] Changed WidgetBuilder to Widget Function(BuildContext, Widget) --- lib/src/manager/pluto_grid_state_manager.dart | 2 +- lib/src/manager/state/row_state.dart | 12 ++++++------ lib/src/pluto_grid.dart | 4 ++-- lib/src/ui/pluto_body_rows.dart | 8 ++------ 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/lib/src/manager/pluto_grid_state_manager.dart b/lib/src/manager/pluto_grid_state_manager.dart index aaff02b94..7643e6fcf 100644 --- a/lib/src/manager/pluto_grid_state_manager.dart +++ b/lib/src/manager/pluto_grid_state_manager.dart @@ -110,7 +110,7 @@ class PlutoGridStateChangeNotifier extends PlutoChangeNotifier } @override - final WidgetBuilder? rowWrapper; + final Widget Function(BuildContext context, Widget row)? rowWrapper; @override final Widget Function(Widget editCellWidget, PlutoCell cell, diff --git a/lib/src/manager/state/row_state.dart b/lib/src/manager/state/row_state.dart index 82a431aae..b2ef39c68 100644 --- a/lib/src/manager/state/row_state.dart +++ b/lib/src/manager/state/row_state.dart @@ -41,7 +41,7 @@ abstract class IRowState { /// Row of currently selected cell. PlutoRow? get currentRow; - WidgetBuilder? get rowWrapper; + Widget Function(BuildContext context, Widget row)? get rowWrapper; PlutoRowColorCallback? get rowColorCallback; @@ -224,11 +224,11 @@ mixin RowState implements IPlutoGridState { @override void setRowChecked( - PlutoRow row, - bool flag, { - bool notify = true, - bool checkedViaSelect = false, - }) { + PlutoRow row, + bool flag, { + bool notify = true, + bool checkedViaSelect = false, + }) { final findRow = refRows.firstWhereOrNull( (element) => element.key == row.key, ); diff --git a/lib/src/pluto_grid.dart b/lib/src/pluto_grid.dart index b6c8aba3e..8d1997d74 100644 --- a/lib/src/pluto_grid.dart +++ b/lib/src/pluto_grid.dart @@ -55,7 +55,7 @@ typedef PlutoSelectDateCallBack = Future Function( PlutoCell dateCell, PlutoColumn column); typedef PlutoOnActiveCellChangedEventCallback = void Function( - PlutoGridOnActiveCellChangedEvent event); + PlutoGridOnActiveCellChangedEvent event); /// [PlutoGrid] is a widget that receives columns and rows and is expressed as a grid-type UI. /// @@ -97,7 +97,7 @@ class PlutoGrid extends PlutoStatefulWidget { }); /// A wrapper that wraps arround each row. - final WidgetBuilder? rowWrapper; + final Widget Function(BuildContext context, Widget row)? rowWrapper; final Widget Function(Widget editCellWidget, PlutoCell cell, TextEditingController controller)? editCellWrapper; diff --git a/lib/src/ui/pluto_body_rows.dart b/lib/src/ui/pluto_body_rows.dart index ced13c926..b95101d0e 100644 --- a/lib/src/ui/pluto_body_rows.dart +++ b/lib/src/ui/pluto_body_rows.dart @@ -106,7 +106,7 @@ class PlutoBodyRowsState extends PlutoStateWithChange { : stateManager.rowTotalHeight, addRepaintBoundaries: false, itemBuilder: (ctx, i) { - Widget w = PlutoBaseRow( + Widget row = PlutoBaseRow( key: ValueKey('body_row_${_rows[i].key}'), rowIdx: i, row: _rows[i], @@ -115,11 +115,7 @@ class PlutoBodyRowsState extends PlutoStateWithChange { visibilityLayout: true, ); - if (stateManager.rowWrapper != null) { - w = stateManager.rowWrapper!(w); - } - - return w; + return stateManager.rowWrapper?.call(context, row) ?? row; }, ), ), From 53035c3202e2b6b2f9a93671365b5111a79e5030 Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Wed, 4 Dec 2024 01:36:56 +0100 Subject: [PATCH 06/22] Added stateManager --- lib/src/manager/pluto_grid_state_manager.dart | 2 +- lib/src/manager/state/row_state.dart | 2 +- lib/src/pluto_grid.dart | 5 ++++- lib/src/ui/pluto_body_rows.dart | 4 +++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/src/manager/pluto_grid_state_manager.dart b/lib/src/manager/pluto_grid_state_manager.dart index 7643e6fcf..b29d1690a 100644 --- a/lib/src/manager/pluto_grid_state_manager.dart +++ b/lib/src/manager/pluto_grid_state_manager.dart @@ -110,7 +110,7 @@ class PlutoGridStateChangeNotifier extends PlutoChangeNotifier } @override - final Widget Function(BuildContext context, Widget row)? rowWrapper; + final RowWrapper? rowWrapper; @override final Widget Function(Widget editCellWidget, PlutoCell cell, diff --git a/lib/src/manager/state/row_state.dart b/lib/src/manager/state/row_state.dart index b2ef39c68..48c466947 100644 --- a/lib/src/manager/state/row_state.dart +++ b/lib/src/manager/state/row_state.dart @@ -41,7 +41,7 @@ abstract class IRowState { /// Row of currently selected cell. PlutoRow? get currentRow; - Widget Function(BuildContext context, Widget row)? get rowWrapper; + RowWrapper? get rowWrapper; PlutoRowColorCallback? get rowColorCallback; diff --git a/lib/src/pluto_grid.dart b/lib/src/pluto_grid.dart index 8d1997d74..5da3da498 100644 --- a/lib/src/pluto_grid.dart +++ b/lib/src/pluto_grid.dart @@ -57,6 +57,9 @@ typedef PlutoSelectDateCallBack = Future Function( typedef PlutoOnActiveCellChangedEventCallback = void Function( PlutoGridOnActiveCellChangedEvent event); +typedef RowWrapper = Widget Function( + BuildContext context, Widget row, PlutoGridStateManager stateManager); + /// [PlutoGrid] is a widget that receives columns and rows and is expressed as a grid-type UI. /// /// [PlutoGrid] supports movement and editing with the keyboard, @@ -97,7 +100,7 @@ class PlutoGrid extends PlutoStatefulWidget { }); /// A wrapper that wraps arround each row. - final Widget Function(BuildContext context, Widget row)? rowWrapper; + final RowWrapper? rowWrapper; final Widget Function(Widget editCellWidget, PlutoCell cell, TextEditingController controller)? editCellWrapper; diff --git a/lib/src/ui/pluto_body_rows.dart b/lib/src/ui/pluto_body_rows.dart index b95101d0e..558611f0b 100644 --- a/lib/src/ui/pluto_body_rows.dart +++ b/lib/src/ui/pluto_body_rows.dart @@ -115,7 +115,9 @@ class PlutoBodyRowsState extends PlutoStateWithChange { visibilityLayout: true, ); - return stateManager.rowWrapper?.call(context, row) ?? row; + return stateManager.rowWrapper + ?.call(context, row, stateManager) ?? + row; }, ), ), From f8e232c37acd95fa0f93b431f583155492688fde Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Wed, 4 Dec 2024 01:49:42 +0100 Subject: [PATCH 07/22] Added coments --- lib/src/manager/pluto_grid_state_manager.dart | 1 + lib/src/manager/state/row_state.dart | 5 +++++ lib/src/pluto_grid.dart | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/src/manager/pluto_grid_state_manager.dart b/lib/src/manager/pluto_grid_state_manager.dart index b29d1690a..b977d151a 100644 --- a/lib/src/manager/pluto_grid_state_manager.dart +++ b/lib/src/manager/pluto_grid_state_manager.dart @@ -109,6 +109,7 @@ class PlutoGridStateChangeNotifier extends PlutoChangeNotifier _initialize(); } + /// {@macro pluto_grid_row_wrapper} @override final RowWrapper? rowWrapper; diff --git a/lib/src/manager/state/row_state.dart b/lib/src/manager/state/row_state.dart index 48c466947..8aeb7fa26 100644 --- a/lib/src/manager/state/row_state.dart +++ b/lib/src/manager/state/row_state.dart @@ -41,6 +41,11 @@ abstract class IRowState { /// Row of currently selected cell. PlutoRow? get currentRow; + /// {@template pluto_grid_row_wrapper} + /// + /// A wrapper that wraps arround each row. + /// + /// {@endtemplate} RowWrapper? get rowWrapper; PlutoRowColorCallback? get rowColorCallback; diff --git a/lib/src/pluto_grid.dart b/lib/src/pluto_grid.dart index 5da3da498..459280a66 100644 --- a/lib/src/pluto_grid.dart +++ b/lib/src/pluto_grid.dart @@ -99,7 +99,7 @@ class PlutoGrid extends PlutoStatefulWidget { this.mode = PlutoGridMode.normal, }); - /// A wrapper that wraps arround each row. + /// {@macro pluto_grid_row_wrapper} final RowWrapper? rowWrapper; final Widget Function(Widget editCellWidget, PlutoCell cell, From 80772c01dd703c96592e06d7c8c408f39743e41e Mon Sep 17 00:00:00 2001 From: Pierre CORSINI <50719398+pierrecorsini@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:45:49 +0100 Subject: [PATCH 08/22] fix: guard agains missing scroll client (disposed) --- lib/src/plugin/pluto_infinity_scroll_rows.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/plugin/pluto_infinity_scroll_rows.dart b/lib/src/plugin/pluto_infinity_scroll_rows.dart index 060862574..756d0232f 100644 --- a/lib/src/plugin/pluto_infinity_scroll_rows.dart +++ b/lib/src/plugin/pluto_infinity_scroll_rows.dart @@ -202,7 +202,7 @@ class _PlutoInfinityScrollRowsState extends State { if (!_isLast) { WidgetsBinding.instance.addPostFrameCallback((_) { - if (scroll.position.maxScrollExtent == 0) { + if (scroll.hasClients && scroll.position.maxScrollExtent == 0) { var lastRow = stateManager.rows.isNotEmpty ? stateManager.rows.last : null; _update(lastRow); } From 10c9ce36d0e54e42936f0465428012a0bfdf21c4 Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Fri, 6 Dec 2024 18:30:31 +0100 Subject: [PATCH 09/22] Fix unit tests --- demo/pubspec.yaml | 174 +++---- lib/src/helper/pluto_key_manager_event.dart | 448 ++++++++++-------- .../helper/pluto_key_manager_event_test.dart | 433 +++++++++-------- 3 files changed, 572 insertions(+), 483 deletions(-) diff --git a/demo/pubspec.yaml b/demo/pubspec.yaml index 9d24b2f0e..06ae60b00 100644 --- a/demo/pubspec.yaml +++ b/demo/pubspec.yaml @@ -1,86 +1,88 @@ -name: demo -description: PlutoGrid demo app. - -# The following line prevents the package from being accidentally published to -# pub.dev using `pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 - -environment: - sdk: ^3.0.0 - -dependencies: - flutter: - sdk: flutter - pluto_grid_plus: 8.4.3 - faker: ^2.1.0 - url_launcher: ^6.2.1 - font_awesome_flutter: ^10.6.0 - rainbow_color: ^2.0.1 - pluto_menu_bar: ^3.0.1 - file_saver: ^0.2.10 - pluto_grid_plus_export: 1.0.5 - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.6 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^5.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - assets: - - assets/images/ - - fonts: - - family: OpenSans - fonts: - - asset: assets/fonts/open_sans/OpenSans-ExtraBold.ttf - weight: 800 - - asset: assets/fonts/open_sans/OpenSans-ExtraBoldItalic.ttf - weight: 800 - style: italic - - asset: assets/fonts/open_sans/OpenSans-Bold.ttf - weight: 700 - - asset: assets/fonts/open_sans/OpenSans-BoldItalic.ttf - weight: 700 - style: italic - - asset: assets/fonts/open_sans/OpenSans-SemiBold.ttf - weight: 600 - - asset: assets/fonts/open_sans/OpenSans-SemiBoldItalic.ttf - weight: 600 - style: italic - - asset: assets/fonts/open_sans/OpenSans-Regular.ttf - weight: 400 - - asset: assets/fonts/open_sans/OpenSans-Italic.ttf - weight: 400 - style: italic - - asset: assets/fonts/open_sans/OpenSans-Light.ttf - weight: 300 - - asset: assets/fonts/open_sans/OpenSans-LightItalic.ttf - weight: 300 - style: italic - +name: demo +description: PlutoGrid demo app. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ^3.0.0 + +dependency_overrides: + pluto_grid_plus: + path: ../ + +dependencies: + flutter: + sdk: flutter + pluto_grid_plus: 8.4.3 + faker: ^2.1.0 + url_launcher: ^6.2.1 + font_awesome_flutter: ^10.6.0 + rainbow_color: ^2.0.1 + pluto_menu_bar: ^3.0.1 + file_saver: ^0.2.10 + pluto_grid_plus_export: 1.0.5 + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.6 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/ + + fonts: + - family: OpenSans + fonts: + - asset: assets/fonts/open_sans/OpenSans-ExtraBold.ttf + weight: 800 + - asset: assets/fonts/open_sans/OpenSans-ExtraBoldItalic.ttf + weight: 800 + style: italic + - asset: assets/fonts/open_sans/OpenSans-Bold.ttf + weight: 700 + - asset: assets/fonts/open_sans/OpenSans-BoldItalic.ttf + weight: 700 + style: italic + - asset: assets/fonts/open_sans/OpenSans-SemiBold.ttf + weight: 600 + - asset: assets/fonts/open_sans/OpenSans-SemiBoldItalic.ttf + weight: 600 + style: italic + - asset: assets/fonts/open_sans/OpenSans-Regular.ttf + weight: 400 + - asset: assets/fonts/open_sans/OpenSans-Italic.ttf + weight: 400 + style: italic + - asset: assets/fonts/open_sans/OpenSans-Light.ttf + weight: 300 + - asset: assets/fonts/open_sans/OpenSans-LightItalic.ttf + weight: 300 + style: italic diff --git a/lib/src/helper/pluto_key_manager_event.dart b/lib/src/helper/pluto_key_manager_event.dart index 13294fcce..855c39e17 100644 --- a/lib/src/helper/pluto_key_manager_event.dart +++ b/lib/src/helper/pluto_key_manager_event.dart @@ -1,207 +1,241 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -class PlutoKeyManagerEvent { - FocusNode focusNode; - KeyEvent event; - - PlutoKeyManagerEvent({ - required this.focusNode, - required this.event, - }); - - bool get needsThrottle => isMoving || isTab || isPageUp || isPageDown; - - bool get isKeyDownEvent => event.runtimeType == KeyDownEvent; - - bool get isKeyUpEvent => event.runtimeType == KeyUpEvent; - - bool get isMoving => isHorizontal || isVertical; - - bool get isHorizontal => isLeft || isRight; - - bool get isVertical => isUp || isDown; - - bool get isLeft => - event.logicalKey.keyId == LogicalKeyboardKey.arrowLeft.keyId; - - bool get isRight => - event.logicalKey.keyId == LogicalKeyboardKey.arrowRight.keyId; - - bool get isUp => event.logicalKey.keyId == LogicalKeyboardKey.arrowUp.keyId; - - bool get isDown => - event.logicalKey.keyId == LogicalKeyboardKey.arrowDown.keyId; - - bool get isHome => event.logicalKey.keyId == LogicalKeyboardKey.home.keyId; - - bool get isEnd => event.logicalKey.keyId == LogicalKeyboardKey.end.keyId; - - bool get isPageUp { - // windows 에서 pageUp keyId 가 0x10700000021. - return event.logicalKey.keyId == LogicalKeyboardKey.pageUp.keyId || - event.logicalKey.keyId == 0x10700000021; - } - - bool get isPageDown { - // windows 에서 pageDown keyId 가 0x10700000022. - return event.logicalKey.keyId == LogicalKeyboardKey.pageDown.keyId || - event.logicalKey.keyId == 0x10700000022; - } - - bool get isEsc => event.logicalKey.keyId == LogicalKeyboardKey.escape.keyId; - - bool get isEnter => - event.logicalKey.keyId == LogicalKeyboardKey.enter.keyId || - event.logicalKey.keyId == LogicalKeyboardKey.numpadEnter.keyId; - - bool get isTab => event.logicalKey.keyId == LogicalKeyboardKey.tab.keyId; - - bool get isF2 => event.logicalKey.keyId == LogicalKeyboardKey.f2.keyId; - - bool get isF3 => event.logicalKey.keyId == LogicalKeyboardKey.f3.keyId; - - bool get isF4 => event.logicalKey.keyId == LogicalKeyboardKey.f4.keyId; - - bool get isBackspace => - event.logicalKey.keyId == LogicalKeyboardKey.backspace.keyId; - - bool get isShift => - event.logicalKey.keyId == LogicalKeyboardKey.shift.keyId; - - bool get isControl => - event.logicalKey.keyId == LogicalKeyboardKey.control.keyId; - - bool get isCharacter => _characters.contains(event.logicalKey.keyId); - - bool get isCtrlC { - return isCtrlPressed && - event.logicalKey.keyId == LogicalKeyboardKey.keyC.keyId; - } - - bool get isCtrlV { - return isCtrlPressed && - event.logicalKey.keyId == LogicalKeyboardKey.keyV.keyId; - } - - bool get isCtrlA { - return isCtrlPressed && - event.logicalKey.keyId == LogicalKeyboardKey.keyA.keyId; - } - - bool get isShiftPressed { - return HardwareKeyboard.instance.isShiftPressed; - } - - bool get isCtrlPressed { - return HardwareKeyboard.instance.isMetaPressed || - HardwareKeyboard.instance.isControlPressed; - } - - bool get isAltPressed { - return HardwareKeyboard.instance.isAltPressed; - } - - bool get isModifierPressed { - return isShiftPressed || isCtrlPressed || isAltPressed; - } -} - -const _characters = { - 0x0000000041, // keyA, - 0x0000000042, // keyB, - 0x0000000043, // keyC, - 0x0000000044, // keyD, - 0x0000000045, // keyE, - 0x0000000046, // keyF, - 0x0000000047, // keyG, - 0x0000000048, // keyH, - 0x0000000049, // keyI, - 0x000000004a, // keyJ, - 0x000000004b, // keyK, - 0x000000004c, // keyL, - 0x000000004d, // keyM, - 0x000000004e, // keyN, - 0x000000004f, // keyO, - 0x0000000050, // keyP, - 0x0000000051, // keyQ, - 0x0000000052, // keyR, - 0x0000000053, // keyS, - 0x0000000054, // keyT, - 0x0000000055, // keyU, - 0x0000000056, // keyV, - 0x0000000057, // keyW, - 0x0000000058, // keyX, - 0x0000000059, // keyY, - 0x000000005a, // keyZ, - 0x0000000061, // keyA, - 0x0000000062, // keyB, - 0x0000000063, // keyC, - 0x0000000064, // keyD, - 0x0000000065, // keyE, - 0x0000000066, // keyF, - 0x0000000067, // keyG, - 0x0000000068, // keyH, - 0x0000000069, // keyI, - 0x000000006a, // keyJ, - 0x000000006b, // keyK, - 0x000000006c, // keyL, - 0x000000006d, // keyM, - 0x000000006e, // keyN, - 0x000000006f, // keyO, - 0x0000000070, // keyP, - 0x0000000071, // keyQ, - 0x0000000072, // keyR, - 0x0000000073, // keyS, - 0x0000000074, // keyT, - 0x0000000075, // keyU, - 0x0000000076, // keyV, - 0x0000000077, // keyW, - 0x0000000078, // keyX, - 0x0000000079, // keyY, - 0x000000007a, // keyZ, - 0x0000000031, // digit1, - 0x0000000032, // digit2, - 0x0000000033, // digit3, - 0x0000000034, // digit4, - 0x0000000035, // digit5, - 0x0000000036, // digit6, - 0x0000000037, // digit7, - 0x0000000038, // digit8, - 0x0000000039, // digit9, - 0x0000000030, // digit0, - 0x0000000020, // space, - 0x000000002d, // minus, - 0x000000003d, // equal, - 0x000000005b, // bracketLeft, - 0x000000005d, // bracketRight, - 0x000000005c, // backslash, - 0x000000003b, // semicolon, - 0x0000000027, // quote, - 0x0000000060, // backquote, - 0x000000002c, // comma, - 0x000000002e, // period, - 0x000000002f, // slash, - 0x0100070054, // numpadDivide, - 0x0100070055, // numpadMultiply, - 0x0100070056, // numpadSubtract, - 0x0100070057, // numpadAdd, - 0x0100070059, // numpad1, - 0x010007005a, // numpad2, - 0x010007005b, // numpad3, - 0x010007005c, // numpad4, - 0x010007005d, // numpad5, - 0x010007005e, // numpad6, - 0x010007005f, // numpad7, - 0x0100070060, // numpad8, - 0x0100070061, // numpad9, - 0x0100070062, // numpad0, - 0x0100070063, // numpadDecimal, - 0x0100070064, // intlBackslash, - 0x0100070067, // numpadEqual, - 0x0100070085, // numpadComma, - 0x0100070087, // intlRo, - 0x0100070089, // intlYen, - 0x01000700b6, // numpadParenLeft, - 0x01000700b7, // numpadParenRight, -}; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class PlutoKeyManagerEvent { + FocusNode focusNode; + KeyEvent event; + bool Function(LogicalKeyboardKey key)? isLogicalKeyPressed; + + PlutoKeyManagerEvent({ + required this.focusNode, + required this.event, + this.isLogicalKeyPressed, + }); + + bool get needsThrottle => isMoving || isTab || isPageUp || isPageDown; + + bool get isKeyDownEvent => event.runtimeType == KeyDownEvent; + + bool get isKeyUpEvent => event.runtimeType == KeyUpEvent; + + bool get isMoving => isHorizontal || isVertical; + + bool get isHorizontal => isLeft || isRight; + + bool get isVertical => isUp || isDown; + + bool get isLeft => + event.logicalKey.keyId == LogicalKeyboardKey.arrowLeft.keyId; + + bool get isRight => + event.logicalKey.keyId == LogicalKeyboardKey.arrowRight.keyId; + + bool get isUp => event.logicalKey.keyId == LogicalKeyboardKey.arrowUp.keyId; + + bool get isDown => + event.logicalKey.keyId == LogicalKeyboardKey.arrowDown.keyId; + + bool get isHome => event.logicalKey.keyId == LogicalKeyboardKey.home.keyId; + + bool get isEnd => event.logicalKey.keyId == LogicalKeyboardKey.end.keyId; + + bool get isPageUp { + // windows 에서 pageUp keyId 가 0x10700000021. + return event.logicalKey.keyId == LogicalKeyboardKey.pageUp.keyId || + event.logicalKey.keyId == 0x10700000021; + } + + bool get isPageDown { + // windows 에서 pageDown keyId 가 0x10700000022. + return event.logicalKey.keyId == LogicalKeyboardKey.pageDown.keyId || + event.logicalKey.keyId == 0x10700000022; + } + + bool get isEsc => event.logicalKey.keyId == LogicalKeyboardKey.escape.keyId; + + bool get isEnter => + event.logicalKey.keyId == LogicalKeyboardKey.enter.keyId || + event.logicalKey.keyId == LogicalKeyboardKey.numpadEnter.keyId; + + bool get isTab => event.logicalKey.keyId == LogicalKeyboardKey.tab.keyId; + + bool get isF2 => event.logicalKey.keyId == LogicalKeyboardKey.f2.keyId; + + bool get isF3 => event.logicalKey.keyId == LogicalKeyboardKey.f3.keyId; + + bool get isF4 => event.logicalKey.keyId == LogicalKeyboardKey.f4.keyId; + + bool get isBackspace => + event.logicalKey.keyId == LogicalKeyboardKey.backspace.keyId; + + /// This can be: + /// + /// LogicalKeyboardKey.shift + /// LogicalKeyboardKey.shiftLeft + /// LogicalKeyboardKey.shiftRight + bool get isShift => [ + LogicalKeyboardKey.shift, + LogicalKeyboardKey.shiftLeft, + LogicalKeyboardKey.shiftRight, + ].any((lKey) => lKey.keyId == event.logicalKey.keyId); + + bool get isLeftShift => [ + LogicalKeyboardKey.shiftLeft, + ].any((lKey) => lKey.keyId == event.logicalKey.keyId); + + bool get isRightShift => [ + LogicalKeyboardKey.shiftRight, + ].any((lKey) => lKey.keyId == event.logicalKey.keyId); + + /// This can be: + /// + /// LogicalKeyboardKey.control + /// LogicalKeyboardKey.controlLeft + /// LogicalKeyboardKey.controlRight + bool get isControl => [ + LogicalKeyboardKey.control, + LogicalKeyboardKey.controlLeft, + LogicalKeyboardKey.controlRight, + ].any((lKey) => lKey.keyId == event.logicalKey.keyId); + + bool get isLeftControl => [ + LogicalKeyboardKey.controlLeft, + ].any((lKey) => lKey.keyId == event.logicalKey.keyId); + + bool get isRightControl => [ + LogicalKeyboardKey.controlRight, + ].any((lKey) => lKey.keyId == event.logicalKey.keyId); + + bool get isCharacter => _characters.contains(event.logicalKey.keyId); + + bool get isCtrlC { + return isCtrlPressed && + event.logicalKey.keyId == LogicalKeyboardKey.keyC.keyId; + } + + bool get isCtrlV { + return isCtrlPressed && + event.logicalKey.keyId == LogicalKeyboardKey.keyV.keyId; + } + + bool get isCtrlA { + return isCtrlPressed && + event.logicalKey.keyId == LogicalKeyboardKey.keyA.keyId; + } + + bool get isShiftPressed { + return HardwareKeyboard.instance.isShiftPressed; + } + + bool get isCtrlPressed { + return HardwareKeyboard.instance.isMetaPressed || + HardwareKeyboard.instance.isControlPressed; + } + + bool get isAltPressed { + return HardwareKeyboard.instance.isAltPressed; + } + + bool get isModifierPressed { + return isShiftPressed || isCtrlPressed || isAltPressed; + } +} + +const _characters = { + 0x0000000041, // keyA, + 0x0000000042, // keyB, + 0x0000000043, // keyC, + 0x0000000044, // keyD, + 0x0000000045, // keyE, + 0x0000000046, // keyF, + 0x0000000047, // keyG, + 0x0000000048, // keyH, + 0x0000000049, // keyI, + 0x000000004a, // keyJ, + 0x000000004b, // keyK, + 0x000000004c, // keyL, + 0x000000004d, // keyM, + 0x000000004e, // keyN, + 0x000000004f, // keyO, + 0x0000000050, // keyP, + 0x0000000051, // keyQ, + 0x0000000052, // keyR, + 0x0000000053, // keyS, + 0x0000000054, // keyT, + 0x0000000055, // keyU, + 0x0000000056, // keyV, + 0x0000000057, // keyW, + 0x0000000058, // keyX, + 0x0000000059, // keyY, + 0x000000005a, // keyZ, + 0x0000000061, // keyA, + 0x0000000062, // keyB, + 0x0000000063, // keyC, + 0x0000000064, // keyD, + 0x0000000065, // keyE, + 0x0000000066, // keyF, + 0x0000000067, // keyG, + 0x0000000068, // keyH, + 0x0000000069, // keyI, + 0x000000006a, // keyJ, + 0x000000006b, // keyK, + 0x000000006c, // keyL, + 0x000000006d, // keyM, + 0x000000006e, // keyN, + 0x000000006f, // keyO, + 0x0000000070, // keyP, + 0x0000000071, // keyQ, + 0x0000000072, // keyR, + 0x0000000073, // keyS, + 0x0000000074, // keyT, + 0x0000000075, // keyU, + 0x0000000076, // keyV, + 0x0000000077, // keyW, + 0x0000000078, // keyX, + 0x0000000079, // keyY, + 0x000000007a, // keyZ, + 0x0000000031, // digit1, + 0x0000000032, // digit2, + 0x0000000033, // digit3, + 0x0000000034, // digit4, + 0x0000000035, // digit5, + 0x0000000036, // digit6, + 0x0000000037, // digit7, + 0x0000000038, // digit8, + 0x0000000039, // digit9, + 0x0000000030, // digit0, + 0x0000000020, // space, + 0x000000002d, // minus, + 0x000000003d, // equal, + 0x000000005b, // bracketLeft, + 0x000000005d, // bracketRight, + 0x000000005c, // backslash, + 0x000000003b, // semicolon, + 0x0000000027, // quote, + 0x0000000060, // backquote, + 0x000000002c, // comma, + 0x000000002e, // period, + 0x000000002f, // slash, + 0x0100070054, // numpadDivide, + 0x0100070055, // numpadMultiply, + 0x0100070056, // numpadSubtract, + 0x0100070057, // numpadAdd, + 0x0100070059, // numpad1, + 0x010007005a, // numpad2, + 0x010007005b, // numpad3, + 0x010007005c, // numpad4, + 0x010007005d, // numpad5, + 0x010007005e, // numpad6, + 0x010007005f, // numpad7, + 0x0100070060, // numpad8, + 0x0100070061, // numpad9, + 0x0100070062, // numpad0, + 0x0100070063, // numpadDecimal, + 0x0100070064, // intlBackslash, + 0x0100070067, // numpadEqual, + 0x0100070085, // numpadComma, + 0x0100070087, // intlRo, + 0x0100070089, // intlYen, + 0x01000700b6, // numpadParenLeft, + 0x01000700b7, // numpadParenRight, +}; diff --git a/test/src/helper/pluto_key_manager_event_test.dart b/test/src/helper/pluto_key_manager_event_test.dart index dc20b95b2..c31764414 100644 --- a/test/src/helper/pluto_key_manager_event_test.dart +++ b/test/src/helper/pluto_key_manager_event_test.dart @@ -1,190 +1,243 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:pluto_grid_plus/pluto_grid_plus.dart'; - -void main() { - late FocusNode focusNode; - - late PlutoKeyManagerEvent? keyManagerEvent; - - KeyEventResult callback(FocusNode node, KeyEvent event) { - keyManagerEvent = PlutoKeyManagerEvent( - focusNode: node, - event: event, - ); - - return KeyEventResult.handled; - } - - setUp(() { - focusNode = FocusNode(); - }); - - tearDown(() { - keyManagerEvent = null; - }); - - Future buildWidget({ - required WidgetTester tester, - required KeyEventResult Function(FocusNode, KeyEvent) callback, - }) async { - await tester.pumpWidget(MaterialApp( - home: FocusScope( - autofocus: true, - onKeyEvent: callback, - child: Focus( - focusNode: focusNode, - child: const SizedBox(width: 100, height: 100), - ), - ), - )); - - focusNode.requestFocus(); - } - - testWidgets( - '아무 키나 입력하면 isKeyDownEvent 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.keyE; - await tester.sendKeyDownEvent(key); - expect(keyManagerEvent!.isKeyDownEvent, true); - await tester.sendKeyUpEvent(key); - expect(keyManagerEvent!.isKeyDownEvent, false); - }, - ); - - testWidgets( - 'Home 키를 입력하면 isHome 이 true 여야 한다.', - (tester) async { - late PlutoKeyManagerEvent keyManagerEvent; - - KeyEventResult callback(FocusNode node, KeyEvent event) { - keyManagerEvent = PlutoKeyManagerEvent( - focusNode: node, - event: event, - ); - - return KeyEventResult.handled; - } - - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.home; - await tester.sendKeyDownEvent(key); - expect(keyManagerEvent.isHome, true); - await tester.sendKeyUpEvent(key); - }, - ); - - testWidgets( - 'End 키를 입력하면 isEnd 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.end; - await tester.sendKeyDownEvent(key); - expect(keyManagerEvent!.isEnd, true); - await tester.sendKeyUpEvent(key); - }, - ); - - testWidgets( - 'F4 키를 입력하면 isF4 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.f4; - await tester.sendKeyDownEvent(key); - expect(keyManagerEvent!.isF4, true); - await tester.sendKeyUpEvent(key); - }, - ); - - testWidgets( - 'Backspace 키를 입력하면 isBackspace 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.backspace; - await tester.sendKeyDownEvent(key); - expect(keyManagerEvent!.isBackspace, true); - await tester.sendKeyUpEvent(key); - }, - ); - - testWidgets( - 'Shift 키를 입력하면 isShift 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.shift; - await tester.sendKeyDownEvent(key); - expect(keyManagerEvent!.isShift, true); - await tester.sendKeyUpEvent(key); - }, - ); - - testWidgets( - 'Control 키를 입력하면 isControl 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.control; - await tester.sendKeyDownEvent(key); - expect(keyManagerEvent!.isControl, true); - await tester.sendKeyUpEvent(key); - }, - ); - - // While key combos still work in the real world, these 3 tests are failing due to what I suspect is an - // incomplete deprecation/migration from focusNode `onKey` to `onKeyEvent`. - // Flutter 3.19 does not trigger our event for `sendKeyUpEvent` only, and I prefer not - // to switch these tests to `sendKeyDownEvent` as that may cause unexpected behavior - // such as pasting multiple times due to repeating key presses. It might also be fine. - - // https://github.com/flutter/flutter/issues/136419 - testWidgets( - 'Control + C 키를 입력하면 isCtrlC 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.control; - const key2 = LogicalKeyboardKey.keyC; - await tester.sendKeyDownEvent(key); - await tester.sendKeyUpEvent( - key2); // sendKeyUpEvent is not sending a keyManagerEvent - - expect(keyManagerEvent?.isCtrlC, true); - await tester.sendKeyUpEvent(key); - }, - ); - - testWidgets( - 'Control + V 키를 입력하면 isCtrlV 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.control; - await tester.sendKeyDownEvent(key); - await tester.sendKeyUpEvent(LogicalKeyboardKey.keyV); - expect(keyManagerEvent!.isCtrlV, true); - await tester.sendKeyUpEvent(key); - }, - ); - - testWidgets( - 'Control + A 키를 입력하면 isCtrlA 가 true 여야 한다.', - (tester) async { - await buildWidget(tester: tester, callback: callback); - - const key = LogicalKeyboardKey.control; - await tester.sendKeyDownEvent(key); - await tester.sendKeyUpEvent(LogicalKeyboardKey.keyA); - expect(keyManagerEvent!.isCtrlA, true); - await tester.sendKeyUpEvent(key); - }, - ); -} +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pluto_grid_plus/pluto_grid_plus.dart'; + +void main() { + late FocusNode focusNode; + + late PlutoKeyManagerEvent? keyManagerEvent; + + KeyEventResult callback(FocusNode node, KeyEvent event) { + keyManagerEvent = PlutoKeyManagerEvent( + focusNode: node, + event: event, + isLogicalKeyPressed: HardwareKeyboard.instance.isLogicalKeyPressed, + ); + + return KeyEventResult.handled; + } + + setUp(() { + focusNode = FocusNode(); + }); + + tearDown(() { + keyManagerEvent = null; + }); + + Future buildWidget({ + required WidgetTester tester, + required FocusOnKeyEventCallback callback, + }) async { + await tester.pumpWidget(MaterialApp( + home: FocusScope( + autofocus: true, + onKeyEvent: callback, + child: Focus( + focusNode: focusNode, + child: const SizedBox(width: 100, height: 100), + ), + ), + )); + + focusNode.requestFocus(); + } + + testWidgets( + '아무 키나 입력하면 isKeyDownEvent 가 true 여야 한다.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.keyE; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isKeyDownEvent, true); + await tester.sendKeyUpEvent(key); + expect(keyManagerEvent!.isKeyDownEvent, false); + }, + ); + + testWidgets( + 'Home 키를 입력하면 isHome 이 true 여야 한다.', + (tester) async { + late PlutoKeyManagerEvent keyManagerEvent; + + KeyEventResult callback(FocusNode node, KeyEvent event) { + keyManagerEvent = PlutoKeyManagerEvent( + focusNode: node, + event: event, + ); + + return KeyEventResult.handled; + } + + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.home; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent.isHome, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'End 키를 입력하면 isEnd 가 true 여야 한다.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.end; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isEnd, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'F4 키를 입력하면 isF4 가 true 여야 한다.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.f4; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isF4, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'Backspace 키를 입력하면 isBackspace 가 true 여야 한다.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.backspace; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isBackspace, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'When the Shift key is pressed, isShift must be `true`.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.shift; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isShift, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'When the LeftShift key is pressed, isLeftShift must be `true`.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.shiftLeft; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isLeftShift, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'When the RightShift key is pressed, RightShift must be `true`.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.shiftRight; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isRightShift, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'If the Control key is pressed, isControl should be true.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.control; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isControl, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'If the controlLeft key is pressed, isLeftControl should be true.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.controlLeft; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isLeftControl, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'If the controlRight key is pressed, isRightControl should be true.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.controlRight; + await tester.sendKeyDownEvent(key); + expect(keyManagerEvent!.isRightControl, true); + await tester.sendKeyUpEvent(key); + }, + ); + + testWidgets( + 'If the Control + C keys are pressed, isCtrlC should be true.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.control; + const key2 = LogicalKeyboardKey.keyC; + + await tester.sendKeyDownEvent(key); + await tester.sendKeyDownEvent(key2); + + expect(keyManagerEvent?.isCtrlC, true); + + await tester.sendKeyUpEvent(key); + await tester.sendKeyUpEvent(key2); + }, + ); + + testWidgets( + 'If the Control + V keys are pressed, isCtrlV should be true.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.control; + const key2 = LogicalKeyboardKey.keyV; + + await tester.sendKeyDownEvent(key); + await tester.sendKeyDownEvent(key2); + + expect(keyManagerEvent!.isCtrlV, true); + await tester.sendKeyUpEvent(key); + await tester.sendKeyUpEvent(key2); + }, + ); + + testWidgets( + 'If the Control + A keys are pressed, isCtrlA should be true.', + (tester) async { + await buildWidget(tester: tester, callback: callback); + + const key = LogicalKeyboardKey.control; + const key2 = LogicalKeyboardKey.keyA; + + await tester.sendKeyDownEvent(key); + await tester.sendKeyDownEvent(key2); + + expect(keyManagerEvent!.isCtrlA, true); + + await tester.sendKeyUpEvent(key); + await tester.sendKeyUpEvent(key2); + }, + ); +} From 1c917b8b37f7cb0574443d486fafe638a4f18729 Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Fri, 6 Dec 2024 19:33:25 +0100 Subject: [PATCH 10/22] Changed test to english --- .../helper/pluto_key_manager_event_test.dart | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/src/helper/pluto_key_manager_event_test.dart b/test/src/helper/pluto_key_manager_event_test.dart index c31764414..f91afa98f 100644 --- a/test/src/helper/pluto_key_manager_event_test.dart +++ b/test/src/helper/pluto_key_manager_event_test.dart @@ -45,7 +45,7 @@ void main() { } testWidgets( - '아무 키나 입력하면 isKeyDownEvent 가 true 여야 한다.', + 'When any key is pressed, isKeyDownEvent must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -58,7 +58,7 @@ void main() { ); testWidgets( - 'Home 키를 입력하면 isHome 이 true 여야 한다.', + 'When the Home key is pressed, isHome must be `true`.', (tester) async { late PlutoKeyManagerEvent keyManagerEvent; @@ -81,7 +81,7 @@ void main() { ); testWidgets( - 'End 키를 입력하면 isEnd 가 true 여야 한다.', + 'When the End key is pressed, isEnd must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -93,7 +93,7 @@ void main() { ); testWidgets( - 'F4 키를 입력하면 isF4 가 true 여야 한다.', + 'When the F4 key is pressed, isF4 must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -105,7 +105,7 @@ void main() { ); testWidgets( - 'Backspace 키를 입력하면 isBackspace 가 true 여야 한다.', + 'When the Backspace key is pressed, isBackspace must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -141,7 +141,7 @@ void main() { ); testWidgets( - 'When the RightShift key is pressed, RightShift must be `true`.', + 'When the RightShift key is pressed, isRightShift must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -153,7 +153,7 @@ void main() { ); testWidgets( - 'If the Control key is pressed, isControl should be true.', + 'When the Control key is pressed, isControl must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -165,7 +165,7 @@ void main() { ); testWidgets( - 'If the controlLeft key is pressed, isLeftControl should be true.', + 'When the LeftControl key is pressed, isLeftControl must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -177,7 +177,7 @@ void main() { ); testWidgets( - 'If the controlRight key is pressed, isRightControl should be true.', + 'When the RightControl key is pressed, isRightControl must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -189,7 +189,7 @@ void main() { ); testWidgets( - 'If the Control + C keys are pressed, isCtrlC should be true.', + 'When Control + C keys are pressed, isCtrlC must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -207,7 +207,7 @@ void main() { ); testWidgets( - 'If the Control + V keys are pressed, isCtrlV should be true.', + 'When Control + V keys are pressed, isCtrlV must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); @@ -224,7 +224,7 @@ void main() { ); testWidgets( - 'If the Control + A keys are pressed, isCtrlA should be true.', + 'When Control + A keys are pressed, isCtrlA must be `true`.', (tester) async { await buildWidget(tester: tester, callback: callback); From f0179124d8108e186f2ff7a21e4b9952a039bcaa Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Fri, 6 Dec 2024 20:04:36 +0100 Subject: [PATCH 11/22] Fixed test --- .../helper/pluto_aggregate_helper_test.dart | 824 +++++++++--------- 1 file changed, 412 insertions(+), 412 deletions(-) diff --git a/test/src/helper/pluto_aggregate_helper_test.dart b/test/src/helper/pluto_aggregate_helper_test.dart index 2bc4111d7..080be252c 100644 --- a/test/src/helper/pluto_aggregate_helper_test.dart +++ b/test/src/helper/pluto_aggregate_helper_test.dart @@ -1,412 +1,412 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:pluto_grid_plus/pluto_grid_plus.dart'; - -void main() { - group('sum', () { - test('숫자 컬럼이 아닌경우 0이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.text(), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), - PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), - PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), - PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), - PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), - ]; - - expect(PlutoAggregateHelper.sum(rows: rows, column: column), 0); - }); - - test('[양수] condition 이 없이 sum 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10)}), - PlutoRow(cells: {'column': PlutoCell(value: 20)}), - PlutoRow(cells: {'column': PlutoCell(value: 30)}), - PlutoRow(cells: {'column': PlutoCell(value: 40)}), - PlutoRow(cells: {'column': PlutoCell(value: 50)}), - ]; - - expect(PlutoAggregateHelper.sum(rows: rows, column: column), 150); - }); - - test('[음수] condition 이 없이 sum 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: -10)}), - PlutoRow(cells: {'column': PlutoCell(value: -20)}), - PlutoRow(cells: {'column': PlutoCell(value: -30)}), - PlutoRow(cells: {'column': PlutoCell(value: -40)}), - PlutoRow(cells: {'column': PlutoCell(value: -50)}), - ]; - - expect(PlutoAggregateHelper.sum(rows: rows, column: column), -150); - }); - - test('[소수] condition 이 없이 sum 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - ]; - - expect(PlutoAggregateHelper.sum(rows: rows, column: column), 50.005); - }); - - test('condition 이 있는 경우 조건에 맞는 아이템의 합계 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - ]; - - expect( - PlutoAggregateHelper.sum( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value == 10.001, - ), - 30.003, - ); - }); - - test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 0이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - ]; - - expect( - PlutoAggregateHelper.sum( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value == 10.003, - ), - 0, - ); - }); - }); - - group('average', () { - test('[양수] condition 이 없이 average 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10)}), - PlutoRow(cells: {'column': PlutoCell(value: 20)}), - PlutoRow(cells: {'column': PlutoCell(value: 30)}), - PlutoRow(cells: {'column': PlutoCell(value: 40)}), - PlutoRow(cells: {'column': PlutoCell(value: 50)}), - ]; - - expect(PlutoAggregateHelper.average(rows: rows, column: column), 30); - }); - - test('[음수] condition 이 없이 average 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: -10)}), - PlutoRow(cells: {'column': PlutoCell(value: -20)}), - PlutoRow(cells: {'column': PlutoCell(value: -30)}), - PlutoRow(cells: {'column': PlutoCell(value: -40)}), - PlutoRow(cells: {'column': PlutoCell(value: -50)}), - ]; - - expect(PlutoAggregateHelper.average(rows: rows, column: column), -30); - }); - - test('[소수] condition 이 없이 average 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect(PlutoAggregateHelper.average(rows: rows, column: column), 10.003); - }); - }); - - group('min', () { - test('[양수] condition 이 없이 min 을 호출 한 경우 최소 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 101)}), - PlutoRow(cells: {'column': PlutoCell(value: 102)}), - PlutoRow(cells: {'column': PlutoCell(value: 103)}), - PlutoRow(cells: {'column': PlutoCell(value: 104)}), - PlutoRow(cells: {'column': PlutoCell(value: 105)}), - ]; - - expect(PlutoAggregateHelper.min(rows: rows, column: column), 101); - }); - - test('[음수] condition 이 없이 min 을 호출 한 경우 최소 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: -101)}), - PlutoRow(cells: {'column': PlutoCell(value: -102)}), - PlutoRow(cells: {'column': PlutoCell(value: -103)}), - PlutoRow(cells: {'column': PlutoCell(value: -104)}), - PlutoRow(cells: {'column': PlutoCell(value: -105)}), - ]; - - expect(PlutoAggregateHelper.min(rows: rows, column: column), -105); - }); - - test('[소수] condition 이 없이 min 을 호출 한 경우 최소 값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect(PlutoAggregateHelper.min(rows: rows, column: column), 10.001); - }); - - test('condition 이 있는 경우 조건에 맞는 아이템이 있다면 조건내에서 최소값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect( - PlutoAggregateHelper.min( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value >= 10.003, - ), - 10.003, - ); - }); - - test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 null 이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - ]; - - expect( - PlutoAggregateHelper.min( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value == 10.003, - ), - null, - ); - }); - }); - - group('max', () { - test('condition 이 있는 경우 조건에 맞는 아이템이 있다면 조건내에서 최대값이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect( - PlutoAggregateHelper.max( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value >= 10.003, - ), - 10.005, - ); - }); - - test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 null 이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect( - PlutoAggregateHelper.max( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value >= 10.006, - ), - null, - ); - }); - }); - - group('count', () { - test('condition 이 없는 경우 전체 리스트 개수가 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect(PlutoAggregateHelper.count(rows: rows, column: column), 5); - }); - - test('condition 이 있는 경우 조건에 맞는 아이템이 있다면 조건에 맞는 아이템 개수가 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect( - PlutoAggregateHelper.count( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value >= 10.003, - ), - 3, - ); - }); - - test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 0 이 리턴 되어야 한다.', () { - final column = PlutoColumn( - title: 'column', - field: 'column', - type: PlutoColumnType.number(format: '#,###.###'), - ); - - final rows = [ - PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), - PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), - ]; - - expect( - PlutoAggregateHelper.count( - rows: rows, - column: column, - filter: (PlutoCell cell) => cell.value >= 10.006, - ), - 0, - ); - }); - }); -} +import 'package:flutter_test/flutter_test.dart'; +import 'package:pluto_grid_plus/pluto_grid_plus.dart'; + +void main() { + group('sum', () { + test('숫자 컬럼이 아닌경우 0이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.text(), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), + PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), + PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), + PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), + PlutoRow(cells: {'column': PlutoCell(value: '10.001')}), + ]; + + expect(PlutoAggregateHelper.sum(rows: rows, column: column), 0); + }); + + test('[양수] condition 이 없이 sum 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10)}), + PlutoRow(cells: {'column': PlutoCell(value: 20)}), + PlutoRow(cells: {'column': PlutoCell(value: 30)}), + PlutoRow(cells: {'column': PlutoCell(value: 40)}), + PlutoRow(cells: {'column': PlutoCell(value: 50)}), + ]; + + expect(PlutoAggregateHelper.sum(rows: rows, column: column), 150); + }); + + test('[음수] condition 이 없이 sum 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: -10)}), + PlutoRow(cells: {'column': PlutoCell(value: -20)}), + PlutoRow(cells: {'column': PlutoCell(value: -30)}), + PlutoRow(cells: {'column': PlutoCell(value: -40)}), + PlutoRow(cells: {'column': PlutoCell(value: -50)}), + ]; + + expect(PlutoAggregateHelper.sum(rows: rows, column: column), -150); + }); + + test('[소수] condition 이 없이 sum 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + ]; + + expect(PlutoAggregateHelper.sum(rows: rows, column: column), 50.005); + }); + + test('condition 이 있는 경우 조건에 맞는 아이템의 합계 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + ]; + + expect( + PlutoAggregateHelper.sum( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value == 10.001, + ), + 30.003, + ); + }); + + test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 0이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + ]; + + expect( + PlutoAggregateHelper.sum( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value == 10.003, + ), + null, + ); + }); + }); + + group('average', () { + test('[양수] condition 이 없이 average 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10)}), + PlutoRow(cells: {'column': PlutoCell(value: 20)}), + PlutoRow(cells: {'column': PlutoCell(value: 30)}), + PlutoRow(cells: {'column': PlutoCell(value: 40)}), + PlutoRow(cells: {'column': PlutoCell(value: 50)}), + ]; + + expect(PlutoAggregateHelper.average(rows: rows, column: column), 30); + }); + + test('[음수] condition 이 없이 average 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: -10)}), + PlutoRow(cells: {'column': PlutoCell(value: -20)}), + PlutoRow(cells: {'column': PlutoCell(value: -30)}), + PlutoRow(cells: {'column': PlutoCell(value: -40)}), + PlutoRow(cells: {'column': PlutoCell(value: -50)}), + ]; + + expect(PlutoAggregateHelper.average(rows: rows, column: column), -30); + }); + + test('[소수] condition 이 없이 average 을 호출 한 경우 전체 합계 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect(PlutoAggregateHelper.average(rows: rows, column: column), 10.003); + }); + }); + + group('min', () { + test('[양수] condition 이 없이 min 을 호출 한 경우 최소 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 101)}), + PlutoRow(cells: {'column': PlutoCell(value: 102)}), + PlutoRow(cells: {'column': PlutoCell(value: 103)}), + PlutoRow(cells: {'column': PlutoCell(value: 104)}), + PlutoRow(cells: {'column': PlutoCell(value: 105)}), + ]; + + expect(PlutoAggregateHelper.min(rows: rows, column: column), 101); + }); + + test('[음수] condition 이 없이 min 을 호출 한 경우 최소 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: -101)}), + PlutoRow(cells: {'column': PlutoCell(value: -102)}), + PlutoRow(cells: {'column': PlutoCell(value: -103)}), + PlutoRow(cells: {'column': PlutoCell(value: -104)}), + PlutoRow(cells: {'column': PlutoCell(value: -105)}), + ]; + + expect(PlutoAggregateHelper.min(rows: rows, column: column), -105); + }); + + test('[소수] condition 이 없이 min 을 호출 한 경우 최소 값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect(PlutoAggregateHelper.min(rows: rows, column: column), 10.001); + }); + + test('condition 이 있는 경우 조건에 맞는 아이템이 있다면 조건내에서 최소값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect( + PlutoAggregateHelper.min( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value >= 10.003, + ), + 10.003, + ); + }); + + test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 null 이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + ]; + + expect( + PlutoAggregateHelper.min( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value == 10.003, + ), + null, + ); + }); + }); + + group('max', () { + test('condition 이 있는 경우 조건에 맞는 아이템이 있다면 조건내에서 최대값이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect( + PlutoAggregateHelper.max( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value >= 10.003, + ), + 10.005, + ); + }); + + test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 null 이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect( + PlutoAggregateHelper.max( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value >= 10.006, + ), + null, + ); + }); + }); + + group('count', () { + test('condition 이 없는 경우 전체 리스트 개수가 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect(PlutoAggregateHelper.count(rows: rows, column: column), 5); + }); + + test('condition 이 있는 경우 조건에 맞는 아이템이 있다면 조건에 맞는 아이템 개수가 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect( + PlutoAggregateHelper.count( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value >= 10.003, + ), + 3, + ); + }); + + test('condition 이 있는 경우 조건에 맞는 아이템이 없다면 0 이 리턴 되어야 한다.', () { + final column = PlutoColumn( + title: 'column', + field: 'column', + type: PlutoColumnType.number(format: '#,###.###'), + ); + + final rows = [ + PlutoRow(cells: {'column': PlutoCell(value: 10.001)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.002)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.003)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.004)}), + PlutoRow(cells: {'column': PlutoCell(value: 10.005)}), + ]; + + expect( + PlutoAggregateHelper.count( + rows: rows, + column: column, + filter: (PlutoCell cell) => cell.value >= 10.006, + ), + 0, + ); + }); + }); +} From f0005781eb1a4c83af618468723ceb6754cbaafa Mon Sep 17 00:00:00 2001 From: Stan Persoons <147701137+stan-at-work@users.noreply.github.com> Date: Fri, 6 Dec 2024 20:09:34 +0100 Subject: [PATCH 12/22] Added tests on pull_req --- .github/workflows/tests.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/tests.yaml diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 000000000..f72b9453d --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,13 @@ +name: Tests +on: + pull_request: + branches: + - master +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: Install Flutter Dependencies + run: flutter pub get + - name: Run Flutter Tests + run: flutter test From 64f470498fd60c475d5982a2fb456ff0893c510a Mon Sep 17 00:00:00 2001 From: spe Date: Sat, 7 Dec 2024 15:00:54 +0100 Subject: [PATCH 13/22] Add vs-code formatting restrictions --- .vscode/settings.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..8d4d525e8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dart.lineLength": 80, +} \ No newline at end of file From 80764b3b632610a11f8642b44732673eed86ab1b Mon Sep 17 00:00:00 2001 From: spe Date: Sat, 7 Dec 2024 15:37:54 +0100 Subject: [PATCH 14/22] Added empty screen to homepage --- demo/lib/screen/home_screen.dart | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/demo/lib/screen/home_screen.dart b/demo/lib/screen/home_screen.dart index e84c7aada..8daa879fc 100644 --- a/demo/lib/screen/home_screen.dart +++ b/demo/lib/screen/home_screen.dart @@ -1,5 +1,6 @@ import 'dart:math'; +import 'package:demo/screen/empty_screen.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -114,7 +115,8 @@ class HomeScreen extends StatelessWidget { icon: const FaIcon(FontAwesomeIcons.link), color: Colors.white, onPressed: () { - launchUrl('https://pub.dev/packages/pluto_grid_plus'); + launchUrl( + 'https://pub.dev/packages/pluto_grid_plus'); }, ), const Text( @@ -145,7 +147,8 @@ class HomeScreen extends StatelessWidget { icon: const FaIcon(FontAwesomeIcons.github), color: Colors.white, onPressed: () { - launchUrl('https://github.com/doonfrs/pluto_grid_plus'); + launchUrl( + 'https://github.com/doonfrs/pluto_grid_plus'); }, ), const Text( @@ -489,6 +492,14 @@ class PlutoFeatures extends StatelessWidget { Navigator.pushNamed(context, DarkModeScreen.routeName); }, ), + PlutoListTile.amber( + title: 'Empty', + description: + 'This screen is used during development, this is a template to test issues', + onTapLiveDemo: () { + Navigator.pushNamed(context, EmptyScreen.routeName); + }, + ), PlutoListTile.amber( title: 'Development', description: From aec6708e328b1ef69e0b6066dd771a6704114f45 Mon Sep 17 00:00:00 2001 From: spe Date: Sat, 7 Dec 2024 17:52:04 +0100 Subject: [PATCH 15/22] Added clear columns filter event --- demo/lib/main.dart | 1 + ...pluto_grid_clear_columns_filter_event.dart | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 lib/src/manager/event/pluto_grid_clear_columns_filter_event.dart diff --git a/demo/lib/main.dart b/demo/lib/main.dart index 7508fe929..82070b82c 100644 --- a/demo/lib/main.dart +++ b/demo/lib/main.dart @@ -53,6 +53,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( + debugShowCheckedModeBanner: false, initialRoute: kReleaseMode ? HomeScreen.routeName : DevelopmentScreen.routeName, routes: { diff --git a/lib/src/manager/event/pluto_grid_clear_columns_filter_event.dart b/lib/src/manager/event/pluto_grid_clear_columns_filter_event.dart new file mode 100644 index 000000000..c873b7e9f --- /dev/null +++ b/lib/src/manager/event/pluto_grid_clear_columns_filter_event.dart @@ -0,0 +1,24 @@ +import 'package:pluto_grid_plus/pluto_grid_plus.dart'; + +/// Event to clear the provided columns there filter +class PlutoGridClearColumnsFilterEvent extends PlutoGridEvent { + final Iterable? columns; + final int? debounceMilliseconds; + final PlutoGridEventType? eventType; + + PlutoGridClearColumnsFilterEvent({ + this.columns, + this.debounceMilliseconds, + this.eventType, + }) : super( + type: eventType ?? PlutoGridEventType.normal, + duration: Duration( + milliseconds: debounceMilliseconds?.abs() ?? + PlutoGridSettings.debounceMillisecondsForColumnFilter), + ); + + @override + void handler(PlutoGridStateManager stateManager) { + stateManager.setFilterWithFilterRows([]); + } +} From 0191c585740d0492a1ce693cc3989c6283e7145c Mon Sep 17 00:00:00 2001 From: spe Date: Sat, 7 Dec 2024 17:53:05 +0100 Subject: [PATCH 16/22] FIX for https://github.com/doonfrs/pluto_grid_plus/issues/105 --- lib/pluto_grid_plus.dart | 1 + .../event/pluto_grid_change_column_filter_event.dart | 12 +++++------- lib/src/ui/columns/pluto_column_filter.dart | 1 + 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/pluto_grid_plus.dart b/lib/pluto_grid_plus.dart index 04ed11a9f..daa732cd3 100644 --- a/lib/pluto_grid_plus.dart +++ b/lib/pluto_grid_plus.dart @@ -17,6 +17,7 @@ export './src/manager/event/pluto_grid_cannot_move_current_cell_event.dart'; export './src/manager/event/pluto_grid_cell_gesture_event.dart'; export './src/manager/event/pluto_grid_change_column_filter_event.dart'; export './src/manager/event/pluto_grid_change_column_sort_event.dart'; +export './src/manager/event/pluto_grid_clear_columns_filter_event.dart'; export './src/manager/event/pluto_grid_drag_rows_event.dart'; export './src/manager/event/pluto_grid_event.dart'; export './src/manager/event/pluto_grid_scroll_update_event.dart'; diff --git a/lib/src/manager/event/pluto_grid_change_column_filter_event.dart b/lib/src/manager/event/pluto_grid_change_column_filter_event.dart index bc4623d54..432f92b0e 100644 --- a/lib/src/manager/event/pluto_grid_change_column_filter_event.dart +++ b/lib/src/manager/event/pluto_grid_change_column_filter_event.dart @@ -7,21 +7,19 @@ class PlutoGridChangeColumnFilterEvent extends PlutoGridEvent { final PlutoFilterType filterType; final String filterValue; final int? debounceMilliseconds; + final PlutoGridEventType? eventType; PlutoGridChangeColumnFilterEvent({ required this.column, required this.filterType, required this.filterValue, this.debounceMilliseconds, + this.eventType, }) : super( - type: PlutoGridEventType.debounce, + type: eventType ?? PlutoGridEventType.normal, duration: Duration( - milliseconds: debounceMilliseconds == null - ? PlutoGridSettings.debounceMillisecondsForColumnFilter - : debounceMilliseconds < 0 - ? 0 - : debounceMilliseconds, - ), + milliseconds: debounceMilliseconds?.abs() ?? + PlutoGridSettings.debounceMillisecondsForColumnFilter), ); List _getFilterRows(PlutoGridStateManager? stateManager) { diff --git a/lib/src/ui/columns/pluto_column_filter.dart b/lib/src/ui/columns/pluto_column_filter.dart index 19e5b22a9..e669d5152 100644 --- a/lib/src/ui/columns/pluto_column_filter.dart +++ b/lib/src/ui/columns/pluto_column_filter.dart @@ -227,6 +227,7 @@ class PlutoColumnFilterState extends PlutoStateWithChange { column: widget.column, filterType: widget.column.defaultFilter, filterValue: changed, + eventType: PlutoGridEventType.debounce, debounceMilliseconds: stateManager.configuration.columnFilter.debounceMilliseconds, ), From 386a4e6c020d2a8a882db48b5cae17305db2036c Mon Sep 17 00:00:00 2001 From: Yeikel Uriarte Arteaga Date: Tue, 10 Dec 2024 22:05:39 -0500 Subject: [PATCH 17/22] fix: remove change in file unrelated with PR --- .fvm/fvm_config.json | 3 ++- .gitignore | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json index 722fd1f83..b3db758e4 100644 --- a/.fvm/fvm_config.json +++ b/.fvm/fvm_config.json @@ -1,3 +1,4 @@ { - "flutterSdkVersion": "3.24.2" + "flutterSdkVersion": "stable", + "flavors": {} } \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8b7e51baa..92fc76786 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,8 @@ coverage/ !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +# FVM Support - https://fvm.app/ +.fvm/flutter_sdk example/windows/flutter/generated_plugin_registrant.cc example/windows/flutter/generated_plugin_registrant.h example/windows/flutter/generated_plugins.cmake @@ -83,8 +85,3 @@ example/windows/flutter/generated_plugins.cmake example/windows/flutter/generated_plugin_registrant.cc example/windows/flutter/generated_plugin_registrant.h example/windows/flutter/generated_plugins.cmake - -# FVM Support - https://fvm.app/ -.fvm/flutter_sdk -# FVM Version Cache -.fvm/ From b5d2cd70b9fa2cd915caa4317ca02abb8212367a Mon Sep 17 00:00:00 2001 From: Yeikel Uriarte Arteaga Date: Tue, 10 Dec 2024 22:07:25 -0500 Subject: [PATCH 18/22] fix: remove change in file unrelated with PR --- .fvm/fvm_config.json | 2 +- .gitignore | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json index b3db758e4..41959e974 100644 --- a/.fvm/fvm_config.json +++ b/.fvm/fvm_config.json @@ -1,4 +1,4 @@ { "flutterSdkVersion": "stable", "flavors": {} -} \ No newline at end of file +} diff --git a/.gitignore b/.gitignore index 92fc76786..92f3f9a64 100644 --- a/.gitignore +++ b/.gitignore @@ -80,8 +80,4 @@ coverage/ .fvm/flutter_sdk example/windows/flutter/generated_plugin_registrant.cc example/windows/flutter/generated_plugin_registrant.h -example/windows/flutter/generated_plugins.cmake - -example/windows/flutter/generated_plugin_registrant.cc -example/windows/flutter/generated_plugin_registrant.h -example/windows/flutter/generated_plugins.cmake +example/windows/flutter/generated_plugins.cmake \ No newline at end of file From 34aacde0080769b898ea9e4cfb51588c8ec363c9 Mon Sep 17 00:00:00 2001 From: Yeikel Uriarte Arteaga Date: Tue, 10 Dec 2024 22:09:32 -0500 Subject: [PATCH 19/22] fix: remove change in file unrelated with PR --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 92f3f9a64..ac480b7b4 100644 --- a/.gitignore +++ b/.gitignore @@ -79,5 +79,4 @@ coverage/ # FVM Support - https://fvm.app/ .fvm/flutter_sdk example/windows/flutter/generated_plugin_registrant.cc -example/windows/flutter/generated_plugin_registrant.h -example/windows/flutter/generated_plugins.cmake \ No newline at end of file +example/windows/flutter/generated_plugin_registrant.h \ No newline at end of file From 8d4bf347cf51337fd5a7a1b37847d3358193f1b6 Mon Sep 17 00:00:00 2001 From: Yeikel Uriarte Arteaga Date: Tue, 10 Dec 2024 22:12:23 -0500 Subject: [PATCH 20/22] fix: remove change in file unrelated with PR --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ac480b7b4..b28e1b84a 100644 --- a/.gitignore +++ b/.gitignore @@ -79,4 +79,5 @@ coverage/ # FVM Support - https://fvm.app/ .fvm/flutter_sdk example/windows/flutter/generated_plugin_registrant.cc -example/windows/flutter/generated_plugin_registrant.h \ No newline at end of file +example/windows/flutter/generated_plugin_registrant.h +example/windows/flutter/generated_plugins.cmake From f3c055b5bae4d2937a15d3fb0995cc4a27d424c2 Mon Sep 17 00:00:00 2001 From: Yeikel Uriarte Arteaga Date: Wed, 11 Dec 2024 13:10:12 -0500 Subject: [PATCH 21/22] fix: rename new method to avoid confusion --- lib/src/model/pluto_column.dart | 4 ++-- lib/src/ui/cells/pluto_default_cell.dart | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/model/pluto_column.dart b/lib/src/model/pluto_column.dart index b0e382ec3..d0cadebc6 100644 --- a/lib/src/model/pluto_column.dart +++ b/lib/src/model/pluto_column.dart @@ -152,7 +152,7 @@ class PlutoColumn { bool enableTitleChecked; - bool Function(PlutoRow row)? disableRowCheckWhen; + bool Function(PlutoRow row)? disableRowCheckboxWhen; /// Sort rows by tapping on the column heading. bool enableSorting; @@ -262,7 +262,7 @@ class PlutoColumn { this.enableAutoEditing = false, this.enableEditingMode = true, this.hide = false, - this.disableRowCheckWhen, + this.disableRowCheckboxWhen, }) : _key = UniqueKey(), _checkReadOnly = checkReadOnly; diff --git a/lib/src/ui/cells/pluto_default_cell.dart b/lib/src/ui/cells/pluto_default_cell.dart index a5d7a4b67..1d584edde 100644 --- a/lib/src/ui/cells/pluto_default_cell.dart +++ b/lib/src/ui/cells/pluto_default_cell.dart @@ -101,7 +101,7 @@ class _PlutoDefaultCellState extends PlutoStateWithChange { @override void updateState(PlutoNotifierEvent event) { final disable = - widget.column.disableRowCheckWhen?.call(widget.row) ?? false; + widget.column.disableRowCheckboxWhen?.call(widget.row) ?? false; if (disable) return; _hasFocus = update( @@ -373,7 +373,7 @@ class CheckboxSelectionWidgetState @override void updateState(PlutoNotifierEvent event) { final disable = - widget.column.disableRowCheckWhen?.call(widget.row) ?? false; + widget.column.disableRowCheckboxWhen?.call(widget.row) ?? false; if (disable) { _checked = _pureValue; return; @@ -423,7 +423,7 @@ class CheckboxSelectionWidgetState @override Widget build(BuildContext context) { final disable = - widget.column.disableRowCheckWhen?.call(widget.row) ?? false; + widget.column.disableRowCheckboxWhen?.call(widget.row) ?? false; return PlutoScaledCheckbox( value: _checked, From 9f207328d599a5ba22e3e6e111b272256e58ab4c Mon Sep 17 00:00:00 2001 From: "ciocca@gmail.com" Date: Thu, 12 Dec 2024 22:31:37 -0300 Subject: [PATCH 22/22] Add optional width to column in PlutoColumnType.select --- lib/src/model/pluto_column_type.dart | 9 +++++++-- lib/src/ui/cells/pluto_select_cell.dart | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/src/model/pluto_column_type.dart b/lib/src/model/pluto_column_type.dart index 68256a852..01cb713cf 100644 --- a/lib/src/model/pluto_column_type.dart +++ b/lib/src/model/pluto_column_type.dart @@ -99,6 +99,7 @@ abstract class PlutoColumnType { bool enableColumnFilter = false, IconData? popupIcon = Icons.arrow_drop_down, Widget Function(dynamic item)? builder, + double? width, }) { return PlutoColumnTypeSelect( onItemSelected: onItemSelected ?? (event) {}, @@ -106,7 +107,8 @@ abstract class PlutoColumnType { items: items, enableColumnFilter: enableColumnFilter, popupIcon: popupIcon, - builder: builder); + builder: builder, + width: width); } /// Set as a date column. @@ -367,6 +369,8 @@ class PlutoColumnTypeSelect final bool enableColumnFilter; final Function(PlutoGridOnSelectedEvent event) onItemSelected; + final double? width; + @override final IconData? popupIcon; @@ -376,7 +380,8 @@ class PlutoColumnTypeSelect required this.items, required this.enableColumnFilter, this.popupIcon, - this.builder}); + this.builder, + this.width}); @override bool isValid(dynamic value) => items.contains(value) == true; diff --git a/lib/src/ui/cells/pluto_select_cell.dart b/lib/src/ui/cells/pluto_select_cell.dart index c31e454ac..f96f649a7 100644 --- a/lib/src/ui/cells/pluto_select_cell.dart +++ b/lib/src/ui/cells/pluto_select_cell.dart @@ -64,6 +64,7 @@ class PlutoSelectCellState extends State popupColumns = [ PlutoColumn( + width: widget.column.type.select.width ?? PlutoGridSettings.columnWidth, title: widget.column.title, field: widget.column.title, readOnly: true,