1 19 20 package org.netbeans.core.windows.model; 21 22 23 24 import java.util.*; 25 import java.util.logging.Level ; 26 import java.util.logging.Logger ; 27 import org.netbeans.core.windows.*; 28 29 30 38 class SplitSubModel { 39 40 41 protected final Model parentModel; 42 43 44 private final Map<ModeImpl, ModeNode> modes2nodes = 45 new WeakHashMap<ModeImpl, ModeNode>(20); 46 47 49 protected Node root; 50 51 52 private static final boolean DEBUG = Debug.isLoggable(SplitSubModel.class); 53 54 55 56 public SplitSubModel(Model parentModel) { 57 this.parentModel = parentModel; 58 } 59 60 61 private ModeNode getModeNode(ModeImpl mode) { 62 synchronized(modes2nodes) { 63 ModeNode node = modes2nodes.get(mode); 64 if(node == null) { 65 node = new ModeNode(mode); 66 modes2nodes.put(mode, node); 67 } 68 69 return node; 70 } 71 } 72 73 public SplitConstraint[] getModelElementConstraints(ModelElement element) { 74 if(element instanceof Node) { 75 Node node = (Node)element; 76 if(!isInTree(node)) { 77 return null; 78 } 79 return node.getNodeConstraints(); 80 } 81 82 return null; 83 } 84 85 public SplitConstraint[] getModeConstraints(ModeImpl mode) { 86 ModeNode modeNode = getModeNode(mode); 87 return modeNode.getNodeConstraints(); 88 } 89 90 98 public String getSlideSideForMode( ModeImpl mode ) { 99 ModeNode modeNode = getModeNode( mode ); 100 return getPositionRelativeToEditor( modeNode, modeNode.getParent() ); 101 } 102 103 110 private String getPositionRelativeToEditor( Node node, SplitNode parent ) { 111 if( null == parent ) 112 return Constants.LEFT; 114 Node editorNode = getEditorChildNode( parent ); 115 if( null != editorNode ) { 116 int orientation = parent.getOrientation(); 119 int nodeIndex = parent.getChildIndex( node ); 120 int editorIndex = parent.getChildIndex( editorNode ); 121 if( orientation == Constants.VERTICAL ) { 122 if( nodeIndex > editorIndex ) 123 return Constants.BOTTOM; 124 return Constants.TOP; } else { 126 if( nodeIndex < editorIndex ) 127 return Constants.LEFT; 128 return Constants.RIGHT; 129 } 130 } 131 return getPositionRelativeToEditor( parent, parent.getParent() ); 133 } 134 135 142 private Node getEditorChildNode( SplitNode split ) { 143 List<Node> children = split.getChildren(); 144 for( Iterator<Node> i=children.iterator(); i.hasNext(); ) { 145 Node node = i.next(); 146 if( node instanceof EditorSplitSubModel.EditorNode 147 || 148 node instanceof SplitNode && null != getEditorChildNode( (SplitNode)node ) ) { 149 return node; 150 } 151 } 152 return null; 153 } 154 155 156 161 public boolean addMode(ModeImpl mode, SplitConstraint[] constraints) { 162 if(mode == null || constraints == null) { 164 Logger.getLogger(SplitSubModel.class.getName()).log(Level.WARNING, null, 165 new java.lang.IllegalArgumentException ("Mode=" + 166 mode + 167 " constraints=" + 168 Arrays.toString(constraints))); 169 return false; 170 } 171 172 173 Node modeNode = getModeNode(mode); 174 175 if(DEBUG) { 176 debugLog(""); debugLog(""); debugLog("=========================================="); debugLog("Adding mode to tree=" + mode); debugLog("constraints=" + Arrays.asList(constraints)); debugLog("modeNode=" + modeNode); } 183 184 return addNodeToTree(modeNode, constraints); 185 } 186 187 public boolean addModeToSide(ModeImpl mode, ModeImpl attachMode, String side) { 189 if(mode == null || mode.getState() == Constants.MODE_STATE_SEPARATED) { 190 Logger.getLogger(SplitSubModel.class.getName()).log(Level.WARNING, null, 191 new java.lang.IllegalArgumentException ("Mode=" + 192 mode)); 193 return false; 194 } 195 196 Node modeNode = getModeNode(mode); 197 Node attachModeNode = getModeNode(attachMode); 198 199 if(DEBUG) { 200 debugLog(""); debugLog(""); debugLog("=========================================="); debugLog("Adding mode to between=" + mode); debugLog("attachMode=" + attachMode); debugLog("side=" + side); } 207 208 return addNodeToTreeToSide(modeNode, attachModeNode, side); 209 } 210 211 public boolean addModeToSideRoot(ModeImpl mode, String side) { 212 if(mode == null || mode.getState() == Constants.MODE_STATE_SEPARATED) { 213 Logger.getLogger(SplitSubModel.class.getName()).log(Level.WARNING, null, 214 new java.lang.IllegalArgumentException ("Mode=" + 215 mode)); 216 return false; 217 } 218 219 Node modeNode = getModeNode(mode); 220 221 if(DEBUG) { 222 debugLog(""); debugLog(""); debugLog("=========================================="); debugLog("Adding mode to root's side=" + mode); debugLog("side=" + side); } 228 229 return addNodeToTreeToSide(modeNode, root, side); 230 } 231 232 public boolean addModeAround(ModeImpl mode, String side) { 234 if(mode == null || mode.getState() == Constants.MODE_STATE_SEPARATED) { 235 Logger.getLogger(SplitSubModel.class.getName()).log(Level.WARNING, null, 236 new java.lang.IllegalArgumentException ("Mode=" + 237 mode)); 238 return false; 239 } 240 241 Node modeNode = getModeNode(mode); 242 243 if(DEBUG) { 244 debugLog(""); debugLog(""); debugLog("=========================================="); debugLog("Adding mode to around=" + mode); debugLog("side=" + side); } 250 251 return addNodeToTreeAround(modeNode, side); 252 } 253 254 public boolean addModeAroundEditor(ModeImpl mode, String side) { 256 if(mode == null || mode.getState() == Constants.MODE_STATE_SEPARATED) { 257 Logger.getLogger(SplitSubModel.class.getName()).log(Level.WARNING, null, 258 new java.lang.IllegalArgumentException ("Mode=" + 259 mode)); 260 return false; 261 } 262 263 Node modeNode = getModeNode(mode); 264 265 if(DEBUG) { 266 debugLog(""); debugLog(""); debugLog("=========================================="); debugLog("Adding mode to around=" + mode); debugLog("side=" + side); } 272 273 return addNodeToTreeAroundEditor(modeNode, side); 274 } 275 276 private boolean isInTree(Node descendant) { 277 if(root == null) { 278 return false; 279 } 280 281 if(descendant == root) { 282 return true; 283 } 284 285 Node parent = descendant.getParent(); 286 while(parent != null) { 287 if(parent == root) { 288 return true; 289 } 290 parent = parent.getParent(); 291 } 292 293 return false; 294 } 295 296 297 protected boolean addNodeToTree(Node addingNode, SplitConstraint[] constraints) { 298 if(isInTree(addingNode)) { 299 return false; 300 } 301 302 SplitNode splitNode; 304 if(root == null) { 306 if(constraints.length == 0) { 307 root = addingNode; 308 return true; 309 } 310 311 splitNode = new SplitNode(constraints[0].orientation); 313 root = splitNode; 314 } else if(root instanceof SplitNode) { 315 splitNode = (SplitNode)root; 316 } else { 317 splitNode = new SplitNode(0); splitNode.setChildAt(-1, 0.5D, root); 320 root = splitNode; 321 } 322 323 for(int level = 0; level < constraints.length; level++) { 325 int orientation = constraints[level].orientation; 326 327 if(orientation != splitNode.getOrientation()) { 329 SplitNode newSplit = new SplitNode(orientation); 331 if(splitNode == root) { 332 newSplit.setChildAt(-1, 0.5D, splitNode); 334 root = newSplit; 335 } else { 336 SplitNode parent = splitNode.getParent(); 337 int oldIndex = parent.getChildIndex(splitNode); 338 double oldSplitWeight = parent.getChildSplitWeight(splitNode); 339 parent.removeChild(splitNode); 341 342 newSplit.setChildAt(-1, 0.5D, splitNode); 344 parent.setChildAt(oldIndex, oldSplitWeight, newSplit); 345 } 346 347 splitNode = newSplit; 348 } 349 350 if(level < constraints.length - 1) { 353 int index = constraints[level].index; 354 double splitWeight = constraints[level].splitWeight; 355 356 Node child = splitNode.getChildAt(index); 357 if(child instanceof SplitNode) { 358 splitNode = (SplitNode)child; 361 } else { 362 SplitNode newSplit = new SplitNode(constraints[level + 1].orientation); 364 splitNode.setChildAt(index, splitWeight, newSplit); 365 splitNode = newSplit; 366 } 367 } 368 } 369 370 if(constraints.length == 0) { 372 splitNode.setChildAt(-1, 0.5D, addingNode); 373 } else { 374 splitNode.setChildAt( 375 constraints[constraints.length - 1].index, 376 constraints[constraints.length - 1].splitWeight, 377 addingNode 378 ); 379 } 380 381 verifyNode(root); 382 383 return true; 384 } 385 386 private boolean addNodeToTreeToSide(Node addingNode, Node attachNode, String side) { 388 if(isInTree(addingNode)) { 389 return false; 390 } 391 392 if(!isInTree(attachNode)) { 393 return false; 394 } 395 396 if(DEBUG) { 397 debugLog(""); debugLog("Inserting to side="+side); } 400 401 if(attachNode == root) { 403 int addingIndex = (side == Constants.TOP || side == Constants.LEFT) ? 0 : -1; 404 int oldIndex = addingIndex == 0 ? -1 : 0; 405 int orientation = (side == Constants.TOP || side == Constants.BOTTOM) ? Constants.VERTICAL : Constants.HORIZONTAL; 407 SplitNode newSplit = new SplitNode(orientation); 408 newSplit.setChildAt(addingIndex, Constants.DROP_TO_SIDE_RATIO, addingNode); 409 newSplit.setChildAt(oldIndex, 1D - Constants.DROP_TO_SIDE_RATIO, attachNode); 410 root = newSplit; 411 } else { 412 SplitNode parent = attachNode.getParent(); 413 if(parent == null) { 414 return false; 415 } 416 417 int attachIndex = parent.getChildIndex(attachNode); 418 double attachWeight = parent.getChildSplitWeight(attachNode); 419 int orientation = (side == Constants.TOP || side == Constants.BOTTOM) ? Constants.VERTICAL : Constants.HORIZONTAL; 421 if( orientation == parent.getOrientation() ) { 422 if( side == Constants.BOTTOM || side == Constants.RIGHT ) 424 attachIndex++; 425 parent.setChildAt( attachIndex, Constants.DROP_TO_SIDE_RATIO, addingNode ); 426 } else { 427 SplitNode newSplit = new SplitNode(orientation); 429 parent.removeChild(attachNode); 430 int addingIndex = (side == Constants.TOP || side == Constants.LEFT) ? 0 : -1; 431 int oldIndex = addingIndex == 0 ? -1 : 0; 432 newSplit.setChildAt(addingIndex, Constants.DROP_TO_SIDE_RATIO, addingNode); 433 newSplit.setChildAt(oldIndex, 1D - Constants.DROP_TO_SIDE_RATIO, attachNode); 434 parent.setChildAt(attachIndex, attachWeight, newSplit); 435 } 436 } 437 438 return true; 439 } 440 441 private boolean addNodeToTreeAround(Node addingNode, String side) { 443 Node top = root; 444 445 if(top instanceof SplitNode) { 446 SplitNode parent = (SplitNode)top; 447 448 if((parent.getOrientation() == Constants.VERTICAL 449 && (side == Constants.TOP || side == Constants.BOTTOM)) 450 || (parent.getOrientation() == Constants.HORIZONTAL 451 && (side == Constants.LEFT || side == Constants.RIGHT))) { 452 double splitWeights = 0D; 454 for(Iterator it = parent.getChildren().iterator(); it.hasNext(); ) { 455 Node next = (Node)it.next(); 456 splitWeights += parent.getChildSplitWeight(next); 457 } 458 459 double addingSplitWeight = splitWeights * Constants.DROP_AROUND_RATIO; 460 int index = (side == Constants.TOP || side == Constants.LEFT) ? 0 : -1; 461 462 parent.setChildAt(index, addingSplitWeight, addingNode); 463 if(addingSplitWeight > 1D) { 464 double ratio = 1D/addingSplitWeight; 465 parent.normalizeWeights(ratio); 466 } 467 return true; 468 } else { 469 int orientation = (side == Constants.TOP || side == Constants.BOTTOM) ? Constants.VERTICAL : Constants.HORIZONTAL; 471 SplitNode newSplit = new SplitNode(orientation); 472 int addingIndex = (side == Constants.TOP || side == Constants.LEFT) ? 0 : -1; 473 int oldIndex = addingIndex == 0 ? -1 : 0; 474 newSplit.setChildAt(addingIndex, Constants.DROP_AROUND_RATIO, addingNode); 475 newSplit.setChildAt(oldIndex, 1D - Constants.DROP_AROUND_RATIO, parent); 476 root = newSplit; 477 return true; 478 } 479 } 480 481 SplitConstraint[] newConstraints; if(side == Constants.TOP) { 483 newConstraints = new SplitConstraint[] {new SplitConstraint(Constants.VERTICAL, 0, Constants.DROP_AROUND_RATIO)}; 484 } else if(side == Constants.BOTTOM) { 485 newConstraints = new SplitConstraint[] {new SplitConstraint(Constants.VERTICAL, -1, Constants.DROP_AROUND_RATIO)}; 486 } else if(side == Constants.LEFT) { 487 newConstraints = new SplitConstraint[] {new SplitConstraint(Constants.HORIZONTAL, 0, Constants.DROP_AROUND_RATIO)}; 488 } else if(side == Constants.RIGHT) { 489 newConstraints = new SplitConstraint[] {new SplitConstraint(Constants.HORIZONTAL, -1, Constants.DROP_AROUND_RATIO)}; 490 } else { 491 return false; 493 } 494 495 return addNodeToTree(addingNode, newConstraints); 496 } 497 498 protected boolean addNodeToTreeAroundEditor(Node addingNode, String side) { 500 return false; 502 } 503 504 505 506 public boolean removeMode(ModeImpl mode) { 507 if(mode == null) { 508 throw new NullPointerException ("Cannot remove null mode!"); 509 } 510 511 return removeNodeFromTree(getModeNode(mode)); 512 } 513 514 515 protected boolean removeNodeFromTree(Node node) { 516 if(!isInTree(node)) { 517 return false; 518 } 519 520 SplitNode parent = node.getParent(); 521 if(parent == null && node != root) { 522 return false; 524 } 525 526 if(node == root) { 527 root = null; 528 } else { 529 parent.removeChild(node); 530 531 List children = parent.getChildren(); 532 533 if(children.isEmpty()) { 534 if(parent == root) { 536 root = null; 537 } else { 538 SplitNode grandParent = parent.getParent(); 539 grandParent.removeChild(parent); 540 } 541 } else if( children.size() == 1 ) { 542 Node orphan = (Node)children.get( 0 ); 544 if( parent == root ) { 545 orphan.setParent( null ); 546 root = orphan; 547 } else { 548 SplitNode grandParent = parent.getParent(); 549 int index = grandParent.getChildIndex( parent ); 550 double weight = grandParent.getChildSplitWeight( parent ); 551 grandParent.removeChild( parent ); 552 grandParent.setChildAt( index, weight, orphan ); 553 } 554 } 555 } 556 557 verifyNode(root); 558 559 return true; 560 } 561 562 564 private void verifyNode(Node node) { 565 if(node instanceof SplitNode) { 566 SplitNode splitNode = (SplitNode)node; 567 for(Iterator it = splitNode.getChildren().iterator(); it.hasNext(); ) { 568 Node child = (Node)it.next(); 569 570 if(child.getParent() != splitNode) { 571 Logger.getLogger(SplitSubModel.class.getName()).log(Level.WARNING, null, 572 new java.lang.IllegalStateException ("Node->" + 573 child + 574 " has wrong parent->" + 575 child.getParent() + 576 " is has to be->" + 577 splitNode + 578 " \nModel: " + 579 toString())); 580 child.setParent(splitNode); 582 } 583 584 verifyNode(child); 585 } 586 } 587 } 588 589 590 public void reset() { 591 detachNodes(root); 592 root = null; 593 } 594 595 596 private static void detachNodes(Node node) { 597 if(node instanceof SplitNode) { 598 SplitNode splitNode = (SplitNode)node; 599 600 for(Iterator it = splitNode.getChildren().iterator(); it.hasNext(); ) { 601 Node child = (Node)it.next(); 602 splitNode.removeChild(child); 603 detachNodes(child); 604 } 605 } 606 } 607 608 public boolean setSplitWeights( ModelElement[] snapshots, double[] splitWeights ) { 609 if( 0 == snapshots.length ) 610 return false; 611 for( int i=0; i<snapshots.length; i++ ) { 612 Node node = (Node)snapshots[i]; 613 if( null == node || null == node.getParent() ) 614 return false; 615 } 616 Node firstNode = (Node)snapshots[0]; 617 SplitNode parent = firstNode.getParent(); 618 619 if(parent == null || !isInTree(parent)) { 620 return false; 621 } 622 623 boolean res = true; 624 for( int i=0; i<snapshots.length; i++ ) { 625 Node node = (Node)snapshots[ i ]; 626 double weight = splitWeights[ i ]; 627 SplitNode parentNode = node.getParent(); 628 if( null == parentNode || !isInTree( parentNode ) ) { 629 res = false; 630 } else { 631 parentNode.setChildSplitWeight( node, weight ); 632 } 633 } 634 635 return res; 636 } 637 638 639 public ModeStructureSnapshot.ElementSnapshot createSplitSnapshot() { 640 return root == null ? null : root.createSnapshot(); 641 } 642 643 public Set<ModeStructureSnapshot.ModeSnapshot> createSeparateSnapshots() { 644 return findSeparateModeSnapshots(root); 645 } 646 647 private Set<ModeStructureSnapshot.ModeSnapshot> findSeparateModeSnapshots(Node node) { 648 Set<ModeStructureSnapshot.ModeSnapshot> s = 649 new HashSet<ModeStructureSnapshot.ModeSnapshot>(); 650 if(node instanceof ModeNode) { 651 ModeNode modeNode = (ModeNode)node; 652 if(modeNode.isVisibleSeparate()) { 653 s.add((ModeStructureSnapshot.ModeSnapshot)modeNode.createSnapshot()); 654 } 655 } else if(node instanceof SplitNode) { 656 SplitNode splitNode = (SplitNode)node; 657 for(Iterator it = splitNode.getChildren().iterator(); it.hasNext(); ) { 658 Node child = (Node)it.next(); 659 s.addAll(findSeparateModeSnapshots(child)); 660 } 661 } 662 663 return s; 664 } 665 666 667 public String toString() { 668 return dumpNode(root, 0, null); 670 } 671 672 673 private static String dumpNode(Node node, int ind, String state) { 674 ind++; 675 if (node == null) { 676 return "NULL NODE\n"; 677 } 678 StringBuffer buffer = new StringBuffer (); 679 if(state == null) { 680 buffer.append("\n"); 681 } 682 StringBuffer sb = getOffset(ind); 683 if(node instanceof ModeNode) { 684 buffer.append(sb); 685 buffer.append("<mode-node"); buffer.append(" [" + Integer.toHexString(System.identityHashCode(node)) + "]"); buffer.append(" index=\""); if (node.getParent() != null) { 689 buffer.append(node.getParent().getChildIndex(node)); 690 } 691 buffer.append(" splitWeight="); if (node.getParent() != null) { 693 buffer.append(node.getParent().getChildSplitWeight(node)); 694 } 695 buffer.append("\""); buffer.append(" state=\""); buffer.append(state); 698 buffer.append("\""); buffer.append(" name=\"" + ((ModeNode)node).getMode().getName() + "\""); buffer.append(" parent="); buffer.append(node.getParent() == null ? null : "["+Integer.toHexString(node.getParent().hashCode())+"]"); 702 buffer.append(" constraints=\'" + java.util.Arrays.asList(node.getNodeConstraints()) + "\""); 703 buffer.append("</mode-node>\n"); } else if(node instanceof SplitNode) { 705 buffer.append(sb); 706 buffer.append("<split-node"); buffer.append(" [" + Integer.toHexString(System.identityHashCode(node)) + "]"); buffer.append(" index=\""); if (node.getParent() != null) { 710 buffer.append(node.getParent().getChildIndex(node)); 711 } 712 buffer.append(" splitWeight="); if (node.getParent() != null) { 714 buffer.append(node.getParent().getChildSplitWeight(node)); 715 } 716 buffer.append("\""); SplitNode split = (SplitNode) node; 718 buffer.append(" state=\""); buffer.append(state); 720 buffer.append("\" orientation=\""); buffer.append(split.getOrientation()); 722 buffer.append("\">\n"); 723 int j = 0; 724 for(Iterator it = split.getChildren().iterator(); it.hasNext(); j++ ) { 725 Node child = (Node)it.next(); 726 buffer.append(dumpNode(child, ind, "child["+j+"]")); 727 } 728 buffer.append(sb); 729 buffer.append("</split-node>\n"); } else { 731 buffer.append(sb); 733 buffer.append("<editor-node"); buffer.append(" [" + Integer.toHexString(System.identityHashCode(node)) + "]"); buffer.append(" index=\""); if (node.getParent() != null) { 737 buffer.append(node.getParent().getChildIndex(node)); 738 } 739 buffer.append("\""); buffer.append(" splitWeight="); if (node.getParent() != null) { 742 buffer.append(node.getParent().getChildSplitWeight(node)); 743 } 744 buffer.append(" parent="); buffer.append(node.getParent() == null ? null : "["+Integer.toHexString(node.getParent().hashCode())+"]"); 746 buffer.append("</editor-node>\n"); } 748 return buffer.toString(); 749 } 750 751 private static StringBuffer getOffset (int ind) { 752 StringBuffer sb = new StringBuffer (); 753 for (int i = 0; i < ind - 1; i++) { 754 sb.append("\t"); } 756 return sb; 757 } 758 759 762 public ModeImpl getModeForOriginator(ModelElement originator) { 763 if(originator instanceof ModeNode) { 764 return ((ModeNode)originator).getMode(); 765 } 766 767 return null; 768 } 769 770 773 private static void debugLog(String message) { 774 Debug.log(SplitSubModel.class, message); 775 } 776 777 781 protected static abstract class Node implements ModelElement { 782 783 private SplitNode parent; 784 785 786 public Node() { 787 } 788 789 790 public String toString() { 791 return super.toString() 792 + "[parent=" + (parent == null ? null 794 : (parent.getClass() + "@" + Integer.toHexString(parent.hashCode()))) 796 + "]"; } 798 799 800 public void setParent(SplitNode parent) { 801 if(this.parent == parent) { 802 return; 803 } 804 805 this.parent = parent; 806 } 807 808 809 public SplitNode getParent() { 810 return parent; 811 } 812 813 public abstract double getResizeWeight(); 814 815 817 public SplitConstraint[] getNodeConstraints() { 818 Node node = this; 819 List<SplitConstraint> conList = new ArrayList<SplitConstraint>(5); 820 do { 821 SplitConstraint item = getConstraintForNode(node); 822 if(item != null) { 823 conList.add(item); 824 } 825 826 node = node.getParent(); 827 } while(node != null); 828 829 Collections.reverse(conList); 830 return conList.toArray(new SplitConstraint[0]); 831 } 832 833 834 private static SplitConstraint getConstraintForNode(Node node) { 835 SplitNode parent = node.getParent(); 836 if(parent != null) { 837 return new SplitConstraint( 838 parent.getOrientation(), 839 parent.getChildIndex(node), 840 parent.getChildSplitWeight(node) 841 ); 842 } 843 844 return null; 845 } 846 847 850 851 public boolean isVisibleInSplit() { 852 return false; 853 } 854 855 856 public boolean hasVisibleDescendant() { 857 return isVisibleInSplit(); 858 } 859 860 861 public abstract ModeStructureSnapshot.ElementSnapshot createSnapshot(); 862 863 } 865 866 868 protected static class SplitNode extends Node { 869 870 871 private final int orientation; 872 873 876 private final TreeMap<Integer , Node> index2child = new TreeMap<Integer , Node>(); 877 878 879 private final Map<Node, Double > child2splitWeight = new HashMap<Node, Double >(); 880 881 882 public SplitNode(int orientation) { 883 this.orientation = orientation; 884 } 885 886 887 889 public String toString() { 890 StringBuffer sb = new StringBuffer (); 891 sb.append(super.toString()); 892 893 for(Iterator it = index2child.keySet().iterator(); it.hasNext(); ) { 894 Integer index = (Integer )it.next(); 895 Node child = (Node)index2child.get(index); 896 sb.append("child[" + index.intValue() +"]=" + child.getClass() 897 + "@" + Integer.toHexString(child.hashCode())); } 899 900 return sb.toString(); 901 } 902 903 904 public int getOrientation() { 905 return orientation; 906 } 907 908 public void setChildAt(int index, double splitWeight, Node child) { 909 if(index == -1) { 911 if(index2child.isEmpty()) { 912 index = 0; 913 } else { 914 index = ((Integer )index2child.lastKey()).intValue() + 1; 915 } 916 } 917 918 Integer ind = Integer.valueOf(index); 919 920 Node oldChild = (Node)index2child.get(ind); 921 for(int i = ind.intValue() + 1; oldChild != null; i++) { 923 oldChild = (Node)index2child.put(Integer.valueOf(i), oldChild); 924 } 925 926 index2child.put(ind, child); 928 setChildSplitWeightImpl(child, splitWeight); 930 child.setParent(this); 931 932 verifyChildren(); 933 } 934 935 public Node getChildAt(int index) { 936 return (Node)index2child.get(Integer.valueOf(index)); 937 } 938 939 private void verifyChildren() { 940 for(Iterator it = index2child.values().iterator(); it.hasNext(); ) { 941 Node child = (Node)it.next(); 942 if(child.getParent() != this) { 943 Logger.getLogger(SplitSubModel.class.getName()).log(Level.WARNING, null, 944 new java.lang.IllegalStateException ("Node " + 945 child + 946 " is a child in split " + 947 this + 948 " but his parent is " + 949 child.getParent() + 950 ". Repairing")); child.setParent(this); 953 } 954 } 955 } 956 957 public double getChildSplitWeight(Node child) { 958 Double db = child2splitWeight.get(child); 959 if(db != null) { 960 return db.doubleValue(); 961 } 962 963 return -1D; 964 } 965 966 public void setChildSplitWeight(Node child, double weight) { 967 if(child == null || !child2splitWeight.keySet().contains(child)) { 968 return; 969 } 970 971 setChildSplitWeightImpl(child, weight); 972 } 973 974 private void setChildSplitWeightImpl(Node child, double weight) { 975 child2splitWeight.put(child, Double.valueOf(weight)); 976 } 977 978 979 private void normalizeWeights(double ratio) { 980 for(Map.Entry<Node, Double > entry: child2splitWeight.entrySet()) { 981 double w = entry.getValue().doubleValue(); 982 w = ratio * w; 983 entry.setValue(Double.valueOf(w)); 984 } 985 } 986 987 public int getChildIndex(Node child) { 988 for(Iterator it = index2child.keySet().iterator(); it.hasNext(); ) { 989 Object key = it.next(); 990 if(child == index2child.get(key)) { 991 return ((Integer )key).intValue(); 992 } 993 } 994 995 return -1; 996 } 997 998 public List<Node> getChildren() { 999 return new ArrayList<Node>(index2child.values()); 1000 } 1001 1002 public List<Node> getVisibleChildren() { 1003 List<Node> l = getChildren(); 1004 for(Iterator<Node> it = l.iterator(); it.hasNext(); ) { 1005 Node node = it.next(); 1006 if(!node.hasVisibleDescendant()) { 1007 it.remove(); 1008 } 1009 } 1010 1011 return l; 1012 } 1013 1014 protected boolean removeChild(Node child) { 1015 boolean result = index2child.values().remove(child); 1016 child2splitWeight.remove(child); 1017 child.setParent(null); 1018 1019 return result; 1020 } 1021 1022 1023 public boolean isVisibleInSplit() { 1024 int count = 0; 1025 for(Iterator it = index2child.values().iterator(); it.hasNext(); ) { 1026 Node node = (Node)it.next(); 1027 if(node.hasVisibleDescendant()) { 1028 count++; 1029 if(count >= 2) { 1031 return true; 1032 } 1033 } 1034 } 1035 1036 return false; 1037 } 1038 1039 1040 public boolean hasVisibleDescendant() { 1041 for(Iterator it = index2child.values().iterator(); it.hasNext(); ) { 1042 Node node = (Node)it.next(); 1043 if(node.hasVisibleDescendant()) { 1044 return true; 1045 } 1046 } 1047 1048 return false; 1049 } 1050 1051 public double getResizeWeight() { 1052 List children = getVisibleChildren(); 1053 double max = 0D; 1054 for(Iterator it = children.iterator(); it.hasNext(); ) { 1055 double resizeWeight = ((Node)it.next()).getResizeWeight(); 1056 max = Math.max(max, resizeWeight); 1057 } 1058 1059 return max; 1060 } 1061 1062 public ModeStructureSnapshot.ElementSnapshot createSnapshot() { 1063 List<ModeStructureSnapshot.ElementSnapshot> childSnapshots = 1064 new ArrayList<ModeStructureSnapshot.ElementSnapshot>(); 1065 Map<ModeStructureSnapshot.ElementSnapshot,Double > childSnapshot2splitWeight = 1066 new HashMap<ModeStructureSnapshot.ElementSnapshot, Double >(); 1067 for(Node child: getChildren()) { 1068 ModeStructureSnapshot.ElementSnapshot childSnapshot = child.createSnapshot(); 1069 childSnapshots.add(childSnapshot); 1070 childSnapshot2splitWeight.put(childSnapshot, child2splitWeight.get(child)); 1071 } 1072 1073 ModeStructureSnapshot.SplitSnapshot splitSnapshot = new ModeStructureSnapshot.SplitSnapshot(this, null, 1074 getOrientation(), childSnapshots, childSnapshot2splitWeight, getResizeWeight()); 1075 1076 for(ModeStructureSnapshot.ElementSnapshot snapshot: childSnapshots) { 1078 snapshot.setParent(splitSnapshot); 1079 } 1080 1081 return splitSnapshot; 1082 } 1083 } 1085 1086 1087 protected static class ModeNode extends Node { 1088 1089 private final ModeImpl mode; 1090 1091 1092 1093 public ModeNode(ModeImpl mode) { 1094 this.mode = mode; 1095 } 1096 1097 public ModeImpl getMode() { 1098 return mode; 1099 } 1100 1101 public boolean isVisibleInSplit() { 1102 if(mode.getOpenedTopComponents().isEmpty()) { 1103 return false; 1104 } 1105 1106 if(mode.getState() == Constants.MODE_STATE_SEPARATED) { 1107 return false; 1108 } 1109 1110 if(mode.getKind() == Constants.MODE_KIND_EDITOR ) { 1111 WindowManagerImpl wm = WindowManagerImpl.getInstance(); 1112 if( null != wm.getEditorMaximizedMode() && wm.getEditorMaximizedMode() != mode ) 1113 return false; 1114 } 1115 1116 return true; 1117 } 1118 1119 public boolean isVisibleSeparate() { 1120 if(mode.getOpenedTopComponents().isEmpty()) { 1121 return false; 1122 } 1123 1124 if(mode.getState() == Constants.MODE_STATE_JOINED) { 1125 return false; 1126 } 1127 1128 return true; 1129 } 1130 1131 public double getResizeWeight() { 1132 return 0D; 1133 } 1134 1135 public ModeStructureSnapshot.ElementSnapshot createSnapshot() { 1136 return new ModeStructureSnapshot.ModeSnapshot(this, null, mode, getResizeWeight()); 1137 } 1138 } 1140 1141} 1142 1143 | Popular Tags |