Skip to content

Instantly share code, notes, and snippets.

@termslang
Last active August 11, 2021 22:20
Show Gist options
  • Save termslang/2a2c611b8e1ddb101f955d2f625c9b19 to your computer and use it in GitHub Desktop.
Save termslang/2a2c611b8e1ddb101f955d2f625c9b19 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
/// Globals
Key selectedNode = UniqueKey();
Set<Key> selectedSubnodes = Set();
List<Node> nodes = [
Node('A', [
Node('A1'),
Node('A2', [
Node('A21'),
Node('A22'),
Node('A23', [Node('A231')]),
Node('A24'),
]),
]),
Node('B'),
Node('C', [
Node('C1'),
Node('C2'),
Node('C3'),
]),
];
/// Model
class Node {
final Key key = UniqueKey();
String title = '';
List<Node> nodes;
Node(this.title, [_nodes]) : this.nodes = _nodes == null ? [] : _nodes;
}
/// App
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'TreeRendererWidget'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: TreeRendererWidget(nodes: nodes));
}
}
class TreeRendererWidget extends StatefulWidget {
final List<Node> nodes;
final int depth;
TreeRendererWidget({Key? key, required this.nodes, this.depth = 0}) : super(key: key);
@override
_TreeRendererWidgetState createState() => _TreeRendererWidgetState();
}
class _TreeRendererWidgetState extends State<TreeRendererWidget> {
@override
Widget build(BuildContext context) {
var ancestralState = context.findRootAncestorStateOfType<_MyHomePageState>();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widget.nodes.map((Node n) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () {
ancestralState?.setState(() {
if (selectedNode == n.key) {
selectedNode = UniqueKey();
selectedSubnodes.clear();
} else {
selectedNode = n.key;
selectedSubnodes.clear();
_addSubnode(n);
}
});
},
child: Container(
color: selectedNode == n.key
? Colors.red
: selectedSubnodes.contains(n.key)
? Colors.orange
: Colors.white,
child: Text(
' ' * widget.depth * 5 + '• ' + n.title,
style: TextStyle(fontSize: 30),
),
),
),
TreeRendererWidget(nodes: n.nodes, depth: widget.depth + 1)
],
);
}).toList(),
);
}
void _addSubnode(Node n) {
n.nodes.forEach((nn) {
selectedSubnodes.add(nn.key);
_addSubnode(nn);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment