Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/src/manager/pluto_change_notifier_filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ abstract class PlutoChangeNotifierFilterResolver {

/// grid_state
stateManager.resetCurrentState.hashCode: 'resetCurrentState',
stateManager.setConfiguration.hashCode: 'setConfiguration',

/// layout_state
stateManager.setShowColumnTitle.hashCode: 'setShowColumnTitle',
Expand All @@ -115,6 +116,7 @@ abstract class PlutoChangeNotifierFilterResolver {
stateManager.setShowLoading.hashCode: 'setShowLoading',
stateManager.notifyChangedShowFrozenColumn.hashCode:
'notifyChangedShowFrozenColumn',
stateManager.setTextDirection.hashCode: 'setTextDirection',

/// pagination_state
stateManager.setPageSize.hashCode: 'setPageSize',
Expand Down
4 changes: 4 additions & 0 deletions lib/src/manager/state/grid_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ abstract class IGridState {
PlutoGridConfiguration configuration, {
bool updateLocale = true,
bool applyColumnFilter = true,
bool notify = true,
});

void setGridMode(PlutoGridMode mode);
Expand Down Expand Up @@ -134,6 +135,7 @@ mixin GridState implements IPlutoGridState {
PlutoGridConfiguration configuration, {
bool updateLocale = true,
bool applyColumnFilter = true,
bool notify = true,
}) {
if (_state._configuration == configuration) return;

Expand All @@ -146,6 +148,8 @@ mixin GridState implements IPlutoGridState {
if (applyColumnFilter) {
_state._configuration!.applyColumnFilter(refColumns.originalList);
}

notifyListeners(notify);
}

@override
Expand Down
14 changes: 12 additions & 2 deletions lib/src/manager/state/layout_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ abstract class ILayoutState {

void notifyChangedShowFrozenColumn();

void setTextDirection(TextDirection textDirection);
void setTextDirection(TextDirection textDirection, {bool notify = true});

@visibleForTesting
void setGridGlobalOffset(Offset offset);
Expand Down Expand Up @@ -503,8 +503,18 @@ mixin LayoutState implements IPlutoGridState {
}

@override
void setTextDirection(TextDirection textDirection) {
void setTextDirection(TextDirection textDirection, {bool notify = true}) {
if (_state._textDirection == textDirection) return;

_state._textDirection = textDirection;

// setTextDirection is invoked from PlutoGridLayoutDelegate's constructor,
// which is created while PlutoGrid itself is building (inside
// LayoutBuilder). Notifying synchronously at that point would ask
// dependent widgets to rebuild while the widget tree above them is still
// being built, which Flutter disallows. Defer to the next frame instead,
// matching the pattern already used by setKeepFocus.
notifyListenersOnPostFrame(notify);
}

@override
Expand Down
9 changes: 8 additions & 1 deletion test/mock/shared_mocks.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2427,6 +2427,7 @@ class MockPlutoGridStateManager extends _i1.Mock
_i2.PlutoGridConfiguration? configuration, {
bool? updateLocale = true,
bool? applyColumnFilter = true,
bool? notify = true,
}) =>
super.noSuchMethod(
Invocation.method(
Expand All @@ -2435,6 +2436,7 @@ class MockPlutoGridStateManager extends _i1.Mock
{
#updateLocale: updateLocale,
#applyColumnFilter: applyColumnFilter,
#notify: notify,
},
),
returnValueForMissingStub: null,
Expand Down Expand Up @@ -2774,10 +2776,15 @@ class MockPlutoGridStateManager extends _i1.Mock
);

@override
void setTextDirection(_i5.TextDirection? textDirection) => super.noSuchMethod(
void setTextDirection(
_i5.TextDirection? textDirection, {
bool? notify = true,
}) =>
super.noSuchMethod(
Invocation.method(
#setTextDirection,
[textDirection],
{#notify: notify},
),
returnValueForMissingStub: null,
);
Expand Down
119 changes: 119 additions & 0 deletions test/src/manager/state/grid_state_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:pluto_grid/pluto_grid.dart';

import '../../../helper/column_helper.dart';
import '../../../helper/row_helper.dart';
import '../../../mock/mock_methods.dart';
import '../../../mock/shared_mocks.mocks.dart';

void main() {
PlutoGridStateManager createStateManager({
required List<PlutoColumn> columns,
required List<PlutoRow> rows,
FocusNode? gridFocusNode,
PlutoGridScrollController? scroll,
PlutoGridConfiguration configuration = const PlutoGridConfiguration(),
}) {
final stateManager = PlutoGridStateManager(
columns: columns,
rows: rows,
gridFocusNode: gridFocusNode ?? MockFocusNode(),
scroll: scroll ?? MockPlutoGridScrollController(),
configuration: configuration,
);

stateManager.setEventManager(MockPlutoGridEventManager());

return stateManager;
}

group('setConfiguration', () {
testWidgets(
'When the configuration is changed, listeners should be notified.',
(WidgetTester tester) async {
// given
List<PlutoColumn> columns = ColumnHelper.textColumn('body', count: 3);
List<PlutoRow> rows = RowHelper.count(3, columns);

PlutoGridStateManager stateManager = createStateManager(
columns: columns,
rows: rows,
);

final listener = MockMethods();

stateManager.addListener(listener.noParamReturnVoid);

// when
stateManager.setConfiguration(
const PlutoGridConfiguration(
style: PlutoGridStyleConfig(enableGridBorderShadow: true),
),
);

// then
verify(listener.noParamReturnVoid()).called(1);
},
);

testWidgets(
'When the configuration is set to an equal value, '
'listeners should not be notified.',
(WidgetTester tester) async {
// given
List<PlutoColumn> columns = ColumnHelper.textColumn('body', count: 3);
List<PlutoRow> rows = RowHelper.count(3, columns);

const configuration = PlutoGridConfiguration();

PlutoGridStateManager stateManager = createStateManager(
columns: columns,
rows: rows,
configuration: configuration,
);

final listener = MockMethods();

stateManager.addListener(listener.noParamReturnVoid);

// when
stateManager.setConfiguration(configuration);

// then
verifyNever(listener.noParamReturnVoid());
},
);

testWidgets(
'When notify is false, listeners should not be notified '
'even though the configuration changed.',
(WidgetTester tester) async {
// given
List<PlutoColumn> columns = ColumnHelper.textColumn('body', count: 3);
List<PlutoRow> rows = RowHelper.count(3, columns);

PlutoGridStateManager stateManager = createStateManager(
columns: columns,
rows: rows,
);

final listener = MockMethods();

stateManager.addListener(listener.noParamReturnVoid);

// when
stateManager.setConfiguration(
const PlutoGridConfiguration(
style: PlutoGridStyleConfig(enableGridBorderShadow: true),
),
notify: false,
);

// then
verifyNever(listener.noParamReturnVoid());
},
);
});
}
87 changes: 87 additions & 0 deletions test/src/manager/state/layout_state_test.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:pluto_grid/pluto_grid.dart';

import '../../../helper/column_helper.dart';
import '../../../helper/pluto_widget_test_helper.dart';
import '../../../helper/row_helper.dart';
import '../../../mock/mock_methods.dart';
import '../../../mock/shared_mocks.mocks.dart';

void main() {
Expand Down Expand Up @@ -158,4 +160,89 @@ void main() {
},
);
});

group('setTextDirection', () {
late PlutoGridStateManager stateManager;

setUp(() {
List<PlutoColumn> columns = ColumnHelper.textColumn('body', count: 3);
List<PlutoRow> rows = RowHelper.count(3, columns);

stateManager = PlutoGridStateManager(
columns: columns,
rows: rows,
gridFocusNode: MockFocusNode(),
scroll: MockPlutoGridScrollController(),
);

stateManager.setEventManager(MockPlutoGridEventManager());
});

testWidgets(
'When the text direction is changed, '
'listeners should be notified on the next frame.',
(WidgetTester tester) async {
// given
expect(stateManager.isLTR, isTrue);

final listener = MockMethods();

stateManager.addListener(listener.noParamReturnVoid);

// when
stateManager.setTextDirection(TextDirection.rtl);

// notifyListenersOnPostFrame defers the notification, so listeners
// must not have been called synchronously yet.
verifyNever(listener.noParamReturnVoid());

await tester.pump();

// then
expect(stateManager.isRTL, isTrue);
verify(listener.noParamReturnVoid()).called(1);
},
);

testWidgets(
'When the text direction is set to the same value, '
'listeners should not be notified.',
(WidgetTester tester) async {
// given
expect(stateManager.isLTR, isTrue);

final listener = MockMethods();

stateManager.addListener(listener.noParamReturnVoid);

// when
stateManager.setTextDirection(TextDirection.ltr);

await tester.pump();

// then
verifyNever(listener.noParamReturnVoid());
},
);

testWidgets(
'When notify is false, listeners should not be notified '
'even though the text direction changed.',
(WidgetTester tester) async {
// given
final listener = MockMethods();

stateManager.addListener(listener.noParamReturnVoid);

// when
stateManager.setTextDirection(TextDirection.rtl, notify: false);

await tester.pump();

// then
expect(stateManager.isRTL, isTrue);
verifyNever(listener.noParamReturnVoid());
},
);
});
}