summaryrefslogtreecommitdiff
path: root/src/js/view/mxEdgeStyle.js
diff options
context:
space:
mode:
authoradhitya2016-04-11 15:10:54 +0000
committeradhitya2016-04-11 15:10:54 +0000
commit92f3207b50a1caca07df5c5b238212af3358905b (patch)
tree38c92f9649c6f1016d2ef70fa2fd33c86b437cba /src/js/view/mxEdgeStyle.js
parentab5fb6e125d82fdd5818aea3ce370c43c2293ddd (diff)
downloadxcos-on-web-92f3207b50a1caca07df5c5b238212af3358905b.tar.gz
xcos-on-web-92f3207b50a1caca07df5c5b238212af3358905b.tar.bz2
xcos-on-web-92f3207b50a1caca07df5c5b238212af3358905b.zip
Revert last two commits - Keyboard shortcuts are not working
Diffstat (limited to 'src/js/view/mxEdgeStyle.js')
-rw-r--r--src/js/view/mxEdgeStyle.js1302
1 files changed, 1302 insertions, 0 deletions
diff --git a/src/js/view/mxEdgeStyle.js b/src/js/view/mxEdgeStyle.js
new file mode 100644
index 0000000..41493d6
--- /dev/null
+++ b/src/js/view/mxEdgeStyle.js
@@ -0,0 +1,1302 @@
+/**
+ * $Id: mxEdgeStyle.js,v 1.68 2012-11-20 09:06:07 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+var mxEdgeStyle =
+{
+ /**
+ * Class: mxEdgeStyle
+ *
+ * Provides various edge styles to be used as the values for
+ * <mxConstants.STYLE_EDGE> in a cell style.
+ *
+ * Example:
+ *
+ * (code)
+ * var style = stylesheet.getDefaultEdgeStyle();
+ * style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;
+ * (end)
+ *
+ * Sets the default edge style to <ElbowConnector>.
+ *
+ * Custom edge style:
+ *
+ * To write a custom edge style, a function must be added to the mxEdgeStyle
+ * object as follows:
+ *
+ * (code)
+ * mxEdgeStyle.MyStyle = function(state, source, target, points, result)
+ * {
+ * if (source != null && target != null)
+ * {
+ * var pt = new mxPoint(target.getCenterX(), source.getCenterY());
+ *
+ * if (mxUtils.contains(source, pt.x, pt.y))
+ * {
+ * pt.y = source.y + source.height;
+ * }
+ *
+ * result.push(pt);
+ * }
+ * };
+ * (end)
+ *
+ * In the above example, a right angle is created using a point on the
+ * horizontal center of the target vertex and the vertical center of the source
+ * vertex. The code checks if that point intersects the source vertex and makes
+ * the edge straight if it does. The point is then added into the result array,
+ * which acts as the return value of the function.
+ *
+ * The new edge style should then be registered in the <mxStyleRegistry> as follows:
+ * (code)
+ * mxStyleRegistry.putValue('myEdgeStyle', mxEdgeStyle.MyStyle);
+ * (end)
+ *
+ * The custom edge style above can now be used in a specific edge as follows:
+ *
+ * (code)
+ * model.setStyle(edge, 'edgeStyle=myEdgeStyle');
+ * (end)
+ *
+ * Note that the key of the <mxStyleRegistry> entry for the function should
+ * be used in string values, unless <mxGraphView.allowEval> is true, in
+ * which case you can also use mxEdgeStyle.MyStyle for the value in the
+ * cell style above.
+ *
+ * Or it can be used for all edges in the graph as follows:
+ *
+ * (code)
+ * var style = graph.getStylesheet().getDefaultEdgeStyle();
+ * style[mxConstants.STYLE_EDGE] = mxEdgeStyle.MyStyle;
+ * (end)
+ *
+ * Note that the object can be used directly when programmatically setting
+ * the value, but the key in the <mxStyleRegistry> should be used when
+ * setting the value via a key, value pair in a cell style.
+ *
+ * Function: EntityRelation
+ *
+ * Implements an entity relation style for edges (as used in database
+ * schema diagrams). At the time the function is called, the result
+ * array contains a placeholder (null) for the first absolute point,
+ * that is, the point where the edge and source terminal are connected.
+ * The implementation of the style then adds all intermediate waypoints
+ * except for the last point, that is, the connection point between the
+ * edge and the target terminal. The first ant the last point in the
+ * result array are then replaced with mxPoints that take into account
+ * the terminal's perimeter and next point on the edge.
+ *
+ * Parameters:
+ *
+ * state - <mxCellState> that represents the edge to be updated.
+ * source - <mxCellState> that represents the source terminal.
+ * target - <mxCellState> that represents the target terminal.
+ * points - List of relative control points.
+ * result - Array of <mxPoints> that represent the actual points of the
+ * edge.
+ */
+ EntityRelation: function (state, source, target, points, result)
+ {
+ var view = state.view;
+ var graph = view.graph;
+ var segment = mxUtils.getValue(state.style,
+ mxConstants.STYLE_SEGMENT,
+ mxConstants.ENTITY_SEGMENT) * view.scale;
+
+ var pts = state.absolutePoints;
+ var p0 = pts[0];
+ var pe = pts[pts.length-1];
+
+ var isSourceLeft = false;
+
+ if (p0 != null)
+ {
+ source = new mxCellState();
+ source.x = p0.x;
+ source.y = p0.y;
+ }
+ else if (source != null)
+ {
+ var constraint = mxUtils.getPortConstraints(source, state, true, mxConstants.DIRECTION_MASK_NONE);
+
+ if (constraint != mxConstants.DIRECTION_MASK_NONE)
+ {
+ isSourceLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
+ }
+ else
+ {
+ var sourceGeometry = graph.getCellGeometry(source.cell);
+
+ if (sourceGeometry.relative)
+ {
+ isSourceLeft = sourceGeometry.x <= 0.5;
+ }
+ else if (target != null)
+ {
+ isSourceLeft = target.x + target.width < source.x;
+ }
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ var isTargetLeft = true;
+
+ if (pe != null)
+ {
+ target = new mxCellState();
+ target.x = pe.x;
+ target.y = pe.y;
+ }
+ else if (target != null)
+ {
+ var constraint = mxUtils.getPortConstraints(target, state, false, mxConstants.DIRECTION_MASK_NONE);
+
+ if (constraint != mxConstants.DIRECTION_MASK_NONE)
+ {
+ isTargetLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
+ }
+ else
+ {
+ var targetGeometry = graph.getCellGeometry(target.cell);
+
+ if (targetGeometry.relative)
+ {
+ isTargetLeft = targetGeometry.x <= 0.5;
+ }
+ else if (source != null)
+ {
+ isTargetLeft = source.x + source.width < target.x;
+ }
+ }
+ }
+
+ if (source != null && target != null)
+ {
+ var x0 = (isSourceLeft) ? source.x : source.x + source.width;
+ var y0 = view.getRoutingCenterY(source);
+
+ var xe = (isTargetLeft) ? target.x : target.x + target.width;
+ var ye = view.getRoutingCenterY(target);
+
+ var seg = segment;
+
+ var dx = (isSourceLeft) ? -seg : seg;
+ var dep = new mxPoint(x0 + dx, y0);
+
+ dx = (isTargetLeft) ? -seg : seg;
+ var arr = new mxPoint(xe + dx, ye);
+
+ // Adds intermediate points if both go out on same side
+ if (isSourceLeft == isTargetLeft)
+ {
+ var x = (isSourceLeft) ?
+ Math.min(x0, xe)-segment :
+ Math.max(x0, xe)+segment;
+
+ result.push(new mxPoint(x, y0));
+ result.push(new mxPoint(x, ye));
+ }
+ else if ((dep.x < arr.x) == isSourceLeft)
+ {
+ var midY = y0 + (ye - y0) / 2;
+
+ result.push(dep);
+ result.push(new mxPoint(dep.x, midY));
+ result.push(new mxPoint(arr.x, midY));
+ result.push(arr);
+ }
+ else
+ {
+ result.push(dep);
+ result.push(arr);
+ }
+ }
+ },
+
+ /**
+ * Function: Loop
+ *
+ * Implements a self-reference, aka. loop.
+ */
+ Loop: function (state, source, target, points, result)
+ {
+ if (source != null)
+ {
+ var view = state.view;
+ var graph = view.graph;
+ var pt = (points != null && points.length > 0) ? points[0] : null;
+
+ if (pt != null)
+ {
+ pt = view.transformControlPoint(state, pt);
+
+ if (mxUtils.contains(source, pt.x, pt.y))
+ {
+ pt = null;
+ }
+ }
+
+ var x = 0;
+ var dx = 0;
+ var y = 0;
+ var dy = 0;
+
+ var seg = mxUtils.getValue(state.style, mxConstants.STYLE_SEGMENT,
+ graph.gridSize) * view.scale;
+ var dir = mxUtils.getValue(state.style, mxConstants.STYLE_DIRECTION,
+ mxConstants.DIRECTION_WEST);
+
+ if (dir == mxConstants.DIRECTION_NORTH ||
+ dir == mxConstants.DIRECTION_SOUTH)
+ {
+ x = view.getRoutingCenterX(source);
+ dx = seg;
+ }
+ else
+ {
+ y = view.getRoutingCenterY(source);
+ dy = seg;
+ }
+
+ if (pt == null ||
+ pt.x < source.x ||
+ pt.x > source.x + source.width)
+ {
+ if (pt != null)
+ {
+ x = pt.x;
+ dy = Math.max(Math.abs(y - pt.y), dy);
+ }
+ else
+ {
+ if (dir == mxConstants.DIRECTION_NORTH)
+ {
+ y = source.y - 2 * dx;
+ }
+ else if (dir == mxConstants.DIRECTION_SOUTH)
+ {
+ y = source.y + source.height + 2 * dx;
+ }
+ else if (dir == mxConstants.DIRECTION_EAST)
+ {
+ x = source.x - 2 * dy;
+ }
+ else
+ {
+ x = source.x + source.width + 2 * dy;
+ }
+ }
+ }
+ else if (pt != null)
+ {
+ x = view.getRoutingCenterX(source);
+ dx = Math.max(Math.abs(x - pt.x), dy);
+ y = pt.y;
+ dy = 0;
+ }
+
+ result.push(new mxPoint(x - dx, y - dy));
+ result.push(new mxPoint(x + dx, y + dy));
+ }
+ },
+
+ /**
+ * Function: ElbowConnector
+ *
+ * Uses either <SideToSide> or <TopToBottom> depending on the horizontal
+ * flag in the cell style. <SideToSide> is used if horizontal is true or
+ * unspecified. See <EntityRelation> for a description of the
+ * parameters.
+ */
+ ElbowConnector: function (state, source, target, points, result)
+ {
+ var pt = (points != null && points.length > 0) ? points[0] : null;
+
+ var vertical = false;
+ var horizontal = false;
+
+ if (source != null && target != null)
+ {
+ if (pt != null)
+ {
+ var left = Math.min(source.x, target.x);
+ var right = Math.max(source.x + source.width,
+ target.x + target.width);
+
+ var top = Math.min(source.y, target.y);
+ var bottom = Math.max(source.y + source.height,
+ target.y + target.height);
+
+ pt = state.view.transformControlPoint(state, pt);
+
+ vertical = pt.y < top || pt.y > bottom;
+ horizontal = pt.x < left || pt.x > right;
+ }
+ else
+ {
+ var left = Math.max(source.x, target.x);
+ var right = Math.min(source.x + source.width,
+ target.x + target.width);
+
+ vertical = left == right;
+
+ if (!vertical)
+ {
+ var top = Math.max(source.y, target.y);
+ var bottom = Math.min(source.y + source.height,
+ target.y + target.height);
+
+ horizontal = top == bottom;
+ }
+ }
+ }
+
+ if (!horizontal && (vertical ||
+ state.style[mxConstants.STYLE_ELBOW] == mxConstants.ELBOW_VERTICAL))
+ {
+ mxEdgeStyle.TopToBottom(state, source, target, points, result);
+ }
+ else
+ {
+ mxEdgeStyle.SideToSide(state, source, target, points, result);
+ }
+ },
+
+ /**
+ * Function: SideToSide
+ *
+ * Implements a vertical elbow edge. See <EntityRelation> for a description
+ * of the parameters.
+ */
+ SideToSide: function (state, source, target, points, result)
+ {
+ var view = state.view;
+ var pt = (points != null && points.length > 0) ? points[0] : null;
+ var pts = state.absolutePoints;
+ var p0 = pts[0];
+ var pe = pts[pts.length-1];
+
+ if (pt != null)
+ {
+ pt = view.transformControlPoint(state, pt);
+ }
+
+ if (p0 != null)
+ {
+ source = new mxCellState();
+ source.x = p0.x;
+ source.y = p0.y;
+ }
+
+ if (pe != null)
+ {
+ target = new mxCellState();
+ target.x = pe.x;
+ target.y = pe.y;
+ }
+
+ if (source != null && target != null)
+ {
+ var l = Math.max(source.x, target.x);
+ var r = Math.min(source.x + source.width,
+ target.x + target.width);
+
+ var x = (pt != null) ? pt.x : r + (l - r) / 2;
+
+ var y1 = view.getRoutingCenterY(source);
+ var y2 = view.getRoutingCenterY(target);
+
+ if (pt != null)
+ {
+ if (pt.y >= source.y && pt.y <= source.y + source.height)
+ {
+ y1 = pt.y;
+ }
+
+ if (pt.y >= target.y && pt.y <= target.y + target.height)
+ {
+ y2 = pt.y;
+ }
+ }
+
+ if (!mxUtils.contains(target, x, y1) &&
+ !mxUtils.contains(source, x, y1))
+ {
+ result.push(new mxPoint(x, y1));
+ }
+
+ if (!mxUtils.contains(target, x, y2) &&
+ !mxUtils.contains(source, x, y2))
+ {
+ result.push(new mxPoint(x, y2));
+ }
+
+ if (result.length == 1)
+ {
+ if (pt != null)
+ {
+ if (!mxUtils.contains(target, x, pt.y) &&
+ !mxUtils.contains(source, x, pt.y))
+ {
+ result.push(new mxPoint(x, pt.y));
+ }
+ }
+ else
+ {
+ var t = Math.max(source.y, target.y);
+ var b = Math.min(source.y + source.height,
+ target.y + target.height);
+
+ result.push(new mxPoint(x, t + (b - t) / 2));
+ }
+ }
+ }
+ },
+
+ /**
+ * Function: TopToBottom
+ *
+ * Implements a horizontal elbow edge. See <EntityRelation> for a
+ * description of the parameters.
+ */
+ TopToBottom: function(state, source, target, points, result)
+ {
+ var view = state.view;
+ var pt = (points != null && points.length > 0) ? points[0] : null;
+ var pts = state.absolutePoints;
+ var p0 = pts[0];
+ var pe = pts[pts.length-1];
+
+ if (pt != null)
+ {
+ pt = view.transformControlPoint(state, pt);
+ }
+
+ if (p0 != null)
+ {
+ source = new mxCellState();
+ source.x = p0.x;
+ source.y = p0.y;
+ }
+
+ if (pe != null)
+ {
+ target = new mxCellState();
+ target.x = pe.x;
+ target.y = pe.y;
+ }
+
+ if (source != null && target != null)
+ {
+ var t = Math.max(source.y, target.y);
+ var b = Math.min(source.y + source.height,
+ target.y + target.height);
+
+ var x = view.getRoutingCenterX(source);
+
+ if (pt != null &&
+ pt.x >= source.x &&
+ pt.x <= source.x + source.width)
+ {
+ x = pt.x;
+ }
+
+ var y = (pt != null) ? pt.y : b + (t - b) / 2;
+
+ if (!mxUtils.contains(target, x, y) &&
+ !mxUtils.contains(source, x, y))
+ {
+ result.push(new mxPoint(x, y));
+ }
+
+ if (pt != null &&
+ pt.x >= target.x &&
+ pt.x <= target.x + target.width)
+ {
+ x = pt.x;
+ }
+ else
+ {
+ x = view.getRoutingCenterX(target);
+ }
+
+ if (!mxUtils.contains(target, x, y) &&
+ !mxUtils.contains(source, x, y))
+ {
+ result.push(new mxPoint(x, y));
+ }
+
+ if (result.length == 1)
+ {
+ if (pt != null && result.length == 1)
+ {
+ if (!mxUtils.contains(target, pt.x, y) &&
+ !mxUtils.contains(source, pt.x, y))
+ {
+ result.push(new mxPoint(pt.x, y));
+ }
+ }
+ else
+ {
+ var l = Math.max(source.x, target.x);
+ var r = Math.min(source.x + source.width,
+ target.x + target.width);
+
+ result.push(new mxPoint(l + (r - l) / 2, y));
+ }
+ }
+ }
+ },
+
+ /**
+ * Function: SegmentConnector
+ *
+ * Implements an orthogonal edge style. Use <mxEdgeSegmentHandler>
+ * as an interactive handler for this style.
+ */
+ SegmentConnector: function(state, source, target, hints, result)
+ {
+ // Creates array of all way- and terminalpoints
+ var pts = state.absolutePoints;
+ var horizontal = true;
+ var hint = null;
+
+ // Adds the first point
+ var pt = pts[0];
+
+ if (pt == null && source != null)
+ {
+ pt = new mxPoint(state.view.getRoutingCenterX(source), state.view.getRoutingCenterY(source));
+ }
+ else if (pt != null)
+ {
+ pt = pt.clone();
+ }
+
+ var lastInx = pts.length - 1;
+
+ // Adds the waypoints
+ if (hints != null && hints.length > 0)
+ {
+ hint = state.view.transformControlPoint(state, hints[0]);
+
+ var currentTerm = source;
+ var currentPt = pts[0];
+ var hozChan = false;
+ var vertChan = false;
+ var currentHint = hint;
+ var hintsLen = hints.length;
+
+ for (var i = 0; i < 2; i++)
+ {
+ var fixedVertAlign = currentPt != null && currentPt.x == currentHint.x;
+ var fixedHozAlign = currentPt != null && currentPt.y == currentHint.y;
+ var inHozChan = currentTerm != null && (currentHint.y >= currentTerm.y &&
+ currentHint.y <= currentTerm.y + currentTerm.height);
+ var inVertChan = currentTerm != null && (currentHint.x >= currentTerm.x &&
+ currentHint.x <= currentTerm.x + currentTerm.width);
+
+ hozChan = fixedHozAlign || (currentPt == null && inHozChan);
+ vertChan = fixedVertAlign || (currentPt == null && inVertChan);
+
+ if (currentPt != null && (!fixedHozAlign && !fixedVertAlign) && (inHozChan || inVertChan))
+ {
+ horizontal = inHozChan ? false : true;
+ break;
+ }
+
+ if (vertChan || hozChan)
+ {
+ horizontal = hozChan;
+
+ if (i == 1)
+ {
+ // Work back from target end
+ horizontal = hints.length % 2 == 0 ? hozChan : vertChan;
+ }
+
+ break;
+ }
+
+ currentTerm = target;
+ currentPt = pts[lastInx];
+ currentHint = state.view.transformControlPoint(state, hints[hintsLen - 1]);
+ }
+
+ if (horizontal && ((pts[0] != null && pts[0].y != hint.y) ||
+ (pts[0] == null && source != null &&
+ (hint.y < source.y || hint.y > source.y + source.height))))
+ {
+ result.push(new mxPoint(pt.x, hint.y));
+ }
+ else if (!horizontal && ((pts[0] != null && pts[0].x != hint.x) ||
+ (pts[0] == null && source != null &&
+ (hint.x < source.x || hint.x > source.x + source.width))))
+ {
+ result.push(new mxPoint(hint.x, pt.y));
+ }
+
+ if (horizontal)
+ {
+ pt.y = hint.y;
+ }
+ else
+ {
+ pt.x = hint.x;
+ }
+
+ for (var i = 0; i < hints.length; i++)
+ {
+ horizontal = !horizontal;
+ hint = state.view.transformControlPoint(state, hints[i]);
+
+// mxLog.show();
+// mxLog.debug('hint', i, hint.x, hint.y);
+
+ if (horizontal)
+ {
+ pt.y = hint.y;
+ }
+ else
+ {
+ pt.x = hint.x;
+ }
+
+ result.push(pt.clone());
+ }
+ }
+ else
+ {
+ hint = pt;
+ // FIXME: First click in connect preview toggles orientation
+ horizontal = true;
+ }
+
+ // Adds the last point
+ pt = pts[lastInx];
+
+ if (pt == null && target != null)
+ {
+ pt = new mxPoint(state.view.getRoutingCenterX(target), state.view.getRoutingCenterY(target));
+ }
+
+ if (horizontal && ((pts[lastInx] != null && pts[lastInx].y != hint.y) ||
+ (pts[lastInx] == null && target != null &&
+ (hint.y < target.y || hint.y > target.y + target.height))))
+ {
+ result.push(new mxPoint(pt.x, hint.y));
+ }
+ else if (!horizontal && ((pts[lastInx] != null && pts[lastInx].x != hint.x) ||
+ (pts[lastInx] == null && target != null &&
+ (hint.x < target.x || hint.x > target.x + target.width))))
+ {
+ result.push(new mxPoint(hint.x, pt.y));
+ }
+
+ // Removes bends inside the source terminal for floating ports
+ if (pts[0] == null && source != null)
+ {
+ while (result.length > 1 && mxUtils.contains(source, result[1].x, result[1].y))
+ {
+ result = result.splice(1, 1);
+ }
+ }
+
+ // Removes bends inside the target terminal
+ if (pts[lastInx] == null && target != null)
+ {
+ while (result.length > 1 && mxUtils.contains(target, result[result.length - 1].x, result[result.length - 1].y))
+ {
+ result = result.splice(result.length - 1, 1);
+ }
+ }
+
+ },
+
+ orthBuffer: 10,
+
+ dirVectors: [ [ -1, 0 ],
+ [ 0, -1 ], [ 1, 0 ], [ 0, 1 ], [ -1, 0 ], [ 0, -1 ], [ 1, 0 ] ],
+
+ wayPoints1: [ [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0],
+ [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0], [ 0, 0] ],
+
+ routePatterns: [
+ [ [ 513, 2308, 2081, 2562 ], [ 513, 1090, 514, 2184, 2114, 2561 ],
+ [ 513, 1090, 514, 2564, 2184, 2562 ],
+ [ 513, 2308, 2561, 1090, 514, 2568, 2308 ] ],
+ [ [ 514, 1057, 513, 2308, 2081, 2562 ], [ 514, 2184, 2114, 2561 ],
+ [ 514, 2184, 2562, 1057, 513, 2564, 2184 ],
+ [ 514, 1057, 513, 2568, 2308, 2561 ] ],
+ [ [ 1090, 514, 1057, 513, 2308, 2081, 2562 ], [ 2114, 2561 ],
+ [ 1090, 2562, 1057, 513, 2564, 2184 ],
+ [ 1090, 514, 1057, 513, 2308, 2561, 2568 ] ],
+ [ [ 2081, 2562 ], [ 1057, 513, 1090, 514, 2184, 2114, 2561 ],
+ [ 1057, 513, 1090, 514, 2184, 2562, 2564 ],
+ [ 1057, 2561, 1090, 514, 2568, 2308 ] ] ],
+
+ inlineRoutePatterns: [
+ [ null, [ 2114, 2568 ], null, null ],
+ [ null, [ 514, 2081, 2114, 2568 ] , null, null ],
+ [ null, [ 2114, 2561 ], null, null ],
+ [ [ 2081, 2562 ], [ 1057, 2114, 2568 ],
+ [ 2184, 2562 ],
+ null ] ],
+ vertexSeperations: [],
+
+ limits: [
+ [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+ [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ],
+
+ LEFT_MASK: 32,
+
+ TOP_MASK: 64,
+
+ RIGHT_MASK: 128,
+
+ BOTTOM_MASK: 256,
+
+ LEFT: 1,
+
+ TOP: 2,
+
+ RIGHT: 4,
+
+ BOTTOM: 8,
+
+ // TODO remove magic numbers
+ SIDE_MASK: 480,
+ //mxEdgeStyle.LEFT_MASK | mxEdgeStyle.TOP_MASK | mxEdgeStyle.RIGHT_MASK
+ //| mxEdgeStyle.BOTTOM_MASK,
+
+ CENTER_MASK: 512,
+
+ SOURCE_MASK: 1024,
+
+ TARGET_MASK: 2048,
+
+ VERTEX_MASK: 3072,
+ // mxEdgeStyle.SOURCE_MASK | mxEdgeStyle.TARGET_MASK,
+
+ /**
+ * Function: OrthConnector
+ *
+ * Implements a local orthogonal router between the given
+ * cells.
+ */
+ OrthConnector: function(state, source, target, points, result)
+ {
+ var graph = state.view.graph;
+ var sourceEdge = source == null ? false : graph.getModel().isEdge(source.cell);
+ var targetEdge = target == null ? false : graph.getModel().isEdge(target.cell);
+
+ if ((points != null && points.length > 0) || (sourceEdge) || (targetEdge))
+ {
+ mxEdgeStyle.SegmentConnector(state, source, target, points, result);
+ return;
+ }
+
+ var pts = state.absolutePoints;
+ var p0 = pts[0];
+ var pe = pts[pts.length-1];
+
+ var sourceX = source != null ? source.x : p0.x;
+ var sourceY = source != null ? source.y : p0.y;
+ var sourceWidth = source != null ? source.width : 1;
+ var sourceHeight = source != null ? source.height : 1;
+
+ var targetX = target != null ? target.x : pe.x;
+ var targetY = target != null ? target.y : pe.y;
+ var targetWidth = target != null ? target.width : 1;
+ var targetHeight = target != null ? target.height : 1;
+
+ var scaledOrthBuffer = state.view.scale * mxEdgeStyle.orthBuffer;
+ // Determine the side(s) of the source and target vertices
+ // that the edge may connect to
+ // portConstraint [source, target]
+ var portConstraint = [mxConstants.DIRECTION_MASK_ALL, mxConstants.DIRECTION_MASK_ALL];
+
+ if (source != null)
+ {
+ portConstraint[0] = mxUtils.getPortConstraints(source, state, true,
+ mxConstants.DIRECTION_MASK_ALL);
+ }
+
+ if (target != null)
+ {
+ portConstraint[1] = mxUtils.getPortConstraints(target, state, false,
+ mxConstants.DIRECTION_MASK_ALL);
+ }
+
+ var dir = [0, 0] ;
+
+ // Work out which faces of the vertices present against each other
+ // in a way that would allow a 3-segment connection if port constraints
+ // permitted.
+ // geo -> [source, target] [x, y, width, height]
+ var geo = [ [sourceX, sourceY, sourceWidth, sourceHeight] ,
+ [targetX, targetY, targetWidth, targetHeight] ];
+
+ for (var i = 0; i < 2; i++)
+ {
+ mxEdgeStyle.limits[i][1] = geo[i][0] - scaledOrthBuffer;
+ mxEdgeStyle.limits[i][2] = geo[i][1] - scaledOrthBuffer;
+ mxEdgeStyle.limits[i][4] = geo[i][0] + geo[i][2] + scaledOrthBuffer;
+ mxEdgeStyle.limits[i][8] = geo[i][1] + geo[i][3] + scaledOrthBuffer;
+ }
+
+ // Work out which quad the target is in
+ var sourceCenX = geo[0][0] + geo[0][2] / 2.0;
+ var sourceCenY = geo[0][1] + geo[0][3] / 2.0;
+ var targetCenX = geo[1][0] + geo[1][2] / 2.0;
+ var targetCenY = geo[1][1] + geo[1][3] / 2.0;
+
+ var dx = sourceCenX - targetCenX;
+ var dy = sourceCenY - targetCenY;
+
+ var quad = 0;
+
+ if (dx < 0)
+ {
+ if (dy < 0)
+ {
+ quad = 2;
+ }
+ else
+ {
+ quad = 1;
+ }
+ }
+ else
+ {
+ if (dy <= 0)
+ {
+ quad = 3;
+
+ // Special case on x = 0 and negative y
+ if (dx == 0)
+ {
+ quad = 2;
+ }
+ }
+ }
+
+ // Check for connection constraints
+ var currentTerm = null;
+
+ if (source != null)
+ {
+ currentTerm = p0;
+ }
+
+ var constraint = [ [0.5, 0.5] , [0.5, 0.5] ];
+
+ for (var i = 0; i < 2; i++)
+ {
+ if (currentTerm != null)
+ {
+ constraint[i][0] = (currentTerm.x - geo[i][0]) / geo[i][2];
+
+ if (constraint[i][0] < 0.01)
+ {
+ dir[i] = mxConstants.DIRECTION_MASK_WEST;
+ }
+ else if (constraint[i][0] > 0.99)
+ {
+ dir[i] = mxConstants.DIRECTION_MASK_EAST;
+ }
+
+ constraint[i][1] = (currentTerm.y - geo[i][1]) / geo[i][3];
+
+ if (constraint[i][1] < 0.01)
+ {
+ dir[i] = mxConstants.DIRECTION_MASK_NORTH;
+ }
+ else if (constraint[i][1] > 0.99)
+ {
+ dir[i] = mxConstants.DIRECTION_MASK_SOUTH;
+ }
+ }
+
+ currentTerm = null;
+
+ if (target != null)
+ {
+ currentTerm = pe;
+ }
+ }
+
+ var sourceTopDist = geo[0][1] - (geo[1][1] + geo[1][3]);
+ var sourceLeftDist = geo[0][0] - (geo[1][0] + geo[1][2]);
+ var sourceBottomDist = geo[1][1] - (geo[0][1] + geo[0][3]);
+ var sourceRightDist = geo[1][0] - (geo[0][0] + geo[0][2]);
+
+ mxEdgeStyle.vertexSeperations[1] = Math.max(
+ sourceLeftDist - 2 * scaledOrthBuffer, 0);
+ mxEdgeStyle.vertexSeperations[2] = Math.max(sourceTopDist - 2 * scaledOrthBuffer,
+ 0);
+ mxEdgeStyle.vertexSeperations[4] = Math.max(sourceBottomDist - 2
+ * scaledOrthBuffer, 0);
+ mxEdgeStyle.vertexSeperations[3] = Math.max(sourceRightDist - 2
+ * scaledOrthBuffer, 0);
+
+ //==============================================================
+ // Start of source and target direction determination
+
+ // Work through the preferred orientations by relative positioning
+ // of the vertices and list them in preferred and available order
+
+ var dirPref = [];
+ var horPref = [];
+ var vertPref = [];
+
+ horPref[0] = (sourceLeftDist >= sourceRightDist) ? mxConstants.DIRECTION_MASK_WEST
+ : mxConstants.DIRECTION_MASK_EAST;
+ vertPref[0] = (sourceTopDist >= sourceBottomDist) ? mxConstants.DIRECTION_MASK_NORTH
+ : mxConstants.DIRECTION_MASK_SOUTH;
+
+ horPref[1] = mxUtils.reversePortConstraints(horPref[0]);
+ vertPref[1] = mxUtils.reversePortConstraints(vertPref[0]);
+
+ var preferredHorizDist = sourceLeftDist >= sourceRightDist ? sourceLeftDist
+ : sourceRightDist;
+ var preferredVertDist = sourceTopDist >= sourceBottomDist ? sourceTopDist
+ : sourceBottomDist;
+
+ var prefOrdering = [ [0, 0] , [0, 0] ];
+ var preferredOrderSet = false;
+
+ // If the preferred port isn't available, switch it
+ for (var i = 0; i < 2; i++)
+ {
+ if (dir[i] != 0x0)
+ {
+ continue;
+ }
+
+ if ((horPref[i] & portConstraint[i]) == 0)
+ {
+ horPref[i] = mxUtils.reversePortConstraints(horPref[i]);
+ }
+
+ if ((vertPref[i] & portConstraint[i]) == 0)
+ {
+ vertPref[i] = mxUtils
+ .reversePortConstraints(vertPref[i]);
+ }
+
+ prefOrdering[i][0] = vertPref[i];
+ prefOrdering[i][1] = horPref[i];
+ }
+
+ if (preferredVertDist > scaledOrthBuffer * 2
+ && preferredHorizDist > scaledOrthBuffer * 2)
+ {
+ // Possibility of two segment edge connection
+ if (((horPref[0] & portConstraint[0]) > 0)
+ && ((vertPref[1] & portConstraint[1]) > 0))
+ {
+ prefOrdering[0][0] = horPref[0];
+ prefOrdering[0][1] = vertPref[0];
+ prefOrdering[1][0] = vertPref[1];
+ prefOrdering[1][1] = horPref[1];
+ preferredOrderSet = true;
+ }
+ else if (((vertPref[0] & portConstraint[0]) > 0)
+ && ((horPref[1] & portConstraint[1]) > 0))
+ {
+ prefOrdering[0][0] = vertPref[0];
+ prefOrdering[0][1] = horPref[0];
+ prefOrdering[1][0] = horPref[1];
+ prefOrdering[1][1] = vertPref[1];
+ preferredOrderSet = true;
+ }
+ }
+ if (preferredVertDist > scaledOrthBuffer * 2 && !preferredOrderSet)
+ {
+ prefOrdering[0][0] = vertPref[0];
+ prefOrdering[0][1] = horPref[0];
+ prefOrdering[1][0] = vertPref[1];
+ prefOrdering[1][1] = horPref[1];
+ preferredOrderSet = true;
+
+ }
+ if (preferredHorizDist > scaledOrthBuffer * 2 && !preferredOrderSet)
+ {
+ prefOrdering[0][0] = horPref[0];
+ prefOrdering[0][1] = vertPref[0];
+ prefOrdering[1][0] = horPref[1];
+ prefOrdering[1][1] = vertPref[1];
+ preferredOrderSet = true;
+ }
+
+ // The source and target prefs are now an ordered list of
+ // the preferred port selections
+ // It the list can contain gaps, compact it
+
+ for (var i = 0; i < 2; i++)
+ {
+ if (dir[i] != 0x0)
+ {
+ continue;
+ }
+
+ if ((prefOrdering[i][0] & portConstraint[i]) == 0)
+ {
+ prefOrdering[i][0] = prefOrdering[i][1];
+ }
+
+ dirPref[i] = prefOrdering[i][0] & portConstraint[i];
+ dirPref[i] |= (prefOrdering[i][1] & portConstraint[i]) << 8;
+ dirPref[i] |= (prefOrdering[1 - i][i] & portConstraint[i]) << 16;
+ dirPref[i] |= (prefOrdering[1 - i][1 - i] & portConstraint[i]) << 24;
+
+ if ((dirPref[i] & 0xF) == 0)
+ {
+ dirPref[i] = dirPref[i] << 8;
+ }
+ if ((dirPref[i] & 0xF00) == 0)
+ {
+ dirPref[i] = (dirPref[i] & 0xF) | dirPref[i] >> 8;
+ }
+ if ((dirPref[i] & 0xF0000) == 0)
+ {
+ dirPref[i] = (dirPref[i] & 0xFFFF)
+ | ((dirPref[i] & 0xF000000) >> 8);
+ }
+
+ dir[i] = dirPref[i] & 0xF;
+
+ if (portConstraint[i] == mxConstants.DIRECTION_MASK_WEST
+ || portConstraint[i] == mxConstants.DIRECTION_MASK_NORTH
+ || portConstraint[i] == mxConstants.DIRECTION_MASK_EAST
+ || portConstraint[i] == mxConstants.DIRECTION_MASK_SOUTH)
+ {
+ dir[i] = portConstraint[i];
+ }
+ }
+
+ //==============================================================
+ // End of source and target direction determination
+
+ var sourceIndex = dir[0] == mxConstants.DIRECTION_MASK_EAST ? 3
+ : dir[0];
+ var targetIndex = dir[1] == mxConstants.DIRECTION_MASK_EAST ? 3
+ : dir[1];
+
+ sourceIndex -= quad;
+ targetIndex -= quad;
+
+ if (sourceIndex < 1)
+ {
+ sourceIndex += 4;
+ }
+ if (targetIndex < 1)
+ {
+ targetIndex += 4;
+ }
+
+ var routePattern = mxEdgeStyle.routePatterns[sourceIndex - 1][targetIndex - 1];
+
+ mxEdgeStyle.wayPoints1[0][0] = geo[0][0];
+ mxEdgeStyle.wayPoints1[0][1] = geo[0][1];
+
+ switch (dir[0])
+ {
+ case mxConstants.DIRECTION_MASK_WEST:
+ mxEdgeStyle.wayPoints1[0][0] -= scaledOrthBuffer;
+ mxEdgeStyle.wayPoints1[0][1] += constraint[0][1] * geo[0][3];
+ break;
+ case mxConstants.DIRECTION_MASK_SOUTH:
+ mxEdgeStyle.wayPoints1[0][0] += constraint[0][0] * geo[0][2];
+ mxEdgeStyle.wayPoints1[0][1] += geo[0][3] + scaledOrthBuffer;
+ break;
+ case mxConstants.DIRECTION_MASK_EAST:
+ mxEdgeStyle.wayPoints1[0][0] += geo[0][2] + scaledOrthBuffer;
+ mxEdgeStyle.wayPoints1[0][1] += constraint[0][1] * geo[0][3];
+ break;
+ case mxConstants.DIRECTION_MASK_NORTH:
+ mxEdgeStyle.wayPoints1[0][0] += constraint[0][0] * geo[0][2];
+ mxEdgeStyle.wayPoints1[0][1] -= scaledOrthBuffer;
+ break;
+ }
+
+ var currentIndex = 0;
+
+ // Orientation, 0 horizontal, 1 vertical
+ var lastOrientation = (dir[0] & (mxConstants.DIRECTION_MASK_EAST | mxConstants.DIRECTION_MASK_WEST)) > 0 ? 0
+ : 1;
+ var initialOrientation = lastOrientation;
+ var currentOrientation = 0;
+
+ for (var i = 0; i < routePattern.length; i++)
+ {
+ var nextDirection = routePattern[i] & 0xF;
+
+ // Rotate the index of this direction by the quad
+ // to get the real direction
+ var directionIndex = nextDirection == mxConstants.DIRECTION_MASK_EAST ? 3
+ : nextDirection;
+
+ directionIndex += quad;
+
+ if (directionIndex > 4)
+ {
+ directionIndex -= 4;
+ }
+
+ var direction = mxEdgeStyle.dirVectors[directionIndex - 1];
+
+ currentOrientation = (directionIndex % 2 > 0) ? 0 : 1;
+ // Only update the current index if the point moved
+ // in the direction of the current segment move,
+ // otherwise the same point is moved until there is
+ // a segment direction change
+ if (currentOrientation != lastOrientation)
+ {
+ currentIndex++;
+ // Copy the previous way point into the new one
+ // We can't base the new position on index - 1
+ // because sometime elbows turn out not to exist,
+ // then we'd have to rewind.
+ mxEdgeStyle.wayPoints1[currentIndex][0] = mxEdgeStyle.wayPoints1[currentIndex - 1][0];
+ mxEdgeStyle.wayPoints1[currentIndex][1] = mxEdgeStyle.wayPoints1[currentIndex - 1][1];
+ }
+
+ var tar = (routePattern[i] & mxEdgeStyle.TARGET_MASK) > 0;
+ var sou = (routePattern[i] & mxEdgeStyle.SOURCE_MASK) > 0;
+ var side = (routePattern[i] & mxEdgeStyle.SIDE_MASK) >> 5;
+ side = side << quad;
+
+ if (side > 0xF)
+ {
+ side = side >> 4;
+ }
+
+ var center = (routePattern[i] & mxEdgeStyle.CENTER_MASK) > 0;
+
+ if ((sou || tar) && side < 9)
+ {
+ var limit = 0;
+ var souTar = sou ? 0 : 1;
+
+ if (center && currentOrientation == 0)
+ {
+ limit = geo[souTar][0] + constraint[souTar][0] * geo[souTar][2];
+ }
+ else if (center)
+ {
+ limit = geo[souTar][1] + constraint[souTar][1] * geo[souTar][3];
+ }
+ else
+ {
+ limit = mxEdgeStyle.limits[souTar][side];
+ }
+
+ if (currentOrientation == 0)
+ {
+ var lastX = mxEdgeStyle.wayPoints1[currentIndex][0];
+ var deltaX = (limit - lastX) * direction[0];
+
+ if (deltaX > 0)
+ {
+ mxEdgeStyle.wayPoints1[currentIndex][0] += direction[0]
+ * deltaX;
+ }
+ }
+ else
+ {
+ var lastY = mxEdgeStyle.wayPoints1[currentIndex][1];
+ var deltaY = (limit - lastY) * direction[1];
+
+ if (deltaY > 0)
+ {
+ mxEdgeStyle.wayPoints1[currentIndex][1] += direction[1]
+ * deltaY;
+ }
+ }
+ }
+
+ else if (center)
+ {
+ // Which center we're travelling to depend on the current direction
+ mxEdgeStyle.wayPoints1[currentIndex][0] += direction[0]
+ * Math.abs(mxEdgeStyle.vertexSeperations[directionIndex] / 2);
+ mxEdgeStyle.wayPoints1[currentIndex][1] += direction[1]
+ * Math.abs(mxEdgeStyle.vertexSeperations[directionIndex] / 2);
+ }
+
+ if (currentIndex > 0
+ && mxEdgeStyle.wayPoints1[currentIndex][currentOrientation] == mxEdgeStyle.wayPoints1[currentIndex - 1][currentOrientation])
+ {
+ currentIndex--;
+ }
+ else
+ {
+ lastOrientation = currentOrientation;
+ }
+ }
+
+ for (var i = 0; i <= currentIndex; i++)
+ {
+ if (i == currentIndex)
+ {
+ // Last point can cause last segment to be in
+ // same direction as jetty/approach. If so,
+ // check the number of points is consistent
+ // with the relative orientation of source and target
+ // jettys. Same orientation requires an even
+ // number of turns (points), different requires
+ // odd.
+ var targetOrientation = (dir[1] & (mxConstants.DIRECTION_MASK_EAST | mxConstants.DIRECTION_MASK_WEST)) > 0 ? 0
+ : 1;
+ var sameOrient = targetOrientation == initialOrientation ? 0 : 1;
+
+ // (currentIndex + 1) % 2 is 0 for even number of points,
+ // 1 for odd
+ if (sameOrient != (currentIndex + 1) % 2)
+ {
+ // The last point isn't required
+ break;
+ }
+ }
+
+ result.push(new mxPoint(mxEdgeStyle.wayPoints1[i][0], mxEdgeStyle.wayPoints1[i][1]));
+ }
+ },
+
+ getRoutePattern: function(dir, quad, dx, dy)
+ {
+ var sourceIndex = dir[0] == mxConstants.DIRECTION_MASK_EAST ? 3
+ : dir[0];
+ var targetIndex = dir[1] == mxConstants.DIRECTION_MASK_EAST ? 3
+ : dir[1];
+
+ sourceIndex -= quad;
+ targetIndex -= quad;
+
+ if (sourceIndex < 1)
+ {
+ sourceIndex += 4;
+ }
+ if (targetIndex < 1)
+ {
+ targetIndex += 4;
+ }
+
+ var result = routePatterns[sourceIndex - 1][targetIndex - 1];
+
+ if (dx == 0 || dy == 0)
+ {
+ if (inlineRoutePatterns[sourceIndex - 1][targetIndex - 1] != null)
+ {
+ result = inlineRoutePatterns[sourceIndex - 1][targetIndex - 1];
+ }
+ }
+
+ return result;
+ }
+}; \ No newline at end of file