replace ghost nodes by real nodes on drag end
This commit is contained in:
parent
89c1d44141
commit
0e408faabc
75
editor.ts
75
editor.ts
@ -428,6 +428,7 @@ var selection : WF.WFNode | WF.WFGhostNode | WF.WFEdge | null = null; // The cur
|
||||
var rightSelection : WF.WFNode | WF.WFEdge | null = null; // The currently right clicked node/edge.
|
||||
var edgeTo : WF.WFNode | null = null; // Target of an edge to be created.
|
||||
var edgeFrom : WF.WFNode | null = null; // Start on an edge to be created.
|
||||
var edgeTarget : WF.WFNode | null = null; // Possible source/target for an edge after dragging the respective ghost node.
|
||||
//Utility elements
|
||||
const curtain = <HTMLElement>document.getElementById('curtain');
|
||||
const submenuBackdrop = <HTMLElement>document.getElementById('submenu-backdrop');
|
||||
@ -572,14 +573,16 @@ export function addState() {
|
||||
var nodeId = stateIdCounter ++;
|
||||
var x = newStateCoords.x;
|
||||
var y = newStateCoords.y;
|
||||
var state : WF.WFNode = { id: 'state_' + nodeId,
|
||||
x: x,
|
||||
y: y,
|
||||
name: 'state_' + nodeId,
|
||||
fx: x,
|
||||
fy: y,
|
||||
val: 5,
|
||||
stateData: new WF.StateData({ abbreviation: `S${nodeId}`, final: 'false' }) };
|
||||
var state = new WF.WFNode ({
|
||||
id: 'state_' + nodeId,
|
||||
x: x,
|
||||
y: y,
|
||||
name: 'state_' + nodeId,
|
||||
fx: x,
|
||||
fy: y,
|
||||
val: 5,
|
||||
stateData: { abbreviation: `S${nodeId}`, final: 'false' }
|
||||
});
|
||||
workflow.states.push(state);
|
||||
updateGraph();
|
||||
select(state);
|
||||
@ -587,8 +590,8 @@ export function addState() {
|
||||
}
|
||||
|
||||
export function addEdge() {
|
||||
var x = newStateCoords.x;
|
||||
var y = newStateCoords.y;
|
||||
var x = newStateCoords.x - 20;
|
||||
var y = newStateCoords.y + 20;
|
||||
var ghostState = new WF.WFGhostNode({
|
||||
id: `@@ghost@(${x},${y})`,
|
||||
x: x,
|
||||
@ -596,11 +599,13 @@ export function addEdge() {
|
||||
fx: x,
|
||||
fy: y,
|
||||
val: 7 });
|
||||
var x = newStateCoords.x + 20;
|
||||
var y = newStateCoords.y - 20;
|
||||
var ghostState2 = new WF.WFGhostNode({
|
||||
id: `@@ghost@(${x+50},${y})`,
|
||||
x: x + 50,
|
||||
id: `@@ghost@(${x},${y})`,
|
||||
x: x,
|
||||
y: y,
|
||||
fx: x + 50,
|
||||
fx: x,
|
||||
fy: y,
|
||||
val: 7 });
|
||||
workflow.states.push(ghostState, ghostState2);
|
||||
@ -712,14 +717,15 @@ function removeAction(action: WF.WFEdge) {
|
||||
* Removes a state from the workflow.
|
||||
* @param {*} state The state to remove.
|
||||
*/
|
||||
function removeState(state: WF.WFNode) {
|
||||
function removeState(state: WF.WFNode | WF.WFGhostNode) {
|
||||
workflow.actions
|
||||
.filter(edge => edge.source === state || edge.target === state)
|
||||
.forEach(edge => removeAction(edge));
|
||||
workflow.states.splice(workflow.states.indexOf(state), 1);
|
||||
var abbreviation = state.stateData && state.stateData.abbreviation;
|
||||
abbreviation && stateAbbreviations.splice(stateAbbreviations.indexOf(abbreviation), 1);
|
||||
nodeIndex.remove(state.id);
|
||||
if (state instanceof WF.WFNode) {
|
||||
stateAbbreviations.splice(stateAbbreviations.indexOf(state.stateData.abbreviation), 1);
|
||||
nodeIndex.remove(state.id);
|
||||
}
|
||||
}
|
||||
|
||||
var selfLoops: Map<string, WF.WFEdge[]> = new Map(); // All edges whose targets equal their sources.
|
||||
@ -1186,6 +1192,13 @@ function getEdgeColour(edge: LinkObject) {
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
} else if (edgeTarget === node) {
|
||||
ctx.save();
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = nodeColourDefaultFinal.value();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
} else if (node === selection || node === rightSelection) {
|
||||
ctx.save();
|
||||
ctx.lineCap = 'round';
|
||||
@ -1207,9 +1220,37 @@ function getEdgeColour(edge: LinkObject) {
|
||||
ctx.fillText(wfNode.text, wfNode.x, wfNode.y);
|
||||
}
|
||||
})
|
||||
.onNodeDrag((node: NodeObject, delta: { x: number, y: number }) => {
|
||||
edgeTarget = null;
|
||||
if (!(node instanceof WF.WFGhostNode)) return;
|
||||
const fineTuningThreshold = 0;
|
||||
if (Math.sqrt(Math.round(Math.abs(delta.x * delta.y))) > fineTuningThreshold) return;
|
||||
for (const node2 of workflow.states) {
|
||||
if (!(node2 instanceof WF.WFNode)) continue;
|
||||
if (Math.sqrt(Math.pow(node.x - node2.x, 2) + Math.pow(node.y - node2.y, 2)) <= 2*node2.val) {
|
||||
edgeTarget = node2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
console.log('close:', edgeTarget);
|
||||
|
||||
})
|
||||
.onNodeDragEnd((node: NodeObject) => {
|
||||
node.fx = node.x;
|
||||
node.fy = node.y;
|
||||
if (node instanceof WF.WFGhostNode && edgeTarget) {
|
||||
var edgesFrom : WF.WFEdge[] = [];
|
||||
var edgesTo : WF.WFEdge[] = [];
|
||||
workflow.actions.forEach(edge => {
|
||||
edge.source === node && edgesFrom.push(edge);
|
||||
edge.target === node && edgesTo.push(edge);
|
||||
});
|
||||
if (!(edgesFrom || edgesTo)) throw new Error('Could not find an edge for the dragged ghost node');
|
||||
edgesFrom.forEach(edge => edge.source = <WF.WFNode>edgeTarget);
|
||||
edgesTo.forEach(edge => edge.target = <WF.WFNode>edgeTarget);
|
||||
removeState(node);
|
||||
updateGraph();
|
||||
}
|
||||
})
|
||||
.onNodeClick((node: NodeObject, _: MouseEvent) => {
|
||||
const wfNode = node as (WF.WFNode | WF.WFGhostNode);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user