summaryrefslogtreecommitdiff
path: root/src/js/layout/mxPartitionLayout.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/layout/mxPartitionLayout.js')
-rw-r--r--src/js/layout/mxPartitionLayout.js240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/js/layout/mxPartitionLayout.js b/src/js/layout/mxPartitionLayout.js
new file mode 100644
index 0000000..d3592f8
--- /dev/null
+++ b/src/js/layout/mxPartitionLayout.js
@@ -0,0 +1,240 @@
+/**
+ * $Id: mxPartitionLayout.js,v 1.25 2010-01-04 11:18:25 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxPartitionLayout
+ *
+ * Extends <mxGraphLayout> for partitioning the parent cell vertically or
+ * horizontally by filling the complete area with the child cells. A horizontal
+ * layout partitions the height of the given parent whereas a a non-horizontal
+ * layout partitions the width. If the parent is a layer (that is, a child of
+ * the root node), then the current graph size is partitioned. The children do
+ * not need to be connected for this layout to work.
+ *
+ * Example:
+ *
+ * (code)
+ * var layout = new mxPartitionLayout(graph, true, 10, 20);
+ * layout.execute(graph.getDefaultParent());
+ * (end)
+ *
+ * Constructor: mxPartitionLayout
+ *
+ * Constructs a new stack layout layout for the specified graph,
+ * spacing, orientation and offset.
+ */
+function mxPartitionLayout(graph, horizontal, spacing, border)
+{
+ mxGraphLayout.call(this, graph);
+ this.horizontal = (horizontal != null) ? horizontal : true;
+ this.spacing = spacing || 0;
+ this.border = border || 0;
+};
+
+/**
+ * Extends mxGraphLayout.
+ */
+mxPartitionLayout.prototype = new mxGraphLayout();
+mxPartitionLayout.prototype.constructor = mxPartitionLayout;
+
+/**
+ * Variable: horizontal
+ *
+ * Boolean indicating the direction in which the space is partitioned.
+ * Default is true.
+ */
+mxPartitionLayout.prototype.horizontal = null;
+
+/**
+ * Variable: spacing
+ *
+ * Integer that specifies the absolute spacing in pixels between the
+ * children. Default is 0.
+ */
+mxPartitionLayout.prototype.spacing = null;
+
+/**
+ * Variable: border
+ *
+ * Integer that specifies the absolute inset in pixels for the parent that
+ * contains the children. Default is 0.
+ */
+mxPartitionLayout.prototype.border = null;
+
+/**
+ * Variable: resizeVertices
+ *
+ * Boolean that specifies if vertices should be resized. Default is true.
+ */
+mxPartitionLayout.prototype.resizeVertices = true;
+
+/**
+ * Function: isHorizontal
+ *
+ * Returns <horizontal>.
+ */
+mxPartitionLayout.prototype.isHorizontal = function()
+{
+ return this.horizontal;
+};
+
+/**
+ * Function: moveCell
+ *
+ * Implements <mxGraphLayout.moveCell>.
+ */
+mxPartitionLayout.prototype.moveCell = function(cell, x, y)
+{
+ var model = this.graph.getModel();
+ var parent = model.getParent(cell);
+
+ if (cell != null &&
+ parent != null)
+ {
+ var i = 0;
+ var last = 0;
+ var childCount = model.getChildCount(parent);
+
+ // Finds index of the closest swimlane
+ // TODO: Take into account the orientation
+ for (i = 0; i < childCount; i++)
+ {
+ var child = model.getChildAt(parent, i);
+ var bounds = this.getVertexBounds(child);
+
+ if (bounds != null)
+ {
+ var tmp = bounds.x + bounds.width / 2;
+
+ if (last < x && tmp > x)
+ {
+ break;
+ }
+
+ last = tmp;
+ }
+ }
+
+ // Changes child order in parent
+ var idx = parent.getIndex(cell);
+ idx = Math.max(0, i - ((i > idx) ? 1 : 0));
+
+ model.add(parent, cell, idx);
+ }
+};
+
+/**
+ * Function: execute
+ *
+ * Implements <mxGraphLayout.execute>. All children where <isVertexIgnored>
+ * returns false and <isVertexMovable> returns true are modified.
+ */
+mxPartitionLayout.prototype.execute = function(parent)
+{
+ var horizontal = this.isHorizontal();
+ var model = this.graph.getModel();
+ var 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 (this.graph.container != null &&
+ ((pgeo == null &&
+ model.isLayer(parent)) ||
+ parent == this.graph.getView().currentRoot))
+ {
+ var width = this.graph.container.offsetWidth - 1;
+ var height = this.graph.container.offsetHeight - 1;
+ pgeo = new mxRectangle(0, 0, width, height);
+ }
+
+ if (pgeo != null)
+ {
+ var children = [];
+ var childCount = model.getChildCount(parent);
+
+ for (var i = 0; i < childCount; i++)
+ {
+ var child = model.getChildAt(parent, i);
+
+ if (!this.isVertexIgnored(child) &&
+ this.isVertexMovable(child))
+ {
+ children.push(child);
+ }
+ }
+
+ var n = children.length;
+
+ if (n > 0)
+ {
+ var x0 = this.border;
+ var y0 = this.border;
+ var other = (horizontal) ? pgeo.height : pgeo.width;
+ other -= 2 * this.border;
+
+ var size = (this.graph.isSwimlane(parent)) ?
+ this.graph.getStartSize(parent) :
+ new mxRectangle();
+
+ other -= (horizontal) ? size.height : size.width;
+ x0 = x0 + size.width;
+ y0 = y0 + size.height;
+
+ var tmp = this.border + (n - 1) * this.spacing;
+ var value = (horizontal) ?
+ ((pgeo.width - x0 - tmp) / n) :
+ ((pgeo.height - 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 (var i = 0; i < n; i++)
+ {
+ var child = children[i];
+ var geo = model.getGeometry(child);
+
+ if (geo != null)
+ {
+ geo = geo.clone();
+ geo.x = x0;
+ geo.y = y0;
+
+ if (horizontal)
+ {
+ if (this.resizeVertices)
+ {
+ geo.width = value;
+ geo.height = other;
+ }
+
+ x0 += value + this.spacing;
+ }
+ else
+ {
+ if (this.resizeVertices)
+ {
+ geo.height = value;
+ geo.width = other;
+ }
+
+ y0 += value + this.spacing;
+ }
+
+ model.setGeometry(child, geo);
+ }
+ }
+ }
+ finally
+ {
+ model.endUpdate();
+ }
+ }
+ }
+ }
+};