| /** |
| * Copyright (c) 2006-2015, JGraph Ltd |
| * Copyright (c) 2006-2015, Gaudenz Alder |
| */ |
| /** |
| * Class: mxSwimlaneManager |
| * |
| * Manager for swimlanes and nested swimlanes that sets the size of newly added |
| * swimlanes to that of their siblings, and propagates changes to the size of a |
| * swimlane to its siblings, if <siblings> is true, and its ancestors, if |
| * <bubbling> is true. |
| * |
| * Constructor: mxSwimlaneManager |
| * |
| * Constructs a new swimlane manager for the given graph. |
| * |
| * Arguments: |
| * |
| * graph - Reference to the enclosing graph. |
| */ |
| function mxSwimlaneManager(graph, horizontal, addEnabled, resizeEnabled) |
| { |
| this.horizontal = (horizontal != null) ? horizontal : true; |
| this.addEnabled = (addEnabled != null) ? addEnabled : true; |
| this.resizeEnabled = (resizeEnabled != null) ? resizeEnabled : true; |
| |
| this.addHandler = mxUtils.bind(this, function(sender, evt) |
| { |
| if (this.isEnabled() && this.isAddEnabled()) |
| { |
| this.cellsAdded(evt.getProperty('cells')); |
| } |
| }); |
| |
| this.resizeHandler = mxUtils.bind(this, function(sender, evt) |
| { |
| if (this.isEnabled() && this.isResizeEnabled()) |
| { |
| this.cellsResized(evt.getProperty('cells')); |
| } |
| }); |
| |
| this.setGraph(graph); |
| }; |
| |
| /** |
| * Extends mxEventSource. |
| */ |
| mxSwimlaneManager.prototype = new mxEventSource(); |
| mxSwimlaneManager.prototype.constructor = mxSwimlaneManager; |
| |
| /** |
| * Variable: graph |
| * |
| * Reference to the enclosing <mxGraph>. |
| */ |
| mxSwimlaneManager.prototype.graph = null; |
| |
| /** |
| * Variable: enabled |
| * |
| * Specifies if event handling is enabled. Default is true. |
| */ |
| mxSwimlaneManager.prototype.enabled = true; |
| |
| /** |
| * Variable: horizontal |
| * |
| * Specifies the orientation of the swimlanes. Default is true. |
| */ |
| mxSwimlaneManager.prototype.horizontal = true; |
| |
| /** |
| * Variable: addEnabled |
| * |
| * Specifies if newly added cells should be resized to match the size of their |
| * existing siblings. Default is true. |
| */ |
| mxSwimlaneManager.prototype.addEnabled = true; |
| |
| /** |
| * Variable: resizeEnabled |
| * |
| * Specifies if resizing of swimlanes should be handled. Default is true. |
| */ |
| mxSwimlaneManager.prototype.resizeEnabled = true; |
| |
| /** |
| * Variable: moveHandler |
| * |
| * Holds the function that handles the move event. |
| */ |
| mxSwimlaneManager.prototype.addHandler = null; |
| |
| /** |
| * Variable: moveHandler |
| * |
| * Holds the function that handles the move event. |
| */ |
| mxSwimlaneManager.prototype.resizeHandler = null; |
| |
| /** |
| * Function: isEnabled |
| * |
| * Returns true if events are handled. This implementation |
| * returns <enabled>. |
| */ |
| mxSwimlaneManager.prototype.isEnabled = function() |
| { |
| return this.enabled; |
| }; |
| |
| /** |
| * Function: setEnabled |
| * |
| * Enables or disables event handling. This implementation |
| * updates <enabled>. |
| * |
| * Parameters: |
| * |
| * enabled - Boolean that specifies the new enabled state. |
| */ |
| mxSwimlaneManager.prototype.setEnabled = function(value) |
| { |
| this.enabled = value; |
| }; |
| |
| /** |
| * Function: isHorizontal |
| * |
| * Returns <horizontal>. |
| */ |
| mxSwimlaneManager.prototype.isHorizontal = function() |
| { |
| return this.horizontal; |
| }; |
| |
| /** |
| * Function: setHorizontal |
| * |
| * Sets <horizontal>. |
| */ |
| mxSwimlaneManager.prototype.setHorizontal = function(value) |
| { |
| this.horizontal = value; |
| }; |
| |
| /** |
| * Function: isAddEnabled |
| * |
| * Returns <addEnabled>. |
| */ |
| mxSwimlaneManager.prototype.isAddEnabled = function() |
| { |
| return this.addEnabled; |
| }; |
| |
| /** |
| * Function: setAddEnabled |
| * |
| * Sets <addEnabled>. |
| */ |
| mxSwimlaneManager.prototype.setAddEnabled = function(value) |
| { |
| this.addEnabled = value; |
| }; |
| |
| /** |
| * Function: isResizeEnabled |
| * |
| * Returns <resizeEnabled>. |
| */ |
| mxSwimlaneManager.prototype.isResizeEnabled = function() |
| { |
| return this.resizeEnabled; |
| }; |
| |
| /** |
| * Function: setResizeEnabled |
| * |
| * Sets <resizeEnabled>. |
| */ |
| mxSwimlaneManager.prototype.setResizeEnabled = function(value) |
| { |
| this.resizeEnabled = value; |
| }; |
| |
| /** |
| * Function: getGraph |
| * |
| * Returns the graph that this manager operates on. |
| */ |
| mxSwimlaneManager.prototype.getGraph = function() |
| { |
| return this.graph; |
| }; |
| |
| /** |
| * Function: setGraph |
| * |
| * Sets the graph that the manager operates on. |
| */ |
| mxSwimlaneManager.prototype.setGraph = function(graph) |
| { |
| if (this.graph != null) |
| { |
| this.graph.removeListener(this.addHandler); |
| this.graph.removeListener(this.resizeHandler); |
| } |
| |
| this.graph = graph; |
| |
| if (this.graph != null) |
| { |
| this.graph.addListener(mxEvent.ADD_CELLS, this.addHandler); |
| this.graph.addListener(mxEvent.CELLS_RESIZED, this.resizeHandler); |
| } |
| }; |
| |
| /** |
| * Function: isSwimlaneIgnored |
| * |
| * Returns true if the given swimlane should be ignored. |
| */ |
| mxSwimlaneManager.prototype.isSwimlaneIgnored = function(swimlane) |
| { |
| return !this.getGraph().isSwimlane(swimlane); |
| }; |
| |
| /** |
| * Function: isCellHorizontal |
| * |
| * Returns true if the given cell is horizontal. If the given cell is not a |
| * swimlane, then the global orientation is returned. |
| */ |
| mxSwimlaneManager.prototype.isCellHorizontal = function(cell) |
| { |
| if (this.graph.isSwimlane(cell)) |
| { |
| var style = this.graph.getCellStyle(cell); |
| |
| return mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, 1) == 1; |
| } |
| |
| return !this.isHorizontal(); |
| }; |
| |
| /** |
| * Function: cellsAdded |
| * |
| * Called if any cells have been added. |
| * |
| * Parameters: |
| * |
| * cell - Array of <mxCells> that have been added. |
| */ |
| mxSwimlaneManager.prototype.cellsAdded = function(cells) |
| { |
| if (cells != null) |
| { |
| var model = this.getGraph().getModel(); |
| |
| model.beginUpdate(); |
| try |
| { |
| for (var i = 0; i < cells.length; i++) |
| { |
| if (!this.isSwimlaneIgnored(cells[i])) |
| { |
| this.swimlaneAdded(cells[i]); |
| } |
| } |
| } |
| finally |
| { |
| model.endUpdate(); |
| } |
| } |
| }; |
| |
| /** |
| * Function: swimlaneAdded |
| * |
| * Updates the size of the given swimlane to match that of any existing |
| * siblings swimlanes. |
| * |
| * Parameters: |
| * |
| * swimlane - <mxCell> that represents the new swimlane. |
| */ |
| mxSwimlaneManager.prototype.swimlaneAdded = function(swimlane) |
| { |
| var model = this.getGraph().getModel(); |
| var parent = model.getParent(swimlane); |
| var childCount = model.getChildCount(parent); |
| var geo = null; |
| |
| // Finds the first valid sibling swimlane as reference |
| for (var i = 0; i < childCount; i++) |
| { |
| var child = model.getChildAt(parent, i); |
| |
| if (child != swimlane && !this.isSwimlaneIgnored(child)) |
| { |
| geo = model.getGeometry(child); |
| |
| if (geo != null) |
| { |
| break; |
| } |
| } |
| } |
| |
| // Applies the size of the refernece to the newly added swimlane |
| if (geo != null) |
| { |
| var parentHorizontal = (parent != null) ? this.isCellHorizontal(parent) : this.horizontal; |
| this.resizeSwimlane(swimlane, geo.width, geo.height, parentHorizontal); |
| } |
| }; |
| |
| /** |
| * Function: cellsResized |
| * |
| * Called if any cells have been resizes. Calls <swimlaneResized> for all |
| * swimlanes where <isSwimlaneIgnored> returns false. |
| * |
| * Parameters: |
| * |
| * cells - Array of <mxCells> whose size was changed. |
| */ |
| mxSwimlaneManager.prototype.cellsResized = function(cells) |
| { |
| if (cells != null) |
| { |
| var model = this.getGraph().getModel(); |
| |
| model.beginUpdate(); |
| try |
| { |
| // Finds the top-level swimlanes and adds offsets |
| for (var i = 0; i < cells.length; i++) |
| { |
| if (!this.isSwimlaneIgnored(cells[i])) |
| { |
| var geo = model.getGeometry(cells[i]); |
| |
| if (geo != null) |
| { |
| var size = new mxRectangle(0, 0, geo.width, geo.height); |
| var top = cells[i]; |
| var current = top; |
| |
| while (current != null) |
| { |
| top = current; |
| current = model.getParent(current); |
| var tmp = (this.graph.isSwimlane(current)) ? |
| this.graph.getStartSize(current) : |
| new mxRectangle(); |
| size.width += tmp.width; |
| size.height += tmp.height; |
| } |
| |
| var parentHorizontal = (current != null) ? this.isCellHorizontal(current) : this.horizontal; |
| this.resizeSwimlane(top, size.width, size.height, parentHorizontal); |
| } |
| } |
| } |
| } |
| finally |
| { |
| model.endUpdate(); |
| } |
| } |
| }; |
| |
| /** |
| * Function: resizeSwimlane |
| * |
| * Called from <cellsResized> for all swimlanes that are not ignored to update |
| * the size of the siblings and the size of the parent swimlanes, recursively, |
| * if <bubbling> is true. |
| * |
| * Parameters: |
| * |
| * swimlane - <mxCell> whose size has changed. |
| */ |
| mxSwimlaneManager.prototype.resizeSwimlane = function(swimlane, w, h, parentHorizontal) |
| { |
| var model = this.getGraph().getModel(); |
| |
| model.beginUpdate(); |
| try |
| { |
| var horizontal = this.isCellHorizontal(swimlane); |
| |
| if (!this.isSwimlaneIgnored(swimlane)) |
| { |
| var geo = model.getGeometry(swimlane); |
| |
| if (geo != null) |
| { |
| if ((parentHorizontal && geo.height != h) || (!parentHorizontal && geo.width != w)) |
| { |
| geo = geo.clone(); |
| |
| if (parentHorizontal) |
| { |
| geo.height = h; |
| } |
| else |
| { |
| geo.width = w; |
| } |
| |
| model.setGeometry(swimlane, geo); |
| } |
| } |
| } |
| |
| var tmp = (this.graph.isSwimlane(swimlane)) ? |
| this.graph.getStartSize(swimlane) : |
| new mxRectangle(); |
| w -= tmp.width; |
| h -= tmp.height; |
| |
| var childCount = model.getChildCount(swimlane); |
| |
| for (var i = 0; i < childCount; i++) |
| { |
| var child = model.getChildAt(swimlane, i); |
| this.resizeSwimlane(child, w, h, horizontal); |
| } |
| } |
| finally |
| { |
| model.endUpdate(); |
| } |
| }; |
| |
| /** |
| * Function: destroy |
| * |
| * Removes all handlers from the <graph> and deletes the reference to it. |
| */ |
| mxSwimlaneManager.prototype.destroy = function() |
| { |
| this.setGraph(null); |
| }; |