From d5314d2a8539bdac75e626e74c9877bc6b5b217d Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Tue, 16 Feb 2021 20:46:41 +0000 Subject: [PATCH 1/3] Add select-up/downstream-nodes action to editor --- .../editor-client/src/js/keymap.json | 2 + .../@node-red/editor-client/src/js/nodes.js | 93 ++++++++++++++++--- .../editor-client/src/js/ui/view-tools.js | 37 ++++++++ 3 files changed, 117 insertions(+), 15 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/keymap.json b/packages/node_modules/@node-red/editor-client/src/js/keymap.json index 5d8930ebf..aa357a832 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/keymap.json +++ b/packages/node_modules/@node-red/editor-client/src/js/keymap.json @@ -44,6 +44,8 @@ "ctrl-z": "core:undo", "ctrl-y": "core:redo", "ctrl-a": "core:select-all-nodes", + "alt-s u": "core:select-upstream-nodes", + "alt-s d": "core:select-downstream-nodes", "shift-?": "core:show-help", "w": "core:scroll-view-up", "d": "core:scroll-view-right", 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 236f7fa57..d39fe48ff 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 @@ -18,9 +18,11 @@ RED.nodes = (function() { var node_defs = {}; var nodes = {}; var nodeTabMap = {}; + var linkTabMap = {}; var configNodes = {}; var links = []; + var nodeLinks = {}; var defaultWorkspace; var workspaces = {}; var workspacesOrder =[]; @@ -33,7 +35,7 @@ RED.nodes = (function() { var initialLoad; var dirty = false; - +RED.ll = function() { return nodeLinks} function setDirty(d) { dirty = d; RED.events.emit("workspace:dirty",{dirty:dirty}); @@ -286,6 +288,9 @@ RED.nodes = (function() { n.i = nextId+1; } nodes[n.id] = n; + if (!nodeLinks[n.id]) { + nodeLinks[n.id] = {in:[],out:[]}; + } if (nodeTabMap[n.z]) { nodeTabMap[n.z][n.id] = n; } else { @@ -296,6 +301,22 @@ RED.nodes = (function() { } function addLink(l) { links.push(l); + if (l.source) { + // Possible the node hasn't been added yet + if (!nodeLinks[l.source.id]) { + nodeLinks[l.source.id] = {in:[],out:[]}; + } + nodeLinks[l.source.id].out.push(l); + } + if (l.target) { + if (!nodeLinks[l.target.id]) { + nodeLinks[l.target.id] = {in:[],out:[]}; + } + nodeLinks[l.target.id].in.push(l); + } + if (l.source.z === l.target.z && linkTabMap[l.source.z]) { + linkTabMap[l.source.z].push(l); + } RED.events.emit("links:add",l); } @@ -320,6 +341,7 @@ RED.nodes = (function() { } else if (id in nodes) { node = nodes[id]; delete nodes[id] + delete nodeLinks[id]; if (nodeTabMap[node.z]) { delete nodeTabMap[node.z][node.id]; } @@ -407,6 +429,24 @@ RED.nodes = (function() { var index = links.indexOf(l); if (index != -1) { links.splice(index,1); + if (l.source) { + var sIndex = nodeLinks[l.source.id].out.indexOf(l) + if (sIndex !== -1) { + nodeLinks[l.source.id].out.splice(sIndex,1) + } + } + if (l.target) { + var tIndex = nodeLinks[l.target.id].in.indexOf(l) + if (tIndex !== -1) { + nodeLinks[l.target.id].in.splice(tIndex,1) + } + } + if (l.source.z === l.target.z && linkTabMap[l.source.z]) { + index = linkTabMap[l.source.z].indexOf(l); + if (index !== -1) { + linkTabMap[l.source.z].splice(index,1) + } + } } RED.events.emit("links:remove",l); } @@ -414,6 +454,7 @@ RED.nodes = (function() { function addWorkspace(ws,targetIndex) { workspaces[ws.id] = ws; nodeTabMap[ws.id] = {}; + linkTabMap[ws.id] = []; ws._def = RED.nodes.getType('tab'); if (targetIndex === undefined) { @@ -437,6 +478,7 @@ RED.nodes = (function() { if (ws) { delete workspaces[id]; delete nodeTabMap[id]; + delete linkTabMap[id]; workspacesOrder.splice(workspacesOrder.indexOf(id),1); var i; var node; @@ -502,6 +544,7 @@ RED.nodes = (function() { } subflows[sf.id] = sf; nodeTabMap[sf.id] = {}; + linkTabMap[sf.id] = []; RED.nodes.registerType("subflow:"+sf.id, { defaults:{ @@ -581,7 +624,7 @@ RED.nodes = (function() { var stack = [node]; while(stack.length !== 0) { var n = stack.shift(); - var childLinks = links.filter(function(d) { return (d.source === n) || (d.target === n);}); + var childLinks = [].concat(nodeLinks[n.id].in).concat(nodeLinks[n.id].out); for (var i=0;i 0) { + var nodes = []; + selection.nodes.forEach(function(n) { + visited.add(n); + var filter = {}; + filter[from] = {id:n.id} + var initialLinks = RED.nodes.filterLinks(filter); + nodes = nodes.concat(initialLinks.map(function(n){return n[to]})); + }) + while(nodes.length > 0) { + var n = nodes.shift(); + visited.add(n); + var filter = {}; + filter[from] = {id:n.id} + var links = RED.nodes.filterLinks(filter); + links.forEach(function(l) { + if (!visited.has(l[to])) { + nodes.push(l[to]); + } + }) + } + RED.view.select({nodes:Array.from(visited)}); + } + } + function alignToGrid() { var selection = RED.view.selection(); if (selection.nodes) { @@ -206,6 +240,9 @@ RED.view.tools = (function() { RED.actions.add("core:step-selection-right", function() { moveSelection(RED.view.gridSize(),0);}); RED.actions.add("core:step-selection-down", function() { moveSelection(0,RED.view.gridSize());}); RED.actions.add("core:step-selection-left", function() { moveSelection(-RED.view.gridSize(),0);}); + + RED.actions.add("core:select-downstream-nodes", selectDownstream); + RED.actions.add("core:select-upstream-nodes", selectUpstream); }, /** * Aligns all selected nodes to the current grid From 35f788693da24f0fc25250a1f43de2603f715fe0 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Tue, 16 Feb 2021 21:16:21 +0000 Subject: [PATCH 2/3] Add select-connected action --- .../@node-red/editor-client/src/js/keymap.json | 2 ++ .../editor-client/src/js/ui/view-tools.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/node_modules/@node-red/editor-client/src/js/keymap.json b/packages/node_modules/@node-red/editor-client/src/js/keymap.json index aa357a832..13cefe691 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/keymap.json +++ b/packages/node_modules/@node-red/editor-client/src/js/keymap.json @@ -46,6 +46,8 @@ "ctrl-a": "core:select-all-nodes", "alt-s u": "core:select-upstream-nodes", "alt-s d": "core:select-downstream-nodes", + "alt-s c": "core:select-connected-nodes", + "alt-s d": "core:select-downstream-nodes", "shift-?": "core:show-help", "w": "core:scroll-view-up", "d": "core:scroll-view-right", diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js index 27078538d..e335d3907 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js @@ -16,6 +16,21 @@ RED.view.tools = (function() { + function selectAllConnected() { + console.log(args); + var selection = RED.view.selection(); + var visited = new Set(); + if (selection.nodes && selection.nodes.length > 0) { + selection.nodes.forEach(function(n) { + if (!visited.has(n)) { + var connected = RED.nodes.getAllFlowNodes(n); + connected.forEach(function(nn) { visited.add(nn) }) + } + }); + RED.view.select({nodes:Array.from(visited)}); + } + + } function selectDownstream() { selectStream('source','target') @@ -241,6 +256,7 @@ RED.view.tools = (function() { RED.actions.add("core:step-selection-down", function() { moveSelection(0,RED.view.gridSize());}); RED.actions.add("core:step-selection-left", function() { moveSelection(-RED.view.gridSize(),0);}); + RED.actions.add("core:select-connected-nodes", selectAllConnected); RED.actions.add("core:select-downstream-nodes", selectDownstream); RED.actions.add("core:select-upstream-nodes", selectUpstream); }, From ca75efcbaf06af700aec9b3387034ccb1afb243a Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 17 Feb 2021 17:32:55 +0000 Subject: [PATCH 3/3] Adds shift-click support for selecting up/down stream nodes --- .../editor-client/src/js/keymap.json | 1 - .../@node-red/editor-client/src/js/nodes.js | 57 +++++++++++-------- .../editor-client/src/js/ui/view-tools.js | 52 ++++------------- .../@node-red/editor-client/src/js/ui/view.js | 15 ++++- 4 files changed, 60 insertions(+), 65 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/keymap.json b/packages/node_modules/@node-red/editor-client/src/js/keymap.json index 13cefe691..cd6d2e384 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/keymap.json +++ b/packages/node_modules/@node-red/editor-client/src/js/keymap.json @@ -47,7 +47,6 @@ "alt-s u": "core:select-upstream-nodes", "alt-s d": "core:select-downstream-nodes", "alt-s c": "core:select-connected-nodes", - "alt-s d": "core:select-downstream-nodes", "shift-?": "core:show-help", "w": "core:scroll-view-up", "d": "core:scroll-view-right", 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 d39fe48ff..cc55565f2 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 @@ -35,7 +35,7 @@ RED.nodes = (function() { var initialLoad; var dirty = false; -RED.ll = function() { return nodeLinks} + function setDirty(d) { dirty = d; RED.events.emit("workspace:dirty",{dirty:dirty}); @@ -617,29 +617,38 @@ RED.ll = function() { return nodeLinks} return false; } - function getAllFlowNodes(node) { - var visited = {}; - visited[node.id] = true; - var nns = [node]; - var stack = [node]; - while(stack.length !== 0) { - var n = stack.shift(); - var childLinks = [].concat(nodeLinks[n.id].in).concat(nodeLinks[n.id].out); - for (var i=0;i 0) { + var n = nodes.shift(); + visited.add(n); + var links = []; + if (!direction || direction === 'up') { + links = links.concat(nodeLinks[n.id].in); + } + if (!direction || direction === 'down') { + links = links.concat(nodeLinks[n.id].out); + } + links.forEach(function(l) { + if (!visited.has(l.source)) { + nodes.push(l.source); + } + if (!visited.has(l.target)) { + nodes.push(l.target); + } + }) + } + return Array.from(visited); + } + function convertWorkspace(n) { var node = {}; @@ -2247,6 +2256,8 @@ RED.ll = function() { return nodeLinks} identifyImportConflicts: identifyImportConflicts, getAllFlowNodes: getAllFlowNodes, + getAllUpstreamNodes: getAllUpstreamNodes, + getAllDownstreamNodes: getAllDownstreamNodes, createExportableNodeSet: createExportableNodeSet, createCompleteNodeSet: createCompleteNodeSet, updateConfigNodeUsers: updateConfigNodeUsers, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js index e335d3907..2d5bbeb63 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js @@ -16,14 +16,20 @@ RED.view.tools = (function() { - function selectAllConnected() { - console.log(args); + function selectConnected(type) { var selection = RED.view.selection(); var visited = new Set(); if (selection.nodes && selection.nodes.length > 0) { selection.nodes.forEach(function(n) { if (!visited.has(n)) { - var connected = RED.nodes.getAllFlowNodes(n); + var connected; + if (type === 'all') { + connected = RED.nodes.getAllFlowNodes(n); + } else if (type === 'up') { + connected = RED.nodes.getAllUpstreamNodes(n); + } else if (type === 'down') { + connected = RED.nodes.getAllDownstreamNodes(n); + } connected.forEach(function(nn) { visited.add(nn) }) } }); @@ -32,40 +38,6 @@ RED.view.tools = (function() { } - function selectDownstream() { - selectStream('source','target') - } - function selectUpstream() { - selectStream('target','source') - } - function selectStream(from,to) { - var selection = RED.view.selection(); - var visited = new Set(); - if (selection.nodes && selection.nodes.length > 0) { - var nodes = []; - selection.nodes.forEach(function(n) { - visited.add(n); - var filter = {}; - filter[from] = {id:n.id} - var initialLinks = RED.nodes.filterLinks(filter); - nodes = nodes.concat(initialLinks.map(function(n){return n[to]})); - }) - while(nodes.length > 0) { - var n = nodes.shift(); - visited.add(n); - var filter = {}; - filter[from] = {id:n.id} - var links = RED.nodes.filterLinks(filter); - links.forEach(function(l) { - if (!visited.has(l[to])) { - nodes.push(l[to]); - } - }) - } - RED.view.select({nodes:Array.from(visited)}); - } - } - function alignToGrid() { var selection = RED.view.selection(); if (selection.nodes) { @@ -256,9 +228,9 @@ RED.view.tools = (function() { RED.actions.add("core:step-selection-down", function() { moveSelection(0,RED.view.gridSize());}); RED.actions.add("core:step-selection-left", function() { moveSelection(-RED.view.gridSize(),0);}); - RED.actions.add("core:select-connected-nodes", selectAllConnected); - RED.actions.add("core:select-downstream-nodes", selectDownstream); - RED.actions.add("core:select-upstream-nodes", selectUpstream); + RED.actions.add("core:select-connected-nodes", function() { selectConnected("all") }); + RED.actions.add("core:select-downstream-nodes", function() { selectConnected("down") }); + RED.actions.add("core:select-upstream-nodes", function() { selectConnected("up") }); }, /** * Aligns all selected nodes to the current grid 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 e6bf6476c..e00972148 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 @@ -2992,6 +2992,7 @@ RED.view = (function() { enterActiveGroup(ag); activeGroup.selected = true; } + console.log(d3.event); var cnodes = RED.nodes.getAllFlowNodes(mousedown_node); for (var n=0;n 30 ? 25 : 8; + if (edgeDelta < targetEdgeDelta) { + if (clickPosition < 0) { + cnodes = RED.nodes.getAllUpstreamNodes(mousedown_node); + } else { + cnodes = RED.nodes.getAllDownstreamNodes(mousedown_node); + } + } else { + cnodes = RED.nodes.getAllFlowNodes(mousedown_node); + } for (var n=0;n