123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- /**
- * Copyright (c) 2006-2015, JGraph Ltd
- * Copyright (c) 2006-2015, Gaudenz Alder
- */
- /**
- * Class: mxStackLayout
- *
- * Extends <mxGraphLayout> to create a horizontal or vertical stack of the
- * child vertices. The children do not need to be connected for this layout
- * to work.
- *
- * Example:
- *
- * (code)
- * var layout = new mxStackLayout(graph, true);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxStackLayout
- *
- * Constructs a new stack layout layout for the specified graph,
- * spacing, orientation and offset.
- */
- function mxStackLayout(graph, horizontal, spacing, x0, y0, border)
- {
- mxGraphLayout.call(this, graph);
- this.horizontal = (horizontal != null) ? horizontal : true;
- this.spacing = (spacing != null) ? spacing : 0;
- this.x0 = (x0 != null) ? x0 : 0;
- this.y0 = (y0 != null) ? y0 : 0;
- this.border = (border != null) ? border : 0;
- };
- /**
- * Extends mxGraphLayout.
- */
- mxStackLayout.prototype = new mxGraphLayout();
- mxStackLayout.prototype.constructor = mxStackLayout;
- /**
- * Variable: horizontal
- *
- * Specifies the orientation of the layout. Default is true.
- */
- mxStackLayout.prototype.horizontal = null;
- /**
- * Variable: spacing
- *
- * Specifies the spacing between the cells. Default is 0.
- */
- mxStackLayout.prototype.spacing = null;
- /**
- * Variable: x0
- *
- * Specifies the horizontal origin of the layout. Default is 0.
- */
- mxStackLayout.prototype.x0 = null;
- /**
- * Variable: y0
- *
- * Specifies the vertical origin of the layout. Default is 0.
- */
- mxStackLayout.prototype.y0 = null;
- /**
- * Variable: border
- *
- * Border to be added if fill is true. Default is 0.
- */
- mxStackLayout.prototype.border = 0;
- /**
- * Variable: marginTop
- *
- * Top margin for the child area. Default is 0.
- */
- mxStackLayout.prototype.marginTop = 0;
- /**
- * Variable: marginLeft
- *
- * Top margin for the child area. Default is 0.
- */
- mxStackLayout.prototype.marginLeft = 0;
- /**
- * Variable: marginRight
- *
- * Top margin for the child area. Default is 0.
- */
- mxStackLayout.prototype.marginRight = 0;
- /**
- * Variable: marginBottom
- *
- * Top margin for the child area. Default is 0.
- */
- mxStackLayout.prototype.marginBottom = 0;
- /**
- * Variable: keepFirstLocation
- *
- * Boolean indicating if the location of the first cell should be
- * kept, that is, it will not be moved to x0 or y0. Default is false.
- */
- mxStackLayout.prototype.keepFirstLocation = false;
- /**
- * Variable: fill
- *
- * Boolean indicating if dimension should be changed to fill out the parent
- * cell. Default is false.
- */
- mxStackLayout.prototype.fill = false;
-
- /**
- * Variable: resizeParent
- *
- * If the parent should be resized to match the width/height of the
- * stack. Default is false.
- */
- mxStackLayout.prototype.resizeParent = false;
- /**
- * Variable: resizeParentMax
- *
- * Use maximum of existing value and new value for resize of parent.
- * Default is false.
- */
- mxStackLayout.prototype.resizeParentMax = false;
- /**
- * Variable: resizeLast
- *
- * If the last element should be resized to fill out the parent. Default is
- * false. If <resizeParent> is true then this is ignored.
- */
- mxStackLayout.prototype.resizeLast = false;
- /**
- * Variable: wrap
- *
- * Value at which a new column or row should be created. Default is null.
- */
- mxStackLayout.prototype.wrap = null;
- /**
- * Variable: borderCollapse
- *
- * If the strokeWidth should be ignored. Default is true.
- */
- mxStackLayout.prototype.borderCollapse = true;
- /**
- * Variable: allowGaps
- *
- * If gaps should be allowed in the stack. Default is false.
- */
- mxStackLayout.prototype.allowGaps = false;
- /**
- * Variable: gridSize
- *
- * Grid size for alignment of position and size. Default is 0.
- */
- mxStackLayout.prototype.gridSize = 0;
- /**
- * Function: isHorizontal
- *
- * Returns <horizontal>.
- */
- mxStackLayout.prototype.isHorizontal = function()
- {
- return this.horizontal;
- };
- /**
- * Function: moveCell
- *
- * Implements <mxGraphLayout.moveCell>.
- */
- mxStackLayout.prototype.moveCell = function(cell, x, y)
- {
- var model = this.graph.getModel();
- var parent = model.getParent(cell);
- var horizontal = this.isHorizontal();
-
- if (cell != null && parent != null)
- {
- var i = 0;
- var last = 0;
- var childCount = model.getChildCount(parent);
- var value = (horizontal) ? x : y;
- var pstate = this.graph.getView().getState(parent);
- if (pstate != null)
- {
- value -= (horizontal) ? pstate.x : pstate.y;
- }
-
- value /= this.graph.view.scale;
-
- for (i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
-
- if (child != cell)
- {
- var bounds = model.getGeometry(child);
-
- if (bounds != null)
- {
- var tmp = (horizontal) ?
- bounds.x + bounds.width / 2 :
- bounds.y + bounds.height / 2;
-
- if (last <= value && tmp > value)
- {
- 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: getParentSize
- *
- * Returns the size for the parent container or the size of the graph
- * container if the parent is a layer or the root of the model.
- */
- mxStackLayout.prototype.getParentSize = function(parent)
- {
- 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);
- }
-
- return pgeo;
- };
- /**
- * Function: getLayoutCells
- *
- * Returns the cells to be layouted.
- */
- mxStackLayout.prototype.getLayoutCells = function(parent)
- {
- var model = this.graph.getModel();
- var childCount = model.getChildCount(parent);
- var cells = [];
-
- for (var i = 0; i < childCount; i++)
- {
- var child = model.getChildAt(parent, i);
-
- if (!this.isVertexIgnored(child) && this.isVertexMovable(child))
- {
- cells.push(child);
- }
- }
-
- if (this.allowGaps)
- {
- cells.sort(mxUtils.bind(this, function(c1, c2)
- {
- var geo1 = this.graph.getCellGeometry(c1);
- var geo2 = this.graph.getCellGeometry(c2);
-
- return (this.horizontal) ?
- ((geo1.x == geo2.x) ? 0 : ((geo1.x > geo2.x > 0) ? 1 : -1)) :
- ((geo1.y == geo2.y) ? 0 : ((geo1.y > geo2.y > 0) ? 1 : -1));
- }));
- }
-
- return cells;
- };
- /**
- * Function: snap
- *
- * Snaps the given value to the grid size.
- */
- mxStackLayout.prototype.snap = function(value)
- {
- if (this.gridSize != null && this.gridSize > 0)
- {
- value = Math.max(value, this.gridSize);
-
- if (value / this.gridSize > 1)
- {
- var mod = value % this.gridSize;
- value += mod > this.gridSize / 2 ? (this.gridSize - mod) : -mod;
- }
- }
-
- return value;
- };
- /**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>.
- *
- * Only children where <isVertexIgnored> returns false are taken into
- * account.
- */
- mxStackLayout.prototype.execute = function(parent)
- {
- if (parent != null)
- {
- var pgeo = this.getParentSize(parent);
- var horizontal = this.isHorizontal();
- var model = this.graph.getModel();
- var fillValue = null;
-
- if (pgeo != null)
- {
- fillValue = (horizontal) ? pgeo.height - this.marginTop - this.marginBottom :
- pgeo.width - this.marginLeft - this.marginRight;
- }
-
- fillValue -= 2 * this.border;
- var x0 = this.x0 + this.border + this.marginLeft;
- var y0 = this.y0 + this.border + this.marginTop;
-
- // Handles swimlane start size
- if (this.graph.isSwimlane(parent))
- {
- // Uses computed style to get latest
- var style = this.graph.getCellStyle(parent);
- var start = mxUtils.getNumber(style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE);
- var horz = mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true) == 1;
- if (pgeo != null)
- {
- if (horz)
- {
- start = Math.min(start, pgeo.height);
- }
- else
- {
- start = Math.min(start, pgeo.width);
- }
- }
-
- if (horizontal == horz)
- {
- fillValue -= start;
- }
- if (horz)
- {
- y0 += start;
- }
- else
- {
- x0 += start;
- }
- }
- model.beginUpdate();
- try
- {
- var tmp = 0;
- var last = null;
- var lastValue = 0;
- var lastChild = null;
- var cells = this.getLayoutCells(parent);
-
- for (var i = 0; i < cells.length; i++)
- {
- var child = cells[i];
- var geo = model.getGeometry(child);
-
- if (geo != null)
- {
- geo = geo.clone();
-
- if (this.wrap != null && last != null)
- {
- if ((horizontal && last.x + last.width +
- geo.width + 2 * this.spacing > this.wrap) ||
- (!horizontal && last.y + last.height +
- geo.height + 2 * this.spacing > this.wrap))
- {
- last = null;
-
- if (horizontal)
- {
- y0 += tmp + this.spacing;
- }
- else
- {
- x0 += tmp + this.spacing;
- }
-
- tmp = 0;
- }
- }
-
- tmp = Math.max(tmp, (horizontal) ? geo.height : geo.width);
- var sw = 0;
-
- if (!this.borderCollapse)
- {
- var childStyle = this.graph.getCellStyle(child);
- sw = mxUtils.getNumber(childStyle, mxConstants.STYLE_STROKEWIDTH, 1);
- }
-
- if (last != null)
- {
- var temp = lastValue + this.spacing + Math.floor(sw / 2);
-
- if (horizontal)
- {
- geo.x = this.snap(((this.allowGaps) ? Math.max(temp, geo.x) :
- temp) - this.marginLeft) + this.marginLeft;
- }
- else
- {
- geo.y = this.snap(((this.allowGaps) ? Math.max(temp, geo.y) :
- temp) - this.marginTop) + this.marginTop;
- }
- }
- else if (!this.keepFirstLocation)
- {
- if (horizontal)
- {
- geo.x = (this.allowGaps && geo.x > x0) ? Math.max(this.snap(geo.x -
- this.marginLeft) + this.marginLeft, x0) : x0;
- }
- else
- {
- geo.y = (this.allowGaps && geo.y > y0) ? Math.max(this.snap(geo.y -
- this.marginTop) + this.marginTop, y0) : y0;
- }
- }
-
- if (horizontal)
- {
- geo.y = y0;
- }
- else
- {
- geo.x = x0;
- }
-
- if (this.fill && fillValue != null)
- {
- if (horizontal)
- {
- geo.height = fillValue;
- }
- else
- {
- geo.width = fillValue;
- }
- }
-
- if (horizontal)
- {
- geo.width = this.snap(geo.width);
- }
- else
- {
- geo.height = this.snap(geo.height);
- }
-
- this.setChildGeometry(child, geo);
- lastChild = child;
- last = geo;
-
- if (horizontal)
- {
- lastValue = last.x + last.width + Math.floor(sw / 2);
- }
- else
- {
- lastValue = last.y + last.height + Math.floor(sw / 2);
- }
- }
- }
- if (this.resizeParent && pgeo != null && last != null && !this.graph.isCellCollapsed(parent))
- {
- this.updateParentGeometry(parent, pgeo, last);
- }
- else if (this.resizeLast && pgeo != null && last != null && lastChild != null)
- {
- if (horizontal)
- {
- last.width = pgeo.width - last.x - this.spacing - this.marginRight - this.marginLeft;
- }
- else
- {
- last.height = pgeo.height - last.y - this.spacing - this.marginBottom;
- }
-
- this.setChildGeometry(lastChild, last);
- }
- }
- finally
- {
- model.endUpdate();
- }
- }
- };
- /**
- * Function: setChildGeometry
- *
- * Sets the specific geometry to the given child cell.
- *
- * Parameters:
- *
- * child - The given child of <mxCell>.
- * geo - The specific geometry of <mxGeometry>.
- */
- mxStackLayout.prototype.setChildGeometry = function(child, geo)
- {
- var geo2 = this.graph.getCellGeometry(child);
-
- if (geo2 == null || geo.x != geo2.x || geo.y != geo2.y ||
- geo.width != geo2.width || geo.height != geo2.height)
- {
- this.graph.getModel().setGeometry(child, geo);
- }
- };
- /**
- * Function: updateParentGeometry
- *
- * Updates the geometry of the given parent cell.
- *
- * Parameters:
- *
- * parent - The given parent of <mxCell>.
- * pgeo - The new <mxGeometry> for parent.
- * last - The last <mxGeometry>.
- */
- mxStackLayout.prototype.updateParentGeometry = function(parent, pgeo, last)
- {
- var horizontal = this.isHorizontal();
- var model = this.graph.getModel();
- var pgeo2 = pgeo.clone();
-
- if (horizontal)
- {
- var tmp = last.x + last.width + this.marginRight + this.border;
-
- if (this.resizeParentMax)
- {
- pgeo2.width = Math.max(pgeo2.width, tmp);
- }
- else
- {
- pgeo2.width = tmp;
- }
- }
- else
- {
- var tmp = last.y + last.height + this.marginBottom + this.border;
-
- if (this.resizeParentMax)
- {
- pgeo2.height = Math.max(pgeo2.height, tmp);
- }
- else
- {
- pgeo2.height = tmp;
- }
- }
-
- if (pgeo.x != pgeo2.x || pgeo.y != pgeo2.y ||
- pgeo.width != pgeo2.width || pgeo.height != pgeo2.height)
- {
- model.setGeometry(parent, pgeo2);
- }
- };
- __mxOutput.mxStackLayout = typeof mxStackLayout !== 'undefined' ? mxStackLayout : undefined;
|