diff options
author | adhitya | 2016-04-11 15:10:54 +0000 |
---|---|---|
committer | adhitya | 2016-04-11 15:10:54 +0000 |
commit | 92f3207b50a1caca07df5c5b238212af3358905b (patch) | |
tree | 38c92f9649c6f1016d2ef70fa2fd33c86b437cba /src/js/view/mxEdgeStyle.js | |
parent | ab5fb6e125d82fdd5818aea3ce370c43c2293ddd (diff) | |
download | xcos-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.js | 1302 |
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 |