From 373267c53b5d1336ca70b3ae33630904f5482f31 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 20 Apr 2020 21:30:03 +0100 Subject: [PATCH] Add more consistent events in the editor This introduces a much more consistent set of events within the editor for whenever a element is added, removed or modified. The events emited on the `RED.events` event system. The event names take the form: `":"`. `` can be one of: - nodes - flows - subflows - groups - links `` can be one of: - add - remove - change The payload of the events is the object in question. There is also: - flows:reorder - when tabs are reordered. Payload is array of flow ids. - workspace:clear - when the workspace is emptied - part of switching projects The `nodes:change` event was already used by RED.nodes.dirty() to cause the Deploy button to become active. This renames that event to: - workspace:dirty - Payload is boolean flag for the dirty state This commit also updates the Palette to use the subflows:change event to only redraw subflows that have actually changed rather than refresh them all whenever one of them *might* have changed. This removes a noticable flicker of the icon which was needlessly being redrawn. --- .../@node-red/editor-client/src/js/events.js | 9 +- .../@node-red/editor-client/src/js/history.js | 17 ++- .../@node-red/editor-client/src/js/nodes.js | 76 +++++++----- .../editor-client/src/js/ui/deploy.js | 2 +- .../editor-client/src/js/ui/editor.js | 5 +- .../editor-client/src/js/ui/group.js | 15 +++ .../editor-client/src/js/ui/palette.js | 108 ++++++++++-------- .../editor-client/src/js/ui/subflow.js | 9 +- .../@node-red/editor-client/src/js/ui/view.js | 4 +- .../editor-client/src/js/ui/workspaces.js | 11 +- 10 files changed, 167 insertions(+), 89 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/events.js b/packages/node_modules/@node-red/editor-client/src/js/events.js index f79cc864f..41e669aba 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/events.js +++ b/packages/node_modules/@node-red/editor-client/src/js/events.js @@ -32,11 +32,16 @@ } } } - function emit(evt,arg) { + function emit() { + var evt = arguments[0] + var args = Array.prototype.slice.call(arguments,1); + if (RED.events.DEBUG) { + console.log(evt,args); + } if (handlers[evt]) { for (var i=0;i', { class: "red-ui-palette-icon-container"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "") }).appendTo(d); + iconContainer.attr("data-palette-icon", icon_url); RED.utils.createIconElement(icon_url, iconContainer, true); } @@ -452,61 +457,67 @@ RED.palette = (function() { categoryNode.show(); paletteNode.show(); } - function refreshNodeTypes() { - RED.nodes.eachSubflow(function(sf) { - var paletteNode = getPaletteNode('subflow:'+sf.id); - var portInput = paletteNode.find(".red-ui-palette-port-input"); - var portOutput = paletteNode.find(".red-ui-palette-port-output"); + RED.nodes.eachSubflow(refreshSubflow) + } + function refreshSubflow(sf) { + var paletteNode = getPaletteNode('subflow:'+sf.id); + var portInput = paletteNode.find(".red-ui-palette-port-input"); + var portOutput = paletteNode.find(".red-ui-palette-port-output"); - var paletteLabel = paletteNode.find(".red-ui-palette-label"); - paletteLabel.attr("class","red-ui-palette-label" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : "")); + var paletteLabel = paletteNode.find(".red-ui-palette-label"); + paletteLabel.attr("class","red-ui-palette-label" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : "")); - var paletteIconContainer = paletteNode.find(".red-ui-palette-icon-container"); - paletteIconContainer.attr("class","red-ui-palette-icon-container" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : "")); + var paletteIconContainer = paletteNode.find(".red-ui-palette-icon-container"); + paletteIconContainer.attr("class","red-ui-palette-icon-container" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : "")); - if (portInput.length === 0 && sf.in.length > 0) { - var portIn = document.createElement("div"); - portIn.className = "red-ui-palette-port red-ui-palette-port-input"; - paletteNode.append(portIn); - } else if (portInput.length !== 0 && sf.in.length === 0) { - portInput.remove(); - } + if (portInput.length === 0 && sf.in.length > 0) { + var portIn = document.createElement("div"); + portIn.className = "red-ui-palette-port red-ui-palette-port-input"; + paletteNode.append(portIn); + } else if (portInput.length !== 0 && sf.in.length === 0) { + portInput.remove(); + } - if (portOutput.length === 0 && sf.out.length > 0) { - var portOut = document.createElement("div"); - portOut.className = "red-ui-palette-port red-ui-palette-port-output"; - paletteNode.append(portOut); - } else if (portOutput.length !== 0 && sf.out.length === 0) { - portOutput.remove(); - } + if (portOutput.length === 0 && sf.out.length > 0) { + var portOut = document.createElement("div"); + portOut.className = "red-ui-palette-port red-ui-palette-port-output"; + paletteNode.append(portOut); + } else if (portOutput.length !== 0 && sf.out.length === 0) { + portOutput.remove(); + } + var currentLabel = paletteNode.attr("data-palette-label"); + var currentInfo = paletteNode.attr("data-palette-info"); + + if (currentLabel !== sf.name || currentInfo !== sf.info) { + paletteNode.attr("data-palette-info",sf.info); setLabel(sf.type+":"+sf.id,paletteNode,sf.name,RED.utils.renderMarkdown(sf.info||"")); - setIcon(paletteNode,sf); + } + setIcon(paletteNode,sf); - var currentCategory = paletteNode.data('category'); - var newCategory = (sf.category||"subflows"); - if (currentCategory !== newCategory) { - var category = escapeCategory(newCategory); - createCategory(newCategory,category,category,"node-red"); + var currentCategory = paletteNode.data('category'); + var newCategory = (sf.category||"subflows"); + if (currentCategory !== newCategory) { + var category = escapeCategory(newCategory); + createCategory(newCategory,category,category,"node-red"); - var currentCategoryNode = paletteNode.closest(".red-ui-palette-category"); - var newCategoryNode = $("#red-ui-palette-"+category); - newCategoryNode.append(paletteNode); - if (newCategoryNode.find(".red-ui-palette-node").length === 1) { - categoryContainers[category].open(); - } - - paletteNode.data('category',newCategory); - if (currentCategoryNode.find(".red-ui-palette-node").length === 0) { - if (currentCategoryNode.find("i").hasClass("expanded")) { - currentCategoryNode.find(".red-ui-palette-content").slideToggle(); - currentCategoryNode.find("i").toggleClass("expanded"); - } - } + var currentCategoryNode = paletteNode.closest(".red-ui-palette-category"); + var newCategoryNode = $("#red-ui-palette-"+category); + newCategoryNode.append(paletteNode); + if (newCategoryNode.find(".red-ui-palette-node").length === 1) { + categoryContainers[category].open(); } - paletteNode.css("backgroundColor", sf.color); - }); + paletteNode.data('category',newCategory); + if (currentCategoryNode.find(".red-ui-palette-node").length === 0) { + if (currentCategoryNode.find("i").hasClass("expanded")) { + currentCategoryNode.find(".red-ui-palette-content").slideToggle(); + currentCategoryNode.find("i").toggleClass("expanded"); + } + } + } + + paletteNode.css("backgroundColor", sf.color); } function filterChange(val) { @@ -544,6 +555,8 @@ RED.palette = (function() { $('').appendTo("#red-ui-palette"); $('
').appendTo("#red-ui-palette"); + $("#red-ui-palette > .red-ui-palette-spinner").show(); + RED.events.on('registry:node-type-added', function(nodeType) { var def = RED.nodes.getType(nodeType); @@ -585,7 +598,8 @@ RED.palette = (function() { } }); - $("#red-ui-palette > .red-ui-palette-spinner").show(); + RED.events.on("subflows:change",refreshSubflow); + $("#red-ui-palette-search input").searchBox({ diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js b/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js index 137af02ac..b60cbe991 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js @@ -106,7 +106,7 @@ RED.subflow = (function() { RED.view.redraw(); $("#red-ui-subflow-input-add").addClass("active"); $("#red-ui-subflow-input-remove").removeClass("active"); - RED.palette.refresh(); + RED.events.emit("subflows:change",subflow); } function removeSubflowInput() { @@ -128,7 +128,7 @@ RED.subflow = (function() { $("#red-ui-subflow-input-add").removeClass("active"); $("#red-ui-subflow-input-remove").addClass("active"); activeSubflow.changed = true; - RED.palette.refresh(); + RED.events.emit("subflows:change",activeSubflow); return {subflowInputs: [ removedInput ], links:removedInputLinks}; } @@ -169,7 +169,7 @@ RED.subflow = (function() { RED.nodes.dirty(true); RED.view.redraw(); $("#red-ui-subflow-output .spinner-value").text(subflow.out.length); - RED.palette.refresh(); + RED.events.emit("subflows:change",subflow); } function removeSubflowOutput(removedSubflowOutputs) { @@ -209,7 +209,7 @@ RED.subflow = (function() { } } activeSubflow.changed = true; - RED.palette.refresh(); + RED.events.emit("subflows:change",activeSubflow); return {subflowOutputs: removedSubflowOutputs, links: removedLinks} } @@ -244,6 +244,7 @@ RED.subflow = (function() { RED.view.select(); RED.nodes.dirty(true); RED.view.redraw(); + RED.events.emit("subflows:change",subflow); $("#red-ui-subflow-status").prop("checked",!!subflow.status); $("#red-ui-subflow-status").parent().parent().toggleClass("active",!!subflow.status); } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index e4fe0a33d..35bcbb4e6 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -393,6 +393,8 @@ RED.view = (function() { historyEvent.removedLinks = [spliceLink]; } + RED.nodes.add(nn); + var group = $(ui.helper).data("group"); if (group) { RED.group.addToGroup(group, nn); @@ -409,7 +411,6 @@ RED.view = (function() { } RED.history.push(historyEvent); - RED.nodes.add(nn); RED.editor.validateNode(nn); RED.nodes.dirty(true); // auto select dropped node - so info shows (if visible) @@ -4528,6 +4529,7 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } } node.dirty = true; node.changed = true; + RED.events.emit("nodes:change",node); } } } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js index 1f361d0f7..7a5f7a86c 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js @@ -140,6 +140,7 @@ RED.workspaces = (function() { }); RED.view.redraw(); } + RED.events.emit("flows:change",workspace); } RED.tray.close(); } @@ -380,6 +381,7 @@ RED.workspaces = (function() { } workspace.changed = true; RED.history.push(historyEvent); + RED.events.emit("flows:change",workspace); RED.nodes.dirty(true); RED.sidebar.config.refresh(); var selection = RED.view.selection(); @@ -412,9 +414,14 @@ RED.workspaces = (function() { } function setWorkspaceOrder(order) { - RED.nodes.setWorkspaceOrder(order.filter(function(id) { + var newOrder = order.filter(function(id) { return RED.nodes.workspace(id) !== undefined; - })); + }) + var currentOrder = RED.nodes.getWorkspaceOrder(); + if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) { + RED.nodes.setWorkspaceOrder(newOrder); + RED.events.emit("flows:reorder",newOrder); + } workspace_tabs.order(order); }