1 19 package org.openide.explorer.view; 20 21 import org.openide.awt.MouseUtils; 22 import org.openide.explorer.ExplorerManager; 23 import org.openide.nodes.Children; 24 import org.openide.nodes.Node; 25 import org.openide.nodes.NodeOp; 26 import org.openide.util.ContextAwareAction; 27 import org.openide.util.Lookup; 28 import org.openide.util.Mutex; 29 import org.openide.util.NbBundle; 30 import org.openide.util.RequestProcessor; 31 import org.openide.util.Utilities; 32 import org.openide.util.WeakListeners; 33 import org.openide.util.actions.SystemAction; 34 import org.openide.util.lookup.Lookups; 35 import org.openide.util.lookup.ProxyLookup; 36 import java.awt.Container ; 37 import java.awt.Cursor ; 38 import java.awt.Dimension ; 39 import java.awt.Font ; 40 import java.awt.Graphics ; 41 import java.awt.Insets ; 42 import java.awt.Point ; 43 import java.awt.Rectangle ; 44 import java.awt.Toolkit ; 45 import java.awt.datatransfer.Clipboard ; 46 import java.awt.datatransfer.DataFlavor ; 47 import java.awt.datatransfer.Transferable ; 48 import java.awt.dnd.Autoscroll ; 49 import java.awt.dnd.DnDConstants ; 50 import java.awt.event.ActionEvent ; 51 import java.awt.event.ActionListener ; 52 import java.awt.event.FocusEvent ; 53 import java.awt.event.FocusListener ; 54 import java.awt.event.InputEvent ; 55 import java.awt.event.KeyAdapter ; 56 import java.awt.event.KeyEvent ; 57 import java.awt.event.KeyListener ; 58 import java.awt.event.MouseAdapter ; 59 import java.awt.event.MouseEvent ; 60 import java.beans.PropertyChangeEvent ; 61 import java.beans.PropertyChangeListener ; 62 import java.beans.PropertyVetoException ; 63 import java.beans.VetoableChangeListener ; 64 import java.util.ArrayList ; 65 import java.util.Arrays ; 66 import java.util.Iterator ; 67 import java.util.List ; 68 import java.util.logging.Level ; 69 import java.util.logging.Logger ; 70 import javax.accessibility.AccessibleContext ; 71 import javax.swing.AbstractAction ; 72 import javax.swing.Action ; 73 import javax.swing.BorderFactory ; 74 import javax.swing.BoxLayout ; 75 import javax.swing.JComponent ; 76 import javax.swing.JLabel ; 77 import javax.swing.JMenu ; 78 import javax.swing.JPanel ; 79 import javax.swing.JPopupMenu ; 80 import javax.swing.JScrollPane ; 81 import javax.swing.JTextField ; 82 import javax.swing.JTree ; 83 import javax.swing.JViewport ; 84 import javax.swing.KeyStroke ; 85 import javax.swing.SwingUtilities ; 86 import javax.swing.ToolTipManager ; 87 import javax.swing.TransferHandler ; 88 import javax.swing.UIManager ; 89 import javax.swing.border.Border ; 90 import javax.swing.event.DocumentEvent ; 91 import javax.swing.event.DocumentListener ; 92 import javax.swing.event.TreeExpansionEvent ; 93 import javax.swing.event.TreeExpansionListener ; 94 import javax.swing.event.TreeModelEvent ; 95 import javax.swing.event.TreeModelListener ; 96 import javax.swing.event.TreeSelectionEvent ; 97 import javax.swing.event.TreeSelectionListener ; 98 import javax.swing.event.TreeWillExpandListener ; 99 import javax.swing.plaf.UIResource ; 100 import javax.swing.text.Position ; 101 import javax.swing.tree.ExpandVetoException ; 102 import javax.swing.tree.RowMapper ; 103 import javax.swing.tree.TreeModel ; 104 import javax.swing.tree.TreeNode ; 105 import javax.swing.tree.TreePath ; 106 import javax.swing.tree.TreeSelectionModel ; 107 108 109 114 public abstract class TreeView extends JScrollPane { 115 static { 116 UIManager.put("Tree.scrollsHorizontallyAndVertically", Boolean.TRUE); 118 } 119 120 124 125 static final long serialVersionUID = -1639001987693376168L; 126 127 129 private static final int TIME_TO_COLLAPSE = (System.getProperty("netbeans.debug.heap") != null) ? 0 : 15000; 130 131 132 private static final int MIN_TREEVIEW_WIDTH = 400; 133 134 135 private static final int MIN_TREEVIEW_HEIGHT = 400; 136 137 private static boolean isSynth = UIManager.getLookAndFeel().getClass().getName().indexOf( 139 "com.sun.java.swing.plaf.gtk" 140 ) != -1; 141 142 146 147 transient protected JTree tree; 148 149 150 transient NodeTreeModel treeModel; 151 152 153 transient ExplorerManager manager; 154 155 157 158 transient PopupSupport defaultActionListener; 159 160 161 transient boolean defaultActionEnabled; 162 163 164 transient PopupAdapter popupListener; 165 166 167 transient TreePropertyListener managerListener = null; 168 169 170 transient PropertyChangeListener wlpc; 171 172 173 transient VetoableChangeListener wlvc; 174 175 176 private transient boolean dragActive = true; 177 178 179 private transient boolean dropActive = true; 180 181 182 transient TreeViewDragSupport dragSupport; 183 184 185 transient TreeViewDropSupport dropSupport; 186 transient boolean dropTargetPopupAllowed = true; 187 transient private Container contentPane; 188 transient private List storeSelectedPaths; 189 190 transient private int allowedDragActions = DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE; 192 transient private int allowedDropActions = DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE; 193 194 196 public TreeView() { 197 this(true, true); 198 } 199 200 204 public TreeView(boolean defaultAction, boolean popupAllowed) { 205 initializeTree(); 206 207 setDropTarget( DragDropUtilities.dragAndDropEnabled ); 214 215 setPopupAllowed(popupAllowed); 216 setDefaultActionAllowed(defaultAction); 217 218 Dimension dim = null; 219 220 try { 221 dim = getPreferredSize(); 222 223 if (dim == null) { 224 dim = new Dimension (MIN_TREEVIEW_WIDTH, MIN_TREEVIEW_HEIGHT); 225 } 226 } catch (NullPointerException npe) { 227 dim = new Dimension (MIN_TREEVIEW_WIDTH, MIN_TREEVIEW_HEIGHT); 228 } 229 230 if (dim.width < MIN_TREEVIEW_WIDTH) { 231 dim.width = MIN_TREEVIEW_WIDTH; 232 } 233 234 if (dim.height < MIN_TREEVIEW_HEIGHT) { 235 dim.height = MIN_TREEVIEW_HEIGHT; 236 } 237 238 setPreferredSize(dim); 239 } 240 241 public void updateUI() { 242 super.updateUI(); 243 244 setViewportBorder(BorderFactory.createEmptyBorder()); 246 setBorder(BorderFactory.createEmptyBorder()); 247 } 248 249 public Border getBorder() { 250 if (isSynth) { 251 return BorderFactory.createEmptyBorder(); 252 } else { 253 return super.getBorder(); 254 } 255 } 256 257 263 void initializeTree() { 264 treeModel = createModel(); 266 treeModel.addView(this); 267 268 tree = new ExplorerTree(treeModel); 269 270 NodeRenderer rend = new NodeRenderer(); 271 tree.setCellRenderer(rend); 272 tree.putClientProperty("JTree.lineStyle", "Angled"); setViewportView(tree); 274 275 tree.setCellEditor(new TreeViewCellEditor(tree)); 277 tree.setEditable(true); 278 279 setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); 281 282 ToolTipManager.sharedInstance().registerComponent(tree); 283 284 managerListener = new TreePropertyListener(); 286 tree.addTreeExpansionListener(managerListener); 287 tree.addTreeWillExpandListener(managerListener); 288 289 setRequestFocusEnabled(false); 291 292 defaultActionListener = new PopupSupport(); 293 getInputMap( JTree.WHEN_FOCUSED ).put( 294 KeyStroke.getKeyStroke( KeyEvent.VK_F10, KeyEvent.SHIFT_DOWN_MASK ), "org.openide.actions.PopupAction" ); 295 getActionMap().put("org.openide.actions.PopupAction", defaultActionListener.popup); 296 tree.addFocusListener(defaultActionListener); 297 tree.addMouseListener(defaultActionListener); 298 } 299 300 303 public boolean isPopupAllowed() { 304 return popupListener != null; 305 } 306 307 311 public void setPopupAllowed(boolean value) { 312 if ((popupListener == null) && value) { 313 popupListener = new PopupAdapter(); 315 tree.addMouseListener(popupListener); 316 317 return; 318 } 319 320 if ((popupListener != null) && !value) { 321 tree.removeMouseListener(popupListener); 323 popupListener = null; 324 325 return; 326 } 327 } 328 329 void setDropTargetPopupAllowed(boolean value) { 330 dropTargetPopupAllowed = value; 331 332 if (dropSupport != null) { 333 dropSupport.setDropTargetPopupAllowed(value); 334 } 335 } 336 337 boolean isDropTargetPopupAllowed() { 338 return (dropSupport != null) ? dropSupport.isDropTargetPopupAllowed() : dropTargetPopupAllowed; 339 } 340 341 344 public boolean isDefaultActionEnabled() { 345 return defaultActionEnabled; 346 } 347 348 349 public void requestFocus() { 350 tree.requestFocus(); 351 } 352 353 354 public boolean requestFocusInWindow() { 355 return tree.requestFocusInWindow(); 356 } 357 358 362 public void setDefaultActionAllowed(boolean value) { 363 defaultActionEnabled = value; 364 365 if (value) { 366 tree.registerKeyboardAction( 367 defaultActionListener, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), JComponent.WHEN_FOCUSED 368 ); 369 } else { 370 tree.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false)); 372 } 373 } 374 375 380 public boolean isRootVisible() { 381 return tree.isRootVisible(); 382 } 383 384 389 public void setRootVisible(boolean visible) { 390 tree.setRootVisible(visible); 391 tree.setShowsRootHandles(!visible); 392 } 393 394 395 399 public boolean isDragSource() { 400 return dragActive; 401 } 402 403 406 public void setDragSource(boolean state) { 407 if (state && (dragSupport == null)) { 409 dragSupport = new TreeViewDragSupport(this, tree); 410 } 411 412 dragActive = state; 414 415 if (dragSupport != null) { 416 dragSupport.activate(dragActive); 417 } 418 } 419 420 424 public boolean isDropTarget() { 425 return dropActive; 426 } 427 428 432 public void setDropTarget(boolean state) { 433 if (dropActive && (dropSupport == null)) { 435 dropSupport = new TreeViewDropSupport(this, tree, dropTargetPopupAllowed); 436 } 437 438 dropActive = state; 440 441 if (dropSupport != null) { 442 dropSupport.activate(dropActive); 443 } 444 } 445 446 451 public int getAllowedDragActions() { 452 return allowedDragActions; 453 } 454 455 458 public void setAllowedDragActions(int actions) { 459 allowedDragActions = actions; 461 } 462 463 468 public int getAllowedDropActions() { 469 return allowedDropActions; 470 } 471 472 475 public void setAllowedDropActions(int actions) { 476 allowedDropActions = actions; 478 } 479 480 484 488 public void collapseNode(Node n) { 489 if (n == null) { 490 throw new IllegalArgumentException (); 491 } 492 493 TreePath treePath = new TreePath (treeModel.getPathToRoot(VisualizerNode.getVisualizer(null, n))); 494 tree.collapsePath(treePath); 495 } 496 497 501 public void expandNode(Node n) { 502 if (n == null) { 503 throw new IllegalArgumentException (); 504 } 505 506 lookupExplorerManager(); 507 508 TreePath treePath = new TreePath (treeModel.getPathToRoot(VisualizerNode.getVisualizer(null, n))); 509 510 tree.expandPath(treePath); 511 } 512 513 517 public boolean isExpanded(Node n) { 518 TreePath treePath = new TreePath (treeModel.getPathToRoot(VisualizerNode.getVisualizer(null, n))); 519 520 return tree.isExpanded(treePath); 521 } 522 523 525 public void expandAll() { 526 int i = 0; 527 int j ; 528 529 do { 530 do { 531 j = tree.getRowCount(); 532 tree.expandRow(i); 533 } while (j != tree.getRowCount()); 534 535 i++; 536 } while (i < tree.getRowCount()); 537 } 538 539 543 public void validate() { 544 Children.MUTEX.readAccess(new Runnable () { 545 public void run() { 546 TreeView.super.validate(); 547 } 548 }); 549 } 550 551 553 public void addNotify() { 554 super.addNotify(); 555 lookupExplorerManager(); 556 } 557 558 560 private void lookupExplorerManager() { 561 ExplorerManager newManager = ExplorerManager.find(TreeView.this); 563 564 if (newManager != manager) { 565 if (manager != null) { 566 manager.removeVetoableChangeListener(wlvc); 567 manager.removePropertyChangeListener(wlpc); 568 } 569 570 manager = newManager; 571 572 manager.addVetoableChangeListener(wlvc = WeakListeners.vetoableChange(managerListener, manager)); 573 manager.addPropertyChangeListener(wlpc = WeakListeners.propertyChange(managerListener, manager)); 574 575 synchronizeRootContext(); 576 synchronizeExploredContext(); 577 synchronizeSelectedNodes(); 578 } 579 580 tree.getSelectionModel().removeTreeSelectionListener(managerListener); 584 tree.getSelectionModel().addTreeSelectionListener(managerListener); 585 } 586 587 589 public void removeNotify() { 590 super.removeNotify(); 591 592 tree.getSelectionModel().removeTreeSelectionListener(managerListener); 593 } 594 595 599 602 protected abstract NodeTreeModel createModel(); 603 604 612 protected abstract void selectionChanged(Node[] nodes, ExplorerManager em) 613 throws PropertyVetoException ; 614 615 622 protected abstract boolean selectionAccept(Node[] nodes); 623 624 629 protected abstract void showPath(TreePath path); 630 631 635 protected abstract void showSelection(TreePath [] paths); 636 637 643 protected boolean useExploredContextMenu() { 644 return false; 645 } 646 647 650 private boolean isSelectionModeBroken(Node[] nodes) { 651 if ((nodes.length <= 1) || (getSelectionMode() == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)) { 654 return false; 655 } 656 657 if (getSelectionMode() == TreeSelectionModel.SINGLE_TREE_SELECTION) { 660 return true; 661 } 662 663 TreePath [] paths = new TreePath [nodes.length]; 665 RowMapper rowMapper = tree.getSelectionModel().getRowMapper(); 666 667 if (rowMapper == null) { 669 return false; 670 } 671 672 ArrayList <Node> toBeExpaned = new ArrayList <Node>(3); 673 674 for (int i = 0; i < nodes.length; i++) { 675 toBeExpaned.clear(); 676 677 Node n = nodes[i]; 678 679 while (n.getParentNode() != null) { 680 if (!isExpanded(n)) { 681 toBeExpaned.add(n); 682 } 683 684 n = n.getParentNode(); 685 } 686 687 for (int j = toBeExpaned.size() - 1; j >= 0; j--) { 688 expandNode((Node) toBeExpaned.get(j)); 689 } 690 691 TreePath treePath = new TreePath (treeModel.getPathToRoot(VisualizerNode.getVisualizer(null, nodes[i]))); 692 paths[i] = treePath; 693 } 694 695 int[] rows = rowMapper.getRowsForPaths(paths); 696 697 Arrays.sort(rows); 699 700 for (int i = 1; i < rows.length; i++) { 701 if (rows[i] != (rows[i - 1] + 1)) { 702 return true; 703 } 704 } 705 706 return false; 708 } 709 710 714 716 final void callSelectionChanged(Node[] nodes) { 717 manager.removePropertyChangeListener(wlpc); 718 manager.removeVetoableChangeListener(wlvc); 719 720 try { 721 selectionChanged(nodes, manager); 722 } catch (PropertyVetoException e) { 723 synchronizeSelectedNodes(); 724 } finally { 725 manager.addPropertyChangeListener(wlpc); 726 manager.addVetoableChangeListener(wlvc); 727 } 728 } 729 730 732 final void synchronizeRootContext() { 733 treeModel.setNode(manager.getRootContext()); 734 } 735 736 738 final void synchronizeExploredContext() { 739 Node n = manager.getExploredContext(); 740 741 if (n != null) { 742 TreePath treePath = new TreePath (treeModel.getPathToRoot(VisualizerNode.getVisualizer(null, n))); 743 showPath(treePath); 744 } 745 } 746 747 761 public void setSelectionMode(int mode) { 762 tree.getSelectionModel().setSelectionMode(mode); 763 } 764 765 772 public int getSelectionMode() { 773 return tree.getSelectionModel().getSelectionMode(); 774 } 775 776 private void showWaitCursor() { 780 if (getRootPane() == null) { 781 return; 782 } 783 784 contentPane = getRootPane().getContentPane(); 785 786 if (SwingUtilities.isEventDispatchThread()) { 787 contentPane.setCursor(Utilities.createProgressCursor(contentPane)); 788 } else { 789 SwingUtilities.invokeLater(new CursorR(contentPane, Utilities.createProgressCursor(contentPane))); 790 } 791 } 792 793 private void showNormalCursor() { 794 if (contentPane == null) { 795 return; 796 } 797 798 if (SwingUtilities.isEventDispatchThread()) { 799 contentPane.setCursor(null); 800 } else { 801 SwingUtilities.invokeLater(new CursorR(contentPane, null)); 802 } 803 } 804 805 private void prepareWaitCursor(final Node node) { 806 if (node == null) { 808 showNormalCursor(); 809 } 810 811 showWaitCursor(); 812 RequestProcessor.getDefault().post(new Runnable () { 813 814 public void run() { 815 try { 816 node.getChildren().getNodes(true); 817 } 818 catch (Exception e) { 819 Logger.getLogger(TreeView.class.getName()).log(Level.WARNING, 821 null, e); 822 } 823 finally { 824 showNormalCursor(); 826 } 827 } 828 }); 829 } 830 831 834 final void synchronizeSelectedNodes() { 835 VisualizerNode.runQueue(); 837 838 Node[] arr = manager.getSelectedNodes(); 839 TreePath [] paths = new TreePath [arr.length]; 840 841 for (int i = 0; i < arr.length; i++) { 842 TreePath treePath = new TreePath (treeModel.getPathToRoot(VisualizerNode.getVisualizer(null, arr[i]))); 843 paths[i] = treePath; 844 } 845 846 tree.getSelectionModel().removeTreeSelectionListener(managerListener); 847 showSelection(paths); 848 tree.getSelectionModel().addTreeSelectionListener(managerListener); 849 } 850 851 void scrollTreeToVisible(TreePath path, TreeNode child) { 852 Rectangle base = tree.getVisibleRect(); 853 Rectangle b1 = tree.getPathBounds(path); 854 Rectangle b2 = tree.getPathBounds(new TreePath (treeModel.getPathToRoot(child))); 855 856 if ((base != null) && (b1 != null) && (b2 != null)) { 857 tree.scrollRectToVisible(new Rectangle (base.x, b1.y, 1, b2.y - b1.y + b2.height)); 858 } 859 } 860 861 private void createPopup(int xpos, int ypos, JPopupMenu popup) { 862 if (popup.getSubElements().length > 0) { 863 popup.show(TreeView.this, xpos, ypos); 864 } 865 } 866 867 void createPopup(int xpos, int ypos) { 868 if (isPopupAllowed()) { 870 Node[] arr = manager.getSelectedNodes(); 871 872 if (arr.length == 0) { 873 arr = new Node[] { manager.getRootContext() }; 876 877 try { 878 manager.setSelectedNodes(arr); 879 } catch (PropertyVetoException e) { 880 assert false : e; } 882 } 883 884 Action[] actions = NodeOp.findActions(arr); 885 886 if (actions.length > 0) { 887 createPopup(xpos, ypos, Utilities.actionsToPopup(actions, this)); 888 } 889 } 890 } 891 892 894 void createExtendedPopup(int xpos, int ypos, JMenu newMenu) { 895 Node[] ns = manager.getSelectedNodes(); 896 JPopupMenu popup = null; 897 898 if (ns.length > 0) { 899 Action[] actions = NodeOp.findActions(ns); 901 popup = Utilities.actionsToPopup(actions, this); 902 } else { 903 if (manager.getRootContext() != null) { 905 popup = manager.getRootContext().getContextMenu(); 906 } 907 } 908 909 int cnt = 0; 910 911 if (popup == null) { 912 popup = SystemAction.createPopupMenu(new SystemAction[] { }); 913 } 914 915 popup.add(newMenu); 916 917 createPopup(xpos, ypos, popup); 918 } 919 920 923 Point getPositionForPopup() { 924 int i = tree.getLeadSelectionRow(); 925 926 if (i < 0) { 927 return null; 928 } 929 930 Rectangle rect = tree.getRowBounds(i); 931 932 if (rect == null) { 933 return null; 934 } 935 936 Point p = new Point (rect.x, rect.y); 937 938 p = SwingUtilities.convertPoint(tree, p, TreeView.this); 940 941 return p; 942 } 943 944 static Action takeAction(Action action, Node node) { 945 if (action instanceof ContextAwareAction) { 947 Lookup contextLookup = node.getLookup(); 948 Lookup.Result<Node> res = contextLookup.lookup(new Lookup.Template<Node>(Node.class)); 949 950 Iterator it = res.allInstances().iterator(); 952 953 boolean add = true; 955 956 while (it.hasNext() && add) { 957 add = !node.equals(it.next()); 958 } 959 960 if (add) { 961 contextLookup = new ProxyLookup(new Lookup[] { Lookups.singleton(node), node.getLookup() }); 962 } 963 964 Action contextInstance = ((ContextAwareAction) action).createContextAwareInstance(contextLookup); 965 assert contextInstance != action : "Cannot be same. ContextAwareAction: " + action + 966 ", ContextAwareInstance: " + contextInstance; 967 action = contextInstance; 968 } 969 970 return action; 971 } 972 973 978 final static TreePath findSiblingTreePath(TreePath parentPath, int[] childIndices) { 979 if (childIndices == null) { 980 throw new IllegalArgumentException ("Indexes of changed children are null."); } 982 983 if (parentPath == null) { 984 throw new IllegalArgumentException ("The tree path to parent is null."); } 986 987 if (childIndices.length == 0) { 989 return null; 990 } 991 992 TreeNode parent = (TreeNode ) parentPath.getLastPathComponent(); 993 Object [] parentPaths = parentPath.getPath(); 994 TreePath newSelection = null; 995 996 int childCount = parent.getChildCount(); 997 if (childCount > 0) { 998 int childPathLength = parentPaths.length + 1; 1000 Object [] childPath = new Object [childPathLength]; 1001 System.arraycopy(parentPaths, 0, childPath, 0, parentPaths.length); 1002 1003 int selectedChild = Math.min(childIndices[0], childCount-1); 1004 1005 childPath[childPathLength - 1] = parent.getChildAt(selectedChild); 1006 newSelection = new TreePath (childPath); 1007 } else { 1008 newSelection = new TreePath (parentPaths); 1010 } 1011 1012 return newSelection; 1013 } 1014 1015 void removedNodes(List <VisualizerNode> removed) { 1017 TreeSelectionModel sm = tree.getSelectionModel(); 1018 TreePath [] selPaths = (sm != null) ? sm.getSelectionPaths() : null; 1019 if (selPaths == null) return; 1020 1021 List <TreePath > remSel = null; 1022 for (VisualizerNode vn : removed) { 1023 TreePath path = new TreePath (treeModel.getPathToRoot(vn)); 1024 for(TreePath tp : selPaths) { 1025 if (path.isDescendant(tp)) { 1026 if (remSel == null) remSel = new ArrayList (); 1027 remSel.add(tp); 1028 } 1029 } 1030 } 1031 1032 if (remSel != null) { 1033 sm.removeSelectionPaths(remSel.toArray(new TreePath [remSel.size()])); 1034 } 1035 } 1036 1037 private static class CursorR implements Runnable { 1038 private Container contentPane; 1039 private Cursor c; 1040 1041 private CursorR(Container cont, Cursor c) { 1042 contentPane = cont; 1043 this.c = c; 1044 } 1045 1046 public void run() { 1047 contentPane.setCursor(c); 1048 } 1049 } 1050 1051 1052 class TreePropertyListener implements VetoableChangeListener , PropertyChangeListener , TreeExpansionListener , 1053 TreeWillExpandListener , TreeSelectionListener , Runnable { 1054 private RequestProcessor.Task scheduled; 1055 private TreePath [] readAccessPaths; 1056 1057 TreePropertyListener() { 1058 } 1059 1060 public void vetoableChange(PropertyChangeEvent evt) 1061 throws PropertyVetoException { 1062 if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { 1063 Node[] nodes = (Node[]) evt.getNewValue(); 1065 1066 if (isSelectionModeBroken(nodes)) { 1067 throw new PropertyVetoException ( 1068 "selection mode " + getSelectionMode() + " broken by " + Arrays.asList(nodes), evt 1069 ); } 1071 1072 if (!selectionAccept(nodes)) { 1073 throw new PropertyVetoException ("selection " + Arrays.asList(nodes) + " rejected", evt); } 1075 } 1076 } 1077 1078 public final void propertyChange(final PropertyChangeEvent evt) { 1079 if (manager == null) { 1080 return; } 1082 1083 if (evt.getPropertyName().equals(ExplorerManager.PROP_ROOT_CONTEXT)) { 1084 synchronizeRootContext(); 1085 } 1086 1087 if (evt.getPropertyName().equals(ExplorerManager.PROP_EXPLORED_CONTEXT)) { 1088 synchronizeExploredContext(); 1089 } 1090 1091 if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { 1092 synchronizeSelectedNodes(); 1093 } 1094 } 1095 1096 public synchronized void treeExpanded(TreeExpansionEvent ev) { 1097 1098 if (!tree.getScrollsOnExpand()) { 1099 return; 1100 } 1101 1102 RequestProcessor.Task t = scheduled; 1103 1104 if (t != null) { 1105 t.cancel(); 1106 } 1107 1108 class Request implements Runnable { 1109 private TreePath path; 1110 1111 public Request(TreePath path) { 1112 this.path = path; 1113 } 1114 1115 public void run() { 1116 if (!SwingUtilities.isEventDispatchThread()) { 1117 SwingUtilities.invokeLater(this); 1118 1119 return; 1120 } 1121 1122 try { 1123 if (!tree.isVisible(path)) { 1124 return; 1126 } 1127 1128 if (treeModel == null) { 1129 return; 1131 } 1132 1133 TreeNode myNode = (TreeNode ) path.getLastPathComponent(); 1134 1135 if (treeModel.getPathToRoot(myNode)[0] != treeModel.getRoot()) { 1136 return; 1141 } 1142 1143 int lastChildIndex = myNode.getChildCount() - 1; 1146 1147 if (lastChildIndex >= 0) { 1148 TreeNode lastChild = myNode.getChildAt(lastChildIndex); 1149 1150 Rectangle base = tree.getVisibleRect(); 1151 Rectangle b1 = tree.getPathBounds(path); 1152 Rectangle b2 = tree.getPathBounds(new TreePath (treeModel.getPathToRoot(lastChild))); 1153 1154 if ((base != null) && (b1 != null) && (b2 != null)) { 1155 tree.scrollRectToVisible(new Rectangle (base.x, b1.y, 1, b2.y - b1.y + b2.height)); 1156 } 1157 1158 } 1160 } finally { 1161 path = null; 1162 } 1163 } 1164 } 1165 1166 scheduled = RequestProcessor.getDefault().post(new Request(ev.getPath()), 250); } 1170 1171 public synchronized void treeCollapsed(final TreeExpansionEvent ev) { 1172 showNormalCursor(); 1173 class Request implements Runnable { 1174 private TreePath path; 1175 1176 public Request(TreePath path) { 1177 this.path = path; 1178 } 1179 1180 public void run() { 1181 if (!SwingUtilities.isEventDispatchThread()) { 1182 SwingUtilities.invokeLater(this); 1183 1184 return; 1185 } 1186 1187 try { 1188 if (tree.isExpanded(path)) { 1189 return; 1192 } 1193 1194 if (!tree.isVisible(path)) { 1195 return; 1198 } 1199 1200 if (treeModel == null) { 1201 return; 1203 } 1204 1205 TreeNode myNode = (TreeNode ) path.getLastPathComponent(); 1206 1207 if (treeModel.getPathToRoot(myNode)[0] != treeModel.getRoot()) { 1208 return; 1213 } 1214 1215 treeModel.nodeStructureChanged(myNode); 1216 } finally { 1217 this.path = null; 1218 } 1219 } 1220 } 1221 1222 RequestProcessor.getDefault().post(new Request(ev.getPath()), TIME_TO_COLLAPSE); 1226 } 1227 1228 1231 public void valueChanged(TreeSelectionEvent ev) { 1232 TreePath [] paths = tree.getSelectionPaths(); 1233 storeSelectedPaths = Arrays.asList((paths == null) ? new TreePath [0] : paths); 1234 1235 if (paths == null) { 1236 if (ExplorerDnDManager.getDefault().isDnDActive()) { 1238 return; 1239 } 1240 1241 callSelectionChanged(new Node[0]); 1242 } else { 1243 readAccessPaths = paths; 1248 Children.MUTEX.postReadRequest(this); 1249 } 1250 } 1251 1252 1254 public void run() { 1255 if (readAccessPaths == null) { 1256 return; 1257 } 1258 1259 TreePath [] paths = readAccessPaths; 1260 1261 readAccessPaths = null; 1267 1268 java.util.List <Node> ll = new java.util.ArrayList <Node>(paths.length); 1269 1270 for (int i = 0; i < paths.length; i++) { 1271 Node n = Visualizer.findNode(paths[i].getLastPathComponent()); 1272 1273 if( isUnderRoot( manager.getRootContext(), n ) ) { 1274 ll.add(n); 1275 } 1276 } 1277 callSelectionChanged(ll.toArray(new Node[ll.size()])); 1278 } 1279 1280 1283 private boolean isUnderRoot(Node rootContext, Node node) { 1284 while (node != null) { 1285 if (node.equals(rootContext)) { 1286 return true; 1287 } 1288 1289 node = node.getParentNode(); 1290 } 1291 1292 return false; 1293 } 1294 1295 public void treeWillCollapse(TreeExpansionEvent event) 1296 throws ExpandVetoException { 1297 } 1298 1299 public void treeWillExpand(TreeExpansionEvent event) 1300 throws ExpandVetoException { 1301 TreePath path = event.getPath(); 1303 prepareWaitCursor(DragDropUtilities.secureFindNode(path.getLastPathComponent())); 1304 } 1305 } 1306 1308 1310 class PopupAdapter extends MouseUtils.PopupMouseAdapter { 1311 PopupAdapter() { 1312 } 1313 1314 protected void showPopup(MouseEvent e) { 1315 int selRow = tree.getRowForLocation(e.getX(), e.getY()); 1316 1317 if ((selRow == -1) && !isRootVisible()) { 1318 try { 1320 manager.setSelectedNodes(new Node[] { manager.getRootContext() }); 1321 } catch (PropertyVetoException exc) { 1322 assert false : exc; } 1324 } else if (!tree.isRowSelected(selRow)) { 1325 tree.setSelectionRow(selRow); 1328 } 1329 1330 if ((selRow != -1) || !isRootVisible()) { 1331 Point p = SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), TreeView.this); 1332 1333 createPopup((int) p.getX(), (int) p.getY()); 1334 } 1335 } 1336 } 1337 1338 final class PopupSupport extends MouseAdapter implements Runnable , FocusListener , ActionListener { 1339 public final Action popup = new AbstractAction () { 1340 public void actionPerformed(ActionEvent evt) { 1341 SwingUtilities.invokeLater(PopupSupport.this); 1342 } 1343 1344 1350 public boolean isEnabled() { 1351 return TreeView.this.isFocusOwner() || tree.isFocusOwner(); 1352 } 1353 }; 1354 1355 public void run() { 1357 Point p = getPositionForPopup(); 1358 1359 if (p == null) { 1360 p = new Point (0, 0); 1362 } 1363 1364 createPopup(p.x, p.y); 1365 } 1366 1367 public void focusGained(java.awt.event.FocusEvent ev) { 1368 ev.getComponent().removeFocusListener(this); 1370 1371 if (DragDropUtilities.dragAndDropEnabled && dragActive) { 1373 setDragSource(true); 1374 1375 } 1377 } 1378 1379 public void focusLost(FocusEvent ev) { 1380 } 1381 1382 1383 public void mouseClicked(MouseEvent e) { 1384 int selRow = tree.getRowForLocation(e.getX(), e.getY()); 1385 1386 if ((selRow != -1) && SwingUtilities.isLeftMouseButton(e) && MouseUtils.isDoubleClick(e)) { 1387 if (defaultActionEnabled) { 1389 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); 1390 Node node = Visualizer.findNode(selPath.getLastPathComponent()); 1391 1392 Action a = takeAction(node.getPreferredAction(), node); 1393 1394 if (a != null) { 1395 if (a.isEnabled()) { 1396 a.actionPerformed(new ActionEvent (node, ActionEvent.ACTION_PERFORMED, "")); } else { 1398 Toolkit.getDefaultToolkit().beep(); 1399 } 1400 1401 e.consume(); 1402 1403 return; 1404 } 1405 } 1406 1407 if (tree.isExpanded(selRow)) { 1408 tree.collapseRow(selRow); 1409 } else { 1410 tree.expandRow(selRow); 1411 } 1412 } 1413 } 1414 1415 1416 public void actionPerformed(ActionEvent evt) { 1417 Node[] nodes = manager.getSelectedNodes(); 1418 1419 if (nodes.length == 1) { 1420 Action a = takeAction(nodes[0].getPreferredAction(), nodes[0]); 1421 1422 if (a != null) { 1423 if (a.isEnabled()) { 1424 a.actionPerformed(new ActionEvent (nodes[0], ActionEvent.ACTION_PERFORMED, "")); } else { 1426 Toolkit.getDefaultToolkit().beep(); 1427 } 1428 } 1429 } 1430 } 1431 } 1432 1433 private final class ExplorerTree extends JTree implements Autoscroll { 1434 AutoscrollSupport support; 1435 private String maxPrefix; 1436 int SEARCH_FIELD_PREFERRED_SIZE = 160; 1437 int SEARCH_FIELD_SPACE = 3; 1438 private boolean firstPaint = true; 1439 1440 private JTextField searchTextField = new JTextField () { 1442 public boolean isManagingFocus() { 1443 return true; 1444 } 1445 1446 public void processKeyEvent(KeyEvent ke) { 1447 if (ke.getKeyCode() == ke.VK_ESCAPE) { 1451 removeSearchField(); 1452 ke.consume(); 1453 1454 SwingUtilities.invokeLater( 1456 new Runnable () { 1457 public void run() { 1463 ExplorerTree.this.requestFocus(); 1464 } 1465 } 1466 ); 1467 } else { 1468 super.processKeyEvent(ke); 1469 } 1470 } 1471 }; 1472 1473 private JPanel searchpanel = null; 1474 final private int heightOfTextField = searchTextField.getPreferredSize().height; 1475 private int originalScrollMode; 1476 1477 ExplorerTree(TreeModel model) { 1478 super(model); 1479 toggleClickCount = 0; 1480 1481 getInputMap().put(KeyStroke.getKeyStroke("control C"), "none"); getInputMap().put(KeyStroke.getKeyStroke("control V"), "none"); getInputMap().put(KeyStroke.getKeyStroke("control X"), "none"); getInputMap().put(KeyStroke.getKeyStroke("COPY"), "none"); getInputMap().put(KeyStroke.getKeyStroke("PASTE"), "none"); getInputMap().put(KeyStroke.getKeyStroke("CUT"), "none"); 1493 if (Utilities.isMac()) { 1494 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.META_MASK), "none"); getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.META_MASK), "none"); getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.META_MASK), "none"); } 1498 1499 setupSearch(); 1500 1501 setDragEnabled( true ); 1502 } 1503 1504 public void addNotify() { 1505 super.addNotify(); 1506 ViewTooltips.register(this); 1507 } 1508 1509 public void removeNotify() { 1510 super.removeNotify(); 1511 ViewTooltips.unregister(this); 1512 } 1513 1514 public void updateUI() { 1515 super.updateUI(); 1516 setBorder(BorderFactory.createEmptyBorder()); 1517 if( getTransferHandler() != null && getTransferHandler() instanceof UIResource ) { 1518 setTransferHandler( new DummyTransferHandler() ); 1521 } 1522 } 1523 1524 private void calcRowHeight(Graphics g) { 1525 int height = Math.max(18, 2 + g.getFontMetrics(getFont()).getHeight()); 1526 1527 String s = System.getProperty("nb.cellrenderer.fixedheight"); 1530 if (s != null) { 1531 try { 1532 height = Integer.parseInt(s); 1533 } catch (Exception e) { 1534 } 1536 } 1537 1538 if (getRowHeight() != height) { 1539 setRowHeight(height); 1540 } else { 1541 revalidate(); 1542 repaint(); 1543 } 1544 } 1545 1546 public void paint(final Graphics g) { 1551 new GuardedActions(0, g); 1552 } 1553 1554 protected void validateTree() { 1555 new GuardedActions(1, null); 1556 } 1557 1558 public void doLayout() { 1559 new GuardedActions(2, null); 1560 } 1561 1562 private void guardedPaint(Graphics g) { 1563 if (firstPaint) { 1564 firstPaint = false; 1565 calcRowHeight(g); 1566 1567 g.setColor(getBackground()); 1570 g.fillRect(0, 0, getWidth(), getHeight()); 1571 1572 return; 1573 } 1574 1575 ExplorerTree.super.paint(g); 1576 } 1577 1578 private void guardedValidateTree() { 1579 super.validateTree(); 1580 } 1581 1582 private void guardedDoLayout() { 1583 super.doLayout(); 1584 1585 Rectangle visibleRect = getVisibleRect(); 1586 1587 if ((searchpanel != null) && searchpanel.isDisplayable()) { 1588 int width = Math.min( 1589 getPreferredSize().width - (SEARCH_FIELD_SPACE * 2), 1590 SEARCH_FIELD_PREFERRED_SIZE - SEARCH_FIELD_SPACE 1591 ); 1592 1593 searchpanel.setBounds( 1594 Math.max(SEARCH_FIELD_SPACE, (visibleRect.x + visibleRect.width) - width), 1595 visibleRect.y + SEARCH_FIELD_SPACE, Math.min(visibleRect.width, width) - SEARCH_FIELD_SPACE, 1596 heightOfTextField 1597 ); 1598 } 1599 } 1600 1601 public void setFont(Font f) { 1602 if (f != getFont()) { 1603 firstPaint = true; 1604 super.setFont(f); 1605 } 1606 } 1607 1608 protected void processFocusEvent(FocusEvent fe) { 1609 super.processFocusEvent(fe); 1610 1611 new GuardedActions(3, null); 1615 } 1616 1617 private void repaintSelection() { 1618 int first = getSelectionModel().getMinSelectionRow(); 1619 int last = getSelectionModel().getMaxSelectionRow(); 1620 1621 if (first != -1) { 1622 if (first == last) { 1623 Rectangle r = getRowBounds(first); 1624 repaint(r.x, r.y, r.width, r.height); 1625 } else { 1626 Rectangle top = getRowBounds(first); 1627 Rectangle bottom = getRowBounds(last); 1628 Rectangle r = new Rectangle (); 1629 r.x = Math.min(top.x, bottom.x); 1630 r.y = top.y; 1631 r.width = getWidth(); 1632 r.height = (bottom.y + bottom.height) - top.y; 1633 repaint(r.x, r.y, r.width, r.height); 1634 } 1635 } 1636 } 1637 1638 private void prepareSearchPanel() { 1639 if (searchpanel == null) { 1640 searchpanel = new JPanel (); 1641 1642 JLabel lbl = new JLabel (NbBundle.getMessage(TreeView.class, "LBL_QUICKSEARCH")); searchpanel.setLayout(new BoxLayout (searchpanel, BoxLayout.X_AXIS)); 1644 searchpanel.add(lbl); 1645 searchpanel.add(searchTextField); 1646 lbl.setLabelFor(searchTextField); 1647 searchpanel.setBorder(BorderFactory.createRaisedBevelBorder()); 1648 lbl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); 1649 } 1650 } 1651 1652 private void setupSearch() { 1653 KeyListener [] keyListeners = getListeners(KeyListener .class); 1655 1656 for (int i = 0; i < keyListeners.length; i++) { 1657 removeKeyListener(keyListeners[i]); 1658 } 1659 1660 addKeyListener( 1662 new KeyAdapter () { 1663 public void keyTyped(KeyEvent e) { 1664 int modifiers = e.getModifiers(); 1665 int keyCode = e.getKeyCode(); 1666 char c = e.getKeyChar(); 1667 1668 if ((c == '+') || (c == '-')) return; 1670 1671 if (((modifiers > 0) && (modifiers != KeyEvent.SHIFT_MASK)) || e.isActionKey()) { 1672 return; 1673 } 1674 1675 if (Character.isISOControl(c) || 1676 (keyCode == KeyEvent.VK_SHIFT) || 1677 (keyCode == KeyEvent.VK_ESCAPE)) return; 1678 1679 final KeyStroke stroke = KeyStroke.getKeyStrokeForEvent(e); 1680 searchTextField.setText(String.valueOf(stroke.getKeyChar())); 1681 1682 displaySearchField(); 1683 e.consume(); 1684 } 1685 } 1686 ); 1687 1688 SearchFieldListener searchFieldListener = new SearchFieldListener(); 1693 searchTextField.addKeyListener(searchFieldListener); 1694 searchTextField.addFocusListener(searchFieldListener); 1695 searchTextField.getDocument().addDocumentListener(searchFieldListener); 1696 } 1697 1698 private List <TreePath > doSearch(String prefix) { 1699 List <TreePath > results = new ArrayList <TreePath >(); 1700 1701 int[] rows = getSelectionRows(); 1703 int startIndex = ((rows == null) || (rows.length == 0)) ? 0 : rows[0]; 1704 1705 int size = getRowCount(); 1706 1707 if (size == 0) { 1708 return results; 1710 } 1711 1712 while (true) { 1713 startIndex = startIndex % size; 1714 1715 TreePath path = getNextMatch(prefix, startIndex, Position.Bias.Forward); 1716 1717 if ((path != null) && !results.contains(path)) { 1718 startIndex = tree.getRowForPath(path); 1719 results.add(path); 1720 1721 String elementName = ((VisualizerNode) path.getLastPathComponent()).getDisplayName(); 1722 1723 if (maxPrefix == null) { 1725 maxPrefix = elementName; 1726 } 1727 1728 maxPrefix = findMaxPrefix(maxPrefix, elementName); 1729 1730 startIndex++; 1732 } else { 1733 break; 1734 } 1735 } 1736 1737 return results; 1738 } 1739 1740 private String findMaxPrefix(String str1, String str2) { 1741 String res = null; 1742 1743 for (int i = 0; str1.regionMatches(true, 0, str2, 0, i); i++) { 1744 res = str1.substring(0, i); 1745 } 1746 1747 return res; 1748 } 1749 1750 1753 private void displaySearchField() { 1754 if (!searchTextField.isDisplayable()) { 1755 JViewport viewport = TreeView.this.getViewport(); 1756 originalScrollMode = viewport.getScrollMode(); 1757 viewport.setScrollMode(JViewport.SIMPLE_SCROLL_MODE); 1758 searchTextField.setFont(ExplorerTree.this.getFont()); 1759 prepareSearchPanel(); 1760 add(searchpanel); 1761 revalidate(); 1762 repaint(); 1763 1764 SwingUtilities.invokeLater( 1766 new Runnable () { 1767 public void run() { 1768 searchTextField.requestFocus(); 1769 } 1770 } 1771 ); 1772 } 1773 } 1774 1775 1778 private void removeSearchField() { 1779 if (searchpanel.isDisplayable()) { 1780 remove(searchpanel); 1781 TreeView.this.getViewport().setScrollMode(originalScrollMode); 1782 1783 Rectangle r = searchpanel.getBounds(); 1784 this.repaint(r); 1785 } 1786 } 1787 1788 1789 public void autoscroll(Point cursorLoc) { 1790 getSupport().autoscroll(cursorLoc); 1791 } 1792 1793 1797 public Insets getAutoscrollInsets() { 1798 return getSupport().getAutoscrollInsets(); 1799 } 1800 1801 1802 AutoscrollSupport getSupport() { 1803 if (support == null) { 1804 support = new AutoscrollSupport(this, new Insets (15, 10, 15, 10)); 1805 } 1806 1807 return support; 1808 } 1809 1810 public String getToolTipText(MouseEvent event) { 1811 if (event != null) { 1812 Point p = event.getPoint(); 1813 int selRow = getRowForLocation(p.x, p.y); 1814 1815 if (selRow != -1) { 1816 TreePath path = getPathForRow(selRow); 1817 VisualizerNode v = (VisualizerNode) path.getLastPathComponent(); 1818 String tooltip = v.getShortDescription(); 1819 String displayName = v.getDisplayName(); 1820 1821 if ((tooltip != null) && !tooltip.equals(displayName)) { 1822 return tooltip; 1823 } 1824 } 1825 } 1826 1827 return null; 1828 } 1829 1830 protected TreeModelListener createTreeModelListener() { 1831 return new ModelHandler(); 1832 } 1833 1834 public AccessibleContext getAccessibleContext() { 1835 if (accessibleContext == null) { 1836 accessibleContext = new AccessibleExplorerTree(); 1837 } 1838 1839 return accessibleContext; 1840 } 1841 1842 private class GuardedActions implements Mutex.Action<Void > { 1843 private int type; 1844 private Object p1; 1845 1846 public GuardedActions(int type, Object p1) { 1847 this.type = type; 1848 this.p1 = p1; 1849 Children.MUTEX.readAccess(this); 1850 } 1851 1852 public Void run() { 1853 switch (type) { 1854 case 0: 1855 guardedPaint((Graphics ) p1); 1856 1857 break; 1858 1859 case 1: 1860 guardedValidateTree(); 1861 1862 break; 1863 1864 case 2: 1865 guardedDoLayout(); 1866 1867 break; 1868 1869 case 3: 1870 repaintSelection(); 1871 1872 break; 1873 1874 default: 1875 throw new IllegalStateException ("type: " + type); 1876 } 1877 1878 return null; 1879 } 1880 } 1881 1882 private class SearchFieldListener extends KeyAdapter implements DocumentListener , FocusListener { 1883 1884 private List <TreePath > results = new ArrayList <TreePath >(); 1885 1886 1887 private int currentSelectionIndex; 1888 1889 SearchFieldListener() { 1890 } 1891 1892 public void changedUpdate(DocumentEvent e) { 1893 searchForNode(); 1894 } 1895 1896 public void insertUpdate(DocumentEvent e) { 1897 searchForNode(); 1898 } 1899 1900 public void removeUpdate(DocumentEvent e) { 1901 searchForNode(); 1902 } 1903 1904 public void keyPressed(KeyEvent e) { 1905 int keyCode = e.getKeyCode(); 1906 1907 if (keyCode == KeyEvent.VK_ESCAPE) { 1908 removeSearchField(); 1909 ExplorerTree.this.requestFocus(); 1910 } else if (keyCode == KeyEvent.VK_UP) { 1911 currentSelectionIndex--; 1912 displaySearchResult(); 1913 1914 e.consume(); 1917 } else if (keyCode == KeyEvent.VK_DOWN) { 1918 currentSelectionIndex++; 1919 displaySearchResult(); 1920 1921 e.consume(); 1924 } else if (keyCode == KeyEvent.VK_TAB) { 1925 if (maxPrefix != null) { 1926 searchTextField.setText(maxPrefix); 1927 } 1928 1929 e.consume(); 1930 } else if (keyCode == KeyEvent.VK_ENTER) { 1931 removeSearchField(); 1932 1933 TreePath selectedTPath = getSelectionPath(); 1935 1936 if (selectedTPath != null) { 1937 TreeNode selectedTNode = (TreeNode ) selectedTPath.getLastPathComponent(); 1938 Node selectedNode = Visualizer.findNode(selectedTNode); 1939 1940 if ( 1941 (selectedNode.getPreferredAction() != null) && 1942 selectedNode.getPreferredAction().isEnabled() 1943 ) { 1944 selectedNode.getPreferredAction().actionPerformed( 1945 new ActionEvent (this, ActionEvent.ACTION_PERFORMED, "") 1946 ); 1947 } else { 1948 expandPath(getSelectionPath()); 1949 } 1950 } 1951 1952 ExplorerTree.this.requestFocus(); 1953 ExplorerTree.this.dispatchEvent(e); 1954 } 1955 } 1956 1957 1958 private void searchForNode() { 1959 currentSelectionIndex = 0; 1960 results.clear(); 1961 maxPrefix = null; 1962 1963 String text = searchTextField.getText().toUpperCase(); 1964 1965 if (text.length() > 0) { 1966 results = doSearch(text); 1967 displaySearchResult(); 1968 } 1969 } 1970 1971 private void displaySearchResult() { 1972 int sz = results.size(); 1973 1974 if (sz > 0) { 1975 if (currentSelectionIndex < 0) { 1976 currentSelectionIndex = sz - 1; 1977 } else if (currentSelectionIndex >= sz) { 1978 currentSelectionIndex = 0; 1979 } 1980 1981 TreePath path = results.get(currentSelectionIndex); 1982 setSelectionPath(path); 1983 scrollPathToVisible(path); 1984 } else { 1985 clearSelection(); 1986 } 1987 } 1988 1989 public void focusGained(FocusEvent e) { 1990 } 1992 1993 public void focusLost(FocusEvent e) { 1994 removeSearchField(); 1995 } 1996 } 1997 1998 private class AccessibleExplorerTree extends JTree.AccessibleJTree { 1999 AccessibleExplorerTree() { 2000 } 2001 2002 public String getAccessibleName() { 2003 return TreeView.this.getAccessibleContext().getAccessibleName(); 2004 } 2005 2006 public String getAccessibleDescription() { 2007 return TreeView.this.getAccessibleContext().getAccessibleDescription(); 2008 } 2009 } 2010 2011 private class ModelHandler extends JTree.TreeModelHandler { 2012 ModelHandler() { 2013 } 2014 2015 public void treeStructureChanged(TreeModelEvent e) { 2016 TreePath [] selectionPaths = getSelectionPaths(); 2018 java.util.Enumeration expanded = getExpandedDescendants(e.getTreePath()); 2019 2020 super.treeStructureChanged(e); 2022 2023 if (expanded != null) { 2025 while (expanded.hasMoreElements()) { 2026 expandPath((TreePath ) expanded.nextElement()); 2027 } 2028 } 2029 2030 if ((selectionPaths != null) && (selectionPaths.length > 0)) { 2032 boolean wasSelected = isPathSelected(selectionPaths[0]); 2033 2034 setSelectionPaths(selectionPaths); 2035 2036 if (!wasSelected) { 2037 scrollPathToVisible(selectionPaths[0]); 2039 } 2040 } 2041 } 2042 2043 public void treeNodesRemoved(TreeModelEvent e) { 2044 super.treeNodesRemoved(e); 2046 2047 if (ExplorerDnDManager.getDefault().isDnDActive()) { 2049 return; 2050 } 2051 2052 if (tree.getSelectionCount() == 0) { 2053 TreePath path = findSiblingTreePath(e.getTreePath(), e.getChildIndices()); 2054 2055 if ((path == null) || path.equals(e.getTreePath())) { 2057 return; 2058 } else if (path.getPathCount() > 0) { 2059 tree.setSelectionPath(path); 2060 } 2061 } 2062 } 2063 } 2064 } 2065 2066 private static class DummyTransferHandler extends TransferHandler { 2067 public void exportAsDrag(JComponent comp, InputEvent e, int action) { 2068 } 2070 public void exportToClipboard(JComponent comp, Clipboard clip, int action) 2071 throws IllegalStateException { 2072 } 2074 public boolean canImport(JComponent comp, DataFlavor [] transferFlavors) { 2075 return false; } 2077 public boolean importData(JComponent comp, Transferable t) { 2078 return false; 2079 } 2080 public int getSourceActions(JComponent c) { 2081 return COPY_OR_MOVE; 2082 } 2083 } 2084} 2085 | Popular Tags |