/** * Copyright (c) 2006-2015, JGraph Ltd * Copyright (c) 2006-2015, Gaudenz Alder */ /** * * Class: mxCellStatePreview * * Implements a live preview for moving cells. * * Constructor: mxCellStatePreview * * Constructs a move preview for the given graph. * * Parameters: * * graph - Reference to the enclosing . */ function mxCellStatePreview(graph) { this.deltas = new mxDictionary(); this.graph = graph; }; /** * Variable: graph * * Reference to the enclosing . */ mxCellStatePreview.prototype.graph = null; /** * Variable: deltas * * Reference to the enclosing . */ mxCellStatePreview.prototype.deltas = null; /** * Variable: count * * Contains the number of entries in the map. */ mxCellStatePreview.prototype.count = 0; /** * Function: isEmpty * * Returns true if this contains no entries. */ mxCellStatePreview.prototype.isEmpty = function() { return this.count == 0; }; /** * Function: moveState */ mxCellStatePreview.prototype.moveState = function(state, dx, dy, add, includeEdges) { add = (add != null) ? add : true; includeEdges = (includeEdges != null) ? includeEdges : true; var delta = this.deltas.get(state.cell); if (delta == null) { // Note: Deltas stores the point and the state since the key is a string. delta = {point: new mxPoint(dx, dy), state: state}; this.deltas.put(state.cell, delta); this.count++; } else if (add) { delta.point.x += dx; delta.point.y += dy; } else { delta.point.x = dx; delta.point.y = dy; } if (includeEdges) { this.addEdges(state); } return delta.point; }; /** * Function: show */ mxCellStatePreview.prototype.show = function(visitor) { this.deltas.visit(mxUtils.bind(this, function(key, delta) { this.translateState(delta.state, delta.point.x, delta.point.y); })); this.deltas.visit(mxUtils.bind(this, function(key, delta) { this.revalidateState(delta.state, delta.point.x, delta.point.y, visitor); })); }; /** * Function: translateState */ mxCellStatePreview.prototype.translateState = function(state, dx, dy) { if (state != null) { var model = this.graph.getModel(); if (model.isVertex(state.cell)) { state.view.updateCellState(state); var geo = model.getGeometry(state.cell); // Moves selection cells and non-relative vertices in // the first phase so that edge terminal points will // be updated in the second phase if ((dx != 0 || dy != 0) && geo != null && (!geo.relative || this.deltas.get(state.cell) != null)) { state.x += dx; state.y += dy; } } var childCount = model.getChildCount(state.cell); for (var i = 0; i < childCount; i++) { this.translateState(state.view.getState(model.getChildAt(state.cell, i)), dx, dy); } } }; /** * Function: revalidateState */ mxCellStatePreview.prototype.revalidateState = function(state, dx, dy, visitor) { if (state != null) { var model = this.graph.getModel(); // Updates the edge terminal points and restores the // (relative) positions of any (relative) children if (model.isEdge(state.cell)) { state.view.updateCellState(state); } var geo = this.graph.getCellGeometry(state.cell); var pState = state.view.getState(model.getParent(state.cell)); // Moves selection vertices which are relative if ((dx != 0 || dy != 0) && geo != null && geo.relative && model.isVertex(state.cell) && (pState == null || model.isVertex(pState.cell) || this.deltas.get(state.cell) != null)) { state.x += dx; state.y += dy; } this.graph.cellRenderer.redraw(state); // Invokes the visitor on the given state if (visitor != null) { visitor(state); } var childCount = model.getChildCount(state.cell); for (var i = 0; i < childCount; i++) { this.revalidateState(this.graph.view.getState(model.getChildAt(state.cell, i)), dx, dy, visitor); } } }; /** * Function: addEdges */ mxCellStatePreview.prototype.addEdges = function(state) { var model = this.graph.getModel(); var edgeCount = model.getEdgeCount(state.cell); for (var i = 0; i < edgeCount; i++) { var s = state.view.getState(model.getEdgeAt(state.cell, i)); if (s != null) { this.moveState(s, 0, 0); } } };