1 7 8 package javax.swing.tree; 9 10 import javax.swing.event.TreeModelEvent ; 11 import java.awt.Dimension ; 12 import java.awt.Rectangle ; 13 import java.util.Enumeration ; 14 import java.util.Hashtable ; 15 import java.util.NoSuchElementException ; 16 import java.util.Stack ; 17 18 33 34 public class FixedHeightLayoutCache extends AbstractLayoutCache { 35 36 private FHTreeStateNode root; 37 38 39 private int rowCount; 40 41 45 private Rectangle boundsBuffer; 46 47 50 private Hashtable treePathMapping; 51 52 55 private SearchInfo info; 56 57 private Stack tempStacks; 58 59 60 public FixedHeightLayoutCache() { 61 super(); 62 tempStacks = new Stack (); 63 boundsBuffer = new Rectangle (); 64 treePathMapping = new Hashtable (); 65 info = new SearchInfo(); 66 setRowHeight(1); 67 } 68 69 74 public void setModel(TreeModel newModel) { 75 super.setModel(newModel); 76 rebuild(false); 77 } 78 79 86 public void setRootVisible(boolean rootVisible) { 87 if(isRootVisible() != rootVisible) { 88 super.setRootVisible(rootVisible); 89 if(root != null) { 90 if(rootVisible) { 91 rowCount++; 92 root.adjustRowBy(1); 93 } 94 else { 95 rowCount--; 96 root.adjustRowBy(-1); 97 } 98 visibleNodesChanged(); 99 } 100 } 101 } 102 103 109 public void setRowHeight(int rowHeight) { 110 if(rowHeight <= 0) 111 throw new IllegalArgumentException ("FixedHeightLayoutCache only supports row heights greater than 0"); 112 if(getRowHeight() != rowHeight) { 113 super.setRowHeight(rowHeight); 114 visibleNodesChanged(); 115 } 116 } 117 118 121 public int getRowCount() { 122 return rowCount; 123 } 124 125 129 public void invalidatePathBounds(TreePath path) { 130 } 131 132 133 137 public void invalidateSizes() { 138 visibleNodesChanged(); 141 } 142 143 146 public boolean isExpanded(TreePath path) { 147 if(path != null) { 148 FHTreeStateNode lastNode = getNodeForPath(path, true, false); 149 150 return (lastNode != null && lastNode.isExpanded()); 151 } 152 return false; 153 } 154 155 162 public Rectangle getBounds(TreePath path, Rectangle placeIn) { 163 if(path == null) 164 return null; 165 166 FHTreeStateNode node = getNodeForPath(path, true, false); 167 168 if(node != null) 169 return getBounds(node, -1, placeIn); 170 171 TreePath parentPath = path.getParentPath(); 173 174 node = getNodeForPath(parentPath, true, false); 175 if(node != null) { 176 int childIndex = treeModel.getIndexOfChild 177 (parentPath.getLastPathComponent(), 178 path.getLastPathComponent()); 179 180 if(childIndex != -1) 181 return getBounds(node, childIndex, placeIn); 182 } 183 return null; 184 } 185 186 190 public TreePath getPathForRow(int row) { 191 if(row >= 0 && row < getRowCount()) { 192 if(root.getPathForRow(row, getRowCount(), info)) { 193 return info.getPath(); 194 } 195 } 196 return null; 197 } 198 199 204 public int getRowForPath(TreePath path) { 205 if(path == null || root == null) 206 return -1; 207 208 FHTreeStateNode node = getNodeForPath(path, true, false); 209 210 if(node != null) 211 return node.getRow(); 212 213 TreePath parentPath = path.getParentPath(); 214 215 node = getNodeForPath(parentPath, true, false); 216 if(node != null && node.isExpanded()) { 217 return node.getRowToModelIndex(treeModel.getIndexOfChild 218 (parentPath.getLastPathComponent(), 219 path.getLastPathComponent())); 220 } 221 return -1; 222 } 223 224 231 public TreePath getPathClosestTo(int x, int y) { 232 if(getRowCount() == 0) 233 return null; 234 235 int row = getRowContainingYLocation(y); 236 237 return getPathForRow(row); 238 } 239 240 243 public int getVisibleChildCount(TreePath path) { 244 FHTreeStateNode node = getNodeForPath(path, true, false); 245 246 if(node == null) 247 return 0; 248 return node.getTotalChildCount(); 249 } 250 251 256 public Enumeration <TreePath > getVisiblePathsFrom(TreePath path) { 257 if(path == null) 258 return null; 259 260 FHTreeStateNode node = getNodeForPath(path, true, false); 261 262 if(node != null) { 263 return new VisibleFHTreeStateNodeEnumeration(node); 264 } 265 TreePath parentPath = path.getParentPath(); 266 267 node = getNodeForPath(parentPath, true, false); 268 if(node != null && node.isExpanded()) { 269 return new VisibleFHTreeStateNodeEnumeration(node, 270 treeModel.getIndexOfChild(parentPath.getLastPathComponent(), 271 path.getLastPathComponent())); 272 } 273 return null; 274 } 275 276 280 public void setExpandedState(TreePath path, boolean isExpanded) { 281 if(isExpanded) 282 ensurePathIsExpanded(path, true); 283 else if(path != null) { 284 TreePath parentPath = path.getParentPath(); 285 286 if(parentPath != null) { 288 FHTreeStateNode parentNode = getNodeForPath(parentPath, 289 false, true); 290 if(parentNode != null) 291 parentNode.makeVisible(); 292 } 293 FHTreeStateNode childNode = getNodeForPath(path, true, 295 false); 296 297 if(childNode != null) 298 childNode.collapse(true); 299 } 300 } 301 302 305 public boolean getExpandedState(TreePath path) { 306 FHTreeStateNode node = getNodeForPath(path, true, false); 307 308 return (node != null) ? (node.isVisible() && node.isExpanded()) : 309 false; 310 } 311 312 316 328 public void treeNodesChanged(TreeModelEvent e) { 329 if(e != null) { 330 int changedIndexs[]; 331 FHTreeStateNode changedParent = getNodeForPath 332 (e.getTreePath(), false, false); 333 int maxCounter; 334 335 changedIndexs = e.getChildIndices(); 336 338 if (changedParent != null) { 340 if (changedIndexs != null && 341 (maxCounter = changedIndexs.length) > 0) { 342 Object parentValue = changedParent.getUserObject(); 343 344 for(int counter = 0; counter < maxCounter; counter++) { 345 FHTreeStateNode child = changedParent. 346 getChildAtModelIndex(changedIndexs[counter]); 347 348 if(child != null) { 349 child.setUserObject(treeModel.getChild(parentValue, 350 changedIndexs[counter])); 351 } 352 } 353 if(changedParent.isVisible() && changedParent.isExpanded()) 354 visibleNodesChanged(); 355 } 356 else if (changedParent == root && changedParent.isVisible() && 358 changedParent.isExpanded()) { 359 visibleNodesChanged(); 360 } 361 } 362 } 363 } 364 365 372 public void treeNodesInserted(TreeModelEvent e) { 373 if(e != null) { 374 int changedIndexs[]; 375 FHTreeStateNode changedParent = getNodeForPath 376 (e.getTreePath(), false, false); 377 int maxCounter; 378 379 changedIndexs = e.getChildIndices(); 380 382 if(changedParent != null && changedIndexs != null && 384 (maxCounter = changedIndexs.length) > 0) { 385 boolean isVisible = 386 (changedParent.isVisible() && 387 changedParent.isExpanded()); 388 389 for(int counter = 0; counter < maxCounter; counter++) { 390 changedParent.childInsertedAtModelIndex 391 (changedIndexs[counter], isVisible); 392 } 393 if(isVisible && treeSelectionModel != null) 394 treeSelectionModel.resetRowSelection(); 395 if(changedParent.isVisible()) 396 this.visibleNodesChanged(); 397 } 398 } 399 } 400 401 411 public void treeNodesRemoved(TreeModelEvent e) { 412 if(e != null) { 413 int changedIndexs[]; 414 int maxCounter; 415 TreePath parentPath = e.getTreePath(); 416 FHTreeStateNode changedParentNode = getNodeForPath 417 (parentPath, false, false); 418 419 changedIndexs = e.getChildIndices(); 420 if(changedParentNode != null && changedIndexs != null && 423 (maxCounter = changedIndexs.length) > 0) { 424 Object [] children = e.getChildren(); 425 boolean isVisible = 426 (changedParentNode.isVisible() && 427 changedParentNode.isExpanded()); 428 429 for(int counter = maxCounter - 1; counter >= 0; counter--) { 430 changedParentNode.removeChildAtModelIndex 431 (changedIndexs[counter], isVisible); 432 } 433 if(isVisible) { 434 if(treeSelectionModel != null) 435 treeSelectionModel.resetRowSelection(); 436 if (treeModel.getChildCount(changedParentNode. 437 getUserObject()) == 0 && 438 changedParentNode.isLeaf()) { 439 changedParentNode.collapse(false); 441 } 442 visibleNodesChanged(); 443 } 444 else if(changedParentNode.isVisible()) 445 visibleNodesChanged(); 446 } 447 } 448 } 449 450 459 public void treeStructureChanged(TreeModelEvent e) { 460 if(e != null) { 461 TreePath changedPath = e.getTreePath(); 462 FHTreeStateNode changedNode = getNodeForPath 463 (changedPath, false, false); 464 465 if (changedNode == root || 468 (changedNode == null && 469 ((changedPath == null && treeModel != null && 470 treeModel.getRoot() == null) || 471 (changedPath != null && changedPath.getPathCount() <= 1)))) { 472 rebuild(true); 473 } 474 else if(changedNode != null) { 475 boolean wasExpanded, wasVisible; 476 FHTreeStateNode parent = (FHTreeStateNode) 477 changedNode.getParent(); 478 479 wasExpanded = changedNode.isExpanded(); 480 wasVisible = changedNode.isVisible(); 481 482 int index = parent.getIndex(changedNode); 483 changedNode.collapse(false); 484 parent.remove(index); 485 486 if(wasVisible && wasExpanded) { 487 int row = changedNode.getRow(); 488 parent.resetChildrenRowsFrom(row, index, 489 changedNode.getChildIndex()); 490 changedNode = getNodeForPath(changedPath, false, true); 491 changedNode.expand(); 492 } 493 if(treeSelectionModel != null && wasVisible && wasExpanded) 494 treeSelectionModel.resetRowSelection(); 495 if(wasVisible) 496 this.visibleNodesChanged(); 497 } 498 } 499 } 500 501 502 506 private void visibleNodesChanged() { 507 } 508 509 514 private Rectangle getBounds(FHTreeStateNode parent, int childIndex, 515 Rectangle placeIn) { 516 boolean expanded; 517 int level; 518 int row; 519 Object value; 520 521 if(childIndex == -1) { 522 row = parent.getRow(); 524 value = parent.getUserObject(); 525 expanded = parent.isExpanded(); 526 level = parent.getLevel(); 527 } 528 else { 529 row = parent.getRowToModelIndex(childIndex); 530 value = treeModel.getChild(parent.getUserObject(), childIndex); 531 expanded = false; 532 level = parent.getLevel() + 1; 533 } 534 535 Rectangle bounds = getNodeDimensions(value, row, level, 536 expanded, boundsBuffer); 537 if(bounds == null) 539 return null; 540 541 if(placeIn == null) 542 placeIn = new Rectangle (); 543 544 placeIn.x = bounds.x; 545 placeIn.height = getRowHeight(); 546 placeIn.y = row * placeIn.height; 547 placeIn.width = bounds.width; 548 return placeIn; 549 } 550 551 555 private void adjustRowCountBy(int changeAmount) { 556 rowCount += changeAmount; 557 } 558 559 562 private void addMapping(FHTreeStateNode node) { 563 treePathMapping.put(node.getTreePath(), node); 564 } 565 566 569 private void removeMapping(FHTreeStateNode node) { 570 treePathMapping.remove(node.getTreePath()); 571 } 572 573 577 private FHTreeStateNode getMapping(TreePath path) { 578 return (FHTreeStateNode)treePathMapping.get(path); 579 } 580 581 584 private void rebuild(boolean clearSelection) { 585 Object rootUO; 586 587 treePathMapping.clear(); 588 if(treeModel != null && (rootUO = treeModel.getRoot()) != null) { 589 root = createNodeForValue(rootUO, 0); 590 root.path = new TreePath (rootUO); 591 addMapping(root); 592 if(isRootVisible()) { 593 rowCount = 1; 594 root.row = 0; 595 } 596 else { 597 rowCount = 0; 598 root.row = -1; 599 } 600 root.expand(); 601 } 602 else { 603 root = null; 604 rowCount = 0; 605 } 606 if(clearSelection && treeSelectionModel != null) { 607 treeSelectionModel.clearSelection(); 608 } 609 this.visibleNodesChanged(); 610 } 611 612 617 private int getRowContainingYLocation(int location) { 618 if(getRowCount() == 0) 619 return -1; 620 return Math.max(0, Math.min(getRowCount() - 1, 621 location / getRowHeight())); 622 } 623 624 630 private boolean ensurePathIsExpanded(TreePath aPath, 631 boolean expandLast) { 632 if(aPath != null) { 633 if(treeModel.isLeaf(aPath.getLastPathComponent())) { 635 aPath = aPath.getParentPath(); 636 expandLast = true; 637 } 638 if(aPath != null) { 639 FHTreeStateNode lastNode = getNodeForPath(aPath, false, 640 true); 641 642 if(lastNode != null) { 643 lastNode.makeVisible(); 644 if(expandLast) 645 lastNode.expand(); 646 return true; 647 } 648 } 649 } 650 return false; 651 } 652 653 656 private FHTreeStateNode createNodeForValue(Object value,int childIndex) { 657 return new FHTreeStateNode(value, childIndex, -1); 658 } 659 660 665 private FHTreeStateNode getNodeForPath(TreePath path, 666 boolean onlyIfVisible, 667 boolean shouldCreate) { 668 if(path != null) { 669 FHTreeStateNode node; 670 671 node = getMapping(path); 672 if(node != null) { 673 if(onlyIfVisible && !node.isVisible()) 674 return null; 675 return node; 676 } 677 if(onlyIfVisible) 678 return null; 679 680 Stack paths; 682 683 if(tempStacks.size() == 0) { 684 paths = new Stack (); 685 } 686 else { 687 paths = (Stack )tempStacks.pop(); 688 } 689 690 try { 691 paths.push(path); 692 path = path.getParentPath(); 693 node = null; 694 while(path != null) { 695 node = getMapping(path); 696 if(node != null) { 697 while(node != null && paths.size() > 0) { 700 path = (TreePath )paths.pop(); 701 node = node.createChildFor(path. 702 getLastPathComponent()); 703 } 704 return node; 705 } 706 paths.push(path); 707 path = path.getParentPath(); 708 } 709 } 710 finally { 711 paths.removeAllElements(); 712 tempStacks.push(paths); 713 } 714 return null; 716 } 717 return null; 718 } 719 720 727 private class FHTreeStateNode extends DefaultMutableTreeNode { 728 729 protected boolean isExpanded; 730 731 732 protected int childIndex; 733 734 735 protected int childCount; 736 737 739 protected int row; 740 741 742 protected TreePath path; 743 744 745 public FHTreeStateNode(Object userObject, int childIndex, int row) { 746 super(userObject); 747 this.childIndex = childIndex; 748 this.row = row; 749 } 750 751 755 759 public void setParent(MutableTreeNode parent) { 760 super.setParent(parent); 761 if(parent != null) { 762 path = ((FHTreeStateNode)parent).getTreePath(). 763 pathByAddingChild(getUserObject()); 764 addMapping(this); 765 } 766 } 767 768 772 public void remove(int childIndex) { 773 FHTreeStateNode node = (FHTreeStateNode)getChildAt(childIndex); 774 775 node.removeFromMapping(); 776 super.remove(childIndex); 777 } 778 779 782 public void setUserObject(Object o) { 783 super.setUserObject(o); 784 if(path != null) { 785 FHTreeStateNode parent = (FHTreeStateNode)getParent(); 786 787 if(parent != null) 788 resetChildrenPaths(parent.getTreePath()); 789 else 790 resetChildrenPaths(null); 791 } 792 } 793 794 797 800 public int getChildIndex() { 801 return childIndex; 802 } 803 804 807 public TreePath getTreePath() { 808 return path; 809 } 810 811 816 public FHTreeStateNode getChildAtModelIndex(int index) { 817 for(int counter = getChildCount() - 1; counter >= 0; counter--) 819 if(((FHTreeStateNode)getChildAt(counter)).childIndex == index) 820 return (FHTreeStateNode)getChildAt(counter); 821 return null; 822 } 823 824 828 public boolean isVisible() { 829 FHTreeStateNode parent = (FHTreeStateNode)getParent(); 830 831 if(parent == null) 832 return true; 833 return (parent.isExpanded() && parent.isVisible()); 834 } 835 836 839 public int getRow() { 840 return row; 841 } 842 843 847 public int getRowToModelIndex(int index) { 848 FHTreeStateNode child; 849 int lastRow = getRow() + 1; 850 int retValue = lastRow; 851 852 for(int counter = 0, maxCounter = getChildCount(); 854 counter < maxCounter; counter++) { 855 child = (FHTreeStateNode)getChildAt(counter); 856 if(child.childIndex >= index) { 857 if(child.childIndex == index) 858 return child.row; 859 if(counter == 0) 860 return getRow() + 1 + index; 861 return child.row - (child.childIndex - index); 862 } 863 } 864 return getRow() + 1 + getTotalChildCount() - 866 (childCount - index); 867 } 868 869 873 public int getTotalChildCount() { 874 if(isExpanded()) { 875 FHTreeStateNode parent = (FHTreeStateNode)getParent(); 876 int pIndex; 877 878 if(parent != null && (pIndex = parent.getIndex(this)) + 1 < 879 parent.getChildCount()) { 880 FHTreeStateNode nextSibling = (FHTreeStateNode)parent. 883 getChildAt(pIndex + 1); 884 885 return nextSibling.row - row - 886 (nextSibling.childIndex - childIndex); 887 } 888 else { 889 int retCount = childCount; 890 891 for(int counter = getChildCount() - 1; counter >= 0; 892 counter--) { 893 retCount += ((FHTreeStateNode)getChildAt(counter)) 894 .getTotalChildCount(); 895 } 896 return retCount; 897 } 898 } 899 return 0; 900 } 901 902 905 public boolean isExpanded() { 906 return isExpanded; 907 } 908 909 912 public int getVisibleLevel() { 913 if (isRootVisible()) { 914 return getLevel(); 915 } else { 916 return getLevel() - 1; 917 } 918 } 919 920 923 protected void resetChildrenPaths(TreePath parentPath) { 924 removeMapping(this); 925 if(parentPath == null) 926 path = new TreePath (getUserObject()); 927 else 928 path = parentPath.pathByAddingChild(getUserObject()); 929 addMapping(this); 930 for(int counter = getChildCount() - 1; counter >= 0; counter--) 931 ((FHTreeStateNode)getChildAt(counter)). 932 resetChildrenPaths(path); 933 } 934 935 939 protected void removeFromMapping() { 940 if(path != null) { 941 removeMapping(this); 942 for(int counter = getChildCount() - 1; counter >= 0; counter--) 943 ((FHTreeStateNode)getChildAt(counter)).removeFromMapping(); 944 } 945 } 946 947 952 protected FHTreeStateNode createChildFor(Object userObject) { 953 int newChildIndex = treeModel.getIndexOfChild 954 (getUserObject(), userObject); 955 956 if(newChildIndex < 0) 957 return null; 958 959 FHTreeStateNode aNode; 960 FHTreeStateNode child = createNodeForValue(userObject, 961 newChildIndex); 962 int childRow; 963 964 if(isVisible()) { 965 childRow = getRowToModelIndex(newChildIndex); 966 } 967 else { 968 childRow = -1; 969 } 970 child.row = childRow; 971 for(int counter = 0, maxCounter = getChildCount(); 972 counter < maxCounter; counter++) { 973 aNode = (FHTreeStateNode)getChildAt(counter); 974 if(aNode.childIndex > newChildIndex) { 975 insert(child, counter); 976 return child; 977 } 978 } 979 add(child); 980 return child; 981 } 982 983 987 protected void adjustRowBy(int amount) { 988 row += amount; 989 if(isExpanded) { 990 for(int counter = getChildCount() - 1; counter >= 0; 991 counter--) 992 ((FHTreeStateNode)getChildAt(counter)).adjustRowBy(amount); 993 } 994 } 995 996 1002 protected void adjustRowBy(int amount, int startIndex) { 1003 if(isExpanded) { 1005 for(int counter = getChildCount() - 1; counter >= startIndex; 1007 counter--) 1008 ((FHTreeStateNode)getChildAt(counter)).adjustRowBy(amount); 1009 } 1010 FHTreeStateNode parent = (FHTreeStateNode)getParent(); 1012 1013 if(parent != null) { 1014 parent.adjustRowBy(amount, parent.getIndex(this) + 1); 1015 } 1016 } 1017 1018 1022 protected void didExpand() { 1023 int nextRow = setRowAndChildren(row); 1024 FHTreeStateNode parent = (FHTreeStateNode)getParent(); 1025 int childRowCount = nextRow - row - 1; 1026 1027 if(parent != null) { 1028 parent.adjustRowBy(childRowCount, parent.getIndex(this) + 1); 1029 } 1030 adjustRowCountBy(childRowCount); 1031 } 1032 1033 1038 protected int setRowAndChildren(int nextRow) { 1039 row = nextRow; 1040 1041 if(!isExpanded()) 1042 return row + 1; 1043 1044 int lastRow = row + 1; 1045 int lastModelIndex = 0; 1046 FHTreeStateNode child; 1047 int maxCounter = getChildCount(); 1048 1049 for(int counter = 0; counter < maxCounter; counter++) { 1050 child = (FHTreeStateNode)getChildAt(counter); 1051 lastRow += (child.childIndex - lastModelIndex); 1052 lastModelIndex = child.childIndex + 1; 1053 if(child.isExpanded) { 1054 lastRow = child.setRowAndChildren(lastRow); 1055 } 1056 else { 1057 child.row = lastRow++; 1058 } 1059 } 1060 return lastRow + childCount - lastModelIndex; 1061 } 1062 1063 1070 protected void resetChildrenRowsFrom(int newRow, int childIndex, 1076 int modelIndex) { 1077 int lastRow = newRow; 1078 int lastModelIndex = modelIndex; 1079 FHTreeStateNode node; 1080 int maxCounter = getChildCount(); 1081 1082 for(int counter = childIndex; counter < maxCounter; counter++) { 1083 node = (FHTreeStateNode)getChildAt(counter); 1084 lastRow += (node.childIndex - lastModelIndex); 1085 lastModelIndex = node.childIndex + 1; 1086 if(node.isExpanded) { 1087 lastRow = node.setRowAndChildren(lastRow); 1088 } 1089 else { 1090 node.row = lastRow++; 1091 } 1092 } 1093 lastRow += childCount - lastModelIndex; 1094 node = (FHTreeStateNode)getParent(); 1095 if(node != null) { 1096 node.resetChildrenRowsFrom(lastRow, node.getIndex(this) + 1, 1097 this.childIndex + 1); 1098 } 1099 else { rowCount = lastRow; 1101 } 1102 } 1103 1104 1108 protected void makeVisible() { 1109 FHTreeStateNode parent = (FHTreeStateNode)getParent(); 1110 1111 if(parent != null) 1112 parent.expandParentAndReceiver(); 1113 } 1114 1115 1119 protected void expandParentAndReceiver() { 1120 FHTreeStateNode parent = (FHTreeStateNode)getParent(); 1121 1122 if(parent != null) 1123 parent.expandParentAndReceiver(); 1124 expand(); 1125 } 1126 1127 1130 protected void expand() { 1131 if(!isExpanded && !isLeaf()) { 1132 boolean visible = isVisible(); 1133 1134 isExpanded = true; 1135 childCount = treeModel.getChildCount(getUserObject()); 1136 1137 if(visible) { 1138 didExpand(); 1139 } 1140 1141 if(visible && treeSelectionModel != null) { 1143 treeSelectionModel.resetRowSelection(); 1144 } 1145 } 1146 } 1147 1148 1152 protected void collapse(boolean adjustRows) { 1153 if(isExpanded) { 1154 if(isVisible() && adjustRows) { 1155 int childCount = getTotalChildCount(); 1156 1157 isExpanded = false; 1158 adjustRowCountBy(-childCount); 1159 adjustRowBy(-childCount, 0); 1162 } 1163 else 1164 isExpanded = false; 1165 1166 if(adjustRows && isVisible() && treeSelectionModel != null) 1167 treeSelectionModel.resetRowSelection(); 1168 } 1169 } 1170 1171 1174 public boolean isLeaf() { 1175 TreeModel model = getModel(); 1176 1177 return (model != null) ? model.isLeaf(this.getUserObject()) : 1178 true; 1179 } 1180 1181 1185 protected void addNode(FHTreeStateNode newChild) { 1186 boolean added = false; 1187 int childIndex = newChild.getChildIndex(); 1188 1189 for(int counter = 0, maxCounter = getChildCount(); 1190 counter < maxCounter; counter++) { 1191 if(((FHTreeStateNode)getChildAt(counter)).getChildIndex() > 1192 childIndex) { 1193 added = true; 1194 insert(newChild, counter); 1195 counter = maxCounter; 1196 } 1197 } 1198 if(!added) 1199 add(newChild); 1200 } 1201 1202 1207 protected void removeChildAtModelIndex(int modelIndex, 1208 boolean isChildVisible) { 1209 FHTreeStateNode childNode = getChildAtModelIndex(modelIndex); 1210 1211 if(childNode != null) { 1212 int row = childNode.getRow(); 1213 int index = getIndex(childNode); 1214 1215 childNode.collapse(false); 1216 remove(index); 1217 adjustChildIndexs(index, -1); 1218 childCount--; 1219 if(isChildVisible) { 1220 resetChildrenRowsFrom(row, index, modelIndex); 1222 } 1223 } 1224 else { 1225 int maxCounter = getChildCount(); 1226 FHTreeStateNode aChild; 1227 1228 for(int counter = 0; counter < maxCounter; counter++) { 1229 aChild = (FHTreeStateNode)getChildAt(counter); 1230 if(aChild.childIndex >= modelIndex) { 1231 if(isChildVisible) { 1232 adjustRowBy(-1, counter); 1233 adjustRowCountBy(-1); 1234 } 1235 for(; counter < maxCounter; counter++) 1239 ((FHTreeStateNode)getChildAt(counter)). 1240 childIndex--; 1241 childCount--; 1242 return; 1243 } 1244 } 1245 if(isChildVisible) { 1248 adjustRowBy(-1, maxCounter); 1249 adjustRowCountBy(-1); 1250 } 1251 childCount--; 1252 } 1253 } 1254 1255 1259 protected void adjustChildIndexs(int index, int amount) { 1260 for(int counter = index, maxCounter = getChildCount(); 1261 counter < maxCounter; counter++) { 1262 ((FHTreeStateNode)getChildAt(counter)).childIndex += amount; 1263 } 1264 } 1265 1266 1271 protected void childInsertedAtModelIndex(int index, 1272 boolean isExpandedAndVisible) { 1273 FHTreeStateNode aChild; 1274 int maxCounter = getChildCount(); 1275 1276 for(int counter = 0; counter < maxCounter; counter++) { 1277 aChild = (FHTreeStateNode)getChildAt(counter); 1278 if(aChild.childIndex >= index) { 1279 if(isExpandedAndVisible) { 1280 adjustRowBy(1, counter); 1281 adjustRowCountBy(1); 1282 } 1283 1285 for(; counter < maxCounter; counter++) 1286 ((FHTreeStateNode)getChildAt(counter)).childIndex++; 1287 childCount++; 1288 return; 1289 } 1290 } 1291 if(isExpandedAndVisible) { 1294 adjustRowBy(1, maxCounter); 1295 adjustRowCountBy(1); 1296 } 1297 childCount++; 1298 } 1299 1300 1307 protected boolean getPathForRow(int row, int nextRow, 1308 SearchInfo info) { 1309 if(this.row == row) { 1310 info.node = this; 1311 info.isNodeParentNode = false; 1312 info.childIndex = childIndex; 1313 return true; 1314 } 1315 1316 FHTreeStateNode child; 1317 FHTreeStateNode lastChild = null; 1318 1319 for(int counter = 0, maxCounter = getChildCount(); 1320 counter < maxCounter; counter++) { 1321 child = (FHTreeStateNode)getChildAt(counter); 1322 if(child.row > row) { 1323 if(counter == 0) { 1324 info.node = this; 1326 info.isNodeParentNode = true; 1327 info.childIndex = row - this.row - 1; 1328 return true; 1329 } 1330 else { 1331 int lastChildEndRow = 1 + child.row - 1333 (child.childIndex - lastChild.childIndex); 1334 1335 if(row < lastChildEndRow) { 1336 return lastChild.getPathForRow(row, 1337 lastChildEndRow, info); 1338 } 1339 info.node = this; 1341 info.isNodeParentNode = true; 1342 info.childIndex = row - lastChildEndRow + 1343 lastChild.childIndex + 1; 1344 return true; 1345 } 1346 } 1347 lastChild = child; 1348 } 1349 1350 if(lastChild != null) { 1353 int lastChildEndRow = nextRow - 1354 (childCount - lastChild.childIndex) + 1; 1355 1356 if(row < lastChildEndRow) { 1357 return lastChild.getPathForRow(row, lastChildEndRow, info); 1358 } 1359 info.node = this; 1361 info.isNodeParentNode = true; 1362 info.childIndex = row - lastChildEndRow + 1363 lastChild.childIndex + 1; 1364 return true; 1365 } 1366 else { 1367 int retChildIndex = row - this.row - 1; 1369 1370 if(retChildIndex >= childCount) { 1371 return false; 1372 } 1373 info.node = this; 1374 info.isNodeParentNode = true; 1375 info.childIndex = retChildIndex; 1376 return true; 1377 } 1378 } 1379 1380 1384 protected int getCountTo(int stopIndex) { 1385 FHTreeStateNode aChild; 1386 int retCount = stopIndex + 1; 1387 1388 for(int counter = 0, maxCounter = getChildCount(); 1389 counter < maxCounter; counter++) { 1390 aChild = (FHTreeStateNode)getChildAt(counter); 1391 if(aChild.childIndex >= stopIndex) 1392 counter = maxCounter; 1393 else 1394 retCount += aChild.getTotalChildCount(); 1395 } 1396 if(parent != null) 1397 return retCount + ((FHTreeStateNode)getParent()) 1398 .getCountTo(childIndex); 1399 if(!isRootVisible()) 1400 return (retCount - 1); 1401 return retCount; 1402 } 1403 1404 1410 protected int getNumExpandedChildrenTo(int stopIndex) { 1411 FHTreeStateNode aChild; 1412 int retCount = stopIndex; 1413 1414 for(int counter = 0, maxCounter = getChildCount(); 1415 counter < maxCounter; counter++) { 1416 aChild = (FHTreeStateNode)getChildAt(counter); 1417 if(aChild.childIndex >= stopIndex) 1418 return retCount; 1419 else { 1420 retCount += aChild.getTotalChildCount(); 1421 } 1422 } 1423 return retCount; 1424 } 1425 1426 1429 protected void didAdjustTree() { 1430 } 1431 1432 } 1434 1435 1438 private class SearchInfo { 1439 protected FHTreeStateNode node; 1440 protected boolean isNodeParentNode; 1441 protected int childIndex; 1442 1443 protected TreePath getPath() { 1444 if(node == null) 1445 return null; 1446 1447 if(isNodeParentNode) 1448 return node.getTreePath().pathByAddingChild(treeModel.getChild 1449 (node.getUserObject(), 1450 childIndex)); 1451 return node.path; 1452 } 1453 } 1455 1456 1459 private class VisibleFHTreeStateNodeEnumeration 1462 implements Enumeration <TreePath > 1463 { 1464 1465 protected FHTreeStateNode parent; 1466 1468 protected int nextIndex; 1469 1470 protected int childCount; 1471 1472 protected VisibleFHTreeStateNodeEnumeration(FHTreeStateNode node) { 1473 this(node, -1); 1474 } 1475 1476 protected VisibleFHTreeStateNodeEnumeration(FHTreeStateNode parent, 1477 int startIndex) { 1478 this.parent = parent; 1479 this.nextIndex = startIndex; 1480 this.childCount = treeModel.getChildCount(this.parent. 1481 getUserObject()); 1482 } 1483 1484 1487 public boolean hasMoreElements() { 1488 return (parent != null); 1489 } 1490 1491 1494 public TreePath nextElement() { 1495 if(!hasMoreElements()) 1496 throw new NoSuchElementException ("No more visible paths"); 1497 1498 TreePath retObject; 1499 1500 if(nextIndex == -1) 1501 retObject = parent.getTreePath(); 1502 else { 1503 FHTreeStateNode node = parent.getChildAtModelIndex(nextIndex); 1504 1505 if(node == null) 1506 retObject = parent.getTreePath().pathByAddingChild 1507 (treeModel.getChild(parent.getUserObject(), 1508 nextIndex)); 1509 else 1510 retObject = node.getTreePath(); 1511 } 1512 updateNextObject(); 1513 return retObject; 1514 } 1515 1516 1520 protected void updateNextObject() { 1521 if(!updateNextIndex()) { 1522 findNextValidParent(); 1523 } 1524 } 1525 1526 1530 protected boolean findNextValidParent() { 1531 if(parent == root) { 1532 parent = null; 1534 return false; 1535 } 1536 while(parent != null) { 1537 FHTreeStateNode newParent = (FHTreeStateNode)parent. 1538 getParent(); 1539 1540 if(newParent != null) { 1541 nextIndex = parent.childIndex; 1542 parent = newParent; 1543 childCount = treeModel.getChildCount 1544 (parent.getUserObject()); 1545 if(updateNextIndex()) 1546 return true; 1547 } 1548 else 1549 parent = null; 1550 } 1551 return false; 1552 } 1553 1554 1558 protected boolean updateNextIndex() { 1559 if(nextIndex == -1 && !parent.isExpanded()) { 1562 return false; 1563 } 1564 1565 if(childCount == 0) { 1567 return false; 1568 } 1569 else if(++nextIndex >= childCount) { 1571 return false; 1572 } 1573 1574 FHTreeStateNode child = parent.getChildAtModelIndex(nextIndex); 1575 1576 if(child != null && child.isExpanded()) { 1577 parent = child; 1578 nextIndex = -1; 1579 childCount = treeModel.getChildCount(child.getUserObject()); 1580 } 1581 return true; 1582 } 1583 } } 1585 | Popular Tags |