Avoid regenerating every node label on redraw

This commit is contained in:
Nick O'Leary 2020-06-13 23:02:10 +01:00
parent 1c30584153
commit 61d9ccf263
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
2 changed files with 86 additions and 67 deletions

View File

@ -2179,6 +2179,20 @@ RED.view = (function() {
}
return width;
}
function getLabelParts(str, className) {
var lines = convertLineBreakCharacter(str);
var width = 0;
for (var i=0;i<lines.length;i++) {
var calculateTextW = calculateTextDimensions(lines[i],className)[0];
if (width<calculateTextW) {
width=calculateTextW;
}
}
return {
lines:lines,
width: width
}
}
var textDimensionPlaceholder = {};
var textDimensionCache = {};
@ -2202,7 +2216,6 @@ RED.view = (function() {
return textDimensionCache[className][str];
}
var separateTextByLineBreak = [];
function convertLineBreakCharacter(str) {
var result = [];
var count = 0;
@ -2230,7 +2243,6 @@ RED.view = (function() {
if (count == 0 || count < str.length) {
result.push(result_temp.trim());
}
separateTextByLineBreak = result;
return result;
}
@ -3512,28 +3524,10 @@ RED.view = (function() {
var isLink = (d.type === "link in" || d.type === "link out")
var hideLabel = d.hasOwnProperty('l')?!d.l : isLink;
node.attr("id",d.id);
var labelWidth = calculateTextWidth(RED.utils.getNodeLabel(d), "red-ui-flow-node-label") + 50;
if (d.resize || d.w === undefined) {
if (hideLabel) {
d.w = node_height;
} else {
d.w = Math.max(node_width,20*(Math.ceil((labelWidth+(d._def.inputs>0?7:0))/20)) );
}
}
if (hideLabel) {
d.h = Math.max(node_height,(d.outputs || 0) * 15);
} else {
d.h = Math.max(6+24*separateTextByLineBreak.length, (d.outputs || 0) * 15, 30);
}
// if (d._def.badge) {
// var badge = node.append("svg:g").attr("class","node_badge_group");
// var badgeRect = badge.append("rect").attr("class","node_badge").attr("rx",5).attr("ry",5).attr("width",40).attr("height",15);
// badge.append("svg:text").attr("class","node_badge_label").attr("x",35).attr("y",11).attr("text-anchor","end").text(d._def.badge());
// if (d._def.onbadgeclick) {
// badgeRect.attr("cursor","pointer")
// .on("click",function(d) { d._def.onbadgeclick.call(d);d3.event.preventDefault();});
// }
// }
d.w = node_height;
d.h = node_height;
d.resize = true;
if (d._def.button) {
var buttonGroup = document.createElementNS("http://www.w3.org/2000/svg","g");
buttonGroup.__data__ = d;
@ -3629,12 +3623,13 @@ RED.view = (function() {
nodeContents.appendChild(icon_groupEl);
}
var text = document.createElementNS("http://www.w3.org/2000/svg","text");
var text = document.createElementNS("http://www.w3.org/2000/svg","g");
text.setAttribute("class","red-ui-flow-node-label"+(hideLabel?" hide":"")+(d._def.align?" red-ui-flow-node-label-"+d._def.align:""));
text.setAttribute("x", 38);
text.setAttribute("dy", ".3px");
text.setAttribute("text-anchor",d._def.align !== "right" ? "start":"end");
text.setAttribute("transform","translate(38,0)");
// text.setAttribute("dy", ".3px");
// text.setAttribute("text-anchor",d._def.align !== "right" ? "start":"end");
nodeContents.appendChild(text);
node[0][0].__textGroup__ = text;
var statusEl = document.createElementNS("http://www.w3.org/2000/svg","g");
// statusEl.__data__ = d;
@ -3690,54 +3685,72 @@ RED.view = (function() {
});
node.each(function(d,i) {
if (d.dirty) {
var thisNode = d3.select(this);
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
var label = RED.utils.getNodeLabel(d, d.type);
var labelWidth = calculateTextWidth(label, "red-ui-flow-node-label") + 50;
var labelParts;
if (this.__hideLabel__ !== hideLabel || d.resize || this.__label__ !== label) {
labelParts = getLabelParts(label, "red-ui-flow-node-label");
this.__label__ = label;
if (labelParts.lines.length !== this.__labelLineCount__) {
d.resize = true;
}
this.__labelLineCount__ = labelParts.lines.length;
}
if (d.resize || this.__hideLabel__ !== hideLabel || this.__outputs__.length !== d.outputs) {
if (hideLabel) {
d.h = Math.max(node_height,(d.outputs || 0) * 15);
} else {
d.h = Math.max(6+24*labelParts.lines.length,(d.outputs || 0) * 15, 30);
}
this.__hideLabel__ = hideLabel;
}
if (d.resize) {
var ow = d.w;
if (hideLabel) {
d.w = node_height;
} else {
d.w = Math.max(node_width,20*(Math.ceil((labelWidth+(d._def.inputs>0?7:0))/20)) );
d.w = Math.max(node_width,20*(Math.ceil((labelParts.width+50+(d._def.inputs>0?7:0))/20)) );
}
// d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) );
d.x += (d.w-ow)/2;
d.resize = false;
}
if (hideLabel) {
d.h = Math.max(node_height,(d.outputs || 0) * 15);
} else {
d.h = Math.max(6+24*separateTextByLineBreak.length,(d.outputs || 0) * 15, 30);
}
var thisNode = d3.select(this);
//thisNode.selectAll(".centerDot").attr({"cx":function(d) { return d.w/2;},"cy":function(d){return d.h/2}});
this.setAttribute("transform", "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")");
if (mouse_mode != RED.state.MOVING_ACTIVE) {
this.classList.toggle("red-ui-flow-node-disabled", d.d === true);
this.classList.toggle("red-ui-flow-subflow", activeSubflow != null)
this.classList.toggle("red-ui-flow-node-selected", !!d.selected )
this.__mainRect__.setAttribute("width", d.w)
this.__mainRect__.setAttribute("height", d.h)
this.__mainRect__.classList.toggle("red-ui-flow-node-highlighted",!!d.highlighted );
var text = thisNode.selectAll(".red-ui-flow-node-label");
thisNode.selectAll(".red-ui-flow-node-label-text").remove();
var sa = convertLineBreakCharacter(label);
var sn = sa.length;
var yp = d.h / 2 - (sn / 2) * 24 + 16
sa.forEach(function (line) {
text.append("tspan")
.classed("red-ui-flow-node-label-text", true)
.text(line)
.attr("x", 38)
.attr("y", yp);
yp += 24;
});
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 = "";
if (d._def.labelStyle) {
@ -3751,28 +3764,25 @@ RED.view = (function() {
textClass = " "+textClass;
}
textClass = "red-ui-flow-node-label"+(d._def.align?" red-ui-flow-node-label-"+d._def.align:"")+textClass+(hideLabel?" hide":"");
text.attr("class", textClass);
this.__textGroup__.setAttribute("class", textClass);
var yp = d.h / 2 - (this.__labelLineCount__ / 2) * 24 + 13;
if ((!d._def.align && d.inputs !== 0 && d.outputs === 0) || "right" === d._def.align) {
this.__iconGroup__.classList.toggle("red-ui-flow-node-icon-group-right", true);
thisNode.selectAll(".red-ui-flow-node-label").classed("red-ui-flow-node-label-right", true).attr("text-anchor", "end");
this.__iconGroup__.classList.add("red-ui-flow-node-icon-group-right");
this.__iconGroup__.setAttribute("transform", "translate("+(d.w-30)+",0)");
this.__textGroup__.classList.add("red-ui-flow-node-label-right");
this.__textGroup__.setAttribute("transform", "translate("+(d.w-38)+","+yp+")");
} else {
if (this.__iconGroup__) {// is null for uknown nodes
this.__iconGroup__.classList.toggle("red-ui-flow-node-icon-group-right", false);
this.__iconGroup__.classList.remove("red-ui-flow-node-icon-group-right");
this.__iconGroup__.setAttribute("transform", "");
}
thisNode.selectAll(".red-ui-flow-node-label").classed("red-ui-flow-node-label-right", false).attr("text-anchor", "start");
this.__textGroup__.classList.remove("red-ui-flow-node-label-right");
this.__textGroup__.setAttribute("transform", "translate(38,"+yp+")");
}
var alignX;
// thisNode.selectAll(".red-ui-flow-node-icon-group").attr("transform", "translate(0, 0)" );
thisNode.selectAll(".red-ui-flow-node-label").attr("x", function () { alignX=38; return 38; });
thisNode.selectAll(".red-ui-flow-node-icon-group-right").attr("transform", "translate("+(d.w-30)+",0)");
thisNode.selectAll(".red-ui-flow-node-label-right").attr("x", function(){ alignX=d.w-38; return d.w-38});
thisNode.selectAll(".red-ui-flow-node-label-text").attr("x", function () { return 38; });
thisNode.selectAll(".red-ui-flow-node-label-right").selectAll("tspan").attr("x", function(){ return d.w-38});
//thisNode.selectAll(".red-ui-flow-node-icon-right").attr("x",function(d){return d.w-d3.select(this).attr("width")-1-(d.outputs>0?5:0);});
//thisNode.selectAll(".red-ui-flow-node-icon-shade-right").attr("x",function(d){return d.w-30;});
//thisNode.selectAll(".red-ui-flow-node-icon-shade-border-right").attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2)});
var inputPorts = thisNode.selectAll(".red-ui-flow-port-input");
if ((!isLink || (showAllLinkPorts === -1 && !activeLinkNodes[d.id])) && d.inputs === 0 && !inputPorts.empty()) {
inputPorts.remove();
@ -4238,8 +4248,9 @@ RED.view = (function() {
}
if (!d.minWidth) {
if (d.style.label && d.name) {
d.minWidth = calculateTextWidth(d.name||"","red-ui-flow-group-label") + 8;
d.labels = separateTextByLineBreak;
var labelParts = getLabelParts(d.name||"","red-ui-flow-group-label");
d.minWidth = labelParts.width + 8;
d.labels = labelParts.lines;
} else {
d.minWidth = 40;
}

View File

@ -35,6 +35,14 @@
pointer-events: none;
-webkit-touch-callout: none;
@include disable-selection;
.red-ui-flow-node-label-text {
alignment-baseline: middle;
}
&.red-ui-flow-node-label-right .red-ui-flow-node-label-text {
text-anchor: end;
}
}
.red-ui-flow-port-label {