package com.mxgraph.layout; import java.util.ArrayList; import java.util.List; import com.mxgraph.model.mxGeometry; import com.mxgraph.model.mxICell; import com.mxgraph.model.mxIGraphModel; import com.mxgraph.util.mxRectangle; import com.mxgraph.view.mxGraph; public class mxPartitionLayout extends mxGraphLayout { /** * Boolean indicating the direction in which the space is partitioned. * Default is true. */ protected boolean horizontal; /** * Integer that specifies the absolute spacing in pixels between the * children. Default is 0. */ protected int spacing; /** * Integer that specifies the absolute inset in pixels for the parent that * contains the children. Default is 0. */ protected int border; /** * Boolean that specifies if vertices should be resized. Default is true. */ protected boolean resizeVertices = true; /** * Constructs a new stack layout layout for the specified graph, * spacing, orientation and offset. */ public mxPartitionLayout(mxGraph graph) { this(graph, true); } /** * Constructs a new stack layout layout for the specified graph, * spacing, orientation and offset. */ public mxPartitionLayout(mxGraph graph, boolean horizontal) { this(graph, horizontal, 0); } /** * Constructs a new stack layout layout for the specified graph, * spacing, orientation and offset. */ public mxPartitionLayout(mxGraph graph, boolean horizontal, int spacing) { this(graph, horizontal, spacing, 0); } /** * Constructs a new stack layout layout for the specified graph, * spacing, orientation and offset. */ public mxPartitionLayout(mxGraph graph, boolean horizontal, int spacing, int border) { super(graph); this.horizontal = horizontal; this.spacing = spacing; this.border = border; } /* * (non-Javadoc) * @see com.mxgraph.layout.mxGraphLayout#move(java.lang.Object, double, double) */ public void moveCell(Object cell, double x, double y) { mxIGraphModel model = graph.getModel(); Object parent = model.getParent(cell); if (cell instanceof mxICell && parent instanceof mxICell) { int i = 0; double last = 0; int childCount = model.getChildCount(parent); // Finds index of the closest swimlane // TODO: Take into account the orientation for (i = 0; i < childCount; i++) { Object child = model.getChildAt(parent, i); mxRectangle bounds = getVertexBounds(child); if (bounds != null) { double tmp = bounds.getX() + bounds.getWidth() / 2; if (last < x && tmp > x) { break; } last = tmp; } } // Changes child order in parent int idx = ((mxICell) parent).getIndex((mxICell) cell); idx = Math.max(0, i - ((i > idx) ? 1 : 0)); model.add(parent, cell, idx); } } /** * Hook for subclassers to return the container size. */ public mxRectangle getContainerSize() { return new mxRectangle(); } /* * (non-Javadoc) * @see com.mxgraph.layout.mxIGraphLayout#execute(java.lang.Object) */ public void execute(Object parent) { mxIGraphModel model = graph.getModel(); mxGeometry pgeo = model.getGeometry(parent); // Handles special case where the parent is either a layer with no // geometry or the current root of the view in which case the size // of the graph's container will be used. if (pgeo == null && model.getParent(parent) == model.getRoot() || parent == graph.getView().getCurrentRoot()) { mxRectangle tmp = getContainerSize(); pgeo = new mxGeometry(0, 0, tmp.getWidth(), tmp.getHeight()); } if (pgeo != null) { int childCount = model.getChildCount(parent); List<Object> children = new ArrayList<Object>(childCount); for (int i = 0; i < childCount; i++) { Object child = model.getChildAt(parent, i); if (!isVertexIgnored(child) && isVertexMovable(child)) { children.add(child); } } int n = children.size(); if (n > 0) { double x0 = border; double y0 = border; double other = (horizontal) ? pgeo.getHeight() : pgeo .getWidth(); other -= 2 * border; mxRectangle size = graph.getStartSize(parent); other -= (horizontal) ? size.getHeight() : size.getWidth(); x0 = x0 + size.getWidth(); y0 = y0 + size.getHeight(); double tmp = border + (n - 1) * spacing; double value = (horizontal) ? ((pgeo.getWidth() - x0 - tmp) / n) : ((pgeo.getHeight() - y0 - tmp) / n); // Avoids negative values, that is values where the sum of the // spacing plus the border is larger then the available space if (value > 0) { model.beginUpdate(); try { for (int i = 0; i < n; i++) { Object child = children.get(i); mxGeometry geo = model.getGeometry(child); if (geo != null) { geo = (mxGeometry) geo.clone(); geo.setX(x0); geo.setY(y0); if (horizontal) { if (resizeVertices) { geo.setWidth(value); geo.setHeight(other); } x0 += value + spacing; } else { if (resizeVertices) { geo.setHeight(value); geo.setWidth(other); } y0 += value + spacing; } model.setGeometry(child, geo); } } } finally { model.endUpdate(); } } } } } }