1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #4232 from node-red/wiring-tweak

Improve wiring for horizontally aligned nodes
This commit is contained in:
Nick O'Leary 2023-06-23 16:46:02 +01:00 committed by GitHub
commit 8bcaea7830
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 138 additions and 67 deletions

View File

@ -1033,7 +1033,7 @@ RED.view = (function() {
})
}
function generateLinkPath(origX,origY, destX, destY, sc) {
function generateLinkPath(origX,origY, destX, destY, sc, hasStatus = false) {
var dy = destY-origY;
var dx = destX-origX;
var delta = Math.sqrt(dy*dy+dx*dx);
@ -1050,62 +1050,110 @@ RED.view = (function() {
} else {
scale = 0.4-0.2*(Math.max(0,(node_width-Math.min(Math.abs(dx),Math.abs(dy)))/node_width));
}
function genCP(cp) {
return ` M ${cp[0]-5} ${cp[1]} h 10 M ${cp[0]} ${cp[1]-5} v 10 `
}
if (dx*sc > 0) {
return "M "+origX+" "+origY+
" C "+(origX+sc*(node_width*scale))+" "+(origY+scaleY*node_height)+" "+
(destX-sc*(scale)*node_width)+" "+(destY-scaleY*node_height)+" "+
destX+" "+destY
let cp = [
[(origX+sc*(node_width*scale)), (origY+scaleY*node_height)],
[(destX-sc*(scale)*node_width), (destY-scaleY*node_height)]
]
return `M ${origX} ${origY} C ${cp[0][0]} ${cp[0][1]} ${cp[1][0]} ${cp[1][1]} ${destX} ${destY}`
// + ` ${genCP(cp[0])} ${genCP(cp[1])}`
} else {
let topX, topY, bottomX, bottomY
let cp
let midX = Math.floor(destX-dx/2);
let midY = Math.floor(destY-dy/2);
if (Math.abs(dy) < 10) {
bottomY = Math.max(origY, destY) + (hasStatus?35:25)
let startCurveHeight = bottomY - origY
let endCurveHeight = bottomY - destY
cp = [
[ origX + sc*15 , origY ],
[ origX + sc*25 , origY + 5 ],
[ origX + sc*25 , origY + startCurveHeight/2 ],
var midX = Math.floor(destX-dx/2);
var midY = Math.floor(destY-dy/2);
//
if (dy === 0) {
midY = destY + node_height;
}
var cp_height = node_height/2;
var y1 = (destY + midY)/2
var topX =origX + sc*node_width*scale;
var topY = dy>0?Math.min(y1 - dy/2 , origY+cp_height):Math.max(y1 - dy/2 , origY-cp_height);
var bottomX = destX - sc*node_width*scale;
var bottomY = dy>0?Math.max(y1, destY-cp_height):Math.min(y1, destY+cp_height);
var x1 = (origX+topX)/2;
var scy = dy>0?1:-1;
var cp = [
// Orig -> Top
[x1,origY],
[topX,dy>0?Math.max(origY, topY-cp_height):Math.min(origY, topY+cp_height)],
// Top -> Mid
// [Mirror previous cp]
[x1,dy>0?Math.min(midY, topY+cp_height):Math.max(midY, topY-cp_height)],
// Mid -> Bottom
// [Mirror previous cp]
[bottomX,dy>0?Math.max(midY, bottomY-cp_height):Math.min(midY, bottomY+cp_height)],
// Bottom -> Dest
// [Mirror previous cp]
[(destX+bottomX)/2,destY]
];
if (cp[2][1] === topY+scy*cp_height) {
if (Math.abs(dy) < cp_height*10) {
cp[1][1] = topY-scy*cp_height/2;
cp[3][1] = bottomY-scy*cp_height/2;
}
cp[2][0] = topX;
}
return "M "+origX+" "+origY+
" C "+
cp[0][0]+" "+cp[0][1]+" "+
cp[1][0]+" "+cp[1][1]+" "+
topX+" "+topY+
" S "+
cp[2][0]+" "+cp[2][1]+" "+
midX+" "+midY+
" S "+
cp[3][0]+" "+cp[3][1]+" "+
bottomX+" "+bottomY+
" S "+
[ origX + sc*25 , origY + startCurveHeight - 5 ],
[ origX + sc*15 , origY + startCurveHeight ],
[ origX , origY + startCurveHeight ],
[ destX - sc*15, origY + startCurveHeight ],
[ destX - sc*25, origY + startCurveHeight - 5 ],
[ destX - sc*25, destY + endCurveHeight/2 ],
[ destX - sc*25, destY + 5 ],
[ destX - sc*15, destY ],
[ destX, destY ],
]
return "M "+origX+" "+origY+
" C "+
cp[0][0]+" "+cp[0][1]+" "+
cp[1][0]+" "+cp[1][1]+" "+
cp[2][0]+" "+cp[2][1]+" "+
" C " +
cp[3][0]+" "+cp[3][1]+" "+
cp[4][0]+" "+cp[4][1]+" "+
destX+" "+destY
cp[5][0]+" "+cp[5][1]+" "+
" h "+dx+
" C "+
cp[6][0]+" "+cp[6][1]+" "+
cp[7][0]+" "+cp[7][1]+" "+
cp[8][0]+" "+cp[8][1]+" "+
" C " +
cp[9][0]+" "+cp[9][1]+" "+
cp[10][0]+" "+cp[10][1]+" "+
cp[11][0]+" "+cp[11][1]+" "
// +genCP(cp[0])+genCP(cp[1])+genCP(cp[2])+genCP(cp[3])+genCP(cp[4])
// +genCP(cp[5])+genCP(cp[6])+genCP(cp[7])+genCP(cp[8])+genCP(cp[9])+genCP(cp[10])
} else {
var cp_height = node_height/2;
var y1 = (destY + midY)/2
topX = origX + sc*node_width*scale;
topY = dy>0?Math.min(y1 - dy/2 , origY+cp_height):Math.max(y1 - dy/2 , origY-cp_height);
bottomX = destX - sc*node_width*scale;
bottomY = dy>0?Math.max(y1, destY-cp_height):Math.min(y1, destY+cp_height);
var x1 = (origX+topX)/2;
var scy = dy>0?1:-1;
cp = [
// Orig -> Top
[x1,origY],
[topX,dy>0?Math.max(origY, topY-cp_height):Math.min(origY, topY+cp_height)],
// Top -> Mid
// [Mirror previous cp]
[x1,dy>0?Math.min(midY, topY+cp_height):Math.max(midY, topY-cp_height)],
// Mid -> Bottom
// [Mirror previous cp]
[bottomX,dy>0?Math.max(midY, bottomY-cp_height):Math.min(midY, bottomY+cp_height)],
// Bottom -> Dest
// [Mirror previous cp]
[(destX+bottomX)/2,destY]
];
if (cp[2][1] === topY+scy*cp_height) {
if (Math.abs(dy) < cp_height*10) {
cp[1][1] = topY-scy*cp_height/2;
cp[3][1] = bottomY-scy*cp_height/2;
}
cp[2][0] = topX;
}
return "M "+origX+" "+origY+
" C "+
cp[0][0]+" "+cp[0][1]+" "+
cp[1][0]+" "+cp[1][1]+" "+
topX+" "+topY+
" S "+
cp[2][0]+" "+cp[2][1]+" "+
midX+" "+midY+
" S "+
cp[3][0]+" "+cp[3][1]+" "+
bottomX+" "+bottomY+
" S "+
cp[4][0]+" "+cp[4][1]+" "+
destX+" "+destY
// +genCP(cp[0])+genCP(cp[1])+genCP(cp[2])+genCP(cp[3])+genCP(cp[4])
}
}
}
@ -1722,7 +1770,7 @@ RED.view = (function() {
var portY = -((numOutputs-1)/2)*13 +13*sourcePort;
var sc = (drag_line.portType === PORT_TYPE_OUTPUT)?1:-1;
drag_line.el.attr("d",generateLinkPath(drag_line.node.x+sc*drag_line.node.w/2,drag_line.node.y+portY,mousePos[0],mousePos[1],sc));
drag_line.el.attr("d",generateLinkPath(drag_line.node.x+sc*drag_line.node.w/2,drag_line.node.y+portY,mousePos[0],mousePos[1],sc, !!drag_line.node.status));
}
d3.event.preventDefault();
} else if (mouse_mode == RED.state.MOVING) {
@ -4112,21 +4160,27 @@ RED.view = (function() {
nodeEl.__statusGroup__.style.display = "none";
} else {
nodeEl.__statusGroup__.style.display = "inline";
let backgroundWidth = 12
var fill = status_colours[d.status.fill]; // Only allow our colours for now
if (d.status.shape == null && fill == null) {
backgroundWidth = 0
nodeEl.__statusShape__.style.display = "none";
nodeEl.__statusBackground__.setAttribute("x", 17)
nodeEl.__statusGroup__.setAttribute("transform","translate(-14,"+(d.h+3)+")");
} else {
nodeEl.__statusGroup__.setAttribute("transform","translate(3,"+(d.h+3)+")");
var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill;
nodeEl.__statusShape__.style.display = "inline";
nodeEl.__statusShape__.setAttribute("class","red-ui-flow-node-status "+statusClass);
nodeEl.__statusBackground__.setAttribute("x", 3)
}
if (d.status.hasOwnProperty('text')) {
nodeEl.__statusLabel__.textContent = d.status.text;
} else {
nodeEl.__statusLabel__.textContent = "";
}
const textSize = nodeEl.__statusLabel__.getBBox()
nodeEl.__statusBackground__.setAttribute('width', backgroundWidth + textSize.width + 6)
}
delete d.dirtyStatus;
}
@ -4532,17 +4586,30 @@ RED.view = (function() {
statusEl.style.display = "none";
node[0][0].__statusGroup__ = statusEl;
var statusRect = document.createElementNS("http://www.w3.org/2000/svg","rect");
statusRect.setAttribute("class","red-ui-flow-node-status");
statusRect.setAttribute("x",6);
statusRect.setAttribute("y",1);
statusRect.setAttribute("width",9);
statusRect.setAttribute("height",9);
statusRect.setAttribute("rx",2);
statusRect.setAttribute("ry",2);
statusRect.setAttribute("stroke-width","3");
statusEl.appendChild(statusRect);
node[0][0].__statusShape__ = statusRect;
var statusBackground = document.createElementNS("http://www.w3.org/2000/svg","rect");
statusBackground.setAttribute("class","red-ui-flow-node-status-background");
statusBackground.setAttribute("x",3);
statusBackground.setAttribute("y",-1);
statusBackground.setAttribute("width",200);
statusBackground.setAttribute("height",13);
statusBackground.setAttribute("rx",1);
statusBackground.setAttribute("ry",1);
statusEl.appendChild(statusBackground);
node[0][0].__statusBackground__ = statusBackground;
var statusIcon = document.createElementNS("http://www.w3.org/2000/svg","rect");
statusIcon.setAttribute("class","red-ui-flow-node-status");
statusIcon.setAttribute("x",6);
statusIcon.setAttribute("y",1);
statusIcon.setAttribute("width",9);
statusIcon.setAttribute("height",9);
statusIcon.setAttribute("rx",2);
statusIcon.setAttribute("ry",2);
statusIcon.setAttribute("stroke-width","3");
statusEl.appendChild(statusIcon);
node[0][0].__statusShape__ = statusIcon;
var statusLabel = document.createElementNS("http://www.w3.org/2000/svg","text");
statusLabel.setAttribute("class","red-ui-flow-node-status-label");
@ -5067,7 +5134,7 @@ RED.view = (function() {
// " C "+(d.x1+scale*node_width)+" "+(d.y1+scaleY*node_height)+" "+
// (d.x2-scale*node_width)+" "+(d.y2-scaleY*node_height)+" "+
// d.x2+" "+d.y2;
var path = generateLinkPath(d.x1,d.y1,d.x2,d.y2,1);
var path = generateLinkPath(d.x1,d.y1,d.x2,d.y2,1, !!(d.source.status || d.target.status));
if (/NaN/.test(path)) {
path = ""
}

View File

@ -304,7 +304,11 @@ g.red-ui-flow-node-selected {
stroke: var(--red-ui-node-status-colors-#{"" + $current-color});
}
}
.red-ui-flow-node-status-background {
stroke: none;
fill: var(--red-ui-view-background);
fill-opacity: 0.9;
}
.red-ui-flow-node-status-label {
@include disable-selection;
stroke-width: 0;