From a22f569ca0b9ecbbdb53599bcd1129226daa3cca Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 11 May 2022 23:13:12 +0100 Subject: [PATCH 1/2] Rework Junctions to be more node like in their event handling --- .../@node-red/editor-client/src/js/ui/view.js | 117 +++++++++--------- .../editor-client/src/sass/flow.scss | 28 +++++ 2 files changed, 86 insertions(+), 59 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index f36562a20..cdd76a4d2 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -3231,52 +3231,16 @@ RED.view = (function() { port.classed("red-ui-flow-port-hovered",false); } - function junctionMouseOver(junction, d) { - junction.classed("red-ui-flow-junction-hovered",true); + function junctionMouseOver(junction, d, portType) { + var active = (portType === undefined) || + (mouse_mode !== RED.state.JOINING && mouse_mode !== RED.state.QUICK_JOINING) || + (drag_lines.length > 0 && drag_lines[0].portType !== portType && !drag_lines[0].virtualLink) + junction.classed("red-ui-flow-junction-hovered", active); } function junctionMouseOut(junction, d) { junction.classed("red-ui-flow-junction-hovered",false); } - function junctionMouseDown(junction, d, evt) { - if (RED.view.DEBUG) { console.warn("junctionMouseDown", d); } - evt = evt || d3.event; - d3.event = evt - if (evt === 1) { - return; - } - if (mouse_mode === RED.state.SELECTING_NODE) { - evt.stopPropagation(); - return; - } - if (mouse_mode == RED.state.QUICK_JOINING) { - d3.event.stopPropagation(); - return; - } - - // mousedown_node = d; - // mousedown_port_type = portType; - // mousedown_port_index = portIndex || 0; - if (mouse_mode !== RED.state.QUICK_JOINING && (evt.ctrlKey || evt.metaKey)) { - mouse_mode = RED.state.QUICK_JOINING; - document.body.style.cursor = "crosshair"; - showDragLines([{node:d,port:0,portType: PORT_TYPE_OUTPUT}]); - $(window).on('keyup',disableQuickJoinEventHandler); - } else if (event.button != 2) { - nodeMouseDown.call(junction[0][0],d) - // clearSelection(); - // movingSet.add(d); - // mousedown_node = d; - // mouse_mode = RED.state.MOVING; - // var mouse = d3.touches(junction[0][0])[0]||d3.mouse(junction[0][0]); - // mouse[0] += d.x-d.w/2; - // mouse[1] += d.y-d.h/2; - // prepareDrag(mouse); - } - evt.stopPropagation(); - evt.preventDefault(); - } - function prepareDrag(mouse) { mouse_mode = RED.state.MOVING; // Called when movingSet should be prepared to be dragged @@ -3436,6 +3400,9 @@ RED.view = (function() { return; } else if (mouse_mode === RED.state.SELECTING_NODE) { d3.event.stopPropagation(); + if (d.type === 'junction') { + return + } if (selectNodesOptions.single) { selectNodesOptions.done(d); return; @@ -3462,12 +3429,12 @@ RED.view = (function() { var now = Date.now(); clickElapsed = now-clickTime; clickTime = now; - dblClickPrimed = (lastClickNode == mousedown_node && + dblClickPrimed = lastClickNode == mousedown_node && (d3.event.touches || d3.event.button === 0) && !d3.event.shiftKey && !d3.event.altKey && - clickElapsed < dblClickInterval - ) - lastClickNode = mousedown_node; + clickElapsed < dblClickInterval && + d.type !== 'junction' + lastClickNode = mousedown_node; if (!d.selected && d.g /*&& !RED.nodes.group(d.g).selected*/) { var nodeGroup = RED.nodes.group(d.g); @@ -3593,9 +3560,9 @@ RED.view = (function() { clearSelection(); } var clickPosition = (d3.event.offsetX/scaleFactor - mousedown_node.x) - var edgeDelta = (mousedown_node.w/2) - Math.abs(clickPosition); + var edgeDelta = ((mousedown_node.w||10)/2) - Math.abs(clickPosition); var cnodes; - var targetEdgeDelta = mousedown_node.w > 30 ? 25 : 8; + var targetEdgeDelta = mousedown_node.w > 30 ? 25 : (mousedown_node.w > 0 ? 8 : 3); if (edgeDelta < targetEdgeDelta) { if (clickPosition < 0) { cnodes = [mousedown_node].concat(RED.nodes.getAllUpstreamNodes(mousedown_node)); @@ -3740,10 +3707,8 @@ RED.view = (function() { function portMouseOverProxy(e) { portMouseOver(d3.select(this), this.__data__,this.__portType__,this.__portIndex__, e); } function portMouseOutProxy(e) { portMouseOut(d3.select(this), this.__data__,this.__portType__,this.__portIndex__, e); } - function junctionMouseOverProxy(e) { junctionMouseOver(d3.select(this), this.__data__) } + function junctionMouseOverProxy(e) { junctionMouseOver(d3.select(this), this.__data__, this.__portType__) } function junctionMouseOutProxy(e) { junctionMouseOut(d3.select(this), this.__data__) } - function junctionMouseDownProxy(e) { junctionMouseDown(d3.select(this), this.__data__, e) } - function junctionMouseUpProxy(e) { junctionMouseUp(d3.select(this), this.__data__) } function linkMouseDown(d) { if (mouse_mode === RED.state.SELECTING_NODE) { @@ -4894,22 +4859,56 @@ RED.view = (function() { junctionBack.setAttribute("y",-5); junctionBack.setAttribute("width",10); junctionBack.setAttribute("height",10); - junctionBack.setAttribute("rx",5); - junctionBack.setAttribute("ry",5); + junctionBack.setAttribute("rx",3); + junctionBack.setAttribute("ry",3); junctionBack.__data__ = d; this.__junctionBack__ = junctionBack; contents.appendChild(junctionBack); + var junctionInput = document.createElementNS("http://www.w3.org/2000/svg","rect"); + junctionInput.setAttribute("class","red-ui-flow-junction-port red-ui-flow-junction-port-input"); + junctionInput.setAttribute("x",-5); + junctionInput.setAttribute("y",-5); + junctionInput.setAttribute("width",10); + junctionInput.setAttribute("height",10); + junctionInput.setAttribute("rx",3); + junctionInput.setAttribute("ry",3); + junctionInput.__data__ = d; + junctionInput.__portType__ = PORT_TYPE_INPUT; + junctionInput.__portIndex__ = 0; + this.__junctionInput__ = junctionOutput; + contents.appendChild(junctionInput); + junctionInput.addEventListener("mouseup", portMouseUpProxy); + junctionInput.addEventListener("mousedown", portMouseDownProxy); + + + this.__junctionInput__ = junctionInput; + contents.appendChild(junctionInput); + var junctionOutput = document.createElementNS("http://www.w3.org/2000/svg","rect"); + junctionOutput.setAttribute("class","red-ui-flow-junction-port red-ui-flow-junction-port-output"); + junctionOutput.setAttribute("x",-5); + junctionOutput.setAttribute("y",-5); + junctionOutput.setAttribute("width",10); + junctionOutput.setAttribute("height",10); + junctionOutput.setAttribute("rx",3); + junctionOutput.setAttribute("ry",3); + junctionOutput.__data__ = d; + junctionOutput.__portType__ = PORT_TYPE_OUTPUT; + junctionOutput.__portIndex__ = 0; + this.__junctionOutput__ = junctionOutput; + contents.appendChild(junctionOutput); + junctionOutput.addEventListener("mouseup", portMouseUpProxy); + junctionOutput.addEventListener("mousedown", portMouseDownProxy); + + junctionOutput.addEventListener("mouseover", junctionMouseOverProxy); + junctionOutput.addEventListener("mouseout", junctionMouseOutProxy); + junctionInput.addEventListener("mouseover", junctionMouseOverProxy); + junctionInput.addEventListener("mouseout", junctionMouseOutProxy); junctionBack.addEventListener("mouseover", junctionMouseOverProxy); junctionBack.addEventListener("mouseout", junctionMouseOutProxy); - junctionBack.addEventListener("mouseup", portMouseUpProxy); - junctionBack.addEventListener("mousedown", junctionMouseDownProxy); - // d3.select(junctionBack).on("mousedown", nodeMouseDown); - - this.__portType__ = PORT_TYPE_INPUT - this.__portIndex__ = 0 -// function portMouseUpProxy(e) { portMouseUp(this.__data__,this.__portType__,this.__portIndex__, e); } + // These handlers expect to be registered as d3 events + d3.select(junctionBack).on("mousedown", nodeMouseDown).on("mouseup", nodeMouseUp); junction[0][0].appendChild(contents); }) diff --git a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss index 91f80ac0c..712731eb6 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss @@ -379,11 +379,39 @@ g.red-ui-flow-link-unknown path.red-ui-flow-link-line { white-space: pre; @include disable-selection; } +.red-ui-flow-junction:hover { + .red-ui-flow-junction-background { + transform: scale(1.4); + stroke-width: 0.6; + } + .red-ui-flow-junction-port { + opacity: 1 + } + .red-ui-flow-junction-port-input { + transform: translate(-10px,0) + } + .red-ui-flow-junction-port-output { + transform: translate(10px,0) + } +} +.red-ui-flow-junction-port { + stroke: $node-border; + stroke-width: 1; + fill: $node-port-background; + cursor: crosshair; + transition: transform 0.1s; + opacity: 0; +} .red-ui-flow-junction-background { stroke: $node-border; stroke-width: 1; fill: $node-port-background; cursor: crosshair; + transform: scale(1); + transition: transform 0.1s; + &:hover { + + } } .red-ui-flow-junction-hovered { stroke: $port-selected-color; From f6aee816518958f94a92e417226b4edf50a3793d Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 12 May 2022 10:02:35 +0100 Subject: [PATCH 2/2] Hide junction ports whilst dragging nodes --- .../@node-red/editor-client/src/js/ui/view.js | 4 +++- .../@node-red/editor-client/src/sass/flow.scss | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index cdd76a4d2..04055b7f7 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -172,7 +172,8 @@ RED.view = (function() { length: function() { return set.length}, get: function(i) { return set[i] }, forEach: function(func) { set.forEach(func) }, - nodes: function() { return set.map(function(n) { return n.n })} + nodes: function() { return set.map(function(n) { return n.n })}, + has: function(node) { return setIds.has(node.id) } } return api; })(); @@ -4917,6 +4918,7 @@ RED.view = (function() { var junction = d3.select(this); this.setAttribute("transform", "translate(" + (d.x) + "," + (d.y) + ")"); if (d.dirty) { + junction.classed("red-ui-flow-junction-dragging", mouse_mode === RED.state.MOVING_ACTIVE && movingSet.has(d)) junction.classed("selected", !!d.selected) dirtyNodes[d.id] = d; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss index 712731eb6..2e6de1932 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss @@ -379,13 +379,19 @@ g.red-ui-flow-link-unknown path.red-ui-flow-link-line { white-space: pre; @include disable-selection; } -.red-ui-flow-junction:hover { +.red-ui-flow-junction-dragging { + .red-ui-flow-junction-background { + background: red !important + } +} +.red-ui-flow-junction:not(.red-ui-flow-junction-dragging):hover { .red-ui-flow-junction-background { transform: scale(1.4); stroke-width: 0.6; } .red-ui-flow-junction-port { - opacity: 1 + opacity: 1; + pointer-events: auto; } .red-ui-flow-junction-port-input { transform: translate(-10px,0) @@ -401,6 +407,7 @@ g.red-ui-flow-link-unknown path.red-ui-flow-link-line { cursor: crosshair; transition: transform 0.1s; opacity: 0; + pointer-events: none; } .red-ui-flow-junction-background { stroke: $node-border;