mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #2877 from node-red/select-tools
Add new select-* actions to editor
This commit is contained in:
commit
de24831fb9
@ -44,6 +44,9 @@
|
|||||||
"ctrl-z": "core:undo",
|
"ctrl-z": "core:undo",
|
||||||
"ctrl-y": "core:redo",
|
"ctrl-y": "core:redo",
|
||||||
"ctrl-a": "core:select-all-nodes",
|
"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",
|
"shift-?": "core:show-help",
|
||||||
"w": "core:scroll-view-up",
|
"w": "core:scroll-view-up",
|
||||||
"d": "core:scroll-view-right",
|
"d": "core:scroll-view-right",
|
||||||
|
@ -18,9 +18,11 @@ RED.nodes = (function() {
|
|||||||
var node_defs = {};
|
var node_defs = {};
|
||||||
var nodes = {};
|
var nodes = {};
|
||||||
var nodeTabMap = {};
|
var nodeTabMap = {};
|
||||||
|
var linkTabMap = {};
|
||||||
|
|
||||||
var configNodes = {};
|
var configNodes = {};
|
||||||
var links = [];
|
var links = [];
|
||||||
|
var nodeLinks = {};
|
||||||
var defaultWorkspace;
|
var defaultWorkspace;
|
||||||
var workspaces = {};
|
var workspaces = {};
|
||||||
var workspacesOrder =[];
|
var workspacesOrder =[];
|
||||||
@ -286,6 +288,9 @@ RED.nodes = (function() {
|
|||||||
n.i = nextId+1;
|
n.i = nextId+1;
|
||||||
}
|
}
|
||||||
nodes[n.id] = n;
|
nodes[n.id] = n;
|
||||||
|
if (!nodeLinks[n.id]) {
|
||||||
|
nodeLinks[n.id] = {in:[],out:[]};
|
||||||
|
}
|
||||||
if (nodeTabMap[n.z]) {
|
if (nodeTabMap[n.z]) {
|
||||||
nodeTabMap[n.z][n.id] = n;
|
nodeTabMap[n.z][n.id] = n;
|
||||||
} else {
|
} else {
|
||||||
@ -296,6 +301,22 @@ RED.nodes = (function() {
|
|||||||
}
|
}
|
||||||
function addLink(l) {
|
function addLink(l) {
|
||||||
links.push(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);
|
RED.events.emit("links:add",l);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,6 +341,7 @@ RED.nodes = (function() {
|
|||||||
} else if (id in nodes) {
|
} else if (id in nodes) {
|
||||||
node = nodes[id];
|
node = nodes[id];
|
||||||
delete nodes[id]
|
delete nodes[id]
|
||||||
|
delete nodeLinks[id];
|
||||||
if (nodeTabMap[node.z]) {
|
if (nodeTabMap[node.z]) {
|
||||||
delete nodeTabMap[node.z][node.id];
|
delete nodeTabMap[node.z][node.id];
|
||||||
}
|
}
|
||||||
@ -407,6 +429,24 @@ RED.nodes = (function() {
|
|||||||
var index = links.indexOf(l);
|
var index = links.indexOf(l);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
links.splice(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);
|
RED.events.emit("links:remove",l);
|
||||||
}
|
}
|
||||||
@ -414,6 +454,7 @@ RED.nodes = (function() {
|
|||||||
function addWorkspace(ws,targetIndex) {
|
function addWorkspace(ws,targetIndex) {
|
||||||
workspaces[ws.id] = ws;
|
workspaces[ws.id] = ws;
|
||||||
nodeTabMap[ws.id] = {};
|
nodeTabMap[ws.id] = {};
|
||||||
|
linkTabMap[ws.id] = [];
|
||||||
|
|
||||||
ws._def = RED.nodes.getType('tab');
|
ws._def = RED.nodes.getType('tab');
|
||||||
if (targetIndex === undefined) {
|
if (targetIndex === undefined) {
|
||||||
@ -437,6 +478,7 @@ RED.nodes = (function() {
|
|||||||
if (ws) {
|
if (ws) {
|
||||||
delete workspaces[id];
|
delete workspaces[id];
|
||||||
delete nodeTabMap[id];
|
delete nodeTabMap[id];
|
||||||
|
delete linkTabMap[id];
|
||||||
workspacesOrder.splice(workspacesOrder.indexOf(id),1);
|
workspacesOrder.splice(workspacesOrder.indexOf(id),1);
|
||||||
var i;
|
var i;
|
||||||
var node;
|
var node;
|
||||||
@ -502,6 +544,7 @@ RED.nodes = (function() {
|
|||||||
}
|
}
|
||||||
subflows[sf.id] = sf;
|
subflows[sf.id] = sf;
|
||||||
nodeTabMap[sf.id] = {};
|
nodeTabMap[sf.id] = {};
|
||||||
|
linkTabMap[sf.id] = [];
|
||||||
|
|
||||||
RED.nodes.registerType("subflow:"+sf.id, {
|
RED.nodes.registerType("subflow:"+sf.id, {
|
||||||
defaults:{
|
defaults:{
|
||||||
@ -574,29 +617,38 @@ RED.nodes = (function() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllFlowNodes(node) {
|
function getAllDownstreamNodes(node) {
|
||||||
var visited = {};
|
return getAllFlowNodes(node,'down');
|
||||||
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<childLinks.length;i++) {
|
|
||||||
var child = (childLinks[i].source === n)?childLinks[i].target:childLinks[i].source;
|
|
||||||
var id = child.id;
|
|
||||||
if (!id) {
|
|
||||||
id = child.direction+":"+child.i;
|
|
||||||
}
|
}
|
||||||
if (!visited[id]) {
|
function getAllUpstreamNodes(node) {
|
||||||
visited[id] = true;
|
return getAllFlowNodes(node,'up');
|
||||||
nns.push(child);
|
|
||||||
stack.push(child);
|
|
||||||
}
|
}
|
||||||
|
function getAllFlowNodes(node, direction) {
|
||||||
|
var selection = RED.view.selection();
|
||||||
|
var visited = new Set();
|
||||||
|
var nodes = [node];
|
||||||
|
while(nodes.length > 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);
|
||||||
}
|
}
|
||||||
return nns;
|
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) {
|
function convertWorkspace(n) {
|
||||||
var node = {};
|
var node = {};
|
||||||
@ -1884,9 +1936,37 @@ RED.nodes = (function() {
|
|||||||
}
|
}
|
||||||
function filterLinks(filter) {
|
function filterLinks(filter) {
|
||||||
var result = [];
|
var result = [];
|
||||||
|
var candidateLinks = [];
|
||||||
for (var n=0;n<links.length;n++) {
|
var hasCandidates = false;
|
||||||
var link = links[n];
|
var filterSZ = filter.source && filter.source.z;
|
||||||
|
var filterTZ = filter.target && filter.target.z;
|
||||||
|
var filterZ;
|
||||||
|
if (filterSZ || filterTZ) {
|
||||||
|
if (filterSZ === filterTZ) {
|
||||||
|
filterZ = filterSZ;
|
||||||
|
} else {
|
||||||
|
filterZ = (filterSZ === undefined)?filterTZ:filterSZ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filterZ) {
|
||||||
|
candidateLinks = linkTabMap[filterZ] || [];
|
||||||
|
hasCandidates = true;
|
||||||
|
} else if (filter.source && filter.source.hasOwnProperty("id")) {
|
||||||
|
if (nodeLinks[filter.source.id]) {
|
||||||
|
hasCandidates = true;
|
||||||
|
candidateLinks = candidateLinks.concat(nodeLinks[filter.source.id].out)
|
||||||
|
}
|
||||||
|
} else if (filter.target && filter.target.hasOwnProperty("id")) {
|
||||||
|
if (nodeLinks[filter.target.id]) {
|
||||||
|
hasCandidates = true;
|
||||||
|
candidateLinks = candidateLinks.concat(nodeLinks[filter.target.id].in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasCandidates) {
|
||||||
|
candidateLinks = links;
|
||||||
|
}
|
||||||
|
for (var n=0;n<candidateLinks.length;n++) {
|
||||||
|
var link = candidateLinks[n];
|
||||||
if (filter.source) {
|
if (filter.source) {
|
||||||
if (filter.source.hasOwnProperty("id") && link.source.id !== filter.source.id) {
|
if (filter.source.hasOwnProperty("id") && link.source.id !== filter.source.id) {
|
||||||
continue;
|
continue;
|
||||||
@ -1943,6 +2023,8 @@ RED.nodes = (function() {
|
|||||||
nodes = {};
|
nodes = {};
|
||||||
links = [];
|
links = [];
|
||||||
nodeTabMap = {};
|
nodeTabMap = {};
|
||||||
|
linkTabMap = {};
|
||||||
|
nodeLinks = {};
|
||||||
configNodes = {};
|
configNodes = {};
|
||||||
workspacesOrder = [];
|
workspacesOrder = [];
|
||||||
groups = {};
|
groups = {};
|
||||||
@ -1968,16 +2050,6 @@ RED.nodes = (function() {
|
|||||||
RED.sidebar.info.refresh();
|
RED.sidebar.info.refresh();
|
||||||
|
|
||||||
RED.events.emit("workspace:clear");
|
RED.events.emit("workspace:clear");
|
||||||
|
|
||||||
// var node_defs = {};
|
|
||||||
// var nodes = {};
|
|
||||||
// var configNodes = {};
|
|
||||||
// var links = [];
|
|
||||||
// var defaultWorkspace;
|
|
||||||
// var workspaces = {};
|
|
||||||
// var workspacesOrder =[];
|
|
||||||
// var subflows = {};
|
|
||||||
// var loadedFlowVersion = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addGroup(group) {
|
function addGroup(group) {
|
||||||
@ -2184,6 +2256,8 @@ RED.nodes = (function() {
|
|||||||
identifyImportConflicts: identifyImportConflicts,
|
identifyImportConflicts: identifyImportConflicts,
|
||||||
|
|
||||||
getAllFlowNodes: getAllFlowNodes,
|
getAllFlowNodes: getAllFlowNodes,
|
||||||
|
getAllUpstreamNodes: getAllUpstreamNodes,
|
||||||
|
getAllDownstreamNodes: getAllDownstreamNodes,
|
||||||
createExportableNodeSet: createExportableNodeSet,
|
createExportableNodeSet: createExportableNodeSet,
|
||||||
createCompleteNodeSet: createCompleteNodeSet,
|
createCompleteNodeSet: createCompleteNodeSet,
|
||||||
updateConfigNodeUsers: updateConfigNodeUsers,
|
updateConfigNodeUsers: updateConfigNodeUsers,
|
||||||
|
@ -16,6 +16,27 @@
|
|||||||
|
|
||||||
RED.view.tools = (function() {
|
RED.view.tools = (function() {
|
||||||
|
|
||||||
|
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;
|
||||||
|
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() {
|
function alignToGrid() {
|
||||||
var selection = RED.view.selection();
|
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-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-down", function() { moveSelection(0,RED.view.gridSize());});
|
||||||
RED.actions.add("core:step-selection-left", function() { moveSelection(-RED.view.gridSize(),0);});
|
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
|
* Aligns all selected nodes to the current grid
|
||||||
|
@ -2992,6 +2992,7 @@ RED.view = (function() {
|
|||||||
enterActiveGroup(ag);
|
enterActiveGroup(ag);
|
||||||
activeGroup.selected = true;
|
activeGroup.selected = true;
|
||||||
}
|
}
|
||||||
|
console.log(d3.event);
|
||||||
var cnodes = RED.nodes.getAllFlowNodes(mousedown_node);
|
var cnodes = RED.nodes.getAllFlowNodes(mousedown_node);
|
||||||
for (var n=0;n<cnodes.length;n++) {
|
for (var n=0;n<cnodes.length;n++) {
|
||||||
if (!cnodes[n].selected) {
|
if (!cnodes[n].selected) {
|
||||||
@ -3080,7 +3081,19 @@ RED.view = (function() {
|
|||||||
// } else
|
// } else
|
||||||
if (d3.event.shiftKey) {
|
if (d3.event.shiftKey) {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
var cnodes = RED.nodes.getAllFlowNodes(mousedown_node);
|
var clickPosition = (d3.event.offsetX - mousedown_node.x)
|
||||||
|
var edgeDelta = (mousedown_node.w/2) - Math.abs(clickPosition);
|
||||||
|
var cnodes;
|
||||||
|
var targetEdgeDelta = mousedown_node.w > 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<cnodes.length;n++) {
|
for (var n=0;n<cnodes.length;n++) {
|
||||||
cnodes[n].selected = true;
|
cnodes[n].selected = true;
|
||||||
cnodes[n].dirty = true;
|
cnodes[n].dirty = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user