1 14 package org.wings; 15 16 import org.apache.commons.logging.Log; 17 import org.apache.commons.logging.LogFactory; 18 import org.wings.plaf.TreeCG; 19 import org.wings.tree.SDefaultTreeSelectionModel; 20 import org.wings.tree.STreeCellRenderer; 21 import org.wings.tree.STreeSelectionModel; 22 23 import javax.swing.event.*; 24 import javax.swing.tree.*; 25 import java.awt.*; 26 import java.util.ArrayList ; 27 28 32 public class STree extends SComponent implements LowLevelEventListener, Scrollable { 33 36 public static final int NO_SELECTION = SListSelectionModel.NO_SELECTION; 37 38 41 public static final int SINGLE_SELECTION = SListSelectionModel.SINGLE_SELECTION; 42 43 46 public static final int SINGLE_INTERVAL_SELECTION = SListSelectionModel.SINGLE_INTERVAL_SELECTION; 47 48 51 public static final int MULTIPLE_SELECTION = SListSelectionModel.MULTIPLE_INTERVAL_SELECTION; 52 53 56 public static final int MULTIPLE_INTERVAL_SELECTION = SListSelectionModel.MULTIPLE_INTERVAL_SELECTION; 57 58 private final transient static Log log = LogFactory.getLog(STree.class); 59 60 private int nodeIndentDepth; 61 62 68 protected static TreeModel getDefaultTreeModel() { 69 DefaultMutableTreeNode root = new DefaultMutableTreeNode("STree"); 70 DefaultMutableTreeNode parent; 71 72 parent = new DefaultMutableTreeNode("colors"); 73 root.add(parent); 74 parent.add(new DefaultMutableTreeNode("blue")); 75 parent.add(new DefaultMutableTreeNode("violet")); 76 parent.add(new DefaultMutableTreeNode("red")); 77 parent.add(new DefaultMutableTreeNode("yellow")); 78 79 parent = new DefaultMutableTreeNode("sports"); 80 root.add(parent); 81 parent.add(new DefaultMutableTreeNode("basketball")); 82 parent.add(new DefaultMutableTreeNode("soccer")); 83 parent.add(new DefaultMutableTreeNode("football")); 84 parent.add(new DefaultMutableTreeNode("hockey")); 85 86 parent = new DefaultMutableTreeNode("food"); 87 root.add(parent); 88 parent.add(new DefaultMutableTreeNode("hot dogs")); 89 parent.add(new DefaultMutableTreeNode("pizza")); 90 parent.add(new DefaultMutableTreeNode("ravioli")); 91 parent.add(new DefaultMutableTreeNode("bananas")); 92 return new DefaultTreeModel(root); 93 } 94 95 protected TreeModel model; 96 97 transient protected TreeModelListener treeModelListener; 98 99 protected STreeCellRenderer renderer; 100 101 protected STreeSelectionModel selectionModel; 102 103 106 private ArrayList delayedExpansionEvents; 107 108 112 protected final ArrayList requestedExpansionPaths = new ArrayList (); 113 114 protected AbstractLayoutCache treeState = new VariableHeightLayoutCache(); 115 116 119 protected Rectangle viewport; 120 121 122 protected boolean epochCheckEnabled = true; 123 124 125 128 private final TreeSelectionListener forwardSelectionEvent = 129 new TreeSelectionListener() { 130 public void valueChanged(TreeSelectionEvent e) { 131 fireTreeSelectionEvent(e); 132 } 133 }; 134 135 public STree(TreeModel model) { 136 super(); 137 setModel(model); 138 setRootVisible(true); 139 setSelectionModel(new SDefaultTreeSelectionModel()); 140 } 141 142 public STree() { 143 this(getDefaultTreeModel()); 144 } 145 146 public void addTreeSelectionListener(TreeSelectionListener tsl) { 147 addEventListener(TreeSelectionListener.class, tsl); 148 } 149 150 public void removeTreeSelectionListener(TreeSelectionListener tsl) { 151 removeEventListener(TreeSelectionListener.class, tsl); 152 } 153 154 protected void fireTreeSelectionEvent(TreeSelectionEvent e) { 155 Object [] listeners = getListenerList(); 157 for (int i = listeners.length - 2; i >= 0; i -= 2) { 160 if (listeners[i] == TreeSelectionListener.class) { 161 ((TreeSelectionListener) listeners[i + 1]).valueChanged(e); 162 } 163 } 164 reload(); 165 } 166 167 174 public void addTreeWillExpandListener(TreeWillExpandListener tel) { 175 addEventListener(TreeWillExpandListener.class, tel); 176 } 177 178 183 public void removeTreeWillExpandListener(TreeWillExpandListener tel) { 184 removeEventListener(TreeWillExpandListener.class, tel); 185 } 186 187 188 197 public void fireTreeWillExpand(TreePath path, boolean expand) 198 throws ExpandVetoException { 199 200 Object [] listeners = getListenerList(); 202 TreeExpansionEvent e = null; 203 for (int i = listeners.length - 2; i >= 0; i -= 2) { 206 if (listeners[i] == TreeWillExpandListener.class) { 207 if (e == null) 209 e = new TreeExpansionEvent(this, path); 210 211 if (expand) { 212 ((TreeWillExpandListener) listeners[i + 1]). 213 treeWillExpand(e); 214 } else { 215 ((TreeWillExpandListener) listeners[i + 1]). 216 treeWillCollapse(e); 217 } 218 } 219 } 220 } 221 222 public void addTreeExpansionListener(TreeExpansionListener tel) { 223 addEventListener(TreeExpansionListener.class, tel); 224 } 225 226 public void removeTreeExpansionListener(TreeExpansionListener tel) { 227 removeEventListener(TreeExpansionListener.class, tel); 228 } 229 230 231 private static class DelayedExpansionEvent { 232 TreeExpansionEvent expansionEvent; 233 boolean expansion; 234 235 DelayedExpansionEvent(TreeExpansionEvent e, boolean b) { 236 expansionEvent = e; 237 expansion = b; 238 } 239 240 } 241 242 protected void addDelayedExpansionEvent(TreeExpansionEvent e, 243 boolean expansion) { 244 if (delayedExpansionEvents == null) { 245 delayedExpansionEvents = new ArrayList (); 246 } 247 248 delayedExpansionEvents.add(new DelayedExpansionEvent(e, expansion)); 249 } 250 251 protected void fireDelayedExpansionEvents() { 252 if (delayedExpansionEvents != null && 253 !getSelectionModel().getDelayEvents()) { 254 for (int i = 0; i < delayedExpansionEvents.size(); i++) { 255 DelayedExpansionEvent e = 256 (DelayedExpansionEvent) delayedExpansionEvents.get(i); 257 258 fireTreeExpansionEvent(e.expansionEvent, e.expansion); 259 } 260 delayedExpansionEvents.clear(); 261 } 262 } 263 264 265 274 protected void fireTreeExpanded(TreePath path) { 275 fireTreeExpansionEvent(new TreeExpansionEvent(this, path), true); 276 } 277 278 protected void fireTreeExpansionEvent(TreeExpansionEvent e, boolean expansion) { 279 if (getSelectionModel().getDelayEvents()) { 280 addDelayedExpansionEvent(e, expansion); 281 } else { 282 Object [] listeners = getListenerList(); 284 for (int i = listeners.length - 2; i >= 0; i -= 2) { 287 if (listeners[i] == TreeExpansionListener.class) { 288 if (expansion) 289 ((TreeExpansionListener) listeners[i + 1]).treeExpanded(e); 290 else 291 ((TreeExpansionListener) listeners[i + 1]).treeCollapsed(e); 292 } 293 } 294 } 295 } 296 297 306 public void fireTreeCollapsed(TreePath path) { 307 fireTreeExpansionEvent(new TreeExpansionEvent(this, path), false); 308 } 309 310 protected void processRequestedExpansionPaths() { 311 getSelectionModel().setDelayEvents(true); 312 313 for (int i = 0; i < requestedExpansionPaths.size(); i++) { 314 try { 315 TreePath path = (TreePath) requestedExpansionPaths.get(i); 316 togglePathExpansion(path); 317 } catch (ExpandVetoException ex) { 318 } 320 } 321 requestedExpansionPaths.clear(); 322 getSelectionModel().setDelayEvents(false); 323 } 324 325 public void fireIntermediateEvents() { 326 processRequestedExpansionPaths(); 327 328 getSelectionModel().fireDelayedIntermediateEvents(); 329 } 330 331 public void fireFinalEvents() { 332 super.fireFinalEvents(); 333 fireDelayedExpansionEvents(); 334 getSelectionModel().fireDelayedFinalEvents(); 335 } 336 337 338 public boolean isEpochCheckEnabled() { 339 return epochCheckEnabled; 340 } 341 342 343 public void setEpochCheckEnabled(boolean epochCheckEnabled) { 344 this.epochCheckEnabled = epochCheckEnabled; 345 } 346 347 public void setRootVisible(boolean rootVisible) { 348 treeState.setRootVisible(rootVisible); 349 } 350 351 352 public boolean isRootVisible() { 353 return treeState.isRootVisible(); 354 } 355 356 357 public void setModel(TreeModel m) { 358 if (model != null && treeModelListener != null) 359 model.removeTreeModelListener(treeModelListener); 360 model = m; 361 treeState.setModel(m); 362 363 if (model != null) { 364 if (treeModelListener == null) 365 treeModelListener = createTreeModelListener(); 366 367 if (treeModelListener != null) 368 model.addTreeModelListener(treeModelListener); 369 370 if (!model.isLeaf(model.getRoot())) 372 treeState.setExpandedState(new TreePath(model.getRoot()), true); 373 } 374 } 375 376 377 public TreeModel getModel() { 378 return model; 379 } 380 381 382 public int getRowCount() { 383 return treeState.getRowCount(); 384 } 385 386 387 public TreePath getPathForRow(int row) { 388 return treeState.getPathForRow(row); 389 } 390 391 392 protected int fillPathForAbsoluteRow(int row, Object node, ArrayList path) { 393 if (row == 0) { 395 return 0; 396 } 398 for (int i = 0; i < model.getChildCount(node); i++) { 399 path.add(model.getChild(node, i)); 400 row = fillPathForAbsoluteRow(row - 1, model.getChild(node, i), path); 401 if (row == 0) { 402 return 0; 403 } path.remove(path.size() - 1); 405 } 406 return row; 407 } 408 409 public TreePath getPathForAbsoluteRow(int row) { 410 ArrayList path = new ArrayList (10); 412 413 path.add(model.getRoot()); 414 fillPathForAbsoluteRow(row, model.getRoot(), path); 415 416 return new TreePath(path.toArray()); 417 } 418 419 427 public void setSelectionModel(STreeSelectionModel selectionModel) { 428 if (this.selectionModel != null) 429 this.selectionModel.removeTreeSelectionListener(forwardSelectionEvent); 430 431 if (selectionModel != null) 432 selectionModel.addTreeSelectionListener(forwardSelectionEvent); 433 434 if (selectionModel == null) 435 this.selectionModel = SDefaultTreeSelectionModel.NO_SELECTION_MODEL; 436 else 437 this.selectionModel = selectionModel; 438 } 439 440 448 public STreeSelectionModel getSelectionModel() { 449 return selectionModel; 450 } 451 452 462 protected TreePath[] getPathBetweenRows(int index0, int index1) { 463 int newMinIndex = Math.min(index0, index1); 464 int newMaxIndex = Math.max(index0, index1); 465 466 TreePath[] selection = new TreePath[newMaxIndex - newMinIndex + 1]; 467 468 for (int i = newMinIndex; i <= newMaxIndex; i++) { 469 selection[i - newMinIndex] = getPathForRow(i); 470 } 471 472 return selection; 473 } 474 475 482 public void setSelectionPath(TreePath path) { 483 getSelectionModel().setSelectionPath(path); 484 } 485 486 494 public void setSelectionPaths(TreePath[] paths) { 495 getSelectionModel().setSelectionPaths(paths); 496 } 497 498 504 public void setSelectionRow(int row) { 505 int[] rows = {row}; 506 setSelectionRows(rows); 507 } 508 509 516 public void setSelectionRows(int[] rows) { 517 if (rows == null) 518 return; 519 520 TreePath paths[] = new TreePath[rows.length]; 521 for (int i = 0; i < rows.length; i++) { 522 paths[i] = getPathForRow(i); 523 } 524 525 setSelectionPaths(paths); 526 } 527 528 535 public void addSelectionPath(TreePath path) { 536 getSelectionModel().addSelectionPath(path); 537 } 538 539 547 public void addSelectionPaths(TreePath[] paths) { 548 getSelectionModel().addSelectionPaths(paths); 549 } 550 551 557 public void addSelectionRow(int row) { 558 int[] rows = {row}; 559 addSelectionRows(rows); 560 } 561 562 568 public void addSelectionRows(int[] rows) { 569 if (rows != null) { 570 int numRows = rows.length; 571 TreePath[] paths = new TreePath[numRows]; 572 573 for (int counter = 0; counter < numRows; counter++) 574 paths[counter] = getPathForRow(rows[counter]); 575 addSelectionPaths(paths); 576 } 577 } 578 579 587 public Object getLastSelectedPathComponent() { 588 Object obj = null; 589 TreePath selPath = getSelectionModel().getSelectionPath(); 590 if (selPath != null) { 591 obj = selPath.getLastPathComponent(); 592 } 593 return obj; 594 } 595 596 602 public TreePath getSelectionPath() { 603 return getSelectionModel().getSelectionPath(); 604 } 605 606 612 public TreePath[] getSelectionPaths() { 613 return getSelectionModel().getSelectionPaths(); 614 } 615 616 622 public int[] getSelectionRows() { 623 return getSelectionModel().getSelectionRows(); 624 } 625 626 631 public int getSelectionCount() { 632 return selectionModel.getSelectionCount(); 633 } 634 635 641 public int getMinSelectionRow() { 642 return getSelectionModel().getMinSelectionRow(); 643 } 644 645 651 public int getMaxSelectionRow() { 652 return getSelectionModel().getMaxSelectionRow(); 653 } 654 655 661 public int getLeadSelectionRow() { 662 return getSelectionModel().getLeadSelectionRow(); 663 } 664 665 670 public TreePath getLeadSelectionPath() { 671 return getSelectionModel().getLeadSelectionPath(); 672 } 673 674 680 public boolean isPathSelected(TreePath path) { 681 return getSelectionModel().isPathSelected(path); 682 } 683 684 691 public boolean isRowSelected(int row) { 692 return getSelectionModel().isRowSelected(row); 693 } 694 695 703 public void removeSelectionInterval(int index0, int index1) { 704 TreePath[] paths = getPathBetweenRows(index0, index1); 705 this.getSelectionModel().removeSelectionPaths(paths); 706 } 707 708 714 public void removeSelectionPath(TreePath path) { 715 getSelectionModel().removeSelectionPath(path); 716 } 717 718 725 public void removeSelectionPaths(TreePath[] paths) { 726 getSelectionModel().removeSelectionPaths(paths); 727 } 728 729 735 public void removeSelectionRow(int row) { 736 int[] rows = {row}; 737 removeSelectionRows(rows); 738 } 739 740 public void removeSelectionRows(int[] rows) { 741 TreePath[] paths = new TreePath[rows.length]; 742 for (int i = 0; i < rows.length; i++) 743 paths[i] = getPathForRow(rows[i]); 744 removeSelectionPaths(paths); 745 } 746 747 public int getMaximumExpandedDepth() { 748 int max = 0; 749 for (int i = 0; i < getRowCount(); i++) 750 max = Math.max(max, getPathForRow(i).getPathCount()); 751 return max; 752 } 753 754 762 public void expandRow(TreePath p) { 763 treeState.setExpandedState(p, true); 764 775 fireTreeExpanded(p); 776 reload(); 777 } 778 779 public void expandRow(int row) { 780 expandRow(getPathForRow(row)); 781 } 782 783 public void collapseRow(TreePath p) { 784 treeState.setExpandedState(p, false); 785 fireTreeCollapsed(p); 786 reload(); 787 } 788 789 public void collapseRow(int row) { 790 collapseRow(getPathForRow(row)); 791 } 792 793 public boolean isVisible(TreePath path) { 794 if (path != null) { 795 TreePath parentPath = path.getParentPath(); 796 797 if (parentPath != null) 798 return isExpanded(parentPath); 799 800 return true; 802 } 803 804 return false; 805 } 806 807 public boolean isExpanded(TreePath path) { 808 return treeState.isExpanded(path); 809 } 810 811 protected void togglePathSelection(TreePath path) { 812 if (path != null) { 813 if (isPathSelected(path)) { 814 removeSelectionPath(path); 815 } else { 816 addSelectionPath(path); 817 } 818 } 819 } 820 821 protected void togglePathExpansion(TreePath path) 822 throws ExpandVetoException { 823 if (path != null) { 824 if (treeState.isExpanded(path)) { 825 fireTreeWillExpand(path, false); 826 collapseRow(path); 827 } else { 828 fireTreeWillExpand(path, true); 829 expandRow(path); 830 } 831 } 832 } 833 834 838 public String getExpansionParameter(int row, boolean absolute) { 839 return (absolute ? "j" : "h") + row; 840 } 841 842 846 public String getSelectionParameter(int row, boolean absolute) { 847 return (absolute ? "a" : "b") + row; 848 } 849 850 851 public void processLowLevelEvent(String action, String [] values) { 852 processKeyEvents(values); 853 854 getSelectionModel().setDelayEvents(true); 855 for (int i = 0; i < values.length; i++) { 856 if (values[i].length() < 2) continue; 858 int row = Integer.parseInt(values[i].substring(1)); 859 860 if (row < 0) continue; 862 if (values[i].charAt(0) == 'b') { 863 TreePath path = getPathForRow(row); 864 if (path != null) { 866 togglePathSelection(path); 867 } 868 } else if (values[i].charAt(0) == 'h') { 869 TreePath path = getPathForRow(row); 870 if (path != null) { 872 requestedExpansionPaths.add(path); 873 } 874 } else if (values[i].charAt(0) == 'a') { 875 TreePath path = getPathForAbsoluteRow(row); 876 if (path != null) { 878 togglePathSelection(path); 879 } 880 } else if (values[i].charAt(0) == 'j') { 881 TreePath path = getPathForAbsoluteRow(row); 882 if (path != null) { 884 requestedExpansionPaths.add(path); 885 } 886 } 887 } 888 SForm.addArmedComponent(this); 889 getSelectionModel().setDelayEvents(false); 890 } 891 892 public void setNodeIndentDepth(int depth) { 893 nodeIndentDepth = depth; 894 } 895 896 public int getNodeIndentDepth() { 897 return nodeIndentDepth; 898 } 899 900 public void setCellRenderer(STreeCellRenderer x) { 901 renderer = x; 902 } 903 904 public STreeCellRenderer getCellRenderer() { 905 return renderer; 906 } 907 908 911 protected TreeModelListener createTreeModelListener() { 912 return new TreeModelHandler(); 913 } 914 915 916 920 protected class TreeModelHandler implements TreeModelListener { 921 public void treeNodesChanged(TreeModelEvent e) { 922 if (e == null) 923 return; 924 treeState.treeNodesChanged(e); 925 reload(); 926 } 927 928 public void treeNodesInserted(TreeModelEvent e) { 929 if (e == null) 930 return; 931 treeState.treeNodesInserted(e); 932 reload(); 933 } 934 935 public void treeStructureChanged(TreeModelEvent e) { 936 if (e == null) 937 return; 938 treeState.treeStructureChanged(e); 939 reload(); 940 } 941 942 public void treeNodesRemoved(TreeModelEvent e) { 943 if (e == null) 944 return; 945 treeState.treeNodesRemoved(e); 946 reload(); 947 } 948 } 949 950 public void setParent(SContainer p) { 951 super.setParent(p); 952 if (getCellRendererPane() != null) 953 getCellRendererPane().setParent(p); 954 } 955 956 protected void setParentFrame(SFrame f) { 957 super.setParentFrame(f); 958 if (getCellRendererPane() != null) 959 getCellRendererPane().setParentFrame(f); 960 } 961 962 963 private SCellRendererPane cellRendererPane = new SCellRendererPane(); 965 966 967 public SCellRendererPane getCellRendererPane() { 968 return cellRendererPane; 969 } 970 971 976 public Rectangle getScrollableViewportSize() { 977 return new Rectangle(0, 0, 1, getRowCount()); 978 } 979 980 983 public void setViewportSize(Rectangle d) { 984 Rectangle oldViewport = viewport; 985 viewport = d; 986 if ((viewport == null && oldViewport != null) || 987 (viewport != null && !viewport.equals(oldViewport))) 988 reload(); 989 } 990 991 public Rectangle getViewportSize() { 992 return viewport; 993 } 994 995 public Dimension getPreferredExtent() { 996 return null; 997 } 998 999 public void setCG(TreeCG cg) { 1000 super.setCG(cg); 1001 } 1002} 1003 1004 1005 | Popular Tags |