summaryrefslogtreecommitdiff
path: root/src/js/handler/mxEdgeHandler.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/handler/mxEdgeHandler.js')
-rw-r--r--src/js/handler/mxEdgeHandler.js1529
1 files changed, 0 insertions, 1529 deletions
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;
- }
- }
- }
-};