/** * Copyright (c) 2006-2015, JGraph Ltd * Copyright (c) 2006-2015, Gaudenz Alder */ /** * Class: mxPartitionLayout * * Extends 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 . */ mxPartitionLayout.prototype.isHorizontal = function() { return this.horizontal; }; /** * Function: moveCell * * Implements . */ 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 . All children where * returns false and 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(); } } } } };