Skip to content

Commit

Permalink
[two_dimensional_scrollables] Adds generics to the callbacks and buil…
Browse files Browse the repository at this point in the history
…ders of TreeView (flutter#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
  • Loading branch information
baumths authored Jun 6, 2024
1 parent 6a01138 commit fb1eeff
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 37 deletions.
4 changes: 4 additions & 0 deletions packages/two_dimensional_scrollables/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.3.1

* Adds generics to the callbacks and builders of TreeView.

## 0.3.0

* Adds new TreeView widget and associated classes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class CustomTreeExampleState extends State<CustomTreeExample> {

Widget _treeNodeBuilder(
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<String> node,
AnimationStyle toggleAnimationStyle,
) {
final bool isParentNode = node.children.isNotEmpty;
Expand Down Expand Up @@ -144,7 +144,7 @@ class CustomTreeExampleState extends State<CustomTreeExample> {
// Spacer
const SizedBox(width: 8.0),
// Content
Text(node.content.toString()),
Text(node.content),
],
);
}
Expand Down Expand Up @@ -188,14 +188,14 @@ class CustomTreeExampleState extends State<CustomTreeExample> {
controller: _horizontalController,
),
tree: _tree,
onNodeToggle: (TreeViewNode<Object?> node) {
onNodeToggle: (TreeViewNode<String> node) {
setState(() {
_selectedNode = node as TreeViewNode<String>;
_selectedNode = node;
});
},
treeNodeBuilder: _treeNodeBuilder,
treeRowBuilder: (TreeViewNode<Object?> node) {
if (_selectedNode == (node as TreeViewNode<String>)) {
treeRowBuilder: (TreeViewNode<String> node) {
if (_selectedNode == node) {
return TreeRow(
extent: FixedTreeRowExtent(
node.children.isNotEmpty ? 60.0 : 50.0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,13 @@ class TreeExampleState extends State<TreeExample> {
controller: horizontalController,
),
tree: _tree,
onNodeToggle: (TreeViewNode<Object?> node) {
onNodeToggle: (TreeViewNode<String> node) {
setState(() {
_selectedNode = node as TreeViewNode<String>;
_selectedNode = node;
});
},
treeRowBuilder: (TreeViewNode<Object?> node) {
if (_selectedNode == (node as TreeViewNode<String>)) {
treeRowBuilder: (TreeViewNode<String> node) {
if (_selectedNode == node) {
return TreeView.defaultTreeRowBuilder(node).copyWith(
recognizerFactories: _getTapRecognizer(node),
backgroundDecoration: TreeRowDecoration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,14 +338,14 @@ class TreeView<T> extends StatefulWidget {
///
/// By default, if this is unset, the [TreeView.defaultTreeNodeBuilder] is
/// used.
final TreeViewNodeBuilder treeNodeBuilder;
final TreeViewNodeBuilder<T> treeNodeBuilder;

/// Builds the [TreeRow] that describes the row for the provided
/// [TreeViewNode].
///
/// By default, if this is unset, the [TreeView.defaultTreeRowBuilder]
/// is used.
final TreeViewRowBuilder treeRowBuilder;
final TreeViewRowBuilder<T> treeRowBuilder;

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

/// The default [AnimationStyle] for expanding and collapsing nodes in the
/// [TreeView].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import 'tree.dart';
///
/// * [TreeViewNode.toggleNode], for controlling node expansion
/// programmatically.
typedef TreeViewNodeCallback = void Function(TreeViewNode<Object?> node);
typedef TreeViewNodeCallback<T> = void Function(TreeViewNode<T> node);

/// A mixin for classes implementing a tree structure as expected by a
/// [TreeViewController].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import 'tree_span.dart';
///
/// Used by the [TreeViewDelegateMixin.buildRow] to configure rows in the
/// [TreeView].
typedef TreeViewRowBuilder = TreeRow Function(TreeViewNode<Object?> node);
typedef TreeViewRowBuilder<T> = TreeRow Function(TreeViewNode<T> node);

/// Signature for a function that creates a [Widget] to represent the given
/// [TreeViewNode] in the [TreeView].
///
/// Used by [TreeView.treeRowBuilder] to build rows on demand for the
/// tree.
typedef TreeViewNodeBuilder = Widget Function(
typedef TreeViewNodeBuilder<T> = Widget Function(
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<T> node,
AnimationStyle toggleAnimationStyle,
);

Expand Down
2 changes: 1 addition & 1 deletion packages/two_dimensional_scrollables/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: two_dimensional_scrollables
description: Widgets that scroll using the two dimensional scrolling foundation.
version: 0.3.0
version: 0.3.1
repository: https://github.com/flutter/packages/tree/main/packages/two_dimensional_scrollables
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+two_dimensional_scrollables%22+

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,10 @@ void main() {
final List<String> log = <String>[];
final TreeView<String> treeView = TreeView<String>(
tree: treeNodes,
treeRowBuilder: (TreeViewNode<Object?> node) {
treeRowBuilder: (TreeViewNode<String> node) {
if (node.depth! == 0) {
return getTappableRow(
node as TreeViewNode<String>,
node,
() {
log.add(node.content);
tapCounter++;
Expand Down Expand Up @@ -174,7 +174,7 @@ void main() {
int exitCounter = 0;
final TreeView<String> treeView = TreeView<String>(
tree: treeNodes,
treeRowBuilder: (TreeViewNode<Object?> node) {
treeRowBuilder: (TreeViewNode<String> node) {
if (node.depth! == 0) {
return getMouseTrackingRow(
onEnter: (_) => enterCounter++,
Expand Down Expand Up @@ -397,7 +397,7 @@ void main() {

treeView = TreeView<String>(
tree: treeNodes,
treeRowBuilder: (TreeViewNode<Object?> node) {
treeRowBuilder: (TreeViewNode<String> node) {
if (node.depth! == 1) {
// extent == 100
return row;
Expand Down Expand Up @@ -766,7 +766,7 @@ void main() {
controller: horizontalController,
),
tree: treeNodes,
treeRowBuilder: (TreeViewNode<Object?> node) {
treeRowBuilder: (TreeViewNode<String> node) {
return row.copyWith(
backgroundDecoration: node.depth! == 0
? rootBackgroundDecoration
Expand Down
53 changes: 39 additions & 14 deletions packages/two_dimensional_scrollables/test/tree_view/tree_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void main() {
controller: controller,
treeNodeBuilder: (
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<String> node,
AnimationStyle toggleAnimationStyle,
) {
returnedController ??= TreeViewController.of(context);
Expand All @@ -153,7 +153,7 @@ void main() {
tree: simpleNodeSet,
treeNodeBuilder: (
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<String> node,
AnimationStyle toggleAnimationStyle,
) {
returnedController ??= TreeViewController.maybeOf(context);
Expand Down Expand Up @@ -454,9 +454,9 @@ void main() {
home: TreeView<String>(
tree: simpleNodeSet,
controller: controller,
onNodeToggle: (TreeViewNode<Object?> node) {
onNodeToggle: (TreeViewNode<String> node) {
toggled = true;
toggledNode = node as TreeViewNode<String>;
toggledNode = node;
},
),
));
Expand All @@ -476,13 +476,13 @@ void main() {
home: TreeView<String>(
tree: simpleNodeSet,
controller: controller,
onNodeToggle: (TreeViewNode<Object?> node) {
onNodeToggle: (TreeViewNode<String> node) {
toggled = true;
toggledNode = node as TreeViewNode<String>;
toggledNode = node;
},
treeNodeBuilder: (
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<String> node,
AnimationStyle toggleAnimationStyle,
) {
final Duration animationDuration = toggleAnimationStyle.duration ??
Expand Down Expand Up @@ -510,7 +510,7 @@ void main() {
// Spacer
const SizedBox(width: 8.0),
// Content
Text(node.content.toString()),
Text(node.content),
]),
),
);
Expand All @@ -535,11 +535,11 @@ void main() {
tree: simpleNodeSet,
treeNodeBuilder: (
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<String> node,
AnimationStyle toggleAnimationStyle,
) {
style ??= toggleAnimationStyle;
return Text(node.content.toString());
return Text(node.content);
},
),
));
Expand All @@ -558,11 +558,11 @@ void main() {
toggleAnimationStyle: AnimationStyle.noAnimation,
treeNodeBuilder: (
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<String> node,
AnimationStyle toggleAnimationStyle,
) {
style = toggleAnimationStyle;
return Text(node.content.toString());
return Text(node.content);
},
),
));
Expand All @@ -580,11 +580,11 @@ void main() {
),
treeNodeBuilder: (
BuildContext context,
TreeViewNode<Object?> node,
TreeViewNode<String> node,
AnimationStyle toggleAnimationStyle,
) {
style ??= toggleAnimationStyle;
return Text(node.content.toString());
return Text(node.content);
},
),
));
Expand Down Expand Up @@ -693,6 +693,31 @@ void main() {
expect(find.text('Child 2:1'), findsNothing);
expect(find.text('Root 3'), findsOneWidget);
});

test('should use the generic type for callbacks and builders', () {
final TreeView<String> treeView = TreeView<String>(
tree: simpleNodeSet,
treeNodeBuilder: (
BuildContext context,
TreeViewNode<String> node,
AnimationStyle animationStyle,
) {
return TreeView.defaultTreeNodeBuilder(
context,
node,
animationStyle,
);
},
treeRowBuilder: (TreeViewNode<String> node) {
return TreeView.defaultTreeRowBuilder(node);
},
onNodeToggle: (TreeViewNode<String> node) {},
);

expect(treeView.onNodeToggle, isA<TreeViewNodeCallback<String>>());
expect(treeView.treeNodeBuilder, isA<TreeViewNodeBuilder<String>>());
expect(treeView.treeRowBuilder, isA<TreeViewRowBuilder<String>>());
});
});

group('TreeViewport', () {
Expand Down

0 comments on commit fb1eeff

Please sign in to comment.