mxCircleLayout.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /**
  2. * Copyright (c) 2006-2015, JGraph Ltd
  3. * Copyright (c) 2006-2015, Gaudenz Alder
  4. */
  5. /**
  6. * Class: mxCircleLayout
  7. *
  8. * Extends <mxGraphLayout> to implement a circluar layout for a given radius.
  9. * The vertices do not need to be connected for this layout to work and all
  10. * connections between vertices are not taken into account.
  11. *
  12. * Example:
  13. *
  14. * (code)
  15. * var layout = new mxCircleLayout(graph);
  16. * layout.execute(graph.getDefaultParent());
  17. * (end)
  18. *
  19. * Constructor: mxCircleLayout
  20. *
  21. * Constructs a new circular layout for the specified radius.
  22. *
  23. * Arguments:
  24. *
  25. * graph - <mxGraph> that contains the cells.
  26. * radius - Optional radius as an int. Default is 100.
  27. */
  28. function mxCircleLayout(graph, radius)
  29. {
  30. mxGraphLayout.call(this, graph);
  31. this.radius = (radius != null) ? radius : 100;
  32. };
  33. /**
  34. * Extends mxGraphLayout.
  35. */
  36. mxCircleLayout.prototype = new mxGraphLayout();
  37. mxCircleLayout.prototype.constructor = mxCircleLayout;
  38. /**
  39. * Variable: radius
  40. *
  41. * Integer specifying the size of the radius. Default is 100.
  42. */
  43. mxCircleLayout.prototype.radius = null;
  44. /**
  45. * Variable: moveCircle
  46. *
  47. * Boolean specifying if the circle should be moved to the top,
  48. * left corner specified by <x0> and <y0>. Default is false.
  49. */
  50. mxCircleLayout.prototype.moveCircle = false;
  51. /**
  52. * Variable: x0
  53. *
  54. * Integer specifying the left coordinate of the circle.
  55. * Default is 0.
  56. */
  57. mxCircleLayout.prototype.x0 = 0;
  58. /**
  59. * Variable: y0
  60. *
  61. * Integer specifying the top coordinate of the circle.
  62. * Default is 0.
  63. */
  64. mxCircleLayout.prototype.y0 = 0;
  65. /**
  66. * Variable: resetEdges
  67. *
  68. * Specifies if all edge points of traversed edges should be removed.
  69. * Default is true.
  70. */
  71. mxCircleLayout.prototype.resetEdges = true;
  72. /**
  73. * Variable: disableEdgeStyle
  74. *
  75. * Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are
  76. * modified by the result. Default is true.
  77. */
  78. mxCircleLayout.prototype.disableEdgeStyle = true;
  79. /**
  80. * Function: execute
  81. *
  82. * Implements <mxGraphLayout.execute>.
  83. */
  84. mxCircleLayout.prototype.execute = function(parent)
  85. {
  86. var model = this.graph.getModel();
  87. // Moves the vertices to build a circle. Makes sure the
  88. // radius is large enough for the vertices to not
  89. // overlap
  90. model.beginUpdate();
  91. try
  92. {
  93. // Gets all vertices inside the parent and finds
  94. // the maximum dimension of the largest vertex
  95. var max = 0;
  96. var top = null;
  97. var left = null;
  98. var vertices = [];
  99. var childCount = model.getChildCount(parent);
  100. for (var i = 0; i < childCount; i++)
  101. {
  102. var cell = model.getChildAt(parent, i);
  103. if (!this.isVertexIgnored(cell))
  104. {
  105. vertices.push(cell);
  106. var bounds = this.getVertexBounds(cell);
  107. if (top == null)
  108. {
  109. top = bounds.y;
  110. }
  111. else
  112. {
  113. top = Math.min(top, bounds.y);
  114. }
  115. if (left == null)
  116. {
  117. left = bounds.x;
  118. }
  119. else
  120. {
  121. left = Math.min(left, bounds.x);
  122. }
  123. max = Math.max(max, Math.max(bounds.width, bounds.height));
  124. }
  125. else if (!this.isEdgeIgnored(cell))
  126. {
  127. // Resets the points on the traversed edge
  128. if (this.resetEdges)
  129. {
  130. this.graph.resetEdge(cell);
  131. }
  132. if (this.disableEdgeStyle)
  133. {
  134. this.setEdgeStyleEnabled(cell, false);
  135. }
  136. }
  137. }
  138. var r = this.getRadius(vertices.length, max);
  139. // Moves the circle to the specified origin
  140. if (this.moveCircle)
  141. {
  142. left = this.x0;
  143. top = this.y0;
  144. }
  145. this.circle(vertices, r, left, top);
  146. }
  147. finally
  148. {
  149. model.endUpdate();
  150. }
  151. };
  152. /**
  153. * Function: getRadius
  154. *
  155. * Returns the radius to be used for the given vertex count. Max is the maximum
  156. * width or height of all vertices in the layout.
  157. */
  158. mxCircleLayout.prototype.getRadius = function(count, max)
  159. {
  160. return Math.max(count * max / Math.PI, this.radius);
  161. };
  162. /**
  163. * Function: circle
  164. *
  165. * Executes the circular layout for the specified array
  166. * of vertices and the given radius. This is called from
  167. * <execute>.
  168. */
  169. mxCircleLayout.prototype.circle = function(vertices, r, left, top)
  170. {
  171. var vertexCount = vertices.length;
  172. var phi = 2 * Math.PI / vertexCount;
  173. for (var i = 0; i < vertexCount; i++)
  174. {
  175. if (this.isVertexMovable(vertices[i]))
  176. {
  177. this.setVertexLocation(vertices[i],
  178. Math.round(left + r + r * Math.sin(i * phi)),
  179. Math.round(top + r + r * Math.cos(i * phi)));
  180. }
  181. }
  182. };
  183. __mxOutput.mxCircleLayout = typeof mxCircleLayout !== 'undefined' ? mxCircleLayout : undefined;