actionsbuilder.viewer.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. var ActionsBuilder;
  2. (function (ActionsBuilder) {
  3. var Viewer = (function () {
  4. /*
  5. * Constructor
  6. * @param type: the root type object (OBJECT or SCENE)
  7. */
  8. function Viewer(type) {
  9. var _this = this;
  10. this.objectName = "Unnamed Object";
  11. this.zoom = 1.0;
  12. this._firstUpdate = true;
  13. // Get HTML elements
  14. this.viewerContainer = document.getElementById("GraphContainerID");
  15. this.viewerElement = document.getElementById("GraphElementID");
  16. // Create element
  17. this.paper = Raphael("GraphElementID", screen.width, screen.height);
  18. // Configure this
  19. //var name = type === Type.OBJECT ? "Unnamed object" : "Scene";
  20. this.root = this.addAction(null, type, { name: this.objectName, text: this.objectName, properties: [], description: "" });
  21. this.selectedNode = null;
  22. // Configure events
  23. window.addEventListener("resize", function (event) {
  24. _this.onResize(event);
  25. });
  26. window.addEventListener("mousemove", function (event) {
  27. _this.onMove(event);
  28. });
  29. this.paper.canvas.addEventListener("click", function (event) {
  30. _this.onClick(event);
  31. });
  32. // Load modules
  33. this._toolbar = new ActionsBuilder.Toolbar(this);
  34. this._contextMenu = new ActionsBuilder.ContextMenu(this);
  35. this.parameters = new ActionsBuilder.Parameters(this);
  36. this.utils = new ActionsBuilder.Utils(this);
  37. // Finish
  38. this.parameters.parametersHelpElement.textContent = Viewer._DEFAULT_INFO_MESSAGE;
  39. }
  40. Object.defineProperty(Viewer, "NODE_WIDTH", {
  41. get: function () {
  42. return Viewer._NODE_WIDTH;
  43. },
  44. enumerable: true,
  45. configurable: true
  46. });
  47. Object.defineProperty(Viewer, "NODE_HEIGHT", {
  48. get: function () {
  49. return Viewer._NODE_HEIGHT;
  50. },
  51. enumerable: true,
  52. configurable: true
  53. });
  54. Object.defineProperty(Viewer, "NODE_MINIMIZED_WIDTH", {
  55. get: function () {
  56. return Viewer._NODE_MINIMIZE_WIDTH;
  57. },
  58. enumerable: true,
  59. configurable: true
  60. });
  61. Object.defineProperty(Viewer, "VERTICAL_OFFSET", {
  62. get: function () {
  63. return Viewer._VERTICAL_OFFSET;
  64. },
  65. enumerable: true,
  66. configurable: true
  67. });
  68. /*
  69. * Resize event
  70. * @param event: the resize event
  71. */
  72. Viewer.prototype.onResize = function (event) {
  73. var tools = document.getElementById("ToolsButtonsID");
  74. this.viewerContainer.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 - 50 + "px";
  75. this.viewerElement.style.height = window.innerHeight - tools.getBoundingClientRect().height - 25 - 50 + "px";
  76. this.parameters.onResize();
  77. this._toolbar.onResize();
  78. if (this.paper.height < window.innerHeight) {
  79. this.paper.setSize(this.paper.width, window.innerHeight);
  80. }
  81. if (this._firstUpdate) {
  82. this.viewerElement.scrollLeft = ((this.viewerElement.scrollWidth / 2) - (this.viewerElement.getBoundingClientRect().width / 2));
  83. this._firstUpdate = false;
  84. }
  85. };
  86. /*
  87. * Handles the onMove event
  88. * @param event: the onMove mouse event
  89. */
  90. Viewer.prototype.onMove = function (event) {
  91. this.mousex = event.clientX - this.paper.canvas.getBoundingClientRect().left;
  92. this.mousey = event.clientY - this.paper.canvas.getBoundingClientRect().top;
  93. };
  94. /*
  95. * Handles the onClick event to get selected node
  96. * @param event: the onClick mouse event
  97. */
  98. Viewer.prototype.onClick = function (event) {
  99. if (this._contextMenu.showing) {
  100. return;
  101. }
  102. // Reset selected node
  103. if (this.selectedNode !== null) {
  104. var node = this.selectedNode.node;
  105. node.rect.attr("fill", this.getNodeColor(this.selectedNode.type, node.detached));
  106. }
  107. // Configure new selected node
  108. var result = this.traverseGraph(null, this.mousex, this.mousey, true);
  109. if (result.hit) {
  110. this.selectedNode = result.action;
  111. var node = this.selectedNode.node;
  112. node.rect.attr("fill", this.getSelectedNodeColor(this.selectedNode.type, node.detached));
  113. }
  114. else {
  115. this.selectedNode = null;
  116. this.parameters.clearParameters();
  117. this.parameters.parametersHelpElement.textContent = Viewer._DEFAULT_INFO_MESSAGE;
  118. }
  119. };
  120. /*
  121. * Set the color theme of the viewer
  122. * @param color: the color theme ( ex: "rgb(64, 64, 64)" )
  123. */
  124. Viewer.prototype.setColorTheme = function (color) {
  125. this.paper.canvas.style.background = color;
  126. };
  127. /*
  128. * Returns the color according to the given parameters
  129. * @param action: the action used to select the color
  130. * @param detached: if the node is attached to its parent or not
  131. */
  132. Viewer.prototype.getNodeColor = function (type, detached) {
  133. if (detached) {
  134. return Raphael.rgb(96, 122, 14);
  135. }
  136. switch (type) {
  137. case ActionsBuilder.Type.TRIGGER:
  138. return Raphael.rgb(133, 154, 185);
  139. break;
  140. case ActionsBuilder.Type.ACTION:
  141. return Raphael.rgb(182, 185, 132);
  142. break;
  143. case ActionsBuilder.Type.FLOW_CONTROL:
  144. return Raphael.rgb(185, 132, 140);
  145. break;
  146. case ActionsBuilder.Type.OBJECT:
  147. case ActionsBuilder.Type.SCENE:
  148. return Raphael.rgb(255, 255, 255);
  149. break;
  150. default: break;
  151. }
  152. return null;
  153. };
  154. /*
  155. * Returns the selected node color according to the given parameters
  156. * @param action: the action used to select the color
  157. * @param detached: if the node is attached to its parent or not
  158. */
  159. Viewer.prototype.getSelectedNodeColor = function (type, detached) {
  160. if (detached) {
  161. return Raphael.rgb(96, 122, 14);
  162. }
  163. switch (type) {
  164. case ActionsBuilder.Type.TRIGGER:
  165. return Raphael.rgb(41, 129, 255);
  166. break;
  167. case ActionsBuilder.Type.ACTION:
  168. return Raphael.rgb(255, 220, 42);
  169. break;
  170. case ActionsBuilder.Type.FLOW_CONTROL:
  171. return Raphael.rgb(255, 41, 53);
  172. break;
  173. case ActionsBuilder.Type.OBJECT:
  174. case ActionsBuilder.Type.SCENE:
  175. return Raphael.rgb(255, 255, 255);
  176. break;
  177. default: break;
  178. }
  179. return null;
  180. };
  181. /*
  182. * Removes the given action from the graph
  183. * @param action: the action to remove
  184. * @param removeChildren: if remove the branch or not
  185. */
  186. Viewer.prototype.removeAction = function (action, removeChildren) {
  187. // If selected node is combine
  188. if (action.parent !== null && action.parent.hub === action) {
  189. this.removeAction(action.parent, false);
  190. return;
  191. }
  192. // Basic suppress
  193. this.removeNode(action.node);
  194. if (action.combineArray !== null) {
  195. this.removeNode(action.hub.node);
  196. // Remove combine array
  197. for (var i = 0; i < action.combineArray.length; i++) {
  198. this.removeNode(action.combineArray[i].node);
  199. }
  200. action.combineArray.length = 0;
  201. }
  202. if (removeChildren) {
  203. for (var i = 0; i < action.children.length; i++) {
  204. this.removeAction(action.children[i], removeChildren);
  205. }
  206. action.clearChildren();
  207. }
  208. else {
  209. for (var i = 0; i < action.children.length; i++) {
  210. action.parent.addChild(action.children[i]);
  211. action.children[i].parent = action.parent;
  212. }
  213. }
  214. };
  215. /*
  216. * Removes the given node (not the action)
  217. * @param node: the node to remove
  218. */
  219. Viewer.prototype.removeNode = function (node) {
  220. node.rect.remove();
  221. node.text.remove();
  222. if (node.line !== null) {
  223. node.line.remove();
  224. }
  225. };
  226. /*
  227. * Updates the graph viewer
  228. */
  229. Viewer.prototype.update = function () {
  230. var _this = this;
  231. // Set root position
  232. this._setActionPosition(this.root, (this.paper.width / 2) - (Viewer.NODE_WIDTH / 2) * this.zoom, 10);
  233. // Sets node size
  234. var onSetNodeSize = function (node) {
  235. node.rect.attr("width", node.minimized ? Viewer.NODE_MINIMIZED_WIDTH : Viewer.NODE_WIDTH * _this.zoom);
  236. node.rect.attr("height", Viewer.NODE_HEIGHT * _this.zoom);
  237. node.text.attr("font-size", 11 * _this.zoom);
  238. };
  239. // First pass: set actions positions according to parents
  240. var onSetPositionPass = function (action, yPosition) {
  241. var node = action.node;
  242. var parent = action.parent !== null ? action.parent : null;
  243. // Set node properties (size, text size, etc.)
  244. if (action.combineArray !== null) {
  245. for (var i = 0; i < action.combineArray.length; i++) {
  246. var combinedNode = action.combineArray[i].node;
  247. onSetNodeSize(combinedNode);
  248. }
  249. }
  250. onSetNodeSize(node);
  251. // Set position from parent
  252. if (parent) {
  253. var parentx = parent.node.rect.attr("x");
  254. if (parent.combineArray !== null && parent.combineArray.length > 1) {
  255. parentx += parent.node.rect.attr("width") / 2;
  256. }
  257. _this._setActionPosition(action, parentx, yPosition);
  258. _this._setActionLine(action);
  259. }
  260. // Calculate total width for current action
  261. var totalSize = 0;
  262. for (var i = 0; i < action.children.length; i++) {
  263. var childNode = action.children[i].node;
  264. totalSize += childNode.rect.attr("width");
  265. }
  266. // Get values to place nodes according to the parent position
  267. var nodeWidth = node.rect.attr("width");
  268. var startingPositionX = node.rect.attr("x");
  269. // Set children positions
  270. for (var i = 0; i < action.children.length; i++) {
  271. var childAction = action.children[i];
  272. var childNode = childAction.node;
  273. var newPositionX = startingPositionX;
  274. if (childAction.combineArray !== null && childAction.combineArray.length > 1) {
  275. newPositionX -= (childNode.rect.attr("width") / 2) - nodeWidth / 2;
  276. }
  277. var newPositionY = yPosition + Viewer.VERTICAL_OFFSET * _this.zoom;
  278. onSetPositionPass(childAction, newPositionY);
  279. _this._setActionPosition(childAction, newPositionX, newPositionY);
  280. _this._setActionLine(childAction);
  281. }
  282. };
  283. onSetPositionPass(this.root, 10 * this.zoom);
  284. // Seconds pass, get sizes of groups
  285. var onGetSizePass = function (action, maxSize) {
  286. var mySize = 0;
  287. if (action.combineArray !== null) {
  288. for (var i = 0; i < action.combineArray.length; i++) {
  289. mySize += action.combineArray[i].node.rect.attr("width");
  290. }
  291. }
  292. else {
  293. mySize = action.node.rect.attr("width");
  294. }
  295. if (mySize > maxSize) {
  296. maxSize = mySize;
  297. }
  298. for (var i = 0; i < action.children.length; i++) {
  299. maxSize = onGetSizePass(action.children[i], maxSize);
  300. }
  301. return maxSize;
  302. };
  303. // Resize canvas
  304. var onResizeCanvas = function (action) {
  305. var node = action.node;
  306. var nodex = node.rect.attr("x");
  307. var nodey = node.rect.attr("y");
  308. if (nodex < 0 || nodex > _this.paper.width) {
  309. _this.paper.setSize(_this.paper.width + 1000, _this.paper.height);
  310. _this._setActionPosition(_this.root, (_this.paper.width / 2) - (Viewer.NODE_WIDTH / 2) * _this.zoom, 10);
  311. }
  312. if (nodey > _this.paper.height) {
  313. _this.paper.setSize(_this.paper.width, _this.paper.height + 1000);
  314. _this._setActionPosition(_this.root, (_this.paper.width / 2) - (Viewer.NODE_WIDTH / 2) * _this.zoom, 10);
  315. }
  316. };
  317. var widths = new Array();
  318. for (var i = 0; i < this.root.children.length; i++) {
  319. var trigger = this.root.children[i];
  320. var triggerResult = { triggerWidth: onGetSizePass(trigger, 0), childrenWidths: new Array() };
  321. if (trigger.children.length > 0) {
  322. triggerResult.triggerWidth = 0;
  323. }
  324. for (var j = 0; j < trigger.children.length; j++) {
  325. var actionWidth = onGetSizePass(trigger.children[j], 0);
  326. triggerResult.triggerWidth += actionWidth + 15;
  327. triggerResult.childrenWidths.push({
  328. triggerWidth: actionWidth,
  329. childrenWidths: null
  330. });
  331. }
  332. widths.push(triggerResult);
  333. }
  334. // Third pass, set positions of nodes
  335. var onSetNodePosition = function (action, widthArray, isChild) {
  336. var actionsCount = action.children.length;
  337. var actionsMiddle = actionsCount % 2;
  338. var actionsHasMiddle = actionsMiddle !== 0;
  339. var actionsLeftOffset = 0;
  340. var actionsRightOffset = 0;
  341. var actionWidth = action.node.rect.attr("width");
  342. if (actionsHasMiddle && actionsCount > 1) {
  343. var middle = Math.floor(actionsCount / 2);
  344. actionsLeftOffset += widthArray[middle].triggerWidth / 2;
  345. actionsRightOffset += widthArray[middle].triggerWidth / 2;
  346. }
  347. // Move left
  348. var leftStart = actionsHasMiddle ? Math.floor(actionsCount / 2) - 1 : (actionsCount / 2) - 1;
  349. for (var i = leftStart; i >= 0; i--) {
  350. var child = action.children[i];
  351. var node = child.node;
  352. var width = (widthArray[i].triggerWidth) + 15;
  353. _this._setActionPosition(action.children[i], node.rect.attr("x") - actionsLeftOffset - (width / 2), node.rect.attr("y"));
  354. _this._setActionLine(child);
  355. onResizeCanvas(child);
  356. actionsLeftOffset += width;
  357. }
  358. // Move right
  359. var rightStart = actionsHasMiddle ? Math.round(actionsCount / 2) : actionsCount / 2;
  360. for (var i = rightStart; i < actionsCount; i++) {
  361. var child = action.children[i];
  362. var node = child.node;
  363. var width = (widthArray[i].triggerWidth) + 15;
  364. _this._setActionPosition(action.children[i], node.rect.attr("x") + actionsRightOffset + (width / 2), node.rect.attr("y"));
  365. _this._setActionLine(child);
  366. onResizeCanvas(child);
  367. actionsRightOffset += width;
  368. }
  369. };
  370. onSetNodePosition(this.root, widths, false);
  371. for (var i = 0; i < this.root.children.length; i++) {
  372. onSetNodePosition(this.root.children[i], widths[i].childrenWidths, true);
  373. }
  374. };
  375. /*
  376. * Adds an action to the graph viewer and returns it
  377. * @param parent: the parent action
  378. * @param type: the action type
  379. * @param element: the Actions Builder type (TRIGGERS, ACTIONS, FLOW_CONTROLS)
  380. */
  381. Viewer.prototype.addAction = function (parent, type, element) {
  382. var node = this._createNode(element.text, type, parent === null);
  383. var action = new ActionsBuilder.Action(node);
  384. if (element.name === "CombineAction") {
  385. action.combineArray = new Array();
  386. var hubElement = ActionsBuilder.Elements.FLOW_CONTROLS[ActionsBuilder.Elements.FLOW_CONTROLS.length - 1];
  387. var hub = this.addAction(action, ActionsBuilder.Type.FLOW_CONTROL, hubElement);
  388. action.hub = hub;
  389. action.addChild(hub);
  390. this._createActionAnimation(hub);
  391. }
  392. action.name = element.name;
  393. action.properties = element.properties;
  394. action.type = type;
  395. // Configure properties
  396. for (var i = 0; i < action.properties.length; i++) {
  397. action.propertiesResults.push({ targetType: action.properties[i].targetType, value: action.properties[i].value });
  398. }
  399. if (action.properties !== null && action.properties.length > 0) {
  400. if (action.properties[0].text === "target") {
  401. action.propertiesResults[0].value = this.objectName;
  402. }
  403. }
  404. if (parent !== null) {
  405. if (parent.combineArray === null) {
  406. parent.addChild(action);
  407. }
  408. else if (parent.combineArray !== null && action.name !== "Hub") {
  409. parent.combineArray.push(action);
  410. action.parent = parent;
  411. action.combineAction = parent;
  412. parent.node.text.attr("text", "");
  413. }
  414. }
  415. // Create animation
  416. this._createActionAnimation(action);
  417. return action;
  418. };
  419. /*
  420. * Traverses the graph viewer and returns if an action
  421. * is selected at coordinates (x, y)
  422. * @param start: the start node. Can be null
  423. * @param x: the x coordinate
  424. * @param y: the y coordinate
  425. * @param traverseCombine: if we traverse combine actions children
  426. */
  427. Viewer.prototype.traverseGraph = function (start, x, y, traverseCombine) {
  428. if (start === null)
  429. start = this.root;
  430. var result = { action: start, hit: true };
  431. if (start.node.isPointInside(x, y)) {
  432. return result;
  433. }
  434. for (var i = 0; i < start.children.length; i++) {
  435. var action = start.children[i];
  436. if (action.node.isPointInside(x, y)) {
  437. result.hit = true;
  438. result.action = start.children[i];
  439. if (traverseCombine && action.combineArray !== null) {
  440. for (var j = 0; j < action.combineArray.length; j++) {
  441. if (action.combineArray[j].node.isPointInside(x, y)) {
  442. result.action = action.combineArray[j];
  443. break;
  444. }
  445. }
  446. }
  447. return result;
  448. }
  449. result = this.traverseGraph(action, x, y, traverseCombine);
  450. if (result.hit) {
  451. return result;
  452. }
  453. }
  454. result.hit = false;
  455. result.action = null;
  456. return result;
  457. };
  458. /*
  459. * Sets the action's position (node)
  460. * @param action: the action to place
  461. * @param x: the x position of the action
  462. * @param y: the y position of the action
  463. */
  464. Viewer.prototype._setActionPosition = function (action, x, y) {
  465. var node = action.node;
  466. var offsetx = node.rect.attr("x") - x;
  467. var parent = action.parent;
  468. if (parent !== null && parent.combineArray !== null && parent.combineArray.length > 1) {
  469. var parentNode = parent.node;
  470. x = parentNode.rect.attr("x") + (parent.node.rect.attr("width") / 2) - (node.rect.attr("width") / 2);
  471. }
  472. node.rect.attr("x", x);
  473. node.rect.attr("y", y);
  474. var textBBox = node.text.getBBox();
  475. var textWidth = 0;
  476. if (textBBox !== null && textBBox !== undefined) {
  477. textWidth = textBBox.width;
  478. }
  479. node.text.attr("x", x + node.rect.attr("width") / 2 - textWidth / 2);
  480. node.text.attr("y", y + node.rect.attr("height") / 2);
  481. if (action.combineArray !== null && action.combineArray.length > 0) {
  482. var length = 0;
  483. for (var i = 0; i < action.combineArray.length; i++) {
  484. var combinedAction = action.combineArray[i];
  485. var combinedNode = combinedAction.node;
  486. combinedNode.rect.attr("x", node.rect.attr("x") + length);
  487. combinedNode.rect.attr("y", node.rect.attr("y"));
  488. textBBox = combinedNode.text.getBBox();
  489. if (textBBox !== null) {
  490. textWidth = textBBox.width;
  491. }
  492. combinedNode.text.attr("x", combinedNode.rect.attr("x") + combinedNode.rect.attr("width") / 2 - textWidth / 2);
  493. combinedNode.text.attr("y", y + combinedNode.rect.attr("height") / 2);
  494. length += combinedNode.rect.attr("width");
  495. }
  496. node.rect.attr("width", length);
  497. }
  498. for (var i = 0; i < action.children.length; i++) {
  499. var child = action.children[i];
  500. this._setActionPosition(child, child.node.rect.attr("x") - offsetx, y + Viewer.VERTICAL_OFFSET * this.zoom);
  501. this._setActionLine(child);
  502. }
  503. };
  504. /*
  505. * Configures the line (link) between the action and its parent
  506. * @param action: the action to configure
  507. */
  508. Viewer.prototype._setActionLine = function (action) {
  509. if (action.node.line === null) {
  510. return;
  511. }
  512. var node = action.node;
  513. var nodex = node.rect.attr("x");
  514. var nodey = node.rect.attr("y");
  515. var nodeWidth = node.rect.attr("width");
  516. var nodeHeight = node.rect.attr("height");
  517. var parent = action.parent.node;
  518. var parentx = parent.rect.attr("x");
  519. var parenty = parent.rect.attr("y");
  520. var parentWidth = parent.rect.attr("width");
  521. var parentHeight = parent.rect.attr("height");
  522. if (node.detached) {
  523. node.line.attr("path", ["M", nodex, nodey, "L", nodex, nodey]);
  524. return;
  525. }
  526. var line1x = nodex + (nodeWidth / 2);
  527. var line1y = nodey;
  528. var line2y = line1y - (line1y - parenty - parentHeight) / 2;
  529. var line3x = parentx + (parentWidth / 2);
  530. var line4y = parenty + parentHeight;
  531. node.line.attr("path", ["M", line1x, line1y, "L", line1x, line2y, "L", line3x, line2y, "L", line3x, line4y]);
  532. };
  533. /*
  534. * Creates and returns a node
  535. * @param text: the text to draw in the nde
  536. * @param color: the node's color
  537. * @param noLine: if draw a line to the parent or not
  538. */
  539. Viewer.prototype._createNode = function (text, type, noLine) {
  540. var node = new ActionsBuilder.Node();
  541. var color = this.getNodeColor(type, false);
  542. node.rect = this.paper.rect(20, 20, Viewer.NODE_WIDTH, Viewer.NODE_HEIGHT, 0);
  543. node.rect.attr("fill", color);
  544. node.text = this.paper.text(20, 20, text);
  545. node.text.attr("font-size", 11);
  546. node.text.attr("text-anchor", "start");
  547. node.text.attr("font-family", "Sinkin Sans Light");
  548. if (!noLine) {
  549. node.line = this.paper.path("");
  550. node.line.attr("stroke", color);
  551. }
  552. return node;
  553. };
  554. /*
  555. * Creates the drag animation
  556. * @param action: the action to animate
  557. */
  558. Viewer.prototype._createActionAnimation = function (action) {
  559. var _this = this;
  560. var node = action.node;
  561. var finished = true;
  562. var nodex = 0;
  563. var nodey = 0;
  564. var onMove = function (dx, dy, x, y) { };
  565. var onStart = function (x, y, event) {
  566. if (node.minimized) {
  567. return;
  568. }
  569. if (finished) {
  570. nodex = node.rect.attr("x");
  571. nodey = node.rect.attr("y");
  572. }
  573. finished = false;
  574. node.rect.animate({
  575. x: node.rect.attr("x") - 10,
  576. y: node.rect.attr("y"),
  577. width: (Viewer.NODE_WIDTH + 20) * _this.zoom,
  578. height: (Viewer.NODE_HEIGHT + 10) * _this.zoom,
  579. opacity: 0.25
  580. }, 500, ">");
  581. };
  582. var onEnd = function (event) {
  583. if (!node.minimized) {
  584. node.rect.animate({
  585. x: nodex,
  586. y: nodey,
  587. width: Viewer.NODE_WIDTH * _this.zoom,
  588. height: Viewer.NODE_HEIGHT * _this.zoom,
  589. opacity: 1.0
  590. }, 500, ">", function () { finished = true; });
  591. }
  592. var dragResult = _this.traverseGraph(null, _this.mousex, _this.mousey, true);
  593. if (dragResult.hit && dragResult.action === action || !dragResult.hit) {
  594. // Create parameters. Action can be null
  595. _this.parameters.createParameters(action);
  596. }
  597. else {
  598. // Manage drag'n'drop
  599. if (dragResult.action.children.length > 0 && action.type !== ActionsBuilder.Type.TRIGGER) {
  600. return;
  601. }
  602. if (action.type === ActionsBuilder.Type.TRIGGER && dragResult.action !== _this.root) {
  603. return;
  604. }
  605. if (action.type === ActionsBuilder.Type.ACTION && dragResult.action === _this.root) {
  606. return;
  607. }
  608. if (action.type === ActionsBuilder.Type.FLOW_CONTROL && (dragResult.action === _this.root || dragResult.action.type === ActionsBuilder.Type.FLOW_CONTROL)) {
  609. return;
  610. }
  611. if (action === dragResult.action.parent) {
  612. return;
  613. }
  614. if (action.parent !== null && action.parent.combineArray !== null) {
  615. return;
  616. }
  617. // Reset node
  618. node.rect.stop(node.rect.animation);
  619. node.text.stop(node.text.animation);
  620. node.rect.undrag();
  621. node.text.undrag();
  622. node.rect.attr("opacity", 1.0);
  623. node.rect.attr("width", Viewer.NODE_WIDTH);
  624. node.rect.attr("height", Viewer.NODE_HEIGHT);
  625. if (action.parent !== null) {
  626. // Configure drag'n'drop
  627. action.parent.removeChild(action);
  628. dragResult.action.addChild(action);
  629. _this.update();
  630. _this._createActionAnimation(action);
  631. }
  632. }
  633. };
  634. node.rect.drag(onMove, onStart, onEnd);
  635. node.text.drag(onMove, onStart, onEnd);
  636. };
  637. // Statics
  638. Viewer._NODE_WIDTH = 150;
  639. Viewer._NODE_HEIGHT = 25;
  640. Viewer._NODE_MINIMIZE_WIDTH = 50;
  641. Viewer._VERTICAL_OFFSET = 70;
  642. Viewer._DEFAULT_INFO_MESSAGE = "Select or add a node to customize actions";
  643. return Viewer;
  644. })();
  645. ActionsBuilder.Viewer = Viewer;
  646. })(ActionsBuilder || (ActionsBuilder = {}));