Skip to content
Snippets Groups Projects
Commit fd98b3c4 authored by Maximilian Giller's avatar Maximilian Giller :squid:
Browse files

Drag and drop connect nodes mechanic

parent 0fd73281
No related branches found
Tags v1.0rc0
1 merge request!2Implemented editor in the react framework
Pipeline #56709 passed
......@@ -21,8 +21,14 @@ type clickPosition = {
graph: { x: number; y: number };
window: { x: number; y: number };
};
type positionTranslate = {
x: number;
y: number;
z: number;
};
export class Editor extends React.PureComponent<propTypes, stateTypes> {
private maxDistanceToConnect = 15;
private defaultWarmupTicks = 100;
private warmupTicks = 100;
private renderer: any;
......@@ -31,6 +37,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
super(props);
this.loadGraph = this.loadGraph.bind(this);
this.loadSpace = this.loadSpace.bind(this);
this.extractPositions = this.extractPositions.bind(this);
this.handleNodeClick = this.handleNodeClick.bind(this);
this.onHistoryChange = this.onHistoryChange.bind(this);
this.handleEngineStop = this.handleEngineStop.bind(this);
......@@ -41,7 +48,8 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
this.handleNodeCanvasObject = this.handleNodeCanvasObject.bind(this);
this.handleLinkCanvasObject = this.handleLinkCanvasObject.bind(this);
this.handleBackgroundClick = this.handleBackgroundClick.bind(this);
this.extractPositions = this.extractPositions.bind(this);
this.handleNodeDrag = this.handleNodeDrag.bind(this);
this.handleNodeDragEnd = this.handleNodeDragEnd.bind(this);
this.renderer = React.createRef();
......@@ -308,6 +316,32 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
return undefined;
}
private handleNodeDrag(node: Node, translate: positionTranslate) {
this.setState({
selectedNode: node,
});
const closest = this.state.graph.getClosestOtherNode(node);
// Is close enough for new link?
if (closest.distance > this.maxDistanceToConnect) {
return;
}
// Does link already exist?
if (node.neighbors.includes(closest.node)) {
return;
}
// Add link
node.connect(closest.node);
this.forceUpdate();
}
private handleNodeDragEnd(node: Node, translate: positionTranslate) {
return;
}
private handleEngineStop() {
// Only do something on first stop for each graph
if (this.warmupTicks <= 0) {
......@@ -355,6 +389,8 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
nodeCanvasObjectMode={"after"}
linkCanvasObject={this.handleLinkCanvasObject}
linkCanvasObjectMode={"replace"}
onNodeDrag={this.handleNodeDrag}
onNodeDragEnd={this.handleNodeDragEnd}
onBackgroundClick={(event) =>
this.handleBackgroundClick(
event,
......
......@@ -287,6 +287,57 @@ export class Graph extends ManagedData {
return true;
}
/**
* Calculates the pythagoras distance.
* @param nodeA One node.
* @param nodeB The other node.
* @returns Distance between both nodes.
*/
private nodeDistance(nodeA: Node, nodeB: Node): number {
const a = nodeA as any;
const b = nodeB as any;
const xDistance = Math.abs(a.x - b.x);
const yDistance = Math.abs(a.y - b.y);
return Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));
}
/**
* Goes over all nodes and finds the closest node based on distance, that is not the given reference node.
* @param referenceNode Reference node to get closest other node to.
* @returns Closest node and distance. Undefined, if no closest node can be found.
*/
public getClosestOtherNode(referenceNode: Node): {
node: Node;
distance: number;
} {
if (referenceNode == undefined || this.nodes.length < 2) {
return undefined;
}
// Iterate over all nodes, keep the one with the shortest distance
let closestDistance: number = undefined;
let closestNode: Node = undefined;
this.nodes.forEach((node) => {
if (node.equals(referenceNode)) {
return; // Don't compare to itself
}
const currentDistance = this.nodeDistance(node, referenceNode);
if (
closestDistance == undefined ||
closestDistance > currentDistance
) {
closestDistance = currentDistance;
closestNode = node;
}
});
return { node: closestNode, distance: closestDistance };
}
public static parse(raw: any): Graph {
return new Graph(this.parseData(raw));
}
......
......@@ -85,6 +85,35 @@ export class Node extends GraphElement {
return links;
}
/**
* Calculates a list of all connected nodes to the current node.
* @returns Array containing all connected nodes.
*/
public get neighbors(): Node[] {
const nodes: Node[] = [];
this.links.forEach((link) => {
// Find "other" node
let otherNode = link.source;
if (this.equals(otherNode)) {
otherNode = link.target;
}
// Still undefined?
if (otherNode == undefined) {
// Link apparently not properly set up
return;
}
// Add to list if doesn't exist
if (!nodes.includes(otherNode)) {
nodes.push(otherNode);
}
});
return nodes;
}
/**
* Connects a given node to itself. Only works if they are in the same graph.
* @param node Other node to connect.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment