Subflow: Add labels to OUTPUT nodes

This commit is contained in:
ralphwetzel 2022-01-13 23:33:06 +01:00
parent 7cd3e49f04
commit 28f91685ce
2 changed files with 175 additions and 24 deletions

View File

@ -501,6 +501,12 @@
}
var v = $(this).val();
hasNonBlankLabel = hasNonBlankLabel || v!== "";
// mark changed output port labels as dirty
if (node.type === "subflow" && node.outputLabels[index] !== v) {
node.out[index].dirty = true;
}
newValue[index] = v;
});
@ -509,6 +515,12 @@
changes.outputLabels = node.outputLabels;
node.outputLabels = newValue;
changed = true;
// trigger redraw of dirty port labels
if (node.type === "subflow") {
RED.view.redraw();
}
}
return changed;
}

View File

@ -3728,28 +3728,88 @@ RED.view = (function() {
if (activeSubflow) {
var subflowOutputs = nodeLayer.selectAll(".red-ui-flow-subflow-port-output").data(activeSubflow.out,function(d,i){ return d.id;});
subflowOutputs.exit().remove();
var outGroup = subflowOutputs.enter().insert("svg:g").attr("class","red-ui-flow-node red-ui-flow-subflow-port-output").attr("transform",function(d) { return "translate("+(d.x-20)+","+(d.y-20)+")"});
var outGroup = subflowOutputs.enter().insert("svg:g").attr("class","red-ui-flow-node red-ui-flow-subflow-port-output")
outGroup.each(function(d,i) {
d.w=40;
d.h=40;
var node = d3.select(this);
var nodeContents = document.createDocumentFragment();
d.h = 40;
d.resize = true;
d.dirty = true;
var mainRect = document.createElementNS("http://www.w3.org/2000/svg","rect");
mainRect.__data__ = d;
mainRect.setAttribute("class", "red-ui-flow-subflow-port");
mainRect.setAttribute("rx", 8);
mainRect.setAttribute("ry", 8);
mainRect.setAttribute("width", 40);
mainRect.setAttribute("height", 40);
node[0][0].__mainRect__ = mainRect;
d3.select(mainRect)
.on("mouseup",nodeMouseUp)
.on("mousedown",nodeMouseDown)
.on("touchstart",nodeTouchStart)
.on("touchend",nodeTouchEnd)
nodeContents.appendChild(mainRect);
var output_groupEl = document.createElementNS("http://www.w3.org/2000/svg","g");
output_groupEl.setAttribute("x",0);
output_groupEl.setAttribute("y",0);
var output_output = document.createElementNS("http://www.w3.org/2000/svg","text");
output_output.setAttribute("class","red-ui-flow-port-label");
output_output.style["font-size"] = "10px";
output_output.textContent = "output";
output_groupEl.appendChild(output_output);
node[0][0].__outputOutput__ = output_output;
var output_number = document.createElementNS("http://www.w3.org/2000/svg","text");
output_number.setAttribute("class","red-ui-flow-port-label red-ui-flow-port-index");
output_number.setAttribute("x",0);
output_number.setAttribute("y",0);
output_number.textContent = d.i+1;
output_groupEl.appendChild(output_number);
node[0][0].__outputNumber__ = output_number;
var output_border = document.createElementNS("http://www.w3.org/2000/svg","path");
output_border.setAttribute("d","M 40 1 l 0 38")
output_border.setAttribute("class", "red-ui-flow-node-icon-shade-border")
output_groupEl.appendChild(output_border);
node[0][0].__outputBorder__ = output_border;
nodeContents.appendChild(output_groupEl);
var text = document.createElementNS("http://www.w3.org/2000/svg","g");
text.setAttribute("class","red-ui-flow-port-label");
text.setAttribute("transform","translate(38,0)");
text.setAttribute('style', 'fill : #888'); // hard coded here!
node[0][0].__textGroup__ = text;
nodeContents.append(text);
var portEl = document.createElementNS("http://www.w3.org/2000/svg","g");
portEl.setAttribute('transform','translate(-5,15)')
var port = document.createElementNS("http://www.w3.org/2000/svg","rect");
port.setAttribute("class","red-ui-flow-port");
port.setAttribute("rx",3);
port.setAttribute("ry",3);
port.setAttribute("width",10);
port.setAttribute("height",10);
portEl.appendChild(port);
d3.select(port)
.on("mousedown", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);} )
.on("touchstart", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);d3.event.preventDefault();} )
.on("mouseup", function(d,i){portMouseUp(d,PORT_TYPE_INPUT,0);})
.on("touchend",function(d,i){portMouseUp(d,PORT_TYPE_INPUT,0);d3.event.preventDefault();} )
.on("mouseover",function(d){portMouseOver(d3.select(this),d,PORT_TYPE_INPUT,0);})
.on("mouseout",function(d){portMouseOut(d3.select(this),d,PORT_TYPE_INPUT,0);});
node[0][0].__port__ = portEl
nodeContents.appendChild(portEl);
node[0][0].appendChild(nodeContents);
});
outGroup.append("rect").attr("class","red-ui-flow-subflow-port").attr("rx",8).attr("ry",8).attr("width",40).attr("height",40)
// TODO: This is exactly the same set of handlers used for regular nodes - DRY
.on("mouseup",nodeMouseUp)
.on("mousedown",nodeMouseDown)
.on("touchstart",nodeTouchStart)
.on("touchend",nodeTouchEnd)
outGroup.append("g").attr('transform','translate(-5,15)').append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10)
.on("mousedown", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);} )
.on("touchstart", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);d3.event.preventDefault();} )
.on("mouseup", function(d,i){portMouseUp(d,PORT_TYPE_INPUT,0);})
.on("touchend",function(d,i){portMouseUp(d,PORT_TYPE_INPUT,0);d3.event.preventDefault();} )
.on("mouseover",function(d){portMouseOver(d3.select(this),d,PORT_TYPE_INPUT,0);})
.on("mouseout",function(d){portMouseOut(d3.select(this),d,PORT_TYPE_INPUT,0);});
outGroup.append("svg:text").attr("class","red-ui-flow-port-label").attr("x",20).attr("y",12).style("font-size","10px").text("output");
outGroup.append("svg:text").attr("class","red-ui-flow-port-label red-ui-flow-port-index").attr("x",20).attr("y",28).text(function(d,i){ return i+1});
var subflowInputs = nodeLayer.selectAll(".red-ui-flow-subflow-port-input").data(activeSubflow.in,function(d,i){ return d.id;});
subflowInputs.exit().remove();
@ -3802,11 +3862,90 @@ RED.view = (function() {
subflowOutputs.each(function(d,i) {
if (d.dirty) {
var output = d3.select(this);
output.classed("red-ui-flow-node-selected",function(d) { return d.selected; })
output.selectAll(".red-ui-flow-port-index").text(function(d){ return d.i+1});
output.attr("transform", function(d) { return "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")"; });
var port_height = 40;
var self = this;
var thisNode = d3.select(this);
dirtyNodes[d.id] = d;
var label = getPortLabel(activeSubflow, PORT_TYPE_OUTPUT, d.i) || "";
var hideLabel = (label.length < 1)
var labelParts;
if (d.resize || this.__hideLabel__ !== hideLabel || this.__label__ !== label) {
labelParts = getLabelParts(label, "red-ui-flow-node-label");
if (labelParts.lines.length !== this.__labelLineCount__ || this.__label__ !== label) {
d.resize = true;
}
this.__label__ = label;
this.__labelLineCount__ = labelParts.lines.length;
if (hideLabel) {
d.h = Math.max(port_height,(d.outputs || 0) * 15);
} else {
d.h = Math.max(6+24*labelParts.lines.length,(d.outputs || 0) * 15, port_height);
}
this.__hideLabel__ = hideLabel;
}
if (d.resize) {
var ow = d.w;
if (hideLabel) {
d.w = port_height;
} else {
d.w = Math.max(port_height,20*(Math.ceil((labelParts.width+50+7)/20)) );
}
if (ow !== undefined) {
d.x += (d.w-ow)/2;
}
d.resize = false;
}
this.setAttribute("transform", "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")");
// This might be the first redraw after a node has been click-dragged to start a move.
// So its selected state might have changed since the last redraw.
this.classList.toggle("red-ui-flow-node-selected", !!d.selected )
if (mouse_mode != RED.state.MOVING_ACTIVE) {
this.classList.toggle("red-ui-flow-node-disabled", d.d === true);
this.__mainRect__.setAttribute("width", d.w)
this.__mainRect__.setAttribute("height", d.h)
this.__mainRect__.classList.toggle("red-ui-flow-node-highlighted",!!d.highlighted );
if (labelParts) {
// The label has changed
var sa = labelParts.lines;
var sn = labelParts.lines.length;
var textLines = this.__textGroup__.childNodes;
while(textLines.length > sn) {
textLines[textLines.length-1].remove();
}
for (var i=0; i<sn; i++) {
if (i===textLines.length) {
var line = document.createElementNS("http://www.w3.org/2000/svg","text");
line.setAttribute("class","red-ui-flow-node-label-text");
line.setAttribute("x",0);
line.setAttribute("y",i*24);
this.__textGroup__.appendChild(line);
}
textLines[i].textContent = sa[i];
}
}
var textClass = "red-ui-flow-node-label"+(hideLabel?" hide":"");
this.__textGroup__.setAttribute("class", textClass);
var yp = d.h / 2 - (this.__labelLineCount__ / 2) * 24 + 13;
// this.__textGroup__.classList.remove("red-ui-flow-node-label-right");
this.__textGroup__.setAttribute("transform", "translate(48,"+yp+")");
this.__outputBorder__.setAttribute("d","M 40 1 l 0 "+(hideLabel?0:(d.h - 2)));
this.__port__.setAttribute("transform","translate(-5,"+((d.h/2)-5)+")");
this.__outputNumber__.setAttribute("transform","translate(20,"+Math.max(28, (d.h/2)+2)+")");
this.__outputOutput__.setAttribute("transform","translate(20,"+Math.max(12, (d.h/2)-14)+")");
}
d.dirty = false;
}
});