| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- /**
- * Copyright (c) 2019-2020, JGraph Ltd
- */
- /**
- * Class: mxOrgChartLayout
- *
- * Extends <mxGraphLayout> to implement organization chart layout algorithm.
- * The vertices need to be connected for this layout to work, vertices
- * with no connections are ignored.
- *
- * Example:
- *
- * (code)
- * var layout = new mxOrgChartLayout(graph);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- */
- function mxOrgChartLayout(graph, branchOptimizer, parentChildSpacing, siblingSpacing)
- {
- mxGraphLayout.call(this, graph);
- this.correctY = false;
-
- switch(parseInt(branchOptimizer))
- {
- case 0:
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_LINEAR;
- this.correctY = true;
- break;
- case 1:
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_HANGER2;
- this.correctY = true;
- break;
- case 3:
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE1;
- break;
- case 4:
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE2;
- break;
- case 5:
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_L;
- break;
- case 6:
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_R;
- break;
- case 7:
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_SMART;
- break;
- default: //and case 2
- this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_HANGER4;
- this.correctY = true;
- }
-
- this.parentChildSpacing = parentChildSpacing > 0 ? parentChildSpacing : 20;
- this.siblingSpacing = siblingSpacing > 0 ? siblingSpacing : 20;
- };
- /**
- * Extends mxGraphLayout.
- */
- mxOrgChartLayout.prototype = new mxGraphLayout();
- mxOrgChartLayout.prototype.constructor = mxOrgChartLayout;
- //Branch Optimizers
- mxOrgChartLayout.prototype.BRANCH_OPT_LINEAR = 'branchOptimizerAllLinear';
- mxOrgChartLayout.prototype.BRANCH_OPT_HANGER2 = 'branchOptimizerAllHanger2';
- mxOrgChartLayout.prototype.BRANCH_OPT_HANGER4 = 'branchOptimizerAllHanger4';
- mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE1 = 'branchOptimizerAllFishbone1';
- mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE2 = 'branchOptimizerAllFishbone2';
- mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_L = 'branchOptimizerAllSingleColumnLeft';
- mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_R = 'branchOptimizerAllSingleColumnRight';
- mxOrgChartLayout.prototype.BRANCH_OPT_SMART = 'branchOptimizerSmart';
- /**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>. This operates on all children of the
- * given parent.
- */
- mxOrgChartLayout.prototype.execute = function(parent)
- {
- this.graph.model.beginUpdate();
- try
- {
- RPOrgChart.main(this.graph, parent, this.branchOptimizer, this.parentChildSpacing, this.siblingSpacing, this.correctY);
- }
- finally
- {
- this.graph.model.endUpdate();
- }
- }
- Bridge.define('RPOrgChart',
- {
- statics: {
- config: {
- init: function() {
- }
- },
- main: function (graph, parent, branchOptimizer, parentChildSpacing, siblingSpacing, correctY) {
- Bridge.Console.log = console.log;
- Bridge.Console.error = console.error;
- Bridge.Console.debug = console.debug;
- RPOrgChart.graph = graph;
- RPOrgChart.parent = parent;
- RPOrgChart.dx = 0;
- RPOrgChart.dy = 0;
-
- if (parent.style == 'group' && parent.geometry)
- {
- RPOrgChart.dx = parent.geometry.x;
- RPOrgChart.dy = parent.geometry.y;
- }
-
- RPOrgChart.branchOptimizer = branchOptimizer;
- RPOrgChart.correctY = correctY;
- RPOrgChart.parentChildSpacing = parseInt(parentChildSpacing);
- RPOrgChart.siblingSpacing = parseInt(siblingSpacing);
- RPOrgChart.buildChart(true);
- },
- diagram: {},
- dataSource: {},
- buildChart: function (initData) {
- if (initData) {
- RPOrgChart.initDiagram();
- }
- RPOrgChart.positionBoxes();
- },
- collapseAllBoxes: function(boxContainer, isCollapsed) {
- var en = boxContainer.getBoxesById().getValues().getEnumerator();
- while (en.moveNext()) {
- var box = en.getCurrent();
- if (!box.IsSpecial) {
- box.IsCollapsed = isCollapsed;
- }
- }
- },
- generateData: function ()
- {
- var dataSource = new OrgChart.Test.TestDataSource();
-
- var graph = RPOrgChart.graph;
- var cells = graph.getChildVertices(RPOrgChart.parent);
-
- for (var i = 0; i < cells.length; i++)
- {
- var cell = cells[i];
-
- if (cell.geometry != null && cell.vertex && cell.parent == RPOrgChart.parent) //Vertices and first level children only
- {
- // Find cell parent. If it has more than one parent, take first parent (should be an error?)
- var parentId = null;
-
- var incomingEdge = graph.getIncomingEdges(cell)[0];
-
- if (incomingEdge != null && incomingEdge.source != null)
- {
- parentId = incomingEdge.source.id;
- }
-
- var item = new OrgChart.Test.TestDataItem();
- item.Id = cell.id;
- item.ParentId = parentId;
- dataSource.Items.add(item.getId(), item);
- }
- }
-
- return dataSource;
- },
- initDiagram: function () {
- var dataSource = RPOrgChart.generateData();
- RPOrgChart.dataSource = dataSource;
- var boxContainer = new OrgChart.Layout.BoxContainer.$ctor1(dataSource);
- RPOrgChart.diagram = new OrgChart.Layout.Diagram();
- var diagram = RPOrgChart.diagram;
- diagram.setBoxes(boxContainer);
- var linearLayoutStrategy = new OrgChart.Layout.LinearLayoutStrategy();
- linearLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
- linearLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- linearLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("linear", linearLayoutStrategy);
- var multiLineHangerLayoutStrategy = new OrgChart.Layout.MultiLineHangerLayoutStrategy();
- multiLineHangerLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
- multiLineHangerLayoutStrategy.MaxSiblingsPerRow = 2;
- multiLineHangerLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- multiLineHangerLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("hanger2", multiLineHangerLayoutStrategy);
- multiLineHangerLayoutStrategy = new OrgChart.Layout.MultiLineHangerLayoutStrategy();
- multiLineHangerLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
- multiLineHangerLayoutStrategy.MaxSiblingsPerRow = 4;
- multiLineHangerLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- multiLineHangerLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("hanger4", multiLineHangerLayoutStrategy);
- var singleColumnLayoutStrategy = new OrgChart.Layout.SingleColumnLayoutStrategy();
- singleColumnLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Right;
- singleColumnLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- singleColumnLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("singleColumnRight", singleColumnLayoutStrategy);
- singleColumnLayoutStrategy = new OrgChart.Layout.SingleColumnLayoutStrategy();
- singleColumnLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Left;
- singleColumnLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- singleColumnLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("singleColumnLeft", singleColumnLayoutStrategy);
- var fishboneLayoutStrategy = new OrgChart.Layout.MultiLineFishboneLayoutStrategy();
- fishboneLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
- fishboneLayoutStrategy.MaxGroups = 1;
- fishboneLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- fishboneLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("fishbone1", fishboneLayoutStrategy);
- fishboneLayoutStrategy = new OrgChart.Layout.MultiLineFishboneLayoutStrategy();
- fishboneLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
- fishboneLayoutStrategy.MaxGroups = 2;
- fishboneLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- fishboneLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("fishbone2", fishboneLayoutStrategy);
- var hstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
- hstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
- hstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleRowHorizontal;
- hstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- hstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("hstack", hstackLayoutStrategy);
- var vstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
- vstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
- vstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleColumnVertical;
- vstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- vstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("vstack", vstackLayoutStrategy);
- vstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
- vstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
- vstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleColumnVertical;
- vstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- vstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("vstackMiddle", vstackLayoutStrategy);
- vstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
- vstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
- vstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleColumnVertical;
- vstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- vstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("vstackTop", vstackLayoutStrategy);
- var assistantsLayoutStrategy = new OrgChart.Layout.FishboneAssistantsLayoutStrategy();
- assistantsLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
- assistantsLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
- assistantsLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
- diagram.LayoutSettings.LayoutStrategies.add("assistants", assistantsLayoutStrategy);
- diagram.LayoutSettings.DefaultLayoutStrategyId = "vstack";
- diagram.LayoutSettings.DefaultAssistantLayoutStrategyId = "assistants";
- //diagram.LayoutSettings.setBranchSpacing(5);
- },
- getBoxLevel: function(boxContainer, box) {
- var level = 0;
- var obj = {};
- while (box.ParentId > 0) {
- if (!boxContainer.getBoxesById().tryGetValue(box.ParentId, obj)) {
- break;
- }
- box = obj.v;
- level++;
- }
- return level;
- },
- onLayoutStateChanged: function (sender, args) {
- if (args.State.getCurrentOperation() === OrgChart.Layout.LayoutState.Operation.PreprocessVisualTree) {
- // When layout algorithm is ready to preprocess the tree,
- // we need to have box sizes ready -> hence have to render visible boxes in HTML.
- // Rendering can happen at earlier time, but it's just more convenient to do it here,
- // to utilize some readily available information about visual tree.
- RPOrgChart.renderBoxes();
- }
- },
-
- renderBoxes: function () {
- var visitorFunc = function (node) {
- var box = node.Element;
- if (box.getIsDataBound()) {
- // we're being run when nodes have already been marked as visible or hidden,
- // based on IsCollapsed attribute of each Box
- // so use this knowledge to prevent unnecessary rendering of invisible branches
- if (node.State.IsHidden) {
- return true;
- }
- box.Size = RPOrgChart.getBoxElementSize(box.DataId);
- }
- return true;
- }
- RPOrgChart.diagram.getVisualTree().IterateParentFirst(visitorFunc);
- },
- getBranchOptimizerFunc: function () {
- return RPOrgChart[RPOrgChart.branchOptimizer];
- },
- branchOptimizerAllLinear: function(node) {
- return node.getIsAssistantRoot() ? null : "linear";
- },
-
- branchOptimizerAllHanger2: function(node) {
- return node.getIsAssistantRoot() ? null : "hanger2";
- },
-
- branchOptimizerAllHanger4: function(node) {
- return node.getIsAssistantRoot() ? null : "hanger4";
- },
-
- branchOptimizerAllFishbone1: function(node) {
- return node.getIsAssistantRoot() ? null : "fishbone1";
- },
- branchOptimizerAllFishbone2: function (node) {
- return node.getIsAssistantRoot() ? null : "fishbone2";
- },
- branchOptimizerAllSingleColumnLeft: function (node) {
- return node.getIsAssistantRoot() ? null : "singleColumnRight";
- },
- branchOptimizerAllSingleColumnRight: function (node) {
- return node.getIsAssistantRoot() ? null : "singleColumnLeft";
- },
- branchOptimizerStackers: function(node) {
- if (node.getIsAssistantRoot()) {
- return null;
- }
- return node.Level === 0 // this is Node for boxContainer.SystemRoot, which is not visible itself
- ? "vstackTop"
- : node.Level === 1 // this is children of SystemRoot - they appear as roots in the diagram
- ? "vstackMiddle"
- : "hstack";
- },
- branchOptimizerSmart: function(node) {
- if (node.getIsAssistantRoot()) {
- return null;
- }
- var childCount = node.getChildCount();
- if (childCount <= 1) {
- return "vstack";
- }
- var nonLeafChildren = 0;
- for (var i = 0; i < childCount; i++) {
- if (node.Children.getItem(i).getChildCount() > 0) {
- nonLeafChildren++;
- }
- }
- if (nonLeafChildren <= 1) {
- if (childCount <= 4) {
- return "vstack";
- }
- if (childCount <= 8) {
- return "fishbone1";
- }
- return "fishbone2";
- }
- return "hanger4";
- },
- boxSizeFunc: function (dataId) {
- // ChartLayoutAlgorithm requires this function to accept data ID
- // so have to convert it to Box ID first, to get rendered visual element
- var boxId = RPOrgChart.diagram.getBoxes().getBoxesByDataId().getItem(dataId).Id;
- return RPOrgChart.diagram.getBoxes().getBoxesById().getItem(boxId).Size;
- },
- getBoxElementSize: function (boxId) {
- var geo = RPOrgChart.graph.model.cells[boxId].geometry;
- return new OrgChart.Layout.Size.$ctor1(geo.width, geo.height);
- },
- positionBoxes: function () {
- var diagram = RPOrgChart.diagram;
- var state = new OrgChart.Layout.LayoutState(diagram);
- state.addOperationChanged(RPOrgChart.onLayoutStateChanged);
- state.BoxSizeFunc = Bridge.fn.bind(this, RPOrgChart.boxSizeFunc, null, true);
- state.LayoutOptimizerFunc = Bridge.fn.bind(this, RPOrgChart.getBranchOptimizerFunc(), null, true);
- OrgChart.Layout.LayoutAlgorithm.Apply(state);
- var diagramBoundary = OrgChart.Layout.LayoutAlgorithm.ComputeBranchVisualBoundingRect(diagram.getVisualTree());
- var offsetx = -diagramBoundary.getLeft() + diagramBoundary.getTop();
- var graph = RPOrgChart.graph;
- var cells = graph.model.cells;
- var pointsList = [];
-
- var visitorVertexFunc = function (node)
- {
- if (node.State.IsHidden) {
- return false;
- }
- var box = node.Element;
- if (box.getIsDataBound()) {
- var cell = cells[box.DataId];
- var geo = cell.geometry.clone();
- geo.x = node.State.TopLeft.X + offsetx;
- geo.y = node.State.TopLeft.Y;
- graph.model.setGeometry(cell, geo);
- }
-
- return true;
- }
-
- var visitorEdgeFunc = function (node)
- {
- //The algorithm default is 5 px only above the node, this centers it
- var yCorrection = RPOrgChart.correctY? Math.min(0, -(RPOrgChart.parentChildSpacing / 2) + 5) : 0;
- // Render connectors
- if (node.State.Connector != null) {
-
- var cell = cells[node.Element.DataId];
-
- var outgoingEdge = graph.getOutgoingEdges(cell);
- var uniquePoints = {};
-
- //Sort segments points from top to bottom or left to right + add offset
- for (var ix = 0; ix < node.State.Connector.Segments.length; ix++)
- {
- var edge = node.State.Connector.Segments[ix];
- edge.mark = 1 << ix; //TODO Support up to 31 segments. In this a limit?
- edge.From.X += offsetx;
- edge.To.X += offsetx;
- var fx = edge.From.X, fy = edge.From.Y, tx = edge.To.X, ty = edge.To.Y;
-
- if ((fx == tx && fy > ty) || (fy == ty && fx > tx))
- {
- var tmp = edge.From;
- edge.From = edge.To;
- edge.To = tmp;
- }
- }
-
- //Collecting points including intersection of segments
- for (var ix = 0; ix < node.State.Connector.Segments.length; ix++)
- {
- var edge = node.State.Connector.Segments[ix];
- var fx = edge.From.X, fy = edge.From.Y, tx = edge.To.X, ty = edge.To.Y;
- var fp = new mxPoint(fx, fy);
- pointsList.push(fp);
- fp.mark = edge.mark;
- var up = uniquePoints[fx + ',' + fy];
-
- if (up != null)
- {
- up.mark |= fp.mark;
- }
- else
- {
- uniquePoints[fx + ',' + fy] = fp;
- }
-
- var tp = new mxPoint(tx, ty);
- pointsList.push(tp);
- tp.mark = edge.mark;
- var up = uniquePoints[tx + ',' + ty];
-
- if (up != null)
- {
- up.mark |= tp.mark;
- }
- else
- {
- uniquePoints[tx + ',' + ty] = tp;
- }
-
- //Find intersections
- for (var j = ix + 1; j < node.State.Connector.Segments.length; j++)
- {
- var e2 = node.State.Connector.Segments[j];
- var fx2 = e2.From.X, fy2 = e2.From.Y, tx2 = e2.To.X, ty2 = e2.To.Y;
-
- if (fx == tx && fy <= fy2 && ty >= fy2 && fx2 <= fx && tx2 >= fx) //Ver |_ Hor
- {
- var ip = new mxPoint(fx, fy2);
- pointsList.push(ip);
- ip.mark = edge.mark | e2.mark;
- var up = uniquePoints[fx + ',' + fy2];
-
- if (up != null)
- {
- up.mark |= ip.mark;
- }
- else
- {
- uniquePoints[fx + ',' + fy2] = ip;
- }
- }
- else if (fy == ty && fx <= fx2 && tx >= fx2 && fy2 <= fy && ty2 >= fy) //Hor _| Ver
- {
- var ip = new mxPoint(fx2, fy);
- pointsList.push(ip);
- ip.mark = edge.mark | e2.mark;
- var up = uniquePoints[fx2 + ',' + fy]
-
- if (up != null)
- {
- up.mark |= ip.mark;
- }
- else
- {
- uniquePoints[fx2 + ',' + fy] = ip;
- }
- }
- }
- }
-
- //Sort points on y then x
- var pointsArr = [];
-
- for (var k in uniquePoints)
- {
- pointsArr.push(uniquePoints[k]);
- }
-
- pointsArr.sort(function(a, b)
- {
- var dy = a.y - b.y;
-
- return dy == 0? a.x - b.x : dy;
- });
-
- function pointOnCell(geo, p)
- {
- return p.x >= geo.x && p.x <= geo.x + geo.width && p.y >= geo.y && p.y <= geo.y + geo.height;
- };
-
- function adjustEdgeGeoAndStyle(edge, edgePoints)
- {
- var eGeo = edge.geometry.clone();
-
- for (var i = 0; edgePoints && i < edgePoints.length; i++)
- {
- if (!edgePoints[i].corrected)
- {
- edgePoints[i].y += yCorrection;
- edgePoints[i].corrected = true
- }
- }
-
- eGeo.points = edgePoints;
- graph.model.setGeometry(edge, eGeo);
- //Remove entry and exit points
- graph.setCellStyles('entryX', null, [edge]);
- graph.setCellStyles('entryY', null, [edge]);
- graph.setCellStyles('exitX', null, [edge]);
- graph.setCellStyles('exitY', null, [edge]);
- //Set type orthogonal
- graph.setCellStyles('edgeStyle', 'orthogonalEdgeStyle', [edge]);
- };
-
- var outgoingEdge = graph.getOutgoingEdges(cell);
-
- //Simple case of a single segment. TODO Handle this case earlier
- if (pointsArr.length == 2 && outgoingEdge.length == 1)
- {
- adjustEdgeGeoAndStyle(outgoingEdge[0], pointsArr);
- }
- else
- {
- var srcGeo = cell.geometry;
- var srcP;
-
- //Find src starting point //TODO It should be first point always?
- for (var i = 0; i < pointsArr.length; i++)
- {
- if (pointOnCell(srcGeo, pointsArr[i]))
- {
- srcP = pointsArr[i];
- break;
- }
- }
-
- var selected;
-
- function getNextPoint(lp)
- {
- for (var i = 0; i < pointsArr.length; i++)
- {
- var p = pointsArr[i];
- if (selected[p.x + ',' + p.y]) continue;
-
- if (p.mark & lp.mark)
- {
- selected[p.x + ',' + p.y] = true;
- return p;
- }
- }
- }
-
- for (var j = 0; j < outgoingEdge.length; j++)
- {
- if (outgoingEdge[j].target != null)
- {
- selected = {};
- selected[srcP.x + ',' + srcP.y] = true;
- var trgGeo = outgoingEdge[j].target.geometry;
-
- var edgePoints = [srcP];
- var lp = srcP;
- var safeGuard = 0;
- //Is BFS better?
- while (safeGuard < 1000)
- {
- safeGuard++;
- var np = getNextPoint(lp);
- //retract, then remove this point
- if (np == null)
- {
- edgePoints.pop();
- lp = edgePoints[edgePoints.length - 1];
- }
- else
- {
- edgePoints.push(np);
- lp = np;
- if (pointOnCell(trgGeo, np)) break;
- }
- }
-
- //Remove retracted points TODO can we do it in a better way?
- if (edgePoints.length > 2)
- {
- var spX = edgePoints[0].x;
- var lpX = edgePoints[edgePoints.length - 1].x;
-
- for (var i = edgePoints.length - 2; i > 0; i--)
- {
- if ((spX > lpX && edgePoints[i].x < lpX) || (spX < lpX && edgePoints[i].x < spX))
- {
- edgePoints.splice(i, 1);
- }
- }
- }
-
- var eGeo = outgoingEdge[j].geometry.clone();
- eGeo.points = edgePoints;
- RPOrgChart.graph.model.setGeometry(outgoingEdge[j], eGeo);
-
- //Fix edge points and style
- adjustEdgeGeoAndStyle(outgoingEdge[j], edgePoints);
- }
- }
- }
- }
- return true;
- }
- diagram.getVisualTree().IterateParentFirst(visitorVertexFunc);
- diagram.getVisualTree().IterateParentFirst(visitorEdgeFunc);
-
- //Cleanup
- for (var i = 0; i < pointsList.length; i++)
- {
- delete pointsList[i].mark;
- delete pointsList[i].corrected;
- }
- }
- }
- });
- Bridge.init();
|