Skip to content

Commit fb1eeff

Browse files
authored
[two_dimensional_scrollables] Adds generics to the callbacks and builders of TreeView (#6864)
This PR adds generics to the callbacks and builders of the TreeView widget. This removes the need to type cast the content of a TreeViewNode. Fixes flutter/flutter#149656
1 parent 6a01138 commit fb1eeff

File tree

9 files changed

+66
-37
lines changed

9 files changed

+66
-37
lines changed

packages/two_dimensional_scrollables/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.1
2+
3+
* Adds generics to the callbacks and builders of TreeView.
4+
15
## 0.3.0
26

37
* Adds new TreeView widget and associated classes.

packages/two_dimensional_scrollables/example/lib/tree_view/custom_tree.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class CustomTreeExampleState extends State<CustomTreeExample> {
105105

106106
Widget _treeNodeBuilder(
107107
BuildContext context,
108-
TreeViewNode<Object?> node,
108+
TreeViewNode<String> node,
109109
AnimationStyle toggleAnimationStyle,
110110
) {
111111
final bool isParentNode = node.children.isNotEmpty;
@@ -144,7 +144,7 @@ class CustomTreeExampleState extends State<CustomTreeExample> {
144144
// Spacer
145145
const SizedBox(width: 8.0),
146146
// Content
147-
Text(node.content.toString()),
147+
Text(node.content),
148148
],
149149
);
150150
}
@@ -188,14 +188,14 @@ class CustomTreeExampleState extends State<CustomTreeExample> {
188188
controller: _horizontalController,
189189
),
190190
tree: _tree,
191-
onNodeToggle: (TreeViewNode<Object?> node) {
191+
onNodeToggle: (TreeViewNode<String> node) {
192192
setState(() {
193-
_selectedNode = node as TreeViewNode<String>;
193+
_selectedNode = node;
194194
});
195195
},
196196
treeNodeBuilder: _treeNodeBuilder,
197-
treeRowBuilder: (TreeViewNode<Object?> node) {
198-
if (_selectedNode == (node as TreeViewNode<String>)) {
197+
treeRowBuilder: (TreeViewNode<String> node) {
198+
if (_selectedNode == node) {
199199
return TreeRow(
200200
extent: FixedTreeRowExtent(
201201
node.children.isNotEmpty ? 60.0 : 50.0,

packages/two_dimensional_scrollables/example/lib/tree_view/simple_tree.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ class TreeExampleState extends State<TreeExample> {
100100
controller: horizontalController,
101101
),
102102
tree: _tree,
103-
onNodeToggle: (TreeViewNode<Object?> node) {
103+
onNodeToggle: (TreeViewNode<String> node) {
104104
setState(() {
105-
_selectedNode = node as TreeViewNode<String>;
105+
_selectedNode = node;
106106
});
107107
},
108-
treeRowBuilder: (TreeViewNode<Object?> node) {
109-
if (_selectedNode == (node as TreeViewNode<String>)) {
108+
treeRowBuilder: (TreeViewNode<String> node) {
109+
if (_selectedNode == node) {
110110
return TreeView.defaultTreeRowBuilder(node).copyWith(
111111
recognizerFactories: _getTapRecognizer(node),
112112
backgroundDecoration: TreeRowDecoration(

packages/two_dimensional_scrollables/lib/src/tree_view/tree.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,14 +338,14 @@ class TreeView<T> extends StatefulWidget {
338338
///
339339
/// By default, if this is unset, the [TreeView.defaultTreeNodeBuilder] is
340340
/// used.
341-
final TreeViewNodeBuilder treeNodeBuilder;
341+
final TreeViewNodeBuilder<T> treeNodeBuilder;
342342

343343
/// Builds the [TreeRow] that describes the row for the provided
344344
/// [TreeViewNode].
345345
///
346346
/// By default, if this is unset, the [TreeView.defaultTreeRowBuilder]
347347
/// is used.
348-
final TreeViewRowBuilder treeRowBuilder;
348+
final TreeViewRowBuilder<T> treeRowBuilder;
349349

350350
/// If provided, the controller can be used to expand and collapse
351351
/// [TreeViewNode]s, or lookup information about the current state of the
@@ -360,7 +360,7 @@ class TreeView<T> extends StatefulWidget {
360360
/// a result of being toggled.
361361
///
362362
/// This will not be called if a [TreeViewNode] does not have any children.
363-
final TreeViewNodeCallback? onNodeToggle;
363+
final TreeViewNodeCallback<T>? onNodeToggle;
364364

365365
/// The default [AnimationStyle] for expanding and collapsing nodes in the
366366
/// [TreeView].

packages/two_dimensional_scrollables/lib/src/tree_view/tree_core.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import 'tree.dart';
2121
///
2222
/// * [TreeViewNode.toggleNode], for controlling node expansion
2323
/// programmatically.
24-
typedef TreeViewNodeCallback = void Function(TreeViewNode<Object?> node);
24+
typedef TreeViewNodeCallback<T> = void Function(TreeViewNode<T> node);
2525

2626
/// A mixin for classes implementing a tree structure as expected by a
2727
/// [TreeViewController].

packages/two_dimensional_scrollables/lib/src/tree_view/tree_delegate.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ import 'tree_span.dart';
1212
///
1313
/// Used by the [TreeViewDelegateMixin.buildRow] to configure rows in the
1414
/// [TreeView].
15-
typedef TreeViewRowBuilder = TreeRow Function(TreeViewNode<Object?> node);
15+
typedef TreeViewRowBuilder<T> = TreeRow Function(TreeViewNode<T> node);
1616

1717
/// Signature for a function that creates a [Widget] to represent the given
1818
/// [TreeViewNode] in the [TreeView].
1919
///
2020
/// Used by [TreeView.treeRowBuilder] to build rows on demand for the
2121
/// tree.
22-
typedef TreeViewNodeBuilder = Widget Function(
22+
typedef TreeViewNodeBuilder<T> = Widget Function(
2323
BuildContext context,
24-
TreeViewNode<Object?> node,
24+
TreeViewNode<T> node,
2525
AnimationStyle toggleAnimationStyle,
2626
);
2727

packages/two_dimensional_scrollables/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: two_dimensional_scrollables
22
description: Widgets that scroll using the two dimensional scrolling foundation.
3-
version: 0.3.0
3+
version: 0.3.1
44
repository: https://github.com/flutter/packages/tree/main/packages/two_dimensional_scrollables
55
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+two_dimensional_scrollables%22+
66

packages/two_dimensional_scrollables/test/tree_view/render_tree_test.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ void main() {
141141
final List<String> log = <String>[];
142142
final TreeView<String> treeView = TreeView<String>(
143143
tree: treeNodes,
144-
treeRowBuilder: (TreeViewNode<Object?> node) {
144+
treeRowBuilder: (TreeViewNode<String> node) {
145145
if (node.depth! == 0) {
146146
return getTappableRow(
147-
node as TreeViewNode<String>,
147+
node,
148148
() {
149149
log.add(node.content);
150150
tapCounter++;
@@ -174,7 +174,7 @@ void main() {
174174
int exitCounter = 0;
175175
final TreeView<String> treeView = TreeView<String>(
176176
tree: treeNodes,
177-
treeRowBuilder: (TreeViewNode<Object?> node) {
177+
treeRowBuilder: (TreeViewNode<String> node) {
178178
if (node.depth! == 0) {
179179
return getMouseTrackingRow(
180180
onEnter: (_) => enterCounter++,
@@ -397,7 +397,7 @@ void main() {
397397

398398
treeView = TreeView<String>(
399399
tree: treeNodes,
400-
treeRowBuilder: (TreeViewNode<Object?> node) {
400+
treeRowBuilder: (TreeViewNode<String> node) {
401401
if (node.depth! == 1) {
402402
// extent == 100
403403
return row;
@@ -766,7 +766,7 @@ void main() {
766766
controller: horizontalController,
767767
),
768768
tree: treeNodes,
769-
treeRowBuilder: (TreeViewNode<Object?> node) {
769+
treeRowBuilder: (TreeViewNode<String> node) {
770770
return row.copyWith(
771771
backgroundDecoration: node.depth! == 0
772772
? rootBackgroundDecoration

packages/two_dimensional_scrollables/test/tree_view/tree_test.dart

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ void main() {
130130
controller: controller,
131131
treeNodeBuilder: (
132132
BuildContext context,
133-
TreeViewNode<Object?> node,
133+
TreeViewNode<String> node,
134134
AnimationStyle toggleAnimationStyle,
135135
) {
136136
returnedController ??= TreeViewController.of(context);
@@ -153,7 +153,7 @@ void main() {
153153
tree: simpleNodeSet,
154154
treeNodeBuilder: (
155155
BuildContext context,
156-
TreeViewNode<Object?> node,
156+
TreeViewNode<String> node,
157157
AnimationStyle toggleAnimationStyle,
158158
) {
159159
returnedController ??= TreeViewController.maybeOf(context);
@@ -454,9 +454,9 @@ void main() {
454454
home: TreeView<String>(
455455
tree: simpleNodeSet,
456456
controller: controller,
457-
onNodeToggle: (TreeViewNode<Object?> node) {
457+
onNodeToggle: (TreeViewNode<String> node) {
458458
toggled = true;
459-
toggledNode = node as TreeViewNode<String>;
459+
toggledNode = node;
460460
},
461461
),
462462
));
@@ -476,13 +476,13 @@ void main() {
476476
home: TreeView<String>(
477477
tree: simpleNodeSet,
478478
controller: controller,
479-
onNodeToggle: (TreeViewNode<Object?> node) {
479+
onNodeToggle: (TreeViewNode<String> node) {
480480
toggled = true;
481-
toggledNode = node as TreeViewNode<String>;
481+
toggledNode = node;
482482
},
483483
treeNodeBuilder: (
484484
BuildContext context,
485-
TreeViewNode<Object?> node,
485+
TreeViewNode<String> node,
486486
AnimationStyle toggleAnimationStyle,
487487
) {
488488
final Duration animationDuration = toggleAnimationStyle.duration ??
@@ -510,7 +510,7 @@ void main() {
510510
// Spacer
511511
const SizedBox(width: 8.0),
512512
// Content
513-
Text(node.content.toString()),
513+
Text(node.content),
514514
]),
515515
),
516516
);
@@ -535,11 +535,11 @@ void main() {
535535
tree: simpleNodeSet,
536536
treeNodeBuilder: (
537537
BuildContext context,
538-
TreeViewNode<Object?> node,
538+
TreeViewNode<String> node,
539539
AnimationStyle toggleAnimationStyle,
540540
) {
541541
style ??= toggleAnimationStyle;
542-
return Text(node.content.toString());
542+
return Text(node.content);
543543
},
544544
),
545545
));
@@ -558,11 +558,11 @@ void main() {
558558
toggleAnimationStyle: AnimationStyle.noAnimation,
559559
treeNodeBuilder: (
560560
BuildContext context,
561-
TreeViewNode<Object?> node,
561+
TreeViewNode<String> node,
562562
AnimationStyle toggleAnimationStyle,
563563
) {
564564
style = toggleAnimationStyle;
565-
return Text(node.content.toString());
565+
return Text(node.content);
566566
},
567567
),
568568
));
@@ -580,11 +580,11 @@ void main() {
580580
),
581581
treeNodeBuilder: (
582582
BuildContext context,
583-
TreeViewNode<Object?> node,
583+
TreeViewNode<String> node,
584584
AnimationStyle toggleAnimationStyle,
585585
) {
586586
style ??= toggleAnimationStyle;
587-
return Text(node.content.toString());
587+
return Text(node.content);
588588
},
589589
),
590590
));
@@ -693,6 +693,31 @@ void main() {
693693
expect(find.text('Child 2:1'), findsNothing);
694694
expect(find.text('Root 3'), findsOneWidget);
695695
});
696+
697+
test('should use the generic type for callbacks and builders', () {
698+
final TreeView<String> treeView = TreeView<String>(
699+
tree: simpleNodeSet,
700+
treeNodeBuilder: (
701+
BuildContext context,
702+
TreeViewNode<String> node,
703+
AnimationStyle animationStyle,
704+
) {
705+
return TreeView.defaultTreeNodeBuilder(
706+
context,
707+
node,
708+
animationStyle,
709+
);
710+
},
711+
treeRowBuilder: (TreeViewNode<String> node) {
712+
return TreeView.defaultTreeRowBuilder(node);
713+
},
714+
onNodeToggle: (TreeViewNode<String> node) {},
715+
);
716+
717+
expect(treeView.onNodeToggle, isA<TreeViewNodeCallback<String>>());
718+
expect(treeView.treeNodeBuilder, isA<TreeViewNodeBuilder<String>>());
719+
expect(treeView.treeRowBuilder, isA<TreeViewRowBuilder<String>>());
720+
});
696721
});
697722

698723
group('TreeViewport', () {

0 commit comments

Comments
 (0)