1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654 |
- /**
- * Copyright (c) 2006-2015, JGraph Ltd
- * Copyright (c) 2006-2015, Gaudenz Alder
- */
- 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 (source != null)
- {
- var sourceGeometry = graph.getCellGeometry(source.cell);
-
- if (sourceGeometry.relative)
- {
- isSourceLeft = sourceGeometry.x <= 0.5;
- }
- else if (target != null)
- {
- isSourceLeft = ((pe != null) ? pe.x : target.x + target.width) < ((p0 != null) ? p0.x : source.x);
- }
- }
- 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 && constraint != mxConstants.DIRECTION_MASK_WEST +
- mxConstants.DIRECTION_MASK_EAST)
- {
- isSourceLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
- }
- }
- else
- {
- return;
- }
-
- var isTargetLeft = true;
-
- if (target != null)
- {
- var targetGeometry = graph.getCellGeometry(target.cell);
-
- if (targetGeometry.relative)
- {
- isTargetLeft = targetGeometry.x <= 0.5;
- }
- else if (source != null)
- {
- isTargetLeft = ((p0 != null) ? p0.x : source.x + source.width) < ((pe != null) ? pe.x : target.x);
- }
- }
-
- 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 && constraint != mxConstants.DIRECTION_MASK_WEST +
- mxConstants.DIRECTION_MASK_EAST)
- {
- isTargetLeft = constraint == mxConstants.DIRECTION_MASK_WEST;
- }
- }
-
- 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)
- {
- var pts = state.absolutePoints;
-
- var p0 = pts[0];
- var pe = pts[pts.length-1];
- if (p0 != null && pe != null)
- {
- if (points != null && points.length > 0)
- {
- for (var i = 0; i < points.length; i++)
- {
- var pt = points[i];
- pt = state.view.transformControlPoint(state, pt);
- result.push(new mxPoint(pt.x, pt.y));
- }
- }
- return;
- }
-
- 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 : Math.round(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 : Math.round(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.
- *
- * state - <mxCellState> that represents the edge to be updated.
- * sourceScaled - <mxCellState> that represents the source terminal.
- * targetScaled - <mxCellState> that represents the target terminal.
- * controlHints - List of relative control points.
- * result - Array of <mxPoints> that represent the actual points of the
- * edge.
- *
- */
- SegmentConnector: function(state, sourceScaled, targetScaled, controlHints, result)
- {
- // Creates array of all way- and terminalpoints
- var pts = mxEdgeStyle.scalePointArray(state.absolutePoints, state.view.scale);
- var source = mxEdgeStyle.scaleCellState(sourceScaled, state.view.scale);
- var target = mxEdgeStyle.scaleCellState(targetScaled, state.view.scale);
- var tol = 1;
-
- // Whether the first segment outgoing from the source end is horizontal
- var lastPushed = (result.length > 0) ? result[0] : null;
- var horizontal = true;
- var hint = null;
-
- // Adds waypoints only if outside of tolerance
- function pushPoint(pt)
- {
- pt.x = Math.round(pt.x * state.view.scale * 10) / 10;
- pt.y = Math.round(pt.y * state.view.scale * 10) / 10;
- if (lastPushed == null || Math.abs(lastPushed.x - pt.x) >= tol || Math.abs(lastPushed.y - pt.y) >= Math.max(1, state.view.scale))
- {
- result.push(pt);
- lastPushed = pt;
- }
-
- return lastPushed;
- };
- // 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 (controlHints != null && controlHints.length > 0)
- {
- // Converts all hints and removes nulls
- var hints = [];
-
- for (var i = 0; i < controlHints.length; i++)
- {
- var tmp = state.view.transformControlPoint(state, controlHints[i], true);
-
- if (tmp != null)
- {
- hints.push(tmp);
- }
- }
-
- if (hints.length == 0)
- {
- return;
- }
-
- // Aligns source and target hint to fixed points
- if (pt != null && hints[0] != null)
- {
- if (Math.abs(hints[0].x - pt.x) < tol)
- {
- hints[0].x = pt.x;
- }
-
- if (Math.abs(hints[0].y - pt.y) < tol)
- {
- hints[0].y = pt.y;
- }
- }
-
- var pe = pts[lastInx];
-
- if (pe != null && hints[hints.length - 1] != null)
- {
- if (Math.abs(hints[hints.length - 1].x - pe.x) < tol)
- {
- hints[hints.length - 1].x = pe.x;
- }
-
- if (Math.abs(hints[hints.length - 1].y - pe.y) < tol)
- {
- hints[hints.length - 1].y = pe.y;
- }
- }
-
- hint = hints[0];
- var currentTerm = source;
- var currentPt = pts[0];
- var hozChan = false;
- var vertChan = false;
- var currentHint = hint;
-
- if (currentPt != null)
- {
- currentTerm = null;
- }
-
- // Check for alignment with fixed points and with channels
- // at source and target segments only
- 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 the current hint falls in both the hor and vert channels in the case
- // of a floating port, or if the hint is exactly co-incident with a
- // fixed point, ignore the source and try to work out the orientation
- // from the target end
- if (i==0 && ((hozChan && vertChan) || (fixedVertAlign && fixedHozAlign)))
- {
- }
- else
- {
- 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];
-
- if (currentPt != null)
- {
- currentTerm = null;
- }
-
- currentHint = hints[hints.length - 1];
-
- if (fixedVertAlign && fixedHozAlign)
- {
- hints = hints.slice(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))))
- {
- pushPoint(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))))
- {
- pushPoint(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 = hints[i];
-
- // mxLog.show();
- // mxLog.debug('hint', i, hint.x, hint.y);
-
- if (horizontal)
- {
- pt.y = hint.y;
- }
- else
- {
- pt.x = hint.x;
- }
-
- pushPoint(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 (pt != null)
- {
- if (hint != null)
- {
- 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))))
- {
- pushPoint(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))))
- {
- pushPoint(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 && result[1] != null &&
- mxUtils.contains(source, result[1].x, result[1].y))
- {
- result.splice(1, 1);
- }
- }
-
- // Removes bends inside the target terminal
- if (pts[lastInx] == null && target != null)
- {
- while (result.length > 1 && result[result.length - 1] != null &&
- mxUtils.contains(target, result[result.length - 1].x, result[result.length - 1].y))
- {
- result.splice(result.length - 1, 1);
- }
- }
-
- // Removes last point if inside tolerance with end point
- if (pe != null && result[result.length - 1] != null &&
- Math.abs(pe.x - result[result.length - 1].x) <= tol &&
- Math.abs(pe.y - result[result.length - 1].y) <= tol)
- {
- result.splice(result.length - 1, 1);
-
- // Lines up second last point in result with end point
- if (result[result.length - 1] != null)
- {
- if (Math.abs(result[result.length - 1].x - pe.x) < tol)
- {
- result[result.length - 1].x = pe.x;
- }
-
- if (Math.abs(result[result.length - 1].y - pe.y) < tol)
- {
- result[result.length - 1].y = pe.y;
- }
- }
- }
- },
-
- orthBuffer: 10,
-
- orthPointsFallback: true,
- 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,
-
- getJettySize: function(state, isSource)
- {
- var value = mxUtils.getValue(state.style, (isSource) ? mxConstants.STYLE_SOURCE_JETTY_SIZE :
- mxConstants.STYLE_TARGET_JETTY_SIZE, mxUtils.getValue(state.style,
- mxConstants.STYLE_JETTY_SIZE, mxEdgeStyle.orthBuffer));
-
- if (value == 'auto')
- {
- // Computes the automatic jetty size
- var type = mxUtils.getValue(state.style, (isSource) ? mxConstants.STYLE_STARTARROW : mxConstants.STYLE_ENDARROW, mxConstants.NONE);
-
- if (type != mxConstants.NONE)
- {
- var size = mxUtils.getNumber(state.style, (isSource) ? mxConstants.STYLE_STARTSIZE : mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE);
- value = Math.max(2, Math.ceil((size + mxEdgeStyle.orthBuffer) / mxEdgeStyle.orthBuffer)) * mxEdgeStyle.orthBuffer;
- }
- else
- {
- value = 2 * mxEdgeStyle.orthBuffer;
- }
- }
-
- return value;
- },
-
- /**
- * Function: scalePointArray
- *
- * Scales an array of <mxPoint>
- *
- * Parameters:
- *
- * points - array of <mxPoint> to scale
- * scale - the scaling to divide by
- *
- */
- scalePointArray: function(points, scale)
- {
- var result = [];
- if (points != null)
- {
- for (var i = 0; i < points.length; i++)
- {
- if (points[i] != null)
- {
- var pt = new mxPoint(Math.round(points[i].x / scale * 10) / 10,
- Math.round(points[i].y / scale * 10) / 10);
- result[i] = pt;
- }
- else
- {
- result[i] = null;
- }
- }
- }
- else
- {
- result = null;
- }
-
- return result;
- },
-
- /**
- * Function: scaleCellState
- *
- * Scales an <mxCellState>
- *
- * Parameters:
- *
- * state - <mxCellState> to scale
- * scale - the scaling to divide by
- *
- */
- scaleCellState: function(state, scale)
- {
- var result = null;
- if (state != null)
- {
- result = state.clone();
- result.setRect(Math.round(state.x / scale * 10) / 10,
- Math.round(state.y / scale * 10) / 10,
- Math.round(state.width / scale * 10) / 10,
- Math.round(state.height / scale * 10) / 10);
- }
- else
- {
- result = null;
- }
-
- return result;
- },
- /**
- * Function: OrthConnector
- *
- * Implements a local orthogonal router between the given
- * cells.
- *
- * Parameters:
- *
- * state - <mxCellState> that represents the edge to be updated.
- * sourceScaled - <mxCellState> that represents the source terminal.
- * targetScaled - <mxCellState> that represents the target terminal.
- * controlHints - List of relative control points.
- * result - Array of <mxPoints> that represent the actual points of the
- * edge.
- *
- */
- OrthConnector: function(state, sourceScaled, targetScaled, controlHints, 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);
- var pts = mxEdgeStyle.scalePointArray(state.absolutePoints, state.view.scale);
- var source = mxEdgeStyle.scaleCellState(sourceScaled, state.view.scale);
- var target = mxEdgeStyle.scaleCellState(targetScaled, state.view.scale);
- 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 : 0;
- var sourceHeight = source != null ? source.height : 0;
-
- var targetX = target != null ? target.x : pe.x;
- var targetY = target != null ? target.y : pe.y;
- var targetWidth = target != null ? target.width : 0;
- var targetHeight = target != null ? target.height : 0;
- var sourceBuffer = mxEdgeStyle.getJettySize(state, true);
- var targetBuffer = mxEdgeStyle.getJettySize(state, false);
-
- //console.log('sourceBuffer', sourceBuffer);
- //console.log('targetBuffer', targetBuffer);
- // Workaround for loop routing within buffer zone
- if (source != null && target == source)
- {
- targetBuffer = Math.max(sourceBuffer, targetBuffer);
- sourceBuffer = targetBuffer;
- }
-
- var totalBuffer = targetBuffer + sourceBuffer;
- // console.log('totalBuffer', totalBuffer);
- var tooShort = false;
-
- // Checks minimum distance for fixed points and falls back to segment connector
- if (p0 != null && pe != null)
- {
- var dx = pe.x - p0.x;
- var dy = pe.y - p0.y;
-
- tooShort = dx * dx + dy * dy < totalBuffer * totalBuffer;
- }
- if (tooShort || (mxEdgeStyle.orthPointsFallback && (controlHints != null &&
- controlHints.length > 0)) || sourceEdge || targetEdge)
- {
- mxEdgeStyle.SegmentConnector(state, sourceScaled, targetScaled, controlHints, result);
-
- return;
- }
- // 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];
- var rotation = 0;
-
- if (source != null)
- {
- portConstraint[0] = mxUtils.getPortConstraints(source, state, true,
- mxConstants.DIRECTION_MASK_ALL);
- rotation = mxUtils.getValue(source.style, mxConstants.STYLE_ROTATION, 0);
-
- //console.log('source rotation', rotation);
-
- if (rotation != 0)
- {
- var newRect = mxUtils.getBoundingBox(new mxRectangle(sourceX, sourceY, sourceWidth, sourceHeight), rotation);
- sourceX = newRect.x;
- sourceY = newRect.y;
- sourceWidth = newRect.width;
- sourceHeight = newRect.height;
- }
- }
- if (target != null)
- {
- portConstraint[1] = mxUtils.getPortConstraints(target, state, false,
- mxConstants.DIRECTION_MASK_ALL);
- rotation = mxUtils.getValue(target.style, mxConstants.STYLE_ROTATION, 0);
-
- //console.log('target rotation', rotation);
- if (rotation != 0)
- {
- var newRect = mxUtils.getBoundingBox(new mxRectangle(targetX, targetY, targetWidth, targetHeight), rotation);
- targetX = newRect.x;
- targetY = newRect.y;
- targetWidth = newRect.width;
- targetHeight = newRect.height;
- }
- }
- //console.log('source' , sourceX, sourceY, sourceWidth, sourceHeight);
- //console.log('targetX' , targetX, targetY, targetWidth, targetHeight);
- 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] ];
- var buffer = [sourceBuffer, targetBuffer];
- for (var i = 0; i < 2; i++)
- {
- mxEdgeStyle.limits[i][1] = geo[i][0] - buffer[i];
- mxEdgeStyle.limits[i][2] = geo[i][1] - buffer[i];
- mxEdgeStyle.limits[i][4] = geo[i][0] + geo[i][2] + buffer[i];
- mxEdgeStyle.limits[i][8] = geo[i][1] + geo[i][3] + buffer[i];
- }
-
- // 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;
- // 0 | 1
- // -----
- // 3 | 2
-
- 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;
- }
- }
- }
- //console.log('quad', quad);
- // 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 (Math.abs(currentTerm.x - geo[i][0]) <= 1)
- {
- dir[i] = mxConstants.DIRECTION_MASK_WEST;
- }
- else if (Math.abs(currentTerm.x - geo[i][0] - geo[i][2]) <= 1)
- {
- dir[i] = mxConstants.DIRECTION_MASK_EAST;
- }
- constraint[i][1] = (currentTerm.y - geo[i][1]) / geo[i][3];
- if (Math.abs(currentTerm.y - geo[i][1]) <= 1)
- {
- dir[i] = mxConstants.DIRECTION_MASK_NORTH;
- }
- else if (Math.abs(currentTerm.y - geo[i][1] - geo[i][3]) <= 1)
- {
- 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 - totalBuffer, 0);
- mxEdgeStyle.vertexSeperations[2] = Math.max(sourceTopDist - totalBuffer, 0);
- mxEdgeStyle.vertexSeperations[4] = Math.max(sourceBottomDist - totalBuffer, 0);
- mxEdgeStyle.vertexSeperations[3] = Math.max(sourceRightDist - totalBuffer, 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 > 0
- && preferredHorizDist > 0)
- {
- // 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 > 0 && !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 > 0 && !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
- // If the list contains 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];
-
- //console.log('routePattern', routePattern);
- 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] -= sourceBuffer;
- 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] + sourceBuffer;
- break;
- case mxConstants.DIRECTION_MASK_EAST:
- mxEdgeStyle.wayPoints1[0][0] += geo[0][2] + sourceBuffer;
- 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] -= sourceBuffer;
- 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
- // jx. 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(Math.round(mxEdgeStyle.wayPoints1[i][0] * state.view.scale * 10) / 10,
- Math.round(mxEdgeStyle.wayPoints1[i][1] * state.view.scale * 10) / 10));
- }
-
- //console.log(result);
- // Removes duplicates
- var index = 1;
-
- while (index < result.length)
- {
- if (result[index - 1] == null || result[index] == null ||
- result[index - 1].x != result[index].x ||
- result[index - 1].y != result[index].y)
- {
- index++;
- }
- else
- {
- result.splice(index, 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;
- }
- };
- __mxOutput.mxEdgeStyle = typeof mxEdgeStyle !== 'undefined' ? mxEdgeStyle : undefined;
|