1 7 8 package javax.swing.plaf.basic; 9 10 import javax.swing.*; 11 import javax.swing.event.*; 12 import java.awt.*; 13 import java.awt.event.*; 14 import java.awt.datatransfer.*; 15 import java.awt.dnd.*; 16 import java.beans.*; 17 import java.io.*; 18 import java.util.Enumeration ; 19 import java.util.Hashtable ; 20 import java.util.TooManyListenersException ; 21 import java.util.ArrayList ; 22 import java.util.Collections ; 23 import java.util.Comparator ; 24 import javax.swing.plaf.ActionMapUIResource ; 25 import javax.swing.plaf.ComponentUI ; 26 import javax.swing.plaf.UIResource ; 27 import javax.swing.plaf.TreeUI ; 28 import javax.swing.tree.*; 29 import javax.swing.text.Position ; 30 import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag ; 31 import com.sun.java.swing.SwingUtilities2; 32 import static com.sun.java.swing.SwingUtilities2.DRAG_FIX; 33 34 import sun.swing.DefaultLookup; 35 import sun.swing.UIAction; 36 37 45 46 public class BasicTreeUI extends TreeUI 47 { 48 static private final Actions SHARED_ACTION = new Actions(); 50 51 static private final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0); 52 53 transient protected Icon collapsedIcon; 54 transient protected Icon expandedIcon; 55 56 60 private Color hashColor; 61 62 64 protected int leftChildIndent; 65 67 protected int rightChildIndent; 68 70 protected int totalChildIndent; 71 72 73 protected Dimension preferredMinSize; 74 75 76 protected int lastSelectedRow; 77 78 79 protected JTree tree; 80 81 82 transient protected TreeCellRenderer currentCellRenderer; 83 84 86 protected boolean createdRenderer; 87 88 89 transient protected TreeCellEditor cellEditor; 90 91 93 protected boolean createdCellEditor; 94 95 97 protected boolean stopEditingInCompleteEditing; 98 99 100 protected CellRendererPane rendererPane; 101 102 103 protected Dimension preferredSize; 104 105 106 protected boolean validCachedPreferredSize; 107 108 109 protected AbstractLayoutCache treeState; 110 111 112 113 protected Hashtable <TreePath,Boolean > drawingCache; 114 115 118 protected boolean largeModel; 119 120 121 protected AbstractLayoutCache.NodeDimensions nodeDimensions; 122 123 124 protected TreeModel treeModel; 125 126 127 protected TreeSelectionModel treeSelectionModel; 128 129 132 protected int depthOffset; 133 134 137 private int lastWidth; 138 139 141 143 protected Component editingComponent; 144 145 146 protected TreePath editingPath; 147 148 150 protected int editingRow; 151 152 153 protected boolean editorHasDifferentSize; 154 155 156 private int leadRow; 157 159 private boolean ignoreLAChange; 160 161 162 private boolean leftToRight; 163 164 private PropertyChangeListener propertyChangeListener; 166 private PropertyChangeListener selectionModelPropertyChangeListener; 167 private MouseListener mouseListener; 168 private FocusListener focusListener; 169 private KeyListener keyListener; 170 172 private ComponentListener componentListener; 173 174 private CellEditorListener cellEditorListener; 175 176 private TreeSelectionListener treeSelectionListener; 177 178 private TreeModelListener treeModelListener; 179 180 private TreeExpansionListener treeExpansionListener; 181 182 183 private boolean paintLines = true; 184 185 186 private boolean lineTypeDashed; 187 188 192 private long timeFactor = 1000L; 193 194 private Handler handler; 195 196 200 private MouseEvent releaseEvent; 201 202 public static ComponentUI createUI(JComponent x) { 203 return new BasicTreeUI (); 204 } 205 206 207 static void loadActionMap(LazyActionMap map) { 208 map.put(new Actions(Actions.SELECT_PREVIOUS)); 209 map.put(new Actions(Actions.SELECT_PREVIOUS_CHANGE_LEAD)); 210 map.put(new Actions(Actions.SELECT_PREVIOUS_EXTEND_SELECTION)); 211 212 map.put(new Actions(Actions.SELECT_NEXT)); 213 map.put(new Actions(Actions.SELECT_NEXT_CHANGE_LEAD)); 214 map.put(new Actions(Actions.SELECT_NEXT_EXTEND_SELECTION)); 215 216 map.put(new Actions(Actions.SELECT_CHILD)); 217 map.put(new Actions(Actions.SELECT_CHILD_CHANGE_LEAD)); 218 219 map.put(new Actions(Actions.SELECT_PARENT)); 220 map.put(new Actions(Actions.SELECT_PARENT_CHANGE_LEAD)); 221 222 map.put(new Actions(Actions.SCROLL_UP_CHANGE_SELECTION)); 223 map.put(new Actions(Actions.SCROLL_UP_CHANGE_LEAD)); 224 map.put(new Actions(Actions.SCROLL_UP_EXTEND_SELECTION)); 225 226 map.put(new Actions(Actions.SCROLL_DOWN_CHANGE_SELECTION)); 227 map.put(new Actions(Actions.SCROLL_DOWN_EXTEND_SELECTION)); 228 map.put(new Actions(Actions.SCROLL_DOWN_CHANGE_LEAD)); 229 230 map.put(new Actions(Actions.SELECT_FIRST)); 231 map.put(new Actions(Actions.SELECT_FIRST_CHANGE_LEAD)); 232 map.put(new Actions(Actions.SELECT_FIRST_EXTEND_SELECTION)); 233 234 map.put(new Actions(Actions.SELECT_LAST)); 235 map.put(new Actions(Actions.SELECT_LAST_CHANGE_LEAD)); 236 map.put(new Actions(Actions.SELECT_LAST_EXTEND_SELECTION)); 237 238 map.put(new Actions(Actions.TOGGLE)); 239 240 map.put(new Actions(Actions.CANCEL_EDITING)); 241 242 map.put(new Actions(Actions.START_EDITING)); 243 244 map.put(new Actions(Actions.SELECT_ALL)); 245 246 map.put(new Actions(Actions.CLEAR_SELECTION)); 247 248 map.put(new Actions(Actions.SCROLL_LEFT)); 249 map.put(new Actions(Actions.SCROLL_RIGHT)); 250 251 map.put(new Actions(Actions.SCROLL_LEFT_EXTEND_SELECTION)); 252 map.put(new Actions(Actions.SCROLL_RIGHT_EXTEND_SELECTION)); 253 254 map.put(new Actions(Actions.SCROLL_RIGHT_CHANGE_LEAD)); 255 map.put(new Actions(Actions.SCROLL_LEFT_CHANGE_LEAD)); 256 257 map.put(new Actions(Actions.EXPAND)); 258 map.put(new Actions(Actions.COLLAPSE)); 259 map.put(new Actions(Actions.MOVE_SELECTION_TO_PARENT)); 260 261 map.put(new Actions(Actions.ADD_TO_SELECTION)); 262 map.put(new Actions(Actions.TOGGLE_AND_ANCHOR)); 263 map.put(new Actions(Actions.EXTEND_TO)); 264 map.put(new Actions(Actions.MOVE_SELECTION_TO)); 265 266 map.put(TransferHandler.getCutAction()); 267 map.put(TransferHandler.getCopyAction()); 268 map.put(TransferHandler.getPasteAction()); 269 } 270 271 272 public BasicTreeUI() { 273 super(); 274 } 275 276 protected Color getHashColor() { 277 return hashColor; 278 } 279 280 protected void setHashColor(Color color) { 281 hashColor = color; 282 } 283 284 public void setLeftChildIndent(int newAmount) { 285 leftChildIndent = newAmount; 286 totalChildIndent = leftChildIndent + rightChildIndent; 287 if(treeState != null) 288 treeState.invalidateSizes(); 289 updateSize(); 290 } 291 292 public int getLeftChildIndent() { 293 return leftChildIndent; 294 } 295 296 public void setRightChildIndent(int newAmount) { 297 rightChildIndent = newAmount; 298 totalChildIndent = leftChildIndent + rightChildIndent; 299 if(treeState != null) 300 treeState.invalidateSizes(); 301 updateSize(); 302 } 303 304 public int getRightChildIndent() { 305 return rightChildIndent; 306 } 307 308 public void setExpandedIcon(Icon newG) { 309 expandedIcon = newG; 310 } 311 312 public Icon getExpandedIcon() { 313 return expandedIcon; 314 } 315 316 public void setCollapsedIcon(Icon newG) { 317 collapsedIcon = newG; 318 } 319 320 public Icon getCollapsedIcon() { 321 return collapsedIcon; 322 } 323 324 330 333 protected void setLargeModel(boolean largeModel) { 334 if(getRowHeight() < 1) 335 largeModel = false; 336 if(this.largeModel != largeModel) { 337 completeEditing(); 338 this.largeModel = largeModel; 339 treeState = createLayoutCache(); 340 configureLayoutCache(); 341 updateLayoutCacheExpandedNodes(); 342 updateSize(); 343 } 344 } 345 346 protected boolean isLargeModel() { 347 return largeModel; 348 } 349 350 353 protected void setRowHeight(int rowHeight) { 354 completeEditing(); 355 if(treeState != null) { 356 setLargeModel(tree.isLargeModel()); 357 treeState.setRowHeight(rowHeight); 358 updateSize(); 359 } 360 } 361 362 protected int getRowHeight() { 363 return (tree == null) ? -1 : tree.getRowHeight(); 364 } 365 366 370 protected void setCellRenderer(TreeCellRenderer tcr) { 371 completeEditing(); 372 updateRenderer(); 373 if(treeState != null) { 374 treeState.invalidateSizes(); 375 updateSize(); 376 } 377 } 378 379 383 protected TreeCellRenderer getCellRenderer() { 384 return currentCellRenderer; 385 } 386 387 390 protected void setModel(TreeModel model) { 391 completeEditing(); 392 if(treeModel != null && treeModelListener != null) 393 treeModel.removeTreeModelListener(treeModelListener); 394 treeModel = model; 395 if(treeModel != null) { 396 if(treeModelListener != null) 397 treeModel.addTreeModelListener(treeModelListener); 398 } 399 if(treeState != null) { 400 treeState.setModel(model); 401 updateLayoutCacheExpandedNodes(); 402 updateSize(); 403 } 404 } 405 406 protected TreeModel getModel() { 407 return treeModel; 408 } 409 410 413 protected void setRootVisible(boolean newValue) { 414 completeEditing(); 415 updateDepthOffset(); 416 if(treeState != null) { 417 treeState.setRootVisible(newValue); 418 treeState.invalidateSizes(); 419 updateSize(); 420 } 421 } 422 423 protected boolean isRootVisible() { 424 return (tree != null) ? tree.isRootVisible() : false; 425 } 426 427 430 protected void setShowsRootHandles(boolean newValue) { 431 completeEditing(); 432 updateDepthOffset(); 433 if(treeState != null) { 434 treeState.invalidateSizes(); 435 updateSize(); 436 } 437 } 438 439 protected boolean getShowsRootHandles() { 440 return (tree != null) ? tree.getShowsRootHandles() : false; 441 } 442 443 446 protected void setCellEditor(TreeCellEditor editor) { 447 updateCellEditor(); 448 } 449 450 protected TreeCellEditor getCellEditor() { 451 return (tree != null) ? tree.getCellEditor() : null; 452 } 453 454 457 protected void setEditable(boolean newValue) { 458 updateCellEditor(); 459 } 460 461 protected boolean isEditable() { 462 return (tree != null) ? tree.isEditable() : false; 463 } 464 465 469 protected void setSelectionModel(TreeSelectionModel newLSM) { 470 completeEditing(); 471 if(selectionModelPropertyChangeListener != null && 472 treeSelectionModel != null) 473 treeSelectionModel.removePropertyChangeListener 474 (selectionModelPropertyChangeListener); 475 if(treeSelectionListener != null && treeSelectionModel != null) 476 treeSelectionModel.removeTreeSelectionListener 477 (treeSelectionListener); 478 treeSelectionModel = newLSM; 479 if(treeSelectionModel != null) { 480 if(selectionModelPropertyChangeListener != null) 481 treeSelectionModel.addPropertyChangeListener 482 (selectionModelPropertyChangeListener); 483 if(treeSelectionListener != null) 484 treeSelectionModel.addTreeSelectionListener 485 (treeSelectionListener); 486 if(treeState != null) 487 treeState.setSelectionModel(treeSelectionModel); 488 } 489 else if(treeState != null) 490 treeState.setSelectionModel(null); 491 if(tree != null) 492 tree.repaint(); 493 } 494 495 protected TreeSelectionModel getSelectionModel() { 496 return treeSelectionModel; 497 } 498 499 503 508 public Rectangle getPathBounds(JTree tree, TreePath path) { 509 if(tree != null && treeState != null) { 510 Insets i = tree.getInsets(); 511 Rectangle bounds = treeState.getBounds(path, null); 512 513 if(bounds != null && i != null) { 514 bounds.x += i.left; 515 bounds.y += i.top; 516 } 517 return bounds; 518 } 519 return null; 520 } 521 522 526 public TreePath getPathForRow(JTree tree, int row) { 527 return (treeState != null) ? treeState.getPathForRow(row) : null; 528 } 529 530 535 public int getRowForPath(JTree tree, TreePath path) { 536 return (treeState != null) ? treeState.getRowForPath(path) : -1; 537 } 538 539 542 public int getRowCount(JTree tree) { 543 return (treeState != null) ? treeState.getRowCount() : 0; 544 } 545 546 553 public TreePath getClosestPathForLocation(JTree tree, int x, int y) { 554 if(tree != null && treeState != null) { 555 Insets i = tree.getInsets(); 556 557 if(i == null) 558 i = EMPTY_INSETS; 559 560 return treeState.getPathClosestTo(x - i.left, y - i.top); 561 } 562 return null; 563 } 564 565 569 public boolean isEditing(JTree tree) { 570 return (editingComponent != null); 571 } 572 573 578 public boolean stopEditing(JTree tree) { 579 if(editingComponent != null && cellEditor.stopCellEditing()) { 580 completeEditing(false, false, true); 581 return true; 582 } 583 return false; 584 } 585 586 589 public void cancelEditing(JTree tree) { 590 if(editingComponent != null) { 591 completeEditing(false, true, false); 592 } 593 } 594 595 599 public void startEditingAtPath(JTree tree, TreePath path) { 600 tree.scrollPathToVisible(path); 601 if(path != null && tree.isVisible(path)) 602 startEditing(path, null); 603 } 604 605 608 public TreePath getEditingPath(JTree tree) { 609 return editingPath; 610 } 611 612 616 public void installUI(JComponent c) { 617 if ( c == null ) { 618 throw new NullPointerException ( "null component passed to BasicTreeUI.installUI()" ); 619 } 620 621 tree = (JTree)c; 622 623 prepareForUIInstall(); 624 625 installDefaults(); 627 installKeyboardActions(); 628 installComponents(); 629 installListeners(); 630 631 completeUIInstall(); 632 } 633 634 638 protected void prepareForUIInstall() { 639 drawingCache = new Hashtable <TreePath,Boolean >(7); 640 641 leftToRight = BasicGraphicsUtils.isLeftToRight(tree); 643 lastWidth = tree.getWidth(); 644 stopEditingInCompleteEditing = true; 645 lastSelectedRow = -1; 646 leadRow = -1; 647 preferredSize = new Dimension(); 648 649 largeModel = tree.isLargeModel(); 650 if(getRowHeight() <= 0) 651 largeModel = false; 652 setModel(tree.getModel()); 653 } 654 655 659 protected void completeUIInstall() { 660 662 this.setShowsRootHandles(tree.getShowsRootHandles()); 663 664 updateRenderer(); 665 666 updateDepthOffset(); 667 668 setSelectionModel(tree.getSelectionModel()); 669 670 treeState = createLayoutCache(); 672 configureLayoutCache(); 673 674 updateSize(); 675 } 676 677 protected void installDefaults() { 678 if(tree.getBackground() == null || 679 tree.getBackground() instanceof UIResource ) { 680 tree.setBackground(UIManager.getColor("Tree.background")); 681 } 682 if(getHashColor() == null || getHashColor() instanceof UIResource ) { 683 setHashColor(UIManager.getColor("Tree.hash")); 684 } 685 if (tree.getFont() == null || tree.getFont() instanceof UIResource ) 686 tree.setFont( UIManager.getFont("Tree.font") ); 687 695 setExpandedIcon( (Icon)UIManager.get( "Tree.expandedIcon" ) ); 696 setCollapsedIcon( (Icon)UIManager.get( "Tree.collapsedIcon" ) ); 697 698 setLeftChildIndent(((Integer )UIManager.get("Tree.leftChildIndent")). 699 intValue()); 700 setRightChildIndent(((Integer )UIManager.get("Tree.rightChildIndent")). 701 intValue()); 702 703 LookAndFeel.installProperty(tree, "rowHeight", 704 UIManager.get("Tree.rowHeight")); 705 706 largeModel = (tree.isLargeModel() && tree.getRowHeight() > 0); 707 708 Object scrollsOnExpand = UIManager.get("Tree.scrollsOnExpand"); 709 if (scrollsOnExpand != null) { 710 LookAndFeel.installProperty(tree, "scrollsOnExpand", scrollsOnExpand); 711 } 712 713 paintLines = UIManager.getBoolean("Tree.paintLines"); 714 lineTypeDashed = UIManager.getBoolean("Tree.lineTypeDashed"); 715 716 Long l = (Long )UIManager.get("Tree.timeFactor"); 717 timeFactor = (l!=null) ? l.longValue() : 1000L; 718 719 Object showsRootHandles = UIManager.get("Tree.showsRootHandles"); 720 if (showsRootHandles != null) { 721 LookAndFeel.installProperty(tree, 722 JTree.SHOWS_ROOT_HANDLES_PROPERTY, showsRootHandles); 723 } 724 } 725 726 protected void installListeners() { 727 if ( (propertyChangeListener = createPropertyChangeListener()) 728 != null ) { 729 tree.addPropertyChangeListener(propertyChangeListener); 730 } 731 if (!DRAG_FIX) { 732 tree.addMouseListener(defaultDragRecognizer); 733 tree.addMouseMotionListener(defaultDragRecognizer); 734 } 735 if ( (mouseListener = createMouseListener()) != null ) { 736 tree.addMouseListener(mouseListener); 737 if (mouseListener instanceof MouseMotionListener) { 738 tree.addMouseMotionListener((MouseMotionListener)mouseListener); 739 } 740 } 741 if ((focusListener = createFocusListener()) != null ) { 742 tree.addFocusListener(focusListener); 743 } 744 if ((keyListener = createKeyListener()) != null) { 745 tree.addKeyListener(keyListener); 746 } 747 if((treeExpansionListener = createTreeExpansionListener()) != null) { 748 tree.addTreeExpansionListener(treeExpansionListener); 749 } 750 if((treeModelListener = createTreeModelListener()) != null && 751 treeModel != null) { 752 treeModel.addTreeModelListener(treeModelListener); 753 } 754 if((selectionModelPropertyChangeListener = 755 createSelectionModelPropertyChangeListener()) != null && 756 treeSelectionModel != null) { 757 treeSelectionModel.addPropertyChangeListener 758 (selectionModelPropertyChangeListener); 759 } 760 if((treeSelectionListener = createTreeSelectionListener()) != null && 761 treeSelectionModel != null) { 762 treeSelectionModel.addTreeSelectionListener(treeSelectionListener); 763 } 764 765 TransferHandler th = tree.getTransferHandler(); 766 if (th == null || th instanceof UIResource ) { 767 tree.setTransferHandler(defaultTransferHandler); 768 } 769 DropTarget dropTarget = tree.getDropTarget(); 770 if (dropTarget instanceof UIResource ) { 771 if (defaultDropTargetListener == null) { 772 defaultDropTargetListener = new TreeDropTargetListener(); 773 } 774 try { 775 dropTarget.addDropTargetListener(defaultDropTargetListener); 776 } catch (TooManyListenersException tmle) { 777 } 779 } 780 LookAndFeel.installProperty(tree, "opaque", Boolean.TRUE); 781 } 782 783 protected void installKeyboardActions() { 784 InputMap km = getInputMap(JComponent. 785 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 786 787 SwingUtilities.replaceUIInputMap(tree, JComponent. 788 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, 789 km); 790 km = getInputMap(JComponent.WHEN_FOCUSED); 791 SwingUtilities.replaceUIInputMap(tree, JComponent.WHEN_FOCUSED, km); 792 793 LazyActionMap.installLazyActionMap(tree, BasicTreeUI .class, 794 "Tree.actionMap"); 795 } 796 797 InputMap getInputMap(int condition) { 798 if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { 799 return (InputMap)DefaultLookup.get(tree, this, 800 "Tree.ancestorInputMap"); 801 } 802 else if (condition == JComponent.WHEN_FOCUSED) { 803 InputMap keyMap = (InputMap)DefaultLookup.get(tree, this, 804 "Tree.focusInputMap"); 805 InputMap rtlKeyMap; 806 807 if (tree.getComponentOrientation().isLeftToRight() || 808 ((rtlKeyMap = (InputMap)DefaultLookup.get(tree, this, 809 "Tree.focusInputMap.RightToLeft")) == null)) { 810 return keyMap; 811 } else { 812 rtlKeyMap.setParent(keyMap); 813 return rtlKeyMap; 814 } 815 } 816 return null; 817 } 818 819 822 protected void installComponents() { 823 if ((rendererPane = createCellRendererPane()) != null) { 824 tree.add( rendererPane ); 825 } 826 } 827 828 832 836 protected AbstractLayoutCache.NodeDimensions createNodeDimensions() { 837 return new NodeDimensionsHandler(); 838 } 839 840 844 protected PropertyChangeListener createPropertyChangeListener() { 845 return getHandler(); 846 } 847 848 private Handler getHandler() { 849 if (handler == null) { 850 handler = DRAG_FIX ? new DragFixHandler() : new Handler(); 851 } 852 return handler; 853 } 854 855 859 protected MouseListener createMouseListener() { 860 return getHandler(); 861 } 862 863 867 protected FocusListener createFocusListener() { 868 return getHandler(); 869 } 870 871 875 protected KeyListener createKeyListener() { 876 return getHandler(); 877 } 878 879 883 protected PropertyChangeListener createSelectionModelPropertyChangeListener() { 884 return getHandler(); 885 } 886 887 891 protected TreeSelectionListener createTreeSelectionListener() { 892 return getHandler(); 893 } 894 895 898 protected CellEditorListener createCellEditorListener() { 899 return getHandler(); 900 } 901 902 907 protected ComponentListener createComponentListener() { 908 return new ComponentHandler(); 909 } 910 911 915 protected TreeExpansionListener createTreeExpansionListener() { 916 return getHandler(); 917 } 918 919 923 protected AbstractLayoutCache createLayoutCache() { 924 if(isLargeModel() && getRowHeight() > 0) { 925 return new FixedHeightLayoutCache(); 926 } 927 return new VariableHeightLayoutCache(); 928 } 929 930 933 protected CellRendererPane createCellRendererPane() { 934 return new CellRendererPane(); 935 } 936 937 940 protected TreeCellEditor createDefaultCellEditor() { 941 if(currentCellRenderer != null && 942 (currentCellRenderer instanceof DefaultTreeCellRenderer)) { 943 DefaultTreeCellEditor editor = new DefaultTreeCellEditor 944 (tree, (DefaultTreeCellRenderer)currentCellRenderer); 945 946 return editor; 947 } 948 return new DefaultTreeCellEditor(tree, null); 949 } 950 951 955 protected TreeCellRenderer createDefaultCellRenderer() { 956 return new DefaultTreeCellRenderer(); 957 } 958 959 962 protected TreeModelListener createTreeModelListener() { 963 return getHandler(); 964 } 965 966 970 public void uninstallUI(JComponent c) { 971 completeEditing(); 972 973 prepareForUIUninstall(); 974 975 uninstallDefaults(); 976 uninstallListeners(); 977 uninstallKeyboardActions(); 978 uninstallComponents(); 979 980 completeUIUninstall(); 981 } 982 983 protected void prepareForUIUninstall() { 984 } 985 986 protected void completeUIUninstall() { 987 if(createdRenderer) { 988 tree.setCellRenderer(null); 989 } 990 if(createdCellEditor) { 991 tree.setCellEditor(null); 992 } 993 cellEditor = null; 994 currentCellRenderer = null; 995 rendererPane = null; 996 componentListener = null; 997 propertyChangeListener = null; 998 mouseListener = null; 999 focusListener = null; 1000 keyListener = null; 1001 setSelectionModel(null); 1002 treeState = null; 1003 drawingCache = null; 1004 selectionModelPropertyChangeListener = null; 1005 tree = null; 1006 treeModel = null; 1007 treeSelectionModel = null; 1008 treeSelectionListener = null; 1009 treeExpansionListener = null; 1010 } 1011 1012 protected void uninstallDefaults() { 1013 if (tree.getTransferHandler() instanceof UIResource ) { 1014 tree.setTransferHandler(null); 1015 } 1016 } 1017 1018 protected void uninstallListeners() { 1019 if(componentListener != null) { 1020 tree.removeComponentListener(componentListener); 1021 } 1022 if (propertyChangeListener != null) { 1023 tree.removePropertyChangeListener(propertyChangeListener); 1024 } 1025 if (!DRAG_FIX) { 1026 tree.removeMouseListener(defaultDragRecognizer); 1027 tree.removeMouseMotionListener(defaultDragRecognizer); 1028 } 1029 if (mouseListener != null) { 1030 tree.removeMouseListener(mouseListener); 1031 if (mouseListener instanceof MouseMotionListener) { 1032 tree.removeMouseMotionListener((MouseMotionListener)mouseListener); 1033 } 1034 } 1035 if (focusListener != null) { 1036 tree.removeFocusListener(focusListener); 1037 } 1038 if (keyListener != null) { 1039 tree.removeKeyListener(keyListener); 1040 } 1041 if(treeExpansionListener != null) { 1042 tree.removeTreeExpansionListener(treeExpansionListener); 1043 } 1044 if(treeModel != null && treeModelListener != null) { 1045 treeModel.removeTreeModelListener(treeModelListener); 1046 } 1047 if(selectionModelPropertyChangeListener != null && 1048 treeSelectionModel != null) { 1049 treeSelectionModel.removePropertyChangeListener 1050 (selectionModelPropertyChangeListener); 1051 } 1052 if(treeSelectionListener != null && treeSelectionModel != null) { 1053 treeSelectionModel.removeTreeSelectionListener 1054 (treeSelectionListener); 1055 } 1056 handler = null; 1057 } 1058 1059 protected void uninstallKeyboardActions() { 1060 SwingUtilities.replaceUIActionMap(tree, null); 1061 SwingUtilities.replaceUIInputMap(tree, JComponent. 1062 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, 1063 null); 1064 SwingUtilities.replaceUIInputMap(tree, JComponent.WHEN_FOCUSED, null); 1065 } 1066 1067 1070 protected void uninstallComponents() { 1071 if(rendererPane != null) { 1072 tree.remove(rendererPane); 1073 } 1074 } 1075 1076 1079 private void redoTheLayout() { 1080 if (treeState != null) { 1081 treeState.invalidateSizes(); 1082 } 1083 } 1084 1085 1089 public void paint(Graphics g, JComponent c) { 1090 if (tree != c) { 1091 throw new InternalError ("incorrect component"); 1092 } 1093 1094 if(treeState == null) { 1096 return; 1097 } 1098 1099 int width = tree.getWidth(); 1103 1104 if (width != lastWidth) { 1105 lastWidth = width; 1106 if (!leftToRight) { 1107 redoTheLayout(); 1110 updateSize(); 1111 } 1112 } 1113 1114 Rectangle paintBounds = g.getClipBounds(); 1115 Insets insets = tree.getInsets(); 1116 1117 if(insets == null) 1118 insets = EMPTY_INSETS; 1119 1120 TreePath initialPath = getClosestPathForLocation 1121 (tree, 0, paintBounds.y); 1122 Enumeration paintingEnumerator = treeState.getVisiblePathsFrom 1123 (initialPath); 1124 int row = treeState.getRowForPath(initialPath); 1125 int endY = paintBounds.y + paintBounds.height; 1126 1127 drawingCache.clear(); 1128 1129 if(initialPath != null && paintingEnumerator != null) { 1130 TreePath parentPath = initialPath; 1131 1132 1134 parentPath = parentPath.getParentPath(); 1136 while(parentPath != null) { 1137 paintVerticalPartOfLeg(g, paintBounds, insets, parentPath); 1138 drawingCache.put(parentPath, Boolean.TRUE); 1139 parentPath = parentPath.getParentPath(); 1140 } 1141 1142 boolean done = false; 1143 boolean isExpanded; 1145 boolean hasBeenExpanded; 1146 boolean isLeaf; 1147 Rectangle boundsBuffer = new Rectangle(); 1148 Rectangle bounds; 1149 TreePath path; 1150 boolean rootVisible = isRootVisible(); 1151 1152 while(!done && paintingEnumerator.hasMoreElements()) { 1153 path = (TreePath)paintingEnumerator.nextElement(); 1154 if(path != null) { 1155 isLeaf = treeModel.isLeaf(path.getLastPathComponent()); 1156 if(isLeaf) 1157 isExpanded = hasBeenExpanded = false; 1158 else { 1159 isExpanded = treeState.getExpandedState(path); 1160 hasBeenExpanded = tree.hasBeenExpanded(path); 1161 } 1162 bounds = treeState.getBounds(path, boundsBuffer); 1163 if(bounds == null) 1164 return; 1169 bounds.x += insets.left; 1170 bounds.y += insets.top; 1171 parentPath = path.getParentPath(); 1173 if(parentPath != null) { 1174 if(drawingCache.get(parentPath) == null) { 1175 paintVerticalPartOfLeg(g, paintBounds, 1176 insets, parentPath); 1177 drawingCache.put(parentPath, Boolean.TRUE); 1178 } 1179 paintHorizontalPartOfLeg(g, paintBounds, insets, 1180 bounds, path, row, 1181 isExpanded, 1182 hasBeenExpanded, isLeaf); 1183 } 1184 else if(rootVisible && row == 0) { 1185 paintHorizontalPartOfLeg(g, paintBounds, insets, 1186 bounds, path, row, 1187 isExpanded, 1188 hasBeenExpanded, isLeaf); 1189 } 1190 if(shouldPaintExpandControl(path, row, isExpanded, 1191 hasBeenExpanded, isLeaf)) { 1192 paintExpandControl(g, paintBounds, insets, bounds, 1193 path, row, isExpanded, 1194 hasBeenExpanded, isLeaf); 1195 } 1196 if (!leftToRight) { 1201 bounds.x +=4; 1202 } 1203 paintRow(g, paintBounds, insets, bounds, path, 1204 row, isExpanded, hasBeenExpanded, isLeaf); 1205 if((bounds.y + bounds.height) >= endY) 1206 done = true; 1207 } 1208 else { 1209 done = true; 1210 } 1211 row++; 1212 } 1213 } 1214 rendererPane.removeAll(); 1216 } 1217 1218 1223 protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, 1224 Insets insets, Rectangle bounds, 1225 TreePath path, int row, 1226 boolean isExpanded, 1227 boolean hasBeenExpanded, boolean 1228 isLeaf) { 1229 if (!paintLines) { 1230 return; 1231 } 1232 1233 int depth = path.getPathCount() - 1; 1235 if((depth == 0 || (depth == 1 && !isRootVisible())) && 1236 !getShowsRootHandles()) { 1237 return; 1238 } 1239 1240 int clipLeft = clipBounds.x; 1241 int clipRight = clipBounds.x + (clipBounds.width - 1); 1242 int clipTop = clipBounds.y; 1243 int clipBottom = clipBounds.y + (clipBounds.height - 1); 1244 int lineY = bounds.y + bounds.height / 2; 1245 if (leftToRight) { 1247 int leftX = bounds.x - getRightChildIndent(); 1248 int nodeX = bounds.x - getHorizontalLegBuffer(); 1249 1250 if(lineY >= clipTop && lineY <= clipBottom && nodeX >= clipLeft && 1251 leftX <= clipRight ) { 1252 leftX = Math.max(Math.max(insets.left, leftX), clipLeft); 1253 nodeX = Math.min(Math.max(insets.left, nodeX), clipRight); 1254 1255 if (leftX != nodeX) { 1256 g.setColor(getHashColor()); 1257 paintHorizontalLine(g, tree, lineY, leftX, nodeX); 1258 } 1259 } 1260 } 1261 else { 1262 int leftX = bounds.x + bounds.width + getRightChildIndent(); 1263 int nodeX = bounds.x + bounds.width + 1264 getHorizontalLegBuffer() - 1; 1265 1266 if(lineY >= clipTop && lineY <= clipBottom && 1267 leftX >= clipLeft && nodeX <= clipRight) { 1268 leftX = Math.min(leftX, clipRight); 1269 nodeX = Math.max(nodeX, clipLeft); 1270 1271 g.setColor(getHashColor()); 1272 paintHorizontalLine(g, tree, lineY, nodeX, leftX); 1273 } 1274 } 1275 } 1276 1277 1281 protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, 1282 Insets insets, TreePath path) { 1283 if (!paintLines) { 1284 return; 1285 } 1286 1287 int depth = path.getPathCount() - 1; 1288 if (depth == 0 && !getShowsRootHandles() && !isRootVisible()) { 1289 return; 1290 } 1291 int lineX = getRowX(-1, depth + 1); 1292 if (leftToRight) { 1293 lineX = lineX - getRightChildIndent() + insets.left; 1294 } 1295 else { 1296 lineX = lastWidth - getRowX(-1, depth) - 9; 1297 } 1298 int clipLeft = clipBounds.x; 1299 int clipRight = clipBounds.x + (clipBounds.width - 1); 1300 1301 if (lineX >= clipLeft && lineX <= clipRight) { 1302 int clipTop = clipBounds.y; 1303 int clipBottom = clipBounds.y + clipBounds.height; 1304 Rectangle parentBounds = getPathBounds(tree, path); 1305 Rectangle lastChildBounds = getPathBounds(tree, 1306 getLastChildPath(path)); 1307 1308 if(lastChildBounds == null) 1309 return; 1314 1315 int top; 1316 1317 if(parentBounds == null) { 1318 top = Math.max(insets.top + getVerticalLegBuffer(), 1319 clipTop); 1320 } 1321 else 1322 top = Math.max(parentBounds.y + parentBounds.height + 1323 getVerticalLegBuffer(), clipTop); 1324 if(depth == 0 && !isRootVisible()) { 1325 TreeModel model = getModel(); 1326 1327 if(model != null) { 1328 Object root = model.getRoot(); 1329 1330 if(model.getChildCount(root) > 0) { 1331 parentBounds = getPathBounds(tree, path. 1332 pathByAddingChild(model.getChild(root, 0))); 1333 if(parentBounds != null) 1334 top = Math.max(insets.top + getVerticalLegBuffer(), 1335 parentBounds.y + 1336 parentBounds.height / 2); 1337 } 1338 } 1339 } 1340 1341 int bottom = Math.min(lastChildBounds.y + 1342 (lastChildBounds.height / 2), clipBottom); 1343 1344 if (top <= bottom) { 1345 g.setColor(getHashColor()); 1346 paintVerticalLine(g, tree, lineX, top, bottom); 1347 } 1348 } 1349 } 1350 1351 1355 protected void paintExpandControl(Graphics g, 1356 Rectangle clipBounds, Insets insets, 1357 Rectangle bounds, TreePath path, 1358 int row, boolean isExpanded, 1359 boolean hasBeenExpanded, 1360 boolean isLeaf) { 1361 Object value = path.getLastPathComponent(); 1362 1363 if (!isLeaf && (!hasBeenExpanded || 1366 treeModel.getChildCount(value) > 0)) { 1367 int middleXOfKnob; 1368 if (leftToRight) { 1369 middleXOfKnob = bounds.x - (getRightChildIndent() - 1); 1370 } 1371 else { 1372 middleXOfKnob = bounds.x + bounds.width + getRightChildIndent(); 1373 } 1374 int middleYOfKnob = bounds.y + (bounds.height / 2); 1375 1376 if (isExpanded) { 1377 Icon expandedIcon = getExpandedIcon(); 1378 if(expandedIcon != null) 1379 drawCentered(tree, g, expandedIcon, middleXOfKnob, 1380 middleYOfKnob ); 1381 } 1382 else { 1383 Icon collapsedIcon = getCollapsedIcon(); 1384 if(collapsedIcon != null) 1385 drawCentered(tree, g, collapsedIcon, middleXOfKnob, 1386 middleYOfKnob); 1387 } 1388 } 1389 } 1390 1391 1395 protected void paintRow(Graphics g, Rectangle clipBounds, 1396 Insets insets, Rectangle bounds, TreePath path, 1397 int row, boolean isExpanded, 1398 boolean hasBeenExpanded, boolean isLeaf) { 1399 if(editingComponent != null && editingRow == row) 1401 return; 1402 1403 int leadIndex; 1404 1405 if(tree.hasFocus()) { 1406 leadIndex = getLeadSelectionRow(); 1407 } 1408 else 1409 leadIndex = -1; 1410 1411 Component component; 1412 1413 component = currentCellRenderer.getTreeCellRendererComponent 1414 (tree, path.getLastPathComponent(), 1415 tree.isRowSelected(row), isExpanded, isLeaf, row, 1416 (leadIndex == row)); 1417 1418 rendererPane.paintComponent(g, component, tree, bounds.x, bounds.y, 1419 bounds.width, bounds.height, true); 1420 } 1421 1422 1426 protected boolean shouldPaintExpandControl(TreePath path, int row, 1427 boolean isExpanded, 1428 boolean hasBeenExpanded, 1429 boolean isLeaf) { 1430 if(isLeaf) 1431 return false; 1432 1433 int depth = path.getPathCount() - 1; 1434 1435 if((depth == 0 || (depth == 1 && !isRootVisible())) && 1436 !getShowsRootHandles()) 1437 return false; 1438 return true; 1439 } 1440 1441 1444 protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, 1445 int bottom) { 1446 if (lineTypeDashed) { 1447 drawDashedVerticalLine(g, x, top, bottom); 1448 } else { 1449 g.drawLine(x, top, x, bottom); 1450 } 1451 } 1452 1453 1456 protected void paintHorizontalLine(Graphics g, JComponent c, int y, 1457 int left, int right) { 1458 if (lineTypeDashed) { 1459 drawDashedHorizontalLine(g, y, left, right); 1460 } else { 1461 g.drawLine(left, y, right, y); 1462 } 1463 } 1464 1465 1469 protected int getVerticalLegBuffer() { 1470 return 0; 1471 } 1472 1473 1478 protected int getHorizontalLegBuffer() { 1479 return 0; 1480 } 1481 1482 1486 protected void drawCentered(Component c, Graphics graphics, Icon icon, 1488 int x, int y) { 1489 icon.paintIcon(c, graphics, x - icon.getIconWidth()/2, y - 1490 icon.getIconHeight()/2); 1491 } 1492 1493 protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2){ 1496 x1 += (x1 % 2); 1500 1501 for (int x = x1; x <= x2; x+=2) { 1502 g.drawLine(x, y, x, y); 1503 } 1504 } 1505 1506 protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2) { 1509 y1 += (y1 % 2); 1513 1514 for (int y = y1; y <= y2; y+=2) { 1515 g.drawLine(x, y, x, y); 1516 } 1517 } 1518 1519 1523 1535 protected int getRowX(int row, int depth) { 1536 return totalChildIndent * (depth + depthOffset); 1537 } 1538 1539 1543 protected void updateLayoutCacheExpandedNodes() { 1544 if(treeModel != null && treeModel.getRoot() != null) 1545 updateExpandedDescendants(new TreePath(treeModel.getRoot())); 1546 } 1547 1548 1553 protected void updateExpandedDescendants(TreePath path) { 1554 completeEditing(); 1555 if(treeState != null) { 1556 treeState.setExpandedState(path, true); 1557 1558 Enumeration descendants = tree.getExpandedDescendants(path); 1559 1560 if(descendants != null) { 1561 while(descendants.hasMoreElements()) { 1562 path = (TreePath)descendants.nextElement(); 1563 treeState.setExpandedState(path, true); 1564 } 1565 } 1566 updateLeadRow(); 1567 updateSize(); 1568 } 1569 } 1570 1571 1574 protected TreePath getLastChildPath(TreePath parent) { 1575 if(treeModel != null) { 1576 int childCount = treeModel.getChildCount 1577 (parent.getLastPathComponent()); 1578 1579 if(childCount > 0) 1580 return parent.pathByAddingChild(treeModel.getChild 1581 (parent.getLastPathComponent(), childCount - 1)); 1582 } 1583 return null; 1584 } 1585 1586 1589 protected void updateDepthOffset() { 1590 if(isRootVisible()) { 1591 if(getShowsRootHandles()) 1592 depthOffset = 1; 1593 else 1594 depthOffset = 0; 1595 } 1596 else if(!getShowsRootHandles()) 1597 depthOffset = -1; 1598 else 1599 depthOffset = 0; 1600 } 1601 1602 1607 protected void updateCellEditor() { 1608 TreeCellEditor newEditor; 1609 1610 completeEditing(); 1611 if(tree == null) 1612 newEditor = null; 1613 else { 1614 if(tree.isEditable()) { 1615 newEditor = tree.getCellEditor(); 1616 if(newEditor == null) { 1617 newEditor = createDefaultCellEditor(); 1618 if(newEditor != null) { 1619 tree.setCellEditor(newEditor); 1620 createdCellEditor = true; 1621 } 1622 } 1623 } 1624 else 1625 newEditor = null; 1626 } 1627 if(newEditor != cellEditor) { 1628 if(cellEditor != null && cellEditorListener != null) 1629 cellEditor.removeCellEditorListener(cellEditorListener); 1630 cellEditor = newEditor; 1631 if(cellEditorListener == null) 1632 cellEditorListener = createCellEditorListener(); 1633 if(newEditor != null && cellEditorListener != null) 1634 newEditor.addCellEditorListener(cellEditorListener); 1635 createdCellEditor = false; 1636 } 1637 } 1638 1639 1642 protected void updateRenderer() { 1643 if(tree != null) { 1644 TreeCellRenderer newCellRenderer; 1645 1646 newCellRenderer = tree.getCellRenderer(); 1647 if(newCellRenderer == null) { 1648 tree.setCellRenderer(createDefaultCellRenderer()); 1649 createdRenderer = true; 1650 } 1651 else { 1652 createdRenderer = false; 1653 currentCellRenderer = newCellRenderer; 1654 if(createdCellEditor) { 1655 tree.setCellEditor(null); 1656 } 1657 } 1658 } 1659 else { 1660 createdRenderer = false; 1661 currentCellRenderer = null; 1662 } 1663 updateCellEditor(); 1664 } 1665 1666 1670 protected void configureLayoutCache() { 1671 if(treeState != null && tree != null) { 1672 if(nodeDimensions == null) 1673 nodeDimensions = createNodeDimensions(); 1674 treeState.setNodeDimensions(nodeDimensions); 1675 treeState.setRootVisible(tree.isRootVisible()); 1676 treeState.setRowHeight(tree.getRowHeight()); 1677 treeState.setSelectionModel(getSelectionModel()); 1678 if(treeState.getModel() != tree.getModel()) 1681 treeState.setModel(tree.getModel()); 1682 updateLayoutCacheExpandedNodes(); 1683 if(isLargeModel()) { 1686 if(componentListener == null) { 1687 componentListener = createComponentListener(); 1688 if(componentListener != null) 1689 tree.addComponentListener(componentListener); 1690 } 1691 } 1692 else if(componentListener != null) { 1693 tree.removeComponentListener(componentListener); 1694 componentListener = null; 1695 } 1696 } 1697 else if(componentListener != null) { 1698 tree.removeComponentListener(componentListener); 1699 componentListener = null; 1700 } 1701 } 1702 1703 1707 protected void updateSize() { 1708 validCachedPreferredSize = false; 1709 tree.treeDidChange(); 1710 } 1711 1712 1719 protected void updateCachedPreferredSize() { 1720 if(treeState != null) { 1721 Insets i = tree.getInsets(); 1722 1723 if(isLargeModel()) { 1724 Rectangle visRect = tree.getVisibleRect(); 1725 1726 if(i != null) { 1727 visRect.x -= i.left; 1728 visRect.y -= i.top; 1729 } 1730 if (leftToRight) { 1731 preferredSize.width = treeState.getPreferredWidth(visRect); 1732 } 1733 else { 1734 if (getRowCount(tree) == 0) { 1735 preferredSize.width = 0; 1736 } 1737 else { 1738 preferredSize.width = lastWidth - getMinX(visRect); 1739 } 1740 } 1741 } 1742 else if (leftToRight) { 1743 preferredSize.width = treeState.getPreferredWidth(null); 1744 } 1745 else { 1746 Rectangle tempRect = null; 1747 int rowCount = tree.getRowCount(); 1748 int width = 0; 1749 for (int counter = 0; counter < rowCount; counter++) { 1750 tempRect = treeState.getBounds 1751 (treeState.getPathForRow(counter), tempRect); 1752 if (tempRect != null) { 1753 width = Math.max(lastWidth - tempRect.x, width); 1754 } 1755 } 1756 preferredSize.width = width; 1757 } 1758 preferredSize.height = treeState.getPreferredHeight(); 1759 if(i != null) { 1760 preferredSize.width += i.left + i.right; 1761 preferredSize.height += i.top + i.bottom; 1762 } 1763 } 1764 validCachedPreferredSize = true; 1765 } 1766 1767 1770 private int getMinX(Rectangle bounds) { 1771 TreePath firstPath; 1772 int endY; 1773 1774 if(bounds == null) { 1775 firstPath = getPathForRow(tree, 0); 1776 endY = Integer.MAX_VALUE; 1777 } 1778 else { 1779 firstPath = treeState.getPathClosestTo(bounds.x, bounds.y); 1780 endY = bounds.height + bounds.y; 1781 } 1782 1783 Enumeration paths = treeState.getVisiblePathsFrom(firstPath); 1784 int minX = 0; 1785 1786 if(paths != null && paths.hasMoreElements()) { 1787 Rectangle pBounds = treeState.getBounds 1788 ((TreePath)paths.nextElement(), null); 1789 int width; 1790 1791 if(pBounds != null) { 1792 minX = pBounds.x + pBounds.width; 1793 if (pBounds.y >= endY) { 1794 return minX; 1795 } 1796 } 1797 while (pBounds != null && paths.hasMoreElements()) { 1798 pBounds = treeState.getBounds((TreePath)paths.nextElement(), 1799 pBounds); 1800 if (pBounds != null && pBounds.y < endY) { 1801 minX = Math.min(minX, pBounds.x); 1802 } 1803 else { 1804 pBounds = null; 1805 } 1806 } 1807 return minX; 1808 } 1809 return minX; 1810 } 1811 1812 1815 protected void pathWasExpanded(TreePath path) { 1816 if(tree != null) { 1817 tree.fireTreeExpanded(path); 1818 } 1819 } 1820 1821 1824 protected void pathWasCollapsed(TreePath path) { 1825 if(tree != null) { 1826 tree.fireTreeCollapsed(path); 1827 } 1828 } 1829 1830 1834 protected void ensureRowsAreVisible(int beginRow, int endRow) { 1835 if(tree != null && beginRow >= 0 && endRow < getRowCount(tree)) { 1836 boolean scrollVert = DefaultLookup.getBoolean(tree, this, 1837 "Tree.scrollsHorizontallyAndVertically", false); 1838 if(beginRow == endRow) { 1839 Rectangle scrollBounds = getPathBounds(tree, getPathForRow 1840 (tree, beginRow)); 1841 1842 if(scrollBounds != null) { 1843 if (!scrollVert) { 1844 scrollBounds.x = tree.getVisibleRect().x; 1845 scrollBounds.width = 1; 1846 } 1847 tree.scrollRectToVisible(scrollBounds); 1848 } 1849 } 1850 else { 1851 Rectangle beginRect = getPathBounds(tree, getPathForRow 1852 (tree, beginRow)); 1853 Rectangle visRect = tree.getVisibleRect(); 1854 Rectangle testRect = beginRect; 1855 int beginY = beginRect.y; 1856 int maxY = beginY + visRect.height; 1857 1858 for(int counter = beginRow + 1; counter <= endRow; counter++) { 1859 testRect = getPathBounds(tree, 1860 getPathForRow(tree, counter)); 1861 if((testRect.y + testRect.height) > maxY) 1862 counter = endRow; 1863 } 1864 tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, 1865 testRect.y + testRect.height- 1866 beginY)); 1867 } 1868 } 1869 } 1870 1871 1873 public void setPreferredMinSize(Dimension newSize) { 1874 preferredMinSize = newSize; 1875 } 1876 1877 1879 public Dimension getPreferredMinSize() { 1880 if(preferredMinSize == null) 1881 return null; 1882 return new Dimension(preferredMinSize); 1883 } 1884 1885 1888 public Dimension getPreferredSize(JComponent c) { 1889 return getPreferredSize(c, true); 1890 } 1891 1892 1896 public Dimension getPreferredSize(JComponent c, 1897 boolean checkConsistancy) { 1898 Dimension pSize = this.getPreferredMinSize(); 1899 1900 if(!validCachedPreferredSize) 1901 updateCachedPreferredSize(); 1902 if(tree != null) { 1903 if(pSize != null) 1904 return new Dimension(Math.max(pSize.width, 1905 preferredSize.width), 1906 Math.max(pSize.height, preferredSize.height)); 1907 return new Dimension(preferredSize.width, preferredSize.height); 1908 } 1909 else if(pSize != null) 1910 return pSize; 1911 else 1912 return new Dimension(0, 0); 1913 } 1914 1915 1919 public Dimension getMinimumSize(JComponent c) { 1920 if(this.getPreferredMinSize() != null) 1921 return this.getPreferredMinSize(); 1922 return new Dimension(0, 0); 1923 } 1924 1925 1929 public Dimension getMaximumSize(JComponent c) { 1930 if(tree != null) 1931 return getPreferredSize(tree); 1932 if(this.getPreferredMinSize() != null) 1933 return this.getPreferredMinSize(); 1934 return new Dimension(0, 0); 1935 } 1936 1937 1938 1946 protected void completeEditing() { 1947 1948 if(tree.getInvokesStopCellEditing() && 1949 stopEditingInCompleteEditing && editingComponent != null) { 1950 cellEditor.stopCellEditing(); 1951 } 1952 1954 completeEditing(false, true, false); 1955 } 1956 1957 1963 protected void completeEditing(boolean messageStop, 1964 boolean messageCancel, 1965 boolean messageTree) { 1966 if(stopEditingInCompleteEditing && editingComponent != null) { 1967 Component oldComponent = editingComponent; 1968 TreePath oldPath = editingPath; 1969 TreeCellEditor oldEditor = cellEditor; 1970 Object newValue = oldEditor.getCellEditorValue(); 1971 Rectangle editingBounds = getPathBounds(tree, 1972 editingPath); 1973 boolean requestFocus = (tree != null && 1974 (tree.hasFocus() || SwingUtilities. 1975 findFocusOwner(editingComponent) != null)); 1976 1977 editingComponent = null; 1978 editingPath = null; 1979 if(messageStop) 1980 oldEditor.stopCellEditing(); 1981 else if(messageCancel) 1982 oldEditor.cancelCellEditing(); 1983 tree.remove(oldComponent); 1984 if(editorHasDifferentSize) { 1985 treeState.invalidatePathBounds(oldPath); 1986 updateSize(); 1987 } 1988 else { 1989 editingBounds.x = 0; 1990 editingBounds.width = tree.getSize().width; 1991 tree.repaint(editingBounds); 1992 } 1993 if(requestFocus) 1994 tree.requestFocus(); 1995 if(messageTree) 1996 treeModel.valueForPathChanged(oldPath, newValue); 1997 } 1998 } 1999 2000 private boolean startEditingOnRelease(TreePath path, 2003 MouseEvent event, 2004 MouseEvent releaseEvent) { 2005 this.releaseEvent = releaseEvent; 2006 try { 2007 return startEditing(path, event); 2008 } finally { 2009 this.releaseEvent = null; 2010 } 2011 } 2012 2013 2018 protected boolean startEditing(TreePath path, MouseEvent event) { 2019 if (isEditing(tree) && tree.getInvokesStopCellEditing() && 2020 !stopEditing(tree)) { 2021 return false; 2022 } 2023 completeEditing(); 2024 if(cellEditor != null && tree.isPathEditable(path)) { 2025 int row = getRowForPath(tree, path); 2026 2027 if(cellEditor.isCellEditable(event)) { 2028 editingComponent = cellEditor.getTreeCellEditorComponent 2029 (tree, path.getLastPathComponent(), 2030 tree.isPathSelected(path), tree.isExpanded(path), 2031 treeModel.isLeaf(path.getLastPathComponent()), row); 2032 2033 Rectangle nodeBounds = getPathBounds(tree, path); 2034 2035 editingRow = row; 2036 2037 Dimension editorSize = editingComponent.getPreferredSize(); 2038 2039 if(editorSize.height != nodeBounds.height && 2041 getRowHeight() > 0) 2042 editorSize.height = getRowHeight(); 2043 2044 if(editorSize.width != nodeBounds.width || 2045 editorSize.height != nodeBounds.height) { 2046 editorHasDifferentSize = true; 2049 treeState.invalidatePathBounds(path); 2050 updateSize(); 2051 } 2052 else 2053 editorHasDifferentSize = false; 2054 tree.add(editingComponent); 2055 editingComponent.setBounds(nodeBounds.x, nodeBounds.y, 2056 editorSize.width, 2057 editorSize.height); 2058 editingPath = path; 2059 editingComponent.validate(); 2060 2061 Rectangle visRect = tree.getVisibleRect(); 2062 2063 tree.paintImmediately(nodeBounds.x, nodeBounds.y, 2064 visRect.width + visRect.x - nodeBounds.x, 2065 editorSize.height); 2066 if(cellEditor.shouldSelectCell(event)) { 2067 stopEditingInCompleteEditing = false; 2068 try { 2069 tree.setSelectionRow(row); 2070 } catch (Exception e) { 2071 System.err.println("Editing exception: " + e); 2072 } 2073 stopEditingInCompleteEditing = true; 2074 } 2075 2076 Component focusedComponent = BasicLookAndFeel. 2077 compositeRequestFocus(editingComponent); 2078 boolean selectAll = true; 2079 2080 if(event != null && event instanceof MouseEvent) { 2081 2083 Point componentPoint = SwingUtilities.convertPoint 2084 (tree, new Point(event.getX(), event.getY()), 2085 editingComponent); 2086 2087 2090 Component activeComponent = SwingUtilities. 2093 getDeepestComponentAt(editingComponent, 2094 componentPoint.x, componentPoint.y); 2095 if (activeComponent != null) { 2096 MouseInputHandler handler = 2097 new MouseInputHandler(tree, activeComponent, 2098 event, focusedComponent); 2099 2100 if (releaseEvent != null) { 2101 handler.mouseReleased(releaseEvent); 2102 } 2103 2104 selectAll = false; 2105 } 2106 } 2107 if (selectAll && focusedComponent instanceof JTextField) { 2108 ((JTextField)focusedComponent).selectAll(); 2109 } 2110 return true; 2111 } 2112 else 2113 editingComponent = null; 2114 } 2115 return false; 2116 } 2117 2118 2122 2127 protected void checkForClickInExpandControl(TreePath path, 2128 int mouseX, int mouseY) { 2129 if (isLocationInExpandControl(path, mouseX, mouseY)) { 2130 handleExpandControlClick(path, mouseX, mouseY); 2131 } 2132 } 2133 2134 2139 protected boolean isLocationInExpandControl(TreePath path, 2140 int mouseX, int mouseY) { 2141 if(path != null && !treeModel.isLeaf(path.getLastPathComponent())){ 2142 int boxWidth; 2143 Insets i = tree.getInsets(); 2144 2145 if(getExpandedIcon() != null) 2146 boxWidth = getExpandedIcon().getIconWidth(); 2147 else 2148 boxWidth = 8; 2149 2150 int boxLeftX = getRowX(tree.getRowForPath(path), 2151 path.getPathCount() - 1) - getRightChildIndent() - 2152 boxWidth / 2; 2153 2154 if (leftToRight) { 2155 boxLeftX += i.left; 2156 } 2157 else { 2158 boxLeftX = i.left + lastWidth - 1 - 2159 ((path.getPathCount() - 2 + depthOffset) * 2160 totalChildIndent) - getLeftChildIndent() - 2161 boxWidth / 2; 2162 } 2163 int boxRightX = boxLeftX + boxWidth; 2164 2165 return mouseX >= boxLeftX && mouseX <= boxRightX; 2166 } 2167 return false; 2168 } 2169 2170 2174 protected void handleExpandControlClick(TreePath path, int mouseX, 2175 int mouseY) { 2176 toggleExpandState(path); 2177 } 2178 2179 2185 protected void toggleExpandState(TreePath path) { 2186 if(!tree.isExpanded(path)) { 2187 int row = getRowForPath(tree, path); 2188 2189 tree.expandPath(path); 2190 updateSize(); 2191 if(row != -1) { 2192 if(tree.getScrollsOnExpand()) 2193 ensureRowsAreVisible(row, row + treeState. 2194 getVisibleChildCount(path)); 2195 else 2196 ensureRowsAreVisible(row, row); 2197 } 2198 } 2199 else { 2200 tree.collapsePath(path); 2201 updateSize(); 2202 } 2203 } 2204 2205 2209 protected boolean isToggleSelectionEvent(MouseEvent event) { 2210 return (SwingUtilities.isLeftMouseButton(event) && 2211 event.isControlDown()); 2212 } 2213 2214 2218 protected boolean isMultiSelectEvent(MouseEvent event) { 2219 return (SwingUtilities.isLeftMouseButton(event) && 2220 event.isShiftDown()); 2221 } 2222 2223 2228 protected boolean isToggleEvent(MouseEvent event) { 2229 if(!SwingUtilities.isLeftMouseButton(event)) { 2230 return false; 2231 } 2232 int clickCount = tree.getToggleClickCount(); 2233 2234 if(clickCount <= 0) { 2235 return false; 2236 } 2237 return ((event.getClickCount() % clickCount) == 0); 2238 } 2239 2240 2248 protected void selectPathForEvent(TreePath path, MouseEvent event) { 2249 2250 if(isMultiSelectEvent(event)) { 2251 TreePath anchor = getAnchorSelectionPath(); 2252 int anchorRow = (anchor == null) ? -1 : 2253 getRowForPath(tree, anchor); 2254 2255 if(anchorRow == -1 || tree.getSelectionModel(). 2256 getSelectionMode() == TreeSelectionModel. 2257 SINGLE_TREE_SELECTION) { 2258 tree.setSelectionPath(path); 2259 } 2260 else { 2261 int row = getRowForPath(tree, path); 2262 TreePath lastAnchorPath = anchor; 2263 2264 if (isToggleSelectionEvent(event)) { 2265 if (tree.isRowSelected(anchorRow)) { 2266 tree.addSelectionInterval(anchorRow, row); 2267 } else { 2268 tree.removeSelectionInterval(anchorRow, row); 2269 tree.addSelectionInterval(row, row); 2270 } 2271 } else if(row < anchorRow) { 2272 tree.setSelectionInterval(row, anchorRow); 2273 } else { 2274 tree.setSelectionInterval(anchorRow, row); 2275 } 2276 lastSelectedRow = row; 2277 setAnchorSelectionPath(lastAnchorPath); 2278 setLeadSelectionPath(path); 2279 } 2280 } 2281 2282 2284 else if(isToggleSelectionEvent(event)) { 2285 if(tree.isPathSelected(path)) 2286 tree.removeSelectionPath(path); 2287 else 2288 tree.addSelectionPath(path); 2289 lastSelectedRow = getRowForPath(tree, path); 2290 setAnchorSelectionPath(path); 2291 setLeadSelectionPath(path); 2292 } 2293 2294 2295 else if(SwingUtilities.isLeftMouseButton(event)) { 2296 tree.setSelectionPath(path); 2297 if(isToggleEvent(event)) { 2298 toggleExpandState(path); 2299 } 2300 } 2301 } 2302 2303 2306 protected boolean isLeaf(int row) { 2307 TreePath path = getPathForRow(tree, row); 2308 2309 if(path != null) 2310 return treeModel.isLeaf(path.getLastPathComponent()); 2311 return true; 2313 } 2314 2315 private void setAnchorSelectionPath(TreePath newPath) { 2320 ignoreLAChange = true; 2321 try { 2322 tree.setAnchorSelectionPath(newPath); 2323 } finally{ 2324 ignoreLAChange = false; 2325 } 2326 } 2327 2328 private TreePath getAnchorSelectionPath() { 2329 return tree.getAnchorSelectionPath(); 2330 } 2331 2332 private void setLeadSelectionPath(TreePath newPath) { 2333 setLeadSelectionPath(newPath, false); 2334 } 2335 2336 private void setLeadSelectionPath(TreePath newPath, boolean repaint) { 2337 Rectangle bounds = repaint ? 2338 getPathBounds(tree, getLeadSelectionPath()) : null; 2339 2340 ignoreLAChange = true; 2341 try { 2342 tree.setLeadSelectionPath(newPath); 2343 } finally { 2344 ignoreLAChange = false; 2345 } 2346 leadRow = getRowForPath(tree, newPath); 2347 2348 if(repaint) { 2349 if(bounds != null) 2350 tree.repaint(bounds); 2351 bounds = getPathBounds(tree, newPath); 2352 if(bounds != null) 2353 tree.repaint(bounds); 2354 } 2355 } 2356 2357 private TreePath getLeadSelectionPath() { 2358 return tree.getLeadSelectionPath(); 2359 } 2360 2361 private void updateLeadRow() { 2362 leadRow = getRowForPath(tree, getLeadSelectionPath()); 2363 } 2364 2365 private int getLeadSelectionRow() { 2366 return leadRow; 2367 } 2368 2369 2373 private void extendSelection(TreePath newLead) { 2374 TreePath aPath = getAnchorSelectionPath(); 2375 int aRow = (aPath == null) ? -1 : 2376 getRowForPath(tree, aPath); 2377 int newIndex = getRowForPath(tree, newLead); 2378 2379 if(aRow == -1) { 2380 tree.setSelectionRow(newIndex); 2381 } 2382 else { 2383 if(aRow < newIndex) { 2384 tree.setSelectionInterval(aRow, newIndex); 2385 } 2386 else { 2387 tree.setSelectionInterval(newIndex, aRow); 2388 } 2389 setAnchorSelectionPath(aPath); 2390 setLeadSelectionPath(newLead); 2391 } 2392 } 2393 2394 2398 private void repaintPath(TreePath path) { 2399 if (path != null) { 2400 Rectangle bounds = getPathBounds(tree, path); 2401 if (bounds != null) { 2402 tree.repaint(bounds.x, bounds.y, bounds.width, bounds.height); 2403 } 2404 } 2405 } 2406 2407 2410 public class TreeExpansionHandler implements TreeExpansionListener { 2411 2416 2419 public void treeExpanded(TreeExpansionEvent event) { 2420 getHandler().treeExpanded(event); 2421 } 2422 2423 2426 public void treeCollapsed(TreeExpansionEvent event) { 2427 getHandler().treeCollapsed(event); 2428 } 2429 } 2431 2432 2435 public class ComponentHandler extends ComponentAdapter implements 2436 ActionListener { 2437 2439 protected Timer timer; 2440 2441 protected JScrollBar scrollBar; 2442 2443 public void componentMoved(ComponentEvent e) { 2444 if(timer == null) { 2445 JScrollPane scrollPane = getScrollPane(); 2446 2447 if(scrollPane == null) 2448 updateSize(); 2449 else { 2450 scrollBar = scrollPane.getVerticalScrollBar(); 2451 if(scrollBar == null || 2452 !scrollBar.getValueIsAdjusting()) { 2453 if((scrollBar = scrollPane.getHorizontalScrollBar()) 2455 != null && scrollBar.getValueIsAdjusting()) 2456 startTimer(); 2457 else 2458 updateSize(); 2459 } 2460 else 2461 startTimer(); 2462 } 2463 } 2464 } 2465 2466 2470 protected void startTimer() { 2471 if(timer == null) { 2472 timer = new Timer(200, this); 2473 timer.setRepeats(true); 2474 } 2475 timer.start(); 2476 } 2477 2478 2482 protected JScrollPane getScrollPane() { 2483 Component c = tree.getParent(); 2484 2485 while(c != null && !(c instanceof JScrollPane)) 2486 c = c.getParent(); 2487 if(c instanceof JScrollPane) 2488 return (JScrollPane)c; 2489 return null; 2490 } 2491 2492 2496 public void actionPerformed(ActionEvent ae) { 2497 if(scrollBar == null || !scrollBar.getValueIsAdjusting()) { 2498 if(timer != null) 2499 timer.stop(); 2500 updateSize(); 2501 timer = null; 2502 scrollBar = null; 2503 } 2504 } 2505 } 2507 2508 2511 public class TreeModelHandler implements TreeModelListener { 2512 2513 2518 public void treeNodesChanged(TreeModelEvent e) { 2519 getHandler().treeNodesChanged(e); 2520 } 2521 2522 public void treeNodesInserted(TreeModelEvent e) { 2523 getHandler().treeNodesInserted(e); 2524 } 2525 2526 public void treeNodesRemoved(TreeModelEvent e) { 2527 getHandler().treeNodesInserted(e); 2528 } 2529 2530 public void treeStructureChanged(TreeModelEvent e) { 2531 getHandler().treeStructureChanged(e); 2532 } 2533 } 2535 2536 2540 public class TreeSelectionHandler implements TreeSelectionListener { 2541 2542 2547 2551 public void valueChanged(TreeSelectionEvent event) { 2552 getHandler().valueChanged(event); 2553 } 2554 } 2556 2557 2561 public class CellEditorHandler implements CellEditorListener { 2562 2563 2568 2569 public void editingStopped(ChangeEvent e) { 2570 getHandler().editingStopped(e); 2571 } 2572 2573 2574 public void editingCanceled(ChangeEvent e) { 2575 getHandler().editingCanceled(e); 2576 } 2577 } 2579 2580 2584 public class KeyHandler extends KeyAdapter { 2585 2586 2591 2595 2596 protected Action repeatKeyAction; 2597 2598 2599 protected boolean isKeyDown; 2600 2601 2610 public void keyTyped(KeyEvent e) { 2611 getHandler().keyTyped(e); 2612 } 2613 2614 public void keyPressed(KeyEvent e) { 2615 getHandler().keyPressed(e); 2616 } 2617 2618 public void keyReleased(KeyEvent e) { 2619 getHandler().keyReleased(e); 2620 } 2621 } 2623 2624 2627 public class FocusHandler implements FocusListener { 2628 2633 2637 public void focusGained(FocusEvent e) { 2638 getHandler().focusGained(e); 2639 } 2640 2641 2645 public void focusLost(FocusEvent e) { 2646 focusGained(e); 2647 } 2648 } 2650 2651 2656 public class NodeDimensionsHandler extends 2658 AbstractLayoutCache.NodeDimensions { 2659 2662 public Rectangle getNodeDimensions(Object value, int row, 2663 int depth, boolean expanded, 2664 Rectangle size) { 2665 if(editingComponent != null && editingRow == row) { 2668 Dimension prefSize = editingComponent. 2669 getPreferredSize(); 2670 int rh = getRowHeight(); 2671 2672 if(rh > 0 && rh != prefSize.height) 2673 prefSize.height = rh; 2674 if(size != null) { 2675 size.x = getRowX(row, depth); 2676 size.width = prefSize.width; 2677 size.height = prefSize.height; 2678 } 2679 else { 2680 size = new Rectangle(getRowX(row, depth), 0, 2681 prefSize.width, prefSize.height); 2682 } 2683 2684 if(!leftToRight) { 2685 size.x = lastWidth - size.width - size.x - 2; 2686 } 2687 return size; 2688 } 2689 if(currentCellRenderer != null) { 2691 Component aComponent; 2692 2693 aComponent = currentCellRenderer.getTreeCellRendererComponent 2694 (tree, value, tree.isRowSelected(row), 2695 expanded, treeModel.isLeaf(value), row, 2696 false); 2697 if(tree != null) { 2698 rendererPane.add(aComponent); 2700 aComponent.validate(); 2701 } 2702 Dimension prefSize = aComponent.getPreferredSize(); 2703 2704 if(size != null) { 2705 size.x = getRowX(row, depth); 2706 size.width = prefSize.width; 2707 size.height = prefSize.height; 2708 } 2709 else { 2710 size = new Rectangle(getRowX(row, depth), 0, 2711 prefSize.width, prefSize.height); 2712 } 2713 2714 if(!leftToRight) { 2715 size.x = lastWidth - size.width - size.x - 2; 2716 } 2717 return size; 2718 } 2719 return null; 2720 } 2721 2722 2725 protected int getRowX(int row, int depth) { 2726 return BasicTreeUI.this.getRowX(row, depth); 2727 } 2728 2729 } 2731 2732 2736 public class MouseHandler extends MouseAdapter implements MouseMotionListener 2737 { 2738 2743 2746 public void mousePressed(MouseEvent e) { 2747 getHandler().mousePressed(e); 2748 } 2749 2750 public void mouseDragged(MouseEvent e) { 2751 getHandler().mouseDragged(e); 2752 } 2753 2754 2758 public void mouseMoved(MouseEvent e) { 2759 getHandler().mouseMoved(e); 2760 } 2761 2762 public void mouseReleased(MouseEvent e) { 2763 getHandler().mouseReleased(e); 2764 } 2765 } 2767 2768 2772 public class PropertyChangeHandler implements 2773 PropertyChangeListener { 2774 2775 2780 public void propertyChange(PropertyChangeEvent event) { 2781 getHandler().propertyChange(event); 2782 } 2783 } 2785 2786 2790 public class SelectionModelPropertyChangeHandler implements 2791 PropertyChangeListener { 2792 2793 2798 public void propertyChange(PropertyChangeEvent event) { 2799 getHandler().propertyChange(event); 2800 } 2801 } 2803 2804 2809 public class TreeTraverseAction extends AbstractAction { 2810 2812 protected int direction; 2813 2815 private boolean changeSelection; 2816 2817 public TreeTraverseAction(int direction, String name) { 2818 this(direction, name, true); 2819 } 2820 2821 private TreeTraverseAction(int direction, String name, 2822 boolean changeSelection) { 2823 this.direction = direction; 2824 this.changeSelection = changeSelection; 2825 } 2826 2827 public void actionPerformed(ActionEvent e) { 2828 if (tree != null) { 2829 SHARED_ACTION.traverse(tree, BasicTreeUI.this, direction, 2830 changeSelection); 2831 } 2832 } 2833 2834 public boolean isEnabled() { return (tree != null && 2835 tree.isEnabled()); } 2836 } 2838 2839 2841 public class TreePageAction extends AbstractAction { 2842 2843 protected int direction; 2844 2845 private boolean addToSelection; 2846 private boolean changeSelection; 2847 2848 public TreePageAction(int direction, String name) { 2849 this(direction, name, false, true); 2850 } 2851 2852 private TreePageAction(int direction, String name, 2853 boolean addToSelection, 2854 boolean changeSelection) { 2855 this.direction = direction; 2856 this.addToSelection = addToSelection; 2857 this.changeSelection = changeSelection; 2858 } 2859 2860 public void actionPerformed(ActionEvent e) { 2861 if (tree != null) { 2862 SHARED_ACTION.page(tree, BasicTreeUI.this, direction, 2863 addToSelection, changeSelection); 2864 } 2865 } 2866 2867 public boolean isEnabled() { return (tree != null && 2868 tree.isEnabled()); } 2869 2870 } 2872 2873 2876 public class TreeIncrementAction extends AbstractAction { 2877 2878 protected int direction; 2879 2881 private boolean addToSelection; 2882 private boolean changeSelection; 2883 2884 public TreeIncrementAction(int direction, String name) { 2885 this(direction, name, false, true); 2886 } 2887 2888 private TreeIncrementAction(int direction, String name, 2889 boolean addToSelection, 2890 boolean changeSelection) { 2891 this.direction = direction; 2892 this.addToSelection = addToSelection; 2893 this.changeSelection = changeSelection; 2894 } 2895 2896 public void actionPerformed(ActionEvent e) { 2897 if (tree != null) { 2898 SHARED_ACTION.increment(tree, BasicTreeUI.this, direction, 2899 addToSelection, changeSelection); 2900 } 2901 } 2902 2903 public boolean isEnabled() { return (tree != null && 2904 tree.isEnabled()); } 2905 2906 } 2908 2913 public class TreeHomeAction extends AbstractAction { 2914 protected int direction; 2915 2916 private boolean addToSelection; 2917 private boolean changeSelection; 2918 2919 public TreeHomeAction(int direction, String name) { 2920 this(direction, name, false, true); 2921 } 2922 2923 private TreeHomeAction(int direction, String name, 2924 boolean addToSelection, 2925 boolean changeSelection) { 2926 this.direction = direction; 2927 this.changeSelection = changeSelection; 2928 this.addToSelection = addToSelection; 2929 } 2930 2931 public void actionPerformed(ActionEvent e) { 2932 if (tree != null) { 2933 SHARED_ACTION.home(tree, BasicTreeUI.this, direction, 2934 addToSelection, changeSelection); 2935 } 2936 } 2937 2938 public boolean isEnabled() { return (tree != null && 2939 tree.isEnabled()); } 2940 2941 } 2943 2944 2947 public class TreeToggleAction extends AbstractAction { 2948 public TreeToggleAction(String name) { 2949 } 2950 2951 public void actionPerformed(ActionEvent e) { 2952 if(tree != null) { 2953 SHARED_ACTION.toggle(tree, BasicTreeUI.this); 2954 } 2955 } 2956 2957 public boolean isEnabled() { return (tree != null && 2958 tree.isEnabled()); } 2959 2960 } 2962 2963 2966 public class TreeCancelEditingAction extends AbstractAction { 2967 public TreeCancelEditingAction(String name) { 2968 } 2969 2970 public void actionPerformed(ActionEvent e) { 2971 if(tree != null) { 2972 SHARED_ACTION.cancelEditing(tree, BasicTreeUI.this); 2973 } 2974 } 2975 2976 public boolean isEnabled() { return (tree != null && 2977 tree.isEnabled() && 2978 isEditing(tree)); } 2979 } 2981 2982 2988 public class MouseInputHandler extends Object implements 2991 MouseInputListener 2992 { 2993 2994 protected Component source; 2995 2996 protected Component destination; 2997 private Component focusComponent; 2998 private boolean dispatchedEvent; 2999 3000 public MouseInputHandler(Component source, Component destination, 3001 MouseEvent event){ 3002 this(source, destination, event, null); 3003 } 3004 3005 MouseInputHandler(Component source, Component destination, 3006 MouseEvent event, Component focusComponent) { 3007 this.source = source; 3008 this.destination = destination; 3009 this.source.addMouseListener(this); 3010 this.source.addMouseMotionListener(this); 3011 3012 SwingUtilities2.setSkipClickCount(destination, 3013 event.getClickCount() - 1); 3014 3015 3016 destination.dispatchEvent(SwingUtilities.convertMouseEvent 3017 (source, event, destination)); 3018 this.focusComponent = focusComponent; 3019 } 3020 3021 public void mouseClicked(MouseEvent e) { 3022 if(destination != null) { 3023 dispatchedEvent = true; 3024 destination.dispatchEvent(SwingUtilities.convertMouseEvent 3025 (source, e, destination)); 3026 } 3027 } 3028 3029 public void mousePressed(MouseEvent e) { 3030 } 3031 3032 public void mouseReleased(MouseEvent e) { 3033 if(destination != null) 3034 destination.dispatchEvent(SwingUtilities.convertMouseEvent 3035 (source, e, destination)); 3036 removeFromSource(); 3037 } 3038 3039 public void mouseEntered(MouseEvent e) { 3040 if (!SwingUtilities.isLeftMouseButton(e)) { 3041 removeFromSource(); 3042 } 3043 } 3044 3045 public void mouseExited(MouseEvent e) { 3046 if (!SwingUtilities.isLeftMouseButton(e)) { 3047 removeFromSource(); 3048 } 3049 } 3050 3051 public void mouseDragged(MouseEvent e) { 3052 if(destination != null) { 3053 dispatchedEvent = true; 3054 destination.dispatchEvent(SwingUtilities.convertMouseEvent 3055 (source, e, destination)); 3056 } 3057 } 3058 3059 public void mouseMoved(MouseEvent e) { 3060 removeFromSource(); 3061 } 3062 3063 protected void removeFromSource() { 3064 if(source != null) { 3065 source.removeMouseListener(this); 3066 source.removeMouseMotionListener(this); 3067 if (focusComponent != null && 3068 focusComponent == destination && !dispatchedEvent && 3069 (focusComponent instanceof JTextField)) { 3070 ((JTextField)focusComponent).selectAll(); 3071 } 3072 } 3073 source = destination = null; 3074 } 3075 3076 } 3078 private static final TreeDragGestureRecognizer defaultDragRecognizer = 3079 DRAG_FIX ? null : new TreeDragGestureRecognizer(); 3080 3081 3084 static class TreeDragGestureRecognizer extends BasicDragGestureRecognizer { 3085 3086 3097 protected boolean isDragPossible(MouseEvent e) { 3098 if (super.isDragPossible(e)) { 3099 JTree tree = (JTree) this.getComponent(e); 3100 if (tree.getDragEnabled()) { 3101 TreeUI ui = tree.getUI(); 3102 TreePath path = ui.getClosestPathForLocation(tree, e.getX(), 3103 e.getY()); 3104 if ((path != null) && tree.isPathSelected(path)) { 3105 return true; 3106 } 3107 } 3108 } 3109 return false; 3110 } 3111 } 3112 3113 private static DropTargetListener defaultDropTargetListener = null; 3114 3115 3120 static class TreeDropTargetListener extends BasicDropTargetListener { 3121 3122 3126 protected void saveComponentState(JComponent comp) { 3127 JTree tree = (JTree) comp; 3128 selectedIndices = tree.getSelectionRows(); 3129 } 3130 3131 3135 protected void restoreComponentState(JComponent comp) { 3136 JTree tree = (JTree) comp; 3137 tree.setSelectionRows(selectedIndices); 3138 } 3139 3140 3144 protected void updateInsertionLocation(JComponent comp, Point p) { 3145 JTree tree = (JTree) comp; 3146 BasicTreeUI ui = (BasicTreeUI ) tree.getUI(); 3147 TreePath path = ui.getClosestPathForLocation(tree, p.x, p.y); 3148 if (path != null) { 3149 tree.setSelectionPath(path); 3150 } 3151 } 3152 3153 private int[] selectedIndices; 3154 } 3155 3156 private static final TransferHandler defaultTransferHandler = new TreeTransferHandler(); 3157 3158 static class TreeTransferHandler extends TransferHandler implements UIResource , Comparator { 3159 3160 private JTree tree; 3161 3162 3171 protected Transferable createTransferable(JComponent c) { 3172 if (c instanceof JTree) { 3173 tree = (JTree) c; 3174 TreePath[] paths = tree.getSelectionPaths(); 3175 3176 if (paths == null || paths.length == 0) { 3177 return null; 3178 } 3179 3180 StringBuffer plainBuf = new StringBuffer (); 3181 StringBuffer htmlBuf = new StringBuffer (); 3182 3183 htmlBuf.append("<html>\n<body>\n<ul>\n"); 3184 3185 TreeModel model = tree.getModel(); 3186 TreePath lastPath = null; 3187 TreePath[] displayPaths = getDisplayOrderPaths(paths); 3188 3189 for (int i = 0; i < displayPaths.length; i++) { 3190 TreePath path = displayPaths[i]; 3191 3192 Object node = path.getLastPathComponent(); 3193 boolean leaf = model.isLeaf(node); 3194 String label = getDisplayString(path, true, leaf); 3195 3196 plainBuf.append(label + "\n"); 3197 htmlBuf.append(" <li>" + label + "\n"); 3198 } 3199 3200 plainBuf.deleteCharAt(plainBuf.length() - 1); 3202 htmlBuf.append("</ul>\n</body>\n</html>"); 3203 3204 tree = null; 3205 3206 return new BasicTransferable (plainBuf.toString(), htmlBuf.toString()); 3207 } 3208 3209 return null; 3210 } 3211 3212 public int compare(Object o1, Object o2) { 3213 int row1 = tree.getRowForPath((TreePath)o1); 3214 int row2 = tree.getRowForPath((TreePath)o2); 3215 return row1 - row2; 3216 } 3217 3218 String getDisplayString(TreePath path, boolean selected, boolean leaf) { 3219 int row = tree.getRowForPath(path); 3220 boolean hasFocus = tree.getLeadSelectionRow() == row; 3221 Object node = path.getLastPathComponent(); 3222 return tree.convertValueToText(node, selected, tree.isExpanded(row), 3223 leaf, row, hasFocus); 3224 } 3225 3226 3231 TreePath[] getDisplayOrderPaths(TreePath[] paths) { 3232 ArrayList selOrder = new ArrayList (); 3234 for (int i = 0; i < paths.length; i++) { 3235 selOrder.add(paths[i]); 3236 } 3237 Collections.sort(selOrder, this); 3238 int n = selOrder.size(); 3239 TreePath[] displayPaths = new TreePath[n]; 3240 for (int i = 0; i < n; i++) { 3241 displayPaths[i] = (TreePath) selOrder.get(i); 3242 } 3243 return displayPaths; 3244 } 3245 3246 public int getSourceActions(JComponent c) { 3247 return COPY; 3248 } 3249 3250 } 3251 3252 3253 private class Handler implements CellEditorListener, FocusListener, 3254 KeyListener, MouseListener, PropertyChangeListener, 3255 TreeExpansionListener, TreeModelListener, 3256 TreeSelectionListener { 3257 private String prefix = ""; 3261 private String typedString = ""; 3262 private long lastTime = 0L; 3263 3264 3275 public void keyTyped(KeyEvent e) { 3276 if(tree != null && tree.getRowCount()>0 && tree.hasFocus() && 3278 tree.isEnabled()) { 3279 if (e.isAltDown() || e.isControlDown() || e.isMetaDown() || 3280 isNavigationKey(e)) { 3281 return; 3282 } 3283 boolean startingFromSelection = true; 3284 3285 char c = e.getKeyChar(); 3286 3287 long time = e.getWhen(); 3288 int startingRow = tree.getLeadSelectionRow(); 3289 if (time - lastTime < timeFactor) { 3290 typedString += c; 3291 if((prefix.length() == 1) && (c == prefix.charAt(0))) { 3292 startingRow++; 3295 } else { 3296 prefix = typedString; 3297 } 3298 } else { 3299 startingRow++; 3300 typedString = "" + c; 3301 prefix = typedString; 3302 } 3303 lastTime = time; 3304 3305 if (startingRow < 0 || startingRow >= tree.getRowCount()) { 3306 startingFromSelection = false; 3307 startingRow = 0; 3308 } 3309 TreePath path = tree.getNextMatch(prefix, startingRow, 3310 Position.Bias.Forward); 3311 if (path != null) { 3312 tree.setSelectionPath(path); 3313 int row = getRowForPath(tree, path); 3314 ensureRowsAreVisible(row, row); 3315 } else if (startingFromSelection) { 3316 path = tree.getNextMatch(prefix, 0, 3317 Position.Bias.Forward); 3318 if (path != null) { 3319 tree.setSelectionPath(path); 3320 int row = getRowForPath(tree, path); 3321 ensureRowsAreVisible(row, row); 3322 } 3323 } 3324 } 3325 } 3326 3327 3333 public void keyPressed(KeyEvent e) { 3334 if ( isNavigationKey(e) ) { 3335 prefix = ""; 3336 typedString = ""; 3337 lastTime = 0L; 3338 } 3339 } 3340 3341 public void keyReleased(KeyEvent e) { 3342 } 3343 3344 3349 private boolean isNavigationKey(KeyEvent event) { 3350 InputMap inputMap = tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 3351 KeyStroke key = KeyStroke.getKeyStrokeForEvent(event); 3352 3353 if (inputMap != null && inputMap.get(key) != null) { 3354 return true; 3355 } 3356 return false; 3357 } 3358 3359 3360 public void propertyChange(PropertyChangeEvent event) { 3364 if (event.getSource() == treeSelectionModel) { 3365 treeSelectionModel.resetRowSelection(); 3366 } 3367 else if(event.getSource() == tree) { 3368 String changeName = event.getPropertyName(); 3369 3370 if (changeName == JTree.LEAD_SELECTION_PATH_PROPERTY) { 3371 if (!ignoreLAChange) { 3372 updateLeadRow(); 3373 repaintPath((TreePath)event.getOldValue()); 3374 repaintPath((TreePath)event.getNewValue()); 3375 } 3376 } 3377 else if (changeName == JTree.ANCHOR_SELECTION_PATH_PROPERTY) { 3378 if (!ignoreLAChange) { 3379 repaintPath((TreePath)event.getOldValue()); 3380 repaintPath((TreePath)event.getNewValue()); 3381 } 3382 } 3383 if(changeName == JTree.CELL_RENDERER_PROPERTY) { 3384 setCellRenderer((TreeCellRenderer)event.getNewValue()); 3385 redoTheLayout(); 3386 } 3387 else if(changeName == JTree.TREE_MODEL_PROPERTY) { 3388 setModel((TreeModel)event.getNewValue()); 3389 } 3390 else if(changeName == JTree.ROOT_VISIBLE_PROPERTY) { 3391 setRootVisible(((Boolean )event.getNewValue()). 3392 booleanValue()); 3393 } 3394 else if(changeName == JTree.SHOWS_ROOT_HANDLES_PROPERTY) { 3395 setShowsRootHandles(((Boolean )event.getNewValue()). 3396 booleanValue()); 3397 } 3398 else if(changeName == JTree.ROW_HEIGHT_PROPERTY) { 3399 setRowHeight(((Integer )event.getNewValue()). 3400 intValue()); 3401 } 3402 else if(changeName == JTree.CELL_EDITOR_PROPERTY) { 3403 setCellEditor((TreeCellEditor)event.getNewValue()); 3404 } 3405 else if(changeName == JTree.EDITABLE_PROPERTY) { 3406 setEditable(((Boolean )event.getNewValue()).booleanValue()); 3407 } 3408 else if(changeName == JTree.LARGE_MODEL_PROPERTY) { 3409 setLargeModel(tree.isLargeModel()); 3410 } 3411 else if(changeName == JTree.SELECTION_MODEL_PROPERTY) { 3412 setSelectionModel(tree.getSelectionModel()); 3413 } 3414 else if(changeName == "font") { 3415 completeEditing(); 3416 if(treeState != null) 3417 treeState.invalidateSizes(); 3418 updateSize(); 3419 } 3420 else if (changeName == "componentOrientation") { 3421 if (tree != null) { 3422 leftToRight = BasicGraphicsUtils.isLeftToRight(tree); 3423 redoTheLayout(); 3424 tree.treeDidChange(); 3425 3426 InputMap km = getInputMap(JComponent.WHEN_FOCUSED); 3427 SwingUtilities.replaceUIInputMap(tree, 3428 JComponent.WHEN_FOCUSED, km); 3429 } 3430 } else if ("transferHandler" == changeName) { 3431 DropTarget dropTarget = tree.getDropTarget(); 3432 if (dropTarget instanceof UIResource ) { 3433 if (defaultDropTargetListener == null) { 3434 defaultDropTargetListener = new TreeDropTargetListener(); 3435 } 3436 try { 3437 dropTarget.addDropTargetListener(defaultDropTargetListener); 3438 } catch (TooManyListenersException tmle) { 3439 } 3441 } 3442 } 3443 } 3444 } 3445 3446 private boolean selectedOnPress; 3450 3451 public void mouseClicked(MouseEvent e) { 3452 } 3453 3454 public void mouseEntered(MouseEvent e) { 3455 } 3456 3457 public void mouseExited(MouseEvent e) { 3458 } 3459 3460 3463 public void mousePressed(MouseEvent e) { 3464 if (! e.isConsumed()) { 3465 handleSelection(e); 3466 selectedOnPress = true; 3467 } else { 3468 selectedOnPress = false; 3469 } 3470 } 3471 3472 void handleSelection(MouseEvent e) { 3473 if(tree != null && tree.isEnabled()) { 3474 if (isEditing(tree) && tree.getInvokesStopCellEditing() && 3475 !stopEditing(tree)) { 3476 return; 3477 } 3478 3479 SwingUtilities2.adjustFocus(tree); 3480 3481 TreePath path = getClosestPathForLocation(tree, e.getX(), 3482 e.getY()); 3483 3484 handleSelectionImpl(e, path); 3485 } 3486 } 3487 3488 protected void handleSelectionImpl(MouseEvent e, TreePath path) { 3489 if(path != null) { 3490 Rectangle bounds = getPathBounds(tree, path); 3491 3492 if(e.getY() > (bounds.y + bounds.height)) { 3493 return; 3494 } 3495 3496 if(SwingUtilities.isLeftMouseButton(e)) 3499 checkForClickInExpandControl(path, e.getX(), e.getY()); 3500 3501 int x = e.getX(); 3502 3503 if (x > bounds.x && x <= (bounds.x + bounds.width)) { 3506 if ((DRAG_FIX && tree.getDragEnabled()) 3507 || !startEditing(path, e)) { 3508 3509 selectPathForEvent(path, e); 3510 } 3511 } 3512 } 3513 } 3514 3515 public void mouseDragged(MouseEvent e) { 3516 } 3517 3518 3522 public void mouseMoved(MouseEvent e) { 3523 } 3524 3525 public void mouseReleased(MouseEvent e) { 3526 if ((! e.isConsumed()) && (! selectedOnPress)) { 3527 handleSelection(e); 3528 } 3529 } 3530 3531 public void focusGained(FocusEvent e) { 3535 if(tree != null) { 3536 Rectangle pBounds; 3537 3538 pBounds = getPathBounds(tree, tree.getLeadSelectionPath()); 3539 if(pBounds != null) 3540 tree.repaint(pBounds); 3541 pBounds = getPathBounds(tree, getLeadSelectionPath()); 3542 if(pBounds != null) 3543 tree.repaint(pBounds); 3544 } 3545 } 3546 3547 public void focusLost(FocusEvent e) { 3548 focusGained(e); 3549 } 3550 3551 3552 public void editingStopped(ChangeEvent e) { 3556 completeEditing(false, false, true); 3557 } 3558 3559 3560 public void editingCanceled(ChangeEvent e) { 3561 completeEditing(false, false, false); 3562 } 3563 3564 3565 public void valueChanged(TreeSelectionEvent event) { 3569 completeEditing(); 3571 if(tree.getExpandsSelectedPaths() && treeSelectionModel != null) { 3574 TreePath[] paths = treeSelectionModel 3575 .getSelectionPaths(); 3576 3577 if(paths != null) { 3578 for(int counter = paths.length - 1; counter >= 0; 3579 counter--) { 3580 TreePath path = paths[counter].getParentPath(); 3581 boolean expand = true; 3582 3583 while (path != null) { 3584 if (treeModel.isLeaf(path.getLastPathComponent())){ 3587 expand = false; 3588 path = null; 3589 } 3590 else { 3591 path = path.getParentPath(); 3592 } 3593 } 3594 if (expand) { 3595 tree.makeVisible(paths[counter]); 3596 } 3597 } 3598 } 3599 } 3600 3601 TreePath oldLead = getLeadSelectionPath(); 3602 lastSelectedRow = tree.getMinSelectionRow(); 3603 TreePath lead = tree.getSelectionModel().getLeadSelectionPath(); 3604 setAnchorSelectionPath(lead); 3605 setLeadSelectionPath(lead); 3606 3607 TreePath[] changedPaths = event.getPaths(); 3608 Rectangle nodeBounds; 3609 Rectangle visRect = tree.getVisibleRect(); 3610 boolean paintPaths = true; 3611 int nWidth = tree.getWidth(); 3612 3613 if(changedPaths != null) { 3614 int counter, maxCounter = changedPaths.length; 3615 3616 if(maxCounter > 4) { 3617 tree.repaint(); 3618 paintPaths = false; 3619 } 3620 else { 3621 for (counter = 0; counter < maxCounter; counter++) { 3622 nodeBounds = getPathBounds(tree, 3623 changedPaths[counter]); 3624 if(nodeBounds != null && 3625 visRect.intersects(nodeBounds)) 3626 tree.repaint(0, nodeBounds.y, nWidth, 3627 nodeBounds.height); 3628 } 3629 } 3630 } 3631 if(paintPaths) { 3632 nodeBounds = getPathBounds(tree, oldLead); 3633 if(nodeBounds != null && visRect.intersects(nodeBounds)) 3634 tree.repaint(0, nodeBounds.y, nWidth, nodeBounds.height); 3635 nodeBounds = getPathBounds(tree, lead); 3636 if(nodeBounds != null && visRect.intersects(nodeBounds)) 3637 tree.repaint(0, nodeBounds.y, nWidth, nodeBounds.height); 3638 } 3639 } 3640 3641 3642 public void treeExpanded(TreeExpansionEvent event) { 3646 if(event != null && tree != null) { 3647 TreePath path = event.getPath(); 3648 3649 updateExpandedDescendants(path); 3650 } 3651 } 3652 3653 public void treeCollapsed(TreeExpansionEvent event) { 3654 if(event != null && tree != null) { 3655 TreePath path = event.getPath(); 3656 3657 completeEditing(); 3658 if(path != null && tree.isVisible(path)) { 3659 treeState.setExpandedState(path, false); 3660 updateLeadRow(); 3661 updateSize(); 3662 } 3663 } 3664 } 3665 3666 public void treeNodesChanged(TreeModelEvent e) { 3670 if(treeState != null && e != null) { 3671 treeState.treeNodesChanged(e); 3672 3673 TreePath pPath = e.getTreePath().getParentPath(); 3674 3675 if(pPath == null || treeState.isExpanded(pPath)) 3676 updateSize(); 3677 } 3678 } 3679 3680 public void treeNodesInserted(TreeModelEvent e) { 3681 if(treeState != null && e != null) { 3682 treeState.treeNodesInserted(e); 3683 3684 updateLeadRow(); 3685 3686 TreePath path = e.getTreePath(); 3687 3688 if(treeState.isExpanded(path)) { 3689 updateSize(); 3690 } 3691 else { 3692 int[] indices = e.getChildIndices(); 3696 int childCount = treeModel.getChildCount 3697 (path.getLastPathComponent()); 3698 3699 if(indices != null && (childCount - indices.length) == 0) 3700 updateSize(); 3701 } 3702 } 3703 } 3704 3705 public void treeNodesRemoved(TreeModelEvent e) { 3706 if(treeState != null && e != null) { 3707 treeState.treeNodesRemoved(e); 3708 3709 updateLeadRow(); 3710 3711 TreePath path = e.getTreePath(); 3712 3713 if(treeState.isExpanded(path) || 3714 treeModel.getChildCount(path.getLastPathComponent()) == 0) 3715 updateSize(); 3716 } 3717 } 3718 3719 public void treeStructureChanged(TreeModelEvent e) { 3720 if(treeState != null && e != null) { 3721 treeState.treeStructureChanged(e); 3722 3723 updateLeadRow(); 3724 3725 TreePath pPath = e.getTreePath(); 3726 3727 if (pPath != null) { 3728 pPath = pPath.getParentPath(); 3729 } 3730 if(pPath == null || treeState.isExpanded(pPath)) 3731 updateSize(); 3732 } 3733 } 3734 } 3735 3736 3737 private class DragFixHandler extends Handler implements MouseMotionListener, 3738 BeforeDrag { 3739 3740 private boolean dragPressDidSelection; 3744 3745 private boolean dragStarted; 3749 3750 private TreePath pressedPath; 3752 private MouseEvent pressedEvent; 3753 3754 private boolean valueChangedOnPress; 3757 3758 private boolean isActualPath(TreePath path, int x, int y) { 3759 if (path == null) { 3760 return false; 3761 } 3762 3763 Rectangle bounds = getPathBounds(tree, path); 3764 if (y > (bounds.y + bounds.height)) { 3765 return false; 3766 } 3767 3768 return (x >= bounds.x) && (x <= (bounds.x + bounds.width)); 3769 } 3770 3773 public void mousePressed(MouseEvent e) { 3774 if (SwingUtilities2.shouldIgnore(e, tree)) { 3775 return; 3776 } 3777 3778 if (isEditing(tree) && tree.getInvokesStopCellEditing() 3780 && !stopEditing(tree)) { 3781 return; 3782 } 3783 3784 completeEditing(); 3785 3786 pressedPath = getClosestPathForLocation(tree, e.getX(), e.getY()); 3787 3788 if (tree.getDragEnabled()) { 3789 mousePressedDND(e); 3790 } else { 3791 SwingUtilities2.adjustFocus(tree); 3792 handleSelectionImpl(e, pressedPath); 3793 } 3794 } 3795 3796 private void mousePressedDND(MouseEvent e) { 3797 pressedEvent = e; 3798 boolean grabFocus = true; 3799 dragStarted = false; 3800 valueChangedOnPress = false; 3801 3802 if (isActualPath(pressedPath, e.getX(), e.getY()) && 3804 DragRecognitionSupport.mousePressed(e)) { 3805 3806 dragPressDidSelection = false; 3807 3808 if (e.isControlDown()) { 3809 return; 3812 } else if (!e.isShiftDown() && tree.isPathSelected(pressedPath)) { 3813 setAnchorSelectionPath(pressedPath); 3816 setLeadSelectionPath(pressedPath, true); 3817 return; 3818 } 3819 3820 dragPressDidSelection = true; 3821 3822 grabFocus = false; 3824 } 3825 3826 if (grabFocus) { 3827 SwingUtilities2.adjustFocus(tree); 3828 } 3829 3830 handleSelectionImpl(e, pressedPath); 3831 } 3832 3833 public void dragStarting(MouseEvent me) { 3834 dragStarted = true; 3835 3836 if (me.isControlDown()) { 3837 tree.addSelectionPath(pressedPath); 3838 setAnchorSelectionPath(pressedPath); 3839 setLeadSelectionPath(pressedPath, true); 3840 } 3841 3842 pressedEvent = null; 3843 pressedPath = null; 3844 } 3845 3846 public void mouseDragged(MouseEvent e) { 3847 if (SwingUtilities2.shouldIgnore(e, tree)) { 3848 return; 3849 } 3850 3851 if (tree.getDragEnabled()) { 3852 DragRecognitionSupport.mouseDragged(e, this); 3853 } 3854 } 3855 3856 public void mouseReleased(MouseEvent e) { 3857 if (SwingUtilities2.shouldIgnore(e, tree)) { 3858 return; 3859 } 3860 3861 if (tree.getDragEnabled()) { 3862 mouseReleasedDND(e); 3863 } 3864 3865 pressedEvent = null; 3866 pressedPath = null; 3867 } 3868 3869 private void mouseReleasedDND(MouseEvent e) { 3870 MouseEvent me = DragRecognitionSupport.mouseReleased(e); 3871 if (me != null) { 3872 SwingUtilities2.adjustFocus(tree); 3873 if (!dragPressDidSelection) { 3874 handleSelectionImpl(me, pressedPath); 3875 } 3876 } 3877 3878 if (!dragStarted) { 3879 3880 if (pressedPath != null && !valueChangedOnPress && 3890 isActualPath(pressedPath, pressedEvent.getX(), pressedEvent.getY())) { 3891 3892 startEditingOnRelease(pressedPath, pressedEvent, e); 3893 } 3894 } 3895 } 3896 3897 public void valueChanged(TreeSelectionEvent event) { 3898 valueChangedOnPress = true; 3899 super.valueChanged(event); 3900 } 3901 } 3902 3903 3904 private static class Actions extends UIAction { 3905 private static final String SELECT_PREVIOUS = "selectPrevious"; 3906 private static final String SELECT_PREVIOUS_CHANGE_LEAD = 3907 "selectPreviousChangeLead"; 3908 private static final String SELECT_PREVIOUS_EXTEND_SELECTION = 3909 "selectPreviousExtendSelection"; 3910 private static final String SELECT_NEXT = "selectNext"; 3911 private static final String SELECT_NEXT_CHANGE_LEAD = 3912 "selectNextChangeLead"; 3913 private static final String SELECT_NEXT_EXTEND_SELECTION = 3914 "selectNextExtendSelection"; 3915 private static final String SELECT_CHILD = "selectChild"; 3916 private static final String SELECT_CHILD_CHANGE_LEAD = 3917 "selectChildChangeLead"; 3918 private static final String SELECT_PARENT = "selectParent"; 3919 private static final String SELECT_PARENT_CHANGE_LEAD = 3920 "selectParentChangeLead"; 3921 private static final String SCROLL_UP_CHANGE_SELECTION = 3922 "scrollUpChangeSelection"; 3923 private static final String SCROLL_UP_CHANGE_LEAD = 3924 "scrollUpChangeLead"; 3925 private static final String SCROLL_UP_EXTEND_SELECTION = 3926 "scrollUpExtendSelection"; 3927 private static final String SCROLL_DOWN_CHANGE_SELECTION = 3928 "scrollDownChangeSelection"; 3929 private static final String SCROLL_DOWN_EXTEND_SELECTION = 3930 "scrollDownExtendSelection"; 3931 private static final String SCROLL_DOWN_CHANGE_LEAD = 3932 "scrollDownChangeLead"; 3933 private static final String SELECT_FIRST = "selectFirst"; 3934 private static final String SELECT_FIRST_CHANGE_LEAD = 3935 "selectFirstChangeLead"; 3936 private static final String SELECT_FIRST_EXTEND_SELECTION = 3937 "selectFirstExtendSelection"; 3938 private static final String SELECT_LAST = "selectLast"; 3939 private static final String SELECT_LAST_CHANGE_LEAD = 3940 "selectLastChangeLead"; 3941 private static final String SELECT_LAST_EXTEND_SELECTION = 3942 "selectLastExtendSelection"; 3943 private static final String TOGGLE = "toggle"; 3944 private static final String CANCEL_EDITING = "cancel"; 3945 private static final String START_EDITING = "startEditing"; 3946 private static final String SELECT_ALL = "selectAll"; 3947 private static final String CLEAR_SELECTION = "clearSelection"; 3948 private static final String SCROLL_LEFT = "scrollLeft"; 3949 private static final String SCROLL_RIGHT = "scrollRight"; 3950 private static final String SCROLL_LEFT_EXTEND_SELECTION = 3951 "scrollLeftExtendSelection"; 3952 private static final String SCROLL_RIGHT_EXTEND_SELECTION = 3953 "scrollRightExtendSelection"; 3954 private static final String SCROLL_RIGHT_CHANGE_LEAD = 3955 "scrollRightChangeLead"; 3956 private static final String SCROLL_LEFT_CHANGE_LEAD = 3957 "scrollLeftChangeLead"; 3958 private static final String EXPAND = "expand"; 3959 private static final String COLLAPSE = "collapse"; 3960 private static final String MOVE_SELECTION_TO_PARENT = 3961 "moveSelectionToParent"; 3962 3963 private static final String ADD_TO_SELECTION = "addToSelection"; 3965 3966 private static final String TOGGLE_AND_ANCHOR = "toggleAndAnchor"; 3968 3969 private static final String EXTEND_TO = "extendTo"; 3971 3972 private static final String MOVE_SELECTION_TO = "moveSelectionTo"; 3974 3975 Actions() { 3976 super(null); 3977 } 3978 3979 Actions(String key) { 3980 super(key); 3981 } 3982 3983 public boolean isEnabled(Object o) { 3984 if (o instanceof JTree) { 3985 if (getName() == CANCEL_EDITING) { 3986 return ((JTree)o).isEditing(); 3987 } 3988 } 3989 return true; 3990 } 3991 3992 public void actionPerformed(ActionEvent e) { 3993 JTree tree = (JTree)e.getSource(); 3994 BasicTreeUI ui = (BasicTreeUI )BasicLookAndFeel.getUIOfType( 3995 tree.getUI(), BasicTreeUI .class); 3996 if (ui == null) { 3997 return; 3998 } 3999 String key = getName(); 4000 if (key == SELECT_PREVIOUS) { 4001 increment(tree, ui, -1, false, true); 4002 } 4003 else if (key == SELECT_PREVIOUS_CHANGE_LEAD) { 4004 increment(tree, ui, -1, false, false); 4005 } 4006 else if (key == SELECT_PREVIOUS_EXTEND_SELECTION) { 4007 increment(tree, ui, -1, true, true); 4008 } 4009 else if (key == SELECT_NEXT) { 4010 increment(tree, ui, 1, false, true); 4011 } 4012 else if (key == SELECT_NEXT_CHANGE_LEAD) { 4013 increment(tree, ui, 1, false, false); 4014 } 4015 else if (key == SELECT_NEXT_EXTEND_SELECTION) { 4016 increment(tree, ui, 1, true, true); 4017 } 4018 else if (key == SELECT_CHILD) { 4019 traverse(tree, ui, 1, true); 4020 } 4021 else if (key == SELECT_CHILD_CHANGE_LEAD) { 4022 traverse(tree, ui, 1, false); 4023 } 4024 else if (key == SELECT_PARENT) { 4025 traverse(tree, ui, -1, true); 4026 } 4027 else if (key == SELECT_PARENT_CHANGE_LEAD) { 4028 traverse(tree, ui, -1, false); 4029 } 4030 else if (key == SCROLL_UP_CHANGE_SELECTION) { 4031 page(tree, ui, -1, false, true); 4032 } 4033 else if (key == SCROLL_UP_CHANGE_LEAD) { 4034 page(tree, ui, -1, false, false); 4035 } 4036 else if (key == SCROLL_UP_EXTEND_SELECTION) { 4037 page(tree, ui, -1, true, true); 4038 } 4039 else if (key == SCROLL_DOWN_CHANGE_SELECTION) { 4040 page(tree, ui, 1, false, true); 4041 } 4042 else if (key == SCROLL_DOWN_EXTEND_SELECTION) { 4043 page(tree, ui, 1, true, true); 4044 } 4045 else if (key == SCROLL_DOWN_CHANGE_LEAD) { 4046 page(tree, ui, 1, false, false); 4047 } 4048 else if (key == SELECT_FIRST) { 4049 home(tree, ui, -1, false, true); 4050 } 4051 else if (key == SELECT_FIRST_CHANGE_LEAD) { 4052 home(tree, ui, -1, false, false); 4053 } 4054 else if (key == SELECT_FIRST_EXTEND_SELECTION) { 4055 home(tree, ui, -1, true, true); 4056 } 4057 else if (key == SELECT_LAST) { 4058 home(tree, ui, 1, false, true); 4059 } 4060 else if (key == SELECT_LAST_CHANGE_LEAD) { 4061 home(tree, ui, 1, false, false); 4062 } 4063 else if (key == SELECT_LAST_EXTEND_SELECTION) { 4064 home(tree, ui, 1, true, true); 4065 } 4066 else if (key == TOGGLE) { 4067 toggle(tree, ui); 4068 } 4069 else if (key == CANCEL_EDITING) { 4070 cancelEditing(tree, ui); 4071 } 4072 else if (key == START_EDITING) { 4073 startEditing(tree, ui); 4074 } 4075 else if (key == SELECT_ALL) { 4076 selectAll(tree, ui, true); 4077 } 4078 else if (key == CLEAR_SELECTION) { 4079 selectAll(tree, ui, false); 4080 } 4081 else if (key == ADD_TO_SELECTION) { 4082 if (ui.getRowCount(tree) > 0) { 4083 int lead = ui.getLeadSelectionRow(); 4084 if (!tree.isRowSelected(lead)) { 4085 TreePath aPath = ui.getAnchorSelectionPath(); 4086 tree.addSelectionRow(lead); 4087 ui.setAnchorSelectionPath(aPath); 4088 } 4089 } 4090 } 4091 else if (key == TOGGLE_AND_ANCHOR) { 4092 if (ui.getRowCount(tree) > 0) { 4093 int lead = ui.getLeadSelectionRow(); 4094 TreePath lPath = ui.getLeadSelectionPath(); 4095 if (!tree.isRowSelected(lead)) { 4096 tree.addSelectionRow(lead); 4097 } else { 4098 tree.removeSelectionRow(lead); 4099 ui.setLeadSelectionPath(lPath); 4100 } 4101 ui.setAnchorSelectionPath(lPath); 4102 } 4103 } 4104 else if (key == EXTEND_TO) { 4105 extendSelection(tree, ui); 4106 } 4107 else if (key == MOVE_SELECTION_TO) { 4108 if (ui.getRowCount(tree) > 0) { 4109 int lead = ui.getLeadSelectionRow(); 4110 tree.setSelectionInterval(lead, lead); 4111 } 4112 } 4113 else if (key == SCROLL_LEFT) { 4114 scroll(tree, ui, SwingConstants.HORIZONTAL, -10); 4115 } 4116 else if (key == SCROLL_RIGHT) { 4117 scroll(tree, ui, SwingConstants.HORIZONTAL, 10); 4118 } 4119 else if (key == SCROLL_LEFT_EXTEND_SELECTION) { 4120 scrollChangeSelection(tree, ui, -1, true, true); 4121 } 4122 else if (key == SCROLL_RIGHT_EXTEND_SELECTION) { 4123 scrollChangeSelection(tree, ui, 1, true, true); 4124 } 4125 else if (key == SCROLL_RIGHT_CHANGE_LEAD) { 4126 scrollChangeSelection(tree, ui, 1, false, false); 4127 } 4128 else if (key == SCROLL_LEFT_CHANGE_LEAD) { 4129 scrollChangeSelection(tree, ui, -1, false, false); 4130 } 4131 else if (key == EXPAND) { 4132 expand(tree, ui); 4133 } 4134 else if (key == COLLAPSE) { 4135 collapse(tree, ui); 4136 } 4137 else if (key == MOVE_SELECTION_TO_PARENT) { 4138 moveSelectionToParent(tree, ui); 4139 } 4140 } 4141 4142 private void scrollChangeSelection(JTree tree, BasicTreeUI ui, 4143 int direction, boolean addToSelection, 4144 boolean changeSelection) { 4145 int rowCount; 4146 4147 if((rowCount = ui.getRowCount(tree)) > 0 && 4148 ui.treeSelectionModel != null) { 4149 TreePath newPath; 4150 Rectangle visRect = tree.getVisibleRect(); 4151 4152 if (direction == -1) { 4153 newPath = ui.getClosestPathForLocation(tree, visRect.x, 4154 visRect.y); 4155 visRect.x = Math.max(0, visRect.x - visRect.width); 4156 } 4157 else { 4158 visRect.x = Math.min(Math.max(0, tree.getWidth() - 4159 visRect.width), visRect.x + visRect.width); 4160 newPath = ui.getClosestPathForLocation(tree, visRect.x, 4161 visRect.y + visRect.height); 4162 } 4163 tree.scrollRectToVisible(visRect); 4165 if (addToSelection) { 4167 ui.extendSelection(newPath); 4168 } 4169 else if(changeSelection) { 4170 tree.setSelectionPath(newPath); 4171 } 4172 else { 4173 ui.setLeadSelectionPath(newPath, true); 4174 } 4175 } 4176 } 4177 4178 private void scroll(JTree component, BasicTreeUI ui, int direction, 4179 int amount) { 4180 Rectangle visRect = component.getVisibleRect(); 4181 Dimension size = component.getSize(); 4182 if (direction == SwingConstants.HORIZONTAL) { 4183 visRect.x += amount; 4184 visRect.x = Math.max(0, visRect.x); 4185 visRect.x = Math.min(Math.max(0, size.width - visRect.width), 4186 visRect.x); 4187 } 4188 else { 4189 visRect.y += amount; 4190 visRect.y = Math.max(0, visRect.y); 4191 visRect.y = Math.min(Math.max(0, size.width - visRect.height), 4192 visRect.y); 4193 } 4194 component.scrollRectToVisible(visRect); 4195 } 4196 4197 private void extendSelection(JTree tree, BasicTreeUI ui) { 4198 if (ui.getRowCount(tree) > 0) { 4199 int lead = ui.getLeadSelectionRow(); 4200 4201 if (lead != -1) { 4202 TreePath leadP = ui.getLeadSelectionPath(); 4203 TreePath aPath = ui.getAnchorSelectionPath(); 4204 int aRow = ui.getRowForPath(tree, aPath); 4205 4206 if(aRow == -1) 4207 aRow = 0; 4208 tree.setSelectionInterval(aRow, lead); 4209 ui.setLeadSelectionPath(leadP); 4210 ui.setAnchorSelectionPath(aPath); 4211 } 4212 } 4213 } 4214 4215 private void selectAll(JTree tree, BasicTreeUI ui, boolean selectAll) { 4216 int rowCount = ui.getRowCount(tree); 4217 4218 if(rowCount > 0) { 4219 if(selectAll) { 4220 if (tree.getSelectionModel().getSelectionMode() == 4221 TreeSelectionModel.SINGLE_TREE_SELECTION) { 4222 4223 int lead = ui.getLeadSelectionRow(); 4224 if (lead != -1) { 4225 tree.setSelectionRow(lead); 4226 } else if (tree.getMinSelectionRow() == -1) { 4227 tree.setSelectionRow(0); 4228 ui.ensureRowsAreVisible(0, 0); 4229 } 4230 return; 4231 } 4232 4233 TreePath lastPath = ui.getLeadSelectionPath(); 4234 TreePath aPath = ui.getAnchorSelectionPath(); 4235 4236 if(lastPath != null && !tree.isVisible(lastPath)) { 4237 lastPath = null; 4238 } 4239 tree.setSelectionInterval(0, rowCount - 1); 4240 if(lastPath != null) { 4241 ui.setLeadSelectionPath(lastPath); 4242 } 4243 if(aPath != null && tree.isVisible(aPath)) { 4244 ui.setAnchorSelectionPath(aPath); 4245 } 4246 } 4247 else { 4248 TreePath lastPath = ui.getLeadSelectionPath(); 4249 TreePath aPath = ui.getAnchorSelectionPath(); 4250 4251 tree.clearSelection(); 4252 ui.setAnchorSelectionPath(aPath); 4253 ui.setLeadSelectionPath(lastPath); 4254 } 4255 } 4256 } 4257 4258 private void startEditing(JTree tree, BasicTreeUI ui) { 4259 TreePath lead = ui.getLeadSelectionPath(); 4260 int editRow = (lead != null) ? 4261 ui.getRowForPath(tree, lead) : -1; 4262 4263 if(editRow != -1) { 4264 tree.startEditingAtPath(lead); 4265 } 4266 } 4267 4268 private void cancelEditing(JTree tree, BasicTreeUI ui) { 4269 tree.cancelEditing(); 4270 } 4271 4272 private void toggle(JTree tree, BasicTreeUI ui) { 4273 int selRow = ui.getLeadSelectionRow(); 4274 4275 if(selRow != -1 && !ui.isLeaf(selRow)) { 4276 TreePath aPath = ui.getAnchorSelectionPath(); 4277 TreePath lPath = ui.getLeadSelectionPath(); 4278 4279 ui.toggleExpandState(ui.getPathForRow(tree, selRow)); 4280 ui.setAnchorSelectionPath(aPath); 4281 ui.setLeadSelectionPath(lPath); 4282 } 4283 } 4284 4285 private void expand(JTree tree, BasicTreeUI ui) { 4286 int selRow = ui.getLeadSelectionRow(); 4287 tree.expandRow(selRow); 4288 } 4289 4290 private void collapse(JTree tree, BasicTreeUI ui) { 4291 int selRow = ui.getLeadSelectionRow(); 4292 tree.collapseRow(selRow); 4293 } 4294 4295 private void increment(JTree tree, BasicTreeUI ui, int direction, 4296 boolean addToSelection, 4297 boolean changeSelection) { 4298 4299 if (!addToSelection && !changeSelection && 4301 tree.getSelectionModel().getSelectionMode() != 4302 TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { 4303 changeSelection = true; 4304 } 4305 4306 int rowCount; 4307 4308 if(ui.treeSelectionModel != null && 4309 (rowCount = tree.getRowCount()) > 0) { 4310 int selIndex = ui.getLeadSelectionRow(); 4311 int newIndex; 4312 4313 if(selIndex == -1) { 4314 if(direction == 1) 4315 newIndex = 0; 4316 else 4317 newIndex = rowCount - 1; 4318 } 4319 else 4320 4321 newIndex = Math.min(rowCount - 1, Math.max 4322 (0, (selIndex + direction))); 4323 if(addToSelection && ui.treeSelectionModel. 4324 getSelectionMode() != TreeSelectionModel. 4325 SINGLE_TREE_SELECTION) { 4326 ui.extendSelection(tree.getPathForRow(newIndex)); 4327 } 4328 else if(changeSelection) { 4329 tree.setSelectionInterval(newIndex, newIndex); 4330 } 4331 else { 4332 ui.setLeadSelectionPath(tree.getPathForRow(newIndex),true); 4333 } 4334 ui.ensureRowsAreVisible(newIndex, newIndex); 4335 ui.lastSelectedRow = newIndex; 4336 } 4337 } 4338 4339 private void traverse(JTree tree, BasicTreeUI ui, int direction, 4340 boolean changeSelection) { 4341 4342 if (!changeSelection && 4344 tree.getSelectionModel().getSelectionMode() != 4345 TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { 4346 changeSelection = true; 4347 } 4348 4349 int rowCount; 4350 4351 if((rowCount = tree.getRowCount()) > 0) { 4352 int minSelIndex = ui.getLeadSelectionRow(); 4353 int newIndex; 4354 4355 if(minSelIndex == -1) 4356 newIndex = 0; 4357 else { 4358 4360 if(direction == 1) { 4361 if(!ui.isLeaf(minSelIndex) && 4362 !tree.isExpanded(minSelIndex)) { 4363 ui.toggleExpandState(ui.getPathForRow 4364 (tree, minSelIndex)); 4365 newIndex = -1; 4366 } 4367 else 4368 newIndex = Math.min(minSelIndex + 1, rowCount - 1); 4369 } 4370 4371 else { 4372 if(!ui.isLeaf(minSelIndex) && 4373 tree.isExpanded(minSelIndex)) { 4374 ui.toggleExpandState(ui.getPathForRow 4375 (tree, minSelIndex)); 4376 newIndex = -1; 4377 } 4378 else { 4379 TreePath path = ui.getPathForRow(tree, 4380 minSelIndex); 4381 4382 if(path != null && path.getPathCount() > 1) { 4383 newIndex = ui.getRowForPath(tree, path. 4384 getParentPath()); 4385 } 4386 else 4387 newIndex = -1; 4388 } 4389 } 4390 } 4391 if(newIndex != -1) { 4392 if(changeSelection) { 4393 tree.setSelectionInterval(newIndex, newIndex); 4394 } 4395 else { 4396 ui.setLeadSelectionPath(ui.getPathForRow( 4397 tree, newIndex), true); 4398 } 4399 ui.ensureRowsAreVisible(newIndex, newIndex); 4400 } 4401 } 4402 } 4403 4404 private void moveSelectionToParent(JTree tree, BasicTreeUI ui) { 4405 int selRow = ui.getLeadSelectionRow(); 4406 TreePath path = ui.getPathForRow(tree, selRow); 4407 if (path != null && path.getPathCount() > 1) { 4408 int newIndex = ui.getRowForPath(tree, path.getParentPath()); 4409 if (newIndex != -1) { 4410 tree.setSelectionInterval(newIndex, newIndex); 4411 ui.ensureRowsAreVisible(newIndex, newIndex); 4412 } 4413 } 4414 } 4415 4416 private void page(JTree tree, BasicTreeUI ui, int direction, 4417 boolean addToSelection, boolean changeSelection) { 4418 4419 if (!addToSelection && !changeSelection && 4421 tree.getSelectionModel().getSelectionMode() != 4422 TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { 4423 changeSelection = true; 4424 } 4425 4426 int rowCount; 4427 4428 if((rowCount = ui.getRowCount(tree)) > 0 && 4429 ui.treeSelectionModel != null) { 4430 Dimension maxSize = tree.getSize(); 4431 TreePath lead = ui.getLeadSelectionPath(); 4432 TreePath newPath; 4433 Rectangle visRect = tree.getVisibleRect(); 4434 4435 if(direction == -1) { 4436 newPath = ui.getClosestPathForLocation(tree, visRect.x, 4438 visRect.y); 4439 if(newPath.equals(lead)) { 4440 visRect.y = Math.max(0, visRect.y - visRect.height); 4441 newPath = tree.getClosestPathForLocation(visRect.x, 4442 visRect.y); 4443 } 4444 } 4445 else { 4446 visRect.y = Math.min(maxSize.height, visRect.y + 4448 visRect.height - 1); 4449 newPath = tree.getClosestPathForLocation(visRect.x, 4450 visRect.y); 4451 if(newPath.equals(lead)) { 4452 visRect.y = Math.min(maxSize.height, visRect.y + 4453 visRect.height - 1); 4454 newPath = tree.getClosestPathForLocation(visRect.x, 4455 visRect.y); 4456 } 4457 } 4458 Rectangle newRect = ui.getPathBounds(tree, newPath); 4459 4460 newRect.x = visRect.x; 4461 newRect.width = visRect.width; 4462 if(direction == -1) { 4463 newRect.height = visRect.height; 4464 } 4465 else { 4466 newRect.y -= (visRect.height - newRect.height); 4467 newRect.height = visRect.height; 4468 } 4469 4470 if(addToSelection) { 4471 ui.extendSelection(newPath); 4472 } 4473 else if(changeSelection) { 4474 tree.setSelectionPath(newPath); 4475 } 4476 else { 4477 ui.setLeadSelectionPath(newPath, true); 4478 } 4479 tree.scrollRectToVisible(newRect); 4480 } 4481 } 4482 4483 private void home(JTree tree, BasicTreeUI ui, int direction, 4484 boolean addToSelection, boolean changeSelection) { 4485 4486 if (!addToSelection && !changeSelection && 4488 tree.getSelectionModel().getSelectionMode() != 4489 TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { 4490 changeSelection = true; 4491 } 4492 4493 int rowCount = ui.getRowCount(tree); 4494 4495 if (rowCount > 0) { 4496 if(direction == -1) { 4497 ui.ensureRowsAreVisible(0, 0); 4498 if (addToSelection) { 4499 TreePath aPath = ui.getAnchorSelectionPath(); 4500 int aRow = (aPath == null) ? -1 : 4501 ui.getRowForPath(tree, aPath); 4502 4503 if (aRow == -1) { 4504 tree.setSelectionInterval(0, 0); 4505 } 4506 else { 4507 tree.setSelectionInterval(0, aRow); 4508 ui.setAnchorSelectionPath(aPath); 4509 ui.setLeadSelectionPath(ui.getPathForRow(tree, 0)); 4510 } 4511 } 4512 else if(changeSelection) { 4513 tree.setSelectionInterval(0, 0); 4514 } 4515 else { 4516 ui.setLeadSelectionPath(ui.getPathForRow(tree, 0), 4517 true); 4518 } 4519 } 4520 else { 4521 ui.ensureRowsAreVisible(rowCount - 1, rowCount - 1); 4522 if (addToSelection) { 4523 TreePath aPath = ui.getAnchorSelectionPath(); 4524 int aRow = (aPath == null) ? -1 : 4525 ui.getRowForPath(tree, aPath); 4526 4527 if (aRow == -1) { 4528 tree.setSelectionInterval(rowCount - 1, 4529 rowCount -1); 4530 } 4531 else { 4532 tree.setSelectionInterval(aRow, rowCount - 1); 4533 ui.setAnchorSelectionPath(aPath); 4534 ui.setLeadSelectionPath(ui.getPathForRow(tree, 4535 rowCount -1)); 4536 } 4537 } 4538 else if(changeSelection) { 4539 tree.setSelectionInterval(rowCount - 1, rowCount - 1); 4540 } 4541 else { 4542 ui.setLeadSelectionPath(ui.getPathForRow(tree, 4543 rowCount - 1), true); 4544 } 4545 } 4546 } 4547 } 4548 } 4549} | Popular Tags |