From 34aacbf87ed94e620f3d08ceb3e350b97ea1f7a5 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 8 Jul 2022 23:25:48 +0200 Subject: [PATCH] SplitViewController: add weights setter and notify changes Fixes: #16 --- lib/split_view.dart | 58 ++++++++++++++++++++++++++++++++------- pubspec.yaml | 1 + test/split_view_test.dart | 39 ++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 16 deletions(-) diff --git a/lib/split_view.dart b/lib/split_view.dart index d86f723..d343258 100644 --- a/lib/split_view.dart +++ b/lib/split_view.dart @@ -3,6 +3,7 @@ library split_view; import 'dart:collection'; import 'dart:math'; +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; @@ -74,8 +75,38 @@ class _SplitViewState extends State { void initState() { super.initState(); - _controller = - widget.controller != null ? widget.controller! : SplitViewController(); + _controller = widget.controller ?? SplitViewController(); + _controller.addListener(_handleWeightsChange); + } + + @override + void dispose() { + _controller.removeListener(_handleWeightsChange); + if (widget.controller == null) { + _controller.dispose(); + } + + super.dispose(); + } + + @override + void didUpdateWidget(SplitView oldWidget) { + super.didUpdateWidget(oldWidget); + + if (widget.controller != oldWidget.controller) { + oldWidget.controller?.removeListener(_handleWeightsChange); + widget.controller?.addListener(_handleWeightsChange); + + if (oldWidget.controller != null && widget.controller == null) { + _controller = SplitViewController( + weights: _controller.weights, + limits: _controller.limits, + ); + } else if (widget.controller != null && oldWidget.controller == null) { + _controller.dispose(); + _controller = widget.controller!; + } + } } @override @@ -284,14 +315,16 @@ class _SplitViewState extends State { } newWeight1 = _startWeight1 + _startWeight2 - newWeight2; } - setState(() { - _controller._weights[index] = newWeight1; - _controller._weights[index + 1] = newWeight2; - }); - if (widget.onWeightChanged != null) { - widget.onWeightChanged!(_controller.weights); - } + final weights = List.of(_controller._weights); + weights[index] = newWeight1; + weights[index + 1] = newWeight2; + _controller.weights = weights; + } + + void _handleWeightsChange() { + setState(() {/* build() uses _controller.weights */}); + widget.onWeightChanged?.call(_controller.weights); } Offset _getLocalPosition(BuildContext context, Offset pos) { @@ -307,9 +340,14 @@ class _SplitViewState extends State { } /// Controller for [Splitview] -class SplitViewController { +class SplitViewController extends ChangeNotifier { /// Specifies the weight of each views. UnmodifiableListView get weights => UnmodifiableListView(_weights); + set weights(List weights) { + if (const ListEquality().equals(_weights, weights)) return; + _weights = weights; + notifyListeners(); + } /// Specifies the limits of each views. UnmodifiableListView get limits => diff --git a/pubspec.yaml b/pubspec.yaml index 4e5b7b6..174dcc2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,6 +7,7 @@ environment: sdk: '>=2.12.0 <3.0.0' dependencies: + collection: ^1.16.0 flutter: sdk: flutter diff --git a/test/split_view_test.dart b/test/split_view_test.dart index a2adc0f..48055db 100644 --- a/test/split_view_test.dart +++ b/test/split_view_test.dart @@ -1,11 +1,38 @@ +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:split_view/split_view.dart'; void main() { - test('adds one to input values', () { -// final calculator = Calculator(); -// expect(calculator.addOne(2), 3); -// expect(calculator.addOne(-7), -6); -// expect(calculator.addOne(0), 1); -// expect(() => calculator.addOne(null), throwsNoSuchMethodError); + testWidgets('controller', (tester) async { + final controller = SplitViewController(weights: [0.1, 0.3, 0.6]); + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: SplitView( + gripSize: 10, + controller: controller, + viewMode: SplitViewMode.Horizontal, + children: [ + Container(key: ValueKey(0)), + Container(key: ValueKey(1)), + Container(key: ValueKey(2)), + ], + ), + ), + ), + ); + + final totalWidth = tester.getSize(find.byType(SplitView)).width - 2 * 10; + + expect(tester.getSize(find.byKey(ValueKey(0))).width, totalWidth * 0.1); + expect(tester.getSize(find.byKey(ValueKey(1))).width, totalWidth * 0.3); + expect(tester.getSize(find.byKey(ValueKey(2))).width, totalWidth * 0.6); + + controller.weights = [0.1, 0.4, 0.5]; + await tester.pump(); + + expect(tester.getSize(find.byKey(ValueKey(0))).width, totalWidth * 0.1); + expect(tester.getSize(find.byKey(ValueKey(1))).width, totalWidth * 0.4); + expect(tester.getSize(find.byKey(ValueKey(2))).width, totalWidth * 0.5); }); }