diff options
author | adhitya | 2016-04-10 12:28:28 +0000 |
---|---|---|
committer | adhitya | 2016-04-10 12:28:28 +0000 |
commit | 0b1c069f88dab0288a01c6aed4d77f4e6d2f6474 (patch) | |
tree | b5ae6b1f512a674f79674a12f675d22324cd268f /src/js/handler | |
parent | 1993f1da86e293aaf9996b8d7a4f6d9a9224f270 (diff) | |
download | xcos-on-web-0b1c069f88dab0288a01c6aed4d77f4e6d2f6474.tar.gz xcos-on-web-0b1c069f88dab0288a01c6aed4d77f4e6d2f6474.tar.bz2 xcos-on-web-0b1c069f88dab0288a01c6aed4d77f4e6d2f6474.zip |
Removed (un)necessary files
Diffstat (limited to 'src/js/handler')
-rw-r--r-- | src/js/handler/mxCellHighlight.js | 271 | ||||
-rw-r--r-- | src/js/handler/mxCellMarker.js | 419 | ||||
-rw-r--r-- | src/js/handler/mxCellTracker.js | 149 | ||||
-rw-r--r-- | src/js/handler/mxConnectionHandler.js | 1969 | ||||
-rw-r--r-- | src/js/handler/mxConstraintHandler.js | 308 | ||||
-rw-r--r-- | src/js/handler/mxEdgeHandler.js | 1529 | ||||
-rw-r--r-- | src/js/handler/mxEdgeSegmentHandler.js | 284 | ||||
-rw-r--r-- | src/js/handler/mxElbowEdgeHandler.js | 248 | ||||
-rw-r--r-- | src/js/handler/mxGraphHandler.js | 916 | ||||
-rw-r--r-- | src/js/handler/mxKeyHandler.js | 402 | ||||
-rw-r--r-- | src/js/handler/mxPanningHandler.js | 390 | ||||
-rw-r--r-- | src/js/handler/mxRubberband.js | 348 | ||||
-rw-r--r-- | src/js/handler/mxSelectionCellsHandler.js | 260 | ||||
-rw-r--r-- | src/js/handler/mxTooltipHandler.js | 317 | ||||
-rw-r--r-- | src/js/handler/mxVertexHandler.js | 753 |
15 files changed, 0 insertions, 8563 deletions
diff --git a/src/js/handler/mxCellHighlight.js b/src/js/handler/mxCellHighlight.js deleted file mode 100644 index f967f00..0000000 --- a/src/js/handler/mxCellHighlight.js +++ /dev/null @@ -1,271 +0,0 @@ -/** - * $Id: mxCellHighlight.js,v 1.25 2012-09-27 14:43:40 boris Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxCellHighlight - * - * A helper class to highlight cells. Here is an example for a given cell. - * - * (code) - * var highlight = new mxCellHighlight(graph, '#ff0000', 2); - * highlight.highlight(graph.view.getState(cell))); - * (end) - * - * Constructor: mxCellHighlight - * - * Constructs a cell highlight. - */ -function mxCellHighlight(graph, highlightColor, strokeWidth) -{ - if (graph != null) - { - this.graph = graph; - this.highlightColor = (highlightColor != null) ? highlightColor : mxConstants.DEFAULT_VALID_COLOR; - this.strokeWidth = (strokeWidth != null) ? strokeWidth : mxConstants.HIGHLIGHT_STROKEWIDTH; - - // Updates the marker if the graph changes - this.repaintHandler = mxUtils.bind(this, function() - { - this.repaint(); - }); - - this.graph.getView().addListener(mxEvent.SCALE, this.repaintHandler); - this.graph.getView().addListener(mxEvent.TRANSLATE, this.repaintHandler); - this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.repaintHandler); - this.graph.getModel().addListener(mxEvent.CHANGE, this.repaintHandler); - - // Hides the marker if the current root changes - this.resetHandler = mxUtils.bind(this, function() - { - this.hide(); - }); - - this.graph.getView().addListener(mxEvent.DOWN, this.resetHandler); - this.graph.getView().addListener(mxEvent.UP, this.resetHandler); - } -}; - -/** - * Variable: keepOnTop - * - * Specifies if the highlights should appear on top of everything - * else in the overlay pane. Default is false. - */ -mxCellHighlight.prototype.keepOnTop = false; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxCellHighlight.prototype.graph = true; - -/** - * Variable: state - * - * Reference to the <mxCellState>. - */ -mxCellHighlight.prototype.state = null; - -/** - * Variable: spacing - * - * Specifies the spacing between the highlight for vertices and the vertex. - * Default is 2. - */ -mxCellHighlight.prototype.spacing = 2; - -/** - * Variable: resetHandler - * - * Holds the handler that automatically invokes reset if the highlight - * should be hidden. - */ -mxCellHighlight.prototype.resetHandler = null; - -/** - * Function: setHighlightColor - * - * Sets the color of the rectangle used to highlight drop targets. - * - * Parameters: - * - * color - String that represents the new highlight color. - */ -mxCellHighlight.prototype.setHighlightColor = function(color) -{ - this.highlightColor = color; - - if (this.shape != null) - { - if (this.shape.dialect == mxConstants.DIALECT_SVG) - { - this.shape.innerNode.setAttribute('stroke', color); - } - else if (this.shape.dialect == mxConstants.DIALECT_VML) - { - this.shape.node.strokecolor = color; - } - } -}; - -/** - * Function: drawHighlight - * - * Creates and returns the highlight shape for the given state. - */ -mxCellHighlight.prototype.drawHighlight = function() -{ - this.shape = this.createShape(); - this.repaint(); - - if (!this.keepOnTop && this.shape.node.parentNode.firstChild != this.shape.node) - { - this.shape.node.parentNode.insertBefore(this.shape.node, this.shape.node.parentNode.firstChild); - } - - // Workaround to force a repaint in AppleWebKit - if (this.graph.model.isEdge(this.state.cell)) - { - mxUtils.repaintGraph(this.graph, this.shape.points[0]); - } -}; - -/** - * Function: createShape - * - * Creates and returns the highlight shape for the given state. - */ -mxCellHighlight.prototype.createShape = function() -{ - var shape = null; - - if (this.graph.model.isEdge(this.state.cell)) - { - shape = new mxPolyline(this.state.absolutePoints, - this.highlightColor, this.strokeWidth); - } - else - { - shape = new mxRectangleShape( new mxRectangle(), - null, this.highlightColor, this.strokeWidth); - } - - shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - shape.init(this.graph.getView().getOverlayPane()); - mxEvent.redirectMouseEvents(shape.node, this.graph, this.state); - - return shape; -}; - - -/** - * Function: repaint - * - * Updates the highlight after a change of the model or view. - */ -mxCellHighlight.prototype.repaint = function() -{ - if (this.state != null && this.shape != null) - { - if (this.graph.model.isEdge(this.state.cell)) - { - this.shape.points = this.state.absolutePoints; - } - else - { - this.shape.bounds = new mxRectangle(this.state.x - this.spacing, this.state.y - this.spacing, - this.state.width + 2 * this.spacing, this.state.height + 2 * this.spacing); - } - - // Uses cursor from shape in highlight - if (this.state.shape != null) - { - this.shape.setCursor(this.state.shape.getCursor()); - } - - var alpha = (!this.graph.model.isEdge(this.state.cell)) ? Number(this.state.style[mxConstants.STYLE_ROTATION] || '0') : 0; - - // Event-transparency - if (this.shape.dialect == mxConstants.DIALECT_SVG) - { - this.shape.node.setAttribute('style', 'pointer-events:none;'); - - if (alpha != 0) - { - var cx = this.state.getCenterX(); - var cy = this.state.getCenterY(); - var transform = 'rotate(' + alpha + ' ' + cx + ' ' + cy + ')'; - - this.shape.node.setAttribute('transform', transform); - } - } - else - { - this.shape.node.style.background = ''; - - if (alpha != 0) - { - this.shape.node.rotation = alpha; - } - } - - this.shape.redraw(); - } -}; - -/** - * Function: hide - * - * Resets the state of the cell marker. - */ -mxCellHighlight.prototype.hide = function() -{ - this.highlight(null); -}; - -/** - * Function: mark - * - * Marks the <markedState> and fires a <mark> event. - */ -mxCellHighlight.prototype.highlight = function(state) -{ - if (this.state != state) - { - if (this.shape != null) - { - this.shape.destroy(); - this.shape = null; - } - - this.state = state; - - if (this.state != null) - { - this.drawHighlight(); - } - } -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. - */ -mxCellHighlight.prototype.destroy = function() -{ - this.graph.getView().removeListener(this.repaintHandler); - this.graph.getModel().removeListener(this.repaintHandler); - - this.graph.getView().removeListener(this.resetHandler); - this.graph.getModel().removeListener(this.resetHandler); - - if (this.shape != null) - { - this.shape.destroy(); - this.shape = null; - } -}; diff --git a/src/js/handler/mxCellMarker.js b/src/js/handler/mxCellMarker.js deleted file mode 100644 index b336278..0000000 --- a/src/js/handler/mxCellMarker.js +++ /dev/null @@ -1,419 +0,0 @@ -/** - * $Id: mxCellMarker.js,v 1.30 2011-07-15 12:57:50 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxCellMarker - * - * A helper class to process mouse locations and highlight cells. - * - * Helper class to highlight cells. To add a cell marker to an existing graph - * for highlighting all cells, the following code is used: - * - * (code) - * var marker = new mxCellMarker(graph); - * graph.addMouseListener({ - * mouseDown: function() {}, - * mouseMove: function(sender, me) - * { - * marker.process(me); - * }, - * mouseUp: function() {} - * }); - * (end) - * - * Event: mxEvent.MARK - * - * Fires after a cell has been marked or unmarked. The <code>state</code> - * property contains the marked <mxCellState> or null if no state is marked. - * - * Constructor: mxCellMarker - * - * Constructs a new cell marker. - * - * Parameters: - * - * graph - Reference to the enclosing <mxGraph>. - * validColor - Optional marker color for valid states. Default is - * <mxConstants.DEFAULT_VALID_COLOR>. - * invalidColor - Optional marker color for invalid states. Default is - * <mxConstants.DEFAULT_INVALID_COLOR>. - * hotspot - Portion of the width and hight where a state intersects a - * given coordinate pair. A value of 0 means always highlight. Default is - * <mxConstants.DEFAULT_HOTSPOT>. - */ -function mxCellMarker(graph, validColor, invalidColor, hotspot) -{ - if (graph != null) - { - this.graph = graph; - this.validColor = (validColor != null) ? validColor : mxConstants.DEFAULT_VALID_COLOR; - this.invalidColor = (validColor != null) ? invalidColor : mxConstants.DEFAULT_INVALID_COLOR; - this.hotspot = (hotspot != null) ? hotspot : mxConstants.DEFAULT_HOTSPOT; - - this.highlight = new mxCellHighlight(graph); - } -}; - -/** - * Extends mxEventSource. - */ -mxCellMarker.prototype = new mxEventSource(); -mxCellMarker.prototype.constructor = mxCellMarker; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxCellMarker.prototype.graph = null; - -/** - * Variable: enabled - * - * Specifies if the marker is enabled. Default is true. - */ -mxCellMarker.prototype.enabled = true; - -/** - * Variable: hotspot - * - * Specifies the portion of the width and height that should trigger - * a highlight. The area around the center of the cell to be marked is used - * as the hotspot. Possible values are between 0 and 1. Default is - * mxConstants.DEFAULT_HOTSPOT. - */ -mxCellMarker.prototype.hotspot = mxConstants.DEFAULT_HOTSPOT; - -/** - * Variable: hotspotEnabled - * - * Specifies if the hotspot is enabled. Default is false. - */ -mxCellMarker.prototype.hotspotEnabled = false; - -/** - * Variable: validColor - * - * Holds the valid marker color. - */ -mxCellMarker.prototype.validColor = null; - -/** - * Variable: invalidColor - * - * Holds the invalid marker color. - */ -mxCellMarker.prototype.invalidColor = null; - -/** - * Variable: currentColor - * - * Holds the current marker color. - */ -mxCellMarker.prototype.currentColor = null; - -/** - * Variable: validState - * - * Holds the marked <mxCellState> if it is valid. - */ -mxCellMarker.prototype.validState = null; - -/** - * Variable: markedState - * - * Holds the marked <mxCellState>. - */ -mxCellMarker.prototype.markedState = null; - -/** - * Function: setEnabled - * - * Enables or disables event handling. This implementation - * updates <enabled>. - * - * Parameters: - * - * enabled - Boolean that specifies the new enabled state. - */ -mxCellMarker.prototype.setEnabled = function(enabled) -{ - this.enabled = enabled; -}; - -/** - * Function: isEnabled - * - * Returns true if events are handled. This implementation - * returns <enabled>. - */ -mxCellMarker.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Function: setHotspot - * - * Sets the <hotspot>. - */ -mxCellMarker.prototype.setHotspot = function(hotspot) -{ - this.hotspot = hotspot; -}; - -/** - * Function: getHotspot - * - * Returns the <hotspot>. - */ -mxCellMarker.prototype.getHotspot = function() -{ - return this.hotspot; -}; - -/** - * Function: setHotspotEnabled - * - * Specifies whether the hotspot should be used in <intersects>. - */ -mxCellMarker.prototype.setHotspotEnabled = function(enabled) -{ - this.hotspotEnabled = enabled; -}; - -/** - * Function: isHotspotEnabled - * - * Returns true if hotspot is used in <intersects>. - */ -mxCellMarker.prototype.isHotspotEnabled = function() -{ - return this.hotspotEnabled; -}; - -/** - * Function: hasValidState - * - * Returns true if <validState> is not null. - */ -mxCellMarker.prototype.hasValidState = function() -{ - return this.validState != null; -}; - -/** - * Function: getValidState - * - * Returns the <validState>. - */ -mxCellMarker.prototype.getValidState = function() -{ - return this.validState; -}; - -/** - * Function: getMarkedState - * - * Returns the <markedState>. - */ -mxCellMarker.prototype.getMarkedState = function() -{ - return this.markedState; -}; - -/** - * Function: reset - * - * Resets the state of the cell marker. - */ -mxCellMarker.prototype.reset = function() -{ - this.validState = null; - - if (this.markedState != null) - { - this.markedState = null; - this.unmark(); - } -}; - -/** - * Function: process - * - * Processes the given event and cell and marks the state returned by - * <getState> with the color returned by <getMarkerColor>. If the - * markerColor is not null, then the state is stored in <markedState>. If - * <isValidState> returns true, then the state is stored in <validState> - * regardless of the marker color. The state is returned regardless of the - * marker color and valid state. - */ -mxCellMarker.prototype.process = function(me) -{ - var state = null; - - if (this.isEnabled()) - { - state = this.getState(me); - var isValid = (state != null) ? this.isValidState(state) : false; - var color = this.getMarkerColor(me.getEvent(), state, isValid); - - if (isValid) - { - this.validState = state; - } - else - { - this.validState = null; - } - - if (state != this.markedState || color != this.currentColor) - { - this.currentColor = color; - - if (state != null && this.currentColor != null) - { - this.markedState = state; - this.mark(); - } - else if (this.markedState != null) - { - this.markedState = null; - this.unmark(); - } - } - } - - return state; -}; - -/** - * Function: markCell - * - * Marks the given cell using the given color, or <validColor> if no color is specified. - */ -mxCellMarker.prototype.markCell = function(cell, color) -{ - var state = this.graph.getView().getState(cell); - - if (state != null) - { - this.currentColor = (color != null) ? color : this.validColor; - this.markedState = state; - this.mark(); - } -}; - -/** - * Function: mark - * - * Marks the <markedState> and fires a <mark> event. - */ -mxCellMarker.prototype.mark = function() -{ - this.highlight.setHighlightColor(this.currentColor); - this.highlight.highlight(this.markedState); - this.fireEvent(new mxEventObject(mxEvent.MARK, 'state', this.markedState)); -}; - -/** - * Function: unmark - * - * Hides the marker and fires a <mark> event. - */ -mxCellMarker.prototype.unmark = function() -{ - this.mark(); -}; - -/** - * Function: isValidState - * - * Returns true if the given <mxCellState> is a valid state. If this - * returns true, then the state is stored in <validState>. The return value - * of this method is used as the argument for <getMarkerColor>. - */ -mxCellMarker.prototype.isValidState = function(state) -{ - return true; -}; - -/** - * Function: getMarkerColor - * - * Returns the valid- or invalidColor depending on the value of isValid. - * The given <mxCellState> is ignored by this implementation. - */ -mxCellMarker.prototype.getMarkerColor = function(evt, state, isValid) -{ - return (isValid) ? this.validColor : this.invalidColor; -}; - -/** - * Function: getState - * - * Uses <getCell>, <getStateToMark> and <intersects> to return the - * <mxCellState> for the given <mxMouseEvent>. - */ -mxCellMarker.prototype.getState = function(me) -{ - var view = this.graph.getView(); - cell = this.getCell(me); - var state = this.getStateToMark(view.getState(cell)); - - return (state != null && this.intersects(state, me)) ? state : null; -}; - -/** - * Function: getCell - * - * Returns the <mxCell> for the given event and cell. This returns the - * given cell. - */ -mxCellMarker.prototype.getCell = function(me) -{ - return me.getCell(); -}; - -/** - * Function: getStateToMark - * - * Returns the <mxCellState> to be marked for the given <mxCellState> under - * the mouse. This returns the given state. - */ -mxCellMarker.prototype.getStateToMark = function(state) -{ - return state; -}; - -/** - * Function: intersects - * - * Returns true if the given coordinate pair intersects the given state. - * This returns true if the <hotspot> is 0 or the coordinates are inside - * the hotspot for the given cell state. - */ -mxCellMarker.prototype.intersects = function(state, me) -{ - if (this.hotspotEnabled) - { - return mxUtils.intersectsHotspot(state, me.getGraphX(), me.getGraphY(), - this.hotspot, mxConstants.MIN_HOTSPOT_SIZE, - mxConstants.MAX_HOTSPOT_SIZE); - } - - return true; -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. - */ -mxCellMarker.prototype.destroy = function() -{ - this.graph.getView().removeListener(this.resetHandler); - this.graph.getModel().removeListener(this.resetHandler); - this.highlight.destroy(); -}; diff --git a/src/js/handler/mxCellTracker.js b/src/js/handler/mxCellTracker.js deleted file mode 100644 index 5adcd6a..0000000 --- a/src/js/handler/mxCellTracker.js +++ /dev/null @@ -1,149 +0,0 @@ -/** - * $Id: mxCellTracker.js,v 1.9 2011-08-28 09:49:46 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxCellTracker - * - * Event handler that highlights cells. Inherits from <mxCellMarker>. - * - * Example: - * - * (code) - * new mxCellTracker(graph, '#00FF00'); - * (end) - * - * For detecting dragEnter, dragOver and dragLeave on cells, the following - * code can be used: - * - * (code) - * graph.addMouseListener( - * { - * cell: null, - * mouseDown: function(sender, me) { }, - * mouseMove: function(sender, me) - * { - * var tmp = me.getCell(); - * - * if (tmp != this.cell) - * { - * if (this.cell != null) - * { - * this.dragLeave(me.getEvent(), this.cell); - * } - * - * this.cell = tmp; - * - * if (this.cell != null) - * { - * this.dragEnter(me.getEvent(), this.cell); - * } - * } - * - * if (this.cell != null) - * { - * this.dragOver(me.getEvent(), this.cell); - * } - * }, - * mouseUp: function(sender, me) { }, - * dragEnter: function(evt, cell) - * { - * mxLog.debug('dragEnter', cell.value); - * }, - * dragOver: function(evt, cell) - * { - * mxLog.debug('dragOver', cell.value); - * }, - * dragLeave: function(evt, cell) - * { - * mxLog.debug('dragLeave', cell.value); - * } - * }); - * (end) - * - * Constructor: mxCellTracker - * - * Constructs an event handler that highlights cells. - * - * Parameters: - * - * graph - Reference to the enclosing <mxGraph>. - * color - Color of the highlight. Default is blue. - * funct - Optional JavaScript function that is used to override - * <mxCellMarker.getCell>. - */ -function mxCellTracker(graph, color, funct) -{ - mxCellMarker.call(this, graph, color); - - this.graph.addMouseListener(this); - - if (funct != null) - { - this.getCell = funct; - } - - // Automatic deallocation of memory - if (mxClient.IS_IE) - { - mxEvent.addListener(window, 'unload', mxUtils.bind(this, function() - { - this.destroy(); - })); - } -}; - -/** - * Extends mxCellMarker. - */ -mxCellTracker.prototype = new mxCellMarker(); -mxCellTracker.prototype.constructor = mxCellTracker; - -/** - * Function: mouseDown - * - * Ignores the event. The event is not consumed. - */ -mxCellTracker.prototype.mouseDown = function(sender, me) { }; - -/** - * Function: mouseMove - * - * Handles the event by highlighting the cell under the mousepointer if it - * is over the hotspot region of the cell. - */ -mxCellTracker.prototype.mouseMove = function(sender, me) -{ - if (this.isEnabled()) - { - this.process(me); - } -}; - -/** - * Function: mouseUp - * - * Handles the event by reseting the highlight. - */ -mxCellTracker.prototype.mouseUp = function(sender, me) -{ - this.reset(); -}; - -/** - * Function: destroy - * - * Destroys the object and all its resources and DOM nodes. This doesn't - * normally need to be called. It is called automatically when the window - * unloads. - */ -mxCellTracker.prototype.destroy = function() -{ - if (!this.destroyed) - { - this.destroyed = true; - - this.graph.removeMouseListener(this); - mxCellMarker.prototype.destroy.apply(this); - } -}; diff --git a/src/js/handler/mxConnectionHandler.js b/src/js/handler/mxConnectionHandler.js deleted file mode 100644 index 07daaf8..0000000 --- a/src/js/handler/mxConnectionHandler.js +++ /dev/null @@ -1,1969 +0,0 @@ -/** - * $Id: mxConnectionHandler.js,v 1.216 2012-12-07 15:17:37 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxConnectionHandler - * - * Graph event handler that creates new connections. Uses <mxTerminalMarker> - * for finding and highlighting the source and target vertices and - * <factoryMethod> to create the edge instance. This handler is built-into - * <mxGraph.connectionHandler> and enabled using <mxGraph.setConnectable>. - * - * Example: - * - * (code) - * new mxConnectionHandler(graph, function(source, target, style) - * { - * edge = new mxCell('', new mxGeometry()); - * edge.setEdge(true); - * edge.setStyle(style); - * edge.geometry.relative = true; - * return edge; - * }); - * (end) - * - * Here is an alternative solution that just sets a specific user object for - * new edges by overriding <insertEdge>. - * - * (code) - * mxConnectionHandlerInsertEdge = mxConnectionHandler.prototype.insertEdge; - * mxConnectionHandler.prototype.insertEdge = function(parent, id, value, source, target, style) - * { - * value = 'Test'; - * - * return mxConnectionHandlerInsertEdge.apply(this, arguments); - * }; - * (end) - * - * Using images to trigger connections: - * - * This handler uses mxTerminalMarker to find the source and target cell for - * the new connection and creates a new edge using <connect>. The new edge is - * created using <createEdge> which in turn uses <factoryMethod> or creates a - * new default edge. - * - * The handler uses a "highlight-paradigm" for indicating if a cell is being - * used as a source or target terminal, as seen in MS Visio and other products. - * In order to allow both, moving and connecting cells at the same time, - * <mxConstants.DEFAULT_HOTSPOT> is used in the handler to determine the hotspot - * of a cell, that is, the region of the cell which is used to trigger a new - * connection. The constant is a value between 0 and 1 that specifies the - * amount of the width and height around the center to be used for the hotspot - * of a cell and its default value is 0.5. In addition, - * <mxConstants.MIN_HOTSPOT_SIZE> defines the minimum number of pixels for the - * width and height of the hotspot. - * - * This solution, while standards compliant, may be somewhat confusing because - * there is no visual indicator for the hotspot and the highlight is seen to - * switch on and off while the mouse is being moved in and out. Furthermore, - * this paradigm does not allow to create different connections depending on - * the highlighted hotspot as there is only one hotspot per cell and it - * normally does not allow cells to be moved and connected at the same time as - * there is no clear indication of the connectable area of the cell. - * - * To come across these issues, the handle has an additional <createIcons> hook - * with a default implementation that allows to create one icon to be used to - * trigger new connections. If this icon is specified, then new connections can - * only be created if the image is clicked while the cell is being highlighted. - * The <createIcons> hook may be overridden to create more than one - * <mxImageShape> for creating new connections, but the default implementation - * supports one image and is used as follows: - * - * In order to display the "connect image" whenever the mouse is over the cell, - * an DEFAULT_HOTSPOT of 1 should be used: - * - * (code) - * mxConstants.DEFAULT_HOTSPOT = 1; - * (end) - * - * In order to avoid confusion with the highlighting, the highlight color - * should not be used with a connect image: - * - * (code) - * mxConstants.HIGHLIGHT_COLOR = null; - * (end) - * - * To install the image, the connectImage field of the mxConnectionHandler must - * be assigned a new <mxImage> instance: - * - * (code) - * mxConnectionHandler.prototype.connectImage = new mxImage('images/green-dot.gif', 14, 14); - * (end) - * - * This will use the green-dot.gif with a width and height of 14 pixels as the - * image to trigger new connections. In createIcons the icon field of the - * handler will be set in order to remember the icon that has been clicked for - * creating the new connection. This field will be available under selectedIcon - * in the connect method, which may be overridden to take the icon that - * triggered the new connection into account. This is useful if more than one - * icon may be used to create a connection. - * - * Group: Events - * - * Event: mxEvent.START - * - * Fires when a new connection is being created by the user. The <code>state</code> - * property contains the state of the source cell. - * - * Event: mxEvent.CONNECT - * - * Fires between begin- and endUpdate in <connect>. The <code>cell</code> - * property contains the inserted edge, the <code>event</code> and <code>target</code> - * properties contain the respective arguments that were passed to <connect> (where - * target corresponds to the dropTarget argument). - * - * Note that the target is the cell under the mouse where the mouse button was released. - * Depending on the logic in the handler, this doesn't necessarily have to be the target - * of the inserted edge. To print the source, target or any optional ports IDs that the - * edge is connected to, the following code can be used. To get more details about the - * actual connection point, <mxGraph.getConnectionConstraint> can be used. To resolve - * the port IDs, use <mxGraphModel.getCell>. - * - * (code) - * graph.connectionHandler.addListener(mxEvent.CONNECT, function(sender, evt) - * { - * var edge = evt.getProperty('cell'); - * var source = graph.getModel().getTerminal(edge, true); - * var target = graph.getModel().getTerminal(edge, false); - * - * var style = graph.getCellStyle(edge); - * var sourcePortId = style[mxConstants.STYLE_SOURCE_PORT]; - * var targetPortId = style[mxConstants.STYLE_TARGET_PORT]; - * - * mxLog.show(); - * mxLog.debug('connect', edge, source.id, target.id, sourcePortId, targetPortId); - * }); - * (end) - * - * Event: mxEvent.RESET - * - * Fires when the <reset> method is invoked. - * - * Constructor: mxConnectionHandler - * - * Constructs an event handler that connects vertices using the specified - * factory method to create the new edges. Modify - * <mxConstants.ACTIVE_REGION> to setup the region on a cell which triggers - * the creation of a new connection or use connect icons as explained - * above. - * - * Parameters: - * - * graph - Reference to the enclosing <mxGraph>. - * factoryMethod - Optional function to create the edge. The function takes - * the source and target <mxCell> as the first and second argument and an - * optional cell style from the preview as the third argument. It returns - * the <mxCell> that represents the new edge. - */ -function mxConnectionHandler(graph, factoryMethod) -{ - if (graph != null) - { - this.graph = graph; - this.factoryMethod = factoryMethod; - this.init(); - } -}; - -/** - * Extends mxEventSource. - */ -mxConnectionHandler.prototype = new mxEventSource(); -mxConnectionHandler.prototype.constructor = mxConnectionHandler; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxConnectionHandler.prototype.graph = null; - -/** - * Variable: factoryMethod - * - * Function that is used for creating new edges. The function takes the - * source and target <mxCell> as the first and second argument and returns - * a new <mxCell> that represents the edge. This is used in <createEdge>. - */ -mxConnectionHandler.prototype.factoryMethod = true; - -/** - * Variable: moveIconFront - * - * Specifies if icons should be displayed inside the graph container instead - * of the overlay pane. This is used for HTML labels on vertices which hide - * the connect icon. This has precendence over <moveIconBack> when set - * to true. Default is false. - */ -mxConnectionHandler.prototype.moveIconFront = false; - -/** - * Variable: moveIconBack - * - * Specifies if icons should be moved to the back of the overlay pane. This can - * be set to true if the icons of the connection handler conflict with other - * handles, such as the vertex label move handle. Default is false. - */ -mxConnectionHandler.prototype.moveIconBack = false; - -/** - * Variable: connectImage - * - * <mxImage> that is used to trigger the creation of a new connection. This - * is used in <createIcons>. Default is null. - */ -mxConnectionHandler.prototype.connectImage = null; - -/** - * Variable: targetConnectImage - * - * Specifies if the connect icon should be centered on the target state - * while connections are being previewed. Default is false. - */ -mxConnectionHandler.prototype.targetConnectImage = false; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxConnectionHandler.prototype.enabled = true; - -/** - * Variable: select - * - * Specifies if new edges should be selected. Default is true. - */ -mxConnectionHandler.prototype.select = true; - -/** - * Variable: createTarget - * - * Specifies if <createTargetVertex> should be called if no target was under the - * mouse for the new connection. Setting this to true means the connection - * will be drawn as valid if no target is under the mouse, and - * <createTargetVertex> will be called before the connection is created between - * the source cell and the newly created vertex in <createTargetVertex>, which - * can be overridden to create a new target. Default is false. - */ -mxConnectionHandler.prototype.createTarget = false; - -/** - * Variable: marker - * - * Holds the <mxTerminalMarker> used for finding source and target cells. - */ -mxConnectionHandler.prototype.marker = null; - -/** - * Variable: constraintHandler - * - * Holds the <mxConstraintHandler> used for drawing and highlighting - * constraints. - */ -mxConnectionHandler.prototype.constraintHandler = null; - -/** - * Variable: error - * - * Holds the current validation error while connections are being created. - */ -mxConnectionHandler.prototype.error = null; - -/** - * Variable: waypointsEnabled - * - * Specifies if single clicks should add waypoints on the new edge. Default is - * false. - */ -mxConnectionHandler.prototype.waypointsEnabled = false; - -/** - * Variable: tapAndHoldEnabled - * - * Specifies if tap and hold should be used for starting connections on touch-based - * devices. Default is true. - */ -mxConnectionHandler.prototype.tapAndHoldEnabled = true; - -/** - * Variable: tapAndHoldDelay - * - * Specifies the time for a tap and hold. Default is 500 ms. - */ -mxConnectionHandler.prototype.tapAndHoldDelay = 500; - -/** - * Variable: tapAndHoldInProgress - * - * True if the timer for tap and hold events is running. - */ -mxConnectionHandler.prototype.tapAndHoldInProgress = false; - -/** - * Variable: tapAndHoldValid - * - * True as long as the timer is running and the touch events - * stay within the given <tapAndHoldTolerance>. - */ -mxConnectionHandler.prototype.tapAndHoldValid = false; - -/** - * Variable: tapAndHoldTolerance - * - * Specifies the tolerance for a tap and hold. Default is 4 pixels. - */ -mxConnectionHandler.prototype.tapAndHoldTolerance = 4; - -/** - * Variable: initialTouchX - * - * Holds the x-coordinate of the intial touch event for tap and hold. - */ -mxConnectionHandler.prototype.initialTouchX = 0; - -/** - * Variable: initialTouchY - * - * Holds the y-coordinate of the intial touch event for tap and hold. - */ -mxConnectionHandler.prototype.initialTouchY = 0; - -/** - * Variable: ignoreMouseDown - * - * Specifies if the connection handler should ignore the state of the mouse - * button when highlighting the source. Default is false, that is, the - * handler only highlights the source if no button is being pressed. - */ -mxConnectionHandler.prototype.ignoreMouseDown = false; - -/** - * Variable: first - * - * Holds the <mxPoint> where the mouseDown took place while the handler is - * active. - */ -mxConnectionHandler.prototype.first = null; - -/** - * Variable: connectIconOffset - * - * Holds the offset for connect icons during connection preview. - * Default is mxPoint(0, <mxConstants.TOOLTIP_VERTICAL_OFFSET>). - * Note that placing the icon under the mouse pointer with an - * offset of (0,0) will affect hit detection. - */ -mxConnectionHandler.prototype.connectIconOffset = new mxPoint(0, mxConstants.TOOLTIP_VERTICAL_OFFSET); - -/** - * Variable: edgeState - * - * Optional <mxCellState> that represents the preview edge while the - * handler is active. This is created in <createEdgeState>. - */ -mxConnectionHandler.prototype.edgeState = null; - -/** - * Variable: changeHandler - * - * Holds the change event listener for later removal. - */ -mxConnectionHandler.prototype.changeHandler = null; - -/** - * Variable: drillHandler - * - * Holds the drill event listener for later removal. - */ -mxConnectionHandler.prototype.drillHandler = null; - -/** - * Variable: mouseDownCounter - * - * Counts the number of mouseDown events since the start. The initial mouse - * down event counts as 1. - */ -mxConnectionHandler.prototype.mouseDownCounter = 0; - -/** - * Variable: movePreviewAway - * - * Switch to enable moving the preview away from the mousepointer. This is required in browsers - * where the preview cannot be made transparent to events and if the built-in hit detection on - * the HTML elements in the page should be used. Default is the value of <mxClient.IS_VML>. - */ -mxConnectionHandler.prototype.movePreviewAway = mxClient.IS_VML; - -/** - * Function: isEnabled - * - * Returns true if events are handled. This implementation - * returns <enabled>. - */ -mxConnectionHandler.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. - */ -mxConnectionHandler.prototype.setEnabled = function(enabled) -{ - this.enabled = enabled; -}; - -/** - * Function: isCreateTarget - * - * Returns <createTarget>. - */ -mxConnectionHandler.prototype.isCreateTarget = function() -{ - return this.createTarget; -}; - -/** - * Function: setCreateTarget - * - * Sets <createTarget>. - */ -mxConnectionHandler.prototype.setCreateTarget = function(value) -{ - this.createTarget = value; -}; - -/** - * Function: createShape - * - * Creates the preview shape for new connections. - */ -mxConnectionHandler.prototype.createShape = function() -{ - // Creates the edge preview - var shape = new mxPolyline([], mxConstants.INVALID_COLOR); - shape.isDashed = true; - shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - shape.init(this.graph.getView().getOverlayPane()); - - // Event-transparency - if (this.graph.dialect == mxConstants.DIALECT_SVG) - { - // Sets event transparency on the internal shapes that represent - // the actual dashed line on the screen - shape.pipe.setAttribute('style', 'pointer-events:none;'); - shape.innerNode.setAttribute('style', 'pointer-events:none;'); - } - else - { - // Workaround no event transparency for preview in IE - // FIXME: 3,3 pixel offset for custom hit detection in IE - var getState = mxUtils.bind(this, function(evt) - { - var pt = mxUtils.convertPoint(this.graph.container, mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - - return this.graph.view.getState(this.graph.getCellAt(pt.x, pt.y)); - }); - - // Redirects events on the shape to the graph - mxEvent.redirectMouseEvents(shape.node, this.graph, getState); - } - - return shape; -}; - -/** - * Function: init - * - * Initializes the shapes required for this connection handler. This should - * be invoked if <mxGraph.container> is assigned after the connection - * handler has been created. - */ -mxConnectionHandler.prototype.init = function() -{ - this.graph.addMouseListener(this); - this.marker = this.createMarker(); - this.constraintHandler = new mxConstraintHandler(this.graph); - - // Redraws the icons if the graph changes - this.changeHandler = mxUtils.bind(this, function(sender) - { - if (this.iconState != null) - { - this.iconState = this.graph.getView().getState(this.iconState.cell); - } - - if (this.iconState != null) - { - this.redrawIcons(this.icons, this.iconState); - } - else - { - this.destroyIcons(this.icons); - this.previous = null; - } - - this.constraintHandler.reset(); - }); - - this.graph.getModel().addListener(mxEvent.CHANGE, this.changeHandler); - this.graph.getView().addListener(mxEvent.SCALE, this.changeHandler); - this.graph.getView().addListener(mxEvent.TRANSLATE, this.changeHandler); - this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.changeHandler); - - // Removes the icon if we step into/up or start editing - this.drillHandler = mxUtils.bind(this, function(sender) - { - this.destroyIcons(this.icons); - }); - - this.graph.addListener(mxEvent.START_EDITING, this.drillHandler); - this.graph.getView().addListener(mxEvent.DOWN, this.drillHandler); - this.graph.getView().addListener(mxEvent.UP, this.drillHandler); -}; - -/** - * Function: isConnectableCell - * - * Returns true if the given cell is connectable. This is a hook to - * disable floating connections. This implementation returns true. - */ -mxConnectionHandler.prototype.isConnectableCell = function(cell) -{ - return true; -}; - -/** - * Function: createMarker - * - * Creates and returns the <mxCellMarker> used in <marker>. - */ -mxConnectionHandler.prototype.createMarker = function() -{ - var marker = new mxCellMarker(this.graph); - marker.hotspotEnabled = true; - - // Overrides to return cell at location only if valid (so that - // there is no highlight for invalid cells) - marker.getCell = mxUtils.bind(this, function(evt, cell) - { - var cell = mxCellMarker.prototype.getCell.apply(marker, arguments); - this.error = null; - - if (!this.isConnectableCell(cell)) - { - return null; - } - - if (cell != null) - { - if (this.isConnecting()) - { - if (this.previous != null) - { - this.error = this.validateConnection(this.previous.cell, cell); - - if (this.error != null && this.error.length == 0) - { - cell = null; - - // Enables create target inside groups - if (this.isCreateTarget()) - { - this.error = null; - } - } - } - } - else if (!this.isValidSource(cell)) - { - cell = null; - } - } - else if (this.isConnecting() && !this.isCreateTarget() && - !this.graph.allowDanglingEdges) - { - this.error = ''; - } - - return cell; - }); - - // Sets the highlight color according to validateConnection - marker.isValidState = mxUtils.bind(this, function(state) - { - if (this.isConnecting()) - { - return this.error == null; - } - else - { - return mxCellMarker.prototype.isValidState.apply(marker, arguments); - } - }); - - // Overrides to use marker color only in highlight mode or for - // target selection - marker.getMarkerColor = mxUtils.bind(this, function(evt, state, isValid) - { - return (this.connectImage == null || this.isConnecting()) ? - mxCellMarker.prototype.getMarkerColor.apply(marker, arguments) : - null; - }); - - // Overrides to use hotspot only for source selection otherwise - // intersects always returns true when over a cell - marker.intersects = mxUtils.bind(this, function(state, evt) - { - if (this.connectImage != null || this.isConnecting()) - { - return true; - } - - return mxCellMarker.prototype.intersects.apply(marker, arguments); - }); - - return marker; -}; - -/** - * Function: start - * - * Starts a new connection for the given state and coordinates. - */ -mxConnectionHandler.prototype.start = function(state, x, y, edgeState) -{ - this.previous = state; - this.first = new mxPoint(x, y); - this.edgeState = (edgeState != null) ? edgeState : this.createEdgeState(null); - - // Marks the source state - this.marker.currentColor = this.marker.validColor; - this.marker.markedState = state; - this.marker.mark(); - - this.fireEvent(new mxEventObject(mxEvent.START, 'state', this.previous)); -}; - -/** - * Function: isConnecting - * - * Returns true if the source terminal has been clicked and a new - * connection is currently being previewed. - */ -mxConnectionHandler.prototype.isConnecting = function() -{ - return this.first != null && this.shape != null; -}; - -/** - * Function: isValidSource - * - * Returns <mxGraph.isValidSource> for the given source terminal. - * - * Parameters: - * - * cell - <mxCell> that represents the source terminal. - */ -mxConnectionHandler.prototype.isValidSource = function(cell) -{ - return this.graph.isValidSource(cell); -}; - -/** - * Function: isValidTarget - * - * Returns true. The call to <mxGraph.isValidTarget> is implicit by calling - * <mxGraph.getEdgeValidationError> in <validateConnection>. This is an - * additional hook for disabling certain targets in this specific handler. - * - * Parameters: - * - * cell - <mxCell> that represents the target terminal. - */ -mxConnectionHandler.prototype.isValidTarget = function(cell) -{ - return true; -}; - -/** - * Function: validateConnection - * - * Returns the error message or an empty string if the connection for the - * given source target pair is not valid. Otherwise it returns null. This - * implementation uses <mxGraph.getEdgeValidationError>. - * - * Parameters: - * - * source - <mxCell> that represents the source terminal. - * target - <mxCell> that represents the target terminal. - */ -mxConnectionHandler.prototype.validateConnection = function(source, target) -{ - if (!this.isValidTarget(target)) - { - return ''; - } - - return this.graph.getEdgeValidationError(null, source, target); -}; - -/** - * Function: getConnectImage - * - * Hook to return the <mxImage> used for the connection icon of the given - * <mxCellState>. This implementation returns <connectImage>. - * - * Parameters: - * - * state - <mxCellState> whose connect image should be returned. - */ -mxConnectionHandler.prototype.getConnectImage = function(state) -{ - return this.connectImage; -}; - -/** - * Function: isMoveIconToFrontForState - * - * Returns true if the state has a HTML label in the graph's container, otherwise - * it returns <moveIconFront>. - * - * Parameters: - * - * state - <mxCellState> whose connect icons should be returned. - */ -mxConnectionHandler.prototype.isMoveIconToFrontForState = function(state) -{ - if (state.text != null && state.text.node.parentNode == this.graph.container) - { - return true; - } - - return this.moveIconFront; -}; - -/** - * Function: createIcons - * - * Creates the array <mxImageShapes> that represent the connect icons for - * the given <mxCellState>. - * - * Parameters: - * - * state - <mxCellState> whose connect icons should be returned. - */ -mxConnectionHandler.prototype.createIcons = function(state) -{ - var image = this.getConnectImage(state); - - if (image != null && state != null) - { - this.iconState = state; - var icons = []; - - // Cannot use HTML for the connect icons because the icon receives all - // mouse move events in IE, must use VML and SVG instead even if the - // connect-icon appears behind the selection border and the selection - // border consumes the events before the icon gets a chance - var bounds = new mxRectangle(0, 0, image.width, image.height); - var icon = new mxImageShape(bounds, image.src, null, null, 0); - icon.preserveImageAspect = false; - - if (this.isMoveIconToFrontForState(state)) - { - icon.dialect = mxConstants.DIALECT_STRICTHTML; - icon.init(this.graph.container); - } - else - { - icon.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_SVG : - mxConstants.DIALECT_VML; - icon.init(this.graph.getView().getOverlayPane()); - - // Move the icon back in the overlay pane - if (this.moveIconBack && icon.node.previousSibling != null) - { - icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild); - } - } - - icon.node.style.cursor = mxConstants.CURSOR_CONNECT; - - // Events transparency - var getState = mxUtils.bind(this, function() - { - return (this.currentState != null) ? this.currentState : state; - }); - - // Updates the local icon before firing the mouse down event. - var mouseDown = mxUtils.bind(this, function(evt) - { - if (!mxEvent.isConsumed(evt)) - { - this.icon = icon; - this.graph.fireMouseEvent(mxEvent.MOUSE_DOWN, - new mxMouseEvent(evt, getState())); - } - }); - - mxEvent.redirectMouseEvents(icon.node, this.graph, getState, mouseDown); - - icons.push(icon); - this.redrawIcons(icons, this.iconState); - - return icons; - } - - return null; -}; - -/** - * Function: redrawIcons - * - * Redraws the given array of <mxImageShapes>. - * - * Parameters: - * - * icons - Optional array of <mxImageShapes> to be redrawn. - */ -mxConnectionHandler.prototype.redrawIcons = function(icons, state) -{ - if (icons != null && icons[0] != null && state != null) - { - var pos = this.getIconPosition(icons[0], state); - icons[0].bounds.x = pos.x; - icons[0].bounds.y = pos.y; - icons[0].redraw(); - } -}; - -/** - * Function: redrawIcons - * - * Redraws the given array of <mxImageShapes>. - * - * Parameters: - * - * icons - Optional array of <mxImageShapes> to be redrawn. - */ -mxConnectionHandler.prototype.getIconPosition = function(icon, state) -{ - var scale = this.graph.getView().scale; - var cx = state.getCenterX(); - var cy = state.getCenterY(); - - if (this.graph.isSwimlane(state.cell)) - { - var size = this.graph.getStartSize(state.cell); - - cx = (size.width != 0) ? state.x + size.width * scale / 2 : cx; - cy = (size.height != 0) ? state.y + size.height * scale / 2 : cy; - } - - return new mxPoint(cx - icon.bounds.width / 2, - cy - icon.bounds.height / 2); -}; - -/** - * Function: destroyIcons - * - * Destroys the given array of <mxImageShapes>. - * - * Parameters: - * - * icons - Optional array of <mxImageShapes> to be destroyed. - */ -mxConnectionHandler.prototype.destroyIcons = function(icons) -{ - if (icons != null) - { - this.iconState = null; - - for (var i = 0; i < icons.length; i++) - { - icons[i].destroy(); - } - } -}; - -/** - * Function: isStartEvent - * - * Returns true if the given mouse down event should start this handler. The - * This implementation returns true if the event does not force marquee - * selection, and the currentConstraint and currentFocus of the - * <constraintHandler> are not null, or <previous> and <error> are not null and - * <icons> is null or <icons> and <icon> are not null. - */ -mxConnectionHandler.prototype.isStartEvent = function(me) -{ - return !this.graph.isForceMarqueeEvent(me.getEvent()) && - ((this.constraintHandler.currentFocus != null && - this.constraintHandler.currentConstraint != null) || - (this.previous != null && this.error == null && - (this.icons == null || (this.icons != null && this.icon != null)))); -}; - -/** - * Function: mouseDown - * - * Handles the event by initiating a new connection. - */ -mxConnectionHandler.prototype.mouseDown = function(sender, me) -{ - this.mouseDownCounter++; - - if (this.isEnabled() && this.graph.isEnabled() && !me.isConsumed() && - !this.isConnecting() && this.isStartEvent(me)) - { - if (this.constraintHandler.currentConstraint != null && - this.constraintHandler.currentFocus != null && - this.constraintHandler.currentPoint != null) - { - this.sourceConstraint = this.constraintHandler.currentConstraint; - this.previous = this.constraintHandler.currentFocus; - this.first = this.constraintHandler.currentPoint.clone(); - } - else - { - // Stores the location of the initial mousedown - this.first = new mxPoint(me.getGraphX(), me.getGraphY()); - } - - this.edgeState = this.createEdgeState(me); - this.mouseDownCounter = 1; - - if (this.waypointsEnabled && this.shape == null) - { - this.waypoints = null; - this.shape = this.createShape(); - } - - // Stores the starting point in the geometry of the preview - if (this.previous == null && this.edgeState != null) - { - var pt = this.graph.getPointForEvent(me.getEvent()); - this.edgeState.cell.geometry.setTerminalPoint(pt, true); - } - - this.fireEvent(new mxEventObject(mxEvent.START, 'state', this.previous)); - - me.consume(); - } - // Handles connecting via tap and hold - else if (mxClient.IS_TOUCH && this.tapAndHoldEnabled && !this.tapAndHoldInProgress && - this.isEnabled() && this.graph.isEnabled() && !this.isConnecting()) - { - this.tapAndHoldInProgress = true; - this.initialTouchX = me.getX(); - this.initialTouchY = me.getY(); - var state = this.graph.view.getState(this.marker.getCell(me)); - - var handler = function() - { - if (this.tapAndHoldValid) - { - this.tapAndHold(me, state); - } - - this.tapAndHoldInProgress = false; - this.tapAndHoldValid = false; - }; - - if (this.tapAndHoldThread) - { - window.clearTimeout(this.tapAndHoldThread); - } - - this.tapAndHoldThread = window.setTimeout(mxUtils.bind(this, handler), this.tapAndHoldDelay); - this.tapAndHoldValid = true; - } - - this.selectedIcon = this.icon; - this.icon = null; -}; - -/** - * Function: tapAndHold - * - * Handles the <mxMouseEvent> by highlighting the <mxCellState>. - * - * Parameters: - * - * me - <mxMouseEvent> that represents the touch event. - * state - Optional <mxCellState> that is associated with the event. - */ -mxConnectionHandler.prototype.tapAndHold = function(me, state) -{ - if (state != null) - { - this.marker.currentColor = this.marker.validColor; - this.marker.markedState = state; - this.marker.mark(); - - this.first = new mxPoint(me.getGraphX(), me.getGraphY()); - this.edgeState = this.createEdgeState(me); - this.previous = state; - this.fireEvent(new mxEventObject(mxEvent.START, 'state', this.previous)); - } -}; - -/** - * Function: isImmediateConnectSource - * - * Returns true if a tap on the given source state should immediately start - * connecting. This implementation returns true if the state is not movable - * in the graph. - */ -mxConnectionHandler.prototype.isImmediateConnectSource = function(state) -{ - return !this.graph.isCellMovable(state.cell); -}; - -/** - * Function: createEdgeState - * - * Hook to return an <mxCellState> which may be used during the preview. - * This implementation returns null. - * - * Use the following code to create a preview for an existing edge style: - * - * [code] - * graph.connectionHandler.createEdgeState = function(me) - * { - * var edge = graph.createEdge(null, null, null, null, null, 'edgeStyle=elbowEdgeStyle'); - * - * return new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge)); - * }; - * [/code] - */ -mxConnectionHandler.prototype.createEdgeState = function(me) -{ - return null; -}; - -/** - * Function: updateCurrentState - * - * Updates the current state for a given mouse move event by using - * the <marker>. - */ -mxConnectionHandler.prototype.updateCurrentState = function(me) -{ - var state = this.marker.process(me); - this.constraintHandler.update(me, this.first == null); - this.currentState = state; -}; - -/** - * Function: convertWaypoint - * - * Converts the given point from screen coordinates to model coordinates. - */ -mxConnectionHandler.prototype.convertWaypoint = function(point) -{ - var scale = this.graph.getView().getScale(); - var tr = this.graph.getView().getTranslate(); - - point.x = point.x / scale - tr.x; - point.y = point.y / scale - tr.y; -}; - -/** - * Function: mouseMove - * - * Handles the event by updating the preview edge or by highlighting - * a possible source or target terminal. - */ -mxConnectionHandler.prototype.mouseMove = function(sender, me) -{ - if (this.tapAndHoldValid) - { - this.tapAndHoldValid = - Math.abs(this.initialTouchX - me.getX()) < this.tapAndHoldTolerance && - Math.abs(this.initialTouchY - me.getY()) < this.tapAndHoldTolerance; - } - - if (!me.isConsumed() && (this.ignoreMouseDown || this.first != null || !this.graph.isMouseDown)) - { - // Handles special case when handler is disabled during highlight - if (!this.isEnabled() && this.currentState != null) - { - this.destroyIcons(this.icons); - this.currentState = null; - } - - if (this.first != null || (this.isEnabled() && this.graph.isEnabled())) - { - this.updateCurrentState(me); - } - - if (this.first != null) - { - var view = this.graph.getView(); - var scale = view.scale; - var point = new mxPoint(this.graph.snap(me.getGraphX() / scale) * scale, - this.graph.snap(me.getGraphY() / scale) * scale); - var constraint = null; - var current = point; - - // Uses the current point from the constraint handler if available - if (this.constraintHandler.currentConstraint != null && - this.constraintHandler.currentFocus != null && - this.constraintHandler.currentPoint != null) - { - constraint = this.constraintHandler.currentConstraint; - current = this.constraintHandler.currentPoint.clone(); - } - - var pt2 = this.first; - - // Moves the connect icon with the mouse - if (this.selectedIcon != null) - { - var w = this.selectedIcon.bounds.width; - var h = this.selectedIcon.bounds.height; - - if (this.currentState != null && this.targetConnectImage) - { - var pos = this.getIconPosition(this.selectedIcon, this.currentState); - this.selectedIcon.bounds.x = pos.x; - this.selectedIcon.bounds.y = pos.y; - } - else - { - var bounds = new mxRectangle(me.getGraphX() + this.connectIconOffset.x, - me.getGraphY() + this.connectIconOffset.y, w, h); - this.selectedIcon.bounds = bounds; - } - - this.selectedIcon.redraw(); - } - - // Uses edge state to compute the terminal points - if (this.edgeState != null) - { - this.edgeState.absolutePoints = [null, (this.currentState != null) ? null : current]; - this.graph.view.updateFixedTerminalPoint(this.edgeState, this.previous, true, this.sourceConstraint); - - if (this.currentState != null) - { - if (constraint == null) - { - constraint = this.graph.getConnectionConstraint(this.edgeState, this.previous, false); - } - - this.edgeState.setAbsoluteTerminalPoint(null, false); - this.graph.view.updateFixedTerminalPoint(this.edgeState, this.currentState, false, constraint); - } - - // Scales and translates the waypoints to the model - var realPoints = null; - - if (this.waypoints != null) - { - realPoints = []; - - for (var i = 0; i < this.waypoints.length; i++) - { - var pt = this.waypoints[i].clone(); - this.convertWaypoint(pt); - realPoints[i] = pt; - } - } - - this.graph.view.updatePoints(this.edgeState, realPoints, this.previous, this.currentState); - this.graph.view.updateFloatingTerminalPoints(this.edgeState, this.previous, this.currentState); - current = this.edgeState.absolutePoints[this.edgeState.absolutePoints.length - 1]; - pt2 = this.edgeState.absolutePoints[0]; - } - else - { - if (this.currentState != null) - { - if (this.constraintHandler.currentConstraint == null) - { - var tmp = this.getTargetPerimeterPoint(this.currentState, me); - - if (tmp != null) - { - current = tmp; - } - } - } - - // Computes the source perimeter point - if (this.sourceConstraint == null && this.previous != null) - { - var next = (this.waypoints != null && this.waypoints.length > 0) ? - this.waypoints[0] : current; - var tmp = this.getSourcePerimeterPoint(this.previous, next, me); - - if (tmp != null) - { - pt2 = tmp; - } - } - } - - // Makes sure the cell under the mousepointer can be detected - // by moving the preview shape away from the mouse. This - // makes sure the preview shape does not prevent the detection - // of the cell under the mousepointer even for slow gestures. - if (this.currentState == null && this.movePreviewAway) - { - var tmp = pt2; - - if (this.edgeState != null && this.edgeState.absolutePoints.length > 2) - { - var tmp2 = this.edgeState.absolutePoints[this.edgeState.absolutePoints.length - 2]; - - if (tmp2 != null) - { - tmp = tmp2; - } - } - - var dx = current.x - tmp.x; - var dy = current.y - tmp.y; - - var len = Math.sqrt(dx * dx + dy * dy); - - if (len == 0) - { - return; - } - - current.x -= dx * 4 / len; - current.y -= dy * 4 / len; - } - - // Creates the preview shape (lazy) - if (this.shape == null) - { - var dx = Math.abs(point.x - this.first.x); - var dy = Math.abs(point.y - this.first.y); - - if (dx > this.graph.tolerance || dy > this.graph.tolerance) - { - this.shape = this.createShape(); - - // Revalidates current connection - this.updateCurrentState(me); - } - } - - // Updates the points in the preview edge - if (this.shape != null) - { - if (this.edgeState != null) - { - this.shape.points = this.edgeState.absolutePoints; - } - else - { - var pts = [pt2]; - - if (this.waypoints != null) - { - pts = pts.concat(this.waypoints); - } - - pts.push(current); - this.shape.points = pts; - } - - this.drawPreview(); - } - - mxEvent.consume(me.getEvent()); - me.consume(); - } - else if(!this.isEnabled() || !this.graph.isEnabled()) - { - this.constraintHandler.reset(); - } - else if (this.previous != this.currentState && this.edgeState == null) - { - this.destroyIcons(this.icons); - this.icons = null; - - // Sets the cursor on the current shape - if (this.currentState != null && this.error == null) - { - this.icons = this.createIcons(this.currentState); - - if (this.icons == null) - { - this.currentState.setCursor(mxConstants.CURSOR_CONNECT); - me.consume(); - } - } - - this.previous = this.currentState; - } - else if (this.previous == this.currentState && this.currentState != null && this.icons == null && - !this.graph.isMouseDown) - { - // Makes sure that no cursors are changed - me.consume(); - } - - if (this.constraintHandler.currentConstraint != null) - { - this.marker.reset(); - } - - if (!this.graph.isMouseDown && this.currentState != null && this.icons != null) - { - var hitsIcon = false; - var target = me.getSource(); - - for (var i = 0; i < this.icons.length && !hitsIcon; i++) - { - hitsIcon = target == this.icons[i].node || target.parentNode == this.icons[i].node; - } - - if (!hitsIcon) - { - this.updateIcons(this.currentState, this.icons, me); - } - } - } - else - { - this.constraintHandler.reset(); - } -}; - -/** - * Function: getTargetPerimeterPoint - * - * Returns the perimeter point for the given target state. - * - * Parameters: - * - * state - <mxCellState> that represents the target cell state. - * me - <mxMouseEvent> that represents the mouse move. - */ -mxConnectionHandler.prototype.getTargetPerimeterPoint = function(state, me) -{ - var result = null; - var view = state.view; - var targetPerimeter = view.getPerimeterFunction(state); - - if (targetPerimeter != null) - { - var next = (this.waypoints != null && this.waypoints.length > 0) ? - this.waypoints[this.waypoints.length - 1] : - new mxPoint(this.previous.getCenterX(), this.previous.getCenterY()); - var tmp = targetPerimeter(view.getPerimeterBounds(state), - this.edgeState, next, false); - - if (tmp != null) - { - result = tmp; - } - } - else - { - result = new mxPoint(state.getCenterX(), state.getCenterY()); - } - - return result; -}; - -/** - * Function: getSourcePerimeterPoint - * - * Hook to update the icon position(s) based on a mouseOver event. This is - * an empty implementation. - * - * Parameters: - * - * state - <mxCellState> that represents the target cell state. - * next - <mxPoint> that represents the next point along the previewed edge. - * me - <mxMouseEvent> that represents the mouse move. - */ -mxConnectionHandler.prototype.getSourcePerimeterPoint = function(state, next, me) -{ - var result = null; - var view = state.view; - var sourcePerimeter = view.getPerimeterFunction(state); - - if (sourcePerimeter != null) - { - var tmp = sourcePerimeter(view.getPerimeterBounds(state), state, next, false); - - if (tmp != null) - { - result = tmp; - } - } - else - { - result = new mxPoint(state.getCenterX(), state.getCenterY()); - } - - return result; -}; - - -/** - * Function: updateIcons - * - * Hook to update the icon position(s) based on a mouseOver event. This is - * an empty implementation. - * - * Parameters: - * - * state - <mxCellState> under the mouse. - * icons - Array of currently displayed icons. - * me - <mxMouseEvent> that contains the mouse event. - */ -mxConnectionHandler.prototype.updateIcons = function(state, icons, me) -{ - // empty -}; - -/** - * Function: isStopEvent - * - * Returns true if the given mouse up event should stop this handler. The - * connection will be created if <error> is null. Note that this is only - * called if <waypointsEnabled> is true. This implemtation returns true - * if there is a cell state in the given event. - */ -mxConnectionHandler.prototype.isStopEvent = function(me) -{ - return me.getState() != null; -}; - -/** - * Function: addWaypoint - * - * Adds the waypoint for the given event to <waypoints>. - */ -mxConnectionHandler.prototype.addWaypointForEvent = function(me) -{ - var point = mxUtils.convertPoint(this.graph.container, me.getX(), me.getY()); - var dx = Math.abs(point.x - this.first.x); - var dy = Math.abs(point.y - this.first.y); - var addPoint = this.waypoints != null || (this.mouseDownCounter > 1 && - (dx > this.graph.tolerance || dy > this.graph.tolerance)); - - if (addPoint) - { - if (this.waypoints == null) - { - this.waypoints = []; - } - - var scale = this.graph.view.scale; - var point = new mxPoint(this.graph.snap(me.getGraphX() / scale) * scale, - this.graph.snap(me.getGraphY() / scale) * scale); - this.waypoints.push(point); - } -}; - -/** - * Function: mouseUp - * - * Handles the event by inserting the new connection. - */ -mxConnectionHandler.prototype.mouseUp = function(sender, me) -{ - if (!me.isConsumed() && this.isConnecting()) - { - if (this.waypointsEnabled && !this.isStopEvent(me)) - { - this.addWaypointForEvent(me); - me.consume(); - - return; - } - - // Inserts the edge if no validation error exists - if (this.error == null) - { - var source = (this.previous != null) ? this.previous.cell : null; - var target = null; - - if (this.constraintHandler.currentConstraint != null && - this.constraintHandler.currentFocus != null) - { - target = this.constraintHandler.currentFocus.cell; - } - - if (target == null && this.marker.hasValidState()) - { - target = this.marker.validState.cell; - } - - this.connect(source, target, me.getEvent(), me.getCell()); - } - else - { - // Selects the source terminal for self-references - if (this.previous != null && this.marker.validState != null && - this.previous.cell == this.marker.validState.cell) - { - this.graph.selectCellForEvent(this.marker.source, evt); - } - - // Displays the error message if it is not an empty string, - // for empty error messages, the event is silently dropped - if (this.error.length > 0) - { - this.graph.validationAlert(this.error); - } - } - - // Redraws the connect icons and resets the handler state - this.destroyIcons(this.icons); - me.consume(); - } - - if (this.first != null) - { - this.reset(); - } - - this.tapAndHoldInProgress = false; - this.tapAndHoldValid = false; -}; - -/** - * Function: reset - * - * Resets the state of this handler. - */ -mxConnectionHandler.prototype.reset = function() -{ - if (this.shape != null) - { - this.shape.destroy(); - this.shape = null; - } - - this.destroyIcons(this.icons); - this.icons = null; - this.marker.reset(); - this.constraintHandler.reset(); - this.selectedIcon = null; - this.edgeState = null; - this.previous = null; - this.error = null; - this.sourceConstraint = null; - this.mouseDownCounter = 0; - this.first = null; - this.icon = null; - - this.fireEvent(new mxEventObject(mxEvent.RESET)); -}; - -/** - * Function: drawPreview - * - * Redraws the preview edge using the color and width returned by - * <getEdgeColor> and <getEdgeWidth>. - */ -mxConnectionHandler.prototype.drawPreview = function() -{ - var valid = this.error == null; - var color = this.getEdgeColor(valid); - - if (this.shape.dialect == mxConstants.DIALECT_SVG) - { - this.shape.innerNode.setAttribute('stroke', color); - } - else - { - this.shape.node.strokecolor = color; - } - - this.shape.strokewidth = this.getEdgeWidth(valid); - this.shape.redraw(); - - // Workaround to force a repaint in AppleWebKit - mxUtils.repaintGraph(this.graph, this.shape.points[1]); -}; - -/** - * Function: getEdgeColor - * - * Returns the color used to draw the preview edge. This returns green if - * there is no edge validation error and red otherwise. - * - * Parameters: - * - * valid - Boolean indicating if the color for a valid edge should be - * returned. - */ -mxConnectionHandler.prototype.getEdgeColor = function(valid) -{ - return (valid) ? mxConstants.VALID_COLOR : mxConstants.INVALID_COLOR; -}; - -/** - * Function: getEdgeWidth - * - * Returns the width used to draw the preview edge. This returns 3 if - * there is no edge validation error and 1 otherwise. - * - * Parameters: - * - * valid - Boolean indicating if the width for a valid edge should be - * returned. - */ -mxConnectionHandler.prototype.getEdgeWidth = function(valid) -{ - return (valid) ? 3 : 1; -}; - -/** - * Function: connect - * - * Connects the given source and target using a new edge. This - * implementation uses <createEdge> to create the edge. - * - * Parameters: - * - * source - <mxCell> that represents the source terminal. - * target - <mxCell> that represents the target terminal. - * evt - Mousedown event of the connect gesture. - * dropTarget - <mxCell> that represents the cell under the mouse when it was - * released. - */ -mxConnectionHandler.prototype.connect = function(source, target, evt, dropTarget) -{ - if (target != null || this.isCreateTarget() || this.graph.allowDanglingEdges) - { - // Uses the common parent of source and target or - // the default parent to insert the edge - var model = this.graph.getModel(); - var edge = null; - - model.beginUpdate(); - try - { - if (source != null && target == null && this.isCreateTarget()) - { - target = this.createTargetVertex(evt, source); - - if (target != null) - { - dropTarget = this.graph.getDropTarget([target], evt, dropTarget); - - // Disables edges as drop targets if the target cell was created - // FIXME: Should not shift if vertex was aligned (same in Java) - if (dropTarget == null || !this.graph.getModel().isEdge(dropTarget)) - { - var pstate = this.graph.getView().getState(dropTarget); - - if (pstate != null) - { - var tmp = model.getGeometry(target); - tmp.x -= pstate.origin.x; - tmp.y -= pstate.origin.y; - } - } - else - { - dropTarget = this.graph.getDefaultParent(); - } - - this.graph.addCell(target, dropTarget); - } - } - - var parent = this.graph.getDefaultParent(); - - if (source != null && target != null && - model.getParent(source) == model.getParent(target) && - model.getParent(model.getParent(source)) != model.getRoot()) - { - parent = model.getParent(source); - - if ((source.geometry != null && source.geometry.relative) && - (target.geometry != null && target.geometry.relative)) - { - parent = model.getParent(parent); - } - } - - // Uses the value of the preview edge state for inserting - // the new edge into the graph - var value = null; - var style = null; - - if (this.edgeState != null) - { - value = this.edgeState.cell.value; - style = this.edgeState.cell.style; - } - - edge = this.insertEdge(parent, null, value, source, target, style); - - if (edge != null) - { - // Updates the connection constraints - this.graph.setConnectionConstraint(edge, source, true, this.sourceConstraint); - this.graph.setConnectionConstraint(edge, target, false, this.constraintHandler.currentConstraint); - - // Uses geometry of the preview edge state - if (this.edgeState != null) - { - model.setGeometry(edge, this.edgeState.cell.geometry); - } - - // Makes sure the edge has a non-null, relative geometry - var geo = model.getGeometry(edge); - - if (geo == null) - { - geo = new mxGeometry(); - geo.relative = true; - - model.setGeometry(edge, geo); - } - - // Uses scaled waypoints in geometry - if (this.waypoints != null && this.waypoints.length > 0) - { - var s = this.graph.view.scale; - var tr = this.graph.view.translate; - geo.points = []; - - for (var i = 0; i < this.waypoints.length; i++) - { - var pt = this.waypoints[i]; - geo.points.push(new mxPoint(pt.x / s - tr.x, pt.y / s - tr.y)); - } - } - - if (target == null) - { - var pt = this.graph.getPointForEvent(evt, false); - pt.x -= this.graph.panDx / this.graph.view.scale; - pt.y -= this.graph.panDy / this.graph.view.scale; - geo.setTerminalPoint(pt, false); - } - - this.fireEvent(new mxEventObject(mxEvent.CONNECT, - 'cell', edge, 'event', evt, 'target', dropTarget)); - } - } - catch (e) - { - mxLog.show(); - mxLog.debug(e.message); - } - finally - { - model.endUpdate(); - } - - if (this.select) - { - this.selectCells(edge, target); - } - } -}; - -/** - * Function: selectCells - * - * Selects the given edge after adding a new connection. The target argument - * contains the target vertex if one has been inserted. - */ -mxConnectionHandler.prototype.selectCells = function(edge, target) -{ - this.graph.setSelectionCell(edge); -}; - -/** - * Function: insertEdge - * - * Creates, inserts and returns the new edge for the given parameters. This - * implementation does only use <createEdge> if <factoryMethod> is defined, - * otherwise <mxGraph.insertEdge> will be used. - */ -mxConnectionHandler.prototype.insertEdge = function(parent, id, value, source, target, style) -{ - if (this.factoryMethod == null) - { - return this.graph.insertEdge(parent, id, value, source, target, style); - } - else - { - var edge = this.createEdge(value, source, target, style); - edge = this.graph.addEdge(edge, parent, source, target); - - return edge; - } -}; - -/** - * Function: createTargetVertex - * - * Hook method for creating new vertices on the fly if no target was - * under the mouse. This is only called if <createTarget> is true and - * returns null. - * - * Parameters: - * - * evt - Mousedown event of the connect gesture. - * source - <mxCell> that represents the source terminal. - */ -mxConnectionHandler.prototype.createTargetVertex = function(evt, source) -{ - // Uses the first non-relative source - var geo = this.graph.getCellGeometry(source); - - while (geo != null && geo.relative) - { - source = this.graph.getModel().getParent(source); - geo = this.graph.getCellGeometry(source); - } - - var clone = this.graph.cloneCells([source])[0]; - var geo = this.graph.getModel().getGeometry(clone); - - if (geo != null) - { - var point = this.graph.getPointForEvent(evt); - geo.x = this.graph.snap(point.x - geo.width / 2) - this.graph.panDx / this.graph.view.scale; - geo.y = this.graph.snap(point.y - geo.height / 2) - this.graph.panDy / this.graph.view.scale; - - // Aligns with source if within certain tolerance - if (this.first != null) - { - var sourceState = this.graph.view.getState(source); - - if (sourceState != null) - { - var tol = this.getAlignmentTolerance(); - - if (Math.abs(this.graph.snap(this.first.x) - - this.graph.snap(point.x)) <= tol) - { - geo.x = sourceState.x; - } - else if (Math.abs(this.graph.snap(this.first.y) - - this.graph.snap(point.y)) <= tol) - { - geo.y = sourceState.y; - } - } - } - } - - return clone; -}; - -/** - * Function: getAlignmentTolerance - * - * Returns the tolerance for aligning new targets to sources. - */ -mxConnectionHandler.prototype.getAlignmentTolerance = function() -{ - return (this.graph.isGridEnabled()) ? - this.graph.gridSize : this.graph.tolerance; -}; - -/** - * Function: createEdge - * - * Creates and returns a new edge using <factoryMethod> if one exists. If - * no factory method is defined, then a new default edge is returned. The - * source and target arguments are informal, the actual connection is - * setup later by the caller of this function. - * - * Parameters: - * - * value - Value to be used for creating the edge. - * source - <mxCell> that represents the source terminal. - * target - <mxCell> that represents the target terminal. - * style - Optional style from the preview edge. - */ -mxConnectionHandler.prototype.createEdge = function(value, source, target, style) -{ - var edge = null; - - // Creates a new edge using the factoryMethod - if (this.factoryMethod != null) - { - edge = this.factoryMethod(source, target, style); - } - - if (edge == null) - { - edge = new mxCell(value || ''); - edge.setEdge(true); - edge.setStyle(style); - - var geo = new mxGeometry(); - geo.relative = true; - edge.setGeometry(geo); - } - - return edge; -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. This should be - * called on all instances. It is called automatically for the built-in - * instance created for each <mxGraph>. - */ -mxConnectionHandler.prototype.destroy = function() -{ - this.graph.removeMouseListener(this); - - if (this.shape != null) - { - this.shape.destroy(); - this.shape = null; - } - - if (this.marker != null) - { - this.marker.destroy(); - this.marker = null; - } - - if (this.constraintHandler != null) - { - this.constraintHandler.destroy(); - this.constraintHandler = null; - } - - if (this.changeHandler != null) - { - this.graph.getModel().removeListener(this.changeHandler); - this.graph.getView().removeListener(this.changeHandler); - this.changeHandler = null; - } - - if (this.drillHandler != null) - { - this.graph.removeListener(this.drillHandler); - this.graph.getView().removeListener(this.drillHandler); - this.drillHandler = null; - } -}; diff --git a/src/js/handler/mxConstraintHandler.js b/src/js/handler/mxConstraintHandler.js deleted file mode 100644 index 39b3ab6..0000000 --- a/src/js/handler/mxConstraintHandler.js +++ /dev/null @@ -1,308 +0,0 @@ -/** - * $Id: mxConstraintHandler.js,v 1.15 2012-11-01 16:13:41 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxConstraintHandler - * - * Handles constraints on connection targets. This class is in charge of - * showing fixed points when the mouse is over a vertex and handles constraints - * to establish new connections. - * - * Constructor: mxConstraintHandler - * - * Constructs an new constraint handler. - * - * Parameters: - * - * graph - Reference to the enclosing <mxGraph>. - * factoryMethod - Optional function to create the edge. The function takes - * the source and target <mxCell> as the first and second argument and - * returns the <mxCell> that represents the new edge. - */ -function mxConstraintHandler(graph) -{ - this.graph = graph; -}; - -/** - * Variable: pointImage - * - * <mxImage> to be used as the image for fixed connection points. - */ -mxConstraintHandler.prototype.pointImage = new mxImage(mxClient.imageBasePath + '/point.gif', 5, 5); - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxConstraintHandler.prototype.graph = null; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxConstraintHandler.prototype.enabled = true; - -/** - * Variable: highlightColor - * - * Specifies the color for the highlight. Default is <mxConstants.DEFAULT_VALID_COLOR>. - */ -mxConstraintHandler.prototype.highlightColor = mxConstants.DEFAULT_VALID_COLOR; - -/** - * Function: isEnabled - * - * Returns true if events are handled. This implementation - * returns <enabled>. - */ -mxConstraintHandler.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. - */ -mxConstraintHandler.prototype.setEnabled = function(enabled) -{ - this.enabled = enabled; -}; - -/** - * Function: reset - * - * Resets the state of this handler. - */ -mxConstraintHandler.prototype.reset = function() -{ - if (this.focusIcons != null) - { - for (var i = 0; i < this.focusIcons.length; i++) - { - this.focusIcons[i].destroy(); - } - - this.focusIcons = null; - } - - if (this.focusHighlight != null) - { - this.focusHighlight.destroy(); - this.focusHighlight = null; - } - - this.currentConstraint = null; - this.currentFocusArea = null; - this.currentPoint = null; - this.currentFocus = null; - this.focusPoints = null; -}; - -/** - * Function: getTolerance - * - * Returns the tolerance to be used for intersecting connection points. - */ -mxConstraintHandler.prototype.getTolerance = function() -{ - return this.graph.getTolerance(); -}; - -/** - * Function: getImageForConstraint - * - * Returns the tolerance to be used for intersecting connection points. - */ -mxConstraintHandler.prototype.getImageForConstraint = function(state, constraint, point) -{ - return this.pointImage; -}; - -/** - * Function: isEventIgnored - * - * Returns true if the given <mxMouseEvent> should be ignored in <update>. This - * implementation always returns false. - */ -mxConstraintHandler.prototype.isEventIgnored = function(me, source) -{ - return false; -}; - -/** - * Function: update - * - * Updates the state of this handler based on the given <mxMouseEvent>. - * Source is a boolean indicating if the cell is a source or target. - */ -mxConstraintHandler.prototype.update = function(me, source) -{ - if (this.isEnabled() && !this.isEventIgnored(me)) - { - var tol = this.getTolerance(); - var mouse = new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol); - var connectable = (me.getCell() != null) ? this.graph.isCellConnectable(me.getCell()) : false; - - if ((this.currentFocusArea == null || (!mxUtils.intersects(this.currentFocusArea, mouse) || - (me.getState() != null && this.currentFocus != null && connectable)))) - { - this.currentFocusArea = null; - - if (me.getState() != this.currentFocus) - { - this.currentFocus = null; - this.constraints = (me.getState() != null && connectable) ? - this.graph.getAllConnectionConstraints(me.getState(), source) : null; - - // Only uses cells which have constraints - if (this.constraints != null) - { - this.currentFocus = me.getState(); - this.currentFocusArea = new mxRectangle(me.getState().x, me.getState().y, me.getState().width, me.getState().height); - - if (this.focusIcons != null) - { - for (var i = 0; i < this.focusIcons.length; i++) - { - this.focusIcons[i].destroy(); - } - - this.focusIcons = null; - this.focusPoints = null; - } - - this.focusIcons = []; - this.focusPoints = []; - - for (var i = 0; i < this.constraints.length; i++) - { - var cp = this.graph.getConnectionPoint(me.getState(), this.constraints[i]); - var img = this.getImageForConstraint(me.getState(), this.constraints[i], cp); - - var src = img.src; - var bounds = new mxRectangle(cp.x - img.width / 2, - cp.y - img.height / 2, img.width, img.height); - var icon = new mxImageShape(bounds, src); - icon.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_SVG : - mxConstants.DIALECT_VML; - icon.init(this.graph.getView().getOverlayPane()); - - // Move the icon behind all other overlays - if (icon.node.previousSibling != null) - { - icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild); - } - - var getState = mxUtils.bind(this, function() - { - return (this.currentFocus != null) ? this.currentFocus : me.getState(); - }); - - icon.redraw(); - - mxEvent.redirectMouseEvents(icon.node, this.graph, getState); - this.currentFocusArea.add(icon.bounds); - this.focusIcons.push(icon); - this.focusPoints.push(cp); - } - - this.currentFocusArea.grow(tol); - } - else if (this.focusIcons != null) - { - if (this.focusHighlight != null) - { - this.focusHighlight.destroy(); - this.focusHighlight = null; - } - - for (var i = 0; i < this.focusIcons.length; i++) - { - this.focusIcons[i].destroy(); - } - - this.focusIcons = null; - this.focusPoints = null; - } - } - } - - this.currentConstraint = null; - this.currentPoint = null; - - if (this.focusIcons != null && this.constraints != null && - (me.getState() == null || this.currentFocus == me.getState())) - { - for (var i = 0; i < this.focusIcons.length; i++) - { - if (mxUtils.intersects(this.focusIcons[i].bounds, mouse)) - { - this.currentConstraint = this.constraints[i]; - this.currentPoint = this.focusPoints[i]; - - var tmp = this.focusIcons[i].bounds.clone(); - tmp.grow((mxClient.IS_IE) ? 3 : 2); - - if (mxClient.IS_IE) - { - tmp.width -= 1; - tmp.height -= 1; - } - - if (this.focusHighlight == null) - { - var hl = new mxRectangleShape(tmp, null, this.highlightColor, 3); - hl.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_SVG : - mxConstants.DIALECT_VML; - hl.init(this.graph.getView().getOverlayPane()); - this.focusHighlight = hl; - - var getState = mxUtils.bind(this, function() - { - return (this.currentFocus != null) ? this.currentFocus : me.getState(); - }); - - mxEvent.redirectMouseEvents(hl.node, this.graph, getState/*, mouseDown*/); - } - else - { - this.focusHighlight.bounds = tmp; - this.focusHighlight.redraw(); - } - - break; - } - } - } - - if (this.currentConstraint == null && - this.focusHighlight != null) - { - this.focusHighlight.destroy(); - this.focusHighlight = null; - } - } -}; - -/** - * Function: destroy - * - * Destroy this handler. - */ -mxConstraintHandler.prototype.destroy = function() -{ - this.reset(); -};
\ No newline at end of file diff --git a/src/js/handler/mxEdgeHandler.js b/src/js/handler/mxEdgeHandler.js deleted file mode 100644 index 2028342..0000000 --- a/src/js/handler/mxEdgeHandler.js +++ /dev/null @@ -1,1529 +0,0 @@ -/** - * $Id: mxEdgeHandler.js,v 1.178 2012-09-12 09:16:23 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxEdgeHandler - * - * Graph event handler that reconnects edges and modifies control points and - * the edge label location. Uses <mxTerminalMarker> for finding and - * highlighting new source and target vertices. This handler is automatically - * created in <mxGraph.createHandler> for each selected edge. - * - * To enable adding/removing control points, the following code can be used: - * - * (code) - * mxEdgeHandler.prototype.addEnabled = true; - * mxEdgeHandler.prototype.removeEnabled = true; - * (end) - * - * Note: This experimental feature is not recommended for production use. - * - * Constructor: mxEdgeHandler - * - * Constructs an edge handler for the specified <mxCellState>. - * - * Parameters: - * - * state - <mxCellState> of the cell to be handled. - */ -function mxEdgeHandler(state) -{ - if (state != null) - { - this.state = state; - this.init(); - } -}; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxEdgeHandler.prototype.graph = null; - -/** - * Variable: state - * - * Reference to the <mxCellState> being modified. - */ -mxEdgeHandler.prototype.state = null; - -/** - * Variable: marker - * - * Holds the <mxTerminalMarker> which is used for highlighting terminals. - */ -mxEdgeHandler.prototype.marker = null; - -/** - * Variable: constraintHandler - * - * Holds the <mxConstraintHandler> used for drawing and highlighting - * constraints. - */ -mxEdgeHandler.prototype.constraintHandler = null; - -/** - * Variable: error - * - * Holds the current validation error while a connection is being changed. - */ -mxEdgeHandler.prototype.error = null; - -/** - * Variable: shape - * - * Holds the <mxShape> that represents the preview edge. - */ -mxEdgeHandler.prototype.shape = null; - -/** - * Variable: bends - * - * Holds the <mxShapes> that represent the points. - */ -mxEdgeHandler.prototype.bends = null; - -/** - * Variable: labelShape - * - * Holds the <mxShape> that represents the label position. - */ -mxEdgeHandler.prototype.labelShape = null; - -/** - * Variable: cloneEnabled - * - * Specifies if cloning by control-drag is enabled. Default is true. - */ -mxEdgeHandler.prototype.cloneEnabled = true; - -/** - * Variable: addEnabled - * - * Specifies if adding bends by shift-click is enabled. Default is false. - * Note: This experimental feature is not recommended for production use. - */ -mxEdgeHandler.prototype.addEnabled = false; - -/** - * Variable: removeEnabled - * - * Specifies if removing bends by shift-click is enabled. Default is false. - * Note: This experimental feature is not recommended for production use. - */ -mxEdgeHandler.prototype.removeEnabled = false; - -/** - * Variable: preferHtml - * - * Specifies if bends should be added to the graph container. This is updated - * in <init> based on whether the edge or one of its terminals has an HTML - * label in the container. - */ -mxEdgeHandler.prototype.preferHtml = false; - -/** - * Variable: allowHandleBoundsCheck - * - * Specifies if the bounds of handles should be used for hit-detection in IE - * Default is true. - */ -mxEdgeHandler.prototype.allowHandleBoundsCheck = true; - -/** - * Variable: snapToTerminals - * - * Specifies if waypoints should snap to the routing centers of terminals. - * Default is false. - */ -mxEdgeHandler.prototype.snapToTerminals = false; - -/** - * Variable: crisp - * - * Specifies if the edge handles should be rendered in crisp mode. Default is - * true. - */ -mxEdgeHandler.prototype.crisp = true; - -/** - * Variable: handleImage - * - * Optional <mxImage> to be used as handles. Default is null. - */ -mxEdgeHandler.prototype.handleImage = null; - -/** - * Variable: tolerance - * - * Optional tolerance for hit-detection in <getHandleForEvent>. Default is 0. - */ -mxEdgeHandler.prototype.tolerance = 0; - -/** - * Function: init - * - * Initializes the shapes required for this edge handler. - */ -mxEdgeHandler.prototype.init = function() -{ - this.graph = this.state.view.graph; - this.marker = this.createMarker(); - this.constraintHandler = new mxConstraintHandler(this.graph); - - // Clones the original points from the cell - // and makes sure at least one point exists - this.points = []; - - // Uses the absolute points of the state - // for the initial configuration and preview - this.abspoints = this.getSelectionPoints(this.state); - this.shape = this.createSelectionShape(this.abspoints); - this.shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - this.shape.init(this.graph.getView().getOverlayPane()); - this.shape.node.style.cursor = mxConstants.CURSOR_MOVABLE_EDGE; - - // Event handling - var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown'; - var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove'; - var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup'; - - mxEvent.addListener(this.shape.node, 'dblclick', - mxUtils.bind(this, function(evt) - { - this.graph.dblClick(evt, this.state.cell); - }) - ); - mxEvent.addListener(this.shape.node, md, - mxUtils.bind(this, function(evt) - { - if (this.addEnabled && this.isAddPointEvent(evt)) - { - this.addPoint(this.state, evt); - } - else - { - this.graph.fireMouseEvent(mxEvent.MOUSE_DOWN, - new mxMouseEvent(evt, this.state)); - } - }) - ); - mxEvent.addListener(this.shape.node, mm, - mxUtils.bind(this, function(evt) - { - var cell = this.state.cell; - - // Finds the cell under the mouse if the edge is being connected - // in which case the edge is never highlighted as it cannot - // be its own source or target terminal (transparent preview) - if (this.index != null) - { - var pt = mxUtils.convertPoint(this.graph.container, - mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - cell = this.graph.getCellAt(pt.x, pt.y); - - // Swimlane content area is transparent in this case - if (this.graph.isSwimlane(cell) && this.graph.hitsSwimlaneContent(cell, pt.x, pt.y)) - { - cell = null; - } - } - - this.graph.fireMouseEvent(mxEvent.MOUSE_MOVE, - new mxMouseEvent(evt, this.graph.getView().getState(cell))); - }) - ); - mxEvent.addListener(this.shape.node, mu, - mxUtils.bind(this, function(evt) - { - this.graph.fireMouseEvent(mxEvent.MOUSE_UP, - new mxMouseEvent(evt, this.state)); - }) - ); - - // Updates preferHtml - this.preferHtml = this.state.text != null && - this.state.text.node.parentNode == this.graph.container; - - if (!this.preferHtml) - { - // Checks source terminal - var sourceState = this.state.getVisibleTerminalState(true); - - if (sourceState != null) - { - this.preferHtml = sourceState.text != null && - sourceState.text.node.parentNode == this.graph.container; - } - - if (!this.preferHtml) - { - // Checks target terminal - var targetState = this.state.getVisibleTerminalState(false); - - if (targetState != null) - { - this.preferHtml = targetState.text != null && - targetState.text.node.parentNode == this.graph.container; - } - } - } - - // Creates bends for the non-routed absolute points - // or bends that don't correspond to points - if (this.graph.getSelectionCount() < mxGraphHandler.prototype.maxCells || - mxGraphHandler.prototype.maxCells <= 0) - { - this.bends = this.createBends(); - } - - // Adds a rectangular handle for the label position - this.label = new mxPoint(this.state.absoluteOffset.x, this.state.absoluteOffset.y); - this.labelShape = new mxRectangleShape(new mxRectangle(), - mxConstants.LABEL_HANDLE_FILLCOLOR, - mxConstants.HANDLE_STROKECOLOR); - this.initBend(this.labelShape); - this.labelShape.node.style.cursor = mxConstants.CURSOR_LABEL_HANDLE; - mxEvent.redirectMouseEvents(this.labelShape.node, this.graph, this.state); - - this.redraw(); -}; - -/** - * Function: isAddPointEvent - * - * Returns true if the given event is a trigger to add a new point. This - * implementation returns true if shift is pressed. - */ -mxEdgeHandler.prototype.isAddPointEvent = function(evt) -{ - return mxEvent.isShiftDown(evt); -}; - -/** - * Function: isRemovePointEvent - * - * Returns true if the given event is a trigger to remove a point. This - * implementation returns true if shift is pressed. - */ -mxEdgeHandler.prototype.isRemovePointEvent = function(evt) -{ - return mxEvent.isShiftDown(evt); -}; - -/** - * Function: getSelectionPoints - * - * Returns the list of points that defines the selection stroke. - */ -mxEdgeHandler.prototype.getSelectionPoints = function(state) -{ - return state.absolutePoints; -}; - -/** - * Function: createSelectionShape - * - * Creates the shape used to draw the selection border. - */ -mxEdgeHandler.prototype.createSelectionShape = function(points) -{ - var shape = new mxPolyline(points, this.getSelectionColor()); - shape.strokewidth = this.getSelectionStrokeWidth(); - shape.isDashed = this.isSelectionDashed(); - - return shape; -}; - -/** - * Function: getSelectionColor - * - * Returns <mxConstants.EDGE_SELECTION_COLOR>. - */ -mxEdgeHandler.prototype.getSelectionColor = function() -{ - return mxConstants.EDGE_SELECTION_COLOR; -}; - -/** - * Function: getSelectionStrokeWidth - * - * Returns <mxConstants.EDGE_SELECTION_STROKEWIDTH>. - */ -mxEdgeHandler.prototype.getSelectionStrokeWidth = function() -{ - return mxConstants.EDGE_SELECTION_STROKEWIDTH; -}; - -/** - * Function: isSelectionDashed - * - * Returns <mxConstants.EDGE_SELECTION_DASHED>. - */ -mxEdgeHandler.prototype.isSelectionDashed = function() -{ - return mxConstants.EDGE_SELECTION_DASHED; -}; - -/** - * Function: isConnectableCell - * - * Returns true if the given cell is connectable. This is a hook to - * disable floating connections. This implementation returns true. - */ -mxEdgeHandler.prototype.isConnectableCell = function(cell) -{ - return true; -}; - -/** - * Function: createMarker - * - * Creates and returns the <mxCellMarker> used in <marker>. - */ -mxEdgeHandler.prototype.createMarker = function() -{ - var marker = new mxCellMarker(this.graph); - var self = this; // closure - - // Only returns edges if they are connectable and never returns - // the edge that is currently being modified - marker.getCell = function(me) - { - var cell = mxCellMarker.prototype.getCell.apply(this, arguments); - - if (!self.isConnectableCell(cell)) - { - return null; - } - - var model = self.graph.getModel(); - - if (cell == self.state.cell || (cell != null && - !self.graph.connectableEdges && model.isEdge(cell))) - { - cell = null; - } - - return cell; - }; - - // Sets the highlight color according to validateConnection - marker.isValidState = function(state) - { - var model = self.graph.getModel(); - var other = self.graph.view.getTerminalPort(state, - self.graph.view.getState(model.getTerminal(self.state.cell, - !self.isSource)), !self.isSource); - var otherCell = (other != null) ? other.cell : null; - var source = (self.isSource) ? state.cell : otherCell; - var target = (self.isSource) ? otherCell : state.cell; - - // Updates the error message of the handler - self.error = self.validateConnection(source, target); - - return self.error == null; - }; - - return marker; -}; - -/** - * Function: validateConnection - * - * Returns the error message or an empty string if the connection for the - * given source, target pair is not valid. Otherwise it returns null. This - * implementation uses <mxGraph.getEdgeValidationError>. - * - * Parameters: - * - * source - <mxCell> that represents the source terminal. - * target - <mxCell> that represents the target terminal. - */ -mxEdgeHandler.prototype.validateConnection = function(source, target) -{ - return this.graph.getEdgeValidationError(this.state.cell, source, target); -}; - -/** - * Function: createBends - * - * Creates and returns the bends used for modifying the edge. This is - * typically an array of <mxRectangleShapes>. - */ - mxEdgeHandler.prototype.createBends = function() - { - var cell = this.state.cell; - var bends = []; - - for (var i = 0; i < this.abspoints.length; i++) - { - if (this.isHandleVisible(i)) - { - var source = i == 0; - var target = i == this.abspoints.length - 1; - var terminal = source || target; - - if (terminal || this.graph.isCellBendable(cell)) - { - var bend = this.createHandleShape(i); - this.initBend(bend); - - if (mxClient.IS_TOUCH) - { - bend.node.setAttribute('pointer-events', 'none'); - } - - if (this.isHandleEnabled(i)) - { - if (mxClient.IS_TOUCH) - { - var getState = mxUtils.bind(this, function(evt) - { - var pt = mxUtils.convertPoint(this.graph.container, mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - - return this.graph.view.getState(this.graph.getCellAt(pt.x, pt.y)); - }); - - mxEvent.redirectMouseEvents(bend.node, this.graph, getState); - } - else - { - bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE; - mxEvent.redirectMouseEvents(bend.node, this.graph, this.state); - } - } - - bends.push(bend); - - if (!terminal) - { - this.points.push(new mxPoint(0,0)); - bend.node.style.visibility = 'hidden'; - } - } - } - } - - return bends; -}; -/** - * Function: isHandleEnabled - * - * Creates the shape used to display the given bend. - */ -mxEdgeHandler.prototype.isHandleEnabled = function(index) -{ - return true; -}; - -/** - * Function: isHandleVisible - * - * Returns true if the handle at the given index is visible. - */ -mxEdgeHandler.prototype.isHandleVisible = function(index) -{ - return true; -}; - -/** - * Function: createHandleShape - * - * Creates the shape used to display the given bend. Note that the index may be - * null for special cases, such as when called from - * <mxElbowEdgeHandler.createVirtualBend>. - */ -mxEdgeHandler.prototype.createHandleShape = function(index) -{ - if (this.handleImage != null) - { - return new mxImageShape(new mxRectangle(0, 0, this.handleImage.width, this.handleImage.height), this.handleImage.src); - } - else - { - var s = mxConstants.HANDLE_SIZE; - - if (this.preferHtml) - { - s -= 1; - } - - return new mxRectangleShape(new mxRectangle(0, 0, s, s), mxConstants.HANDLE_FILLCOLOR, mxConstants.HANDLE_STROKECOLOR); - } -}; - -/** - * Function: initBend - * - * Helper method to initialize the given bend. - * - * Parameters: - * - * bend - <mxShape> that represents the bend to be initialized. - */ -mxEdgeHandler.prototype.initBend = function(bend) -{ - bend.crisp = this.crisp; - - if (this.preferHtml) - { - bend.dialect = mxConstants.DIALECT_STRICTHTML; - bend.init(this.graph.container); - } - else - { - bend.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - bend.init(this.graph.getView().getOverlayPane()); - } -}; - -/** - * Function: getHandleForEvent - * - * Returns the index of the handle for the given event. - */ -mxEdgeHandler.prototype.getHandleForEvent = function(me) -{ - // Finds the handle that triggered the event - if (this.bends != null) - { - // Connection highlight may consume events before they reach sizer handle - var tol = this.tolerance; - var hit = (this.allowHandleBoundsCheck && (mxClient.IS_IE || tol > 0)) ? - new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol) : null; - - for (var i = 0; i < this.bends.length; i++) - { - if (me.isSource(this.bends[i]) || (hit != null && - this.bends[i].node.style.visibility != 'hidden' && - mxUtils.intersects(this.bends[i].bounds, hit))) - { - return i; - } - } - } - - if (me.isSource(this.labelShape) || me.isSource(this.state.text)) - { - // Workaround for SELECT element not working in Webkit - if ((!mxClient.IS_SF && !mxClient.IS_GC) || me.getSource().nodeName != 'SELECT') - { - return mxEvent.LABEL_HANDLE; - } - } - - return null; -}; - -/** - * Function: mouseDown - * - * Handles the event by checking if a special element of the handler - * was clicked, in which case the index parameter is non-null. The - * indices may be one of <LABEL_HANDLE> or the number of the respective - * control point. The source and target points are used for reconnecting - * the edge. - */ -mxEdgeHandler.prototype.mouseDown = function(sender, me) -{ - var handle = null; - - // Handles the case where the state in the event points to another - // cell if the cell has a HTML label which sits on top of the handles - // NOTE: Commented out. This should not be required as all HTML labels - // are in order an do not appear behind the handles. - //if (mxClient.IS_SVG || me.getState() == this.state) - { - handle = this.getHandleForEvent(me); - } - - if (handle != null && !me.isConsumed() && this.graph.isEnabled() && - !this.graph.isForceMarqueeEvent(me.getEvent())) - { - if (this.removeEnabled && this.isRemovePointEvent(me.getEvent())) - { - this.removePoint(this.state, handle); - } - else if (handle != mxEvent.LABEL_HANDLE || this.graph.isLabelMovable(me.getCell())) - { - this.start(me.getX(), me.getY(), handle); - } - - me.consume(); - } -}; - -/** - * Function: start - * - * Starts the handling of the mouse gesture. - */ -mxEdgeHandler.prototype.start = function(x, y, index) -{ - this.startX = x; - this.startY = y; - - this.isSource = (this.bends == null) ? false : index == 0; - this.isTarget = (this.bends == null) ? false : index == this.bends.length - 1; - this.isLabel = index == mxEvent.LABEL_HANDLE; - - if (this.isSource || this.isTarget) - { - var cell = this.state.cell; - var terminal = this.graph.model.getTerminal(cell, this.isSource); - - if ((terminal == null && this.graph.isTerminalPointMovable(cell, this.isSource)) || - (terminal != null && this.graph.isCellDisconnectable(cell, terminal, this.isSource))) - { - this.index = index; - } - } - else - { - this.index = index; - } -}; - -/** - * Function: clonePreviewState - * - * Returns a clone of the current preview state for the given point and terminal. - */ -mxEdgeHandler.prototype.clonePreviewState = function(point, terminal) -{ - return this.state.clone(); -}; - -/** - * Function: getSnapToTerminalTolerance - * - * Returns the tolerance for the guides. Default value is - * gridSize * scale / 2. - */ -mxEdgeHandler.prototype.getSnapToTerminalTolerance = function() -{ - return this.graph.gridSize * this.graph.view.scale / 2; -}; - -/** - * Function: getPointForEvent - * - * Returns the point for the given event. - */ -mxEdgeHandler.prototype.getPointForEvent = function(me) -{ - var point = new mxPoint(me.getGraphX(), me.getGraphY()); - - var tt = this.getSnapToTerminalTolerance(); - var view = this.graph.getView(); - var overrideX = false; - var overrideY = false; - - if (this.snapToTerminals && tt > 0) - { - function snapToPoint(pt) - { - if (pt != null) - { - var x = pt.x; - - if (Math.abs(point.x - x) < tt) - { - point.x = x; - overrideX = true; - } - - var y = pt.y; - - if (Math.abs(point.y - y) < tt) - { - point.y = y; - overrideY = true; - } - } - } - - // Temporary function - function snapToTerminal(terminal) - { - if (terminal != null) - { - snapToPoint.call(this, new mxPoint(view.getRoutingCenterX(terminal), - view.getRoutingCenterY(terminal))); - } - }; - - snapToTerminal.call(this, this.state.getVisibleTerminalState(true)); - snapToTerminal.call(this, this.state.getVisibleTerminalState(false)); - - if (this.abspoints != null) - { - for (var i = 0; i < this.abspoints; i++) - { - if (i != this.index) - { - snapToPoint.call(this, this.abspoints[i]); - } - } - } - } - - if (this.graph.isGridEnabledEvent(me.getEvent())) - { - var scale = view.scale; - var tr = view.translate; - - if (!overrideX) - { - point.x = (this.graph.snap(point.x / scale - tr.x) + tr.x) * scale; - } - - if (!overrideY) - { - point.y = (this.graph.snap(point.y / scale - tr.y) + tr.y) * scale; - } - } - - return point; -}; - -/** - * Function: getPreviewTerminalState - * - * Updates the given preview state taking into account the state of the constraint handler. - */ -mxEdgeHandler.prototype.getPreviewTerminalState = function(me) -{ - this.constraintHandler.update(me, this.isSource); - this.marker.process(me); - var currentState = this.marker.getValidState(); - var result = null; - - if (this.constraintHandler.currentFocus != null && - this.constraintHandler.currentConstraint != null) - { - this.marker.reset(); - } - - if (currentState != null) - { - result = currentState; - } - else if (this.constraintHandler.currentConstraint != null && - this.constraintHandler.currentFocus != null) - { - result = this.constraintHandler.currentFocus; - } - - return result; -}; - -/** - * Function: getPreviewPoints - * - * Updates the given preview state taking into account the state of the constraint handler. - */ -mxEdgeHandler.prototype.getPreviewPoints = function(point) -{ - var geometry = this.graph.getCellGeometry(this.state.cell); - var points = (geometry.points != null) ? geometry.points.slice() : null; - - if (!this.isSource && !this.isTarget) - { - this.convertPoint(point, false); - - if (points == null) - { - points = [point]; - } - else - { - points[this.index - 1] = point; - } - } - else if (this.graph.resetEdgesOnConnect) - { - points = null; - } - - return points; -}; - -/** - * Function: updatePreviewState - * - * Updates the given preview state taking into account the state of the constraint handler. - */ -mxEdgeHandler.prototype.updatePreviewState = function(edge, point, terminalState) -{ - // Computes the points for the edge style and terminals - var sourceState = (this.isSource) ? terminalState : this.state.getVisibleTerminalState(true); - var targetState = (this.isTarget) ? terminalState : this.state.getVisibleTerminalState(false); - - var sourceConstraint = this.graph.getConnectionConstraint(edge, sourceState, true); - var targetConstraint = this.graph.getConnectionConstraint(edge, targetState, false); - - var constraint = this.constraintHandler.currentConstraint; - - if (constraint == null) - { - constraint = new mxConnectionConstraint(); - } - - if (this.isSource) - { - sourceConstraint = constraint; - } - else if (this.isTarget) - { - targetConstraint = constraint; - } - - if (!this.isSource || sourceState != null) - { - edge.view.updateFixedTerminalPoint(edge, sourceState, true, sourceConstraint); - } - - if (!this.isTarget || targetState != null) - { - edge.view.updateFixedTerminalPoint(edge, targetState, false, targetConstraint); - } - - if ((this.isSource || this.isTarget) && terminalState == null) - { - edge.setAbsoluteTerminalPoint(point, this.isSource); - - if (this.marker.getMarkedState() == null) - { - this.error = (this.graph.allowDanglingEdges) ? null : ''; - } - } - - edge.view.updatePoints(edge, this.points, sourceState, targetState); - edge.view.updateFloatingTerminalPoints(edge, sourceState, targetState); -}; - -/** - * Function: mouseMove - * - * Handles the event by updating the preview. - */ -mxEdgeHandler.prototype.mouseMove = function(sender, me) -{ - if (this.index != null && this.marker != null) - { - var point = this.getPointForEvent(me); - - if (this.isLabel) - { - this.label.x = point.x; - this.label.y = point.y; - } - else - { - this.points = this.getPreviewPoints(point); - var terminalState = (this.isSource || this.isTarget) ? this.getPreviewTerminalState(me) : null; - var clone = this.clonePreviewState(point, (terminalState != null) ? terminalState.cell : null); - this.updatePreviewState(clone, point, terminalState); - - // Sets the color of the preview to valid or invalid, updates the - // points of the preview and redraws - var color = (this.error == null) ? this.marker.validColor : - this.marker.invalidColor; - this.setPreviewColor(color); - this.abspoints = clone.absolutePoints; - this.active = true; - } - - this.drawPreview(); - mxEvent.consume(me.getEvent()); - me.consume(); - } - // Workaround for disabling the connect highlight when over handle - else if (mxClient.IS_IE && this.getHandleForEvent(me) != null) - { - me.consume(false); - } -}; - -/** - * Function: mouseUp - * - * Handles the event to applying the previewed changes on the edge by - * using <moveLabel>, <connect> or <changePoints>. - */ -mxEdgeHandler.prototype.mouseUp = function(sender, me) -{ - if (this.index != null && this.marker != null) - { - var edge = this.state.cell; - - // Ignores event if mouse has not been moved - if (me.getX() != this.startX || me.getY() != this.startY) - { - // Displays the reason for not carriying out the change - // if there is an error message with non-zero length - if (this.error != null) - { - if (this.error.length > 0) - { - this.graph.validationAlert(this.error); - } - } - else if (this.isLabel) - { - this.moveLabel(this.state, this.label.x, this.label.y); - } - else if (this.isSource || this.isTarget) - { - var terminal = null; - - if (this.constraintHandler.currentConstraint != null && - this.constraintHandler.currentFocus != null) - { - terminal = this.constraintHandler.currentFocus.cell; - } - - if (terminal == null && this.marker.hasValidState()) - { - terminal = this.marker.validState.cell; - } - - if (terminal != null) - { - edge = this.connect(edge, terminal, this.isSource, - this.graph.isCloneEvent(me.getEvent()) && this.cloneEnabled && - this.graph.isCellsCloneable(), me); - } - else if (this.graph.isAllowDanglingEdges()) - { - var pt = this.abspoints[(this.isSource) ? 0 : this.abspoints.length - 1]; - pt.x = pt.x / this.graph.view.scale - this.graph.view.translate.x; - pt.y = pt.y / this.graph.view.scale - this.graph.view.translate.y; - - var pstate = this.graph.getView().getState( - this.graph.getModel().getParent(edge)); - - if (pstate != null) - { - pt.x -= pstate.origin.x; - pt.y -= pstate.origin.y; - } - - pt.x -= this.graph.panDx / this.graph.view.scale; - pt.y -= this.graph.panDy / this.graph.view.scale; - - // Destroys and rectreates this handler - this.changeTerminalPoint(edge, pt, this.isSource); - } - } - else if (this.active) - { - this.changePoints(edge, this.points); - } - else - { - this.graph.getView().invalidate(this.state.cell); - this.graph.getView().revalidate(this.state.cell); - } - } - - // Resets the preview color the state of the handler if this - // handler has not been recreated - if (this.marker != null) - { - this.reset(); - - // Updates the selection if the edge has been cloned - if (edge != this.state.cell) - { - this.graph.setSelectionCell(edge); - } - } - - me.consume(); - } -}; - -/** - * Function: reset - * - * Resets the state of this handler. - */ -mxEdgeHandler.prototype.reset = function() -{ - this.error = null; - this.index = null; - this.label = null; - this.points = null; - this.active = false; - this.isLabel = false; - this.isSource = false; - this.isTarget = false; - this.marker.reset(); - this.constraintHandler.reset(); - this.setPreviewColor(mxConstants.EDGE_SELECTION_COLOR); - this.redraw(); -}; - -/** - * Function: setPreviewColor - * - * Sets the color of the preview to the given value. - */ -mxEdgeHandler.prototype.setPreviewColor = function(color) -{ - if (this.shape != null && this.shape.node != null) - { - if (this.shape.dialect == mxConstants.DIALECT_SVG) - { - this.shape.innerNode.setAttribute('stroke', color); - } - else - { - this.shape.node.strokecolor = color; - } - } -}; - -/** - * Function: convertPoint - * - * Converts the given point in-place from screen to unscaled, untranslated - * graph coordinates and applies the grid. Returns the given, modified - * point instance. - * - * Parameters: - * - * point - <mxPoint> to be converted. - * gridEnabled - Boolean that specifies if the grid should be applied. - */ -mxEdgeHandler.prototype.convertPoint = function(point, gridEnabled) -{ - var scale = this.graph.getView().getScale(); - var tr = this.graph.getView().getTranslate(); - - if (gridEnabled) - { - point.x = this.graph.snap(point.x); - point.y = this.graph.snap(point.y); - } - - point.x = Math.round(point.x / scale - tr.x); - point.y = Math.round(point.y / scale - tr.y); - - var pstate = this.graph.getView().getState( - this.graph.getModel().getParent(this.state.cell)); - - if (pstate != null) - { - point.x -= pstate.origin.x; - point.y -= pstate.origin.y; - } - - return point; -}; - -/** - * Function: moveLabel - * - * Changes the coordinates for the label of the given edge. - * - * Parameters: - * - * edge - <mxCell> that represents the edge. - * x - Integer that specifies the x-coordinate of the new location. - * y - Integer that specifies the y-coordinate of the new location. - */ -mxEdgeHandler.prototype.moveLabel = function(edgeState, x, y) -{ - var model = this.graph.getModel(); - var geometry = model.getGeometry(edgeState.cell); - - if (geometry != null) - { - geometry = geometry.clone(); - - // Resets the relative location stored inside the geometry - var pt = this.graph.getView().getRelativePoint(edgeState, x, y); - geometry.x = pt.x; - geometry.y = pt.y; - - // Resets the offset inside the geometry to find the offset - // from the resulting point - var scale = this.graph.getView().scale; - geometry.offset = new mxPoint(0, 0); - var pt = this.graph.view.getPoint(edgeState, geometry); - geometry.offset = new mxPoint((x - pt.x) / scale, (y - pt.y) / scale); - - model.setGeometry(edgeState.cell, geometry); - } -}; - -/** - * Function: connect - * - * Changes the terminal or terminal point of the given edge in the graph - * model. - * - * Parameters: - * - * edge - <mxCell> that represents the edge to be reconnected. - * terminal - <mxCell> that represents the new terminal. - * isSource - Boolean indicating if the new terminal is the source or - * target terminal. - * isClone - Boolean indicating if the new connection should be a clone of - * the old edge. - * me - <mxMouseEvent> that contains the mouse up event. - */ -mxEdgeHandler.prototype.connect = function(edge, terminal, isSource, isClone, me) -{ - var model = this.graph.getModel(); - var parent = model.getParent(edge); - - model.beginUpdate(); - try - { - // Clones and adds the cell - if (isClone) - { - var clone = edge.clone(); - model.add(parent, clone, model.getChildCount(parent)); - - var other = model.getTerminal(edge, !isSource); - this.graph.connectCell(clone, other, !isSource); - - edge = clone; - } - - var constraint = this.constraintHandler.currentConstraint; - - if (constraint == null) - { - constraint = new mxConnectionConstraint(); - } - - this.graph.connectCell(edge, terminal, isSource, constraint); - } - finally - { - model.endUpdate(); - } - - return edge; -}; - -/** - * Function: changeTerminalPoint - * - * Changes the terminal point of the given edge. - */ -mxEdgeHandler.prototype.changeTerminalPoint = function(edge, point, isSource) -{ - var model = this.graph.getModel(); - var geo = model.getGeometry(edge); - - if (geo != null) - { - model.beginUpdate(); - try - { - geo = geo.clone(); - geo.setTerminalPoint(point, isSource); - model.setGeometry(edge, geo); - this.graph.connectCell(edge, null, isSource, new mxConnectionConstraint()); - } - finally - { - model.endUpdate(); - } - } -}; - -/** - * Function: changePoints - * - * Changes the control points of the given edge in the graph model. - */ -mxEdgeHandler.prototype.changePoints = function(edge, points) -{ - var model = this.graph.getModel(); - var geo = model.getGeometry(edge); - - if (geo != null) - { - geo = geo.clone(); - geo.points = points; - - model.setGeometry(edge, geo); - } -}; - -/** - * Function: addPoint - * - * Adds a control point for the given state and event. - */ -mxEdgeHandler.prototype.addPoint = function(state, evt) -{ - var geo = this.graph.getCellGeometry(state.cell); - - if (geo != null) - { - geo = geo.clone(); - var pt = mxUtils.convertPoint(this.graph.container, mxEvent.getClientX(evt), - mxEvent.getClientY(evt)); - var index = mxUtils.findNearestSegment(state, pt.x, pt.y); - var gridEnabled = this.graph.isGridEnabledEvent(evt); - this.convertPoint(pt, gridEnabled); - - if (geo.points == null) - { - geo.points = [pt]; - } - else - { - geo.points.splice(index, 0, pt); - } - - this.graph.getModel().setGeometry(state.cell, geo); - this.destroy(); - this.init(); - mxEvent.consume(evt); - } -}; - -/** - * Function: removePoint - * - * Removes the control point at the given index from the given state. - */ -mxEdgeHandler.prototype.removePoint = function(state, index) -{ - if (index > 0 && index < this.abspoints.length - 1) - { - var geo = this.graph.getCellGeometry(this.state.cell); - - if (geo != null && - geo.points != null) - { - geo = geo.clone(); - geo.points.splice(index - 1, 1); - this.graph.getModel().setGeometry(state.cell, geo); - this.destroy(); - this.init(); - } - } -}; - -/** - * Function: getHandleFillColor - * - * Returns the fillcolor for the handle at the given index. - */ -mxEdgeHandler.prototype.getHandleFillColor = function(index) -{ - var isSource = index == 0; - var cell = this.state.cell; - var terminal = this.graph.getModel().getTerminal(cell, isSource); - var color = mxConstants.HANDLE_FILLCOLOR; - - if ((terminal != null && !this.graph.isCellDisconnectable(cell, terminal, isSource)) || - (terminal == null && !this.graph.isTerminalPointMovable(cell, isSource))) - { - color = mxConstants.LOCKED_HANDLE_FILLCOLOR; - } - else if (terminal != null && this.graph.isCellDisconnectable(cell, terminal, isSource)) - { - color = mxConstants.CONNECT_HANDLE_FILLCOLOR; - } - - return color; -}; - -/** - * Function: redraw - * - * Redraws the preview, and the bends- and label control points. - */ -mxEdgeHandler.prototype.redraw = function() -{ - this.abspoints = this.state.absolutePoints.slice(); - var cell = this.state.cell; - - // Updates the handle for the label position - var s = mxConstants.LABEL_HANDLE_SIZE; - - this.label = new mxPoint(this.state.absoluteOffset.x, this.state.absoluteOffset.y); - this.labelShape.bounds = new mxRectangle(this.label.x - s / 2, - this.label.y - s / 2, s, s); - this.labelShape.redraw(); - - // Shows or hides the label handle depending on the label - var lab = this.graph.getLabel(cell); - - if (lab != null && lab.length > 0 && this.graph.isLabelMovable(cell)) - { - this.labelShape.node.style.visibility = 'visible'; - } - else - { - this.labelShape.node.style.visibility = 'hidden'; - } - - if (this.bends != null && this.bends.length > 0) - { - var n = this.abspoints.length - 1; - - var p0 = this.abspoints[0]; - var x0 = this.abspoints[0].x; - var y0 = this.abspoints[0].y; - - var b = this.bends[0].bounds; - this.bends[0].bounds = new mxRectangle(x0 - b.width / 2, y0 - b.height / 2, b.width, b.height); - this.bends[0].fill = this.getHandleFillColor(0); - this.bends[0].reconfigure(); - this.bends[0].redraw(); - - var pe = this.abspoints[n]; - var xn = this.abspoints[n].x; - var yn = this.abspoints[n].y; - - var bn = this.bends.length - 1; - b = this.bends[bn].bounds; - this.bends[bn].bounds = new mxRectangle(xn - b.width / 2, yn - b.height / 2, b.width, b.height); - this.bends[bn].fill = this.getHandleFillColor(bn); - this.bends[bn].reconfigure(); - this.bends[bn].redraw(); - - this.redrawInnerBends(p0, pe); - } - - this.drawPreview(); -}; - -/** - * Function: redrawInnerBends - * - * Updates and redraws the inner bends. - * - * Parameters: - * - * p0 - <mxPoint> that represents the location of the first point. - * pe - <mxPoint> that represents the location of the last point. - */ -mxEdgeHandler.prototype.redrawInnerBends = function(p0, pe) -{ - var g = this.graph.getModel().getGeometry(this.state.cell); - var pts = g.points; - - if (pts != null) - { - if (this.points == null) - { - this.points = []; - } - - for (var i = 1; i < this.bends.length-1; i++) - { - if (this.bends[i] != null) - { - if (this.abspoints[i] != null) - { - var x = this.abspoints[i].x; - var y = this.abspoints[i].y; - - var b = this.bends[i].bounds; - this.bends[i].node.style.visibility = 'visible'; - this.bends[i].bounds = new mxRectangle(x - b.width / 2, y - b.height / 2, b.width, b.height); - this.bends[i].redraw(); - - this.points[i - 1] = pts[i - 1]; - } - else - { - this.bends[i].destroy(); - this.bends[i] = null; - } - } - } - } -}; - -/** - * Function: drawPreview - * - * Redraws the preview. - */ -mxEdgeHandler.prototype.drawPreview = function() -{ - if (this.isLabel) - { - var s = mxConstants.LABEL_HANDLE_SIZE; - - var bounds = new mxRectangle(this.label.x - s / 2, this.label.y - s / 2, s, s); - this.labelShape.bounds = bounds; - this.labelShape.redraw(); - } - else - { - this.shape.points = this.abspoints; - this.shape.redraw(); - } - - // Workaround to force a repaint in AppleWebKit - mxUtils.repaintGraph(this.graph, this.shape.points[this.shape.points.length - 1]); -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. This does - * normally not need to be called as handlers are destroyed automatically - * when the corresponding cell is deselected. - */ -mxEdgeHandler.prototype.destroy = function() -{ - if (this.marker != null) - { - this.marker.destroy(); - this.marker = null; - } - - if (this.shape != null) - { - this.shape.destroy(); - this.shape = null; - } - - if (this.labelShape != null) - { - this.labelShape.destroy(); - this.labelShape = null; - } - - if (this.constraintHandler != null) - { - this.constraintHandler.destroy(); - this.constraintHandler = null; - } - - // Destroy the control points for the bends - if (this.bends != null) - { - for (var i = 0; i < this.bends.length; i++) - { - if (this.bends[i] != null) - { - this.bends[i].destroy(); - this.bends[i] = null; - } - } - } -}; diff --git a/src/js/handler/mxEdgeSegmentHandler.js b/src/js/handler/mxEdgeSegmentHandler.js deleted file mode 100644 index e14fde0..0000000 --- a/src/js/handler/mxEdgeSegmentHandler.js +++ /dev/null @@ -1,284 +0,0 @@ -/** - * $Id: mxEdgeSegmentHandler.js,v 1.14 2012-12-17 13:22:49 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -function mxEdgeSegmentHandler(state) -{ - if (state != null) - { - this.state = state; - this.init(); - } -}; - -/** - * Extends mxEdgeHandler. - */ -mxEdgeSegmentHandler.prototype = new mxElbowEdgeHandler(); -mxEdgeSegmentHandler.prototype.constructor = mxEdgeSegmentHandler; - -/** - * Function: getPreviewPoints - * - * Updates the given preview state taking into account the state of the constraint handler. - */ -mxEdgeSegmentHandler.prototype.getPreviewPoints = function(point) -{ - if (this.isSource || this.isTarget) - { - return mxElbowEdgeHandler.prototype.getPreviewPoints.apply(this, arguments); - } - else - { - this.convertPoint(point, false); - var pts = this.state.absolutePoints; - var last = pts[0].clone(); - this.convertPoint(last, false); - var result = []; - - for (var i = 1; i < pts.length; i++) - { - var pt = pts[i].clone(); - this.convertPoint(pt, false); - - if (i == this.index) - { - if (last.x == pt.x) - { - last.x = point.x; - pt.x = point.x; - } - else - { - last.y = point.y; - pt.y = point.y; - } - } - - if (i < pts.length - 1) - { - result.push(pt); - } - - last = pt; - } - - if (result.length == 1) - { - var view = this.state.view; - var source = this.state.getVisibleTerminalState(true); - var target = this.state.getVisibleTerminalState(false); - - if (target != null & source != null) - { - var dx = this.state.origin.x; - var dy = this.state.origin.y; - - if (mxUtils.contains(target, result[0].x + dx, result[0].y + dy)) - { - if (pts[1].y == pts[2].y) - { - result[0].y = view.getRoutingCenterY(source) - dy; - } - else - { - result[0].x = view.getRoutingCenterX(source) - dx; - } - } - else if (mxUtils.contains(source, result[0].x + dx, result[0].y + dy)) - { - if (pts[1].y == pts[0].y) - { - result[0].y = view.getRoutingCenterY(target) - dy; - } - else - { - result[0].x = view.getRoutingCenterX(target) - dx; - } - } - } - } - else if (result.length == 0) - { - result = [point]; - } - - return result; - } -}; - -/** - * Function: createBends - * - * Adds custom bends for the center of each segment. - */ -mxEdgeSegmentHandler.prototype.createBends = function() -{ - var bends = []; - - // Source - var bend = this.createHandleShape(0); - - this.initBend(bend); - bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE; - mxEvent.redirectMouseEvents(bend.node, this.graph, this.state); - bends.push(bend); - - if (mxClient.IS_TOUCH) - { - bend.node.setAttribute('pointer-events', 'none'); - } - - var pts = this.state.absolutePoints; - - // Waypoints (segment handles) - if (this.graph.isCellBendable(this.state.cell)) - { - if (this.points == null) - { - this.points = []; - } - - for (var i = 0; i < pts.length - 1; i++) - { - var bend = this.createVirtualBend(); - bends.push(bend); - var horizontal = pts[i].x - pts[i + 1].x == 0; - bend.node.style.cursor = (horizontal) ? 'col-resize' : 'row-resize'; - this.points.push(new mxPoint(0,0)); - - if (mxClient.IS_TOUCH) - { - bend.node.setAttribute('pointer-events', 'none'); - } - } - } - - // Target - var bend = this.createHandleShape(pts.length); - - this.initBend(bend); - bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE; - mxEvent.redirectMouseEvents(bend.node, this.graph, this.state); - bends.push(bend); - - if (mxClient.IS_TOUCH) - { - bend.node.setAttribute('pointer-events', 'none'); - } - - return bends; -}; - - -/** - * Function: redrawInnerBends - * - * Updates the position of the custom bends. - */ -mxEdgeSegmentHandler.prototype.redrawInnerBends = function(p0, pe) -{ - if (this.graph.isCellBendable(this.state.cell)) - { - var s = mxConstants.HANDLE_SIZE; - var pts = this.state.absolutePoints; - - if (pts != null && pts.length > 1) - { - for (var i = 0; i < this.state.absolutePoints.length - 1; i++) - { - if (this.bends[i + 1] != null) - { - var p0 = pts[i]; - var pe = pts[i + 1]; - var pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2); - this.bends[i+1].bounds = new mxRectangle(pt.x - s / 2, pt.y - s / 2, s, s); - this.bends[i+1].reconfigure(); - this.bends[i+1].redraw(); - } - } - } - } -}; - -/** - * Function: connect - * - * Calls <refresh> after <mxEdgeHandler.connect>. - */ -mxEdgeSegmentHandler.prototype.connect = function(edge, terminal, isSource, isClone, me) -{ - mxEdgeHandler.prototype.connect.apply(this, arguments); - this.refresh(); -}; - -/** - * Function: changeTerminalPoint - * - * Calls <refresh> after <mxEdgeHandler.changeTerminalPoint>. - */ -mxEdgeSegmentHandler.prototype.changeTerminalPoint = function(edge, point, isSource) -{ - mxEdgeHandler.prototype.changeTerminalPoint.apply(this, arguments); - this.refresh(); -}; - -/** - * Function: changePoints - * - * Changes the points of the given edge to reflect the current state of the handler. - */ -mxEdgeSegmentHandler.prototype.changePoints = function(edge, points) -{ - points = []; - var pts = this.abspoints; - - if (pts.length > 1) - { - var pt0 = pts[0]; - var pt1 = pts[1]; - - for (var i = 2; i < pts.length; i++) - { - var pt2 = pts[i]; - - if ((Math.round(pt0.x) != Math.round(pt1.x) || - Math.round(pt1.x) != Math.round(pt2.x)) && - (Math.round(pt0.y) != Math.round(pt1.y) || - Math.round(pt1.y) != Math.round(pt2.y))) - { - pt0 = pt1; - pt1 = pt1.clone(); - this.convertPoint(pt1, false); - points.push(pt1); - } - - pt1 = pt2; - } - } - - mxElbowEdgeHandler.prototype.changePoints.apply(this, arguments); - this.refresh(); -}; - -/** - * Function: refresh - * - * Refreshes the bends of this handler. - */ -mxEdgeSegmentHandler.prototype.refresh = function() -{ - if (this.bends != null) - { - for (var i = 0; i < this.bends.length; i++) - { - if (this.bends[i] != null) - { - this.bends[i].destroy(); - this.bends[i] = null; - } - } - - this.bends = this.createBends(); - } -}; diff --git a/src/js/handler/mxElbowEdgeHandler.js b/src/js/handler/mxElbowEdgeHandler.js deleted file mode 100644 index 85fbb06..0000000 --- a/src/js/handler/mxElbowEdgeHandler.js +++ /dev/null @@ -1,248 +0,0 @@ -/** - * $Id: mxElbowEdgeHandler.js,v 1.43 2012-01-06 13:06:01 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxElbowEdgeHandler - * - * Graph event handler that reconnects edges and modifies control points and - * the edge label location. Uses <mxTerminalMarker> for finding and - * highlighting new source and target vertices. This handler is automatically - * created in <mxGraph.createHandler>. It extends <mxEdgeHandler>. - * - * Constructor: mxEdgeHandler - * - * Constructs an edge handler for the specified <mxCellState>. - * - * Parameters: - * - * state - <mxCellState> of the cell to be modified. - */ -function mxElbowEdgeHandler(state) -{ - if (state != null) - { - this.state = state; - this.init(); - } -}; - -/** - * Extends mxEdgeHandler. - */ -mxElbowEdgeHandler.prototype = new mxEdgeHandler(); -mxElbowEdgeHandler.prototype.constructor = mxElbowEdgeHandler; - -/** - * Specifies if a double click on the middle handle should call - * <mxGraph.flipEdge>. Default is true. - */ -mxElbowEdgeHandler.prototype.flipEnabled = true; - -/** - * Variable: doubleClickOrientationResource - * - * Specifies the resource key for the tooltip to be displayed on the single - * control point for routed edges. If the resource for this key does not - * exist then the value is used as the error message. Default is - * 'doubleClickOrientation'. - */ -mxElbowEdgeHandler.prototype.doubleClickOrientationResource = - (mxClient.language != 'none') ? 'doubleClickOrientation' : ''; - -/** - * Function: createBends - * - * Overrides <mxEdgeHandler.createBends> to create custom bends. - */ - mxElbowEdgeHandler.prototype.createBends = function() - { - var bends = []; - - // Source - var bend = this.createHandleShape(0); - - this.initBend(bend); - bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE; - mxEvent.redirectMouseEvents(bend.node, this.graph, this.state); - bends.push(bend); - - if (mxClient.IS_TOUCH) - { - bend.node.setAttribute('pointer-events', 'none'); - } - - // Virtual - bends.push(this.createVirtualBend()); - this.points.push(new mxPoint(0,0)); - - // Target - bend = this.createHandleShape(2); - - this.initBend(bend); - bend.node.style.cursor = mxConstants.CURSOR_BEND_HANDLE; - mxEvent.redirectMouseEvents(bend.node, this.graph, this.state); - bends.push(bend); - - if (mxClient.IS_TOUCH) - { - bend.node.setAttribute('pointer-events', 'none'); - } - - return bends; - }; - -/** - * Function: createVirtualBend - * - * Creates a virtual bend that supports double clicking and calls - * <mxGraph.flipEdge>. - */ -mxElbowEdgeHandler.prototype.createVirtualBend = function() -{ - var bend = this.createHandleShape(); - this.initBend(bend); - - var crs = this.getCursorForBend(); - bend.node.style.cursor = crs; - - // Double-click changes edge style - var dblClick = mxUtils.bind(this, function(evt) - { - if (!mxEvent.isConsumed(evt) && - this.flipEnabled) - { - this.graph.flipEdge(this.state.cell, evt); - mxEvent.consume(evt); - } - }); - - mxEvent.redirectMouseEvents(bend.node, this.graph, this.state, - null, null, null, dblClick); - - if (!this.graph.isCellBendable(this.state.cell)) - { - bend.node.style.visibility = 'hidden'; - } - - return bend; -}; - -/** - * Function: getCursorForBend - * - * Returns the cursor to be used for the bend. - */ -mxElbowEdgeHandler.prototype.getCursorForBend = function() -{ - return (this.state.style[mxConstants.STYLE_EDGE] == mxEdgeStyle.TopToBottom || - this.state.style[mxConstants.STYLE_EDGE] == mxConstants.EDGESTYLE_TOPTOBOTTOM || - ((this.state.style[mxConstants.STYLE_EDGE] == mxEdgeStyle.ElbowConnector || - this.state.style[mxConstants.STYLE_EDGE] == mxConstants.EDGESTYLE_ELBOW)&& - this.state.style[mxConstants.STYLE_ELBOW] == mxConstants.ELBOW_VERTICAL)) ? - 'row-resize' : 'col-resize'; -}; - -/** - * Function: getTooltipForNode - * - * Returns the tooltip for the given node. - */ -mxElbowEdgeHandler.prototype.getTooltipForNode = function(node) -{ - var tip = null; - - if (this.bends != null && - this.bends[1] != null && - (node == this.bends[1].node || - node.parentNode == this.bends[1].node)) - { - tip = this.doubleClickOrientationResource; - tip = mxResources.get(tip) || tip; // translate - } - - return tip; -}; - -/** - * Function: convertPoint - * - * Converts the given point in-place from screen to unscaled, untranslated - * graph coordinates and applies the grid. - * - * Parameters: - * - * point - <mxPoint> to be converted. - * gridEnabled - Boolean that specifies if the grid should be applied. - */ -mxElbowEdgeHandler.prototype.convertPoint = function(point, gridEnabled) -{ - var scale = this.graph.getView().getScale(); - var tr = this.graph.getView().getTranslate(); - var origin = this.state.origin; - - if (gridEnabled) - { - point.x = this.graph.snap(point.x); - point.y = this.graph.snap(point.y); - } - - point.x = Math.round(point.x / scale - tr.x - origin.x); - point.y = Math.round(point.y / scale - tr.y - origin.y); -}; - -/** - * Function: redrawInnerBends - * - * Updates and redraws the inner bends. - * - * Parameters: - * - * p0 - <mxPoint> that represents the location of the first point. - * pe - <mxPoint> that represents the location of the last point. - */ -mxElbowEdgeHandler.prototype.redrawInnerBends = function(p0, pe) -{ - var g = this.graph.getModel().getGeometry(this.state.cell); - var pts = g.points; - - var pt = (pts != null) ? pts[0] : null; - - if (pt == null) - { - pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2); - } - else - { - pt = new mxPoint(this.graph.getView().scale*(pt.x + - this.graph.getView().translate.x + this.state.origin.x), - this.graph.getView().scale*(pt.y + this.graph.getView().translate.y + - this.state.origin.y)); - } - - // Makes handle slightly bigger if the yellow label handle - // exists and intersects this green handle - var b = this.bends[1].bounds; - var w = b.width; - var h = b.height; - - if (this.handleImage == null) - { - w = mxConstants.HANDLE_SIZE; - h = mxConstants.HANDLE_SIZE; - } - - var bounds = new mxRectangle(pt.x - w / 2, pt.y - h / 2, w, h); - - if (this.handleImage == null && this.labelShape.node.style.visibility != 'hidden' && - mxUtils.intersects(bounds, this.labelShape.bounds)) - { - w += 3; - h += 3; - bounds = new mxRectangle(pt.x - w / 2, pt.y - h / 2, w, h); - } - - this.bends[1].bounds = bounds; - this.bends[1].reconfigure(); - this.bends[1].redraw(); -}; diff --git a/src/js/handler/mxGraphHandler.js b/src/js/handler/mxGraphHandler.js deleted file mode 100644 index 57e27a1..0000000 --- a/src/js/handler/mxGraphHandler.js +++ /dev/null @@ -1,916 +0,0 @@ -/** - * $Id: mxGraphHandler.js,v 1.129 2012-04-13 12:53:30 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxGraphHandler - * - * Graph event handler that handles selection. Individual cells are handled - * separately using <mxVertexHandler> or one of the edge handlers. These - * handlers are created using <mxGraph.createHandler> in - * <mxGraphSelectionModel.cellAdded>. - * - * To avoid the container to scroll a moved cell into view, set - * <scrollAfterMove> to false. - * - * Constructor: mxGraphHandler - * - * Constructs an event handler that creates handles for the - * selection cells. - * - * Parameters: - * - * graph - Reference to the enclosing <mxGraph>. - */ -function mxGraphHandler(graph) -{ - this.graph = graph; - this.graph.addMouseListener(this); - - // Repaints the handler after autoscroll - this.panHandler = mxUtils.bind(this, function() - { - this.updatePreviewShape(); - }); - - this.graph.addListener(mxEvent.PAN, this.panHandler); -}; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxGraphHandler.prototype.graph = null; - -/** - * Variable: maxCells - * - * Defines the maximum number of cells to paint subhandles - * for. Default is 50 for Firefox and 20 for IE. Set this - * to 0 if you want an unlimited number of handles to be - * displayed. This is only recommended if the number of - * cells in the graph is limited to a small number, eg. - * 500. - */ -mxGraphHandler.prototype.maxCells = (mxClient.IS_IE) ? 20 : 50; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxGraphHandler.prototype.enabled = true; - -/** - * Variable: highlightEnabled - * - * Specifies if drop targets under the mouse should be enabled. Default is - * true. - */ -mxGraphHandler.prototype.highlightEnabled = true; - -/** - * Variable: cloneEnabled - * - * Specifies if cloning by control-drag is enabled. Default is true. - */ -mxGraphHandler.prototype.cloneEnabled = true; - -/** - * Variable: moveEnabled - * - * Specifies if moving is enabled. Default is true. - */ -mxGraphHandler.prototype.moveEnabled = true; - -/** - * Variable: guidesEnabled - * - * Specifies if other cells should be used for snapping the right, center or - * left side of the current selection. Default is false. - */ -mxGraphHandler.prototype.guidesEnabled = false; - -/** - * Variable: guide - * - * Holds the <mxGuide> instance that is used for alignment. - */ -mxGraphHandler.prototype.guide = null; - -/** - * Variable: currentDx - * - * Stores the x-coordinate of the current mouse move. - */ -mxGraphHandler.prototype.currentDx = null; - -/** - * Variable: currentDy - * - * Stores the y-coordinate of the current mouse move. - */ -mxGraphHandler.prototype.currentDy = null; - -/** - * Variable: updateCursor - * - * Specifies if a move cursor should be shown if the mouse is ove a movable - * cell. Default is true. - */ -mxGraphHandler.prototype.updateCursor = true; - -/** - * Variable: selectEnabled - * - * Specifies if selecting is enabled. Default is true. - */ -mxGraphHandler.prototype.selectEnabled = true; - -/** - * Variable: removeCellsFromParent - * - * Specifies if cells may be moved out of their parents. Default is true. - */ -mxGraphHandler.prototype.removeCellsFromParent = true; - -/** - * Variable: connectOnDrop - * - * Specifies if drop events are interpreted as new connections if no other - * drop action is defined. Default is false. - */ -mxGraphHandler.prototype.connectOnDrop = false; - -/** - * Variable: scrollOnMove - * - * Specifies if the view should be scrolled so that a moved cell is - * visible. Default is true. - */ -mxGraphHandler.prototype.scrollOnMove = true; - -/** - * Variable: minimumSize - * - * Specifies the minimum number of pixels for the width and height of a - * selection border. Default is 6. - */ -mxGraphHandler.prototype.minimumSize = 6; - -/** - * Variable: previewColor - * - * Specifies the color of the preview shape. Default is black. - */ -mxGraphHandler.prototype.previewColor = 'black'; - -/** - * Variable: htmlPreview - * - * Specifies if the graph container should be used for preview. If this is used - * then drop target detection relies entirely on <mxGraph.getCellAt> because - * the HTML preview does not "let events through". Default is false. - */ -mxGraphHandler.prototype.htmlPreview = false; - -/** - * Variable: shape - * - * Reference to the <mxShape> that represents the preview. - */ -mxGraphHandler.prototype.shape = null; - -/** - * Variable: scaleGrid - * - * Specifies if the grid should be scaled. Default is false. - */ -mxGraphHandler.prototype.scaleGrid = false; - -/** - * Variable: crisp - * - * Specifies if the move preview should be rendered in crisp mode if applicable. - * Default is true. - */ -mxGraphHandler.prototype.crisp = true; - -/** - * Function: isEnabled - * - * Returns <enabled>. - */ -mxGraphHandler.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Function: setEnabled - * - * Sets <enabled>. - */ -mxGraphHandler.prototype.setEnabled = function(value) -{ - this.enabled = value; -}; - -/** - * Function: isCloneEnabled - * - * Returns <cloneEnabled>. - */ -mxGraphHandler.prototype.isCloneEnabled = function() -{ - return this.cloneEnabled; -}; - -/** - * Function: setCloneEnabled - * - * Sets <cloneEnabled>. - * - * Parameters: - * - * value - Boolean that specifies the new clone enabled state. - */ -mxGraphHandler.prototype.setCloneEnabled = function(value) -{ - this.cloneEnabled = value; -}; - -/** - * Function: isMoveEnabled - * - * Returns <moveEnabled>. - */ -mxGraphHandler.prototype.isMoveEnabled = function() -{ - return this.moveEnabled; -}; - -/** - * Function: setMoveEnabled - * - * Sets <moveEnabled>. - */ -mxGraphHandler.prototype.setMoveEnabled = function(value) -{ - this.moveEnabled = value; -}; - -/** - * Function: isSelectEnabled - * - * Returns <selectEnabled>. - */ -mxGraphHandler.prototype.isSelectEnabled = function() -{ - return this.selectEnabled; -}; - -/** - * Function: setSelectEnabled - * - * Sets <selectEnabled>. - */ -mxGraphHandler.prototype.setSelectEnabled = function(value) -{ - this.selectEnabled = value; -}; - -/** - * Function: isRemoveCellsFromParent - * - * Returns <removeCellsFromParent>. - */ -mxGraphHandler.prototype.isRemoveCellsFromParent = function() -{ - return this.removeCellsFromParent; -}; - -/** - * Function: setRemoveCellsFromParent - * - * Sets <removeCellsFromParent>. - */ -mxGraphHandler.prototype.setRemoveCellsFromParent = function(value) -{ - this.removeCellsFromParent = value; -}; - -/** - * Function: getInitialCellForEvent - * - * Hook to return initial cell for the given event. - */ -mxGraphHandler.prototype.getInitialCellForEvent = function(me) -{ - return me.getCell(); -}; - -/** - * Function: isDelayedSelection - * - * Hook to return true for delayed selections. - */ -mxGraphHandler.prototype.isDelayedSelection = function(cell) -{ - return this.graph.isCellSelected(cell); -}; - -/** - * Function: mouseDown - * - * Handles the event by selecing the given cell and creating a handle for - * it. By consuming the event all subsequent events of the gesture are - * redirected to this handler. - */ -mxGraphHandler.prototype.mouseDown = function(sender, me) -{ - if (!me.isConsumed() && this.isEnabled() && this.graph.isEnabled() && - !this.graph.isForceMarqueeEvent(me.getEvent()) && me.getState() != null) - { - var cell = this.getInitialCellForEvent(me); - this.cell = null; - this.delayedSelection = this.isDelayedSelection(cell); - - if (this.isSelectEnabled() && !this.delayedSelection) - { - this.graph.selectCellForEvent(cell, me.getEvent()); - } - - if (this.isMoveEnabled()) - { - var model = this.graph.model; - var geo = model.getGeometry(cell); - - if (this.graph.isCellMovable(cell) && ((!model.isEdge(cell) || this.graph.getSelectionCount() > 1 || - (geo.points != null && geo.points.length > 0) || model.getTerminal(cell, true) == null || - model.getTerminal(cell, false) == null) || this.graph.allowDanglingEdges || - (this.graph.isCloneEvent(me.getEvent()) && this.graph.isCellsCloneable()))) - { - this.start(cell, me.getX(), me.getY()); - } - - this.cellWasClicked = true; - - // Workaround for SELECT element not working in Webkit, this blocks moving - // of the cell if the select element is clicked in Safari which is needed - // because Safari doesn't seem to route the subsequent mouseUp event via - // this handler which leads to an inconsistent state (no reset called). - // Same for cellWasClicked which will block clearing the selection when - // clicking the background after clicking on the SELECT element in Safari. - if ((!mxClient.IS_SF && !mxClient.IS_GC) || me.getSource().nodeName != 'SELECT') - { - me.consume(); - } - else if (mxClient.IS_SF && me.getSource().nodeName == 'SELECT') - { - this.cellWasClicked = false; - this.first = null; - } - } - } -}; - -/** - * Function: getGuideStates - * - * Creates an array of cell states which should be used as guides. - */ -mxGraphHandler.prototype.getGuideStates = function() -{ - var parent = this.graph.getDefaultParent(); - var model = this.graph.getModel(); - - var filter = mxUtils.bind(this, function(cell) - { - return this.graph.view.getState(cell) != null && - model.isVertex(cell) && - model.getGeometry(cell) != null && - !model.getGeometry(cell).relative; - }); - - return this.graph.view.getCellStates(model.filterDescendants(filter, parent)); -}; - -/** - * Function: getCells - * - * Returns the cells to be modified by this handler. This implementation - * returns all selection cells that are movable, or the given initial cell if - * the given cell is not selected and movable. This handles the case of moving - * unselectable or unselected cells. - * - * Parameters: - * - * initialCell - <mxCell> that triggered this handler. - */ -mxGraphHandler.prototype.getCells = function(initialCell) -{ - if (!this.delayedSelection && this.graph.isCellMovable(initialCell)) - { - return [initialCell]; - } - else - { - return this.graph.getMovableCells(this.graph.getSelectionCells()); - } -}; - -/** - * Function: getPreviewBounds - * - * Returns the <mxRectangle> used as the preview bounds for - * moving the given cells. - */ -mxGraphHandler.prototype.getPreviewBounds = function(cells) -{ - var bounds = this.graph.getView().getBounds(cells); - - if (bounds != null) - { - if (bounds.width < this.minimumSize) - { - var dx = this.minimumSize - bounds.width; - bounds.x -= dx / 2; - bounds.width = this.minimumSize; - } - - if (bounds.height < this.minimumSize) - { - var dy = this.minimumSize - bounds.height; - bounds.y -= dy / 2; - bounds.height = this.minimumSize; - } - } - - return bounds; -}; - -/** - * Function: createPreviewShape - * - * Creates the shape used to draw the preview for the given bounds. - */ -mxGraphHandler.prototype.createPreviewShape = function(bounds) -{ - var shape = new mxRectangleShape(bounds, null, this.previewColor); - shape.isDashed = true; - shape.crisp = this.crisp; - - if (this.htmlPreview) - { - shape.dialect = mxConstants.DIALECT_STRICTHTML; - shape.init(this.graph.container); - } - else - { - // 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 - shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - shape.init(this.graph.getView().getOverlayPane()); - - // Event-transparency - if (shape.dialect == mxConstants.DIALECT_SVG) - { - shape.node.setAttribute('style', 'pointer-events:none;'); - } - else - { - shape.node.style.background = ''; - } - } - - return shape; -}; - -/** - * Function: start - * - * Starts the handling of the mouse gesture. - */ -mxGraphHandler.prototype.start = function(cell, x, y) -{ - this.cell = cell; - this.first = mxUtils.convertPoint(this.graph.container, x, y); - this.cells = this.getCells(this.cell); - this.bounds = this.getPreviewBounds(this.cells); - - if (this.guidesEnabled) - { - this.guide = new mxGuide(this.graph, this.getGuideStates()); - } -}; - -/** - * Function: useGuidesForEvent - * - * Returns true if the guides should be used for the given <mxMouseEvent>. - * This implementation returns <mxGuide.isEnabledForEvent>. - */ -mxGraphHandler.prototype.useGuidesForEvent = function(me) -{ - return (this.guide != null) ? this.guide.isEnabledForEvent(me.getEvent()) : true; -}; - - -/** - * Function: snap - * - * Snaps the given vector to the grid and returns the given mxPoint instance. - */ -mxGraphHandler.prototype.snap = function(vector) -{ - var scale = (this.scaleGrid) ? this.graph.view.scale : 1; - - vector.x = this.graph.snap(vector.x / scale) * scale; - vector.y = this.graph.snap(vector.y / scale) * scale; - - return vector; -}; - -/** - * Function: mouseMove - * - * Handles the event by highlighting possible drop targets and updating the - * preview. - */ -mxGraphHandler.prototype.mouseMove = function(sender, me) -{ - var graph = this.graph; - - if (!me.isConsumed() && graph.isMouseDown && this.cell != null && - this.first != null && this.bounds != null) - { - var point = mxUtils.convertPoint(graph.container, me.getX(), me.getY()); - var dx = point.x - this.first.x; - var dy = point.y - this.first.y; - var tol = graph.tolerance; - - if (this.shape!= null || Math.abs(dx) > tol || Math.abs(dy) > tol) - { - // Highlight is used for highlighting drop targets - if (this.highlight == null) - { - this.highlight = new mxCellHighlight(this.graph, - mxConstants.DROP_TARGET_COLOR, 3); - } - - if (this.shape == null) - { - this.shape = this.createPreviewShape(this.bounds); - } - - var gridEnabled = graph.isGridEnabledEvent(me.getEvent()); - var hideGuide = true; - - if (this.guide != null && this.useGuidesForEvent(me)) - { - var delta = this.guide.move(this.bounds, new mxPoint(dx, dy), gridEnabled); - hideGuide = false; - dx = delta.x; - dy = delta.y; - } - else if (gridEnabled) - { - var trx = graph.getView().translate; - var scale = graph.getView().scale; - - var tx = this.bounds.x - (graph.snap(this.bounds.x / scale - trx.x) + trx.x) * scale; - var ty = this.bounds.y - (graph.snap(this.bounds.y / scale - trx.y) + trx.y) * scale; - var v = this.snap(new mxPoint(dx, dy)); - - dx = v.x - tx; - dy = v.y - ty; - } - - if (this.guide != null && hideGuide) - { - this.guide.hide(); - } - - // Constrained movement if shift key is pressed - if (graph.isConstrainedEvent(me.getEvent())) - { - if (Math.abs(dx) > Math.abs(dy)) - { - dy = 0; - } - else - { - dx = 0; - } - } - - this.currentDx = dx; - this.currentDy = dy; - this.updatePreviewShape(); - - var target = null; - var cell = me.getCell(); - - if (graph.isDropEnabled() && this.highlightEnabled) - { - // Contains a call to getCellAt to find the cell under the mouse - target = graph.getDropTarget(this.cells, me.getEvent(), cell); - } - - // Checks if parent is dropped into child - var parent = target; - var model = graph.getModel(); - - while (parent != null && parent != this.cells[0]) - { - parent = model.getParent(parent); - } - - var clone = graph.isCloneEvent(me.getEvent()) && graph.isCellsCloneable() && this.isCloneEnabled(); - var state = graph.getView().getState(target); - var highlight = false; - - if (state != null && parent == null && (model.getParent(this.cell) != target || clone)) - { - if (this.target != target) - { - this.target = target; - this.setHighlightColor(mxConstants.DROP_TARGET_COLOR); - } - - highlight = true; - } - else - { - this.target = null; - - if (this.connectOnDrop && cell != null && this.cells.length == 1 && - graph.getModel().isVertex(cell) && graph.isCellConnectable(cell)) - { - state = graph.getView().getState(cell); - - if (state != null) - { - var error = graph.getEdgeValidationError(null, this.cell, cell); - var color = (error == null) ? - mxConstants.VALID_COLOR : - mxConstants.INVALID_CONNECT_TARGET_COLOR; - this.setHighlightColor(color); - highlight = true; - } - } - } - - if (state != null && highlight) - { - this.highlight.highlight(state); - } - else - { - this.highlight.hide(); - } - } - - me.consume(); - - // Cancels the bubbling of events to the container so - // that the droptarget is not reset due to an mouseMove - // fired on the container with no associated state. - mxEvent.consume(me.getEvent()); - } - else if ((this.isMoveEnabled() || this.isCloneEnabled()) && this.updateCursor && - !me.isConsumed() && me.getState() != null && !graph.isMouseDown) - { - var cursor = graph.getCursorForCell(me.getCell()); - - if (cursor == null && graph.isEnabled() && graph.isCellMovable(me.getCell())) - { - if (graph.getModel().isEdge(me.getCell())) - { - cursor = mxConstants.CURSOR_MOVABLE_EDGE; - } - else - { - cursor = mxConstants.CURSOR_MOVABLE_VERTEX; - } - } - - me.getState().setCursor(cursor); - me.consume(); - } -}; - -/** - * Function: updatePreviewShape - * - * Updates the bounds of the preview shape. - */ -mxGraphHandler.prototype.updatePreviewShape = function() -{ - if (this.shape != null) - { - this.shape.bounds = new mxRectangle(this.bounds.x + this.currentDx - this.graph.panDx, - this.bounds.y + this.currentDy - this.graph.panDy, this.bounds.width, this.bounds.height); - this.shape.redraw(); - } -}; - -/** - * Function: setHighlightColor - * - * Sets the color of the rectangle used to highlight drop targets. - * - * Parameters: - * - * color - String that represents the new highlight color. - */ -mxGraphHandler.prototype.setHighlightColor = function(color) -{ - if (this.highlight != null) - { - this.highlight.setHighlightColor(color); - } -}; - -/** - * Function: mouseUp - * - * Handles the event by applying the changes to the selection cells. - */ -mxGraphHandler.prototype.mouseUp = function(sender, me) -{ - if (!me.isConsumed()) - { - var graph = this.graph; - - if (this.cell != null && this.first != null && this.shape != null && - this.currentDx != null && this.currentDy != null) - { - var scale = graph.getView().scale; - var clone = graph.isCloneEvent(me.getEvent()) && graph.isCellsCloneable() && this.isCloneEnabled(); - var dx = this.currentDx / scale; - var dy = this.currentDy / scale; - - var cell = me.getCell(); - - if (this.connectOnDrop && this.target == null && cell != null && graph.getModel().isVertex(cell) && - graph.isCellConnectable(cell) && graph.isEdgeValid(null, this.cell, cell)) - { - graph.connectionHandler.connect(this.cell, cell, me.getEvent()); - } - else - { - var target = this.target; - - if (graph.isSplitEnabled() && graph.isSplitTarget(target, this.cells, me.getEvent())) - { - graph.splitEdge(target, this.cells, null, dx, dy); - } - else - { - this.moveCells(this.cells, dx, dy, clone, this.target, me.getEvent()); - } - } - } - else if (this.isSelectEnabled() && this.delayedSelection && this.cell != null) - { - this.selectDelayed(me); - } - } - - // Consumes the event if a cell was initially clicked - if (this.cellWasClicked) - { - me.consume(); - } - - this.reset(); -}; - -/** - * Function: selectDelayed - * - * Implements the delayed selection for the given mouse event. - */ -mxGraphHandler.prototype.selectDelayed = function(me) -{ - this.graph.selectCellForEvent(this.cell, me.getEvent()); -}; - -/** - * Function: reset - * - * Resets the state of this handler. - */ -mxGraphHandler.prototype.reset = function() -{ - this.destroyShapes(); - this.cellWasClicked = false; - this.delayedSelection = false; - this.currentDx = null; - this.currentDy = null; - this.guides = null; - this.first = null; - this.cell = null; - this.target = null; -}; - -/** - * Function: shouldRemoveCellsFromParent - * - * Returns true if the given cells should be removed from the parent for the specified - * mousereleased event. - */ -mxGraphHandler.prototype.shouldRemoveCellsFromParent = function(parent, cells, evt) -{ - if (this.graph.getModel().isVertex(parent)) - { - var pState = this.graph.getView().getState(parent); - var pt = mxUtils.convertPoint(this.graph.container, - mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - - return pState != null && !mxUtils.contains(pState, pt.x, pt.y); - } - - return false; -}; - -/** - * Function: moveCells - * - * Moves the given cells by the specified amount. - */ -mxGraphHandler.prototype.moveCells = function(cells, dx, dy, clone, target, evt) -{ - if (clone) - { - cells = this.graph.getCloneableCells(cells); - } - - // Removes cells from parent - if (target == null && this.isRemoveCellsFromParent() && - this.shouldRemoveCellsFromParent(this.graph.getModel().getParent(this.cell), cells, evt)) - { - target = this.graph.getDefaultParent(); - } - - // Passes all selected cells in order to correctly clone or move into - // the target cell. The method checks for each cell if its movable. - cells = this.graph.moveCells(cells, dx - this.graph.panDx / this.graph.view.scale, - dy - this.graph.panDy / this.graph.view.scale, clone, target, evt); - - if (this.isSelectEnabled() && this.scrollOnMove) - { - this.graph.scrollCellToVisible(cells[0]); - } - - // Selects the new cells if cells have been cloned - if (clone) - { - this.graph.setSelectionCells(cells); - } -}; - -/** - * Function: destroyShapes - * - * Destroy the preview and highlight shapes. - */ -mxGraphHandler.prototype.destroyShapes = function() -{ - // Destroys the preview dashed rectangle - if (this.shape != null) - { - this.shape.destroy(); - this.shape = null; - } - - if (this.guide != null) - { - this.guide.destroy(); - this.guide = null; - } - - // Destroys the drop target highlight - if (this.highlight != null) - { - this.highlight.destroy(); - this.highlight = null; - } -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. - */ -mxGraphHandler.prototype.destroy = function() -{ - this.graph.removeMouseListener(this); - this.graph.removeListener(this.panHandler); - this.destroyShapes(); -}; diff --git a/src/js/handler/mxKeyHandler.js b/src/js/handler/mxKeyHandler.js deleted file mode 100644 index cc07e51..0000000 --- a/src/js/handler/mxKeyHandler.js +++ /dev/null @@ -1,402 +0,0 @@ -/** - * $Id: mxKeyHandler.js,v 1.48 2012-03-30 08:30:41 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxKeyHandler - * - * Event handler that listens to keystroke events. This is not a singleton, - * however, it is normally only required once if the target is the document - * element (default). - * - * This handler installs a key event listener in the topmost DOM node and - * processes all events that originate from descandants of <mxGraph.container> - * or from the topmost DOM node. The latter means that all unhandled keystrokes - * are handled by this object regardless of the focused state of the <graph>. - * - * Example: - * - * The following example creates a key handler that listens to the delete key - * (46) and deletes the selection cells if the graph is enabled. - * - * (code) - * var keyHandler = new mxKeyHandler(graph); - * keyHandler.bindKey(46, function(evt) - * { - * if (graph.isEnabled()) - * { - * graph.removeCells(); - * } - * }); - * (end) - * - * Keycodes: - * - * See http://tinyurl.com/yp8jgl or http://tinyurl.com/229yqw for a list of - * keycodes or install a key event listener into the document element and print - * the key codes of the respective events to the console. - * - * To support the Command key and the Control key on the Mac, the following - * code can be used. - * - * (code) - * keyHandler.getFunction = function(evt) - * { - * if (evt != null) - * { - * return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode]; - * } - * - * return null; - * }; - * (end) - * - * Constructor: mxKeyHandler - * - * Constructs an event handler that executes functions bound to specific - * keystrokes. - * - * Parameters: - * - * graph - Reference to the associated <mxGraph>. - * target - Optional reference to the event target. If null, the document - * element is used as the event target, that is, the object where the key - * event listener is installed. - */ -function mxKeyHandler(graph, target) -{ - if (graph != null) - { - this.graph = graph; - this.target = target || document.documentElement; - - // Creates the arrays to map from keycodes to functions - this.normalKeys = []; - this.shiftKeys = []; - this.controlKeys = []; - this.controlShiftKeys = []; - - // Installs the keystroke listener in the target - mxEvent.addListener(this.target, "keydown", - mxUtils.bind(this, function(evt) - { - this.keyDown(evt); - }) - ); - - // Automatically deallocates memory in IE - if (mxClient.IS_IE) - { - mxEvent.addListener(window, 'unload', - mxUtils.bind(this, function() - { - this.destroy(); - }) - ); - } - } -}; - -/** - * Variable: graph - * - * Reference to the <mxGraph> associated with this handler. - */ -mxKeyHandler.prototype.graph = null; - -/** - * Variable: target - * - * Reference to the target DOM, that is, the DOM node where the key event - * listeners are installed. - */ -mxKeyHandler.prototype.target = null; - -/** - * Variable: normalKeys - * - * Maps from keycodes to functions for non-pressed control keys. - */ -mxKeyHandler.prototype.normalKeys = null; - -/** - * Variable: shiftKeys - * - * Maps from keycodes to functions for pressed shift keys. - */ -mxKeyHandler.prototype.shiftKeys = null; - -/** - * Variable: controlKeys - * - * Maps from keycodes to functions for pressed control keys. - */ -mxKeyHandler.prototype.controlKeys = null; - -/** - * Variable: controlShiftKeys - * - * Maps from keycodes to functions for pressed control and shift keys. - */ -mxKeyHandler.prototype.controlShiftKeys = null; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxKeyHandler.prototype.enabled = true; - -/** - * Function: isEnabled - * - * Returns true if events are handled. This implementation returns - * <enabled>. - */ -mxKeyHandler.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Function: setEnabled - * - * Enables or disables event handling by updating <enabled>. - * - * Parameters: - * - * enabled - Boolean that specifies the new enabled state. - */ -mxKeyHandler.prototype.setEnabled = function(enabled) -{ - this.enabled = enabled; -}; - -/** - * Function: bindKey - * - * Binds the specified keycode to the given function. This binding is used - * if the control key is not pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindKey = function(code, funct) -{ - this.normalKeys[code] = funct; -}; - -/** - * Function: bindShiftKey - * - * Binds the specified keycode to the given function. This binding is used - * if the shift key is pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindShiftKey = function(code, funct) -{ - this.shiftKeys[code] = funct; -}; - -/** - * Function: bindControlKey - * - * Binds the specified keycode to the given function. This binding is used - * if the control key is pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindControlKey = function(code, funct) -{ - this.controlKeys[code] = funct; -}; - -/** - * Function: bindControlShiftKey - * - * Binds the specified keycode to the given function. This binding is used - * if the control and shift key are pressed. - * - * Parameters: - * - * code - Integer that specifies the keycode. - * funct - JavaScript function that takes the key event as an argument. - */ -mxKeyHandler.prototype.bindControlShiftKey = function(code, funct) -{ - this.controlShiftKeys[code] = funct; -}; - -/** - * Function: isControlDown - * - * Returns true if the control key is pressed. This uses <mxEvent.isControlDown>. - * - * Parameters: - * - * evt - Key event whose control key pressed state should be returned. - */ -mxKeyHandler.prototype.isControlDown = function(evt) -{ - return mxEvent.isControlDown(evt); -}; - -/** - * Function: getFunction - * - * Returns the function associated with the given key event or null if no - * function is associated with the given event. - * - * Parameters: - * - * evt - Key event whose associated function should be returned. - */ -mxKeyHandler.prototype.getFunction = function(evt) -{ - if (evt != null) - { - if (this.isControlDown(evt)) - { - if (mxEvent.isShiftDown(evt)) - { - return this.controlShiftKeys[evt.keyCode]; - } - else - { - return this.controlKeys[evt.keyCode]; - } - } - else - { - if (mxEvent.isShiftDown(evt)) - { - return this.shiftKeys[evt.keyCode]; - } - else - { - return this.normalKeys[evt.keyCode]; - } - } - } - - return null; -}; - -/** - * Function: isGraphEvent - * - * Returns true if the event should be processed by this handler, that is, - * if the event source is either the target, one of its direct children, a - * descendant of the <mxGraph.container>, or the <mxGraph.cellEditor> of the - * <graph>. - * - * Parameters: - * - * evt - Key event that represents the keystroke. - */ -mxKeyHandler.prototype.isGraphEvent = function(evt) -{ - var source = mxEvent.getSource(evt); - - // Accepts events from the target object or - // in-place editing inside graph - if ((source == this.target || source.parentNode == this.target) || - (this.graph.cellEditor != null && source == this.graph.cellEditor.textarea)) - { - return true; - } - - // Accepts events from inside the container - var elt = source; - - while (elt != null) - { - if (elt == this.graph.container) - { - return true; - } - - elt = elt.parentNode; - } - - return false; -}; - -/** - * Function: keyDown - * - * Handles the event by invoking the function bound to the respective - * keystroke if <mxGraph.isEnabled>, <isEnabled> and <isGraphEvent> all - * return true for the given event and <mxGraph.isEditing> returns false. - * If the graph is editing only the <enter> and <escape> cases are handled - * by calling the respective hooks. - * - * Parameters: - * - * evt - Key event that represents the keystroke. - */ -mxKeyHandler.prototype.keyDown = function(evt) -{ - if (this.graph.isEnabled() && !mxEvent.isConsumed(evt) && - this.isGraphEvent(evt) && this.isEnabled()) - { - // Cancels the editing if escape is pressed - if (evt.keyCode == 27 /* Escape */) - { - this.escape(evt); - } - - // Invokes the function for the keystroke - else if (!this.graph.isEditing()) - { - var boundFunction = this.getFunction(evt); - - if (boundFunction != null) - { - boundFunction(evt); - mxEvent.consume(evt); - } - } - } -}; - -/** - * Function: escape - * - * Hook to process ESCAPE keystrokes. This implementation invokes - * <mxGraph.stopEditing> to cancel the current editing, connecting - * and/or other ongoing modifications. - * - * Parameters: - * - * evt - Key event that represents the keystroke. Possible keycode in this - * case is 27 (ESCAPE). - */ -mxKeyHandler.prototype.escape = function(evt) -{ - if (this.graph.isEscapeEnabled()) - { - this.graph.escape(evt); - } -}; - -/** - * Function: destroy - * - * Destroys the handler and all its references into the DOM. This does - * normally not need to be called, it is called automatically when the - * window unloads (in IE). - */ -mxKeyHandler.prototype.destroy = function() -{ - this.target = null; -}; diff --git a/src/js/handler/mxPanningHandler.js b/src/js/handler/mxPanningHandler.js deleted file mode 100644 index b388144..0000000 --- a/src/js/handler/mxPanningHandler.js +++ /dev/null @@ -1,390 +0,0 @@ -/** - * $Id: mxPanningHandler.js,v 1.79 2012-07-17 14:37:41 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxPanningHandler - * - * Event handler that pans and creates popupmenus. To use the left - * mousebutton for panning without interfering with cell moving and - * resizing, use <isUseLeftButton> and <isIgnoreCell>. For grid size - * steps while panning, use <useGrid>. This handler is built-into - * <mxGraph.panningHandler> and enabled using <mxGraph.setPanning>. - * - * Constructor: mxPanningHandler - * - * Constructs an event handler that creates a <mxPopupMenu> - * and pans the graph. - * - * Event: mxEvent.PAN_START - * - * Fires when the panning handler changes its <active> state to true. The - * <code>event</code> property contains the corresponding <mxMouseEvent>. - * - * Event: mxEvent.PAN - * - * Fires while handle is processing events. The <code>event</code> property contains - * the corresponding <mxMouseEvent>. - * - * Event: mxEvent.PAN_END - * - * Fires when the panning handler changes its <active> state to false. The - * <code>event</code> property contains the corresponding <mxMouseEvent>. - */ -function mxPanningHandler(graph, factoryMethod) -{ - if (graph != null) - { - this.graph = graph; - this.factoryMethod = factoryMethod; - this.graph.addMouseListener(this); - this.init(); - } -}; - -/** - * Extends mxPopupMenu. - */ -mxPanningHandler.prototype = new mxPopupMenu(); -mxPanningHandler.prototype.constructor = mxPanningHandler; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxPanningHandler.prototype.graph = null; - -/** - * Variable: usePopupTrigger - * - * Specifies if the <isPopupTrigger> should also be used for panning. To - * avoid conflicts, the panning is only activated if the mouse was moved - * more than <mxGraph.tolerance>, otherwise, a single click is assumed - * and the popupmenu is displayed. Default is true. - */ -mxPanningHandler.prototype.usePopupTrigger = true; - -/** - * Variable: useLeftButtonForPanning - * - * Specifies if panning should be active for the left mouse button. - * Setting this to true may conflict with <mxRubberband>. Default is false. - */ -mxPanningHandler.prototype.useLeftButtonForPanning = false; - -/** - * Variable: selectOnPopup - * - * Specifies if cells should be selected if a popupmenu is displayed for - * them. Default is true. - */ -mxPanningHandler.prototype.selectOnPopup = true; - -/** - * Variable: clearSelectionOnBackground - * - * Specifies if cells should be deselected if a popupmenu is displayed for - * the diagram background. Default is true. - */ -mxPanningHandler.prototype.clearSelectionOnBackground = true; - -/** - * Variable: ignoreCell - * - * Specifies if panning should be active even if there is a cell under the - * mousepointer. Default is false. - */ -mxPanningHandler.prototype.ignoreCell = false; - -/** - * Variable: previewEnabled - * - * Specifies if the panning should be previewed. Default is true. - */ -mxPanningHandler.prototype.previewEnabled = true; - -/** - * Variable: useGrid - * - * Specifies if the panning steps should be aligned to the grid size. - * Default is false. - */ -mxPanningHandler.prototype.useGrid = false; - -/** - * Variable: panningEnabled - * - * Specifies if panning should be enabled. Default is true. - */ -mxPanningHandler.prototype.panningEnabled = true; - -/** - * Function: isPanningEnabled - * - * Returns <panningEnabled>. - */ -mxPanningHandler.prototype.isPanningEnabled = function() -{ - return this.panningEnabled; -}; - -/** - * Function: setPanningEnabled - * - * Sets <panningEnabled>. - */ -mxPanningHandler.prototype.setPanningEnabled = function(value) -{ - this.panningEnabled = value; -}; - -/** - * Function: init - * - * Initializes the shapes required for this vertex handler. - */ -mxPanningHandler.prototype.init = function() -{ - // Supercall - mxPopupMenu.prototype.init.apply(this); - - // Hides the tooltip if the mouse is over - // the context menu - mxEvent.addListener(this.div, (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove', - mxUtils.bind(this, function(evt) - { - this.graph.tooltipHandler.hide(); - }) - ); -}; - -/** - * Function: isPanningTrigger - * - * Returns true if the given event is a panning trigger for the optional - * given cell. This returns true if control-shift is pressed or if - * <usePopupTrigger> is true and the event is a popup trigger. - */ -mxPanningHandler.prototype.isPanningTrigger = function(me) -{ - var evt = me.getEvent(); - - return (this.useLeftButtonForPanning && (this.ignoreCell || me.getState() == null) && - mxEvent.isLeftMouseButton(evt)) || (mxEvent.isControlDown(evt) && - mxEvent.isShiftDown(evt)) || (this.usePopupTrigger && - mxEvent.isPopupTrigger(evt)); -}; - -/** - * Function: mouseDown - * - * Handles the event by initiating the panning. By consuming the event all - * subsequent events of the gesture are redirected to this handler. - */ -mxPanningHandler.prototype.mouseDown = function(sender, me) -{ - if (!me.isConsumed() && this.isEnabled()) - { - // Hides the popupmenu if is is being displayed - this.hideMenu(); - - this.dx0 = -this.graph.container.scrollLeft; - this.dy0 = -this.graph.container.scrollTop; - - // Checks the event triggers to panning and popupmenu - this.popupTrigger = this.isPopupTrigger(me); - this.panningTrigger = this.isPanningEnabled() && - this.isPanningTrigger(me); - - // Stores the location of the trigger event - this.startX = me.getX(); - this.startY = me.getY(); - - // Displays popup menu on Mac after the mouse was released - if (this.panningTrigger) - { - this.consumePanningTrigger(me); - } - } -}; - -/** - * Function: consumePanningTrigger - * - * Consumes the given <mxMouseEvent> if it was a panning trigger in - * <mouseDown>. The default is to invoke <mxMouseEvent.consume>. Note that this - * will block any further event processing. If you haven't disabled built-in - * context menus and require immediate selection of the cell on mouseDown in - * Safari and/or on the Mac, then use the following code: - * - * (code) - * mxPanningHandler.prototype.consumePanningTrigger = function(me) - * { - * if (me.evt.preventDefault) - * { - * me.evt.preventDefault(); - * } - * - * // Stops event processing in IE - * me.evt.returnValue = false; - * - * // Sets local consumed state - * if (!mxClient.IS_SF && !mxClient.IS_MAC) - * { - * me.consumed = true; - * } - * }; - * (end) - */ -mxPanningHandler.prototype.consumePanningTrigger = function(me) -{ - me.consume(); -}; - -/** - * Function: mouseMove - * - * Handles the event by updating the panning on the graph. - */ -mxPanningHandler.prototype.mouseMove = function(sender, me) -{ - var dx = me.getX() - this.startX; - var dy = me.getY() - this.startY; - - if (this.active) - { - if (this.previewEnabled) - { - // Applies the grid to the panning steps - if (this.useGrid) - { - dx = this.graph.snap(dx); - dy = this.graph.snap(dy); - } - - this.graph.panGraph(dx + this.dx0, dy + this.dy0); - } - - this.fireEvent(new mxEventObject(mxEvent.PAN, 'event', me)); - me.consume(); - } - else if (this.panningTrigger) - { - var tmp = this.active; - - // Panning is activated only if the mouse is moved - // beyond the graph tolerance - this.active = Math.abs(dx) > this.graph.tolerance || - Math.abs(dy) > this.graph.tolerance; - - if (!tmp && this.active) - { - this.fireEvent(new mxEventObject(mxEvent.PAN_START, 'event', me)); - } - } -}; - -/** - * Function: mouseUp - * - * Handles the event by setting the translation on the view or showing the - * popupmenu. - */ -mxPanningHandler.prototype.mouseUp = function(sender, me) -{ - // Shows popup menu if mouse was not moved - var dx = Math.abs(me.getX() - this.startX); - var dy = Math.abs(me.getY() - this.startY); - - if (this.active) - { - if (!this.graph.useScrollbarsForPanning || !mxUtils.hasScrollbars(this.graph.container)) - { - dx = me.getX() - this.startX; - dy = me.getY() - this.startY; - - // Applies the grid to the panning steps - if (this.useGrid) - { - dx = this.graph.snap(dx); - dy = this.graph.snap(dy); - } - - var scale = this.graph.getView().scale; - var t = this.graph.getView().translate; - - this.graph.panGraph(0, 0); - this.panGraph(t.x + dx / scale, t.y + dy / scale); - } - - this.active = false; - this.fireEvent(new mxEventObject(mxEvent.PAN_END, 'event', me)); - me.consume(); - } - else if (this.popupTrigger) - { - if (dx < this.graph.tolerance && dy < this.graph.tolerance) - { - var cell = this.getCellForPopupEvent(me); - - // Selects the cell for which the context menu is being displayed - if (this.graph.isEnabled() && this.selectOnPopup && - cell != null && !this.graph.isCellSelected(cell)) - { - this.graph.setSelectionCell(cell); - } - else if (this.clearSelectionOnBackground && cell == null) - { - this.graph.clearSelection(); - } - - // Hides the tooltip if there is one - this.graph.tooltipHandler.hide(); - var origin = mxUtils.getScrollOrigin(); - var point = new mxPoint(me.getX() + origin.x, - me.getY() + origin.y); - - // Menu is shifted by 1 pixel so that the mouse up event - // is routed via the underlying shape instead of the DIV - this.popup(point.x + 1, point.y + 1, cell, me.getEvent()); - me.consume(); - } - } - - this.panningTrigger = false; - this.popupTrigger = false; -}; - -/** - * Function: getCellForPopupEvent - * - * Hook to return the cell for the mouse up popup trigger handling. - */ -mxPanningHandler.prototype.getCellForPopupEvent = function(me) -{ - return me.getCell(); -}; - -/** - * Function: panGraph - * - * Pans <graph> by the given amount. - */ -mxPanningHandler.prototype.panGraph = function(dx, dy) -{ - this.graph.getView().setTranslate(dx, dy); -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. - */ -mxPanningHandler.prototype.destroy = function() -{ - this.graph.removeMouseListener(this); - - // Supercall - mxPopupMenu.prototype.destroy.apply(this); -}; diff --git a/src/js/handler/mxRubberband.js b/src/js/handler/mxRubberband.js deleted file mode 100644 index f9e7187..0000000 --- a/src/js/handler/mxRubberband.js +++ /dev/null @@ -1,348 +0,0 @@ -/** - * $Id: mxRubberband.js,v 1.48 2012-04-13 12:53:30 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxRubberband - * - * Event handler that selects rectangular regions. This is not built-into - * <mxGraph>. To enable rubberband selection in a graph, use the following code. - * - * Example: - * - * (code) - * var rubberband = new mxRubberband(graph); - * (end) - * - * Constructor: mxRubberband - * - * Constructs an event handler that selects rectangular regions in the graph - * using rubberband selection. - */ -function mxRubberband(graph) -{ - if (graph != null) - { - this.graph = graph; - this.graph.addMouseListener(this); - - // Repaints the marquee after autoscroll - this.panHandler = mxUtils.bind(this, function() - { - this.repaint(); - }); - - this.graph.addListener(mxEvent.PAN, this.panHandler); - - // Automatic deallocation of memory - if (mxClient.IS_IE) - { - mxEvent.addListener(window, 'unload', - mxUtils.bind(this, function() - { - this.destroy(); - }) - ); - } - } -}; - -/** - * Variable: defaultOpacity - * - * Specifies the default opacity to be used for the rubberband div. Default - * is 20. - */ -mxRubberband.prototype.defaultOpacity = 20; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxRubberband.prototype.enabled = true; - -/** - * Variable: div - * - * Holds the DIV element which is currently visible. - */ -mxRubberband.prototype.div = null; - -/** - * Variable: sharedDiv - * - * Holds the DIV element which is used to display the rubberband. - */ -mxRubberband.prototype.sharedDiv = null; - -/** - * Variable: currentX - * - * Holds the value of the x argument in the last call to <update>. - */ -mxRubberband.prototype.currentX = 0; - -/** - * Variable: currentY - * - * Holds the value of the y argument in the last call to <update>. - */ -mxRubberband.prototype.currentY = 0; - -/** - * Function: isEnabled - * - * Returns true if events are handled. This implementation returns - * <enabled>. - */ -mxRubberband.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Function: setEnabled - * - * Enables or disables event handling. This implementation updates - * <enabled>. - */ -mxRubberband.prototype.setEnabled = function(enabled) -{ - this.enabled = enabled; -}; - -/** - * Function: mouseDown - * - * Handles the event by initiating a rubberband selection. By consuming the - * event all subsequent events of the gesture are redirected to this - * handler. - */ -mxRubberband.prototype.mouseDown = function(sender, me) -{ - if (!me.isConsumed() && this.isEnabled() && this.graph.isEnabled() && - (this.graph.isForceMarqueeEvent(me.getEvent()) || me.getState() == null)) - { - var offset = mxUtils.getOffset(this.graph.container); - var origin = mxUtils.getScrollOrigin(this.graph.container); - origin.x -= offset.x; - origin.y -= offset.y; - this.start(me.getX() + origin.x, me.getY() + origin.y); - - // Workaround for rubberband stopping if the mouse leaves the - // graph container in Firefox. - if (mxClient.IS_NS && !mxClient.IS_SF && !mxClient.IS_GC) - { - var container = this.graph.container; - - function createMouseEvent(evt) - { - var me = new mxMouseEvent(evt); - var pt = mxUtils.convertPoint(container, me.getX(), me.getY()); - - me.graphX = pt.x; - me.graphY = pt.y; - - return me; - }; - - this.dragHandler = mxUtils.bind(this, function(evt) - { - this.mouseMove(this.graph, createMouseEvent(evt)); - }); - - this.dropHandler = mxUtils.bind(this, function(evt) - { - this.mouseUp(this.graph, createMouseEvent(evt)); - }); - - mxEvent.addListener(document, 'mousemove', this.dragHandler); - mxEvent.addListener(document, 'mouseup', this.dropHandler); - } - - // Does not prevent the default for this event so that the - // event processing chain is still executed even if we start - // rubberbanding. This is required eg. in ExtJs to hide the - // current context menu. In mouseMove we'll make sure we're - // not selecting anything while we're rubberbanding. - me.consume(false); - } -}; - -/** - * Function: start - * - * Sets the start point for the rubberband selection. - */ -mxRubberband.prototype.start = function(x, y) -{ - this.first = new mxPoint(x, y); -}; - -/** - * Function: mouseMove - * - * Handles the event by updating therubberband selection. - */ -mxRubberband.prototype.mouseMove = function(sender, me) -{ - if (!me.isConsumed() && this.first != null) - { - var origin = mxUtils.getScrollOrigin(this.graph.container); - var offset = mxUtils.getOffset(this.graph.container); - origin.x -= offset.x; - origin.y -= offset.y; - var x = me.getX() + origin.x; - var y = me.getY() + origin.y; - var dx = this.first.x - x; - var dy = this.first.y - y; - var tol = this.graph.tolerance; - - if (this.div != null || Math.abs(dx) > tol || Math.abs(dy) > tol) - { - if (this.div == null) - { - this.div = this.createShape(); - } - - // Clears selection while rubberbanding. This is required because - // the event is not consumed in mouseDown. - mxUtils.clearSelection(); - - this.update(x, y); - me.consume(); - } - } -}; - -/** - * Function: createShape - * - * Creates the rubberband selection shape. - */ -mxRubberband.prototype.createShape = function() -{ - if (this.sharedDiv == null) - { - this.sharedDiv = document.createElement('div'); - this.sharedDiv.className = 'mxRubberband'; - mxUtils.setOpacity(this.sharedDiv, this.defaultOpacity); - } - - this.graph.container.appendChild(this.sharedDiv); - - return this.sharedDiv; -}; - -/** - * Function: mouseUp - * - * Handles the event by selecting the region of the rubberband using - * <mxGraph.selectRegion>. - */ -mxRubberband.prototype.mouseUp = function(sender, me) -{ - var execute = this.div != null; - this.reset(); - - if (execute) - { - var rect = new mxRectangle(this.x, this.y, this.width, this.height); - this.graph.selectRegion(rect, me.getEvent()); - me.consume(); - } -}; - -/** - * Function: reset - * - * Resets the state of the rubberband selection. - */ -mxRubberband.prototype.reset = function() -{ - if (this.div != null) - { - this.div.parentNode.removeChild(this.div); - } - - if (this.dragHandler != null) - { - mxEvent.removeListener(document, 'mousemove', this.dragHandler); - this.dragHandler = null; - } - - if (this.dropHandler != null) - { - mxEvent.removeListener(document, 'mouseup', this.dropHandler); - this.dropHandler = null; - } - - this.currentX = 0; - this.currentY = 0; - this.first = null; - this.div = null; -}; - -/** - * Function: update - * - * Sets <currentX> and <currentY> and calls <repaint>. - */ -mxRubberband.prototype.update = function(x, y) -{ - this.currentX = x; - this.currentY = y; - - this.repaint(); -}; - -/** - * Function: repaint - * - * Computes the bounding box and updates the style of the <div>. - */ -mxRubberband.prototype.repaint = function() -{ - if (this.div != null) - { - var x = this.currentX - this.graph.panDx; - var y = this.currentY - this.graph.panDy; - - this.x = Math.min(this.first.x, x); - this.y = Math.min(this.first.y, y); - this.width = Math.max(this.first.x, x) - this.x; - this.height = Math.max(this.first.y, y) - this.y; - - var dx = (mxClient.IS_VML) ? this.graph.panDx : 0; - var dy = (mxClient.IS_VML) ? this.graph.panDy : 0; - - this.div.style.left = (this.x + dx) + 'px'; - this.div.style.top = (this.y + dy) + 'px'; - this.div.style.width = Math.max(1, this.width) + 'px'; - this.div.style.height = Math.max(1, this.height) + 'px'; - } -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. This does - * normally not need to be called, it is called automatically when the - * window unloads. - */ -mxRubberband.prototype.destroy = function() -{ - if (!this.destroyed) - { - this.destroyed = true; - this.graph.removeMouseListener(this); - this.graph.removeListener(this.panHandler); - this.reset(); - - if (this.sharedDiv != null) - { - this.sharedDiv = null; - } - } -}; diff --git a/src/js/handler/mxSelectionCellsHandler.js b/src/js/handler/mxSelectionCellsHandler.js deleted file mode 100644 index 800d718..0000000 --- a/src/js/handler/mxSelectionCellsHandler.js +++ /dev/null @@ -1,260 +0,0 @@ -/** - * $Id: mxSelectionCellsHandler.js,v 1.5 2012-08-10 11:35:06 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxSelectionCellsHandler - * - * An event handler that manages cell handlers and invokes their mouse event - * processing functions. - * - * Group: Events - * - * Event: mxEvent.ADD - * - * Fires if a cell has been added to the selection. The <code>state</code> - * property contains the <mxCellState> that has been added. - * - * Event: mxEvent.REMOVE - * - * Fires if a cell has been remove from the selection. The <code>state</code> - * property contains the <mxCellState> that has been removed. - * - * Parameters: - * - * graph - Reference to the enclosing <mxGraph>. - */ -function mxSelectionCellsHandler(graph) -{ - this.graph = graph; - this.handlers = new mxDictionary(); - this.graph.addMouseListener(this); - - this.refreshHandler = mxUtils.bind(this, function(sender, evt) - { - if (this.isEnabled()) - { - this.refresh(); - } - }); - - this.graph.getSelectionModel().addListener(mxEvent.CHANGE, this.refreshHandler); - this.graph.getModel().addListener(mxEvent.CHANGE, this.refreshHandler); - this.graph.getView().addListener(mxEvent.SCALE, this.refreshHandler); - this.graph.getView().addListener(mxEvent.TRANSLATE, this.refreshHandler); - this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.refreshHandler); - this.graph.getView().addListener(mxEvent.DOWN, this.refreshHandler); - this.graph.getView().addListener(mxEvent.UP, this.refreshHandler); -}; - -/** - * Extends mxEventSource. - */ -mxSelectionCellsHandler.prototype = new mxEventSource(); -mxSelectionCellsHandler.prototype.constructor = mxSelectionCellsHandler; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxSelectionCellsHandler.prototype.graph = null; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxSelectionCellsHandler.prototype.enabled = true; - -/** - * Variable: refreshHandler - * - * Keeps a reference to an event listener for later removal. - */ -mxSelectionCellsHandler.prototype.refreshHandler = null; - -/** - * Variable: maxHandlers - * - * Defines the maximum number of handlers to paint individually. Default is 100. - */ -mxSelectionCellsHandler.prototype.maxHandlers = 100; - -/** - * Variable: handlers - * - * <mxDictionary> that maps from cells to handlers. - */ -mxSelectionCellsHandler.prototype.handlers = null; - -/** - * Function: isEnabled - * - * Returns <enabled>. - */ -mxSelectionCellsHandler.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Function: setEnabled - * - * Sets <enabled>. - */ -mxSelectionCellsHandler.prototype.setEnabled = function(value) -{ - this.enabled = value; -}; - -/** - * Function: getHandler - * - * Returns the handler for the given cell. - */ -mxSelectionCellsHandler.prototype.getHandler = function(cell) -{ - return this.handlers.get(cell); -}; - -/** - * Function: reset - * - * Resets all handlers. - */ -mxSelectionCellsHandler.prototype.reset = function() -{ - this.handlers.visit(function(key, handler) - { - handler.reset.apply(handler); - }); -}; - -/** - * Function: refresh - * - * Reloads or updates all handlers. - */ -mxSelectionCellsHandler.prototype.refresh = function() -{ - // Removes all existing handlers - var oldHandlers = this.handlers; - this.handlers = new mxDictionary(); - - // Creates handles for all selection cells - var tmp = this.graph.getSelectionCells(); - - for (var i = 0; i < tmp.length; i++) - { - var state = this.graph.view.getState(tmp[i]); - - if (state != null) - { - var handler = oldHandlers.remove(tmp[i]); - - if (handler != null) - { - if (handler.state != state) - { - handler.destroy(); - handler = null; - } - else - { - handler.redraw(); - } - } - - if (handler == null) - { - handler = this.graph.createHandler(state); - this.fireEvent(new mxEventObject(mxEvent.ADD, 'state', state)); - } - - if (handler != null) - { - this.handlers.put(tmp[i], handler); - } - } - } - - // Destroys all unused handlers - oldHandlers.visit(mxUtils.bind(this, function(key, handler) - { - this.fireEvent(new mxEventObject(mxEvent.REMOVE, 'state', handler.state)); - handler.destroy(); - })); -}; - -/** - * Function: mouseDown - * - * Redirects the given event to the handlers. - */ -mxSelectionCellsHandler.prototype.mouseDown = function(sender, me) -{ - if (this.graph.isEnabled() && this.isEnabled()) - { - var args = [sender, me]; - - this.handlers.visit(function(key, handler) - { - handler.mouseDown.apply(handler, args); - }); - } -}; - -/** - * Function: mouseMove - * - * Redirects the given event to the handlers. - */ -mxSelectionCellsHandler.prototype.mouseMove = function(sender, me) -{ - if (this.graph.isEnabled() && this.isEnabled()) - { - var args = [sender, me]; - - this.handlers.visit(function(key, handler) - { - handler.mouseMove.apply(handler, args); - }); - } -}; - -/** - * Function: mouseUp - * - * Redirects the given event to the handlers. - */ -mxSelectionCellsHandler.prototype.mouseUp = function(sender, me) -{ - if (this.graph.isEnabled() && this.isEnabled()) - { - var args = [sender, me]; - - this.handlers.visit(function(key, handler) - { - handler.mouseUp.apply(handler, args); - }); - } -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. - */ -mxSelectionCellsHandler.prototype.destroy = function() -{ - this.graph.removeMouseListener(this); - - if (this.refreshHandler != null) - { - this.graph.getSelectionModel().removeListener(this.refreshHandler); - this.graph.getModel().removeListener(this.refreshHandler); - this.graph.getView().removeListener(this.refreshHandler); - this.refreshHandler = null; - } -}; diff --git a/src/js/handler/mxTooltipHandler.js b/src/js/handler/mxTooltipHandler.js deleted file mode 100644 index 4e34a13..0000000 --- a/src/js/handler/mxTooltipHandler.js +++ /dev/null @@ -1,317 +0,0 @@ -/** - * $Id: mxTooltipHandler.js,v 1.51 2011-03-31 10:11:17 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxTooltipHandler - * - * Graph event handler that displays tooltips. <mxGraph.getTooltip> is used to - * get the tooltip for a cell or handle. This handler is built-into - * <mxGraph.tooltipHandler> and enabled using <mxGraph.setTooltips>. - * - * Example: - * - * (code> - * new mxTooltipHandler(graph); - * (end) - * - * Constructor: mxTooltipHandler - * - * Constructs an event handler that displays tooltips with the specified - * delay (in milliseconds). If no delay is specified then a default delay - * of 500 ms (0.5 sec) is used. - * - * Parameters: - * - * graph - Reference to the enclosing <mxGraph>. - * delay - Optional delay in milliseconds. - */ -function mxTooltipHandler(graph, delay) -{ - if (graph != null) - { - this.graph = graph; - this.delay = delay || 500; - this.graph.addMouseListener(this); - } -}; - -/** - * Variable: zIndex - * - * Specifies the zIndex for the tooltip and its shadow. Default is 10005. - */ -mxTooltipHandler.prototype.zIndex = 10005; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxTooltipHandler.prototype.graph = null; - -/** - * Variable: delay - * - * Delay to show the tooltip in milliseconds. Default is 500. - */ -mxTooltipHandler.prototype.delay = null; - -/** - * Variable: hideOnHover - * - * Specifies if the tooltip should be hidden if the mouse is moved over the - * current cell. Default is false. - */ -mxTooltipHandler.prototype.hideOnHover = false; - -/** - * Variable: enabled - * - * Specifies if events are handled. Default is true. - */ -mxTooltipHandler.prototype.enabled = true; - -/** - * Function: isEnabled - * - * Returns true if events are handled. This implementation - * returns <enabled>. - */ -mxTooltipHandler.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Function: setEnabled - * - * Enables or disables event handling. This implementation - * updates <enabled>. - */ -mxTooltipHandler.prototype.setEnabled = function(enabled) -{ - this.enabled = enabled; -}; - -/** - * Function: isHideOnHover - * - * Returns <hideOnHover>. - */ -mxTooltipHandler.prototype.isHideOnHover = function() -{ - return this.hideOnHover; -}; - -/** - * Function: setHideOnHover - * - * Sets <hideOnHover>. - */ -mxTooltipHandler.prototype.setHideOnHover = function(value) -{ - this.hideOnHover = value; -}; - -/** - * Function: init - * - * Initializes the DOM nodes required for this tooltip handler. - */ -mxTooltipHandler.prototype.init = function() -{ - if (document.body != null) - { - this.div = document.createElement('div'); - this.div.className = 'mxTooltip'; - this.div.style.visibility = 'hidden'; - this.div.style.zIndex = this.zIndex; - - document.body.appendChild(this.div); - - mxEvent.addListener(this.div, 'mousedown', - mxUtils.bind(this, function(evt) - { - this.hideTooltip(); - }) - ); - } -}; - -/** - * Function: mouseDown - * - * Handles the event by initiating a rubberband selection. By consuming the - * event all subsequent events of the gesture are redirected to this - * handler. - */ -mxTooltipHandler.prototype.mouseDown = function(sender, me) -{ - this.reset(me, false); - this.hideTooltip(); -}; - -/** - * Function: mouseMove - * - * Handles the event by updating the rubberband selection. - */ -mxTooltipHandler.prototype.mouseMove = function(sender, me) -{ - if (me.getX() != this.lastX || me.getY() != this.lastY) - { - this.reset(me, true); - - if (this.isHideOnHover() || me.getState() != this.state || (me.getSource() != this.node && - (!this.stateSource || (me.getState() != null && this.stateSource == - (me.isSource(me.getState().shape) || !me.isSource(me.getState().text)))))) - { - this.hideTooltip(); - } - } - - this.lastX = me.getX(); - this.lastY = me.getY(); -}; - -/** - * Function: mouseUp - * - * Handles the event by resetting the tooltip timer or hiding the existing - * tooltip. - */ -mxTooltipHandler.prototype.mouseUp = function(sender, me) -{ - this.reset(me, true); - this.hideTooltip(); -}; - - -/** - * Function: resetTimer - * - * Resets the timer. - */ -mxTooltipHandler.prototype.resetTimer = function() -{ - if (this.thread != null) - { - window.clearTimeout(this.thread); - this.thread = null; - } -}; - -/** - * Function: reset - * - * Resets and/or restarts the timer to trigger the display of the tooltip. - */ -mxTooltipHandler.prototype.reset = function(me, restart) -{ - this.resetTimer(); - - if (restart && this.isEnabled() && me.getState() != null && (this.div == null || - this.div.style.visibility == 'hidden')) - { - var state = me.getState(); - var node = me.getSource(); - var x = me.getX(); - var y = me.getY(); - var stateSource = me.isSource(state.shape) || me.isSource(state.text); - - this.thread = window.setTimeout(mxUtils.bind(this, function() - { - if (!this.graph.isEditing() && !this.graph.panningHandler.isMenuShowing()) - { - // Uses information from inside event cause using the event at - // this (delayed) point in time is not possible in IE as it no - // longer contains the required information (member not found) - var tip = this.graph.getTooltip(state, node, x, y); - this.show(tip, x, y); - this.state = state; - this.node = node; - this.stateSource = stateSource; - } - }), this.delay); - } -}; - -/** - * Function: hide - * - * Hides the tooltip and resets the timer. - */ -mxTooltipHandler.prototype.hide = function() -{ - this.resetTimer(); - this.hideTooltip(); -}; - -/** - * Function: hideTooltip - * - * Hides the tooltip. - */ -mxTooltipHandler.prototype.hideTooltip = function() -{ - if (this.div != null) - { - this.div.style.visibility = 'hidden'; - } -}; - -/** - * Function: show - * - * Shows the tooltip for the specified cell and optional index at the - * specified location (with a vertical offset of 10 pixels). - */ -mxTooltipHandler.prototype.show = function(tip, x, y) -{ - if (tip != null && tip.length > 0) - { - // Initializes the DOM nodes if required - if (this.div == null) - { - this.init(); - } - - var origin = mxUtils.getScrollOrigin(); - - this.div.style.left = (x + origin.x) + 'px'; - this.div.style.top = (y + mxConstants.TOOLTIP_VERTICAL_OFFSET + - origin.y) + 'px'; - - if (!mxUtils.isNode(tip)) - { - this.div.innerHTML = tip.replace(/\n/g, '<br>'); - } - else - { - this.div.innerHTML = ''; - this.div.appendChild(tip); - } - - this.div.style.visibility = ''; - mxUtils.fit(this.div); - } -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. - */ -mxTooltipHandler.prototype.destroy = function() -{ - this.graph.removeMouseListener(this); - mxEvent.release(this.div); - - if (this.div != null && this.div.parentNode != null) - { - this.div.parentNode.removeChild(this.div); - } - - this.div = null; -}; diff --git a/src/js/handler/mxVertexHandler.js b/src/js/handler/mxVertexHandler.js deleted file mode 100644 index 0b12e27..0000000 --- a/src/js/handler/mxVertexHandler.js +++ /dev/null @@ -1,753 +0,0 @@ -/** - * $Id: mxVertexHandler.js,v 1.107 2012-11-20 09:06:07 gaudenz Exp $ - * Copyright (c) 2006-2010, JGraph Ltd - */ -/** - * Class: mxVertexHandler - * - * Event handler for resizing cells. This handler is automatically created in - * <mxGraph.createHandler>. - * - * Constructor: mxVertexHandler - * - * Constructs an event handler that allows to resize vertices - * and groups. - * - * Parameters: - * - * state - <mxCellState> of the cell to be resized. - */ -function mxVertexHandler(state) -{ - if (state != null) - { - this.state = state; - this.init(); - } -}; - -/** - * Variable: graph - * - * Reference to the enclosing <mxGraph>. - */ -mxVertexHandler.prototype.graph = null; - -/** - * Variable: state - * - * Reference to the <mxCellState> being modified. - */ -mxVertexHandler.prototype.state = null; - -/** - * Variable: singleSizer - * - * Specifies if only one sizer handle at the bottom, right corner should be - * used. Default is false. - */ -mxVertexHandler.prototype.singleSizer = false; - -/** - * Variable: index - * - * Holds the index of the current handle. - */ -mxVertexHandler.prototype.index = null; - -/** - * Variable: allowHandleBoundsCheck - * - * Specifies if the bounds of handles should be used for hit-detection in IE - * Default is true. - */ -mxVertexHandler.prototype.allowHandleBoundsCheck = true; - -/** - * Variable: crisp - * - * Specifies if the selection bounds and handles should be rendered in crisp - * mode. Default is true. - */ -mxVertexHandler.prototype.crisp = true; - -/** - * Variable: handleImage - * - * Optional <mxImage> to be used as handles. Default is null. - */ -mxVertexHandler.prototype.handleImage = null; - -/** - * Variable: tolerance - * - * Optional tolerance for hit-detection in <getHandleForEvent>. Default is 0. - */ -mxVertexHandler.prototype.tolerance = 0; - -/** - * Function: init - * - * Initializes the shapes required for this vertex handler. - */ -mxVertexHandler.prototype.init = function() -{ - this.graph = this.state.view.graph; - this.selectionBounds = this.getSelectionBounds(this.state); - this.bounds = new mxRectangle(this.selectionBounds.x, this.selectionBounds.y, - this.selectionBounds.width, this.selectionBounds.height); - this.selectionBorder = this.createSelectionShape(this.bounds); - this.selectionBorder.dialect = - (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - this.selectionBorder.init(this.graph.getView().getOverlayPane()); - - // Event-transparency - if (this.selectionBorder.dialect == mxConstants.DIALECT_SVG) - { - this.selectionBorder.node.setAttribute('pointer-events', 'none'); - } - else - { - this.selectionBorder.node.style.background = ''; - } - - if (this.graph.isCellMovable(this.state.cell)) - { - this.selectionBorder.node.style.cursor = mxConstants.CURSOR_MOVABLE_VERTEX; - } - - mxEvent.redirectMouseEvents(this.selectionBorder.node, this.graph, this.state); - - // Adds the sizer handles - if (mxGraphHandler.prototype.maxCells <= 0 || - this.graph.getSelectionCount() < mxGraphHandler.prototype.maxCells) - { - var resizable = this.graph.isCellResizable(this.state.cell); - this.sizers = []; - - if (resizable || (this.graph.isLabelMovable(this.state.cell) && - this.state.width >= 2 && this.state.height >= 2)) - { - var i = 0; - - if (resizable) - { - if (!this.singleSizer) - { - this.sizers.push(this.createSizer('nw-resize', i++)); - this.sizers.push(this.createSizer('n-resize', i++)); - this.sizers.push(this.createSizer('ne-resize', i++)); - this.sizers.push(this.createSizer('w-resize', i++)); - this.sizers.push(this.createSizer('e-resize', i++)); - this.sizers.push(this.createSizer('sw-resize', i++)); - this.sizers.push(this.createSizer('s-resize', i++)); - } - - this.sizers.push(this.createSizer('se-resize', i++)); - } - - var geo = this.graph.model.getGeometry(this.state.cell); - - if (geo != null && !geo.relative && !this.graph.isSwimlane(this.state.cell) && - this.graph.isLabelMovable(this.state.cell)) - { - // Marks this as the label handle for getHandleForEvent - this.labelShape = this.createSizer(mxConstants.CURSOR_LABEL_HANDLE, - mxEvent.LABEL_HANDLE, mxConstants.LABEL_HANDLE_SIZE, - mxConstants.LABEL_HANDLE_FILLCOLOR); - this.sizers.push(this.labelShape); - } - } - else if (this.graph.isCellMovable(this.state.cell) && !this.graph.isCellResizable(this.state.cell) && - this.state.width < 2 && this.state.height < 2) - { - this.labelShape = this.createSizer(mxConstants.CURSOR_MOVABLE_VERTEX, - null, null, mxConstants.LABEL_HANDLE_FILLCOLOR); - this.sizers.push(this.labelShape); - } - } - - this.redraw(); -}; - -/** - * Function: getSelectionBounds - * - * Returns the mxRectangle that defines the bounds of the selection - * border. - */ -mxVertexHandler.prototype.getSelectionBounds = function(state) -{ - return new mxRectangle(state.x, state.y, state.width, state.height); -}; - -/** - * Function: createSelectionShape - * - * Creates the shape used to draw the selection border. - */ -mxVertexHandler.prototype.createSelectionShape = function(bounds) -{ - var shape = new mxRectangleShape(bounds, null, this.getSelectionColor()); - shape.strokewidth = this.getSelectionStrokeWidth(); - shape.isDashed = this.isSelectionDashed(); - shape.crisp = this.crisp; - - return shape; -}; - -/** - * Function: getSelectionColor - * - * Returns <mxConstants.VERTEX_SELECTION_COLOR>. - */ -mxVertexHandler.prototype.getSelectionColor = function() -{ - return mxConstants.VERTEX_SELECTION_COLOR; -}; - -/** - * Function: getSelectionStrokeWidth - * - * Returns <mxConstants.VERTEX_SELECTION_STROKEWIDTH>. - */ -mxVertexHandler.prototype.getSelectionStrokeWidth = function() -{ - return mxConstants.VERTEX_SELECTION_STROKEWIDTH; -}; - -/** - * Function: isSelectionDashed - * - * Returns <mxConstants.VERTEX_SELECTION_DASHED>. - */ -mxVertexHandler.prototype.isSelectionDashed = function() -{ - return mxConstants.VERTEX_SELECTION_DASHED; -}; - -/** - * Function: createSizer - * - * Creates a sizer handle for the specified cursor and index and returns - * the new <mxRectangleShape> that represents the handle. - */ -mxVertexHandler.prototype.createSizer = function(cursor, index, size, fillColor) -{ - size = size || mxConstants.HANDLE_SIZE; - - var bounds = new mxRectangle(0, 0, size, size); - var sizer = this.createSizerShape(bounds, index, fillColor); - - if (this.state.text != null && this.state.text.node.parentNode == this.graph.container) - { - sizer.bounds.height -= 1; - sizer.bounds.width -= 1; - sizer.dialect = mxConstants.DIALECT_STRICTHTML; - sizer.init(this.graph.container); - } - else - { - sizer.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - sizer.init(this.graph.getView().getOverlayPane()); - } - - mxEvent.redirectMouseEvents(sizer.node, this.graph, this.state); - - if (this.graph.isEnabled()) - { - sizer.node.style.cursor = cursor; - } - - if (!this.isSizerVisible(index)) - { - sizer.node.style.visibility = 'hidden'; - } - - return sizer; -}; - -/** - * Function: isSizerVisible - * - * Returns true if the sizer for the given index is visible. - * This returns true for all given indices. - */ -mxVertexHandler.prototype.isSizerVisible = function(index) -{ - return true; -}; - -/** - * Function: createSizerShape - * - * Creates the shape used for the sizer handle for the specified bounds and - * index. - */ -mxVertexHandler.prototype.createSizerShape = function(bounds, index, fillColor) -{ - if (this.handleImage != null) - { - bounds.width = this.handleImage.width; - bounds.height = this.handleImage.height; - - return new mxImageShape(bounds, this.handleImage.src); - } - else - { - var shape = new mxRectangleShape(bounds, - fillColor || mxConstants.HANDLE_FILLCOLOR, - mxConstants.HANDLE_STROKECOLOR); - shape.crisp = this.crisp; - - return shape; - } -}; - -/** - * Function: createBounds - * - * Helper method to create an <mxRectangle> around the given centerpoint - * with a width and height of 2*s or 6, if no s is given. - */ -mxVertexHandler.prototype.moveSizerTo = function(shape, x, y) -{ - if (shape != null) - { - shape.bounds.x = x - shape.bounds.width / 2; - shape.bounds.y = y - shape.bounds.height / 2; - shape.redraw(); - } -}; - -/** - * Function: getHandleForEvent - * - * Returns the index of the handle for the given event. This returns the index - * of the sizer from where the event originated or <mxEvent.LABEL_INDEX>. - */ -mxVertexHandler.prototype.getHandleForEvent = function(me) -{ - if (me.isSource(this.labelShape)) - { - return mxEvent.LABEL_HANDLE; - } - - if (this.sizers != null) - { - // Connection highlight may consume events before they reach sizer handle - var tol = this.tolerance; - var hit = (this.allowHandleBoundsCheck && (mxClient.IS_IE || tol > 0)) ? - new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol) : null; - - for (var i = 0; i < this.sizers.length; i++) - { - if (me.isSource(this.sizers[i]) || (hit != null && - this.sizers[i].node.style.visibility != 'hidden' && - mxUtils.intersects(this.sizers[i].bounds, hit))) - { - return i; - } - } - } - - return null; -}; - -/** - * Function: mouseDown - * - * Handles the event if a handle has been clicked. By consuming the - * event all subsequent events of the gesture are redirected to this - * handler. - */ -mxVertexHandler.prototype.mouseDown = function(sender, me) -{ - if (!me.isConsumed() && this.graph.isEnabled() && !this.graph.isForceMarqueeEvent(me.getEvent()) && - (this.tolerance > 0 || me.getState() == this.state)) - { - var handle = this.getHandleForEvent(me); - - if (handle != null) - { - this.start(me.getX(), me.getY(), handle); - me.consume(); - } - } -}; - -/** - * Function: start - * - * Starts the handling of the mouse gesture. - */ -mxVertexHandler.prototype.start = function(x, y, index) -{ - var pt = mxUtils.convertPoint(this.graph.container, x, y); - this.startX = pt.x; - this.startY = pt.y; - this.index = index; - - // Creates a preview that can be on top of any HTML label - this.selectionBorder.node.style.visibility = 'hidden'; - this.preview = this.createSelectionShape(this.bounds); - - if (this.state.text != null && this.state.text.node.parentNode == this.graph.container) - { - this.preview.dialect = mxConstants.DIALECT_STRICTHTML; - this.preview.init(this.graph.container); - } - else - { - this.preview.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? - mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; - this.preview.init(this.graph.view.getOverlayPane()); - } -}; - -/** - * Function: mouseMove - * - * Handles the event by updating the preview. - */ -mxVertexHandler.prototype.mouseMove = function(sender, me) -{ - if (!me.isConsumed() && this.index != null) - { - var point = new mxPoint(me.getGraphX(), me.getGraphY()); - var gridEnabled = this.graph.isGridEnabledEvent(me.getEvent()); - var scale = this.graph.getView().scale; - - if (this.index == mxEvent.LABEL_HANDLE) - { - if (gridEnabled) - { - point.x = this.graph.snap(point.x / scale) * scale; - point.y = this.graph.snap(point.y / scale) * scale; - } - - this.moveSizerTo(this.sizers[this.sizers.length - 1], point.x, point.y); - me.consume(); - } - else if (this.index != null) - { - var dx = point.x - this.startX; - var dy = point.y - this.startY; - var tr = this.graph.view.translate; - this.bounds = this.union(this.selectionBounds, dx, dy, this.index, gridEnabled, scale, tr); - this.drawPreview(); - me.consume(); - } - } - // Workaround for disabling the connect highlight when over handle - else if (this.getHandleForEvent(me) != null) - { - me.consume(false); - } -}; - -/** - * Function: mouseUp - * - * Handles the event by applying the changes to the geometry. - */ -mxVertexHandler.prototype.mouseUp = function(sender, me) -{ - if (!me.isConsumed() && this.index != null && this.state != null) - { - var point = new mxPoint(me.getGraphX(), me.getGraphY()); - var scale = this.graph.getView().scale; - - var gridEnabled = this.graph.isGridEnabledEvent(me.getEvent()); - var dx = (point.x - this.startX) / scale; - var dy = (point.y - this.startY) / scale; - - this.resizeCell(this.state.cell, dx, dy, this.index, gridEnabled); - this.reset(); - me.consume(); - } -}; - -/** - * Function: reset - * - * Resets the state of this handler. - */ -mxVertexHandler.prototype.reset = function() -{ - this.index = null; - - if (this.preview != null) - { - this.preview.destroy(); - this.preview = null; - } - - // Checks if handler has been destroyed - if (this.selectionBorder != null) - { - this.selectionBounds = this.getSelectionBounds(this.state); - this.selectionBorder.node.style.visibility = 'visible'; - this.bounds = new mxRectangle(this.selectionBounds.x, this.selectionBounds.y, - this.selectionBounds.width, this.selectionBounds.height); - this.drawPreview(); - } -}; - -/** - * Function: resizeCell - * - * Uses the given vector to change the bounds of the given cell - * in the graph using <mxGraph.resizeCell>. - */ -mxVertexHandler.prototype.resizeCell = function(cell, dx, dy, index, gridEnabled) -{ - var geo = this.graph.model.getGeometry(cell); - - if (index == mxEvent.LABEL_HANDLE) - { - var scale = this.graph.view.scale; - dx = (this.labelShape.bounds.getCenterX() - this.startX) / scale; - dy = (this.labelShape.bounds.getCenterY() - this.startY) / scale; - - geo = geo.clone(); - - if (geo.offset == null) - { - geo.offset = new mxPoint(dx, dy); - } - else - { - geo.offset.x += dx; - geo.offset.y += dy; - } - - this.graph.model.setGeometry(cell, geo); - } - else - { - var bounds = this.union(geo, dx, dy, index, gridEnabled, 1, new mxPoint(0, 0)); - this.graph.resizeCell(cell, bounds); - } -}; - -/** - * Function: union - * - * Returns the union of the given bounds and location for the specified - * handle index. - * - * To override this to limit the size of vertex via a minWidth/-Height style, - * the following code can be used. - * - * (code) - * var vertexHandlerUnion = mxVertexHandler.prototype.union; - * mxVertexHandler.prototype.union = function(bounds, dx, dy, index, gridEnabled, scale, tr) - * { - * var result = vertexHandlerUnion.apply(this, arguments); - * - * result.width = Math.max(result.width, mxUtils.getNumber(this.state.style, 'minWidth', 0)); - * result.height = Math.max(result.height, mxUtils.getNumber(this.state.style, 'minHeight', 0)); - * - * return result; - * }; - * (end) - * - * The minWidth/-Height style can then be used as follows: - * - * (code) - * graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30, 'minWidth=100;minHeight=100;'); - * (end) - */ -mxVertexHandler.prototype.union = function(bounds, dx, dy, index, gridEnabled, scale, tr) -{ - if (this.singleSizer) - { - var x = bounds.x + bounds.width + dx; - var y = bounds.y + bounds.height + dy; - - if (gridEnabled) - { - x = this.graph.snap(x / scale) * scale; - y = this.graph.snap(y / scale) * scale; - } - - var rect = new mxRectangle(bounds.x, bounds.y, 0, 0); - rect.add(new mxRectangle(x, y, 0, 0)); - - return rect; - } - else - { - var left = bounds.x - tr.x * scale; - var right = left + bounds.width; - var top = bounds.y - tr.y * scale; - var bottom = top + bounds.height; - - if (index > 4 /* Bottom Row */) - { - bottom = bottom + dy; - - if (gridEnabled) - { - bottom = this.graph.snap(bottom / scale) * scale; - } - } - else if (index < 3 /* Top Row */) - { - top = top + dy; - - if (gridEnabled) - { - top = this.graph.snap(top / scale) * scale; - } - } - - if (index == 0 || index == 3 || index == 5 /* Left */) - { - left += dx; - - if (gridEnabled) - { - left = this.graph.snap(left / scale) * scale; - } - } - else if (index == 2 || index == 4 || index == 7 /* Right */) - { - right += dx; - - if (gridEnabled) - { - right = this.graph.snap(right / scale) * scale; - } - } - - var width = right - left; - var height = bottom - top; - - // Flips over left side - if (width < 0) - { - left += width; - width = Math.abs(width); - } - - // Flips over top side - if (height < 0) - { - top += height; - height = Math.abs(height); - } - - return new mxRectangle(left + tr.x * scale, top + tr.y * scale, width, height); - } -}; - -/** - * Function: redraw - * - * Redraws the handles and the preview. - */ -mxVertexHandler.prototype.redraw = function() -{ - this.selectionBounds = this.getSelectionBounds(this.state); - this.bounds = new mxRectangle(this.selectionBounds.x, this.selectionBounds.y, - this.selectionBounds.width, this.selectionBounds.height); - - if (this.sizers != null) - { - var s = this.state; - var r = s.x + s.width; - var b = s.y + s.height; - - if (this.singleSizer) - { - this.moveSizerTo(this.sizers[0], r, b); - } - else - { - var cx = s.x + s.width / 2; - var cy = s.y + s.height / 2; - - if (this.sizers.length > 1) - { - this.moveSizerTo(this.sizers[0], s.x, s.y); - this.moveSizerTo(this.sizers[1], cx, s.y); - this.moveSizerTo(this.sizers[2], r, s.y); - this.moveSizerTo(this.sizers[3], s.x, cy); - this.moveSizerTo(this.sizers[4], r, cy); - this.moveSizerTo(this.sizers[5], s.x, b); - this.moveSizerTo(this.sizers[6], cx, b); - this.moveSizerTo(this.sizers[7], r, b); - this.moveSizerTo(this.sizers[8], - cx + s.absoluteOffset.x, - cy + s.absoluteOffset.y); - } - else if (this.state.width >= 2 && this.state.height >= 2) - { - this.moveSizerTo(this.sizers[0], - cx + s.absoluteOffset.x, - cy + s.absoluteOffset.y); - } - else - { - this.moveSizerTo(this.sizers[0], s.x, s.y); - } - } - } - - this.drawPreview(); -}; - -/** - * Function: drawPreview - * - * Redraws the preview. - */ -mxVertexHandler.prototype.drawPreview = function() -{ - if (this.preview != null) - { - this.preview.bounds = this.bounds; - - if (this.preview.node.parentNode == this.graph.container) - { - this.preview.bounds.width = Math.max(0, this.preview.bounds.width - 1); - this.preview.bounds.height = Math.max(0, this.preview.bounds.height - 1); - } - - this.preview.redraw(); - } - - this.selectionBorder.bounds = this.bounds; - this.selectionBorder.redraw(); -}; - -/** - * Function: destroy - * - * Destroys the handler and all its resources and DOM nodes. - */ -mxVertexHandler.prototype.destroy = function() -{ - if (this.preview != null) - { - this.preview.destroy(); - this.preview = null; - } - - this.selectionBorder.destroy(); - this.selectionBorder = null; - this.labelShape = null; - - if (this.sizers != null) - { - for (var i = 0; i < this.sizers.length; i++) - { - this.sizers[i].destroy(); - this.sizers[i] = null; - } - } -}; |