nope/resources/ui/gojs/helpers/add-node-next-to.ts

119 lines
3.5 KiB
TypeScript
Raw Normal View History

2021-07-27 10:55:15 +00:00
/**
* @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<N = any, L = any>(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");
}