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..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 @@ -44,6 +44,9 @@ "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", + "alt-s c": "core:select-connected-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..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 @@ -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 =[]; @@ -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:{ @@ -574,29 +617,38 @@ RED.nodes = (function() { 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 = links.filter(function(d) { return (d.source === n) || (d.target === n);}); - 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 = {}; @@ -1884,9 +1936,37 @@ RED.nodes = (function() { } function filterLinks(filter) { var result = []; - - for (var n=0;n 0) { + selection.nodes.forEach(function(n) { + if (!visited.has(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) }) + } + }); + RED.view.select({nodes:Array.from(visited)}); + } + + } function alignToGrid() { var selection = RED.view.selection(); @@ -206,6 +227,10 @@ 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-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