Source: classes/elements/branch.js

  1. /**
  2. * @class
  3. * @classdesc Represents the line connecting two nodes.
  4. * @extends Syntree.Element
  5. * @extends Syntree.SelectableElement
  6. */
  7. Syntree.Branch = function(parent,child) {
  8. parent = Syntree.Lib.checkArg(parent, 'node');
  9. child = Syntree.Lib.checkArg(child, 'node');
  10. child.parentBranch = this;
  11. parent.childBranches.push(this);
  12. this.parent = parent;
  13. this.child = child;
  14. this.triangle = false;
  15. // Syntree.SelectableElement.call(this);
  16. Syntree.Lib.extend(Syntree.SelectableElement,Syntree.Branch,this);
  17. }
  18. Syntree.Branch.prototype.createGraphic = function() {
  19. this.startPoint = this.parent.getPosition();
  20. this.endPoint = this.child.getPosition();
  21. var shadowLine = Syntree.snap.line(
  22. this.startPoint.x,
  23. this.startPoint.y,
  24. this.endPoint.x,
  25. this.endPoint.y
  26. );
  27. shadowLine.attr({
  28. stroke: 'lightgrey',
  29. strokeWidth: '10px',
  30. class: 'branch-shadow',
  31. id: 'branch-shadow-'+this.id,
  32. });
  33. var line = Syntree.snap.line(
  34. );
  35. line.attr({
  36. stroke:'black',
  37. class: 'branch',
  38. id: 'branch-'+this.id,
  39. });
  40. var triangle = Syntree.snap.path(this.getTrianglePath());
  41. triangle.attr({
  42. stroke: 'black',
  43. fill: 'none',
  44. class: 'triangle',
  45. id: 'triangle-' + this.id,
  46. })
  47. var mid = this.getMidPoint();
  48. var triangleButton = Syntree.snap.image(
  49. '/resources/triangle_button_triangle.png',
  50. mid.x,
  51. mid.y,
  52. 15,
  53. 15
  54. );
  55. triangleButton.attr({
  56. class: 'triangle-button',
  57. id: 'triangle-button-'+this.id,
  58. })
  59. var config_matrix = {
  60. elements_to_add: {
  61. line: {
  62. el_obj: line,
  63. include_in_svg_string: true,
  64. },
  65. shadowLine: {
  66. el_obj: shadowLine,
  67. },
  68. triangle: {
  69. el_obj: triangle,
  70. },
  71. triangleButton: {
  72. el_obj: triangleButton,
  73. },
  74. },
  75. states_synced: {
  76. selected: false,
  77. triangle: false,
  78. parentPosition: false,
  79. childPosition: false,
  80. },
  81. data_object: this,
  82. update_map: {
  83. triangle: {
  84. state_name: 'triangle',
  85. handler: function(d,g) {
  86. if (d.triangle) {
  87. g.getEl('triangle').attr({
  88. path: d.getTrianglePath(),
  89. });
  90. g.getEl('line').attr({
  91. strokeWidth: 0,
  92. });
  93. g.getEl('shadowLine').attr({
  94. strokeWidth: 0,
  95. });
  96. g.getEl('triangleButton').attr({
  97. href: '/resources/triangle_button_triangle.png',
  98. });
  99. } else {
  100. g.getEl('triangle').attr({
  101. path: '',
  102. });
  103. g.getEl('line').attr({
  104. strokeWidth: 1,
  105. });
  106. g.getEl('shadowLine').attr({
  107. strokeWidth: 10,
  108. });
  109. g.getEl('triangleButton').attr({
  110. href: '/resources/triangle_button_branch.png',
  111. });
  112. }
  113. }
  114. },
  115. selected: {
  116. state_name: 'selected',
  117. handler: 'boolean',
  118. elements: {
  119. shadowLine: {
  120. stateTrueAttrs: {
  121. opacity: 1,
  122. },
  123. stateFalseAttrs: {
  124. opacity: 0,
  125. },
  126. },
  127. triangle: {
  128. stateTrueAttrs: {
  129. fill: 'lightgrey',
  130. },
  131. stateFalseAttrs: {
  132. fill: 'white',
  133. }
  134. },
  135. triangleButton: {
  136. stateTrueAttrs: {
  137. visibility: 'visible',
  138. },
  139. stateFalseAttrs: {
  140. visibility: 'hidden',
  141. },
  142. },
  143. }
  144. },
  145. parentPosition: {
  146. state_name: 'parentPosition',
  147. handler: function(d,g) {
  148. d.startPoint = d.parent.getPosition();
  149. var pBBox = d.parent.getLabelBBox();
  150. g.getEl('line').attr({
  151. // x1: d.startPoint.x,
  152. x1: pBBox.cx,
  153. y1: pBBox.y2 + 5,
  154. // y1: d.startPoint.y + (pBBox.height/2),
  155. });
  156. g.getEl('shadowLine').attr({
  157. x1: pBBox.cx,
  158. y1: pBBox.y2 + 5,
  159. // x1: d.startPoint.x,
  160. // y1: d.startPoint.y + (pBBox.height/2),
  161. });
  162. }
  163. },
  164. childPosition: {
  165. state_name: 'childPosition',
  166. handler: function(d,g) {
  167. d.endPoint = d.child.getPosition();
  168. g.getEl('shadowLine').attr({
  169. // x2: d.endPoint.x,
  170. // x2: cBBox.x,
  171. // y2: d.endPoint.y - (cBBox.height/2),
  172. // y2: cBBox.y,
  173. });
  174. }
  175. },
  176. '#default': function(d,g) {
  177. var cBBox = d.child.getLabelBBox();
  178. if (Syntree.Lib.checkType(cBBox.cx, 'number')) {
  179. g.getEl('line').attr({
  180. // x2: d.endPoint.x,
  181. x2: cBBox.cx,
  182. y2: cBBox.y - 5,
  183. // y2: d.endPoint.y - (cBBox.height/2),
  184. });
  185. g.getEl('shadowLine').attr({
  186. // x2: d.endPoint.x,
  187. x2: cBBox.cx,
  188. // y2: d.endPoint.y - (cBBox.height/2),
  189. y2: cBBox.y - 5,
  190. });
  191. }
  192. if (d.triangle) {
  193. g.getEl('triangle').attr({
  194. path: d.getTrianglePath(),
  195. });
  196. }
  197. if (d.selected) {
  198. var mid = d.getMidPoint();
  199. g.getEl('triangleButton').attr({
  200. x: mid.x-7.5,
  201. y: mid.y-7.5,
  202. })
  203. }
  204. }
  205. }
  206. }
  207. this.graphic = new Syntree.Graphic(config_matrix);
  208. }
  209. Syntree.Branch.prototype.toString = function() {
  210. return '[object Branch]'
  211. }
  212. Syntree.Branch.prototype.__delete = function() {
  213. this.parent.childBranches.splice(this.parent.childBranches.indexOf(this), 1);
  214. }
  215. Syntree.Branch.prototype.getMidPoint = function() {
  216. var s = this.getStartPoint();
  217. var e = this.getEndPoint();
  218. return {
  219. x: (s.x + e.x)/2,
  220. y: (s.y + e.y)/2,
  221. }
  222. }
  223. Syntree.Branch.prototype.triangleToggle = function() {
  224. if (this.triangle) {
  225. this.triangle = false;
  226. this.graphic.unsync('triangle');
  227. } else {
  228. this.triangle = true;
  229. this.graphic.unsync('triangle');
  230. }
  231. this.updateGraphics();
  232. }
  233. Syntree.Branch.prototype.getStartPoint = function() {
  234. return {
  235. x: this.parent.getPosition().x,
  236. y: this.parent.getLabelBBox().y2 + 5,
  237. }
  238. }
  239. Syntree.Branch.prototype.getEndPoint = function() {
  240. return {
  241. x: this.child.getPosition().x,
  242. y: this.child.getLabelBBox().y - 5,
  243. }
  244. }
  245. Syntree.Branch.prototype.getTrianglePath = function() {
  246. var start = this.startPoint;
  247. start.y = this.parent.getLabelBBox().y2 + 5;
  248. var cBBox = this.child.getLabelBBox();
  249. var botLeft = {
  250. x: cBBox.x,
  251. y: cBBox.y,
  252. }
  253. var botRight = {
  254. x: cBBox.x2,
  255. y: cBBox.y,
  256. }
  257. s = 'M ' + start.x + ' ' + start.y + ', ';
  258. s += 'L ' + botLeft.x + ' ' + (botLeft.y-5) + ', ';
  259. s += 'L ' + botRight.x + ' ' + (botRight.y-5) + ', ';
  260. s += 'L ' + start.x + ' ' + start.y + ', ';
  261. return s;
  262. }