1/** 2 * Copyright (c) 2006-2017, JGraph Ltd 3 * Copyright (c) 2006-2017, Gaudenz Alder 4 */ 5(function() 6{ 7 /** 8 * Defines resources. 9 */ 10 EditorUi.prototype.altShiftActions[68] = 'selectDescendants'; // Alt+Shift+D 11 12 /** 13 * Overrides folding based on treeFolding style. 14 */ 15 var graphFoldCells = Graph.prototype.foldCells; 16 17 Graph.prototype.foldCells = function(collapse, recurse, cells, checkFoldable, evt) 18 { 19 recurse = (recurse != null) ? recurse : false; 20 21 if (cells == null) 22 { 23 cells = this.getFoldableCells(this.getSelectionCells(), collapse); 24 } 25 26 this.stopEditing(); 27 28 this.model.beginUpdate(); 29 try 30 { 31 var newCells = cells.slice(); 32 var tmp = []; 33 34 for (var i = 0; i < cells.length; i++) 35 { 36 if (mxUtils.getValue(this.getCurrentCellStyle(cells[i]), 37 'treeFolding', '0') == '1') 38 { 39 this.foldTreeCell(collapse, cells[i]); 40 } 41 } 42 43 cells = newCells; 44 cells = graphFoldCells.apply(this, arguments); 45 } 46 finally 47 { 48 this.model.endUpdate(); 49 } 50 51 return cells; 52 }; 53 54 /** 55 * Implements folding a tree cell. 56 */ 57 Graph.prototype.foldTreeCell = function(collapse, cell) 58 { 59 this.model.beginUpdate(); 60 try 61 { 62 var tmp = []; 63 64 this.traverse(cell, true, mxUtils.bind(this, function(vertex, edge) 65 { 66 var treeEdge = edge != null && this.isTreeEdge(edge); 67 68 if (treeEdge) 69 { 70 tmp.push(edge); 71 } 72 73 if (vertex != cell && (edge == null || treeEdge)) 74 { 75 tmp.push(vertex); 76 } 77 78 // Stops traversal on collapsed vertices 79 return (edge == null || treeEdge) && 80 (vertex == cell || !this.model.isCollapsed(vertex)); 81 })); 82 83 this.model.setCollapsed(cell, collapse); 84 85 for (var i = 0; i < tmp.length; i++) 86 { 87 this.model.setVisible(tmp[i], !collapse); 88 } 89 } 90 finally 91 { 92 this.model.endUpdate(); 93 } 94 }; 95 96 /** 97 * Implements folding a tree cell. 98 */ 99 Graph.prototype.isTreeEdge = function(cell) 100 { 101 return !this.isEdgeIgnored(cell); 102 }; 103 104 /** 105 * Returns all tree edges for the given cell. 106 */ 107 Graph.prototype.getTreeEdges = function(cell, parent, incoming, outgoing, includeLoops, recurse) 108 { 109 return this.model.filterCells(this.getEdges(cell, parent, incoming, outgoing, includeLoops, recurse), mxUtils.bind(this, function(cell) 110 { 111 return this.isTreeEdge(cell); 112 })); 113 }; 114 115 /** 116 * Returns all incoming tree edges for the given cell. 117 */ 118 Graph.prototype.getIncomingTreeEdges = function(cell, parent) 119 { 120 return this.getTreeEdges(cell, parent, true, false, false); 121 }; 122 123 /** 124 * Returns all outgoing tree edges for the given cell. 125 */ 126 Graph.prototype.getOutgoingTreeEdges = function(cell, parent) 127 { 128 return this.getTreeEdges(cell, parent, false, true, false); 129 }; 130 131 /** 132 * Overrides functionality in editor. 133 */ 134 var editorUiInit = EditorUi.prototype.init; 135 136 EditorUi.prototype.init = function() 137 { 138 editorUiInit.apply(this, arguments); 139 140 if (!this.editor.isChromelessView() || this.editor.editable) 141 { 142 this.addTrees(); 143 } 144 }; 145 146 EditorUi.prototype.addTrees = function() 147 { 148 var ui = this; 149 var graph = ui.editor.graph; 150 var model = graph.getModel(); 151 var spacing = 10; 152 var level = 40; 153 154 function isTreeVertex(cell) 155 { 156 return model.isVertex(cell) && hasTreeParent(cell); 157 }; 158 159 function isTreeMoving(cell) 160 { 161 var result = false; 162 163 if (cell != null) 164 { 165 var style = graph.getCurrentCellStyle(cell); 166 167 result = style['treeMoving'] == '1'; 168 } 169 170 return result; 171 }; 172 173 function hasTreeParent(cell) 174 { 175 var result = false; 176 177 if (cell != null) 178 { 179 var parent = model.getParent(cell); 180 var pstate = graph.view.getState(parent); 181 var style = (pstate != null) ? pstate.style : graph.getCellStyle(parent); 182 183 result = style['containerType'] == 'tree'; 184 } 185 186 return result; 187 }; 188 189 function hasLayoutParent(cell) 190 { 191 var result = false; 192 193 if (cell != null) 194 { 195 var parent = model.getParent(cell); 196 var pstate = graph.view.getState(parent); 197 198 var state = graph.view.getState(parent); 199 var style = (pstate != null) ? pstate.style : graph.getCellStyle(parent); 200 201 result = style['childLayout'] != null; 202 } 203 204 return result; 205 }; 206 207 var uiCreatePopupMenu = ui.menus.createPopupMenu; 208 ui.menus.createPopupMenu = function(menu, cell, evt) 209 { 210 uiCreatePopupMenu.apply(this, arguments); 211 212 if (graph.getSelectionCount() == 1) 213 { 214 var cell = graph.getSelectionCell(); 215 var sib = graph.getOutgoingTreeEdges(cell); 216 menu.addSeparator(); 217 218 if (sib.length > 0) 219 { 220 if (isTreeVertex(graph.getSelectionCell())) 221 { 222 this.addMenuItems(menu, ['selectChildren'], null, evt); 223 } 224 225 this.addMenuItems(menu, ['selectDescendants'], null, evt); 226 } 227 228 if (isTreeVertex(graph.getSelectionCell())) 229 { 230 menu.addSeparator(); 231 232 if (graph.getIncomingTreeEdges(cell).length > 0) 233 { 234 this.addMenuItems(menu, ['selectSiblings', 'selectParent'], null, evt); 235 } 236 } 237 else if (graph.model.getEdgeCount(cell) > 0) 238 { 239 this.addMenuItems(menu, ['selectConnections'], null, evt); 240 } 241 } 242 }; 243 244 // Adds actions 245 ui.actions.addAction('selectChildren', function() 246 { 247 if (graph.isEnabled() && graph.getSelectionCount() == 1) 248 { 249 var cell = graph.getSelectionCell(); 250 var sib = graph.getOutgoingTreeEdges(cell); 251 252 if (sib != null) 253 { 254 var tmp = []; 255 256 for (var i = 0; i < sib.length; i++) 257 { 258 tmp.push(graph.model.getTerminal(sib[i], false)); 259 } 260 261 graph.setSelectionCells(tmp); 262 } 263 } 264 }, null, null, 'Alt+Shift+X'); 265 266 // Adds actions 267 ui.actions.addAction('selectSiblings', function() 268 { 269 if (graph.isEnabled() && graph.getSelectionCount() == 1) 270 { 271 var cell = graph.getSelectionCell(); 272 var edges = graph.getIncomingTreeEdges(cell); 273 274 if (edges != null && edges.length > 0) 275 { 276 var sib = graph.getOutgoingTreeEdges(graph.model.getTerminal(edges[0], true)); 277 278 if (sib != null) 279 { 280 var tmp = []; 281 282 for (var i = 0; i < sib.length; i++) 283 { 284 tmp.push(graph.model.getTerminal(sib[i], false)); 285 } 286 287 graph.setSelectionCells(tmp); 288 } 289 } 290 } 291 }, null, null, 'Alt+Shift+S'); 292 293 // Adds actions 294 ui.actions.addAction('selectParent', function() 295 { 296 if (graph.isEnabled() && graph.getSelectionCount() == 1) 297 { 298 var cell = graph.getSelectionCell(); 299 var edges = graph.getIncomingTreeEdges(cell); 300 301 if (edges != null && edges.length > 0) 302 { 303 graph.setSelectionCell(graph.model.getTerminal(edges[0], true)); 304 } 305 } 306 }, null, null, 'Alt+Shift+P'); 307 308 ui.actions.addAction('selectDescendants', function(trigger, evt) 309 { 310 var cell = graph.getSelectionCell(); 311 312 if (graph.isEnabled() && graph.model.isVertex(cell)) 313 { 314 if (evt != null && mxEvent.isAltDown(evt)) 315 { 316 graph.setSelectionCells(graph.model.getTreeEdges(cell, 317 evt == null || !mxEvent.isShiftDown(evt), 318 evt == null || !mxEvent.isControlDown(evt))); 319 } 320 else 321 { 322 var subtree = []; 323 324 graph.traverse(cell, true, function(vertex, edge) 325 { 326 var treeEdge = edge != null && graph.isTreeEdge(edge); 327 328 if (treeEdge) 329 { 330 subtree.push(edge); 331 } 332 333 if ((edge == null || treeEdge) && 334 (evt == null || !mxEvent.isShiftDown(evt))) 335 { 336 subtree.push(vertex); 337 } 338 339 return edge == null || treeEdge; 340 }); 341 } 342 343 graph.setSelectionCells(subtree); 344 } 345 }, null, null, 'Alt+Shift+D'); 346 347 /** 348 * Overriddes 349 */ 350 var graphRemoveCells = graph.removeCells; 351 352 graph.removeCells = function(cells, includeEdges) 353 { 354 includeEdges = (includeEdges != null) ? includeEdges : true; 355 356 if (cells == null) 357 { 358 cells = this.getDeletableCells(this.getSelectionCells()); 359 } 360 361 // Adds all edges to the cells 362 if (includeEdges) 363 { 364 // FIXME: Remove duplicate cells in result or do not add if 365 // in cells or descendant of cells 366 cells = this.getDeletableCells(this.addAllEdges(cells)); 367 } 368 369 var tmp = []; 370 371 for (var i = 0; i < cells.length; i++) 372 { 373 var target = cells[i]; 374 375 if (model.isEdge(target) && hasTreeParent(target)) 376 { 377 tmp.push(target); 378 target = model.getTerminal(target, false); 379 } 380 381 if (isTreeVertex(target)) 382 { 383 var subtree = []; 384 385 graph.traverse(target, true, function(vertex, edge) 386 { 387 var treeEdge = edge != null && graph.isTreeEdge(edge); 388 389 if (treeEdge) 390 { 391 subtree.push(edge); 392 } 393 394 if (edge == null || treeEdge) 395 { 396 subtree.push(vertex); 397 } 398 399 return edge == null || treeEdge; 400 }); 401 402 if (subtree.length > 0) 403 { 404 tmp = tmp.concat(subtree); 405 var edges = graph.getIncomingTreeEdges(cells[i]); 406 cells = cells.concat(edges); 407 } 408 } 409 else if (target != null) 410 { 411 tmp.push(cells[i]); 412 } 413 } 414 415 cells = tmp; 416 417 return graphRemoveCells.apply(this, arguments); 418 }; 419 420 ui.hoverIcons.getStateAt = function(state, x, y) 421 { 422 return (isTreeVertex(state.cell)) ? null : this.graph.view.getState(this.graph.getCellAt(x, y)); 423 }; 424 425 var graphDuplicateCells = graph.duplicateCells; 426 427 graph.duplicateCells = function(cells, append) 428 { 429 cells = (cells != null) ? cells : this.getSelectionCells(); 430 var temp = cells.slice(0); 431 432 for (var i = 0; i < temp.length; i++) 433 { 434 var cell = temp[i]; 435 var state = graph.view.getState(cell); 436 437 if (state != null && isTreeVertex(state.cell)) 438 { 439 // Avoids disconnecting subtree by removing all incoming edges 440 var edges = graph.getIncomingTreeEdges(state.cell); 441 442 for (var j = 0; j < edges.length; j++) 443 { 444 mxUtils.remove(edges[j], cells); 445 } 446 } 447 } 448 449 this.model.beginUpdate(); 450 try 451 { 452 var result = graphDuplicateCells.call(this, cells, append); 453 454 if (result.length == cells.length) 455 { 456 for (var i = 0; i < cells.length; i++) 457 { 458 if (isTreeVertex(cells[i])) 459 { 460 var newEdges = graph.getIncomingTreeEdges(result[i]); 461 var edges = graph.getIncomingTreeEdges(cells[i]); 462 463 if (newEdges.length == 0 && edges.length > 0) 464 { 465 var clone = this.cloneCell(edges[0]); 466 this.addEdge(clone, graph.getDefaultParent(), 467 this.model.getTerminal(edges[0], true), result[i]); 468 } 469 } 470 } 471 } 472 } 473 finally 474 { 475 this.model.endUpdate(); 476 } 477 478 return result; 479 }; 480 481 var graphMoveCells = graph.moveCells; 482 483 graph.moveCells = function(cells, dx, dy, clone, target, evt, mapping) 484 { 485 var result = null; 486 487 this.model.beginUpdate(); 488 try 489 { 490 var newSource = target; 491 var style = this.getCurrentCellStyle(target); 492 493 if (cells != null && isTreeVertex(target) && mxUtils.getValue(style, 'treeFolding', '0') == '1') 494 { 495 // Handles only drag from tree or from sidebar with dangling edges 496 for (var i = 0; i < cells.length; i++) 497 { 498 if (isTreeVertex(cells[i]) || (graph.model.isEdge(cells[i]) && 499 graph.model.getTerminal(cells[i], true) == null)) 500 { 501 target = graph.model.getParent(cells[i]); 502 break; 503 } 504 } 505 506 // Applies distance between previous and current parent for non-sidebar drags 507 if (newSource != null && target != newSource && this.view.getState(cells[0]) != null) 508 { 509 var edges = graph.getIncomingTreeEdges(cells[0]); 510 511 if (edges.length > 0) 512 { 513 var state1 = graph.view.getState(graph.model.getTerminal(edges[0], true)); 514 515 if (state1 != null) 516 { 517 var state2 = graph.view.getState(newSource); 518 519 if (state2 != null) 520 { 521 dx = (state2.getCenterX() - state1.getCenterX()) / graph.view.scale; 522 dy = (state2.getCenterY() - state1.getCenterY()) / graph.view.scale; 523 } 524 } 525 } 526 } 527 } 528 529 result = graphMoveCells.apply(this, arguments); 530 531 if (result != null && cells != null && result.length == cells.length) 532 { 533 for (var i = 0; i < result.length; i++) 534 { 535 // Connects all dangling edges from the sidebar 536 // when dropped into drop target (not hover icon) 537 if (this.model.isEdge(result[i])) 538 { 539 if (isTreeVertex(newSource) && mxUtils.indexOf(result, 540 this.model.getTerminal(result[i], true)) < 0) 541 { 542 this.model.setTerminal(result[i], newSource, true); 543 } 544 } 545 else if (isTreeVertex(cells[i])) 546 { 547 var edges = graph.getIncomingTreeEdges(cells[i]); 548 549 if (edges.length > 0) 550 { 551 if (!clone) 552 { 553 if (isTreeVertex(newSource) && mxUtils.indexOf(cells, 554 this.model.getTerminal(edges[0], true)) < 0) 555 { 556 this.model.setTerminal(edges[0], newSource, true); 557 } 558 } 559 else 560 { 561 var newEdges = graph.getIncomingTreeEdges(result[i]); 562 563 if (newEdges.length == 0) 564 { 565 var temp = newSource; 566 567 if (temp == null || temp == graph.model.getParent(cells[i])) 568 { 569 temp = graph.model.getTerminal(edges[0], true); 570 } 571 572 var clone = this.cloneCell(edges[0]); 573 this.addEdge(clone, graph.getDefaultParent(), temp, result[i]); 574 } 575 } 576 } 577 } 578 } 579 } 580 } 581 finally 582 { 583 this.model.endUpdate(); 584 } 585 586 return result; 587 }; 588 589 // Connects all dangling edges from the sidebar (by 590 // default only first dangling edge gets connected) 591 if (ui.sidebar != null) 592 { 593 var sidebarDropAndConnect = ui.sidebar.dropAndConnect; 594 595 ui.sidebar.dropAndConnect = function(source, targets, direction, dropCellIndex) 596 { 597 var model = graph.model; 598 var result = null; 599 600 model.beginUpdate(); 601 try 602 { 603 result = sidebarDropAndConnect.apply(this, arguments); 604 605 if (isTreeVertex(source)) 606 { 607 for (var i = 0; i < result.length; i++) 608 { 609 if (model.isEdge(result[i]) && model.getTerminal(result[i], true) == null) 610 { 611 model.setTerminal(result[i], source, true); 612 var geo = graph.getCellGeometry(result[i]); 613 geo.points = null; 614 615 if (geo.getTerminalPoint(true) != null) 616 { 617 geo.setTerminalPoint(null, true); 618 } 619 } 620 } 621 } 622 } 623 finally 624 { 625 model.endUpdate(); 626 } 627 628 return result; 629 }; 630 } 631 632 /** 633 * Checks source point of incoming edge relative to target terminal. 634 */ 635 function getTreeDirection(cell) 636 { 637 var state = graph.view.getState(cell); 638 639 if (state != null) 640 { 641 var edges = graph.getIncomingTreeEdges(state.cell); 642 643 if (edges.length > 0) 644 { 645 var edgeState = graph.view.getState(edges[0]); 646 647 if (edgeState != null) 648 { 649 var abs = edgeState.absolutePoints; 650 651 if (abs != null && abs.length > 0) 652 { 653 var pt = abs[abs.length - 1]; 654 655 if (pt != null) 656 { 657 if (pt.y == state.y && Math.abs(pt.x - state.getCenterX()) < state.width / 2) 658 { 659 return mxConstants.DIRECTION_SOUTH; 660 } 661 else if (pt.y == state.y + state.height && Math.abs(pt.x - state.getCenterX()) < state.width / 2) 662 { 663 return mxConstants.DIRECTION_NORTH; 664 } 665 else if (pt.x > state.getCenterX()) 666 { 667 return mxConstants.DIRECTION_WEST; 668 } 669 } 670 } 671 } 672 } 673 } 674 675 return mxConstants.DIRECTION_EAST; 676 }; 677 678 function addSibling(cell, after) 679 { 680 after = (after != null) ? after : true; 681 682 graph.model.beginUpdate(); 683 try 684 { 685 var parent = graph.model.getParent(cell); 686 var edges = graph.getIncomingTreeEdges(cell); 687 var clones = graph.cloneCells([edges[0], cell]); 688 graph.model.setTerminal(clones[0], graph.model.getTerminal(edges[0], true), true); 689 var dir = getTreeDirection(cell); 690 var pgeo = parent.geometry; 691 692 if (dir == mxConstants.DIRECTION_SOUTH || dir == mxConstants.DIRECTION_NORTH) 693 { 694 clones[1].geometry.x += (after) ? cell.geometry.width + spacing : 695 -clones[1].geometry.width - spacing; 696 } 697 else 698 { 699 clones[1].geometry.y += (after) ? cell.geometry.height + spacing : 700 -clones[1].geometry.height - spacing; 701 } 702 703 if (graph.view.currentRoot != parent) 704 { 705 clones[1].geometry.x -= pgeo.x; 706 clones[1].geometry.y -= pgeo.y; 707 } 708 709 // Moves existing siblings 710 var state = graph.view.getState(cell); 711 var s = graph.view.scale; 712 713 if (state != null) 714 { 715 var bbox = mxRectangle.fromRectangle(state); 716 717 if (dir == mxConstants.DIRECTION_SOUTH || 718 dir == mxConstants.DIRECTION_NORTH) 719 { 720 bbox.x += ((after) ? cell.geometry.width + spacing : 721 -clones[1].geometry.width - spacing) * s; 722 } 723 else 724 { 725 bbox.y += ((after) ? cell.geometry.height + spacing : 726 -clones[1].geometry.height - spacing) * s; 727 } 728 729 var sib = graph.getOutgoingTreeEdges(graph.model.getTerminal(edges[0], true)); 730 731 if (sib != null) 732 { 733 var hor = (dir == mxConstants.DIRECTION_SOUTH || dir == mxConstants.DIRECTION_NORTH); 734 var dx = 0; 735 var dy = 0; 736 737 for (var i = 0; i < sib.length; i++) 738 { 739 var temp = graph.model.getTerminal(sib[i], false); 740 741 if (dir == getTreeDirection(temp)) 742 { 743 var sibling = graph.view.getState(temp); 744 745 if (temp != cell && sibling != null) 746 { 747 if ((hor && after != sibling.getCenterX() < state.getCenterX()) || 748 (!hor && after != sibling.getCenterY() < state.getCenterY())) 749 { 750 if (mxUtils.intersects(bbox, sibling)) 751 { 752 dx = spacing + Math.max(dx, (Math.min(bbox.x + bbox.width, 753 sibling.x + sibling.width) - Math.max(bbox.x, sibling.x)) / s); 754 dy = spacing + Math.max(dy, (Math.min(bbox.y + bbox.height, 755 sibling.y + sibling.height) - Math.max(bbox.y, sibling.y)) / s); 756 } 757 } 758 } 759 } 760 } 761 762 if (hor) 763 { 764 dy = 0; 765 } 766 else 767 { 768 dx = 0; 769 } 770 771 for (var i = 0; i < sib.length; i++) 772 { 773 var temp = graph.model.getTerminal(sib[i], false); 774 775 if (dir == getTreeDirection(temp)) 776 { 777 var sibling = graph.view.getState(temp); 778 779 if (temp != cell && sibling != null) 780 { 781 if ((hor && after != sibling.getCenterX() < state.getCenterX()) || 782 (!hor && after != sibling.getCenterY() < state.getCenterY())) 783 { 784 var subtree = []; 785 786 graph.traverse(sibling.cell, true, function(vertex, edge) 787 { 788 var treeEdge = edge != null && graph.isTreeEdge(edge); 789 790 if (treeEdge) 791 { 792 subtree.push(edge); 793 } 794 795 if (edge == null || treeEdge) 796 { 797 subtree.push(vertex); 798 } 799 800 return edge == null || treeEdge; 801 }); 802 803 graph.moveCells(subtree, ((after) ? 1 : -1) * dx, ((after) ? 1 : -1) * dy); 804 } 805 } 806 } 807 } 808 } 809 } 810 811 return graph.addCells(clones, parent); 812 } 813 finally 814 { 815 graph.model.endUpdate(); 816 } 817 }; 818 819 function addParent(cell) 820 { 821 graph.model.beginUpdate(); 822 try 823 { 824 var dir = getTreeDirection(cell); 825 var edges = graph.getIncomingTreeEdges(cell); 826 var clones = graph.cloneCells([edges[0], cell]); 827 graph.model.setTerminal(edges[0], clones[1], false); 828 graph.model.setTerminal(clones[0], clones[1], true); 829 graph.model.setTerminal(clones[0], cell, false); 830 831 // Makes space for new parent 832 var parent = graph.model.getParent(cell); 833 var pgeo = parent.geometry; 834 var subtree = []; 835 836 if (graph.view.currentRoot != parent) 837 { 838 clones[1].geometry.x -= pgeo.x; 839 clones[1].geometry.y -= pgeo.y; 840 } 841 842 graph.traverse(cell, true, function(vertex, edge) 843 { 844 var treeEdge = edge != null && graph.isTreeEdge(edge); 845 846 if (treeEdge) 847 { 848 subtree.push(edge); 849 } 850 851 if (edge == null || treeEdge) 852 { 853 subtree.push(vertex); 854 } 855 856 return edge == null || treeEdge; 857 }); 858 859 var dx = cell.geometry.width + level; 860 var dy = cell.geometry.height + level; 861 862 if (dir == mxConstants.DIRECTION_SOUTH) 863 { 864 dx = 0; 865 } 866 else if (dir == mxConstants.DIRECTION_NORTH) 867 { 868 dx = 0; 869 dy = -dy; 870 } 871 else if (dir == mxConstants.DIRECTION_WEST) 872 { 873 dx = -dx; 874 dy = 0; 875 } 876 else if (dir == mxConstants.DIRECTION_EAST) 877 { 878 dy = 0; 879 } 880 881 graph.moveCells(subtree, dx, dy); 882 883 return graph.addCells(clones, parent); 884 } 885 finally 886 { 887 graph.model.endUpdate(); 888 } 889 }; 890 891 function addChild(cell, direction) 892 { 893 graph.model.beginUpdate(); 894 try 895 { 896 var parent = graph.model.getParent(cell); 897 var edges = graph.getIncomingTreeEdges(cell); 898 var dir = getTreeDirection(cell); 899 900 // Handles special case for click on tree root 901 if (edges.length == 0) 902 { 903 edges = [graph.createEdge(parent, null, '', null, null, 904 graph.createCurrentEdgeStyle())]; 905 dir = direction; 906 } 907 908 var clones = graph.cloneCells([edges[0], cell]); 909 graph.model.setTerminal(clones[0], cell, true); 910 911 if (graph.model.getTerminal(clones[0], false) == null) 912 { 913 graph.model.setTerminal(clones[0], clones[1], false); 914 915 var style = graph.getCellStyle(clones[1]); 916 var temp = style['newEdgeStyle']; 917 918 if (temp != null) 919 { 920 try 921 { 922 var styles = JSON.parse(temp); 923 924 for (var key in styles) 925 { 926 graph.setCellStyles(key, styles[key], [clones[0]]); 927 928 // Sets elbow direction 929 if (key == 'edgeStyle' && styles[key] == 'elbowEdgeStyle') 930 { 931 graph.setCellStyles('elbow', (dir == mxConstants.DIRECTION_SOUTH || 932 dir == mxConstants.DIRECTION_NOTH) ? 'vertical' : 'horizontal', 933 [clones[0]]); 934 } 935 } 936 } 937 catch (e) 938 { 939 // ignore 940 } 941 } 942 } 943 944 // Finds free space 945 var edges = graph.getOutgoingTreeEdges(cell); 946 var pgeo = parent.geometry; 947 var targets = []; 948 949 // Not offset if inside group 950 if (graph.view.currentRoot == parent) 951 { 952 pgeo = new mxRectangle(); 953 } 954 955 for (var i = 0; i < edges.length; i++) 956 { 957 var target = graph.model.getTerminal(edges[i], false); 958 959 if (target != null) 960 { 961 targets.push(target); 962 } 963 } 964 965 var bbox = graph.view.getBounds(targets); 966 var tr = graph.view.translate; 967 var s = graph.view.scale; 968 969 if (dir == mxConstants.DIRECTION_SOUTH) 970 { 971 clones[1].geometry.x = (bbox == null) ? cell.geometry.x + (cell.geometry.width - 972 clones[1].geometry.width) / 2 : (bbox.x + bbox.width) / s - tr.x - 973 pgeo.x + spacing; 974 clones[1].geometry.y += clones[1].geometry.height - pgeo.y + level; 975 } 976 else if (dir == mxConstants.DIRECTION_NORTH) 977 { 978 clones[1].geometry.x = (bbox == null) ? cell.geometry.x + (cell.geometry.width - 979 clones[1].geometry.width) / 2 : (bbox.x + bbox.width) / s - tr.x + - 980 pgeo.x + spacing; 981 clones[1].geometry.y -= clones[1].geometry.height + pgeo.y + level; 982 } 983 else if (dir == mxConstants.DIRECTION_WEST) 984 { 985 clones[1].geometry.x -= clones[1].geometry.width + pgeo.x + level; 986 clones[1].geometry.y = (bbox == null) ? cell.geometry.y + (cell.geometry.height - 987 clones[1].geometry.height) / 2 : (bbox.y + bbox.height) / s - tr.y + - 988 pgeo.y + spacing; 989 } 990 else 991 { 992 clones[1].geometry.x += clones[1].geometry.width - pgeo.x + level; 993 clones[1].geometry.y = (bbox == null) ? cell.geometry.y + (cell.geometry.height - 994 clones[1].geometry.height) / 2 : (bbox.y + bbox.height) / s - tr.y + - 995 pgeo.y + spacing; 996 } 997 998 return graph.addCells(clones, parent); 999 } 1000 finally 1001 { 1002 graph.model.endUpdate(); 1003 } 1004 }; 1005 1006 function getOrderedTargets(cell, horizontal, ref) 1007 { 1008 var sib = graph.getOutgoingTreeEdges(cell); 1009 var state = graph.view.getState(ref); 1010 var targets = []; 1011 1012 if (state != null && sib != null) 1013 { 1014 for (var i = 0; i < sib.length; i++) 1015 { 1016 var temp = graph.view.getState(graph.model.getTerminal(sib[i], false)); 1017 1018 if (temp != null && ((!horizontal && (Math.min(temp.x + temp.width, 1019 state.x + state.width) >= Math.max(temp.x, state.x))) || 1020 (horizontal && (Math.min(temp.y + temp.height, state.y + state.height) >= 1021 Math.max(temp.y, state.y))))) 1022 { 1023 targets.push(temp); 1024 } 1025 } 1026 1027 targets.sort(function(a, b) 1028 { 1029 return (horizontal) ? a.x + a.width - b.x - b.width : a.y + a.height - b.y - b.height; 1030 }); 1031 } 1032 1033 return targets; 1034 }; 1035 1036 function selectCell(cell, direction) 1037 { 1038 var dir = getTreeDirection(cell); 1039 var h1 = dir == mxConstants.DIRECTION_EAST || dir == mxConstants.DIRECTION_WEST; 1040 var h2 = direction == mxConstants.DIRECTION_EAST || direction == mxConstants.DIRECTION_WEST; 1041 1042 if (h1 == h2 && dir != direction) 1043 { 1044 ui.actions.get('selectParent').funct(); 1045 } 1046 else if (dir == direction) 1047 { 1048 var sib = graph.getOutgoingTreeEdges(cell); 1049 1050 if (sib != null && sib.length > 0) 1051 { 1052 graph.setSelectionCell(graph.model.getTerminal(sib[0], false)); 1053 } 1054 } 1055 else 1056 { 1057 var edges = graph.getIncomingTreeEdges(cell); 1058 1059 if (edges != null && edges.length > 0) 1060 { 1061 var targets = getOrderedTargets(graph.model.getTerminal(edges[0], true), h2, cell); 1062 var state = graph.view.getState(cell); 1063 1064 if (state != null) 1065 { 1066 var idx = mxUtils.indexOf(targets, state); 1067 1068 if (idx >= 0) 1069 { 1070 idx += (direction == mxConstants.DIRECTION_NORTH || direction == mxConstants.DIRECTION_WEST) ? -1 : 1; 1071 1072 if (idx >= 0 && idx <= targets.length - 1) 1073 { 1074 graph.setSelectionCell(targets[idx].cell); 1075 } 1076 } 1077 } 1078 } 1079 } 1080 }; 1081 1082 // Overrides keyboard shortcuts inside tree containers 1083 var altShiftActions = {88: ui.actions.get('selectChildren'), // Alt+Shift+X 1084 84: ui.actions.get('selectSubtree'), // Alt+Shift+T 1085 80: ui.actions.get('selectParent'), // Alt+Shift+P 1086 83: ui.actions.get('selectSiblings')} // Alt+Shift+S 1087 1088 var editorUiOnKeyDown = ui.onKeyDown; 1089 1090 ui.onKeyDown = function(evt) 1091 { 1092 try 1093 { 1094 if (graph.isEnabled() && !graph.isEditing() && 1095 isTreeVertex(graph.getSelectionCell()) && 1096 graph.getSelectionCount() == 1) 1097 { 1098 var cells = null; 1099 1100 if (graph.getIncomingTreeEdges(graph.getSelectionCell()).length > 0) 1101 { 1102 if (evt.which == 9) // Tab adds child 1103 { 1104 cells = (mxEvent.isShiftDown(evt)) ? 1105 addParent(graph.getSelectionCell()) : 1106 addChild(graph.getSelectionCell()); 1107 } 1108 else if (evt.which == 13) // Enter adds sibling 1109 { 1110 cells = addSibling(graph.getSelectionCell(), !mxEvent.isShiftDown(evt)); 1111 } 1112 } 1113 1114 if (cells != null && cells.length > 0) 1115 { 1116 if (cells.length == 1 && graph.model.isEdge(cells[0])) 1117 { 1118 graph.setSelectionCell(graph.model.getTerminal(cells[0], false)); 1119 } 1120 else 1121 { 1122 graph.setSelectionCell(cells[cells.length - 1]); 1123 } 1124 1125 if (ui.hoverIcons != null) 1126 { 1127 ui.hoverIcons.update(graph.view.getState(graph.getSelectionCell())); 1128 } 1129 1130 graph.startEditingAtCell(graph.getSelectionCell()); 1131 mxEvent.consume(evt); 1132 } 1133 else 1134 { 1135 if (mxEvent.isAltDown(evt) && mxEvent.isShiftDown(evt)) 1136 { 1137 var action = altShiftActions[evt.keyCode]; 1138 1139 if (action != null) 1140 { 1141 action.funct(evt); 1142 mxEvent.consume(evt); 1143 } 1144 } 1145 else 1146 { 1147 if (evt.keyCode == 37) // left 1148 { 1149 selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_WEST); 1150 mxEvent.consume(evt); 1151 } 1152 else if (evt.keyCode == 38) // up 1153 { 1154 selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_NORTH); 1155 mxEvent.consume(evt); 1156 } 1157 else if (evt.keyCode == 39) // right 1158 { 1159 selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_EAST); 1160 mxEvent.consume(evt); 1161 } 1162 else if (evt.keyCode == 40) // down 1163 { 1164 selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_SOUTH); 1165 mxEvent.consume(evt); 1166 } 1167 } 1168 } 1169 } 1170 } 1171 catch (e) 1172 { 1173 ui.handleError(e); 1174 } 1175 1176 if (!mxEvent.isConsumed(evt)) 1177 { 1178 editorUiOnKeyDown.apply(this, arguments); 1179 } 1180 }; 1181 1182 var graphConnectVertex = graph.connectVertex; 1183 1184 graph.connectVertex = function(source, direction, length, evt, forceClone, ignoreCellAt, targetCell) 1185 { 1186 var edges = graph.getIncomingTreeEdges(source); 1187 1188 if (isTreeVertex(source)) 1189 { 1190 var dir = getTreeDirection(source); 1191 var h1 = dir == mxConstants.DIRECTION_EAST || dir == mxConstants.DIRECTION_WEST; 1192 var h2 = direction == mxConstants.DIRECTION_EAST || direction == mxConstants.DIRECTION_WEST; 1193 1194 if (dir == direction || edges.length == 0) 1195 { 1196 return addChild(source, direction); 1197 } 1198 else if (h1 == h2) 1199 { 1200 return addParent(source); 1201 } 1202 else 1203 { 1204 return addSibling(source, direction != mxConstants.DIRECTION_NORTH && 1205 direction != mxConstants.DIRECTION_WEST); 1206 } 1207 } 1208 else 1209 { 1210 return graphConnectVertex.apply(this, arguments); 1211 } 1212 }; 1213 1214 graph.getSubtree = function(initialCell) 1215 { 1216 var cells = [initialCell]; 1217 1218 if ((isTreeMoving(initialCell) || isTreeVertex(initialCell)) && 1219 !hasLayoutParent(initialCell)) 1220 { 1221 // Gets the subtree from cell downwards 1222 graph.traverse(initialCell, true, function(vertex, edge) 1223 { 1224 var treeEdge = edge != null && graph.isTreeEdge(edge); 1225 1226 // LATER: Use dictionary to avoid duplicates 1227 if (treeEdge && mxUtils.indexOf(cells, edge) < 0) 1228 { 1229 cells.push(edge); 1230 } 1231 1232 if ((edge == null || treeEdge) && 1233 mxUtils.indexOf(cells, vertex) < 0) 1234 { 1235 cells.push(vertex); 1236 } 1237 1238 return edge == null || treeEdge; 1239 }); 1240 } 1241 1242 return cells; 1243 }; 1244 1245 var vertexHandlerInit = mxVertexHandler.prototype.init; 1246 1247 mxVertexHandler.prototype.init = function() 1248 { 1249 vertexHandlerInit.apply(this, arguments); 1250 1251 if (((isTreeMoving(this.state.cell) || isTreeVertex(this.state.cell)) && 1252 !hasLayoutParent(this.state.cell)) && this.graph.getOutgoingTreeEdges( 1253 this.state.cell).length > 0) 1254 { 1255 this.moveHandle = mxUtils.createImage(Editor.moveImage); 1256 this.moveHandle.setAttribute('title', 'Move Subtree'); 1257 this.moveHandle.style.position = 'absolute'; 1258 this.moveHandle.style.cursor = 'pointer'; 1259 this.moveHandle.style.width = '24px'; 1260 this.moveHandle.style.height = '24px'; 1261 this.graph.container.appendChild(this.moveHandle); 1262 1263 mxEvent.addGestureListeners(this.moveHandle, mxUtils.bind(this, function(evt) 1264 { 1265 this.graph.graphHandler.start(this.state.cell, 1266 mxEvent.getClientX(evt), mxEvent.getClientY(evt), 1267 this.graph.getSubtree(this.state.cell)); 1268 this.graph.graphHandler.cellWasClicked = true; 1269 this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt); 1270 this.graph.isMouseDown = true; 1271 ui.hoverIcons.reset(); 1272 mxEvent.consume(evt); 1273 })); 1274 } 1275 }; 1276 1277 var vertexHandlerRedrawHandles = mxVertexHandler.prototype.redrawHandles; 1278 1279 mxVertexHandler.prototype.redrawHandles = function() 1280 { 1281 vertexHandlerRedrawHandles.apply(this, arguments); 1282 1283 if (this.moveHandle != null) 1284 { 1285 this.moveHandle.style.left = this.state.x + this.state.width + 1286 ((this.state.width < 40) ? 10 : 0) + 2 + 'px'; 1287 this.moveHandle.style.top = this.state.y + this.state.height + 1288 ((this.state.height < 40) ? 10 : 0) + 2 + 'px'; 1289 } 1290 }; 1291 1292 var vertexHandlerSetHandlesVisible = mxVertexHandler.prototype.setHandlesVisible; 1293 1294 mxVertexHandler.prototype.setHandlesVisible = function(visible) 1295 { 1296 vertexHandlerSetHandlesVisible.apply(this, arguments); 1297 1298 if (this.moveHandle != null) 1299 { 1300 this.moveHandle.style.display = (visible) ? '' : 'none'; 1301 } 1302 }; 1303 1304 var vertexHandlerDestroy = mxVertexHandler.prototype.destroy; 1305 1306 mxVertexHandler.prototype.destroy = function(sender, me) 1307 { 1308 vertexHandlerDestroy.apply(this, arguments); 1309 1310 if (this.moveHandle != null) 1311 { 1312 this.moveHandle.parentNode.removeChild(this.moveHandle); 1313 this.moveHandle = null; 1314 } 1315 }; 1316 }; 1317 1318 /** 1319 * Adds shapes to sidebar in edit mode. 1320 */ 1321 if (typeof Sidebar !== 'undefined') 1322 { 1323 var sidebarCreateAdvancedShapes = Sidebar.prototype.createAdvancedShapes; 1324 Sidebar.prototype.createAdvancedShapes = function() 1325 { 1326 var result = sidebarCreateAdvancedShapes.apply(this, arguments); 1327 var graph = this.graph; 1328 1329 // Style that defines the key, value pairs to be used for creating styles of new connections if no incoming edge exists 1330 var mmEdgeStyle = 'newEdgeStyle={"edgeStyle":"entityRelationEdgeStyle","startArrow":"none","endArrow":"none","segment":10,"curved":1};'; 1331 var treeEdgeStyle = 'newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};'; 1332 1333 return result.concat([ 1334 this.addEntry('tree container', function() 1335 { 1336 var cell = new mxCell('Tree Container', new mxGeometry(0, 0, 400, 320), 1337 'swimlane;startSize=20;horizontal=1;containerType=tree;'); 1338 cell.vertex = true; 1339 1340 var cell2 = new mxCell('Parent', new mxGeometry(140, 60, 120, 40), 1341 'whiteSpace=wrap;html=1;treeFolding=1;treeMoving=1;' + treeEdgeStyle); 1342 cell2.vertex = true; 1343 1344 var cell3 = new mxCell('Child', new mxGeometry(140, 140, 120, 40), 1345 'whiteSpace=wrap;html=1;treeFolding=1;treeMoving=1;' + treeEdgeStyle); 1346 cell3.vertex = true; 1347 1348 var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 1349 'edgeStyle=elbowEdgeStyle;elbow=vertical;' + 1350 'startArrow=none;endArrow=none;rounded=0;'); 1351 edge.geometry.relative = true; 1352 edge.edge = true; 1353 1354 cell2.insertEdge(edge, true); 1355 cell3.insertEdge(edge, false); 1356 1357 cell.insert(edge); 1358 cell.insert(cell2); 1359 cell.insert(cell3); 1360 1361 return sb.createVertexTemplateFromCells([cell], cell.geometry.width, 1362 cell.geometry.height, cell.value); 1363 }), 1364 this.addEntry('tree mindmap mindmaps central idea branch topic', function() 1365 { 1366 var mindmap = new mxCell('Mindmap', new mxGeometry(0, 0, 420, 126), 1367 'swimlane;startSize=20;horizontal=1;containerType=tree;'); 1368 mindmap.vertex = true; 1369 1370 var cell = new mxCell('Central Idea', new mxGeometry(160, 60, 100, 40), 1371 'ellipse;whiteSpace=wrap;html=1;align=center;' + 1372 'treeFolding=1;treeMoving=1;' + mmEdgeStyle); 1373 cell.vertex = true; 1374 1375 var cell2 = new mxCell('Topic', new mxGeometry(320, 40, 80, 20), 1376 'whiteSpace=wrap;html=1;rounded=1;arcSize=50;align=center;verticalAlign=middle;' + 1377 'strokeWidth=1;autosize=1;spacing=4;treeFolding=1;treeMoving=1;' + mmEdgeStyle); 1378 cell2.vertex = true; 1379 1380 var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' + 1381 'startArrow=none;endArrow=none;segment=10;curved=1;'); 1382 edge.geometry.relative = true; 1383 edge.edge = true; 1384 1385 cell.insertEdge(edge, true); 1386 cell2.insertEdge(edge, false); 1387 1388 var cell3 = new mxCell('Branch', new mxGeometry(320, 80, 72, 26), 1389 'whiteSpace=wrap;html=1;shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];' + 1390 'fillColor=none;align=center;verticalAlign=bottom;routingCenterY=0.5;' + 1391 'snapToPoint=1;autosize=1;treeFolding=1;treeMoving=1;' + mmEdgeStyle); 1392 cell3.vertex = true; 1393 1394 var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' + 1395 'startArrow=none;endArrow=none;segment=10;curved=1;'); 1396 edge2.geometry.relative = true; 1397 edge2.edge = true; 1398 1399 cell.insertEdge(edge2, true); 1400 cell3.insertEdge(edge2, false); 1401 1402 var cell4 = new mxCell('Topic', new mxGeometry(20, 40, 80, 20), 1403 'whiteSpace=wrap;html=1;rounded=1;arcSize=50;align=center;verticalAlign=middle;' + 1404 'strokeWidth=1;autosize=1;spacing=4;treeFolding=1;treeMoving=1;' + mmEdgeStyle); 1405 cell4.vertex = true; 1406 1407 var edge3 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' + 1408 'startArrow=none;endArrow=none;segment=10;curved=1;'); 1409 edge3.geometry.relative = true; 1410 edge3.edge = true; 1411 1412 cell.insertEdge(edge3, true); 1413 cell4.insertEdge(edge3, false); 1414 1415 var cell5 = new mxCell('Branch', new mxGeometry(20, 80, 72, 26), 1416 'whiteSpace=wrap;html=1;shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];' + 1417 'fillColor=none;align=center;verticalAlign=bottom;routingCenterY=0.5;' + 1418 'snapToPoint=1;autosize=1;treeFolding=1;treeMoving=1;' + mmEdgeStyle); 1419 cell5.vertex = true; 1420 1421 var edge4 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' + 1422 'startArrow=none;endArrow=none;segment=10;curved=1;'); 1423 edge4.geometry.relative = true; 1424 edge4.edge = true; 1425 1426 cell.insertEdge(edge4, true); 1427 cell5.insertEdge(edge4, false); 1428 1429 mindmap.insert(edge); 1430 mindmap.insert(edge2); 1431 mindmap.insert(edge3); 1432 mindmap.insert(edge4); 1433 mindmap.insert(cell); 1434 mindmap.insert(cell2); 1435 mindmap.insert(cell3); 1436 mindmap.insert(cell4); 1437 mindmap.insert(cell5); 1438 1439 return sb.createVertexTemplateFromCells([mindmap], mindmap.geometry.width, 1440 mindmap.geometry.height, mindmap.value); 1441 }), 1442 this.addEntry('tree mindmap mindmaps central idea', function() 1443 { 1444 var cell = new mxCell('Central Idea', new mxGeometry(0, 0, 100, 40), 1445 'ellipse;whiteSpace=wrap;html=1;align=center;' + mmEdgeStyle + 1446 'treeFolding=1;treeMoving=1;'); 1447 cell.vertex = true; 1448 1449 return sb.createVertexTemplateFromCells([cell], cell.geometry.width, 1450 cell.geometry.height, cell.value); 1451 }), 1452 this.addEntry('tree mindmap mindmaps branch', function() 1453 { 1454 var cell = new mxCell('Branch', new mxGeometry(0, 0, 80, 20), 1455 'whiteSpace=wrap;html=1;shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];' + 1456 'fillColor=none;align=center;verticalAlign=bottom;routingCenterY=0.5;' + 1457 'snapToPoint=1;recursiveResize=0;autosize=1;treeFolding=1;treeMoving=1;' + mmEdgeStyle); 1458 cell.vertex = true; 1459 1460 var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' + 1461 'startArrow=none;endArrow=none;segment=10;curved=1;'); 1462 edge.geometry.setTerminalPoint(new mxPoint(-40, 40), true); 1463 edge.geometry.relative = true; 1464 edge.edge = true; 1465 1466 cell.insertEdge(edge, false); 1467 1468 return sb.createVertexTemplateFromCells([cell, edge], cell.geometry.width, 1469 cell.geometry.height, cell.value); 1470 }), 1471 this.addEntry('tree mindmap mindmaps sub topic', function() 1472 { 1473 var cell = new mxCell('Sub Topic', new mxGeometry(0, 0, 72, 26), 1474 'whiteSpace=wrap;html=1;rounded=1;arcSize=50;align=center;verticalAlign=middle;' + 1475 'strokeWidth=1;autosize=1;spacing=4;treeFolding=1;treeMoving=1;' + mmEdgeStyle); 1476 cell.vertex = true; 1477 1478 var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' + 1479 'startArrow=none;endArrow=none;segment=10;curved=1;'); 1480 edge.geometry.setTerminalPoint(new mxPoint(-40, 40), true); 1481 edge.geometry.relative = true; 1482 edge.edge = true; 1483 1484 cell.insertEdge(edge, false); 1485 1486 return sb.createVertexTemplateFromCells([cell, edge], cell.geometry.width, 1487 cell.geometry.height, cell.value); 1488 }), 1489 this.addEntry('tree orgchart organization division', function() 1490 { 1491 var orgchart = new mxCell('Orgchart', new mxGeometry(0, 0, 280, 220), 1492 'swimlane;startSize=20;horizontal=1;containerType=tree;' + treeEdgeStyle); 1493 orgchart.vertex = true; 1494 1495 var cell = new mxCell('Organization', new mxGeometry(80, 40, 120, 60), 1496 'whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;' + treeEdgeStyle); 1497 graph.setAttributeForCell(cell, 'treeRoot', '1'); 1498 cell.vertex = true; 1499 1500 var cell2 = new mxCell('Division', new mxGeometry(20, 140, 100, 60), 1501 'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;' + treeEdgeStyle); 1502 cell2.vertex = true; 1503 1504 var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 1505 'edgeStyle=elbowEdgeStyle;elbow=vertical;' + 1506 'startArrow=none;endArrow=none;rounded=0;'); 1507 edge.geometry.relative = true; 1508 edge.edge = true; 1509 1510 cell.insertEdge(edge, true); 1511 cell2.insertEdge(edge, false); 1512 1513 var cell3 = new mxCell('Division', new mxGeometry(160, 140, 100, 60), 1514 'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;' + treeEdgeStyle); 1515 cell3.vertex = true; 1516 1517 var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 1518 'edgeStyle=elbowEdgeStyle;elbow=vertical;' + 1519 'startArrow=none;endArrow=none;rounded=0;'); 1520 edge2.geometry.relative = true; 1521 edge2.edge = true; 1522 1523 cell.insertEdge(edge2, true); 1524 cell3.insertEdge(edge2, false); 1525 1526 orgchart.insert(edge); 1527 orgchart.insert(edge2); 1528 orgchart.insert(cell); 1529 orgchart.insert(cell2); 1530 orgchart.insert(cell3); 1531 1532 return sb.createVertexTemplateFromCells([orgchart], orgchart.geometry.width, 1533 orgchart.geometry.height, orgchart.value); 1534 }), 1535 this.addEntry('tree root', function() 1536 { 1537 var cell = new mxCell('Organization', new mxGeometry(0, 0, 120, 60), 1538 'whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;' + treeEdgeStyle); 1539 graph.setAttributeForCell(cell, 'treeRoot', '1'); 1540 cell.vertex = true; 1541 1542 return sb.createVertexTemplateFromCells([cell], cell.geometry.width, 1543 cell.geometry.height, cell.value); 1544 }), 1545 this.addEntry('tree division', function() 1546 { 1547 var cell = new mxCell('Division', new mxGeometry(20, 40, 100, 60), 1548 'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;' + treeEdgeStyle); 1549 cell.vertex = true; 1550 1551 var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 1552 'edgeStyle=elbowEdgeStyle;elbow=vertical;' + 1553 'startArrow=none;endArrow=none;rounded=0;'); 1554 edge.geometry.setTerminalPoint(new mxPoint(0, 0), true); 1555 edge.geometry.relative = true; 1556 edge.edge = true; 1557 1558 cell.insertEdge(edge, false); 1559 1560 return sb.createVertexTemplateFromCells([cell, edge], cell.geometry.width, 1561 cell.geometry.height, cell.value); 1562 }), 1563 this.addEntry('tree sub sections', function() 1564 { 1565 var cell = new mxCell('Sub Section', new mxGeometry(0, 0, 100, 60), 1566 'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;'); 1567 cell.vertex = true; 1568 1569 var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=orthogonalEdgeStyle;' + 1570 'startArrow=none;endArrow=none;rounded=0;targetPortConstraint=eastwest;sourcePortConstraint=northsouth;'); 1571 edge.geometry.setTerminalPoint(new mxPoint(110, -40), true); 1572 edge.geometry.relative = true; 1573 edge.edge = true; 1574 1575 cell.insertEdge(edge, false); 1576 1577 var cell2 = new mxCell('Sub Section', new mxGeometry(120, 0, 100, 60), 1578 'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;'); 1579 cell2.vertex = true; 1580 1581 var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=orthogonalEdgeStyle;' + 1582 'startArrow=none;endArrow=none;rounded=0;targetPortConstraint=eastwest;sourcePortConstraint=northsouth;'); 1583 edge2.geometry.setTerminalPoint(new mxPoint(110, -40), true); 1584 edge2.geometry.relative = true; 1585 edge2.edge = true; 1586 1587 cell2.insertEdge(edge2, false); 1588 1589 return sb.createVertexTemplateFromCells([edge, edge2, cell, cell2], 220, 60, 'Sub Sections'); 1590 }) 1591 ]); 1592 }; 1593 } 1594})(); 1595