From 58c94b7773a6df2447cda03bbd835c3dbd1c260f Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Tue, 11 Jan 2022 00:16:24 +0000 Subject: [PATCH] Add core:detach-selected-nodes action --- .../@node-red/editor-client/src/js/history.js | 7 + .../@node-red/editor-client/src/js/nodes.js | 3 + .../editor-client/src/js/ui/state.js | 3 +- .../@node-red/editor-client/src/js/ui/view.js | 137 ++++++++++++++++-- 4 files changed, 140 insertions(+), 10 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/history.js b/packages/node_modules/@node-red/editor-client/src/js/history.js index 256500200..a8ffe581b 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/history.js +++ b/packages/node_modules/@node-red/editor-client/src/js/history.js @@ -684,6 +684,13 @@ RED.history = (function() { peek: function() { return undoHistory[undoHistory.length-1]; }, + replace: function(ev) { + if (undoHistory.length === 0) { + RED.history.push(ev); + } else { + undoHistory[undoHistory.length-1] = ev; + } + }, clear: function() { undoHistory = []; redoHistory = []; diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index 1904494f1..8feb741ac 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -2552,6 +2552,9 @@ RED.nodes = (function() { addLink: addLink, removeLink: removeLink, getNodeLinks: function(id, portType) { + if (typeof id !== 'string') { + id = id.id; + } if (nodeLinks[id]) { if (portType === 1) { // Return cloned arrays so they can be safely modified by caller diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/state.js b/packages/node_modules/@node-red/editor-client/src/js/ui/state.js index a2c9b762d..bb455d235 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/state.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/state.js @@ -27,5 +27,6 @@ RED.state = { PANNING: 10, SELECTING_NODE: 11, GROUP_DRAGGING: 12, - GROUP_RESIZE: 13 + GROUP_RESIZE: 13, + DETACHED_DRAGGING: 14 } 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 653dea0a4..582a7bca1 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 @@ -538,6 +538,8 @@ RED.view = (function() { RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();}); RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true});}); + RED.actions.add("core:detach-selected-nodes", function() { detachSelectedNodes() }) + RED.events.on("view:selection-changed", function(selection) { var hasSelection = (selection.nodes && selection.nodes.length > 0); var hasMultipleSelection = hasSelection && selection.nodes.length > 1; @@ -1384,7 +1386,7 @@ RED.view = (function() { return; } - if (mouse_mode != RED.state.QUICK_JOINING && mouse_mode != RED.state.IMPORT_DRAGGING && !mousedown_node && !mousedown_group && selectedLinks.length() === 0) { + if (mouse_mode != RED.state.QUICK_JOINING && mouse_mode != RED.state.IMPORT_DRAGGING && mouse_mode != RED.state.DETACHED_DRAGGING && !mousedown_node && !mousedown_group && selectedLinks.length() === 0) { return; } @@ -1489,7 +1491,7 @@ RED.view = (function() { RED.nodes.filterLinks({ target: node.n }).length === 0; } } - } else if (mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.IMPORT_DRAGGING) { + } else if (mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.IMPORT_DRAGGING || mouse_mode == RED.state.DETACHED_DRAGGING) { mousePos = mouse_position; var minX = 0; var minY = 0; @@ -1845,10 +1847,30 @@ RED.view = (function() { // movingSet.add(mousedown_node); // } // } - if (mouse_mode == RED.state.MOVING || mouse_mode == RED.state.MOVING_ACTIVE) { + if (mouse_mode == RED.state.MOVING || mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.DETACHED_DRAGGING) { // if (mousedown_node) { // delete mousedown_node.gSelected; // } + if (mouse_mode === RED.state.DETACHED_DRAGGING) { + var ns = []; + for (var j=0;j { + // var inboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_INPUT); + // var outboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT); + // inboundLinks.forEach(l => { + // if (!selectedNodes.has(l.source)) { + // allInboundLinks.push(l); + // } + // }) + // outboundLinks.forEach(l => { + // if (!selectedNodes.has(l.target)) { + // allOutboundLinks.push(l); + // } + // }) + // }) + + + var node = selection.nodes[0]; + // 1. find all the links attached to this node + var inboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_INPUT); + var outboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT); + + + // 2. delete all those links + inboundLinks.forEach(l => RED.nodes.removeLink(l)) + outboundLinks.forEach(l => RED.nodes.removeLink(l)) + + // 3. restore links from all source nodes to all target nodes + + var newLinks = []; + var createdLinkIds = new Set(); + + inboundLinks.forEach(inLink => { + outboundLinks.forEach(outLink => { + var linkId = inLink.source.id+":"+inLink.sourcePort+":"+outLink.target.id + if (!createdLinkIds.has(linkId)) { + createdLinkIds.add(linkId); + var link = { + source: inLink.source, + sourcePort: inLink.sourcePort, + target: outLink.target + }; + var existingLinks = RED.nodes.filterLinks(link) + if (existingLinks.length === 0) { + newLinks.push(link); + RED.nodes.addLink(link); + } + } + }) + }) + + var oldLinks = inboundLinks.concat(outboundLinks); + + if (oldLinks.length) { + RED.history.push({ + t: "multi", + events: [ + { t:'delete', links: oldLinks }, + { t:'add', links: newLinks } + ], + dirty: RED.nodes.dirty() + }) + RED.nodes.dirty(true) + } + + + prepareDrag([node.x,node.y]); + mouse_mode = RED.state.DETACHED_DRAGGING; + RED.view.redraw(true); + } + } + function calculateTextWidth(str, className) { var result = convertLineBreakCharacter(str); var width = 0; @@ -2956,10 +3060,13 @@ RED.view = (function() { msn.dx = msn.n.x-mouse[0]; msn.dy = msn.n.y-mouse[1]; } - - mouse_offset = d3.mouse(document.body); - if (isNaN(mouse_offset[0])) { - mouse_offset = d3.touches(document.body)[0]; + try { + mouse_offset = d3.mouse(document.body); + if (isNaN(mouse_offset[0])) { + mouse_offset = d3.touches(document.body)[0]; + } + } catch(err) { + mouse_offset = [0,0] } } @@ -3040,7 +3147,7 @@ RED.view = (function() { //var touch0 = d3.event; //var pos = [touch0.pageX,touch0.pageY]; //RED.touch.radialMenu.show(d3.select(this),pos); - if (mouse_mode == RED.state.IMPORT_DRAGGING) { + if (mouse_mode == RED.state.IMPORT_DRAGGING || mouse_mode == RED.state.DETACHED_DRAGGING) { var historyEvent = RED.history.peek(); if (activeSpliceLink) { // TODO: DRY - droppable/nodeMouseDown/canvasMouseUp @@ -3078,6 +3185,18 @@ RED.view = (function() { activeHoverGroup = null; } + if (mouse_mode == RED.state.DETACHED_DRAGGING) { + var ns = []; + for (var j=0;j