viewer.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. /// <reference path="raphael.js" />
  2. /// <reference path="action.js" />
  3. /// <reference path="contextmenu.js" />
  4. /// <reference path="viewertoolbar.js" />
  5. /// <reference path="parametersManager.js" />
  6. /// <reference path="utils.js" />
  7. var AB;
  8. (function (AB) {
  9. var Graph = (function () {
  10. //
  11. // Public functions
  12. //
  13. function Graph() {
  14. var scope = this;
  15. // Members
  16. this.element = document.getElementById("Graph");
  17. this.graph = Raphael("Graph", (50 * screen.width) / 100, screen.height);
  18. this.root = this._createNode("Object name", Raphael.rgb(255, 255, 255), true);
  19. this.utils = new AB.Utils(this);
  20. this.contextMenu = new AB.ContextMenu(this);
  21. this.toolbar = new AB.ToolBar(this);
  22. this.parametersManager = new AB.ParametersManager(this);
  23. this.mousex = 0;
  24. this.mousey = 0;
  25. this.objectName = "";
  26. this.editing = false;
  27. this.zoom = 1.0;
  28. this.selectedNode = null;
  29. this.element.onmouseover = function () {
  30. scope.editing = false;
  31. };
  32. this.element.onmouseout = function () {
  33. scope.editing = true;
  34. };
  35. document.addEventListener("click", function (event) {
  36. if (!scope.contextMenu.showing) {
  37. scope.onClick(event);
  38. }
  39. });
  40. document.ondblclick = function (event) {
  41. var result = scope.traverseGraph(null, scope.mousex, scope.mousey);
  42. if (result.hit && result.element.node != scope.root) {
  43. scope.onReduce();
  44. }
  45. };
  46. document.onmousemove = function (event) {
  47. scope.mousex = event.clientX - scope.graph.canvas.getBoundingClientRect().left;
  48. scope.mousey = event.clientY - scope.graph.canvas.getBoundingClientRect().top;
  49. };
  50. // Set properties
  51. this.element.scrollLeft = (this.element.getBoundingClientRect().width / 2) + (Graph.NODE_WIDTH / 2);
  52. }
  53. // Handles the click event. Called by this and this.contextmenu
  54. // event: the event object
  55. Graph.prototype.onClick = function (event) {
  56. var result = this.traverseGraph(null, this.mousex, this.mousey, true);
  57. if (!this.editing) {
  58. if (this.selectedNode != null) {
  59. var detached = this.isParentDetached(this.selectedNode);
  60. this.selectedNode.node.attr(this.selectedNode.node.rect, "fill", this.getNodeColor(this.selectedNode, detached));
  61. this.selectedNode = null;
  62. if (!result.hit)
  63. this.parametersManager.clearParameters();
  64. }
  65. if (result.hit && result.element.node != this.root) {
  66. this.selectedNode = result.element;
  67. this.selectedNode.node.attr(this.selectedNode.node.rect, "fill", this.getSelectedNodeColor(this.selectedNode, detached));
  68. }
  69. if (!result.hit)
  70. this.selectedNode = null;
  71. }
  72. }
  73. // Returns the node's color for a given type
  74. // action : the action to test
  75. // returns the node color
  76. Graph.prototype.getSelectedNodeColor = function (action, detached) {
  77. // Detached
  78. if (action.detached || (action.node && action.node.detached) || detached)
  79. return Raphael.rgb(96, 122, 14);
  80. // Get proper color
  81. var color = Raphael.rgb(255, 255, 255); // Default color for root
  82. switch (action.type) {
  83. case AB.ActionsBuilder.Type.TRIGGER: color = Raphael.rgb(41, 129, 255); break;
  84. case AB.ActionsBuilder.Type.ACTION: color = Raphael.rgb(255, 220, 42); break;
  85. case AB.ActionsBuilder.Type.FLOW_CONTROL: color = Raphael.rgb(255, 41, 53); break;
  86. }
  87. return color;
  88. }
  89. Graph.prototype.getNodeColor = function (action, detached) {
  90. if (action.detached || (action.node && action.node.detached) || detached)
  91. return Raphael.rgb(96, 122, 14);
  92. // Get proper color
  93. var color = Raphael.rgb(255, 255, 255); // Default color for root
  94. switch (action.type) {
  95. case AB.ActionsBuilder.Type.TRIGGER: color = Raphael.rgb(133, 154, 185); break;
  96. case AB.ActionsBuilder.Type.ACTION: color = Raphael.rgb(182, 185, 132); break;
  97. case AB.ActionsBuilder.Type.FLOW_CONTROL: color = Raphael.rgb(185, 132, 140); break;
  98. }
  99. return color;
  100. }
  101. Graph.prototype.isParentDetached = function (node) {
  102. var parent = node.parent;
  103. while (parent != null) {
  104. if (parent.node.detached)
  105. return true;
  106. parent = parent.parent;
  107. }
  108. return false;
  109. }
  110. // Adds a node to the graph
  111. // parent : the parent of the added node
  112. // listElement : the values
  113. Graph.prototype.addNode = function (parent, listElement) {
  114. var color = this.getNodeColor(listElement);
  115. var n = this._createNode(listElement.name, color, parent.combine ? true : false);
  116. if (listElement.name == "CombineAction") {
  117. n.action.combine = true;
  118. var hubElement = AB.ActionsBuilder.FlowAction.Hub;
  119. var hubType = AB.ActionsBuilder.Type.FLOW_CONTROL;
  120. n.action.hub = this._createNode(hubElement.name, this.getNodeColor({ type: hubType }), false);
  121. n.action.hub.action.type = hubType;
  122. n.action.addChild(n.action.hub.action);
  123. this._createNodeAnimation(n.action.hub);
  124. }
  125. n.action.name = listElement.name;
  126. n.action.type = listElement.type;
  127. n.detached = listElement.detached || false;
  128. n.action.properties = listElement.properties;
  129. for (var i = 0; i < listElement.properties.length; i++)
  130. n.action.propertiesResults.push(listElement.properties[i].value);
  131. if (parent && !parent.combine) {
  132. parent.addChild(n.action);
  133. }
  134. else if (parent.combine) {
  135. // Create hub
  136. parent.combineArray.push(n.action);
  137. n.action.parent = parent;
  138. parent.node.attr(parent.node.text, "text", "");
  139. }
  140. this._createNodeAnimation(n);
  141. return n;
  142. }
  143. // Updates the graph
  144. Graph.prototype.update = function () {
  145. var scope = this;
  146. var rootChildID = 0;
  147. var setNodeSize = function(node) {
  148. if (node.minimized) {
  149. node.attr(node.rect, "width", Graph.NODE_MINIMIZED_WIDTH * scope.zoom);
  150. node.attr(node.rect, "height", Graph.NODE_HEIGHT * scope.zoom);
  151. }
  152. else {
  153. node.attr(node.rect, "width", Graph.NODE_WIDTH * scope.zoom);
  154. node.attr(node.rect, "height", Graph.NODE_HEIGHT * scope.zoom);
  155. }
  156. node.attr(node.text, "font-size", 11 * scope.zoom);
  157. }
  158. var onUpdate = function (action, yOffset) {
  159. var node = action.node;
  160. var parent = action.parent ? action.parent.node : null;
  161. // Set size of node according to zoom
  162. if (action.combine) {
  163. var length = 0;
  164. for (var i = 0; i < action.combineArray.length; i++) {
  165. var n = action.combineArray[i].node;
  166. setNodeSize(n);
  167. length += n.attr(n.rect, "width");
  168. }
  169. }
  170. setNodeSize(node);
  171. // Set position
  172. if (parent) {
  173. scope._setNodePosition(node, parent.attr(parent.rect, "x"), yOffset);
  174. scope._setLine(action);
  175. }
  176. // Calculate total width
  177. var totalWidth = 0;
  178. for (var i = 0; i < action.children.length; i++) {
  179. var n = action.children[i].node;
  180. totalWidth += n.attr(n.rect, "width");
  181. }
  182. var nodeWidth = node.attr(node.rect, "width");
  183. var nodex = node.attr(node.rect, "x");
  184. var startingXPos = nodex + (nodeWidth / 2) - (totalWidth / 2);
  185. // Recursively set position of children
  186. for (var i = 0; i < action.children.length; i++) {
  187. var n = action.children[i].node;
  188. var newx = startingXPos;
  189. var newy = yOffset + Graph.VERTICAL_OFFSET * scope.zoom;
  190. onUpdate(n.action, newy);
  191. scope._setNodePosition(n, newx, newy);
  192. scope._setLine(n.action);
  193. startingXPos += n.attr(n.rect, "width");
  194. }
  195. };
  196. var onPosition = function (action, maxWidth) {
  197. var total = 0;
  198. var start = action.combine && action.combineArray.length > 1 ? 0 : 1;
  199. for (var i = start; i < action.children.length; i++) {
  200. var n = action.children[i].node;
  201. if (action.combine) {
  202. for (var j = 1; j < action.combineArray.length; j++) {
  203. var cn = action.combineArray[j].node;
  204. total += cn.attr(cn.rect, "width");
  205. }
  206. }
  207. else
  208. total += n.attr(n.rect, "width");
  209. }
  210. if (total > maxWidth) {
  211. maxWidth = total;
  212. }
  213. for (var i = 0; i < action.children.length; i++) {
  214. maxWidth = onPosition(action.children[i], maxWidth);
  215. }
  216. return maxWidth;
  217. };
  218. // Set root node position / scale and recursively set position of its children
  219. this._setNodePosition(this.root, (this.graph.width / 2) - (Graph.NODE_WIDTH / 2) * this.zoom, 10);
  220. this.root.attr(this.root.rect, "width", Graph.NODE_WIDTH * scope.zoom);
  221. this.root.attr(this.root.rect, "height", Graph.NODE_HEIGHT * scope.zoom);
  222. onUpdate(this.root.action, 10 * this.zoom);
  223. // Get total widths
  224. var widths = new Array();
  225. /*
  226. object:
  227. {
  228. triggerWidth: number
  229. childrenWidths: new Array<number>()
  230. }
  231. */
  232. for (var i = 0; i < scope.root.action.children.length; i++) {
  233. var a = scope.root.action.children[i];
  234. var obj = {
  235. triggerWidth: onPosition(a, 0),
  236. childrenWidths: new Array()
  237. };
  238. for (var j = 0; j < a.children.length; j++) {
  239. var cw = onPosition(a.children[j], 0);
  240. obj.childrenWidths.push(cw);
  241. obj.triggerWidth += cw;
  242. }
  243. widths.push(obj);
  244. }
  245. // Set new position of children
  246. var rx = scope.root.attr(scope.root.rect, "x");
  247. var rwidth = 0;
  248. var cwidth = 0;
  249. for (var i = 0; i < scope.root.action.children.length; i++) {
  250. var a = scope.root.action.children[i];
  251. var tx = a.node.attr(a.node.rect, "x");
  252. for (var j = 0; j < a.children.length; j++) {
  253. var n = a.children[j].node;
  254. var x = n.attr(n.rect, "x");
  255. var y = n.attr(n.rect, "y");
  256. var inverse = x >= tx ? 1 : -1;
  257. scope._setNodePosition(n, x + (scope.root.action.children.length > 1 ? widths[i].childrenWidths[j] / 1.8 : 0) * inverse, y);
  258. scope._setLine(n.action);
  259. scope._resizeCanvas(n);
  260. cwidth += widths[i].childrenWidths[j] / 2;
  261. }
  262. if (scope.root.action.children.length > 1) {
  263. var n = a.node;
  264. var x = n.attr(n.rect, "x");
  265. var y = n.attr(n.rect, "y");
  266. var inverse = x >= rx && i == 0 && !n.minimized ? 1 : -1;
  267. scope._setNodePosition(n, x + rwidth + (i > 1 ? widths[i - 1].triggerWidth / 1.8 : 0) + (widths[i].triggerWidth / 1.8) * inverse, y);
  268. scope._setLine(n.action);
  269. scope._resizeCanvas(n);
  270. }
  271. rwidth += widths[i].triggerWidth / 2;
  272. }
  273. }
  274. // Creates the JSON according to the graph
  275. // root: the root object to start with
  276. Graph.prototype.createJSON = function (root) {
  277. if (!root) root = this.root.action;
  278. var action = {};
  279. action.type = root.type;
  280. action.name = root.name;
  281. action.detached = root.node.detached;
  282. action.children = new Array();
  283. action.combine = new Array();
  284. action.properties = new Array();
  285. for (var i = 0; i < root.properties.length; i++) {
  286. action.properties[i] = { name: root.properties[i].text, value: root.propertiesResults[i] };
  287. if (root.properties[i].targetType != null)
  288. action.properties[i].targetType = root.properties[i].targetType;
  289. }
  290. if (root.combine) {
  291. for (var i = 0; i < root.combineArray.length; i++) {
  292. var combinedAction = root.combineArray[i];
  293. action.combine.push(this.createJSON(combinedAction, action));
  294. }
  295. }
  296. if (root.combine)
  297. root = root.children[0]; // The hub
  298. for (var i = 0; i < root.children.length; i++) {
  299. action.children.push(this.createJSON(root.children[i], action));
  300. }
  301. return action;
  302. }
  303. // Loads a graph from a JSON
  304. // Graph: the root object's graph
  305. // startNode: the start node to where begin the load
  306. Graph.prototype.loadFromJSON = function (graph, startNode) {
  307. var scope = this;
  308. // If startNode is null, means it replaces all the graph
  309. // If not, it comes from a copy/paste
  310. if (startNode == null) {
  311. for (var i = 0; i < this.root.action.children.length; i++)
  312. this._removeAction(this.root.action.children[i], true);
  313. this.root.action.clearChildren();
  314. }
  315. var load = function (root, parent, detached, combine) {
  316. if (!parent) parent = scope.root.action;
  317. if (!root) root = graph;
  318. if (!detached) detached = false;
  319. if (!combine) combine = false;
  320. var n = null; // Not going to be created
  321. if (root.type != AB.ActionsBuilder.Type.OBJECT) { // Means it is not the root (the edited object)
  322. var e = {};
  323. e.type = root.type;
  324. e.name = root.name;
  325. e.detached = root.detached;
  326. e.combine = root.combine.length > 0;
  327. e.properties = new Array();
  328. e.combineArray = new Array();
  329. for (var i = 0; i < root.properties.length; i++) {
  330. e.properties.push({ text: root.properties[i].name, value: root.properties[i].value });
  331. if (root.properties[i].targetType != null) {
  332. e.properties[e.properties.length - 1].targetType = root.properties[i].targetType;
  333. }
  334. }
  335. n = scope.addNode(parent, e);
  336. if (detached)
  337. n.attr(n.rect, "fill", scope.getNodeColor(n.action));
  338. else
  339. detached = n.detached;
  340. // If combine array length > 0, it is a combine action
  341. for (var i = 0; i < root.combine.length; i++) {
  342. load(root.combine[i], n.action, detached, true);
  343. }
  344. if (!combine)
  345. parent = parent.children[parent.children.length - 1];
  346. else
  347. n.action.parent = null;
  348. }
  349. for (var i = 0; i < root.children.length; i++) {
  350. load(root.children[i], n && n.action.combine ? n.action.hub.action : parent, root.detached, false);
  351. }
  352. }
  353. load(graph, startNode);
  354. this.update();
  355. }
  356. // Traverse the graph and returns if hit a node
  357. // start: the start node to start traverse
  358. // x: the mouse's x position
  359. // y: the mouse's y position
  360. // traverseCombine: if check the combine nodes
  361. Graph.prototype.traverseGraph = function (start, x, y, traverseCombine) {
  362. if (!start) start = this.root.action;
  363. if (traverseCombine == null) traverseCombine = false;
  364. var result = {
  365. hit: true,
  366. element: start
  367. };
  368. if (start.node.isPointInside(x, y))
  369. return result;
  370. for (var i = 0; i < start.children.length; i++) {
  371. if (start.children[i].node.isPointInside(x, y)) {
  372. result.hit = true;
  373. result.element = start.children[i];
  374. if (start.children[i].combine && traverseCombine) {
  375. var a = start.children[i];
  376. for (var j = 0; j < a.combineArray.length; j++) {
  377. if (a.combineArray[j].node.isPointInside(x, y)) {
  378. result.element = a.combineArray[j];
  379. break;
  380. }
  381. }
  382. }
  383. return result;
  384. }
  385. result = this.traverseGraph(start.children[i], x, y, traverseCombine);
  386. if (result.hit)
  387. return result;
  388. }
  389. result.hit = false;
  390. result.element = null;
  391. return result;
  392. }
  393. //
  394. // Private functions
  395. //
  396. // Sets the given node's line
  397. // If commented, the line isn't setted by hidden
  398. Graph.prototype._setLine = function (element) {
  399. var n = element.node;
  400. var nodeWidth = n.attr(n.rect, "width");
  401. var nodeHeight = n.attr(n.rect, "height");
  402. var nodex = n.attr(n.rect, "x");
  403. var nodey = n.attr(n.rect, "y");
  404. if (n.detached) {
  405. n.attr(n.line, "path", ["M", nodex, nodey, "L", nodex, nodey]);
  406. return;
  407. }
  408. var linex = n.attr(n.rect, "x") + nodeWidth / 2;
  409. var liney = n.attr(n.rect, "y");
  410. var p = element.parent.node;
  411. var parentWidth = p.attr(p.rect, "width");
  412. var parentHeight = p.attr(p.rect, "height");
  413. var parentx = p.attr(p.rect, "x");
  414. var parenty = p.attr(p.rect, "y");
  415. var liney2 = liney - (liney - parenty - parentHeight) / 2;
  416. var linex3 = parentx + parentWidth / 2;
  417. var liney4 = parenty + parentHeight;
  418. n.attr(n.line, "path", ["M", linex, liney, "L", linex, liney2, "L", linex3, liney2, "L", linex3, liney4]);
  419. n.attr(n.line, "stroke", this.getSelectedNodeColor(element, element.node.detached));
  420. }
  421. // Sets the given node's position
  422. // Applies changements on its children
  423. Graph.prototype._setNodePosition = function (node, x, y) {
  424. var offsetx = node.attr(node.rect, "x") - x;
  425. node.attr(node.rect, "x", x);
  426. node.attr(node.rect, "y", y);
  427. var bbox = node.text.getBBox();
  428. var textWidth = 0;
  429. if (bbox)
  430. textWidth = node.text.getBBox().width;
  431. node.attr(node.text, "x", x + node.attr(node.rect, "width") / 2 - textWidth / 2);
  432. node.attr(node.text, "y", y + node.attr(node.rect, "height") / 2);
  433. // Set combine nodes positions
  434. if (node.action.combine) {
  435. var length = 0;
  436. for (var i = 0; i < node.action.combineArray.length; i++) {
  437. var a = node.action.combineArray[i];
  438. var n = a.node;
  439. n.attr(n.rect, "x", node.attr(node.rect, "x") + length);
  440. n.attr(n.rect, "y", node.attr(node.rect, "y"));
  441. textWidth = n.text.getBBox().width;
  442. n.attr(n.text, "x", n.attr(n.rect, "x") + n.attr(n.rect, "width") / 2 - textWidth / 2);
  443. n.attr(n.text, "y", y + Graph.NODE_HEIGHT / 2);
  444. length += n.attr(n.rect, "width");
  445. }
  446. node.attr(node.rect, "width", length);
  447. }
  448. for (var i = 0; i < node.action.children.length; i++) {
  449. this._setNodePosition(node.action.children[i].node, node.action.children[i].node.attr(node.action.children[i].node.rect, "x") - offsetx, y + Graph.VERTICAL_OFFSET);
  450. this._setLine(node.action.children[i]);
  451. }
  452. }
  453. // Resizes the canvas if the node is outside the current canvas size
  454. Graph.prototype._resizeCanvas = function (node) {
  455. var x = node.attr(node.rect, "x");
  456. var y = node.attr(node.rect, "y");
  457. if (x > 0 + Graph.NODE_WIDTH && x < this.graph.width - Graph.NODE_WIDTH && y < this.graph.height)
  458. return;
  459. this.graph.setSize(this.graph.width + 500, this.graph.height + 500);
  460. this._setNodePosition(this.root, (this.graph.width / 2) - (Graph.NODE_WIDTH / 2), 10);
  461. this.element.scrollLeft = (this.graph.width / 2) - this.element.getBoundingClientRect().width / 2;
  462. }
  463. // Removes a node
  464. // node : the node to remove
  465. Graph.prototype._removeNode = function (node) {
  466. node.rect.remove();
  467. node.text.remove();
  468. if (node.line)
  469. node.line.remove();
  470. }
  471. // Remove an action from the graph
  472. // action : the action to remove
  473. // removeChildren : if true, it deletes the branch
  474. Graph.prototype._removeAction = function (action, removeChildren) {
  475. if (!removeChildren)
  476. removeChildren = false;
  477. this._removeNode(action.node);
  478. if (action.combine) {
  479. for (var i = 0; i < action.combineArray.length; i++) {
  480. this._removeNode(action.combineArray[i].node);
  481. }
  482. action.combineArray = new Array();
  483. }
  484. if (removeChildren) {
  485. for (var i = 0; i < action.children.length; i++)
  486. this._removeAction(action.children[i], removeChildren);
  487. action.clearChildren();
  488. }
  489. else {
  490. for (var i = 0; i < action.children.length; i++) {
  491. action.parent.addChild(action.children[i]);
  492. action.children[i].parent = action.parent;
  493. }
  494. }
  495. }
  496. // Creates a node
  497. // text : the text/name of the node
  498. // color : the node's color
  499. // noLine : if the node has parent then draw a line, or not
  500. Graph.prototype._createNode = function (text, color, noLine) {
  501. var n = new AB.Node();
  502. n.rect = this.graph.rect(20, 20, Graph.NODE_WIDTH, Graph.NODE_HEIGHT, 0);
  503. n.text = this.graph.text(0, 0, text);
  504. if (!noLine) {
  505. n.line = this.graph.path("M10 10L90 90");
  506. n.line.attr("stroke", color);
  507. }
  508. n.action = new AB.Action(n);
  509. n.rect.attr("fill", color);
  510. n.text.attr("font-size", 11);
  511. n.text.attr("text-anchor", "start");
  512. n.text.attr("font-family", "Sinkin Sans Light");
  513. return n;
  514. }
  515. // Creates the animations for a node
  516. // element: the node
  517. Graph.prototype._createNodeAnimation = function (element) {
  518. var scope = this;
  519. var mousex, mousey;
  520. var finished = true;
  521. var elementx = 0;
  522. var elementy = 0;
  523. var onMove = function (dx, dy, x, y, event) {
  524. mousex = x;
  525. mousey = y;
  526. };
  527. var onStart = function (x, y, event) {
  528. if (element.minimized)
  529. return;
  530. mousex = x;
  531. mousey = y;
  532. if (finished) {
  533. elementx = element.attr(element.rect, "x");
  534. elementy = element.attr(element.rect, "y");
  535. }
  536. finished = false;
  537. if (!element.minimized) {
  538. element.rect.animate({
  539. x: element.attr(element.rect, "x") - 10,
  540. y: element.attr(element.rect, "y") - 5,
  541. width: element.minimized ? Graph.NODE_MINIMIZED_WIDTH + 20 : Graph.NODE_WIDTH + 20,
  542. height: Graph.NODE_HEIGHT + 10,
  543. opacity: 0.25
  544. }, 500, ">");
  545. }
  546. };
  547. var onEnd = function (event) {
  548. if (!element.minimized) {
  549. element.rect.animate({
  550. x: elementx,
  551. y: elementy,
  552. width: element.minimized ? Graph.NODE_MINIMIZED_WIDTH : Graph.NODE_WIDTH,
  553. height: Graph.NODE_HEIGHT,
  554. opacity: 1.0
  555. }, 500, ">", function () { finished = true; });
  556. }
  557. var x = mousex - scope.graph.canvas.getBoundingClientRect().left;
  558. var y = mousey - scope.graph.canvas.getBoundingClientRect().top;
  559. var dragResult = scope.traverseGraph(null, x, y, true);
  560. if (dragResult.hit && dragResult.element == element.action || !dragResult.hit) {
  561. scope.parametersManager.createParameters(element);
  562. }
  563. else {
  564. if (dragResult.element.children.length > 0 && dragResult.element.type != AB.ActionsBuilder.Type.TRIGGER)
  565. return;
  566. if (element.action.type == AB.ActionsBuilder.Type.TRIGGER && dragResult.element != scope.root.action)
  567. return;
  568. if (element.action.type == AB.ActionsBuilder.Type.ACTION && dragResult.element == scope.root.action)
  569. return;
  570. if (element.action.type == AB.ActionsBuilder.Type.FLOW_CONTROL && (dragResult.element == scope.root.action || dragResult.element.type == AB.ActionsBuilder.Type.FLOW_CONTROL))
  571. return;
  572. if (element.action.parent && element.action.parent.combine) // Musn't move hubs
  573. return;
  574. if (element.action == dragResult.element.parent)
  575. return;
  576. // Reset node
  577. element.rect.stop(element.rect.animation);
  578. element.attr(element.rect, "opacity", 1.0);
  579. element.attr(element.rect, "width", Graph.NODE_WIDTH);
  580. element.attr(element.rect, "height", Graph.NODE_HEIGHT);
  581. if (element.action.parent) {
  582. element.action.parent.removeChild(element.action);
  583. dragResult.element.addChild(element.action);
  584. scope.update();
  585. scope._createNodeAnimation(element);
  586. }
  587. }
  588. };
  589. element.rect.drag(onMove, onStart, onEnd);
  590. element.text.drag(onMove, onStart, onEnd);
  591. }
  592. Graph.NODE_MINIMIZED_WIDTH = 50;
  593. Graph.NODE_WIDTH = 150;
  594. Graph.NODE_HEIGHT = 25;
  595. Graph.VERTICAL_OFFSET = 70;
  596. return Graph;
  597. })();
  598. AB.Graph = Graph;
  599. })(AB || (AB = {}));