all files / diagram/layout/ radial-tree.js

95.57% Statements 151/158
85.71% Branches 36/42
100% Functions 20/20
95.51% Lines 149/156
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216       46813×   13×                   13×   13× 13× 87× 87× 86× 86× 13×       13×   12× 11× 11×   13× 12× 12× 12× 12× 12× 12×     85× 85× 85× 85× 85× 85× 73× 73× 73× 73×       85× 85× 85× 18× 18× 73× 73× 73×   18× 55×   18× 18× 18× 18× 18× 18× 18× 18× 18× 18×                   18× 18× 18× 18×     67× 67× 67× 67× 67×   85×   12× 85× 12× 85×   12× 12× 12× 26× 195× 85×     110×     26× 59× 26× 26× 26× 26× 26× 85× 26×   85× 85× 59×     26× 26× 26×   26× 26× 26×     26× 85×   85×   26×   12× 26×     12× 12× 12× 12× 14× 73× 73×   73×   73× 73×       12× 12×   85× 85× 85× 85× 85× 85× 73× 73×     86× 86× 86× 86× 86× 86× 86× 86× 86× 86× 86× 86× 86×        
define(["require", "exports"], function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var RadialTree = (function () {
        function RadialTree() {
        }
        RadialTree.prototype.destroy = function () {
        };
        RadialTree.prototype.getModuleName = function () {
            return 'RadialTree';
        };
        RadialTree.prototype.updateLayout = function (nodes, nameTable, layoutProp, viewport) {
            var layout = {
                type: layoutProp.type,
                nameTable: nameTable, anchorX: 0, anchorY: 0,
                firstLevelNodes: [], centerNode: null, levels: [], maxLevel: 0, graphNodes: {}, layoutNodes: [],
                orientation: layoutProp.orientation,
                horizontalSpacing: layoutProp.horizontalSpacing, verticalSpacing: layoutProp.verticalSpacing,
                verticalAlignment: layoutProp.verticalAlignment, horizontalAlignment: layoutProp.horizontalAlignment,
                fixedNode: layoutProp.fixedNode, margin: layoutProp.margin,
                bounds: layoutProp.bounds, objects: [], root: layoutProp.root
            };
            this.doLayout(layout, nodes, nameTable, viewport);
        };
        RadialTree.prototype.doLayout = function (layout, nodes, nameTable, viewport) {
            var node;
            for (var i = 0; i < nodes.length; i++) {
                node = nodes[parseInt(i.toString(), 10)];
                if (!node.excludeFromLayout) {
                    layout.graphNodes[node.id] = this.setUpLayoutInfo(layout, node);
                    if (!node.inEdges || !node.inEdges.length) {
                        layout.firstLevelNodes.push(node);
                    }
                }
            }
            if (layout.root && nameTable[layout.root]) {
                layout.centerNode = nameTable[layout.root];
            }
            else if (layout.firstLevelNodes.length) {
                layout.centerNode = layout.firstLevelNodes[0];
                layout.root = layout.centerNode.id;
            }
            if (layout.centerNode) {
                this.updateEdges(layout, layout.centerNode, 0, nameTable);
                this.depthFirstAllignment(layout, layout.centerNode, 0, 0);
                this.populateLevels(layout);
                this.transformToCircleLayout(layout);
                this.updateAnchor(layout, viewport);
                this.updateNodes(layout, layout.centerNode, nameTable);
            }
        };
        RadialTree.prototype.updateEdges = function (layout, node, depth, nameTable) {
            var nodeInfo = layout.graphNodes[node.id];
            layout.layoutNodes.push(nodeInfo);
            nodeInfo.level = depth;
            nodeInfo.visited = true;
            layout.maxLevel = Math.max(layout.maxLevel, depth);
            for (var j = 0; j < node.outEdges.length; j++) {
                var edge = nameTable[nameTable[node.outEdges[parseInt(j.toString(), 10)]].targetID];
                Eif (!edge.excludeFromLayout && !edge.visited) {
                    nodeInfo.children.push(edge);
                    this.updateEdges(layout, edge, depth + 1, nameTable);
                }
            }
        };
        RadialTree.prototype.depthFirstAllignment = function (layout, node, x, y) {
            var newValue;
            var nodeInfo = layout.graphNodes[node.id];
            if (nodeInfo.children.length) {
                y += 300;
                for (var i = 0; i < nodeInfo.children.length; i++) {
                    newValue = this.depthFirstAllignment(layout, nodeInfo.children[parseInt(i.toString(), 10)], x, y);
                    x = newValue.x;
                    y = newValue.y;
                }
                nodeInfo.children = nodeInfo.children.sort(function (obj1, obj2) {
                    return layout.graphNodes[obj1.id].x - layout.graphNodes[obj2.id].x;
                });
                var min = layout.graphNodes[nodeInfo.children[0].id].min;
                var max = layout.graphNodes[nodeInfo.children[nodeInfo.children.length - 1].id].max;
                nodeInfo.x = min + (max - min) / 2;
                x = max + layout.horizontalSpacing;
                nodeInfo.segmentOffset = max + layout.horizontalSpacing;
                nodeInfo.x -= nodeInfo.width / 2;
                nodeInfo.y -= nodeInfo.height / 2;
                nodeInfo.min = min;
                nodeInfo.max = max;
                Iif (nodeInfo.x < min && nodeInfo.visited) {
                    nodeInfo.x = min;
                    x = nodeInfo.x + nodeInfo.width / 2 - (max - min) / 2;
                    nodeInfo.visited = false;
                    for (var i = 0; i < nodeInfo.children.length; i++) {
                        newValue = this.depthFirstAllignment(layout, nodeInfo.children[parseInt(i.toString(), 10)], x, y);
                    }
                    nodeInfo.visited = true;
                    x = nodeInfo.x + nodeInfo.width + layout.horizontalSpacing;
                }
                max = layout.graphNodes[nodeInfo.children[nodeInfo.children.length - 1].id].segmentOffset;
                x = x < max ? max : x;
                y -= 300;
                nodeInfo.y = y;
            }
            else {
                nodeInfo.x = x;
                nodeInfo.y = y;
                nodeInfo.min = x;
                nodeInfo.max = x + nodeInfo.width;
                x += nodeInfo.width + layout.horizontalSpacing;
            }
            return { x: x, y: y };
        };
        RadialTree.prototype.populateLevels = function (layout) {
            var stages = [];
            var min = Math.min.apply(Math, layout.layoutNodes.map(function (nodeInfo) { return nodeInfo.x; }));
            var max = Math.max.apply(Math, layout.layoutNodes.map(function (nodeInfo) {
                return nodeInfo.x + nodeInfo.width + layout.horizontalSpacing;
            }));
            var full = max - min;
            layout.levels = [];
            var _loop_1 = function (i) {
                stages = layout.layoutNodes.filter(function (nodeInfo) {
                    if (nodeInfo.level === i) {
                        return nodeInfo;
                    }
                    else {
                        return null;
                    }
                });
                var newlevel = {};
                stages = stages.sort(function (nodeInfo1, nodeInfo2) { return nodeInfo1.x - nodeInfo2.x; });
                newlevel.min = stages[0].x;
                newlevel.max = stages[stages.length - 1].x + stages[stages.length - 1].width + layout.horizontalSpacing;
                newlevel.actualCircumference = 0;
                newlevel.height = 0;
                for (var k = 0; k < stages.length; k++) {
                    if (stages[parseInt(k.toString(), 10)].height > newlevel.height) {
                        newlevel.height = stages[parseInt(k.toString(), 10)].height;
                    }
                    newlevel.actualCircumference += Math.max(stages[parseInt(k.toString(), 10)].width, stages[parseInt(k.toString(), 10)].height);
                    if (k !== stages.length - 1) {
                        newlevel.actualCircumference += layout.horizontalSpacing;
                    }
                }
                newlevel.circumference = newlevel.max - newlevel.min;
                Eif (newlevel.actualCircumference < newlevel.circumference) {
                    newlevel.circumference = (newlevel.circumference + newlevel.actualCircumference) / 2;
                }
                newlevel.radius = newlevel.circumference / (2 * Math.PI) + newlevel.height;
                newlevel.nodes = [];
                if (i > 1) {
                    Eif (layout.levels[i - 1].radius + layout.levels[i - 1].height >= newlevel.radius) {
                        newlevel.radius = layout.levels[i - 1].radius + layout.levels[i - 1].height;
                    }
                }
                for (var j = 0; j < stages.length; j++) {
                    stages[parseInt(j.toString(), 10)].ratio = Math.abs(stages[parseInt(j.toString(), 10)].x
                        + stages[parseInt(j.toString(), 10)].width / 2 - min) / full;
                    newlevel.nodes.push(stages[parseInt(j.toString(), 10)]);
                }
                layout.levels.push(newlevel);
            };
            for (var i = 0; i <= layout.maxLevel; i++) {
                _loop_1(i);
            }
        };
        RadialTree.prototype.transformToCircleLayout = function (layout) {
            var root = layout.graphNodes[layout.centerNode.id];
            root.x = 0;
            root.y = 0;
            for (var i = 1; i < layout.levels.length; i++) {
                for (var j = 0; j < layout.levels[parseInt(i.toString(), 10)].nodes.length; j++) {
                    var nodeInfo = layout.levels[parseInt(i.toString(), 10)].nodes[parseInt(j.toString(), 10)];
                    nodeInfo.x = Math.cos(nodeInfo.ratio * 360 * Math.PI / 180)
                        * (layout.levels[parseInt(i.toString(), 10)].radius + layout.verticalSpacing * i);
                    nodeInfo.y = Math.sin(nodeInfo.ratio * 360 * Math.PI / 180)
                        * (layout.levels[parseInt(i.toString(), 10)].radius + layout.verticalSpacing * i);
                    layout.anchorX = Math.min(layout.anchorX, nodeInfo.x);
                    layout.anchorY = Math.min(layout.anchorY, nodeInfo.y);
                }
            }
        };
        RadialTree.prototype.updateAnchor = function (layout, viewPort) {
            layout.anchorX = layout.centerNode.offsetX || viewPort.x / 2;
            layout.anchorY = layout.centerNode.offsetY || viewPort.y / 2;
        };
        RadialTree.prototype.updateNodes = function (layout, node, nameTable) {
            var nodeInfo = layout.graphNodes[node.id];
            var offsetX = nodeInfo.x + layout.anchorX;
            var offsetY = nodeInfo.y + layout.anchorY;
            node.offsetX = offsetX;
            node.offsetY = offsetY;
            for (var i = 0; i < nodeInfo.children.length; i++) {
                var childInfo = nodeInfo.children[parseInt(i.toString(), 10)];
                this.updateNodes(layout, nameTable[childInfo.id], nameTable);
            }
        };
        RadialTree.prototype.setUpLayoutInfo = function (layout, item) {
            var info = {};
            info.name = item.id;
            info.x = 0;
            info.y = 0;
            info.min = 0;
            info.max = 0;
            info.width = item.actualSize.width;
            info.height = item.actualSize.height;
            info.children = [];
            info.level = 0;
            info.ratio = 0;
            info.visited = false;
            return info;
        };
        return RadialTree;
    }());
    exports.RadialTree = RadialTree;
});