From b6cbc975cbcb07072a7b39f898159f1674be76fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Fri, 21 Aug 2020 19:57:27 +0200 Subject: [PATCH] More generalized version of tree --- example.html | 3 + src/main.js | 72 ++++++++++++++++++ src/script-graph.ts | 1 + src/script-graph2.ts | 169 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 src/script-graph2.ts diff --git a/example.html b/example.html index 7d2d506..2b68379 100644 --- a/example.html +++ b/example.html @@ -15,6 +15,7 @@ padding: 16px; font-family: Roboto, Noto, sans-serif; font-size: 14px; + vertical-align: top; } code { display: block; @@ -34,6 +35,8 @@
+
+
diff --git a/src/main.js b/src/main.js index 904208b..9afd901 100644 --- a/src/main.js +++ b/src/main.js @@ -2,6 +2,9 @@ import {demoConfig} from "./demo-config"; import "@vanillawc/wc-codemirror"; import "./script-graph"; +import "./script-graph2"; + +import { mdiAsterisk, mdiArrowUp, mdiArrowDown } from "@mdi/js"; let index_counter = 0; let nodes = []; @@ -47,6 +50,70 @@ const structure_tree = (inp) => { } +const structure_tree2 = () => { + return [ + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number 1"), + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number 2"), + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number 3"), + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number 4"), + children: [ + [ + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number A1"), + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number A2"), + }, + ], + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number B"), + end: false, + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number B"), + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number B"), + }, + ] + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number 4"), + children: [ + { + icon: mdiArrowUp, + clickCallback: () => console.log("Return"), + }, + { + icon: mdiArrowDown, + clickCallback: () => console.log("Return"), + }, + ], + }, + { + icon: mdiAsterisk, + clickCallback: () => console.log("Number 1"), + }, + ]; +} + window.onload = () => { let src = demoConfig; @@ -65,6 +132,11 @@ window.onload = () => { const graph = document.createElement("script-graph"); graph.tree = structure_tree(src); + + const graph2 = document.createElement("script-graph2"); + graph2.tree = structure_tree2(src); + document.querySelector("#graph2").appendChild(graph2); + graph.addEventListener("selected", (ev) => { const idx = ev.detail; const code = document.querySelector("code"); diff --git a/src/script-graph.ts b/src/script-graph.ts index 74af505..afddb62 100644 --- a/src/script-graph.ts +++ b/src/script-graph.ts @@ -50,6 +50,7 @@ class ScriptGraph extends LitElement { * Tree Node Structure * { * icon: svg, + * styles: * end: false * children: [[TreeNode],...] * click: callback,undefined diff --git a/src/script-graph2.ts b/src/script-graph2.ts new file mode 100644 index 0000000..c318d84 --- /dev/null +++ b/src/script-graph2.ts @@ -0,0 +1,169 @@ +import { + LitElement, + html, + css, + svg, + property +} from "lit-element"; + +const SIZE = 35; +const DIST = 20; + +interface TreeNode { + icon: String; + styles: String; + end?: Boolean; + children?: (TreeNode | TreeNode[])[]; + clickCallback?: any; + addCallback?: any; +} + +class ScriptGraph2 extends LitElement { + @property() selected = null; + @property() tree: [TreeNode]; + @property() nodeSize = SIZE; + @property() nodeSeparation = DIST; + + private _draw_node(x, y, node) { + return svg` + + + + + `; + } + + private _draw_connector(x1, y1, x2, y2) { + return svg` + + `; + } + + private _draw_tree(tree: TreeNode | TreeNode[]) { + if(!tree) return {svg: `Hello`, width: 0, height: 0}; + if(!Array.isArray(tree)) { + let height = this.nodeSize; + let width = this.nodeSize; + let pieces = []; + + if(tree.children) { + const childTrees = tree.children.map((c) =>this._draw_tree(c)); + height += childTrees.reduce((a,i) => Math.max(a, i.height), 0); + width = childTrees.reduce((a,i) => a+i.width, 0) + this.nodeSeparation*(tree.children.length - 1); + const offsets = childTrees.map((sum => value => sum += value.width + this.nodeSeparation)(0)); + + let bottomConnectors = false; + + for (const [idx, child] of childTrees.entries()) { + const x = -width/2 + (idx? offsets[idx-1] : 0) + child.width/2; + // Draw top connectors + pieces.push(this._draw_connector( + 0, + this.nodeSize/2, + x, + this.nodeSize + this.nodeSeparation + )); + + + let endNode = tree.children[idx]; + if(Array.isArray(endNode)) endNode = endNode[endNode.length -1]; + if(endNode.end !== false) { + // Draw bottom fill + pieces.push(this._draw_connector( + x, + this.nodeSeparation + child.height, + x, + this.nodeSeparation + height + )); + + // Draw bottom connectors + pieces.push(this._draw_connector( + x, + this.nodeSeparation + height, + 0, + this.nodeSeparation + height + this.nodeSize/2 + this.nodeSeparation + )); + bottomConnectors = true; + } + + // Draw child tree + pieces.push(svg` + + ${child.svg} + + `); + } + if(bottomConnectors) + height += this.nodeSize + this.nodeSeparation; + + } + if(tree.end !== false) { + // Draw bottom connector + pieces.push(this._draw_connector( + 0, + height, + 0, + height + this.nodeSeparation + )); + height += this.nodeSeparation; + } + + // Draw the node itself + pieces.push(this._draw_node(0, 0, tree)); + + return {svg: pieces, width, height}; + } + + // Array of trees + let pieces = []; + let height = 0; + const children = tree.map((n) => this._draw_tree(n)); + const width = children.reduce((a,i) => Math.max(a, i.width), 0); + for (const [_, node] of children.entries()) { + pieces.push(svg` + + ${node.svg} + + `); + height += node.height; + } + + // TODO TEMPORARY + return {svg: pieces, width, height}; + + } + + + render() { + let tree = this._draw_tree(this.tree); + return html` + + + + ${tree.svg} + + + `; + } + +} + +customElements.define("script-graph2", ScriptGraph2); +