From d148a23ed6bab1f04ad8811656e02934f482deb4 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Tue, 24 Feb 2015 23:02:45 +0000 Subject: [PATCH] Handle config nodes appearing out of order in flow The editor ensures config nodes appear first in the flow file. The code in the runtime and editor assumes this to be the case, so that when a node is instantiated that requires a config node, it can assume the config node already exists. This change allows a config node to appear in the flow file after a node that wants to use it. In both the editor and runtime, the code now scans for config nodes and handles them first. --- public/red/nodes.js | 29 +++++++++++--------- red/nodes/Flow.js | 66 ++++++++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/public/red/nodes.js b/public/red/nodes.js index 78b7429bb..85e384094 100644 --- a/public/red/nodes.js +++ b/public/red/nodes.js @@ -608,6 +608,21 @@ RED.nodes = (function() { }); new_subflows.push(n); addSubflow(n); + } else { + var def = registry.getNodeType(n.type); + if (def && def.category == "config") { + if (!RED.nodes.node(n.id)) { + var configNode = {id:n.id,type:n.type,users:[]}; + for (var d in def.defaults) { + if (def.defaults.hasOwnProperty(d)) { + configNode[d] = n[d]; + } + } + configNode.label = def.label; + configNode._def = def; + RED.nodes.add(configNode); + } + } } } if (defaultWorkspace == null) { @@ -627,19 +642,7 @@ RED.nodes = (function() { // TODO: remove workspace in next release+1 if (n.type !== "workspace" && n.type !== "tab" && n.type !== "subflow") { var def = registry.getNodeType(n.type); - if (def && def.category == "config") { - if (!RED.nodes.node(n.id)) { - var configNode = {id:n.id,type:n.type,users:[]}; - for (var d in def.defaults) { - if (def.defaults.hasOwnProperty(d)) { - configNode[d] = n[d]; - } - } - configNode.label = def.label; - configNode._def = def; - RED.nodes.add(configNode); - } - } else { + if (!def || def.category != "config") { var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false}; if (createNewIds) { if (subflow_map[node.z]) { diff --git a/red/nodes/Flow.js b/red/nodes/Flow.js index 4f56b0daf..e56f34afb 100644 --- a/red/nodes/Flow.js +++ b/red/nodes/Flow.js @@ -228,11 +228,14 @@ Flow.prototype.parseConfig = function(config) { this.nodes = {}; this.subflows = {}; + this.configNodes = {}; + var unknownTypes = {}; for (i=0;i 0) { @@ -560,7 +582,7 @@ Flow.prototype.diffFlow = function(config) { if (node.type == "subflow:"+subflowId) { if (!changedNodes[node.id]) { changedNodes[node.id] = node; - checkSubflowMembership(configNodes,node.id); + checkSubflowMembership(flowNodes,node.id); } } }); @@ -568,7 +590,7 @@ Flow.prototype.diffFlow = function(config) { } config.forEach(function(node) { - buildNodeLinks(newLinks,node,configNodes); + buildNodeLinks(newLinks,node,flowNodes); }); var markLinkedNodes = function(linkChanged,otherChangedNodes,linkMap,allNodes) { @@ -591,7 +613,7 @@ Flow.prototype.diffFlow = function(config) { } } } - markLinkedNodes(linkChangedNodes,{},newLinks,configNodes); + markLinkedNodes(linkChangedNodes,{},newLinks,flowNodes); markLinkedNodes(linkChangedNodes,{},activeLinks,flow.allNodes); var modifiedLinkNodes = {}; @@ -613,8 +635,8 @@ Flow.prototype.diffFlow = function(config) { modifiedLinkNodes[node.id] = node; linkChangedNodes[node.id] = node; if (!changedNodes[link] && !deletedNodes[link]) { - modifiedLinkNodes[link] = configNodes[link]; - linkChangedNodes[link] = configNodes[link]; + modifiedLinkNodes[link] = flowNodes[link]; + linkChangedNodes[link] = flowNodes[link]; } } }); @@ -623,15 +645,15 @@ Flow.prototype.diffFlow = function(config) { modifiedLinkNodes[node.id] = node; linkChangedNodes[node.id] = node; if (!changedNodes[link] && !deletedNodes[link]) { - modifiedLinkNodes[link] = configNodes[link]; - linkChangedNodes[link] = configNodes[link]; + modifiedLinkNodes[link] = flowNodes[link]; + linkChangedNodes[link] = flowNodes[link]; } } }); } }); - markLinkedNodes(linkChangedNodes,modifiedLinkNodes,newLinks,configNodes); + markLinkedNodes(linkChangedNodes,modifiedLinkNodes,newLinks,flowNodes); //config.forEach(function(n) { // console.log((changedNodes[n.id]!=null)?"[C]":"[ ]",(linkChangedNodes[n.id]!=null)?"[L]":"[ ]","[ ]",n.id,n.type,n.name); @@ -643,14 +665,14 @@ Flow.prototype.diffFlow = function(config) { //}); var diff = { - deleted: Object.keys(deletedNodes).filter(function(id) { return deletedNodes[id].type != "subflow" && (!deletedNodes[id].z || configNodes[deletedNodes[id].z].type != "subflow")}), - changed: Object.keys(changedNodes).filter(function(id) { return changedNodes[id].type != "subflow" && (!changedNodes[id].z || configNodes[changedNodes[id].z].type != "subflow")}), - linked: Object.keys(linkChangedNodes).filter(function(id) { return linkChangedNodes[id].type != "subflow" && (!linkChangedNodes[id].z || configNodes[linkChangedNodes[id].z].type != "subflow")}), + deleted: Object.keys(deletedNodes).filter(function(id) { return deletedNodes[id].type != "subflow" && (!deletedNodes[id].z || flowNodes[deletedNodes[id].z].type != "subflow")}), + changed: Object.keys(changedNodes).filter(function(id) { return changedNodes[id].type != "subflow" && (!changedNodes[id].z || flowNodes[changedNodes[id].z].type != "subflow")}), + linked: Object.keys(linkChangedNodes).filter(function(id) { return linkChangedNodes[id].type != "subflow" && (!linkChangedNodes[id].z || flowNodes[linkChangedNodes[id].z].type != "subflow")}), wiringChanged: [] } config.forEach(function(n) { - if (!configNodes[n.z] || configNodes[n.z].type != "subflow") { + if (!flowNodes[n.z] || flowNodes[n.z].type != "subflow") { var originalNode = flow.allNodes[n.id]; if (originalNode && !redUtil.compareObjects(originalNode.wires,n.wires)) { diff.wiringChanged.push(n.id);