Support drag-wiring of link nodes

This commit is contained in:
Nick O'Leary 2018-12-18 10:57:53 +00:00
parent 84cc2ad0fa
commit 33dade0584
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
3 changed files with 342 additions and 70 deletions

View File

@ -296,6 +296,7 @@ RED.history = (function() {
}); });
RED.nodes.dirty(ev.dirty); RED.nodes.dirty(ev.dirty);
RED.view.select(null);
RED.view.redraw(true); RED.view.redraw(true);
RED.palette.refresh(); RED.palette.refresh();
RED.workspaces.refresh(); RED.workspaces.refresh();

View File

@ -42,6 +42,7 @@ RED.view = (function() {
var activeNodes = []; var activeNodes = [];
var activeLinks = []; var activeLinks = [];
var activeFlowLinks = []; var activeFlowLinks = [];
var activeLinkNodes = {};
var selected_link = null, var selected_link = null,
mousedown_link = null, mousedown_link = null,
@ -61,7 +62,8 @@ RED.view = (function() {
clickElapsed = 0, clickElapsed = 0,
scroll_position = [], scroll_position = [],
quickAddActive = false, quickAddActive = false,
quickAddLink = null; quickAddLink = null,
showAllLinkPorts = -1;
var clipboard = ""; var clipboard = "";
@ -263,19 +265,41 @@ RED.view = (function() {
"stroke-width" : "1px" "stroke-width" : "1px"
}); });
} }
var linkLayer = vis.append("g");
var dragGroup = vis.append("g"); var dragGroup = vis.append("g");
var nodeLayer = vis.append("g");
var drag_lines = []; var drag_lines = [];
function showDragLines(nodes) { function showDragLines(nodes) {
showAllLinkPorts = -1;
for (var i=0;i<nodes.length;i++) { for (var i=0;i<nodes.length;i++) {
var node = nodes[i]; var node = nodes[i];
node.el = dragGroup.append("svg:path").attr("class", "drag_line"); node.el = dragGroup.append("svg:path").attr("class", "drag_line");
if ((node.node.type === "link out" && node.portType === PORT_TYPE_OUTPUT) ||
(node.node.type === "link in" && node.portType === PORT_TYPE_INPUT)) {
node.el.attr("class","link_link drag_line");
node.virtualLink = true;
showAllLinkPorts = (node.portType === PORT_TYPE_OUTPUT)?PORT_TYPE_INPUT:PORT_TYPE_OUTPUT;
}
drag_lines.push(node); drag_lines.push(node);
} }
if (showAllLinkPorts !== -1) {
activeNodes.forEach(function(n) {
if (n.type === "link in" || n.type === "link out") {
n.dirty = true;
}
})
}
} }
function hideDragLines() { function hideDragLines() {
if (showAllLinkPorts !== -1) {
activeNodes.forEach(function(n) {
if (n.type === "link in" || n.type === "link out") {
n.dirty = true;
}
})
}
showAllLinkPorts = -1;
while(drag_lines.length) { while(drag_lines.length) {
var line = drag_lines.pop(); var line = drag_lines.pop();
if (line.el) { if (line.el) {
@ -657,10 +681,21 @@ RED.view = (function() {
mouse_mode = RED.state.QUICK_JOINING; mouse_mode = RED.state.QUICK_JOINING;
$(window).on('keyup',disableQuickJoinEventHandler); $(window).on('keyup',disableQuickJoinEventHandler);
} }
var filter = undefined;
if (drag_lines.length > 0) {
if (drag_lines[0].virtualLink) {
filter = {type:drag_lines[0].node.type === 'link in'?'link out':'link in'}
} else if (drag_lines[0].portType === PORT_TYPE_OUTPUT) {
filter = {input:true}
} else {
filter = {output:true}
}
}
quickAddActive = true; quickAddActive = true;
RED.typeSearch.show({ RED.typeSearch.show({
x:d3.event.clientX-mainPos.left-node_width/2, x:d3.event.clientX-mainPos.left-node_width/2,
y:d3.event.clientY-mainPos.top-node_height/2, y:d3.event.clientY-mainPos.top-node_height/2,
filter: filter,
cancel: function() { cancel: function() {
quickAddActive = false; quickAddActive = false;
resetMouseVars(); resetMouseVars();
@ -685,19 +720,54 @@ RED.view = (function() {
if (quickAddLink || drag_lines.length > 0) { if (quickAddLink || drag_lines.length > 0) {
var drag_line = quickAddLink||drag_lines[0]; var drag_line = quickAddLink||drag_lines[0];
var src = null,dst,src_port; var src = null,dst,src_port;
if (drag_line.portType === PORT_TYPE_OUTPUT && nn.inputs > 0) { if (drag_line.portType === PORT_TYPE_OUTPUT && (nn.inputs > 0 || drag_line.virtualLink) ) {
src = drag_line.node; src = drag_line.node;
src_port = drag_line.port; src_port = drag_line.port;
dst = nn; dst = nn;
} else if (drag_line.portType === PORT_TYPE_INPUT && nn.outputs > 0) { } else if (drag_line.portType === PORT_TYPE_INPUT && (nn.outputs > 0 || drag_line.virtualLink)) {
src = nn; src = nn;
dst = drag_line.node; dst = drag_line.node;
src_port = 0; src_port = 0;
} }
if (src !== null) { if (src !== null) {
var link = {source: src, sourcePort:src_port, target: dst}; if (drag_line.virtualLink) {
RED.nodes.addLink(link); historyEvent = {
historyEvent.links = [link]; t:'multi',
events: [historyEvent]
}
var oldSrcLinks = $.extend(true,{},{v:src.links}).v
var oldDstLinks = $.extend(true,{},{v:dst.links}).v
src.links.push(dst.id);
dst.links.push(src.id);
src.dirty = true;
dst.dirty = true;
historyEvent.events.push({
t:'edit',
node: src,
dirty: RED.nodes.dirty(),
changed: src.changed,
changes: {
links:oldSrcLinks
}
});
historyEvent.events.push({
t:'edit',
node: dst,
dirty: RED.nodes.dirty(),
changed: dst.changed,
changes: {
links:oldDstLinks
}
});
src.changed = true;
dst.changed = true;
} else {
var link = {source: src, sourcePort:src_port, target: dst};
RED.nodes.addLink(link);
historyEvent.links = [link];
}
hideDragLines(); hideDragLines();
if (!quickAddLink && drag_line.portType === PORT_TYPE_OUTPUT && nn.outputs > 0) { if (!quickAddLink && drag_line.portType === PORT_TYPE_OUTPUT && nn.outputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]); showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
@ -1216,9 +1286,15 @@ RED.view = (function() {
var currentLinks = activeLinks; var currentLinks = activeLinks;
var addedLinkLinks = {}; var addedLinkLinks = {};
activeFlowLinks = []; activeFlowLinks = [];
var activeLinkNodeIds = Object.keys(activeLinkNodes);
activeLinkNodeIds.forEach(function(n) {
activeLinkNodes[n].dirty = true;
})
activeLinkNodes = {};
for (var i=0;i<moving_set.length;i++) { for (var i=0;i<moving_set.length;i++) {
if (moving_set[i].n.type === "link out" || moving_set[i].n.type === "link in") { if (moving_set[i].n.type === "link out" || moving_set[i].n.type === "link in") {
var linkNode = moving_set[i].n; var linkNode = moving_set[i].n;
activeLinkNodes[linkNode.id] = linkNode;
var offFlowLinks = {}; var offFlowLinks = {};
linkNode.links.forEach(function(id) { linkNode.links.forEach(function(id) {
var target = RED.nodes.node(id); var target = RED.nodes.node(id);
@ -1233,6 +1309,9 @@ RED.view = (function() {
link: true link: true
}); });
addedLinkLinks[linkNode.id+":"+target.id] = true; addedLinkLinks[linkNode.id+":"+target.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
} }
} else { } else {
offFlowLinks[target.z] = offFlowLinks[target.z]||[]; offFlowLinks[target.z] = offFlowLinks[target.z]||[];
@ -1248,6 +1327,8 @@ RED.view = (function() {
link: true link: true
}); });
addedLinkLinks[target.id+":"+linkNode.id] = true; addedLinkLinks[target.id+":"+linkNode.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
} }
} else { } else {
offFlowLinks[target.z] = offFlowLinks[target.z]||[]; offFlowLinks[target.z] = offFlowLinks[target.z]||[];
@ -1269,6 +1350,13 @@ RED.view = (function() {
} }
} }
} }
if (activeFlowLinks.length === 0 && selected_link !== null && selected_link.link) {
activeLinks.push(selected_link);
activeLinkNodes[selected_link.source.id] = selected_link.source;
selected_link.source.dirty = true;
activeLinkNodes[selected_link.target.id] = selected_link.target;
selected_link.target.dirty = true;
}
} else { } else {
selection.flows = workspaceSelection; selection.flows = workspaceSelection;
} }
@ -1445,22 +1533,63 @@ RED.view = (function() {
RED.nodes.dirty(true); RED.nodes.dirty(true);
} }
} }
if (selected_link) { var historyEvent;
RED.nodes.removeLink(selected_link);
removedLinks.push(selected_link); if (selected_link && selected_link.link) {
var sourceId = selected_link.source.id;
var targetId = selected_link.target.id;
var sourceIdIndex = selected_link.target.links.indexOf(sourceId);
var targetIdIndex = selected_link.source.links.indexOf(targetId);
historyEvent = {
t:"multi",
events: [
{
t: "edit",
node: selected_link.source,
changed: selected_link.source.changed,
changes: {
links: $.extend(true,{},{v:selected_link.source.links}).v
}
},
{
t: "edit",
node: selected_link.target,
changed: selected_link.target.changed,
changes: {
links: $.extend(true,{},{v:selected_link.target.links}).v
}
}
],
dirty:RED.nodes.dirty()
}
selected_link.source.changed = true;
selected_link.target.changed = true;
selected_link.target.links.splice(sourceIdIndex,1);
selected_link.source.links.splice(targetIdIndex,1);
selected_link.source.dirty = true;
selected_link.target.dirty = true;
} else {
if (selected_link) {
RED.nodes.removeLink(selected_link);
removedLinks.push(selected_link);
}
RED.nodes.dirty(true); RED.nodes.dirty(true);
historyEvent = {
t:"delete",
nodes:removedNodes,
links:removedLinks,
subflowOutputs:removedSubflowOutputs,
subflowInputs:removedSubflowInputs,
subflow: {
instances: subflowInstances
},
dirty:startDirty
};
} }
var historyEvent = {
t:"delete",
nodes:removedNodes,
links:removedLinks,
subflowOutputs:removedSubflowOutputs,
subflowInputs:removedSubflowInputs,
subflow: {
instances: subflowInstances
},
dirty:startDirty
};
RED.history.push(historyEvent); RED.history.push(historyEvent);
selected_link = null; selected_link = null;
@ -1574,6 +1703,7 @@ RED.view = (function() {
if (d3.event.ctrlKey || d3.event.metaKey) { if (d3.event.ctrlKey || d3.event.metaKey) {
mouse_mode = RED.state.QUICK_JOINING; mouse_mode = RED.state.QUICK_JOINING;
showDragLines([{node:mousedown_node,port:mousedown_port_index,portType:mousedown_port_type}]); showDragLines([{node:mousedown_node,port:mousedown_port_index,portType:mousedown_port_type}]);
quickAddLink = null;
$(window).on('keyup',disableQuickJoinEventHandler); $(window).on('keyup',disableQuickJoinEventHandler);
} }
} }
@ -1584,7 +1714,16 @@ RED.view = (function() {
function portMouseUp(d,portType,portIndex) { function portMouseUp(d,portType,portIndex) {
var i; var i;
if (mouse_mode === RED.state.QUICK_JOINING && drag_lines.length > 0) { if (mouse_mode === RED.state.QUICK_JOINING && drag_lines.length > 0) {
if (drag_lines[0].node===d) { if (drag_lines[0].node === d) {
// Cannot quick-join to self
return
}
if (drag_lines[0].virtualLink &&
(
(drag_lines[0].node.type === 'link in' && d.type !== 'link out') ||
(drag_lines[0].node.type === 'link out' && d.type !== 'link in')
)
) {
return return
} }
} }
@ -1608,12 +1747,17 @@ RED.view = (function() {
} }
var addedLinks = []; var addedLinks = [];
var removedLinks = []; var removedLinks = [];
var modifiedNodes = []; // joining link nodes
var select_link = null;
for (i=0;i<drag_lines.length;i++) { for (i=0;i<drag_lines.length;i++) {
if (drag_lines[i].link) { if (drag_lines[i].link) {
removedLinks.push(drag_lines[i].link) removedLinks.push(drag_lines[i].link)
} }
} }
var linkEditEvents = [];
for (i=0;i<drag_lines.length;i++) { for (i=0;i<drag_lines.length;i++) {
if (portType != drag_lines[i].portType && mouseup_node !== drag_lines[i].node) { if (portType != drag_lines[i].portType && mouseup_node !== drag_lines[i].node) {
var drag_line = drag_lines[i]; var drag_line = drag_lines[i];
@ -1627,21 +1771,75 @@ RED.view = (function() {
dst = drag_line.node; dst = drag_line.node;
src_port = portIndex; src_port = portIndex;
} }
var existingLink = RED.nodes.filterLinks({source:src,target:dst,sourcePort: src_port}).length !== 0; var link = {source: src, sourcePort:src_port, target: dst};
if (!existingLink) { if (drag_line.virtualLink) {
var link = {source: src, sourcePort:src_port, target: dst}; if (/^link (in|out)$/.test(src.type) && /^link (in|out)$/.test(dst.type)) {
RED.nodes.addLink(link); if (src.links.indexOf(dst.id) === -1 && dst.links.indexOf(src.id) === -1) {
addedLinks.push(link); var oldSrcLinks = $.extend(true,{},{v:src.links}).v
var oldDstLinks = $.extend(true,{},{v:dst.links}).v
src.links.push(dst.id);
dst.links.push(src.id);
src.dirty = true;
dst.dirty = true;
modifiedNodes.push(src);
modifiedNodes.push(dst);
link.link = true;
activeLinks.push(link);
activeLinkNodes[src.id] = src;
activeLinkNodes[dst.id] = dst;
select_link = link;
linkEditEvents.push({
t:'edit',
node: src,
dirty: RED.nodes.dirty(),
changed: src.changed,
changes: {
links:oldSrcLinks
}
});
linkEditEvents.push({
t:'edit',
node: dst,
dirty: RED.nodes.dirty(),
changed: dst.changed,
changes: {
links:oldDstLinks
}
});
src.changed = true;
dst.changed = true;
}
}
} else {
var existingLink = RED.nodes.filterLinks({source:src,target:dst,sourcePort: src_port}).length !== 0;
if (!existingLink) {
RED.nodes.addLink(link);
addedLinks.push(link);
}
} }
} }
} }
if (addedLinks.length > 0 || removedLinks.length > 0) { if (addedLinks.length > 0 || removedLinks.length > 0 || modifiedNodes.length > 0) {
var historyEvent = { // console.log(addedLinks);
t:"add", // console.log(removedLinks);
links:addedLinks, // console.log(modifiedNodes);
removedLinks: removedLinks, var historyEvent;
dirty:RED.nodes.dirty() if (modifiedNodes.length > 0) {
}; historyEvent = {
t:"multi",
events: linkEditEvents,
dirty:RED.nodes.dirty()
};
} else {
historyEvent = {
t:"add",
links:addedLinks,
removedLinks: removedLinks,
dirty:RED.nodes.dirty()
};
}
if (activeSubflow) { if (activeSubflow) {
var subflowRefresh = RED.subflow.refresh(true); var subflowRefresh = RED.subflow.refresh(true);
if (subflowRefresh) { if (subflowRefresh) {
@ -1657,7 +1855,7 @@ RED.view = (function() {
RED.nodes.dirty(true); RED.nodes.dirty(true);
} }
if (mouse_mode === RED.state.QUICK_JOINING) { if (mouse_mode === RED.state.QUICK_JOINING) {
if (addedLinks.length > 0) { if (addedLinks.length > 0 || modifiedNodes.length > 0) {
hideDragLines(); hideDragLines();
if (portType === PORT_TYPE_INPUT && d.outputs > 0) { if (portType === PORT_TYPE_INPUT && d.outputs > 0) {
showDragLines([{node:d,port:0,portType:PORT_TYPE_OUTPUT}]); showDragLines([{node:d,port:0,portType:PORT_TYPE_OUTPUT}]);
@ -1666,6 +1864,11 @@ RED.view = (function() {
} else { } else {
resetMouseVars(); resetMouseVars();
} }
selected_link = select_link;
mousedown_link = select_link;
if (select_link) {
updateSelection();
}
} }
redraw(); redraw();
return; return;
@ -1673,7 +1876,11 @@ RED.view = (function() {
resetMouseVars(); resetMouseVars();
hideDragLines(); hideDragLines();
selected_link = null; selected_link = select_link;
mousedown_link = select_link;
if (select_link) {
updateSelection();
}
redraw(); redraw();
} }
} }
@ -1772,9 +1979,20 @@ RED.view = (function() {
}); });
return tooltip; return tooltip;
} }
function portMouseOver(port,d,portType,portIndex) { function portMouseOver(port,d,portType,portIndex) {
clearTimeout(portLabelHoverTimeout); clearTimeout(portLabelHoverTimeout);
var active = (mouse_mode!=RED.state.JOINING || (drag_lines.length > 0 && drag_lines[0].portType !== portType)); var active = (mouse_mode!=RED.state.JOINING && mouse_mode != RED.state.QUICK_JOINING) || // Not currently joining - all ports active
(
drag_lines.length > 0 && // Currently joining
drag_lines[0].portType !== portType && // INPUT->OUTPUT OUTPUT->INPUT
(
!drag_lines[0].virtualLink || // Not a link wire
(drag_lines[0].node.type === 'link in' && d.type === 'link out') ||
(drag_lines[0].node.type === 'link out' && d.type === 'link in')
)
)
if (active && ((portType === PORT_TYPE_INPUT && ((d._def && d._def.inputLabels)||d.inputLabels)) || (portType === PORT_TYPE_OUTPUT && ((d._def && d._def.outputLabels)||d.outputLabels)))) { if (active && ((portType === PORT_TYPE_INPUT && ((d._def && d._def.inputLabels)||d.inputLabels)) || (portType === PORT_TYPE_OUTPUT && ((d._def && d._def.outputLabels)||d.outputLabels)))) {
portLabelHoverTimeout = setTimeout(function() { portLabelHoverTimeout = setTimeout(function() {
var tooltip = getPortLabel(d,portType,portIndex); var tooltip = getPortLabel(d,portType,portIndex);
@ -1815,6 +2033,18 @@ RED.view = (function() {
return; return;
} }
var direction = d._def? (d.inputs > 0 ? 1: 0) : (d.direction == "in" ? 0: 1) var direction = d._def? (d.inputs > 0 ? 1: 0) : (d.direction == "in" ? 0: 1)
if (mouse_mode === RED.state.JOINING || mouse_mode === RED.state.QUICK_JOINING) {
if (drag_lines.length > 0) {
if (drag_lines[0].virtualLink) {
if (d.type === 'link in') {
direction = 1;
} else if (d.type === 'link out') {
direction = 0;
}
}
}
}
portMouseUp(d, direction, 0); portMouseUp(d, direction, 0);
} }
@ -2033,12 +2263,12 @@ RED.view = (function() {
outer.attr("width", space_width*scaleFactor).attr("height", space_height*scaleFactor); outer.attr("width", space_width*scaleFactor).attr("height", space_height*scaleFactor);
// Don't bother redrawing nodes if we're drawing links // Don't bother redrawing nodes if we're drawing links
if (mouse_mode != RED.state.JOINING) { if (showAllLinkPorts !== -1 || mouse_mode != RED.state.JOINING) {
var dirtyNodes = {}; var dirtyNodes = {};
if (activeSubflow) { if (activeSubflow) {
var subflowOutputs = vis.selectAll(".subflowoutput").data(activeSubflow.out,function(d,i){ return d.id;}); var subflowOutputs = nodeLayer.selectAll(".subflowoutput").data(activeSubflow.out,function(d,i){ return d.id;});
subflowOutputs.exit().remove(); subflowOutputs.exit().remove();
var outGroup = subflowOutputs.enter().insert("svg:g").attr("class","node subflowoutput").attr("transform",function(d) { return "translate("+(d.x-20)+","+(d.y-20)+")"}); var outGroup = subflowOutputs.enter().insert("svg:g").attr("class","node subflowoutput").attr("transform",function(d) { return "translate("+(d.x-20)+","+(d.y-20)+")"});
outGroup.each(function(d,i) { outGroup.each(function(d,i) {
@ -2081,7 +2311,7 @@ RED.view = (function() {
outGroup.append("svg:text").attr("class","port_label").attr("x",20).attr("y",8).style("font-size","10px").text("output"); outGroup.append("svg:text").attr("class","port_label").attr("x",20).attr("y",8).style("font-size","10px").text("output");
outGroup.append("svg:text").attr("class","port_label port_index").attr("x",20).attr("y",24).text(function(d,i){ return i+1}); outGroup.append("svg:text").attr("class","port_label port_index").attr("x",20).attr("y",24).text(function(d,i){ return i+1});
var subflowInputs = vis.selectAll(".subflowinput").data(activeSubflow.in,function(d,i){ return d.id;}); var subflowInputs = nodeLayer.selectAll(".subflowinput").data(activeSubflow.in,function(d,i){ return d.id;});
subflowInputs.exit().remove(); subflowInputs.exit().remove();
var inGroup = subflowInputs.enter().insert("svg:g").attr("class","node subflowinput").attr("transform",function(d) { return "translate("+(d.x-20)+","+(d.y-20)+")"}); var inGroup = subflowInputs.enter().insert("svg:g").attr("class","node subflowinput").attr("transform",function(d) { return "translate("+(d.x-20)+","+(d.y-20)+")"});
inGroup.each(function(d,i) { inGroup.each(function(d,i) {
@ -2143,11 +2373,11 @@ RED.view = (function() {
} }
}); });
} else { } else {
vis.selectAll(".subflowoutput").remove(); nodeLayer.selectAll(".subflowoutput").remove();
vis.selectAll(".subflowinput").remove(); nodeLayer.selectAll(".subflowinput").remove();
} }
var node = vis.selectAll(".nodegroup").data(activeNodes,function(d){return d.id}); var node = nodeLayer.selectAll(".nodegroup").data(activeNodes,function(d){return d.id});
node.exit().remove(); node.exit().remove();
var nodeEnter = node.enter().insert("svg:g") var nodeEnter = node.enter().insert("svg:g")
@ -2157,10 +2387,11 @@ RED.view = (function() {
nodeEnter.each(function(d,i) { nodeEnter.each(function(d,i) {
var node = d3.select(this); var node = d3.select(this);
var isLink = d.hasOwnProperty('l')?!d.l : (d.type === "link in" || d.type === "link out") var isLink = (d.type === "link in" || d.type === "link out")
var hideLabel = d.hasOwnProperty('l')?!d.l : isLink;
node.attr("id",d.id); node.attr("id",d.id);
var l = RED.utils.getNodeLabel(d); var l = RED.utils.getNodeLabel(d);
if (isLink) { if (hideLabel) {
d.w = node_height; d.w = node_height;
} else { } else {
d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "node_label", 50)+(d._def.inputs>0?7:0))/20)) ); d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "node_label", 50)+(d._def.inputs>0?7:0))/20)) );
@ -2332,7 +2563,7 @@ RED.view = (function() {
.attr("x", 38) .attr("x", 38)
.attr("dy", ".35em") .attr("dy", ".35em")
.attr("text-anchor","start") .attr("text-anchor","start")
.classed("hidden",isLink); .classed("hidden",hideLabel);
if (d._def.align) { if (d._def.align) {
text.attr("class","node_label node_label_"+d._def.align); text.attr("class","node_label node_label_"+d._def.align);
@ -2360,13 +2591,14 @@ RED.view = (function() {
node.each(function(d,i) { node.each(function(d,i) {
if (d.dirty) { if (d.dirty) {
var isLink = d.hasOwnProperty('l')?!d.l : (d.type === "link in" || d.type === "link out") var isLink = (d.type === "link in" || d.type === "link out")
var hideLabel = d.hasOwnProperty('l')?!d.l : isLink;
dirtyNodes[d.id] = d; dirtyNodes[d.id] = d;
//if (d.x < -50) deleteSelection(); // Delete nodes if dragged back to palette //if (d.x < -50) deleteSelection(); // Delete nodes if dragged back to palette
if (/*!isLink &&*/ d.resize) { if (d.resize) {
var l = RED.utils.getNodeLabel(d); var l = RED.utils.getNodeLabel(d);
var ow = d.w; var ow = d.w;
if (isLink) { if (hideLabel) {
d.w = node_height; d.w = node_height;
} else { } else {
d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "node_label", 50)+(d._def.inputs>0?7:0))/20)) ); d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "node_label", 50)+(d._def.inputs>0?7:0))/20)) );
@ -2396,13 +2628,24 @@ RED.view = (function() {
//thisNode.selectAll(".node_icon_shade_border_right").attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2)}); //thisNode.selectAll(".node_icon_shade_border_right").attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2)});
var inputPorts = thisNode.selectAll(".port_input"); var inputPorts = thisNode.selectAll(".port_input");
if (d.inputs === 0 && !inputPorts.empty()) { if (isLink && showAllLinkPorts === -1 && !activeLinkNodes[d.id] && d.inputs === 0 && !inputPorts.empty()) {
inputPorts.remove(); inputPorts.remove();
//nodeLabel.attr("x",30); } else if (((isLink && (showAllLinkPorts===PORT_TYPE_INPUT||activeLinkNodes[d.id]))|| d.inputs === 1) && inputPorts.empty()) {
} else if (d.inputs === 1 && inputPorts.empty()) {
var inputGroup = thisNode.append("g").attr("class","port_input"); var inputGroup = thisNode.append("g").attr("class","port_input");
inputGroup.append("rect").attr("class","port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) var inputGroupPorts;
.on("mousedown",function(d){portMouseDown(d,PORT_TYPE_INPUT,0);})
if (d.type === "link in") {
inputGroupPorts = inputGroup.append("circle")
.attr("cx",-1).attr("cy",5)
.attr("r",5)
.attr("class","port link_port")
// inputGroupPorts = inputGroup.append("path")
// .attr("d","M 4 -1 h -3 a 6 6 0 1 0 0 12 h 3")
// .attr("class","port link_port")
} else {
inputGroupPorts = inputGroup.append("rect").attr("class","port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10)
}
inputGroupPorts.on("mousedown",function(d){portMouseDown(d,PORT_TYPE_INPUT,0);})
.on("touchstart",function(d){portMouseDown(d,PORT_TYPE_INPUT,0);}) .on("touchstart",function(d){portMouseDown(d,PORT_TYPE_INPUT,0);})
.on("mouseup",function(d){portMouseUp(d,PORT_TYPE_INPUT,0);} ) .on("mouseup",function(d){portMouseUp(d,PORT_TYPE_INPUT,0);} )
.on("touchend",function(d){portMouseUp(d,PORT_TYPE_INPUT,0);} ) .on("touchend",function(d){portMouseUp(d,PORT_TYPE_INPUT,0);} )
@ -2411,13 +2654,38 @@ RED.view = (function() {
} }
var numOutputs = d.outputs; var numOutputs = d.outputs;
if (isLink && d.type === "link out") {
if (showAllLinkPorts===PORT_TYPE_OUTPUT || activeLinkNodes[d.id]) {
d.ports = [0];
numOutputs = 1;
} else {
d.ports = [];
numOutputs = 0;
}
}
var y = (d.h/2)-((numOutputs-1)/2)*13; var y = (d.h/2)-((numOutputs-1)/2)*13;
d.ports = d.ports || d3.range(numOutputs); d.ports = d.ports || d3.range(numOutputs);
d._ports = thisNode.selectAll(".port_output").data(d.ports); d._ports = thisNode.selectAll(".port_output").data(d.ports);
var output_group = d._ports.enter().append("g").attr("class","port_output"); var output_group = d._ports.enter().append("g").attr("class","port_output");
var output_group_ports;
output_group.append("rect").attr("class","port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) if (d.type === "link out") {
.on("mousedown",(function(){var node = d; return function(d,i){portMouseDown(node,PORT_TYPE_OUTPUT,i);}})() ) output_group_ports = output_group.append("circle")
.attr("cx",11).attr("cy",5)
.attr("r",5)
.attr("class","port link_port")
// output_group_ports = output_group.append("path")
// .attr("d","M 6 -1 h 3 a 6 6 0 1 1 0 12 h -3")
// .attr("class","port link_port")
} else {
output_group_ports = output_group.append("rect")
.attr("class","port")
.attr("rx",3).attr("ry",3)
.attr("width",10)
.attr("height",10)
}
output_group_ports.on("mousedown",(function(){var node = d; return function(d,i){portMouseDown(node,PORT_TYPE_OUTPUT,i);}})() )
.on("touchstart",(function(){var node = d; return function(d,i){portMouseDown(node,PORT_TYPE_OUTPUT,i);}})() ) .on("touchstart",(function(){var node = d; return function(d,i){portMouseDown(node,PORT_TYPE_OUTPUT,i);}})() )
.on("mouseup",(function(){var node = d; return function(d,i){portMouseUp(node,PORT_TYPE_OUTPUT,i);}})() ) .on("mouseup",(function(){var node = d; return function(d,i){portMouseUp(node,PORT_TYPE_OUTPUT,i);}})() )
.on("touchend",(function(){var node = d; return function(d,i){portMouseUp(node,PORT_TYPE_OUTPUT,i);}})() ) .on("touchend",(function(){var node = d; return function(d,i){portMouseUp(node,PORT_TYPE_OUTPUT,i);}})() )
@ -2464,7 +2732,7 @@ RED.view = (function() {
} }
return "node_label"+ return "node_label"+
(d._def.align?" node_label_"+d._def.align:"")+s; (d._def.align?" node_label_"+d._def.align:"")+s;
}).classed("hidden",isLink); }).classed("hidden",hideLabel);
if (d._def.icon) { if (d._def.icon) {
var icon = thisNode.select(".node_icon"); var icon = thisNode.select(".node_icon");
var faIcon = thisNode.select(".fa-lg"); var faIcon = thisNode.select(".fa-lg");
@ -2592,7 +2860,7 @@ RED.view = (function() {
} }
}); });
var link = vis.selectAll(".link").data( var link = linkLayer.selectAll(".link").data(
activeLinks, activeLinks,
function(d) { function(d) {
return d.source.id+":"+d.sourcePort+":"+d.target.id+":"+d.target.i; return d.source.id+":"+d.sourcePort+":"+d.target.id+":"+d.target.i;
@ -2638,7 +2906,7 @@ RED.view = (function() {
}); });
link.exit().remove(); link.exit().remove();
var links = vis.selectAll(".link_path"); var links = linkLayer.selectAll(".link_path");
links.each(function(d) { links.each(function(d) {
var link = d3.select(this); var link = d3.select(this);
if (d.added || d===selected_link || d.selected || dirtyNodes[d.source.id] || dirtyNodes[d.target.id]) { if (d.added || d===selected_link || d.selected || dirtyNodes[d.source.id] || dirtyNodes[d.target.id]) {
@ -2666,7 +2934,7 @@ RED.view = (function() {
delete d.added; delete d.added;
return d.target.type == "unknown" || d.source.type == "unknown" return d.target.type == "unknown" || d.source.type == "unknown"
}); });
var offLinks = vis.selectAll(".link_flow_link_g").data( var offLinks = linkLayer.selectAll(".link_flow_link_g").data(
activeFlowLinks, activeFlowLinks,
function(d) { function(d) {
return d.node.id+":"+d.refresh return d.node.id+":"+d.refresh
@ -2697,10 +2965,13 @@ RED.view = (function() {
var y = -(flows.length-1)*h/2; var y = -(flows.length-1)*h/2;
var linkGroups = g.selectAll(".link_group").data(flows); var linkGroups = g.selectAll(".link_group").data(flows);
var enterLinkGroups = linkGroups.enter().append("g").attr("class","link_group") var enterLinkGroups = linkGroups.enter().append("g").attr("class","link_group")
.on('mouseover', function() { d3.select(this).classed('link_group_active',true)}) .on('mouseover', function() { if (mouse_mode !== 0) { return } d3.select(this).classed('link_group_active',true)})
.on('mouseout', function() { d3.select(this).classed('link_group_active',false)}) .on('mouseout', function() {if (mouse_mode !== 0) { return } d3.select(this).classed('link_group_active',false)})
.on('mousedown', function() { d3.event.preventDefault(); d3.event.stopPropagation(); }) .on('mousedown', function() { d3.event.preventDefault(); d3.event.stopPropagation(); })
.on('mouseup', function(f) { .on('mouseup', function(f) {
if (mouse_mode !== 0) {
return
}
d3.event.stopPropagation(); d3.event.stopPropagation();
var targets = d.links[f]; var targets = d.links[f];
RED.workspaces.show(f); RED.workspaces.show(f);
@ -2772,7 +3043,7 @@ RED.view = (function() {
linkGroups.exit().remove(); linkGroups.exit().remove();
}); });
offLinks.exit().remove(); offLinks.exit().remove();
offLinks = vis.selectAll(".link_flow_link_g"); offLinks = linkLayer.selectAll(".link_flow_link_g");
offLinks.each(function(d) { offLinks.each(function(d) {
var s = 1; var s = 1;
if (d.node.type === "link in") { if (d.node.type === "link in") {
@ -2785,7 +3056,7 @@ RED.view = (function() {
} else { } else {
// JOINING - unselect any selected links // JOINING - unselect any selected links
vis.selectAll(".link_selected").data( linkLayer.selectAll(".link_selected").data(
activeLinks, activeLinks,
function(d) { function(d) {
return d.source.id+":"+d.sourcePort+":"+d.target.id+":"+d.target.i; return d.source.id+":"+d.sourcePort+":"+d.target.id+":"+d.target.i;

View File

@ -194,8 +194,8 @@
} }
.port_hovered { .port_hovered {
stroke: $port-selected-color; stroke: $port-selected-color !important;
fill: $port-selected-color; fill: $port-selected-color !important;
} }
.port_quick_link { .port_quick_link {
@ -211,7 +211,7 @@
} }
.drag_line { .drag_line {
stroke: $node-selected-color; stroke: $node-selected-color !important;
stroke-width: 3; stroke-width: 3;
fill: none; fill: none;
pointer-events: none; pointer-events: none;
@ -236,10 +236,10 @@
stroke: $link-link-color; stroke: $link-link-color;
fill: none; fill: none;
stroke-dasharray: 15,2; stroke-dasharray: 15,2;
pointer-events: none; // pointer-events: none;
} }
.link_port { .link_port {
fill: #fff; fill: #eee;
stroke: $link-link-color; stroke: $link-link-color;
stroke-width: 1; stroke-width: 1;
} }