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.view.select(null);
RED.view.redraw(true);
RED.palette.refresh();
RED.workspaces.refresh();

View File

@ -42,6 +42,7 @@ RED.view = (function() {
var activeNodes = [];
var activeLinks = [];
var activeFlowLinks = [];
var activeLinkNodes = {};
var selected_link = null,
mousedown_link = null,
@ -61,7 +62,8 @@ RED.view = (function() {
clickElapsed = 0,
scroll_position = [],
quickAddActive = false,
quickAddLink = null;
quickAddLink = null,
showAllLinkPorts = -1;
var clipboard = "";
@ -263,19 +265,41 @@ RED.view = (function() {
"stroke-width" : "1px"
});
}
var linkLayer = vis.append("g");
var dragGroup = vis.append("g");
var nodeLayer = vis.append("g");
var drag_lines = [];
function showDragLines(nodes) {
showAllLinkPorts = -1;
for (var i=0;i<nodes.length;i++) {
var node = nodes[i];
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);
}
if (showAllLinkPorts !== -1) {
activeNodes.forEach(function(n) {
if (n.type === "link in" || n.type === "link out") {
n.dirty = true;
}
})
}
}
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) {
var line = drag_lines.pop();
if (line.el) {
@ -657,10 +681,21 @@ RED.view = (function() {
mouse_mode = RED.state.QUICK_JOINING;
$(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;
RED.typeSearch.show({
x:d3.event.clientX-mainPos.left-node_width/2,
y:d3.event.clientY-mainPos.top-node_height/2,
filter: filter,
cancel: function() {
quickAddActive = false;
resetMouseVars();
@ -685,19 +720,54 @@ RED.view = (function() {
if (quickAddLink || drag_lines.length > 0) {
var drag_line = quickAddLink||drag_lines[0];
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_port = drag_line.port;
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;
dst = drag_line.node;
src_port = 0;
}
if (src !== null) {
var link = {source: src, sourcePort:src_port, target: dst};
RED.nodes.addLink(link);
historyEvent.links = [link];
if (drag_line.virtualLink) {
historyEvent = {
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();
if (!quickAddLink && drag_line.portType === PORT_TYPE_OUTPUT && nn.outputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
@ -1216,9 +1286,15 @@ RED.view = (function() {
var currentLinks = activeLinks;
var addedLinkLinks = {};
activeFlowLinks = [];
var activeLinkNodeIds = Object.keys(activeLinkNodes);
activeLinkNodeIds.forEach(function(n) {
activeLinkNodes[n].dirty = true;
})
activeLinkNodes = {};
for (var i=0;i<moving_set.length;i++) {
if (moving_set[i].n.type === "link out" || moving_set[i].n.type === "link in") {
var linkNode = moving_set[i].n;
activeLinkNodes[linkNode.id] = linkNode;
var offFlowLinks = {};
linkNode.links.forEach(function(id) {
var target = RED.nodes.node(id);
@ -1233,6 +1309,9 @@ RED.view = (function() {
link: true
});
addedLinkLinks[linkNode.id+":"+target.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
}
} else {
offFlowLinks[target.z] = offFlowLinks[target.z]||[];
@ -1248,6 +1327,8 @@ RED.view = (function() {
link: true
});
addedLinkLinks[target.id+":"+linkNode.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
}
} else {
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 {
selection.flows = workspaceSelection;
}
@ -1445,22 +1533,63 @@ RED.view = (function() {
RED.nodes.dirty(true);
}
}
if (selected_link) {
RED.nodes.removeLink(selected_link);
removedLinks.push(selected_link);
var historyEvent;
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);
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);
selected_link = null;
@ -1574,6 +1703,7 @@ RED.view = (function() {
if (d3.event.ctrlKey || d3.event.metaKey) {
mouse_mode = RED.state.QUICK_JOINING;
showDragLines([{node:mousedown_node,port:mousedown_port_index,portType:mousedown_port_type}]);
quickAddLink = null;
$(window).on('keyup',disableQuickJoinEventHandler);
}
}
@ -1584,7 +1714,16 @@ RED.view = (function() {
function portMouseUp(d,portType,portIndex) {
var i;
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
}
}
@ -1608,12 +1747,17 @@ RED.view = (function() {
}
var addedLinks = [];
var removedLinks = [];
var modifiedNodes = []; // joining link nodes
var select_link = null;
for (i=0;i<drag_lines.length;i++) {
if (drag_lines[i].link) {
removedLinks.push(drag_lines[i].link)
}
}
var linkEditEvents = [];
for (i=0;i<drag_lines.length;i++) {
if (portType != drag_lines[i].portType && mouseup_node !== drag_lines[i].node) {
var drag_line = drag_lines[i];
@ -1627,21 +1771,75 @@ RED.view = (function() {
dst = drag_line.node;
src_port = portIndex;
}
var existingLink = RED.nodes.filterLinks({source:src,target:dst,sourcePort: src_port}).length !== 0;
if (!existingLink) {
var link = {source: src, sourcePort:src_port, target: dst};
RED.nodes.addLink(link);
addedLinks.push(link);
var link = {source: src, sourcePort:src_port, target: dst};
if (drag_line.virtualLink) {
if (/^link (in|out)$/.test(src.type) && /^link (in|out)$/.test(dst.type)) {
if (src.links.indexOf(dst.id) === -1 && dst.links.indexOf(src.id) === -1) {
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) {
var historyEvent = {
t:"add",
links:addedLinks,
removedLinks: removedLinks,
dirty:RED.nodes.dirty()
};
if (addedLinks.length > 0 || removedLinks.length > 0 || modifiedNodes.length > 0) {
// console.log(addedLinks);
// console.log(removedLinks);
// console.log(modifiedNodes);
var historyEvent;
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) {
var subflowRefresh = RED.subflow.refresh(true);
if (subflowRefresh) {
@ -1657,7 +1855,7 @@ RED.view = (function() {
RED.nodes.dirty(true);
}
if (mouse_mode === RED.state.QUICK_JOINING) {
if (addedLinks.length > 0) {
if (addedLinks.length > 0 || modifiedNodes.length > 0) {
hideDragLines();
if (portType === PORT_TYPE_INPUT && d.outputs > 0) {
showDragLines([{node:d,port:0,portType:PORT_TYPE_OUTPUT}]);
@ -1666,6 +1864,11 @@ RED.view = (function() {
} else {
resetMouseVars();
}
selected_link = select_link;
mousedown_link = select_link;
if (select_link) {
updateSelection();
}
}
redraw();
return;
@ -1673,7 +1876,11 @@ RED.view = (function() {
resetMouseVars();
hideDragLines();
selected_link = null;
selected_link = select_link;
mousedown_link = select_link;
if (select_link) {
updateSelection();
}
redraw();
}
}
@ -1772,9 +1979,20 @@ RED.view = (function() {
});
return tooltip;
}
function portMouseOver(port,d,portType,portIndex) {
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)))) {
portLabelHoverTimeout = setTimeout(function() {
var tooltip = getPortLabel(d,portType,portIndex);
@ -1815,6 +2033,18 @@ RED.view = (function() {
return;
}
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);
}
@ -2033,12 +2263,12 @@ RED.view = (function() {
outer.attr("width", space_width*scaleFactor).attr("height", space_height*scaleFactor);
// 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 = {};
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();
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) {
@ -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 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();
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) {
@ -2143,11 +2373,11 @@ RED.view = (function() {
}
});
} else {
vis.selectAll(".subflowoutput").remove();
vis.selectAll(".subflowinput").remove();
nodeLayer.selectAll(".subflowoutput").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();
var nodeEnter = node.enter().insert("svg:g")
@ -2157,10 +2387,11 @@ RED.view = (function() {
nodeEnter.each(function(d,i) {
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);
var l = RED.utils.getNodeLabel(d);
if (isLink) {
if (hideLabel) {
d.w = node_height;
} else {
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("dy", ".35em")
.attr("text-anchor","start")
.classed("hidden",isLink);
.classed("hidden",hideLabel);
if (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) {
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;
//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 ow = d.w;
if (isLink) {
if (hideLabel) {
d.w = node_height;
} else {
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)});
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();
//nodeLabel.attr("x",30);
} else if (d.inputs === 1 && inputPorts.empty()) {
} else if (((isLink && (showAllLinkPorts===PORT_TYPE_INPUT||activeLinkNodes[d.id]))|| d.inputs === 1) && inputPorts.empty()) {
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)
.on("mousedown",function(d){portMouseDown(d,PORT_TYPE_INPUT,0);})
var inputGroupPorts;
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("mouseup",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;
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;
d.ports = d.ports || d3.range(numOutputs);
d._ports = thisNode.selectAll(".port_output").data(d.ports);
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)
.on("mousedown",(function(){var node = d; return function(d,i){portMouseDown(node,PORT_TYPE_OUTPUT,i);}})() )
if (d.type === "link out") {
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("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);}})() )
@ -2464,7 +2732,7 @@ RED.view = (function() {
}
return "node_label"+
(d._def.align?" node_label_"+d._def.align:"")+s;
}).classed("hidden",isLink);
}).classed("hidden",hideLabel);
if (d._def.icon) {
var icon = thisNode.select(".node_icon");
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,
function(d) {
return d.source.id+":"+d.sourcePort+":"+d.target.id+":"+d.target.i;
@ -2638,7 +2906,7 @@ RED.view = (function() {
});
link.exit().remove();
var links = vis.selectAll(".link_path");
var links = linkLayer.selectAll(".link_path");
links.each(function(d) {
var link = d3.select(this);
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;
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,
function(d) {
return d.node.id+":"+d.refresh
@ -2697,10 +2965,13 @@ RED.view = (function() {
var y = -(flows.length-1)*h/2;
var linkGroups = g.selectAll(".link_group").data(flows);
var enterLinkGroups = linkGroups.enter().append("g").attr("class","link_group")
.on('mouseover', function() { d3.select(this).classed('link_group_active',true)})
.on('mouseout', function() { d3.select(this).classed('link_group_active',false)})
.on('mouseover', function() { if (mouse_mode !== 0) { return } d3.select(this).classed('link_group_active',true)})
.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('mouseup', function(f) {
if (mouse_mode !== 0) {
return
}
d3.event.stopPropagation();
var targets = d.links[f];
RED.workspaces.show(f);
@ -2772,7 +3043,7 @@ RED.view = (function() {
linkGroups.exit().remove();
});
offLinks.exit().remove();
offLinks = vis.selectAll(".link_flow_link_g");
offLinks = linkLayer.selectAll(".link_flow_link_g");
offLinks.each(function(d) {
var s = 1;
if (d.node.type === "link in") {
@ -2785,7 +3056,7 @@ RED.view = (function() {
} else {
// JOINING - unselect any selected links
vis.selectAll(".link_selected").data(
linkLayer.selectAll(".link_selected").data(
activeLinks,
function(d) {
return d.source.id+":"+d.sourcePort+":"+d.target.id+":"+d.target.i;

View File

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