You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. /** Modified from original Node-Red source, for audio system visualization
  2. * vim: set ts=4:
  3. * Copyright 2013 IBM Corp.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. **/
  17. RED.nodes = (function() {
  18. var node_defs = {};
  19. var nodes = [];
  20. var configNodes = {};
  21. var links = [];
  22. var defaultWorkspace;
  23. var workspaces = {};
  24. function registerType(nt,def) {
  25. node_defs[nt] = def;
  26. // TODO: too tightly coupled into palette UI
  27. RED.palette.add(nt,def);
  28. }
  29. function getID() {
  30. var str = (1+Math.random()*4294967295).toString(16);
  31. console.log("getID = " + str);
  32. return str;
  33. }
  34. function checkID(name) {
  35. var i;
  36. for (i=0;i<nodes.length;i++) {
  37. console.log("checkID, nodes[i].id = " + nodes[i].id);
  38. if (nodes[i].id == name) return true;
  39. }
  40. /*
  41. for (i in workspaces) {
  42. if (workspaces.hasOwnProperty(i)) { }
  43. }
  44. for (i in configNodes) {
  45. if (configNodes.hasOwnProperty(i)) { }
  46. }
  47. */
  48. return false;
  49. }
  50. function createUniqueCppName(n) {
  51. console.log("getUniqueCppName, n.type=" + n.type + ", n._def.shortName=" + n._def.shortName);
  52. var basename = (n._def.shortName) ? n._def.shortName : n.type.replace(/^Analog/, "");
  53. console.log("getUniqueCppName, using basename=" + basename);
  54. var count = 1;
  55. var sep = /[0-9]$/.test(basename) ? "_" : "";
  56. var name;
  57. while (1) {
  58. name = basename + sep + count;
  59. if (!checkID(name)) break;
  60. count++;
  61. }
  62. console.log("getUniqueCppName, unique name=" + name);
  63. return name;
  64. }
  65. function getType(type) {
  66. return node_defs[type];
  67. }
  68. function addNode(n) {
  69. if (n._def.category == "config") {
  70. configNodes[n.id] = n;
  71. RED.sidebar.config.refresh();
  72. } else {
  73. n.dirty = true;
  74. nodes.push(n);
  75. var updatedConfigNode = false;
  76. for (var d in n._def.defaults) {
  77. if (n._def.defaults.hasOwnProperty(d)) {
  78. var property = n._def.defaults[d];
  79. if (property.type) {
  80. var type = getType(property.type)
  81. if (type && type.category == "config") {
  82. var configNode = configNodes[n[d]];
  83. if (configNode) {
  84. updatedConfigNode = true;
  85. configNode.users.push(n);
  86. }
  87. }
  88. }
  89. }
  90. }
  91. if (updatedConfigNode) {
  92. RED.sidebar.config.refresh();
  93. }
  94. }
  95. }
  96. function addLink(l) {
  97. links.push(l);
  98. }
  99. function addConfig(c) {
  100. configNodes[c.id] = c;
  101. }
  102. function getNode(id) {
  103. if (id in configNodes) {
  104. return configNodes[id];
  105. } else {
  106. for (var n in nodes) {
  107. if (nodes[n].id == id) {
  108. return nodes[n];
  109. }
  110. }
  111. }
  112. return null;
  113. }
  114. function removeNode(id) {
  115. var removedLinks = [];
  116. if (id in configNodes) {
  117. delete configNodes[id];
  118. RED.sidebar.config.refresh();
  119. } else {
  120. var node = getNode(id);
  121. if (node) {
  122. nodes.splice(nodes.indexOf(node),1);
  123. removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
  124. removedLinks.map(function(l) {links.splice(links.indexOf(l), 1); });
  125. }
  126. var updatedConfigNode = false;
  127. for (var d in node._def.defaults) {
  128. if (node._def.defaults.hasOwnProperty(d)) {
  129. var property = node._def.defaults[d];
  130. if (property.type) {
  131. var type = getType(property.type)
  132. if (type && type.category == "config") {
  133. var configNode = configNodes[node[d]];
  134. if (configNode) {
  135. updatedConfigNode = true;
  136. var users = configNode.users;
  137. users.splice(users.indexOf(node),1);
  138. }
  139. }
  140. }
  141. }
  142. }
  143. if (updatedConfigNode) {
  144. RED.sidebar.config.refresh();
  145. }
  146. }
  147. return removedLinks;
  148. }
  149. function removeLink(l) {
  150. var index = links.indexOf(l);
  151. if (index != -1) {
  152. links.splice(index,1);
  153. }
  154. }
  155. function refreshValidation() {
  156. for (var n=0;n<nodes.length;n++) {
  157. RED.editor.validateNode(nodes[n]);
  158. }
  159. }
  160. function addWorkspace(ws) {
  161. workspaces[ws.id] = ws;
  162. }
  163. function getWorkspace(id) {
  164. return workspaces[id];
  165. }
  166. function removeWorkspace(id) {
  167. delete workspaces[id];
  168. var removedNodes = [];
  169. var removedLinks = [];
  170. var n;
  171. for (n=0;n<nodes.length;n++) {
  172. var node = nodes[n];
  173. if (node.z == id) {
  174. removedNodes.push(node);
  175. }
  176. }
  177. for (n=0;n<removedNodes.length;n++) {
  178. var rmlinks = removeNode(removedNodes[n].id);
  179. removedLinks = removedLinks.concat(rmlinks);
  180. }
  181. return {nodes:removedNodes,links:removedLinks};
  182. }
  183. function getAllFlowNodes(node) {
  184. var visited = {};
  185. visited[node.id] = true;
  186. var nns = [node];
  187. var stack = [node];
  188. while(stack.length !== 0) {
  189. var n = stack.shift();
  190. var childLinks = links.filter(function(d) { return (d.source === n) || (d.target === n);});
  191. for (var i=0;i<childLinks.length;i++) {
  192. var child = (childLinks[i].source === n)?childLinks[i].target:childLinks[i].source;
  193. if (!visited[child.id]) {
  194. visited[child.id] = true;
  195. nns.push(child);
  196. stack.push(child);
  197. }
  198. }
  199. }
  200. return nns;
  201. }
  202. /**
  203. * Converts a node to an exportable JSON Object
  204. **/
  205. function convertNode(n, exportCreds) {
  206. exportCreds = exportCreds || false;
  207. var node = {};
  208. node.id = n.id;
  209. node.type = n.type;
  210. for (var d in n._def.defaults) {
  211. if (n._def.defaults.hasOwnProperty(d)) {
  212. node[d] = n[d];
  213. }
  214. }
  215. if(exportCreds && n.credentials) {
  216. node.credentials = {};
  217. for (var cred in n._def.credentials) {
  218. if (n._def.credentials.hasOwnProperty(cred)) {
  219. if (n.credentials[cred] != null) {
  220. node.credentials[cred] = n.credentials[cred];
  221. }
  222. }
  223. }
  224. }
  225. if (n._def.category != "config") {
  226. node.x = n.x;
  227. node.y = n.y;
  228. node.z = n.z;
  229. node.wires = [];
  230. for(var i=0;i<n.outputs;i++) {
  231. node.wires.push([]);
  232. }
  233. var wires = links.filter(function(d){return d.source === n;});
  234. for (var j=0;j<wires.length;j++) {
  235. var w = wires[j];
  236. node.wires[w.sourcePort].push(w.target.id + ":" + w.targetPort);
  237. }
  238. }
  239. return node;
  240. }
  241. /**
  242. * Converts the current node selection to an exportable JSON Object
  243. **/
  244. function createExportableNodeSet(set) {
  245. var nns = [];
  246. var exportedConfigNodes = {};
  247. for (var n=0;n<set.length;n++) {
  248. var node = set[n].n;
  249. var convertedNode = RED.nodes.convertNode(node);
  250. for (var d in node._def.defaults) {
  251. if (node._def.defaults[d].type && node[d] in configNodes) {
  252. var confNode = configNodes[node[d]];
  253. var exportable = getType(node._def.defaults[d].type).exportable;
  254. if ((exportable == null || exportable)) {
  255. if (!(node[d] in exportedConfigNodes)) {
  256. exportedConfigNodes[node[d]] = true;
  257. nns.unshift(RED.nodes.convertNode(confNode));
  258. }
  259. } else {
  260. convertedNode[d] = "";
  261. }
  262. }
  263. }
  264. nns.push(convertedNode);
  265. }
  266. return nns;
  267. }
  268. //TODO: rename this (createCompleteNodeSet)
  269. function createCompleteNodeSet() {
  270. var nns = [];
  271. var i;
  272. for (i in workspaces) {
  273. if (workspaces.hasOwnProperty(i)) {
  274. nns.push(workspaces[i]);
  275. }
  276. }
  277. for (i in configNodes) {
  278. if (configNodes.hasOwnProperty(i)) {
  279. nns.push(convertNode(configNodes[i], true));
  280. }
  281. }
  282. for (i=0;i<nodes.length;i++) {
  283. var node = nodes[i];
  284. nns.push(convertNode(node, true));
  285. }
  286. return nns;
  287. }
  288. function importNodes(newNodesObj,createNewIds) {
  289. try {
  290. var i;
  291. var n;
  292. var newNodes;
  293. if (typeof newNodesObj === "string") {
  294. if (newNodesObj === "") {
  295. return;
  296. }
  297. newNodes = JSON.parse(newNodesObj);
  298. } else {
  299. newNodes = newNodesObj;
  300. }
  301. if (!$.isArray(newNodes)) {
  302. newNodes = [newNodes];
  303. }
  304. var unknownTypes = [];
  305. for (i=0;i<newNodes.length;i++) {
  306. n = newNodes[i];
  307. // TODO: remove workspace in next release+1
  308. if (n.type != "workspace" && n.type != "tab" && !getType(n.type)) {
  309. // TODO: get this UI thing out of here! (see below as well)
  310. n.name = n.type;
  311. n.type = "unknown";
  312. if (unknownTypes.indexOf(n.name)==-1) {
  313. unknownTypes.push(n.name);
  314. }
  315. if (n.x == null && n.y == null) {
  316. // config node - remove it
  317. newNodes.splice(i,1);
  318. i--;
  319. }
  320. }
  321. }
  322. /*
  323. if (unknownTypes.length > 0) {
  324. var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>";
  325. var type = "type"+(unknownTypes.length > 1?"s":"");
  326. RED.notify("<strong>Imported unrecognised "+type+":</strong>"+typeList,"error",false,10000);
  327. //"DO NOT DEPLOY while in this state.<br/>Either, add missing types to Node-RED, restart and then reload page,<br/>or delete unknown "+n.name+", rewire as required, and then deploy.","error");
  328. }
  329. for (i=0;i<newNodes.length;i++) {
  330. n = newNodes[i];
  331. // TODO: remove workspace in next release+1
  332. if (n.type === "workspace" || n.type === "tab") {
  333. if (n.type === "workspace") {
  334. n.type = "tab";
  335. }
  336. if (defaultWorkspace == null) {
  337. defaultWorkspace = n;
  338. }
  339. addWorkspace(n);
  340. RED.view.addWorkspace(n);
  341. }
  342. }
  343. if (defaultWorkspace == null) {
  344. defaultWorkspace = { type:"tab", id:getID(), label:"Sheet 1" };
  345. addWorkspace(defaultWorkspace);
  346. RED.view.addWorkspace(defaultWorkspace);
  347. }
  348. */
  349. var node_map = {};
  350. var new_nodes = [];
  351. var new_links = [];
  352. for (i=0;i<newNodes.length;i++) {
  353. n = newNodes[i];
  354. // TODO: remove workspace in next release+1
  355. if (n.type !== "workspace" && n.type !== "tab") {
  356. var def = getType(n.type);
  357. if (def && def.category == "config") {
  358. if (!RED.nodes.node(n.id)) {
  359. var configNode = {id:n.id,type:n.type,users:[]};
  360. for (var d in def.defaults) {
  361. if (def.defaults.hasOwnProperty(d)) {
  362. configNode[d] = n[d];
  363. }
  364. }
  365. configNode.label = def.label;
  366. configNode._def = def;
  367. RED.nodes.add(configNode);
  368. }
  369. } else {
  370. var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false};
  371. if (createNewIds) {
  372. node.z = RED.view.getWorkspace();
  373. node.id = getID();
  374. } else {
  375. node.id = n.id;
  376. if (node.z == null || !workspaces[node.z]) {
  377. node.z = RED.view.getWorkspace();
  378. }
  379. }
  380. node.type = n.type;
  381. node._def = def;
  382. if (!node._def) {
  383. node._def = {
  384. color:"#fee",
  385. defaults: {},
  386. label: "unknown: "+n.type,
  387. labelStyle: "node_label_italic",
  388. outputs: n.outputs||n.wires.length
  389. }
  390. }
  391. node.outputs = n.outputs||node._def.outputs;
  392. for (var d2 in node._def.defaults) {
  393. if (node._def.defaults.hasOwnProperty(d2)) {
  394. node[d2] = n[d2];
  395. }
  396. }
  397. addNode(node);
  398. RED.editor.validateNode(node);
  399. node_map[n.id] = node;
  400. new_nodes.push(node);
  401. }
  402. }
  403. }
  404. for (i=0;i<new_nodes.length;i++) {
  405. n = new_nodes[i];
  406. for (var w1=0;w1<n.wires.length;w1++) {
  407. var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]];
  408. for (var w2=0;w2<wires.length;w2++) {
  409. var parts = wires[w2].split(":");
  410. if (parts.length == 2 && parts[0] in node_map) {
  411. var dst = node_map[parts[0]];
  412. var link = {source:n,sourcePort:w1,target:dst,targetPort:parts[1]};
  413. addLink(link);
  414. new_links.push(link);
  415. }
  416. }
  417. }
  418. delete n.wires;
  419. }
  420. return [new_nodes,new_links];
  421. } catch(error) {
  422. //TODO: get this UI thing out of here! (see above as well)
  423. RED.notify("<strong>Error</strong>: "+error,"error");
  424. return null;
  425. }
  426. }
  427. return {
  428. registerType: registerType,
  429. getType: getType,
  430. convertNode: convertNode,
  431. add: addNode,
  432. addLink: addLink,
  433. remove: removeNode,
  434. removeLink: removeLink,
  435. addWorkspace: addWorkspace,
  436. removeWorkspace: removeWorkspace,
  437. workspace: getWorkspace,
  438. eachNode: function(cb) {
  439. for (var n=0;n<nodes.length;n++) {
  440. cb(nodes[n]);
  441. }
  442. },
  443. eachLink: function(cb) {
  444. for (var l=0;l<links.length;l++) {
  445. cb(links[l]);
  446. }
  447. },
  448. eachConfig: function(cb) {
  449. for (var id in configNodes) {
  450. if (configNodes.hasOwnProperty(id)) {
  451. cb(configNodes[id]);
  452. }
  453. }
  454. },
  455. node: getNode,
  456. import: importNodes,
  457. refreshValidation: refreshValidation,
  458. getAllFlowNodes: getAllFlowNodes,
  459. createExportableNodeSet: createExportableNodeSet,
  460. createCompleteNodeSet: createCompleteNodeSet,
  461. id: getID,
  462. cppName: createUniqueCppName,
  463. nodes: nodes, // TODO: exposed for d3 vis
  464. links: links // TODO: exposed for d3 vis
  465. };
  466. })();