Skip to content

Commit

Permalink
add expansion state restoration example
Browse files Browse the repository at this point in the history
  • Loading branch information
baumths committed May 2, 2024
1 parent 8e2b8ce commit 44eee5f
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
3 changes: 3 additions & 0 deletions example/lib/src/examples.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'examples/drag_and_drop.dart' show DragAndDropTreeView;
import 'examples/filterable.dart' show FilterableTreeView;
import 'examples/lazy_loading.dart' show LazyLoadingTreeView;
import 'examples/minimal.dart' show MinimalTreeView;
import 'examples/restorable.dart' show RestorableTreeView;
import 'settings/controller.dart' show SettingsController;
import 'shared.dart' show IndentGuideType, LineStyle, enumByName;

Expand Down Expand Up @@ -37,6 +38,7 @@ enum Example {
filterable('Filterable', Icon(Icons.manage_search_rounded)),
lazyLoading('Lazy Loading', Icon(Icons.hourglass_top_rounded)),
minimal('Minimal', Icon(Icons.segment)),
restorable('Restorable', Icon(Icons.restore)),
;

const Example(this.title, this.icon);
Expand All @@ -62,6 +64,7 @@ class ExamplesView extends StatelessWidget {
Example.filterable => const FilterableTreeView(),
Example.lazyLoading => const LazyLoadingTreeView(),
Example.minimal => const MinimalTreeView(),
Example.restorable => const RestorableTreeView(),
},
),
);
Expand Down
119 changes: 119 additions & 0 deletions example/lib/src/examples/restorable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import 'package:flutter/material.dart';
import 'package:flutter_fancy_tree_view/flutter_fancy_tree_view.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../settings/controller.dart';

class MyTreeController extends TreeController<Node> {
MyTreeController({
required super.roots,
required this.expandedIds,
}) : super(childrenProvider: (Node node) => node.children);

final Set<String> expandedIds;

@override
bool getExpansionState(Node node) => expandedIds.contains(node.id);

@override
void setExpansionState(Node node, bool expanded) {
expanded ? expandedIds.add(node.id) : expandedIds.remove(node.id);
}
}

class Node {
Node({required this.id, this.children = const <Node>[]});

final String id;
final List<Node> children;

@override
int get hashCode => id.hashCode;

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Node && other.id == id;
}
}

class RestorableTreeView extends StatefulWidget {
const RestorableTreeView({super.key});

@override
State<RestorableTreeView> createState() => _RestorableTreeViewState();
}

class _RestorableTreeViewState extends State<RestorableTreeView> {
static const String expandedIdsKey = 'fftv.restorableTreeView.expandedIds';

late final MyTreeController treeController;
late final SharedPreferences prefs = context.read<SettingsController>().prefs;

final Node root = Node(id: '0', children: [
Node(id: '1', children: [
Node(id: '2', children: [
Node(id: '3', children: [
Node(id: '4'),
Node(id: '5', children: [
Node(id: '6'),
Node(id: '7', children: [
Node(id: '8'),
]),
]),
]),
Node(id: '9'),
]),
Node(id: '10'),
]),
Node(id: '11'),
]);

@override
void initState() {
super.initState();
treeController = MyTreeController(
roots: <Node>[root],
// Restore expanded ids
expandedIds: <String>{...?prefs.getStringList(expandedIdsKey)},
);
}

@override
void dispose() {
// Persist expanded ids
prefs.setStringList(
expandedIdsKey,
treeController.expandedIds.toList(),
);
treeController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return TreeView<Node>(
treeController: treeController,
nodeBuilder: (BuildContext context, TreeEntry<Node> entry) {
return TreeIndentation(
entry: entry,
child: Row(
children: [
FolderButton(
key: Key('FolderButton#${entry.node.id}'),
isOpen: entry.hasChildren ? entry.isExpanded : null,
onPressed: entry.hasChildren
? () => treeController.toggleExpansion(entry.node)
: null,
),
Flexible(
child: Text('Node #${entry.node.id}'),
),
],
),
);
},
);
}
}

0 comments on commit 44eee5f

Please sign in to comment.