package com.mxgraph.layout; import java.util.ArrayList; import java.util.List; import com.mxgraph.model.mxIGraphModel; import com.mxgraph.util.mxRectangle; import com.mxgraph.view.mxGraph; public class mxCircleLayout extends mxGraphLayout { /** * Integer specifying the size of the radius. Default is 100. */ protected double radius; /** * Boolean specifying if the circle should be moved to the top, * left corner specified by x0 and y0. Default is false. */ protected boolean moveCircle = true; /** * Integer specifying the left coordinate of the circle. * Default is 0. */ protected double x0 = 0; /** * Integer specifying the top coordinate of the circle. * Default is 0. */ protected double y0 = 0; /** * Specifies if all edge points of traversed edges should be removed. * Default is true. */ protected boolean resetEdges = false; /** * Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are * modified by the result. Default is true. */ protected boolean disableEdgeStyle = true; /** * Constructs a new stack layout layout for the specified graph, * spacing, orientation and offset. */ public mxCircleLayout(mxGraph graph) { this(graph, 100); } /** * Constructs a new stack layout layout for the specified graph, * spacing, orientation and offset. */ public mxCircleLayout(mxGraph graph, double radius) { super(graph); this.radius = radius; } /** * @return the radius */ public double getRadius() { return radius; } /** * @param radius the radius to set */ public void setRadius(double radius) { this.radius = radius; } /** * @return the moveCircle */ public boolean isMoveCircle() { return moveCircle; } /** * @param moveCircle the moveCircle to set */ public void setMoveCircle(boolean moveCircle) { this.moveCircle = moveCircle; } /** * @return the x0 */ public double getX0() { return x0; } /** * @param x0 the x0 to set */ public void setX0(double x0) { this.x0 = x0; } /** * @return the y0 */ public double getY0() { return y0; } /** * @param y0 the y0 to set */ public void setY0(double y0) { this.y0 = y0; } /** * @return the resetEdges */ public boolean isResetEdges() { return resetEdges; } /** * @param resetEdges the resetEdges to set */ public void setResetEdges(boolean resetEdges) { this.resetEdges = resetEdges; } /** * @return the disableEdgeStyle */ public boolean isDisableEdgeStyle() { return disableEdgeStyle; } /** * @param disableEdgeStyle the disableEdgeStyle to set */ public void setDisableEdgeStyle(boolean disableEdgeStyle) { this.disableEdgeStyle = disableEdgeStyle; } /* * (non-Javadoc) * @see com.mxgraph.layout.mxIGraphLayout#execute(java.lang.Object) */ public void execute(Object parent) { mxIGraphModel model = graph.getModel(); // Moves the vertices to build a circle. Makes sure the // radius is large enough for the vertices to not // overlap model.beginUpdate(); try { // Gets all vertices inside the parent and finds // the maximum dimension of the largest vertex double max = 0; Double top = null; Double left = null; List<Object> vertices = new ArrayList<Object>(); int childCount = model.getChildCount(parent); for (int i = 0; i < childCount; i++) { Object cell = model.getChildAt(parent, i); if (!isVertexIgnored(cell)) { vertices.add(cell); mxRectangle bounds = getVertexBounds(cell); if (top == null) { top = bounds.getY(); } else { top = Math.min(top, bounds.getY()); } if (left == null) { left = bounds.getX(); } else { left = Math.min(left, bounds.getX()); } max = Math.max(max, Math.max(bounds.getWidth(), bounds .getHeight())); } else if (!isEdgeIgnored(cell)) { if (isResetEdges()) { graph.resetEdge(cell); } if (isDisableEdgeStyle()) { setEdgeStyleEnabled(cell, false); } } } int vertexCount = vertices.size(); double r = Math.max(vertexCount * max / Math.PI, radius); // Moves the circle to the specified origin if (moveCircle) { left = x0; top = y0; } circle(vertices.toArray(), r, left.doubleValue(), top.doubleValue()); } finally { model.endUpdate(); } } /** * Executes the circular layout for the specified array * of vertices and the given radius. */ public void circle(Object[] vertices, double r, double left, double top) { int vertexCount = vertices.length; double phi = 2 * Math.PI / vertexCount; for (int i = 0; i < vertexCount; i++) { if (isVertexMovable(vertices[i])) { setVertexLocation(vertices[i], left + r + r * Math.sin(i * phi), top + r + r * Math.cos(i * phi)); } } } }