Skip to content

Instantly share code, notes, and snippets.

@Hixie
Created February 27, 2020 01:43
Show Gist options
  • Save Hixie/ff07a1203684296acde4b543d7664a2f to your computer and use it in GitHub Desktop.
Save Hixie/ff07a1203684296acde4b543d7664a2f to your computer and use it in GitHub Desktop.
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void _enablePlatformOverrideForDesktop() {
if (!kIsWeb && (Platform.isWindows || Platform.isLinux)) {
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
}
}
void main() {
_enablePlatformOverrideForDesktop();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.ltr,
child: TreeDemo(),
);
}
}
List<SingleNode> _kTestNodes = [
GroupNode('0', [1, 2, 3, 4, 5, 6]),
SingleNode('1'),
SingleNode('2'),
SingleNode('3'),
SingleNode('4'),
SingleNode('5'),
GroupNode('6', [7, 8]),
SingleNode('7'),
SingleNode('8'),
];
class TreeDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _TreeDemoState();
}
}
class _TreeDemoState extends State<TreeDemo> {
TestTreeModel model = TestTreeModel(_kTestNodes);
@override
Widget build(BuildContext context) {
return Column(
children: [
Tree(
model: model,
),
GestureDetector(
child: Icon(Icons.refresh),
onTap: () {
setState(() {
// Move node 6 to index 0 within node 0's children.
model.moveNode(6, 0, 0, 0);
});
},
),
GestureDetector(
child: Icon(Icons.description),
onTap: () {
debugDumpApp();
},
)
],
);
}
}
enum BorderType { box, line, none }
/// A widget with a tree structure. Grabs its structure and data from a [model].
class Tree extends StatefulWidget {
Tree({
Key key,
@required this.model,
}) : assert(model != null),
super(key: key);
/// The model backing the [Tree].
final TestTreeModel model;
@override
_TreeState createState() => _TreeState();
}
class _TreeState extends State<Tree> {
@override
Widget build(BuildContext context) {
return Column(children: _genRows(nodes: widget.model.getTopLevel()).toList());
}
Iterable<Widget> _genRows({
@required List<int> nodes,
double leftIndent = 0,
}) sync* {
for (int i = 0; i < nodes.length; i++) {
int node = nodes[i];
yield Text('${">" * leftIndent.round()} $node', key: ValueKey(node));
yield* _genRows(nodes: widget.model.getChildrenList(node), leftIndent: leftIndent + 1);
}
}
}
class TestTreeModel {
TestTreeModel(this.nodes);
List<SingleNode> nodes;
List<int> getTopLevel() {
return [0];
}
List<int> getChildrenList(int node) {
return nodes[node] is GroupNode ? (nodes[node] as GroupNode).children : [];
}
void moveNode(int source, int sourceParent, int target, int targetParent) {
getChildrenList(sourceParent).remove(source);
List<int> targetChildren = getChildrenList(targetParent);
if (targetParent == target) {
targetChildren.insert(0, source);
return;
}
for (int i = 0; i < targetChildren.length; ++i) {
if (targetChildren[i] == target) {
targetChildren.insert(i, source);
return;
}
}
}
}
class SingleNode {
const SingleNode(this.name);
final String name;
}
class GroupNode extends SingleNode {
const GroupNode(String name, this.children) : super(name);
final List<int> children;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment