From 256d0c820a088da608a182be31fd96f3e99e19f6 Mon Sep 17 00:00:00 2001 From: Dario Del Piano Date: Fri, 28 Oct 2022 09:57:18 +0100 Subject: [PATCH] #36 adding logic for the new path calculation --- installation.sh | 3 +- src/components/Main.js | 11 ++- src/components/graph/MetaGraph.ts | 90 ++++++++++++++++--- .../views/compositions/Composition.js | 28 +++--- 4 files changed, 104 insertions(+), 28 deletions(-) diff --git a/installation.sh b/installation.sh index 0cc3830b..f89ba787 100755 --- a/installation.sh +++ b/installation.sh @@ -56,7 +56,8 @@ if [ "$INSTALL" = true ]; then yarn run start elif [ "$UPDATE" = true ]; then echo " ### Updating meta-diagram" - yarn remove @metacell/meta-diagram + # yarn remove @metacell/meta-diagram + rm -rf yalc.lock PSYVIEW=`pwd` if [ -d '../meta-diagram' ]; then diff --git a/src/components/Main.js b/src/components/Main.js index f8975673..83a94211 100644 --- a/src/components/Main.js +++ b/src/components/Main.js @@ -48,10 +48,15 @@ class Main extends React.Component { } handlePostUpdates(event) { + const node = event.entity; switch(event.function) { case CallbackTypes.POSITION_CHANGED: { - const node = event.entity; - this.metaGraph.handleNodePositionChanged(node, this.mousePos.x, this.mousePos.y); + this.metaGraph.updateGraph(node, this.mousePos.x, this.mousePos.y); + this.interpreter.updateModel(node); + return true; + } + case CallbackTypes.CHILD_POSITION_CHANGED: { + this.metaGraph.handleNodePositionChanged(node); this.interpreter.updateModel(node); return true; } @@ -63,7 +68,7 @@ class Main extends React.Component { } handlePreUpdates(event) { - console.log('preUpdates not yet implemented.'); + // console.log('preUpdates not yet implemented.'); } metaCallback(event) { diff --git a/src/components/graph/MetaGraph.ts b/src/components/graph/MetaGraph.ts index 182dfd14..564d52b7 100644 --- a/src/components/graph/MetaGraph.ts +++ b/src/components/graph/MetaGraph.ts @@ -1,5 +1,6 @@ // import {MetaNodeModel} from "../react-diagrams/MetaNodeModel"; import {MetaLink, MetaNodeModel, MetaLinkModel} from "@metacell/meta-diagram" +import { PNLClasses } from "../../constants"; class Graph { private readonly node: MetaNodeModel; @@ -26,6 +27,10 @@ class Graph { this.children.set(graph.getID(), graph) } + deleteChild(id: string) : void { + this.children.delete(id); + } + getChildren(): MetaNodeModel[] { return Array.from(this.children.values()).map(g => g.getNode()) } @@ -60,10 +65,12 @@ class Graph { export class MetaGraph { private readonly roots: Map; private readonly links: MetaLinkModel[]; + private parentUpdating: boolean; constructor() { this.roots = new Map() this.links = []; + this.parentUpdating = false; } addLinks(links: MetaLink[]) { @@ -170,28 +177,82 @@ export class MetaGraph { return parent } - handleNodePositionChanged(metaNodeModel: MetaNodeModel, cursorX: number, cursorY: number){ + private findParentNodeGraph(path: string[]) : Graph { + const newPath = [...path]; + newPath.pop(); + return this.findNodeGraph(newPath); + } + + updateGraph(metaNodeModel: MetaNodeModel, cursorX: number, cursorY: number) { + this.updateNodeContainerBoundingBox(metaNodeModel); + let parent: MetaNodeModel|undefined = this.rootContainsNode(metaNodeModel, cursorX, cursorY); + let newPath = this.findNewPath(metaNodeModel, parent, cursorX, cursorY); + if (metaNodeModel.getGraphPath().join().toString() !== newPath.join().toString()) { + this.updateNodeInGraph(metaNodeModel, newPath); + } + this.handleNodePositionChanged(metaNodeModel); + } + + handleNodePositionChanged(metaNodeModel: MetaNodeModel){ // TODO: Update node parent (add or remove parent) // update node graph path, // bounding boxes of parents + // update the graph for right parent children relationship + this.updateNodeContainerBoundingBox(metaNodeModel); // Update children position (children should move the same delta as node) this.updateChildrenPosition(metaNodeModel) // Update local position / relative position to the parent this.updateNodeLocalPosition(metaNodeModel) - // update the graph for right parent children relationship - this.updateGraph(metaNodeModel, cursorX, cursorY); } - updateGraph(metaNodeModel: MetaNodeModel, cursorX: number, cursorY: number) { - let parent = undefined; - let search = true; - this.roots.forEach((node, id) => { - if (node.getContainerBoundingBox().containsPoint(cursorX, cursorY)) { + rootContainsNode(metaNodeModel: MetaNodeModel, cursorX: number, cursorY: number): MetaNodeModel|undefined { + let parent = undefined + this.roots.forEach((graph, id) => { + const node = graph.getNode(); + if (node.getID() !== metaNodeModel.getID() + && node.getOption('shape') === PNLClasses.COMPOSITION + && node.getNodeBoundingBox().containsPoint(cursorX, cursorY)) + { parent = node; } }); - // TODO add the new child to the graph and update graphPath for the metaNodeModel instance + return parent; + } + + findNewPath(metaNodeModel: MetaNodeModel, parent: MetaNodeModel|undefined, cursorX: number, cursorY: number) { + let search: boolean = true; + let newPath: string[] = []; + while (search && parent) { + search = false; + const children = this.getChildren(parent); + // eslint-disable-next-line no-loop-func + children.forEach((child: MetaNodeModel) => { + if (!search + && child.getID() !== metaNodeModel.getID() + && child.getOption('shape') === PNLClasses.COMPOSITION + && child.getNodeBoundingBox().containsPoint(cursorX, cursorY)) + { + search = true; + parent = child; + } + }); + // @ts-ignore + newPath = parent.getGraphPath(); + } + return [...newPath, metaNodeModel.getID()]; + } + + updateNodeInGraph(metaNodeModel: MetaNodeModel, newPath: string[]) { + const oldPath = metaNodeModel.getGraphPath(); + if (oldPath.length === 1) { + this.roots.delete(oldPath[0]); + } else { + let parentGraph = this.findParentNodeGraph(oldPath); + parentGraph.deleteChild(metaNodeModel.getID()); + } + metaNodeModel.setOption('graphPath', newPath); + this.addNode(metaNodeModel); } private updateChildrenPosition(metaNodeModel: MetaNodeModel){ @@ -204,7 +265,7 @@ export class MetaGraph { */ // @ts-ignore const localPosition = n.getLocalPosition() - n.setPosition(metaNodeModel.getX() + localPosition.x, metaNodeModel.getY() + localPosition.y) + n.setNodePosition(metaNodeModel.getX() + localPosition.x, metaNodeModel.getY() + localPosition.y) }) } @@ -214,7 +275,12 @@ export class MetaGraph { metaNodeModel.updateLocalPosition(parent) } - updateNodesContainerBoundingBoxes(nodes: MetaNodeModel[]): void { - nodes.forEach(n => n.setContainerBoundingBox(this.getNodeContainerBoundingBox(n))) + updateNodeContainerBoundingBox(node: MetaNodeModel): void { + node.setContainerBoundingBox({ + left: node.getX(), + top: node.getY(), + bottom: node.getY() + node.height, + right: node.getX() + node.width + }); } } diff --git a/src/components/views/compositions/Composition.js b/src/components/views/compositions/Composition.js index 73a36719..8500b5a7 100644 --- a/src/components/views/compositions/Composition.js +++ b/src/components/views/compositions/Composition.js @@ -85,19 +85,9 @@ class Composition extends React.Component { height: props.model.options.height, } this.changeVisibility = this.changeVisibility.bind(this); - } - - changeVisibility() { - this.setState({expanded: !this.state.expanded}); - } - - render() { - const { expanded } = this.state; - const { classes } = this.props; - return ( - - { @@ -111,6 +101,20 @@ class Composition extends React.Component { > } label="New Comp" color="secondary" /> + ); + } + + changeVisibility() { + this.setState({expanded: !this.state.expanded}); + } + + render() { + const { expanded } = this.state; + const { classes } = this.props; + + return ( + + {this.rndElement} ); }