/** * @author Martin Karkowski * @email m.karkowski@zema.de * @create date 2021-06-24 17:58:16 * @modify date 2021-06-24 17:58:16 * @desc [description] */ import * as go from "gojs"; const make = go.GraphObject.make; export function addNodeNextTo(node: go.Node, newNodeOptions: N, newLinkOptions: L, mode: "from" | "to", direction: "n" | "e" | "s" | "w" = "s", offset = 100, movingOffset = 20) { // We get the Diagram of the Node. const diagram = node.diagram; // To position the const nodeBox = node.actualBounds; const middleY = nodeBox.y + nodeBox.height / 2; const middleX = nodeBox.x + nodeBox.width / 2; diagram.startTransaction("add_node_and_link"); // Add the new Node. diagram.model.addNodeData(newNodeOptions); const newNodeBox = diagram.findNodeForData(newNodeOptions).actualBounds; // New Node Location const location = new go.Point(); // Define the Position switch (direction) { case "n": location.x = middleX - newNodeBox.width / 2; location.y = nodeBox.y - offset - newNodeBox.height / 2; break; case "s": location.x = middleX - newNodeBox.width / 2; location.y = nodeBox.y + nodeBox.height + offset - newNodeBox.height / 2; break; case "e": location.x = nodeBox.x + nodeBox.width + offset + newNodeBox.width / 2; location.y = middleY - newNodeBox.height / 2; break; case "w": location.x = nodeBox.x - offset - newNodeBox.width / 2; location.y = middleY - newNodeBox.height / 2; break; } const linkData = Object.assign(newLinkOptions, mode === "from" ? { from: diagram.model.getKeyForNodeData(node.data), to: diagram.model.getKeyForNodeData(newNodeOptions), } : { to: diagram.model.getKeyForNodeData(node.data), from: diagram.model.getKeyForNodeData(newNodeOptions), }); diagram.findNodeForData(newNodeOptions).location = location; // Assign the Position const foundObjects = diagram.findObjectsNear( location, Math.max(newNodeBox.width, newNodeBox.height), // Filter Function, which only returns nodes and // check if the node isnt the node we are considering x => { const p = x.part; return (p instanceof go.Node && p !== node) ? p : null; } ); // If we will found new Objects => we will adapt theese nodes. with respect to there position if (foundObjects.size > 1) { const attribute: "width" | "height" = (direction == "n" || direction == "s") ? "width" : "height"; let length = 0; for (const obj of foundObjects.toArray()) { length += (obj as go.Node).actualBounds[attribute]; } length += movingOffset * (foundObjects.size - 1); const start = length / 2; let _offset = 0; // Iterate over the found elements for (const obj of foundObjects.toArray()) { // Location const locationForNode = obj.position.copy(); switch (direction) { case "n": case "s": locationForNode.x = middleX - start + _offset; break; case "e": case "w": locationForNode.y = middleY - start + _offset; break; } // Adapt the Offset _offset += movingOffset + obj.actualBounds[attribute]; // Adapt the Position diagram.findNodeForData(obj.data).location = locationForNode; } } // and add the link data to the model diagram.model.addLinkData(linkData); console.log(linkData); // Commit the Change diagram.commitTransaction("add_node_and_link"); }