123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- /**
- * Copyright (c) 2006-2015, JGraph Ltd
- * Copyright (c) 2006-2015, Gaudenz Alder
- */
- /**
- * Class: mxGuide
- *
- * Implements the alignment of selection cells to other cells in the graph.
- *
- * Constructor: mxGuide
- *
- * Constructs a new guide object.
- */
- function mxGuide(graph, states)
- {
- this.graph = graph;
- this.setStates(states);
- };
- /**
- * Variable: graph
- *
- * Reference to the enclosing <mxGraph> instance.
- */
- mxGuide.prototype.graph = null;
- /**
- * Variable: states
- *
- * Contains the <mxCellStates> that are used for alignment.
- */
- mxGuide.prototype.states = null;
- /**
- * Variable: horizontal
- *
- * Specifies if horizontal guides are enabled. Default is true.
- */
- mxGuide.prototype.horizontal = true;
- /**
- * Variable: vertical
- *
- * Specifies if vertical guides are enabled. Default is true.
- */
- mxGuide.prototype.vertical = true;
- /**
- * Variable: guideX
- *
- * Holds the <mxShape> for the horizontal guide.
- */
- mxGuide.prototype.guideX = null;
- /**
- * Variable: guideY
- *
- * Holds the <mxShape> for the vertical guide.
- */
- mxGuide.prototype.guideY = null;
- /**
- * Variable: rounded
- *
- * Specifies if rounded coordinates should be used. Default is false.
- */
- mxGuide.prototype.rounded = false;
- /**
- * Variable: tolerance
- *
- * Default tolerance in px if grid is disabled. Default is 2.
- */
- mxGuide.prototype.tolerance = 2;
- /**
- * Function: setStates
- *
- * Sets the <mxCellStates> that should be used for alignment.
- */
- mxGuide.prototype.setStates = function(states)
- {
- this.states = states;
- };
- /**
- * Function: isEnabledForEvent
- *
- * Returns true if the guide should be enabled for the given native event. This
- * implementation always returns true.
- */
- mxGuide.prototype.isEnabledForEvent = function(evt)
- {
- return true;
- };
- /**
- * Function: getGuideTolerance
- *
- * Returns the tolerance for the guides. Default value is gridSize / 2.
- */
- mxGuide.prototype.getGuideTolerance = function(gridEnabled)
- {
- return (gridEnabled && this.graph.gridEnabled) ? this.graph.gridSize / 2 : this.tolerance;
- };
- /**
- * Function: createGuideShape
- *
- * Returns the mxShape to be used for painting the respective guide. This
- * implementation returns a new, dashed and crisp <mxPolyline> using
- * <mxConstants.GUIDE_COLOR> and <mxConstants.GUIDE_STROKEWIDTH> as the format.
- *
- * Parameters:
- *
- * horizontal - Boolean that specifies which guide should be created.
- */
- mxGuide.prototype.createGuideShape = function(horizontal)
- {
- var guide = new mxPolyline([], mxConstants.GUIDE_COLOR, mxConstants.GUIDE_STROKEWIDTH);
- guide.isDashed = true;
-
- return guide;
- };
- /**
- * Function: isStateIgnored
- *
- * Returns true if the given state should be ignored.
- */
- mxGuide.prototype.isStateIgnored = function(state)
- {
- return false;
- };
- /**
- * Function: move
- *
- * Moves the <bounds> by the given <mxPoint> and returnt the snapped point.
- */
- mxGuide.prototype.move = function(bounds, delta, gridEnabled, clone)
- {
- if (this.states != null && (this.horizontal || this.vertical) && bounds != null && delta != null)
- {
- var scale = this.graph.getView().scale;
- var tt = this.getGuideTolerance(gridEnabled) * scale;
- var b = bounds.clone();
- b.x += delta.x;
- b.y += delta.y;
- var overrideX = false;
- var stateX = null;
- var valueX = null;
- var overrideY = false;
- var stateY = null;
- var valueY = null;
- var ttX = tt;
- var ttY = tt;
- var left = b.x;
- var right = b.x + b.width;
- var center = b.getCenterX();
- var top = b.y;
- var bottom = b.y + b.height;
- var middle = b.getCenterY();
-
- // Snaps the left, center and right to the given x-coordinate
- function snapX(x, state, centerAlign)
- {
- var override = false;
-
- if (centerAlign && Math.abs(x - center) < ttX)
- {
- delta.x = x - bounds.getCenterX();
- ttX = Math.abs(x - center);
- override = true;
- }
- else if (!centerAlign)
- {
- if (Math.abs(x - left) < ttX)
- {
- delta.x = x - bounds.x;
- ttX = Math.abs(x - left);
- override = true;
- }
- else if (Math.abs(x - right) < ttX)
- {
- delta.x = x - bounds.x - bounds.width;
- ttX = Math.abs(x - right);
- override = true;
- }
- }
-
- if (override)
- {
- stateX = state;
- valueX = x;
-
- if (this.guideX == null)
- {
- this.guideX = this.createGuideShape(true);
-
- // Makes sure to use either VML or SVG shapes in order to implement
- // event-transparency on the background area of the rectangle since
- // HTML shapes do not let mouseevents through even when transparent
- this.guideX.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.guideX.pointerEvents = false;
- this.guideX.init(this.graph.getView().getOverlayPane());
- }
- }
-
- overrideX = overrideX || override;
- };
-
- // Snaps the top, middle or bottom to the given y-coordinate
- function snapY(y, state, centerAlign)
- {
- var override = false;
-
- if (centerAlign && Math.abs(y - middle) < ttY)
- {
- delta.y = y - bounds.getCenterY();
- ttY = Math.abs(y - middle);
- override = true;
- }
- else if (!centerAlign)
- {
- if (Math.abs(y - top) < ttY)
- {
- delta.y = y - bounds.y;
- ttY = Math.abs(y - top);
- override = true;
- }
- else if (Math.abs(y - bottom) < ttY)
- {
- delta.y = y - bounds.y - bounds.height;
- ttY = Math.abs(y - bottom);
- override = true;
- }
- }
-
- if (override)
- {
- stateY = state;
- valueY = y;
-
- if (this.guideY == null)
- {
- this.guideY = this.createGuideShape(false);
-
- // Makes sure to use either VML or SVG shapes in order to implement
- // event-transparency on the background area of the rectangle since
- // HTML shapes do not let mouseevents through even when transparent
- this.guideY.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
- mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG;
- this.guideY.pointerEvents = false;
- this.guideY.init(this.graph.getView().getOverlayPane());
- }
- }
-
- overrideY = overrideY || override;
- };
-
- for (var i = 0; i < this.states.length; i++)
- {
- var state = this.states[i];
-
- if (state != null && !this.isStateIgnored(state))
- {
- // Align x
- if (this.horizontal)
- {
- snapX.call(this, state.getCenterX(), state, true);
- snapX.call(this, state.x, state, false);
- snapX.call(this, state.x + state.width, state, false);
-
- // Aligns left and right of shape to center of page
- if (state.cell == null)
- {
- snapX.call(this, state.getCenterX(), state, false);
- }
- }
-
- // Align y
- if (this.vertical)
- {
- snapY.call(this, state.getCenterY(), state, true);
- snapY.call(this, state.y, state, false);
- snapY.call(this, state.y + state.height, state, false);
-
- // Aligns left and right of shape to center of page
- if (state.cell == null)
- {
- snapY.call(this, state.getCenterY(), state, false);
- }
- }
- }
- }
- // Moves cells to the raster if not aligned
- this.graph.snapDelta(delta, bounds, !gridEnabled, overrideX, overrideY);
- delta = this.getDelta(bounds, stateX, delta.x, stateY, delta.y)
-
- // Redraws the guides
- var c = this.graph.container;
-
- if (!overrideX && this.guideX != null)
- {
- this.guideX.node.style.visibility = 'hidden';
- }
- else if (this.guideX != null)
- {
- var minY = null;
- var maxY = null;
-
- if (stateX != null && bounds != null)
- {
- minY = Math.min(bounds.y + delta.y - this.graph.panDy, stateX.y);
- maxY = Math.max(bounds.y + bounds.height + delta.y - this.graph.panDy, stateX.y + stateX.height);
- }
-
- if (minY != null && maxY != null)
- {
- this.guideX.points = [new mxPoint(valueX, minY), new mxPoint(valueX, maxY)];
- }
- else
- {
- this.guideX.points = [new mxPoint(valueX, -this.graph.panDy),
- new mxPoint(valueX, c.scrollHeight - 3 - this.graph.panDy)];
- }
-
- this.guideX.stroke = this.getGuideColor(stateX, true);
- this.guideX.node.style.visibility = 'visible';
- this.guideX.redraw();
- }
-
- if (!overrideY && this.guideY != null)
- {
- this.guideY.node.style.visibility = 'hidden';
- }
- else if (this.guideY != null)
- {
- var minX = null;
- var maxX = null;
-
- if (stateY != null && bounds != null)
- {
- minX = Math.min(bounds.x + delta.x - this.graph.panDx, stateY.x);
- maxX = Math.max(bounds.x + bounds.width + delta.x - this.graph.panDx, stateY.x + stateY.width);
- }
-
- if (minX != null && maxX != null)
- {
- this.guideY.points = [new mxPoint(minX, valueY), new mxPoint(maxX, valueY)];
- }
- else
- {
- this.guideY.points = [new mxPoint(-this.graph.panDx, valueY),
- new mxPoint(c.scrollWidth - 3 - this.graph.panDx, valueY)];
- }
-
- this.guideY.stroke = this.getGuideColor(stateY, false);
- this.guideY.node.style.visibility = 'visible';
- this.guideY.redraw();
- }
- }
-
- return delta;
- };
- /**
- * Function: getDelta
- *
- * Rounds to pixels for virtual states (eg. page guides)
- */
- mxGuide.prototype.getDelta = function(bounds, stateX, dx, stateY, dy)
- {
- var s = this.graph.view.scale;
-
- if (this.rounded || (stateX != null && stateX.cell == null))
- {
- dx = Math.round((bounds.x + dx) / s) * s - bounds.x;
- }
- if (this.rounded || (stateY != null && stateY.cell == null))
- {
- dy = Math.round((bounds.y + dy) / s) * s - bounds.y;
- }
-
- return new mxPoint(dx, dy);
- };
- /**
- * Function: getGuideColor
- *
- * Returns the color for the given state.
- */
- mxGuide.prototype.getGuideColor = function(state, horizontal)
- {
- return mxConstants.GUIDE_COLOR;
- };
- /**
- * Function: hide
- *
- * Hides all current guides.
- */
- mxGuide.prototype.hide = function()
- {
- this.setVisible(false);
- };
- /**
- * Function: setVisible
- *
- * Shows or hides the current guides.
- */
- mxGuide.prototype.setVisible = function(visible)
- {
- if (this.guideX != null)
- {
- this.guideX.node.style.visibility = (visible) ? 'visible' : 'hidden';
- }
-
- if (this.guideY != null)
- {
- this.guideY.node.style.visibility = (visible) ? 'visible' : 'hidden';
- }
- };
- /**
- * Function: destroy
- *
- * Destroys all resources that this object uses.
- */
- mxGuide.prototype.destroy = function()
- {
- if (this.guideX != null)
- {
- this.guideX.destroy();
- this.guideX = null;
- }
-
- if (this.guideY != null)
- {
- this.guideY.destroy();
- this.guideY = null;
- }
- };
- __mxOutput.mxGuide = typeof mxGuide !== 'undefined' ? mxGuide : undefined;
|