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; 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 textDimensionPlaceholder = {};
var textDimensionCache = {}; var textDimensionCache = {};
@ -2202,7 +2216,6 @@ RED.view = (function() {
return textDimensionCache[className][str]; return textDimensionCache[className][str];
} }
var separateTextByLineBreak = [];
function convertLineBreakCharacter(str) { function convertLineBreakCharacter(str) {
var result = []; var result = [];
var count = 0; var count = 0;
@ -2230,7 +2243,6 @@ RED.view = (function() {
if (count == 0 || count < str.length) { if (count == 0 || count < str.length) {
result.push(result_temp.trim()); result.push(result_temp.trim());
} }
separateTextByLineBreak = result;
return result; return result;
} }
@ -3512,28 +3524,10 @@ RED.view = (function() {
var isLink = (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; var hideLabel = d.hasOwnProperty('l')?!d.l : isLink;
node.attr("id",d.id); node.attr("id",d.id);
var labelWidth = calculateTextWidth(RED.utils.getNodeLabel(d), "red-ui-flow-node-label") + 50; d.w = node_height;
if (d.resize || d.w === undefined) { d.h = node_height;
if (hideLabel) { d.resize = true;
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();});
// }
// }
if (d._def.button) { if (d._def.button) {
var buttonGroup = document.createElementNS("http://www.w3.org/2000/svg","g"); var buttonGroup = document.createElementNS("http://www.w3.org/2000/svg","g");
buttonGroup.__data__ = d; buttonGroup.__data__ = d;
@ -3629,12 +3623,13 @@ RED.view = (function() {
nodeContents.appendChild(icon_groupEl); 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("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("transform","translate(38,0)");
text.setAttribute("dy", ".3px"); // text.setAttribute("dy", ".3px");
text.setAttribute("text-anchor",d._def.align !== "right" ? "start":"end"); // text.setAttribute("text-anchor",d._def.align !== "right" ? "start":"end");
nodeContents.appendChild(text); nodeContents.appendChild(text);
node[0][0].__textGroup__ = text;
var statusEl = document.createElementNS("http://www.w3.org/2000/svg","g"); var statusEl = document.createElementNS("http://www.w3.org/2000/svg","g");
// statusEl.__data__ = d; // statusEl.__data__ = d;
@ -3690,54 +3685,72 @@ RED.view = (function() {
}); });
node.each(function(d,i) { node.each(function(d,i) {
if (d.dirty) { if (d.dirty) {
var thisNode = d3.select(this);
var isLink = (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; 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
var label = RED.utils.getNodeLabel(d, d.type); 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) { if (d.resize) {
var ow = d.w; var ow = d.w;
if (hideLabel) { if (hideLabel) {
d.w = node_height; d.w = node_height;
} else { } 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.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.x += (d.w-ow)/2;
d.resize = false; 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}}); //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) + ")"); this.setAttribute("transform", "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")");
if (mouse_mode != RED.state.MOVING_ACTIVE) { if (mouse_mode != RED.state.MOVING_ACTIVE) {
this.classList.toggle("red-ui-flow-node-disabled", d.d === true); 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.classList.toggle("red-ui-flow-node-selected", !!d.selected )
this.__mainRect__.setAttribute("width", d.w) this.__mainRect__.setAttribute("width", d.w)
this.__mainRect__.setAttribute("height", d.h) this.__mainRect__.setAttribute("height", d.h)
this.__mainRect__.classList.toggle("red-ui-flow-node-highlighted",!!d.highlighted ); this.__mainRect__.classList.toggle("red-ui-flow-node-highlighted",!!d.highlighted );
var text = thisNode.selectAll(".red-ui-flow-node-label"); if (labelParts) {
thisNode.selectAll(".red-ui-flow-node-label-text").remove(); // The label has changed
var sa = convertLineBreakCharacter(label); var sa = labelParts.lines;
var sn = sa.length; var sn = labelParts.lines.length;
var yp = d.h / 2 - (sn / 2) * 24 + 16 var textLines = this.__textGroup__.childNodes;
sa.forEach(function (line) { while(textLines.length > sn) {
text.append("tspan") textLines[textLines.length-1].remove();
.classed("red-ui-flow-node-label-text", true) }
.text(line) for (var i=0; i<sn; i++) {
.attr("x", 38) if (i===textLines.length) {
.attr("y", yp); var line = document.createElementNS("http://www.w3.org/2000/svg","text");
yp += 24; 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 = ""; var textClass = "";
if (d._def.labelStyle) { if (d._def.labelStyle) {
@ -3751,28 +3764,25 @@ RED.view = (function() {
textClass = " "+textClass; textClass = " "+textClass;
} }
textClass = "red-ui-flow-node-label"+(d._def.align?" red-ui-flow-node-label-"+d._def.align:"")+textClass+(hideLabel?" hide":""); 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) { 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); this.__iconGroup__.classList.add("red-ui-flow-node-icon-group-right");
thisNode.selectAll(".red-ui-flow-node-label").classed("red-ui-flow-node-label-right", true).attr("text-anchor", "end"); 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 { } else {
if (this.__iconGroup__) {// is null for uknown nodes 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"); var inputPorts = thisNode.selectAll(".red-ui-flow-port-input");
if ((!isLink || (showAllLinkPorts === -1 && !activeLinkNodes[d.id])) && d.inputs === 0 && !inputPorts.empty()) { if ((!isLink || (showAllLinkPorts === -1 && !activeLinkNodes[d.id])) && d.inputs === 0 && !inputPorts.empty()) {
inputPorts.remove(); inputPorts.remove();
@ -4238,8 +4248,9 @@ RED.view = (function() {
} }
if (!d.minWidth) { if (!d.minWidth) {
if (d.style.label && d.name) { if (d.style.label && d.name) {
d.minWidth = calculateTextWidth(d.name||"","red-ui-flow-group-label") + 8; var labelParts = getLabelParts(d.name||"","red-ui-flow-group-label");
d.labels = separateTextByLineBreak; d.minWidth = labelParts.width + 8;
d.labels = labelParts.lines;
} else { } else {
d.minWidth = 40; d.minWidth = 40;
} }

View File

@ -35,6 +35,14 @@
pointer-events: none; pointer-events: none;
-webkit-touch-callout: none; -webkit-touch-callout: none;
@include disable-selection; @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 { .red-ui-flow-port-label {