diff options
Diffstat (limited to 'src/js/layout/mxPartitionLayout.js')
-rw-r--r-- | src/js/layout/mxPartitionLayout.js | 240 |
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(); + } + } + } + } +}; |