aboutsummaryrefslogtreecommitdiff
path: root/frontend/lib/views/skill_tree/skill_tree_view.dart
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/lib/views/skill_tree/skill_tree_view.dart')
-rw-r--r--frontend/lib/views/skill_tree/skill_tree_view.dart129
1 files changed, 129 insertions, 0 deletions
diff --git a/frontend/lib/views/skill_tree/skill_tree_view.dart b/frontend/lib/views/skill_tree/skill_tree_view.dart
new file mode 100644
index 000000000..5d5d815b0
--- /dev/null
+++ b/frontend/lib/views/skill_tree/skill_tree_view.dart
@@ -0,0 +1,129 @@
+import 'package:auto_gpt_flutter_client/models/skill_tree/skill_tree_category.dart';
+import 'package:auto_gpt_flutter_client/models/skill_tree/skill_tree_node.dart';
+import 'package:auto_gpt_flutter_client/viewmodels/skill_tree_viewmodel.dart';
+import 'package:auto_gpt_flutter_client/views/skill_tree/tree_node_view.dart';
+import 'package:flutter/material.dart';
+import 'package:graphview/GraphView.dart';
+
+class SkillTreeView extends StatefulWidget {
+ final SkillTreeViewModel viewModel;
+
+ const SkillTreeView({Key? key, required this.viewModel}) : super(key: key);
+
+ @override
+ _SkillTreeViewState createState() => _SkillTreeViewState();
+}
+
+class _SkillTreeViewState extends State<SkillTreeView> {
+ Future<void>? initialization;
+
+ @override
+ void initState() {
+ super.initState();
+ initialization = widget.viewModel.initializeSkillTree();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Stack(
+ children: [
+ FutureBuilder<void>(
+ future: initialization,
+ builder: (context, snapshot) {
+ widget.viewModel.graph.nodes.clear();
+ widget.viewModel.graph.edges.clear();
+ if (snapshot.connectionState == ConnectionState.waiting) {
+ return const CircularProgressIndicator();
+ }
+
+ if (snapshot.hasError) {
+ return const Text("An error occurred");
+ }
+
+ // Create Node and Edge objects for GraphView
+ final Map<String, Node> nodeMap = {};
+ for (var skillTreeNode in widget.viewModel.skillTreeNodes) {
+ final node = Node.Id(skillTreeNode.id);
+ widget.viewModel.graph.addNode(node);
+ nodeMap[skillTreeNode.id] = node;
+ }
+
+ for (var skillTreeEdge in widget.viewModel.skillTreeEdges) {
+ final fromNode = nodeMap[skillTreeEdge.from];
+ final toNode = nodeMap[skillTreeEdge.to];
+ if (fromNode != null && toNode != null) {
+ widget.viewModel.graph.addEdge(fromNode, toNode);
+ }
+ }
+
+ return Scaffold(
+ body: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Expanded(
+ child: InteractiveViewer(
+ constrained: false,
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width,
+ height: MediaQuery.of(context).size.height,
+ child: Align(
+ alignment: Alignment.centerLeft,
+ child: GraphView(
+ graph: widget.viewModel.graph,
+ algorithm:
+ SugiyamaAlgorithm(widget.viewModel.builder),
+ paint: Paint()
+ ..color = Colors.green
+ ..strokeWidth = 1
+ ..style = PaintingStyle.stroke,
+ builder: (Node node) {
+ String nodeId = node.key?.value as String;
+ SkillTreeNode? skillTreeNode =
+ widget.viewModel.getNodeById(nodeId);
+ if (skillTreeNode != null) {
+ return TreeNodeView(
+ node: skillTreeNode,
+ selected: nodeId ==
+ widget.viewModel.selectedNode?.id);
+ } else {
+ return const SizedBox(); // Return an empty widget if the node is not found
+ }
+ },
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ },
+ ),
+ Positioned(
+ top: 10,
+ left: 10,
+ child: Material(
+ type: MaterialType.transparency,
+ child: DropdownButton<SkillTreeCategory>(
+ value: widget.viewModel.currentSkillTreeType,
+ items: SkillTreeCategory.values.map((category) {
+ return DropdownMenuItem<SkillTreeCategory>(
+ value: category,
+ child: Text(category.stringValue),
+ );
+ }).toList(),
+ onChanged: (newValue) {
+ if (newValue != null) {
+ setState(() {
+ widget.viewModel.currentSkillTreeType = newValue;
+ widget.viewModel.initializeSkillTree();
+ });
+ }
+ },
+ ),
+ ),
+ )
+ ],
+ );
+ }
+}