< prev index next >

src/share/classes/javax/swing/JTree.java

Print this page
rev 1527 : 6727662: Code improvement and warnings removing from swing packages
Summary: Removed unnecessary castings and other warnings
Reviewed-by: malenkov


 170      * The cell used to draw nodes. If <code>null</code>, the UI uses a default
 171      * <code>cellRenderer</code>.
 172      */
 173     transient protected TreeCellRenderer  cellRenderer;
 174 
 175     /**
 176      * Height to use for each display row. If this is <= 0 the renderer
 177      * determines the height for each row.
 178      */
 179     protected int                         rowHeight;
 180     private boolean                       rowHeightSet = false;
 181 
 182     /**
 183      * Maps from <code>TreePath</code> to <code>Boolean</code>
 184      * indicating whether or not the
 185      * particular path is expanded. This ONLY indicates whether a
 186      * given path is expanded, and NOT if it is visible or not. That
 187      * information must be determined by visiting all the parent
 188      * paths and seeing if they are visible.
 189      */
 190     transient private Hashtable           expandedState;
 191 
 192 
 193     /**
 194      * True if handles are displayed at the topmost level of the tree.
 195      * <p>
 196      * A handle is a small icon that displays adjacent to the node which
 197      * allows the user to click once to expand or collapse the node. A
 198      * common interface shows a plus sign (+) for a node which can be
 199      * expanded and a minus sign (-) for a node which can be collapsed.
 200      * Handles are always shown for nodes below the topmost level.
 201      * <p>
 202      * If the <code>rootVisible</code> setting specifies that the root
 203      * node is to be displayed, then that is the only node at the topmost
 204      * level. If the root node is not displayed, then all of its
 205      * children are at the topmost level of the tree. Handles are
 206      * always displayed for nodes other than the topmost.
 207      * <p>
 208      * If the root node isn't visible, it is generally a good to make
 209      * this value true. Otherwise, the tree looks exactly like a list,
 210      * and users may not know that the "list entries" are actually


 264      * If true, when a node is expanded, as many of the descendants are
 265      * scrolled to be visible.
 266      */
 267     protected boolean                 scrollsOnExpand;
 268     private boolean                   scrollsOnExpandSet = false;
 269 
 270     /**
 271      * Number of mouse clicks before a node is expanded.
 272      */
 273     protected int                     toggleClickCount;
 274 
 275     /**
 276      * Updates the <code>expandedState</code>.
 277      */
 278     transient protected TreeModelListener       treeModelListener;
 279 
 280     /**
 281      * Used when <code>setExpandedState</code> is invoked,
 282      * will be a <code>Stack</code> of <code>Stack</code>s.
 283      */
 284     transient private Stack           expandedStack;
 285 
 286     /**
 287      * Lead selection path, may not be <code>null</code>.
 288      */
 289     private TreePath                  leadPath;
 290 
 291     /**
 292      * Anchor path.
 293      */
 294     private TreePath                  anchorPath;
 295 
 296     /**
 297      * True if paths in the selection should be expanded.
 298      */
 299     private boolean                   expandsSelectedPaths;
 300 
 301     /**
 302      * This is set to true for the life of the <code>setUI</code> call.
 303      */
 304     private boolean                   settingUI;


 634      * leaf node in the specified manner.
 635      *
 636      * @param root  a <code>TreeNode</code> object
 637      * @param asksAllowsChildren  if false, any node without children is a
 638      *              leaf node; if true, only nodes that do not allow
 639      *              children are leaf nodes
 640      * @see DefaultTreeModel#asksAllowsChildren
 641      */
 642     public JTree(TreeNode root, boolean asksAllowsChildren) {
 643         this(new DefaultTreeModel(root, asksAllowsChildren));
 644     }
 645 
 646     /**
 647      * Returns an instance of <code>JTree</code> which displays the root node
 648      * -- the tree is created using the specified data model.
 649      *
 650      * @param newModel  the <code>TreeModel</code> to use as the data model
 651      */
 652     public JTree(TreeModel newModel) {
 653         super();
 654         expandedStack = new Stack();
 655         toggleClickCount = 2;
 656         expandedState = new Hashtable();
 657         setLayout(null);
 658         rowHeight = 16;
 659         visibleRowCount = 20;
 660         rootVisible = true;
 661         selectionModel = new DefaultTreeSelectionModel();
 662         cellRenderer = null;
 663         scrollsOnExpand = true;
 664         setOpaque(true);
 665         expandsSelectedPaths = true;
 666         updateUI();
 667         setModel(newModel);
 668     }
 669 
 670     /**
 671      * Returns the L&F object that renders this component.
 672      *
 673      * @return the <code>TreeUI</code> object that renders this component
 674      */
 675     public TreeUI getUI() {
 676         return (TreeUI)ui;
 677     }
 678 
 679     /**
 680      * Sets the L&F object that renders this component.
 681      *
 682      * @param ui  the <code>TreeUI</code> L&F object
 683      * @see UIDefaults#getUI
 684      * @beaninfo
 685      *        bound: true
 686      *       hidden: true
 687      *    attribute: visualUpdate true
 688      *  description: The UI object that implements the Component's LookAndFeel.
 689      */
 690     public void setUI(TreeUI ui) {
 691         if ((TreeUI)this.ui != ui) {
 692             settingUI = true;
 693             uiTreeExpansionListener = null;
 694             try {
 695                 super.setUI(ui);
 696             }
 697             finally {
 698                 settingUI = false;
 699             }
 700         }
 701     }
 702 
 703     /**
 704      * Notification from the <code>UIManager</code> that the L&F has changed.
 705      * Replaces the current UI object with the latest version from the
 706      * <code>UIManager</code>.
 707      *
 708      * @see JComponent#updateUI
 709      */
 710     public void updateUI() {
 711         setUI((TreeUI)UIManager.getUI(this));


1256     public final DropMode getDropMode() {
1257         return dropMode;
1258     }
1259 
1260     /**
1261      * Calculates a drop location in this component, representing where a
1262      * drop at the given point should insert data.
1263      *
1264      * @param p the point to calculate a drop location for
1265      * @return the drop location, or <code>null</code>
1266      */
1267     DropLocation dropLocationForPoint(Point p) {
1268         DropLocation location = null;
1269 
1270         int row = getClosestRowForLocation(p.x, p.y);
1271         Rectangle bounds = getRowBounds(row);
1272         TreeModel model = getModel();
1273         Object root = (model == null) ? null : model.getRoot();
1274         TreePath rootPath = (root == null) ? null : new TreePath(root);
1275 
1276         TreePath child = null;
1277         TreePath parent = null;
1278         boolean outside = row == -1
1279                           || p.y < bounds.y
1280                           || p.y >= bounds.y + bounds.height;
1281 
1282         switch(dropMode) {
1283             case USE_SELECTION:
1284             case ON:
1285                 if (outside) {
1286                     location = new DropLocation(p, null, -1);
1287                 } else {
1288                     location = new DropLocation(p, getPathForRow(row), -1);
1289                 }
1290 
1291                 break;
1292             case INSERT:
1293             case ON_OR_INSERT:
1294                 if (row == -1) {
1295                     if (root != null && !model.isLeaf(root) && isExpanded(rootPath)) {
1296                         location = new DropLocation(p, rootPath, 0);
1297                     } else {


1890 
1891     /**
1892      * Returns an <code>Enumeration</code> of the descendants of the
1893      * path <code>parent</code> that
1894      * are currently expanded. If <code>parent</code> is not currently
1895      * expanded, this will return <code>null</code>.
1896      * If you expand/collapse nodes while
1897      * iterating over the returned <code>Enumeration</code>
1898      * this may not return all
1899      * the expanded paths, or may return paths that are no longer expanded.
1900      *
1901      * @param parent  the path which is to be examined
1902      * @return an <code>Enumeration</code> of the descendents of
1903      *          <code>parent</code>, or <code>null</code> if
1904      *          <code>parent</code> is not currently expanded
1905      */
1906     public Enumeration<TreePath> getExpandedDescendants(TreePath parent) {
1907         if(!isExpanded(parent))
1908             return null;
1909 
1910         Enumeration       toggledPaths = expandedState.keys();
1911         Vector            elements = null;
1912         TreePath          path;
1913         Object            value;
1914 
1915         if(toggledPaths != null) {
1916             while(toggledPaths.hasMoreElements()) {
1917                 path = (TreePath)toggledPaths.nextElement();
1918                 value = expandedState.get(path);
1919                 // Add the path if it is expanded, a descendant of parent,
1920                 // and it is visible (all parents expanded). This is rather
1921                 // expensive!
1922                 if(path != parent && value != null &&
1923                    ((Boolean)value).booleanValue() &&
1924                    parent.isDescendant(path) && isVisible(path)) {
1925                     if (elements == null) {
1926                         elements = new Vector();
1927                     }
1928                     elements.addElement(path);
1929                 }
1930             }
1931         }
1932         if (elements == null) {
1933             Set<TreePath> empty = Collections.emptySet();
1934             return Collections.enumeration(empty);
1935         }
1936         return elements.elements();
1937     }
1938 
1939     /**
1940      * Returns true if the node identified by the path has ever been
1941      * expanded.
1942      * @return true if the <code>path</code> has ever been expanded
1943      */
1944     public boolean hasBeenExpanded(TreePath path) {
1945         return (path != null && expandedState.get(path) != null);
1946     }
1947 
1948     /**
1949      * Returns true if the node identified by the path is currently expanded,
1950      *
1951      * @param path  the <code>TreePath</code> specifying the node to check
1952      * @return false if any of the nodes in the node's path are collapsed,
1953      *               true if all nodes in the path are expanded
1954      */
1955     public boolean isExpanded(TreePath path) {
1956         if(path == null)
1957             return false;
1958 
1959         // Is this node expanded?
1960         Object          value = expandedState.get(path);
1961 
1962         if(value == null || !((Boolean)value).booleanValue())
1963             return false;
1964 
1965         // It is, make sure its parent is also expanded.
1966         TreePath        parentPath = path.getParentPath();
1967 
1968         if(parentPath != null)
1969             return isExpanded(parentPath);
1970         return true;
1971     }
1972 
1973     /**
1974      * Returns true if the node at the specified display row is currently
1975      * expanded.
1976      *
1977      * @param row  the row to check, where 0 is the first row in the
1978      *             display
1979      * @return true if the node is currently expanded, otherwise false
1980      */
1981     public boolean isExpanded(int row) {
1982         TreeUI                  tree = getUI();
1983 
1984         if(tree != null) {
1985             TreePath         path = tree.getPathForRow(this, row);
1986 
1987             if(path != null) {
1988                 Boolean value = (Boolean)expandedState.get(path);
1989 
1990                 return (value != null && value.booleanValue());
1991             }
1992         }
1993         return false;
1994     }
1995 
1996     /**
1997      * Returns true if the value identified by path is currently collapsed,
1998      * this will return false if any of the values in path are currently
1999      * not being displayed.
2000      *
2001      * @param path  the <code>TreePath</code> to check
2002      * @return true if any of the nodes in the node's path are collapsed,
2003      *               false if all nodes in the path are expanded
2004      */
2005     public boolean isCollapsed(TreePath path) {
2006         return !isExpanded(path);
2007     }
2008 


2590      * Removes a listener for <code>TreeExpansion</code> events.
2591      *
2592      * @param tel the <code>TreeExpansionListener</code> to remove
2593      */
2594     public void removeTreeExpansionListener(TreeExpansionListener tel) {
2595         listenerList.remove(TreeExpansionListener.class, tel);
2596         if (uiTreeExpansionListener == tel) {
2597             uiTreeExpansionListener = null;
2598         }
2599     }
2600 
2601     /**
2602      * Returns an array of all the <code>TreeExpansionListener</code>s added
2603      * to this JTree with addTreeExpansionListener().
2604      *
2605      * @return all of the <code>TreeExpansionListener</code>s added or an empty
2606      *         array if no listeners have been added
2607      * @since 1.4
2608      */
2609     public TreeExpansionListener[] getTreeExpansionListeners() {
2610         return (TreeExpansionListener[])listenerList.getListeners(
2611                 TreeExpansionListener.class);
2612     }
2613 
2614     /**
2615      * Adds a listener for <code>TreeWillExpand</code> events.
2616      *
2617      * @param tel a <code>TreeWillExpandListener</code> that will be notified
2618      *            when a tree node will be expanded or collapsed (a "negative
2619      *            expansion")
2620      */
2621     public void addTreeWillExpandListener(TreeWillExpandListener tel) {
2622         listenerList.add(TreeWillExpandListener.class, tel);
2623     }
2624 
2625     /**
2626      * Removes a listener for <code>TreeWillExpand</code> events.
2627      *
2628      * @param tel the <code>TreeWillExpandListener</code> to remove
2629      */
2630     public void removeTreeWillExpandListener(TreeWillExpandListener tel) {
2631         listenerList.remove(TreeWillExpandListener.class, tel);
2632     }
2633 
2634     /**
2635      * Returns an array of all the <code>TreeWillExpandListener</code>s added
2636      * to this JTree with addTreeWillExpandListener().
2637      *
2638      * @return all of the <code>TreeWillExpandListener</code>s added or an empty
2639      *         array if no listeners have been added
2640      * @since 1.4
2641      */
2642     public TreeWillExpandListener[] getTreeWillExpandListeners() {
2643         return (TreeWillExpandListener[])listenerList.getListeners(
2644                 TreeWillExpandListener.class);
2645     }
2646 
2647     /**
2648      * Notifies all listeners that have registered interest for
2649      * notification on this event type.  The event instance
2650      * is lazily created using the <code>path</code> parameter.
2651      *
2652      * @param path the <code>TreePath</code> indicating the node that was
2653      *          expanded
2654      * @see EventListenerList
2655      */
2656      public void fireTreeExpanded(TreePath path) {
2657         // Guaranteed to return a non-null array
2658         Object[] listeners = listenerList.getListenerList();
2659         TreeExpansionEvent e = null;
2660         if (uiTreeExpansionListener != null) {
2661             e = new TreeExpansionEvent(this, path);
2662             uiTreeExpansionListener.treeExpanded(e);
2663         }
2664         // Process the listeners last to first, notifying


2781      */
2782     public void removeTreeSelectionListener(TreeSelectionListener tsl) {
2783         listenerList.remove(TreeSelectionListener.class,tsl);
2784         if(listenerList.getListenerCount(TreeSelectionListener.class) == 0
2785            && selectionRedirector != null) {
2786             selectionModel.removeTreeSelectionListener
2787                 (selectionRedirector);
2788             selectionRedirector = null;
2789         }
2790     }
2791 
2792     /**
2793      * Returns an array of all the <code>TreeSelectionListener</code>s added
2794      * to this JTree with addTreeSelectionListener().
2795      *
2796      * @return all of the <code>TreeSelectionListener</code>s added or an empty
2797      *         array if no listeners have been added
2798      * @since 1.4
2799      */
2800     public TreeSelectionListener[] getTreeSelectionListeners() {
2801         return (TreeSelectionListener[])listenerList.getListeners(
2802                 TreeSelectionListener.class);
2803     }
2804 
2805     /**
2806      * Notifies all listeners that have registered interest for
2807      * notification on this event type.
2808      *
2809      * @param e the <code>TreeSelectionEvent</code> to be fired;
2810      *          generated by the
2811      *          <code>TreeSelectionModel</code>
2812      *          when a node is selected or deselected
2813      * @see EventListenerList
2814      */
2815     protected void fireValueChanged(TreeSelectionEvent e) {
2816         // Guaranteed to return a non-null array
2817         Object[] listeners = listenerList.getListenerList();
2818         // Process the listeners last to first, notifying
2819         // those that are interested in this event
2820         for (int i = listeners.length-2; i>=0; i-=2) {
2821             // TreeSelectionEvent e = null;
2822             if (listeners[i]==TreeSelectionListener.class) {


2914         // start search from the next/previous element froom the
2915         // selected element
2916         int increment = (bias == Position.Bias.Forward) ? 1 : -1;
2917         int row = startingRow;
2918         do {
2919             TreePath path = getPathForRow(row);
2920             String text = convertValueToText(
2921                 path.getLastPathComponent(), isRowSelected(row),
2922                 isExpanded(row), true, row, false);
2923 
2924             if (text.toUpperCase().startsWith(prefix)) {
2925                 return path;
2926             }
2927             row = (row + increment + max) % max;
2928         } while (row != startingRow);
2929         return null;
2930     }
2931 
2932     // Serialization support.
2933     private void writeObject(ObjectOutputStream s) throws IOException {
2934         Vector      values = new Vector();
2935 
2936         s.defaultWriteObject();
2937         // Save the cellRenderer, if its Serializable.
2938         if(cellRenderer != null && cellRenderer instanceof Serializable) {
2939             values.addElement("cellRenderer");
2940             values.addElement(cellRenderer);
2941         }
2942         // Save the cellEditor, if its Serializable.
2943         if(cellEditor != null && cellEditor instanceof Serializable) {
2944             values.addElement("cellEditor");
2945             values.addElement(cellEditor);
2946         }
2947         // Save the treeModel, if its Serializable.
2948         if(treeModel != null && treeModel instanceof Serializable) {
2949             values.addElement("treeModel");
2950             values.addElement(treeModel);
2951         }
2952         // Save the selectionModel, if its Serializable.
2953         if(selectionModel != null && selectionModel instanceof Serializable) {
2954             values.addElement("selectionModel");


2961             values.addElement("expandedState");
2962             values.addElement(expandedData);
2963         }
2964 
2965         s.writeObject(values);
2966         if (getUIClassID().equals(uiClassID)) {
2967             byte count = JComponent.getWriteObjCounter(this);
2968             JComponent.setWriteObjCounter(this, --count);
2969             if (count == 0 && ui != null) {
2970                 ui.installUI(this);
2971             }
2972         }
2973     }
2974 
2975     private void readObject(ObjectInputStream s)
2976         throws IOException, ClassNotFoundException {
2977         s.defaultReadObject();
2978 
2979         // Create an instance of expanded state.
2980 
2981         expandedState = new Hashtable();
2982 
2983         expandedStack = new Stack();
2984 
2985         Vector          values = (Vector)s.readObject();
2986         int             indexCounter = 0;
2987         int             maxCounter = values.size();
2988 
2989         if(indexCounter < maxCounter && values.elementAt(indexCounter).
2990            equals("cellRenderer")) {
2991             cellRenderer = (TreeCellRenderer)values.elementAt(++indexCounter);
2992             indexCounter++;
2993         }
2994         if(indexCounter < maxCounter && values.elementAt(indexCounter).
2995            equals("cellEditor")) {
2996             cellEditor = (TreeCellEditor)values.elementAt(++indexCounter);
2997             indexCounter++;
2998         }
2999         if(indexCounter < maxCounter && values.elementAt(indexCounter).
3000            equals("treeModel")) {
3001             treeModel = (TreeModel)values.elementAt(++indexCounter);
3002             indexCounter++;
3003         }


3016             selectionRedirector = new TreeSelectionRedirector();
3017             selectionModel.addTreeSelectionListener(selectionRedirector);
3018         }
3019         // Listener to TreeModel.
3020         if(treeModel != null) {
3021             treeModelListener = createTreeModelListener();
3022             if(treeModelListener != null)
3023                 treeModel.addTreeModelListener(treeModelListener);
3024         }
3025     }
3026 
3027     /**
3028      * Returns an object that can be archived indicating what nodes are
3029      * expanded and what aren't. The objects from the model are NOT
3030      * written out.
3031      */
3032     private Object getArchivableExpandedState() {
3033         TreeModel       model = getModel();
3034 
3035         if(model != null) {
3036             Enumeration        paths = expandedState.keys();
3037 
3038             if(paths != null) {
3039                 Vector         state = new Vector();
3040 
3041                 while(paths.hasMoreElements()) {
3042                     TreePath   path = (TreePath)paths.nextElement();
3043                     Object     archivePath;
3044 
3045                     try {
3046                         archivePath = getModelIndexsForPath(path);
3047                     } catch (Error error) {
3048                         archivePath = null;
3049                     }
3050                     if(archivePath != null) {
3051                         state.addElement(archivePath);
3052                         state.addElement(expandedState.get(path));
3053                     }
3054                 }
3055                 return state;
3056             }
3057         }
3058         return null;
3059     }
3060 
3061     /**
3062      * Updates the expanded state of nodes in the tree based on the


3300      * @return the "block" increment for scrolling in the specified direction
3301      * @see JScrollBar#setBlockIncrement(int)
3302      */
3303     public int getScrollableBlockIncrement(Rectangle visibleRect,
3304                                            int orientation, int direction) {
3305         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
3306             visibleRect.width;
3307     }
3308 
3309     /**
3310      * Returns false to indicate that the width of the viewport does not
3311      * determine the width of the table, unless the preferred width of
3312      * the tree is smaller than the viewports width.  In other words:
3313      * ensure that the tree is never smaller than its viewport.
3314      *
3315      * @return false
3316      * @see Scrollable#getScrollableTracksViewportWidth
3317      */
3318     public boolean getScrollableTracksViewportWidth() {
3319         if (getParent() instanceof JViewport) {
3320             return (((JViewport)getParent()).getWidth() > getPreferredSize().width);
3321         }
3322         return false;
3323     }
3324 
3325     /**
3326      * Returns false to indicate that the height of the viewport does not
3327      * determine the height of the table, unless the preferred height
3328      * of the tree is smaller than the viewports height.  In other words:
3329      * ensure that the tree is never smaller than its viewport.
3330      *
3331      * @return false
3332      * @see Scrollable#getScrollableTracksViewportHeight
3333      */
3334     public boolean getScrollableTracksViewportHeight() {
3335         if (getParent() instanceof JViewport) {
3336             return (((JViewport)getParent()).getHeight() > getPreferredSize().height);
3337         }
3338         return false;
3339     }
3340 
3341     /**
3342      * Sets the expanded state of this <code>JTree</code>.
3343      * If <code>state</code> is
3344      * true, all parents of <code>path</code> and path are marked as
3345      * expanded. If <code>state</code> is false, all parents of
3346      * <code>path</code> are marked EXPANDED, but <code>path</code> itself
3347      * is marked collapsed.<p>
3348      * This will fail if a <code>TreeWillExpandListener</code> vetos it.
3349      */
3350     protected void setExpandedState(TreePath path, boolean state) {
3351         if(path != null) {
3352             // Make sure all parents of path are expanded.
3353             Stack         stack;
3354             TreePath      parentPath = path.getParentPath();
3355 
3356             if (expandedStack.size() == 0) {
3357                 stack = new Stack();
3358             }
3359             else {
3360                 stack = (Stack)expandedStack.pop();
3361             }
3362 
3363             try {
3364                 while(parentPath != null) {
3365                     if(isExpanded(parentPath)) {
3366                         parentPath = null;
3367                     }
3368                     else {
3369                         stack.push(parentPath);
3370                         parentPath = parentPath.getParentPath();
3371                     }
3372                 }
3373                 for(int counter = stack.size() - 1; counter >= 0; counter--) {
3374                     parentPath = (TreePath)stack.pop();
3375                     if(!isExpanded(parentPath)) {
3376                         try {
3377                             fireTreeWillExpand(parentPath);
3378                         } catch (ExpandVetoException eve) {
3379                             // Expand vetoed!
3380                             return;
3381                         }
3382                         expandedState.put(parentPath, Boolean.TRUE);
3383                         fireTreeExpanded(parentPath);
3384                         if (accessibleContext != null) {
3385                             ((AccessibleJTree)accessibleContext).
3386                                               fireVisibleDataPropertyChange();
3387                         }
3388                     }
3389                 }
3390             }
3391             finally {
3392                 if (expandedStack.size() < TEMP_STACK_SIZE) {
3393                     stack.removeAllElements();
3394                     expandedStack.push(stack);


3434                     if (accessibleContext != null) {
3435                         ((AccessibleJTree)accessibleContext).
3436                                           fireVisibleDataPropertyChange();
3437                     }
3438                 }
3439             }
3440         }
3441     }
3442 
3443     /**
3444      * Returns an <code>Enumeration</code> of <code>TreePaths</code>
3445      * that have been expanded that
3446      * are descendants of <code>parent</code>.
3447      */
3448     protected Enumeration<TreePath>
3449         getDescendantToggledPaths(TreePath parent)
3450     {
3451         if(parent == null)
3452             return null;
3453 
3454         Vector            descendants = new Vector();
3455         Enumeration       nodes = expandedState.keys();
3456         TreePath          path;
3457 
3458         while(nodes.hasMoreElements()) {
3459             path = (TreePath)nodes.nextElement();
3460             if(parent.isDescendant(path))
3461                 descendants.addElement(path);
3462         }
3463         return descendants.elements();
3464     }
3465 
3466     /**
3467      * Removes any descendants of the <code>TreePaths</code> in
3468      * <code>toRemove</code>
3469      * that have been expanded.
3470      */
3471      protected void
3472          removeDescendantToggledPaths(Enumeration<TreePath> toRemove)
3473     {
3474          if(toRemove != null) {
3475              while(toRemove.hasMoreElements()) {
3476                  Enumeration         descendants = getDescendantToggledPaths
3477                                          ((TreePath)toRemove.nextElement());
3478 
3479                  if(descendants != null) {
3480                      while(descendants.hasMoreElements()) {
3481                          expandedState.remove(descendants.nextElement());
3482                      }
3483                  }
3484              }
3485          }
3486      }
3487 
3488      /**
3489       * Clears the cache of toggled tree paths. This does NOT send out
3490       * any <code>TreeExpansionListener</code> events.
3491       */
3492      protected void clearToggledPaths() {
3493          expandedState.clear();
3494      }
3495 
3496      /**
3497       * Creates and returns an instance of <code>TreeModelHandler</code>.


4042             if (path != null) {
4043                 // TIGER - 4839971
4044                 // Set parent to null so AccessibleJTreeNode computes
4045                 // its parent.
4046                 AccessibleJTreeNode node = new AccessibleJTreeNode(JTree.this,
4047                                                                    path,
4048                                                                    null);
4049                 PropertyChangeEvent pce = new PropertyChangeEvent(node,
4050                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
4051                     AccessibleState.COLLAPSED,
4052                     AccessibleState.EXPANDED);
4053                 firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
4054                                    null, pce);
4055             }
4056         }
4057 
4058 
4059         private AccessibleContext getCurrentAccessibleContext() {
4060             Component c = getCurrentComponent();
4061             if (c instanceof Accessible) {
4062                 return (((Accessible) c).getAccessibleContext());
4063             } else {
4064                 return null;
4065             }
4066         }
4067 
4068         private Component getCurrentComponent() {
4069             // is the object visible?
4070             // if so, get row, selected, focus & leaf state,
4071             // and then get the renderer component and return it
4072             TreeModel model = JTree.this.getModel();
4073             if (model == null) {
4074                 return null;
4075             }
4076             TreePath path = new TreePath(model.getRoot());
4077             if (JTree.this.isVisible(path)) {
4078                 TreeCellRenderer r = JTree.this.getCellRenderer();
4079                 TreeUI ui = JTree.this.getUI();
4080                 if (ui != null) {
4081                     int row = ui.getRowForPath(JTree.this, path);
4082                     int lsr = JTree.this.getLeadSelectionRow();


4365                     objChildPath[objChildPath.length-1] = childObj;
4366                     return new TreePath(objChildPath);
4367                 }
4368             }
4369 
4370             /**
4371              * Get the AccessibleContext associated with this tree node.
4372              * In the implementation of the Java Accessibility API for
4373              * this class, return this object, which is its own
4374              * AccessibleContext.
4375              *
4376              * @return this object
4377              */
4378             public AccessibleContext getAccessibleContext() {
4379                 return this;
4380             }
4381 
4382             private AccessibleContext getCurrentAccessibleContext() {
4383                 Component c = getCurrentComponent();
4384                 if (c instanceof Accessible) {
4385                     return (((Accessible) c).getAccessibleContext());
4386                 } else {
4387                     return null;
4388                 }
4389             }
4390 
4391             private Component getCurrentComponent() {
4392                 // is the object visible?
4393                 // if so, get row, selected, focus & leaf state,
4394                 // and then get the renderer component and return it
4395                 if (tree.isVisible(path)) {
4396                     TreeCellRenderer r = tree.getCellRenderer();
4397                     if (r == null) {
4398                         return null;
4399                     }
4400                     TreeUI ui = tree.getUI();
4401                     if (ui != null) {
4402                         int row = ui.getRowForPath(JTree.this, path);
4403                         boolean selected = tree.isPathSelected(path);
4404                         boolean expanded = tree.isExpanded(path);
4405                         boolean hasFocus = false; // how to tell?? -PK


4909                         return false;
4910                     }
4911                 }
4912             }
4913 
4914             public void setEnabled(boolean b) {
4915                 AccessibleContext ac = getCurrentAccessibleContext();
4916                 if (ac instanceof AccessibleComponent) {
4917                     ((AccessibleComponent) ac).setEnabled(b);
4918                 } else {
4919                     Component c = getCurrentComponent();
4920                     if (c != null) {
4921                         c.setEnabled(b);
4922                     }
4923                 }
4924             }
4925 
4926             public boolean isVisible() {
4927                 Rectangle pathBounds = tree.getPathBounds(path);
4928                 Rectangle parentBounds = tree.getVisibleRect();
4929                 if (pathBounds != null && parentBounds != null &&
4930                     parentBounds.intersects(pathBounds)) {
4931                     return true;
4932                 } else {
4933                     return false;
4934                 }
4935             }
4936 
4937             public void setVisible(boolean b) {
4938             }
4939 
4940             public boolean isShowing() {
4941                 return (tree.isShowing() && isVisible());
4942             }
4943 
4944             public boolean contains(Point p) {
4945                 AccessibleContext ac = getCurrentAccessibleContext();
4946                 if (ac instanceof AccessibleComponent) {
4947                     Rectangle r = ((AccessibleComponent) ac).getBounds();
4948                     return r.contains(p);
4949                 } else {
4950                     Component c = getCurrentComponent();
4951                     if (c != null) {
4952                         Rectangle r = c.getBounds();
4953                         return r.contains(p);
4954                     } else {




 170      * The cell used to draw nodes. If <code>null</code>, the UI uses a default
 171      * <code>cellRenderer</code>.
 172      */
 173     transient protected TreeCellRenderer  cellRenderer;
 174 
 175     /**
 176      * Height to use for each display row. If this is <= 0 the renderer
 177      * determines the height for each row.
 178      */
 179     protected int                         rowHeight;
 180     private boolean                       rowHeightSet = false;
 181 
 182     /**
 183      * Maps from <code>TreePath</code> to <code>Boolean</code>
 184      * indicating whether or not the
 185      * particular path is expanded. This ONLY indicates whether a
 186      * given path is expanded, and NOT if it is visible or not. That
 187      * information must be determined by visiting all the parent
 188      * paths and seeing if they are visible.
 189      */
 190     transient private Hashtable<TreePath, Boolean> expandedState;
 191 
 192 
 193     /**
 194      * True if handles are displayed at the topmost level of the tree.
 195      * <p>
 196      * A handle is a small icon that displays adjacent to the node which
 197      * allows the user to click once to expand or collapse the node. A
 198      * common interface shows a plus sign (+) for a node which can be
 199      * expanded and a minus sign (-) for a node which can be collapsed.
 200      * Handles are always shown for nodes below the topmost level.
 201      * <p>
 202      * If the <code>rootVisible</code> setting specifies that the root
 203      * node is to be displayed, then that is the only node at the topmost
 204      * level. If the root node is not displayed, then all of its
 205      * children are at the topmost level of the tree. Handles are
 206      * always displayed for nodes other than the topmost.
 207      * <p>
 208      * If the root node isn't visible, it is generally a good to make
 209      * this value true. Otherwise, the tree looks exactly like a list,
 210      * and users may not know that the "list entries" are actually


 264      * If true, when a node is expanded, as many of the descendants are
 265      * scrolled to be visible.
 266      */
 267     protected boolean                 scrollsOnExpand;
 268     private boolean                   scrollsOnExpandSet = false;
 269 
 270     /**
 271      * Number of mouse clicks before a node is expanded.
 272      */
 273     protected int                     toggleClickCount;
 274 
 275     /**
 276      * Updates the <code>expandedState</code>.
 277      */
 278     transient protected TreeModelListener       treeModelListener;
 279 
 280     /**
 281      * Used when <code>setExpandedState</code> is invoked,
 282      * will be a <code>Stack</code> of <code>Stack</code>s.
 283      */
 284     transient private Stack<Stack<TreePath>> expandedStack;
 285 
 286     /**
 287      * Lead selection path, may not be <code>null</code>.
 288      */
 289     private TreePath                  leadPath;
 290 
 291     /**
 292      * Anchor path.
 293      */
 294     private TreePath                  anchorPath;
 295 
 296     /**
 297      * True if paths in the selection should be expanded.
 298      */
 299     private boolean                   expandsSelectedPaths;
 300 
 301     /**
 302      * This is set to true for the life of the <code>setUI</code> call.
 303      */
 304     private boolean                   settingUI;


 634      * leaf node in the specified manner.
 635      *
 636      * @param root  a <code>TreeNode</code> object
 637      * @param asksAllowsChildren  if false, any node without children is a
 638      *              leaf node; if true, only nodes that do not allow
 639      *              children are leaf nodes
 640      * @see DefaultTreeModel#asksAllowsChildren
 641      */
 642     public JTree(TreeNode root, boolean asksAllowsChildren) {
 643         this(new DefaultTreeModel(root, asksAllowsChildren));
 644     }
 645 
 646     /**
 647      * Returns an instance of <code>JTree</code> which displays the root node
 648      * -- the tree is created using the specified data model.
 649      *
 650      * @param newModel  the <code>TreeModel</code> to use as the data model
 651      */
 652     public JTree(TreeModel newModel) {
 653         super();
 654         expandedStack = new Stack<Stack<TreePath>>();
 655         toggleClickCount = 2;
 656         expandedState = new Hashtable<TreePath, Boolean>();
 657         setLayout(null);
 658         rowHeight = 16;
 659         visibleRowCount = 20;
 660         rootVisible = true;
 661         selectionModel = new DefaultTreeSelectionModel();
 662         cellRenderer = null;
 663         scrollsOnExpand = true;
 664         setOpaque(true);
 665         expandsSelectedPaths = true;
 666         updateUI();
 667         setModel(newModel);
 668     }
 669 
 670     /**
 671      * Returns the L&F object that renders this component.
 672      *
 673      * @return the <code>TreeUI</code> object that renders this component
 674      */
 675     public TreeUI getUI() {
 676         return (TreeUI)ui;
 677     }
 678 
 679     /**
 680      * Sets the L&F object that renders this component.
 681      *
 682      * @param ui  the <code>TreeUI</code> L&F object
 683      * @see UIDefaults#getUI
 684      * @beaninfo
 685      *        bound: true
 686      *       hidden: true
 687      *    attribute: visualUpdate true
 688      *  description: The UI object that implements the Component's LookAndFeel.
 689      */
 690     public void setUI(TreeUI ui) {
 691         if (this.ui != ui) {
 692             settingUI = true;
 693             uiTreeExpansionListener = null;
 694             try {
 695                 super.setUI(ui);
 696             }
 697             finally {
 698                 settingUI = false;
 699             }
 700         }
 701     }
 702 
 703     /**
 704      * Notification from the <code>UIManager</code> that the L&F has changed.
 705      * Replaces the current UI object with the latest version from the
 706      * <code>UIManager</code>.
 707      *
 708      * @see JComponent#updateUI
 709      */
 710     public void updateUI() {
 711         setUI((TreeUI)UIManager.getUI(this));


1256     public final DropMode getDropMode() {
1257         return dropMode;
1258     }
1259 
1260     /**
1261      * Calculates a drop location in this component, representing where a
1262      * drop at the given point should insert data.
1263      *
1264      * @param p the point to calculate a drop location for
1265      * @return the drop location, or <code>null</code>
1266      */
1267     DropLocation dropLocationForPoint(Point p) {
1268         DropLocation location = null;
1269 
1270         int row = getClosestRowForLocation(p.x, p.y);
1271         Rectangle bounds = getRowBounds(row);
1272         TreeModel model = getModel();
1273         Object root = (model == null) ? null : model.getRoot();
1274         TreePath rootPath = (root == null) ? null : new TreePath(root);
1275 
1276         TreePath child;
1277         TreePath parent;
1278         boolean outside = row == -1
1279                           || p.y < bounds.y
1280                           || p.y >= bounds.y + bounds.height;
1281 
1282         switch(dropMode) {
1283             case USE_SELECTION:
1284             case ON:
1285                 if (outside) {
1286                     location = new DropLocation(p, null, -1);
1287                 } else {
1288                     location = new DropLocation(p, getPathForRow(row), -1);
1289                 }
1290 
1291                 break;
1292             case INSERT:
1293             case ON_OR_INSERT:
1294                 if (row == -1) {
1295                     if (root != null && !model.isLeaf(root) && isExpanded(rootPath)) {
1296                         location = new DropLocation(p, rootPath, 0);
1297                     } else {


1890 
1891     /**
1892      * Returns an <code>Enumeration</code> of the descendants of the
1893      * path <code>parent</code> that
1894      * are currently expanded. If <code>parent</code> is not currently
1895      * expanded, this will return <code>null</code>.
1896      * If you expand/collapse nodes while
1897      * iterating over the returned <code>Enumeration</code>
1898      * this may not return all
1899      * the expanded paths, or may return paths that are no longer expanded.
1900      *
1901      * @param parent  the path which is to be examined
1902      * @return an <code>Enumeration</code> of the descendents of
1903      *          <code>parent</code>, or <code>null</code> if
1904      *          <code>parent</code> is not currently expanded
1905      */
1906     public Enumeration<TreePath> getExpandedDescendants(TreePath parent) {
1907         if(!isExpanded(parent))
1908             return null;
1909 
1910         Enumeration<TreePath> toggledPaths = expandedState.keys();
1911         Vector<TreePath> elements = null;
1912         TreePath          path;
1913         Object            value;
1914 
1915         if(toggledPaths != null) {
1916             while(toggledPaths.hasMoreElements()) {
1917                 path = toggledPaths.nextElement();
1918                 value = expandedState.get(path);
1919                 // Add the path if it is expanded, a descendant of parent,
1920                 // and it is visible (all parents expanded). This is rather
1921                 // expensive!
1922                 if(path != parent && value != null &&
1923                    ((Boolean)value).booleanValue() &&
1924                    parent.isDescendant(path) && isVisible(path)) {
1925                     if (elements == null) {
1926                         elements = new Vector<TreePath>();
1927                     }
1928                     elements.addElement(path);
1929                 }
1930             }
1931         }
1932         if (elements == null) {
1933             Set<TreePath> empty = Collections.emptySet();
1934             return Collections.enumeration(empty);
1935         }
1936         return elements.elements();
1937     }
1938 
1939     /**
1940      * Returns true if the node identified by the path has ever been
1941      * expanded.
1942      * @return true if the <code>path</code> has ever been expanded
1943      */
1944     public boolean hasBeenExpanded(TreePath path) {
1945         return (path != null && expandedState.get(path) != null);
1946     }
1947 
1948     /**
1949      * Returns true if the node identified by the path is currently expanded,
1950      *
1951      * @param path  the <code>TreePath</code> specifying the node to check
1952      * @return false if any of the nodes in the node's path are collapsed,
1953      *               true if all nodes in the path are expanded
1954      */
1955     public boolean isExpanded(TreePath path) {
1956         if(path == null)
1957             return false;
1958 
1959         // Is this node expanded?
1960         Boolean value = expandedState.get(path);
1961 
1962         if(value == null || !value.booleanValue())
1963             return false;
1964 
1965         // It is, make sure its parent is also expanded.
1966         TreePath        parentPath = path.getParentPath();
1967 
1968         if(parentPath != null)
1969             return isExpanded(parentPath);
1970         return true;
1971     }
1972 
1973     /**
1974      * Returns true if the node at the specified display row is currently
1975      * expanded.
1976      *
1977      * @param row  the row to check, where 0 is the first row in the
1978      *             display
1979      * @return true if the node is currently expanded, otherwise false
1980      */
1981     public boolean isExpanded(int row) {
1982         TreeUI                  tree = getUI();
1983 
1984         if(tree != null) {
1985             TreePath         path = tree.getPathForRow(this, row);
1986 
1987             if(path != null) {
1988                 Boolean value = expandedState.get(path);
1989 
1990                 return (value != null && value.booleanValue());
1991             }
1992         }
1993         return false;
1994     }
1995 
1996     /**
1997      * Returns true if the value identified by path is currently collapsed,
1998      * this will return false if any of the values in path are currently
1999      * not being displayed.
2000      *
2001      * @param path  the <code>TreePath</code> to check
2002      * @return true if any of the nodes in the node's path are collapsed,
2003      *               false if all nodes in the path are expanded
2004      */
2005     public boolean isCollapsed(TreePath path) {
2006         return !isExpanded(path);
2007     }
2008 


2590      * Removes a listener for <code>TreeExpansion</code> events.
2591      *
2592      * @param tel the <code>TreeExpansionListener</code> to remove
2593      */
2594     public void removeTreeExpansionListener(TreeExpansionListener tel) {
2595         listenerList.remove(TreeExpansionListener.class, tel);
2596         if (uiTreeExpansionListener == tel) {
2597             uiTreeExpansionListener = null;
2598         }
2599     }
2600 
2601     /**
2602      * Returns an array of all the <code>TreeExpansionListener</code>s added
2603      * to this JTree with addTreeExpansionListener().
2604      *
2605      * @return all of the <code>TreeExpansionListener</code>s added or an empty
2606      *         array if no listeners have been added
2607      * @since 1.4
2608      */
2609     public TreeExpansionListener[] getTreeExpansionListeners() {
2610         return listenerList.getListeners(TreeExpansionListener.class);

2611     }
2612 
2613     /**
2614      * Adds a listener for <code>TreeWillExpand</code> events.
2615      *
2616      * @param tel a <code>TreeWillExpandListener</code> that will be notified
2617      *            when a tree node will be expanded or collapsed (a "negative
2618      *            expansion")
2619      */
2620     public void addTreeWillExpandListener(TreeWillExpandListener tel) {
2621         listenerList.add(TreeWillExpandListener.class, tel);
2622     }
2623 
2624     /**
2625      * Removes a listener for <code>TreeWillExpand</code> events.
2626      *
2627      * @param tel the <code>TreeWillExpandListener</code> to remove
2628      */
2629     public void removeTreeWillExpandListener(TreeWillExpandListener tel) {
2630         listenerList.remove(TreeWillExpandListener.class, tel);
2631     }
2632 
2633     /**
2634      * Returns an array of all the <code>TreeWillExpandListener</code>s added
2635      * to this JTree with addTreeWillExpandListener().
2636      *
2637      * @return all of the <code>TreeWillExpandListener</code>s added or an empty
2638      *         array if no listeners have been added
2639      * @since 1.4
2640      */
2641     public TreeWillExpandListener[] getTreeWillExpandListeners() {
2642         return listenerList.getListeners(TreeWillExpandListener.class);

2643     }
2644 
2645     /**
2646      * Notifies all listeners that have registered interest for
2647      * notification on this event type.  The event instance
2648      * is lazily created using the <code>path</code> parameter.
2649      *
2650      * @param path the <code>TreePath</code> indicating the node that was
2651      *          expanded
2652      * @see EventListenerList
2653      */
2654      public void fireTreeExpanded(TreePath path) {
2655         // Guaranteed to return a non-null array
2656         Object[] listeners = listenerList.getListenerList();
2657         TreeExpansionEvent e = null;
2658         if (uiTreeExpansionListener != null) {
2659             e = new TreeExpansionEvent(this, path);
2660             uiTreeExpansionListener.treeExpanded(e);
2661         }
2662         // Process the listeners last to first, notifying


2779      */
2780     public void removeTreeSelectionListener(TreeSelectionListener tsl) {
2781         listenerList.remove(TreeSelectionListener.class,tsl);
2782         if(listenerList.getListenerCount(TreeSelectionListener.class) == 0
2783            && selectionRedirector != null) {
2784             selectionModel.removeTreeSelectionListener
2785                 (selectionRedirector);
2786             selectionRedirector = null;
2787         }
2788     }
2789 
2790     /**
2791      * Returns an array of all the <code>TreeSelectionListener</code>s added
2792      * to this JTree with addTreeSelectionListener().
2793      *
2794      * @return all of the <code>TreeSelectionListener</code>s added or an empty
2795      *         array if no listeners have been added
2796      * @since 1.4
2797      */
2798     public TreeSelectionListener[] getTreeSelectionListeners() {
2799         return listenerList.getListeners(TreeSelectionListener.class);

2800     }
2801 
2802     /**
2803      * Notifies all listeners that have registered interest for
2804      * notification on this event type.
2805      *
2806      * @param e the <code>TreeSelectionEvent</code> to be fired;
2807      *          generated by the
2808      *          <code>TreeSelectionModel</code>
2809      *          when a node is selected or deselected
2810      * @see EventListenerList
2811      */
2812     protected void fireValueChanged(TreeSelectionEvent e) {
2813         // Guaranteed to return a non-null array
2814         Object[] listeners = listenerList.getListenerList();
2815         // Process the listeners last to first, notifying
2816         // those that are interested in this event
2817         for (int i = listeners.length-2; i>=0; i-=2) {
2818             // TreeSelectionEvent e = null;
2819             if (listeners[i]==TreeSelectionListener.class) {


2911         // start search from the next/previous element froom the
2912         // selected element
2913         int increment = (bias == Position.Bias.Forward) ? 1 : -1;
2914         int row = startingRow;
2915         do {
2916             TreePath path = getPathForRow(row);
2917             String text = convertValueToText(
2918                 path.getLastPathComponent(), isRowSelected(row),
2919                 isExpanded(row), true, row, false);
2920 
2921             if (text.toUpperCase().startsWith(prefix)) {
2922                 return path;
2923             }
2924             row = (row + increment + max) % max;
2925         } while (row != startingRow);
2926         return null;
2927     }
2928 
2929     // Serialization support.
2930     private void writeObject(ObjectOutputStream s) throws IOException {
2931         Vector<Object> values = new Vector<Object>();
2932 
2933         s.defaultWriteObject();
2934         // Save the cellRenderer, if its Serializable.
2935         if(cellRenderer != null && cellRenderer instanceof Serializable) {
2936             values.addElement("cellRenderer");
2937             values.addElement(cellRenderer);
2938         }
2939         // Save the cellEditor, if its Serializable.
2940         if(cellEditor != null && cellEditor instanceof Serializable) {
2941             values.addElement("cellEditor");
2942             values.addElement(cellEditor);
2943         }
2944         // Save the treeModel, if its Serializable.
2945         if(treeModel != null && treeModel instanceof Serializable) {
2946             values.addElement("treeModel");
2947             values.addElement(treeModel);
2948         }
2949         // Save the selectionModel, if its Serializable.
2950         if(selectionModel != null && selectionModel instanceof Serializable) {
2951             values.addElement("selectionModel");


2958             values.addElement("expandedState");
2959             values.addElement(expandedData);
2960         }
2961 
2962         s.writeObject(values);
2963         if (getUIClassID().equals(uiClassID)) {
2964             byte count = JComponent.getWriteObjCounter(this);
2965             JComponent.setWriteObjCounter(this, --count);
2966             if (count == 0 && ui != null) {
2967                 ui.installUI(this);
2968             }
2969         }
2970     }
2971 
2972     private void readObject(ObjectInputStream s)
2973         throws IOException, ClassNotFoundException {
2974         s.defaultReadObject();
2975 
2976         // Create an instance of expanded state.
2977 
2978         expandedState = new Hashtable<TreePath, Boolean>();
2979 
2980         expandedStack = new Stack<Stack<TreePath>>();
2981 
2982         Vector          values = (Vector)s.readObject();
2983         int             indexCounter = 0;
2984         int             maxCounter = values.size();
2985 
2986         if(indexCounter < maxCounter && values.elementAt(indexCounter).
2987            equals("cellRenderer")) {
2988             cellRenderer = (TreeCellRenderer)values.elementAt(++indexCounter);
2989             indexCounter++;
2990         }
2991         if(indexCounter < maxCounter && values.elementAt(indexCounter).
2992            equals("cellEditor")) {
2993             cellEditor = (TreeCellEditor)values.elementAt(++indexCounter);
2994             indexCounter++;
2995         }
2996         if(indexCounter < maxCounter && values.elementAt(indexCounter).
2997            equals("treeModel")) {
2998             treeModel = (TreeModel)values.elementAt(++indexCounter);
2999             indexCounter++;
3000         }


3013             selectionRedirector = new TreeSelectionRedirector();
3014             selectionModel.addTreeSelectionListener(selectionRedirector);
3015         }
3016         // Listener to TreeModel.
3017         if(treeModel != null) {
3018             treeModelListener = createTreeModelListener();
3019             if(treeModelListener != null)
3020                 treeModel.addTreeModelListener(treeModelListener);
3021         }
3022     }
3023 
3024     /**
3025      * Returns an object that can be archived indicating what nodes are
3026      * expanded and what aren't. The objects from the model are NOT
3027      * written out.
3028      */
3029     private Object getArchivableExpandedState() {
3030         TreeModel       model = getModel();
3031 
3032         if(model != null) {
3033             Enumeration<TreePath> paths = expandedState.keys();
3034 
3035             if(paths != null) {
3036                 Vector<Object> state = new Vector<Object>();
3037 
3038                 while(paths.hasMoreElements()) {
3039                     TreePath path = paths.nextElement();
3040                     Object     archivePath;
3041 
3042                     try {
3043                         archivePath = getModelIndexsForPath(path);
3044                     } catch (Error error) {
3045                         archivePath = null;
3046                     }
3047                     if(archivePath != null) {
3048                         state.addElement(archivePath);
3049                         state.addElement(expandedState.get(path));
3050                     }
3051                 }
3052                 return state;
3053             }
3054         }
3055         return null;
3056     }
3057 
3058     /**
3059      * Updates the expanded state of nodes in the tree based on the


3297      * @return the "block" increment for scrolling in the specified direction
3298      * @see JScrollBar#setBlockIncrement(int)
3299      */
3300     public int getScrollableBlockIncrement(Rectangle visibleRect,
3301                                            int orientation, int direction) {
3302         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
3303             visibleRect.width;
3304     }
3305 
3306     /**
3307      * Returns false to indicate that the width of the viewport does not
3308      * determine the width of the table, unless the preferred width of
3309      * the tree is smaller than the viewports width.  In other words:
3310      * ensure that the tree is never smaller than its viewport.
3311      *
3312      * @return false
3313      * @see Scrollable#getScrollableTracksViewportWidth
3314      */
3315     public boolean getScrollableTracksViewportWidth() {
3316         if (getParent() instanceof JViewport) {
3317             return getParent().getWidth() > getPreferredSize().width;
3318         }
3319         return false;
3320     }
3321 
3322     /**
3323      * Returns false to indicate that the height of the viewport does not
3324      * determine the height of the table, unless the preferred height
3325      * of the tree is smaller than the viewports height.  In other words:
3326      * ensure that the tree is never smaller than its viewport.
3327      *
3328      * @return false
3329      * @see Scrollable#getScrollableTracksViewportHeight
3330      */
3331     public boolean getScrollableTracksViewportHeight() {
3332         if (getParent() instanceof JViewport) {
3333             return getParent().getHeight() > getPreferredSize().height;
3334         }
3335         return false;
3336     }
3337 
3338     /**
3339      * Sets the expanded state of this <code>JTree</code>.
3340      * If <code>state</code> is
3341      * true, all parents of <code>path</code> and path are marked as
3342      * expanded. If <code>state</code> is false, all parents of
3343      * <code>path</code> are marked EXPANDED, but <code>path</code> itself
3344      * is marked collapsed.<p>
3345      * This will fail if a <code>TreeWillExpandListener</code> vetos it.
3346      */
3347     protected void setExpandedState(TreePath path, boolean state) {
3348         if(path != null) {
3349             // Make sure all parents of path are expanded.
3350             Stack<TreePath> stack;
3351             TreePath parentPath = path.getParentPath();
3352 
3353             if (expandedStack.size() == 0) {
3354                 stack = new Stack<TreePath>();
3355             }
3356             else {
3357                 stack = expandedStack.pop();
3358             }
3359 
3360             try {
3361                 while(parentPath != null) {
3362                     if(isExpanded(parentPath)) {
3363                         parentPath = null;
3364                     }
3365                     else {
3366                         stack.push(parentPath);
3367                         parentPath = parentPath.getParentPath();
3368                     }
3369                 }
3370                 for(int counter = stack.size() - 1; counter >= 0; counter--) {
3371                     parentPath = stack.pop();
3372                     if(!isExpanded(parentPath)) {
3373                         try {
3374                             fireTreeWillExpand(parentPath);
3375                         } catch (ExpandVetoException eve) {
3376                             // Expand vetoed!
3377                             return;
3378                         }
3379                         expandedState.put(parentPath, Boolean.TRUE);
3380                         fireTreeExpanded(parentPath);
3381                         if (accessibleContext != null) {
3382                             ((AccessibleJTree)accessibleContext).
3383                                               fireVisibleDataPropertyChange();
3384                         }
3385                     }
3386                 }
3387             }
3388             finally {
3389                 if (expandedStack.size() < TEMP_STACK_SIZE) {
3390                     stack.removeAllElements();
3391                     expandedStack.push(stack);


3431                     if (accessibleContext != null) {
3432                         ((AccessibleJTree)accessibleContext).
3433                                           fireVisibleDataPropertyChange();
3434                     }
3435                 }
3436             }
3437         }
3438     }
3439 
3440     /**
3441      * Returns an <code>Enumeration</code> of <code>TreePaths</code>
3442      * that have been expanded that
3443      * are descendants of <code>parent</code>.
3444      */
3445     protected Enumeration<TreePath>
3446         getDescendantToggledPaths(TreePath parent)
3447     {
3448         if(parent == null)
3449             return null;
3450 
3451         Vector<TreePath> descendants = new Vector<TreePath>();
3452         Enumeration<TreePath> nodes = expandedState.keys();

3453 
3454         while(nodes.hasMoreElements()) {
3455             TreePath path = nodes.nextElement();
3456             if(parent.isDescendant(path))
3457                 descendants.addElement(path);
3458         }
3459         return descendants.elements();
3460     }
3461 
3462     /**
3463      * Removes any descendants of the <code>TreePaths</code> in
3464      * <code>toRemove</code>
3465      * that have been expanded.
3466      */
3467      protected void
3468          removeDescendantToggledPaths(Enumeration<TreePath> toRemove)
3469     {
3470          if(toRemove != null) {
3471              while(toRemove.hasMoreElements()) {
3472                  Enumeration descendants = getDescendantToggledPaths
3473                          (toRemove.nextElement());
3474 
3475                  if(descendants != null) {
3476                      while(descendants.hasMoreElements()) {
3477                          expandedState.remove(descendants.nextElement());
3478                      }
3479                  }
3480              }
3481          }
3482      }
3483 
3484      /**
3485       * Clears the cache of toggled tree paths. This does NOT send out
3486       * any <code>TreeExpansionListener</code> events.
3487       */
3488      protected void clearToggledPaths() {
3489          expandedState.clear();
3490      }
3491 
3492      /**
3493       * Creates and returns an instance of <code>TreeModelHandler</code>.


4038             if (path != null) {
4039                 // TIGER - 4839971
4040                 // Set parent to null so AccessibleJTreeNode computes
4041                 // its parent.
4042                 AccessibleJTreeNode node = new AccessibleJTreeNode(JTree.this,
4043                                                                    path,
4044                                                                    null);
4045                 PropertyChangeEvent pce = new PropertyChangeEvent(node,
4046                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
4047                     AccessibleState.COLLAPSED,
4048                     AccessibleState.EXPANDED);
4049                 firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
4050                                    null, pce);
4051             }
4052         }
4053 
4054 
4055         private AccessibleContext getCurrentAccessibleContext() {
4056             Component c = getCurrentComponent();
4057             if (c instanceof Accessible) {
4058                 return c.getAccessibleContext();
4059             } else {
4060                 return null;
4061             }
4062         }
4063 
4064         private Component getCurrentComponent() {
4065             // is the object visible?
4066             // if so, get row, selected, focus & leaf state,
4067             // and then get the renderer component and return it
4068             TreeModel model = JTree.this.getModel();
4069             if (model == null) {
4070                 return null;
4071             }
4072             TreePath path = new TreePath(model.getRoot());
4073             if (JTree.this.isVisible(path)) {
4074                 TreeCellRenderer r = JTree.this.getCellRenderer();
4075                 TreeUI ui = JTree.this.getUI();
4076                 if (ui != null) {
4077                     int row = ui.getRowForPath(JTree.this, path);
4078                     int lsr = JTree.this.getLeadSelectionRow();


4361                     objChildPath[objChildPath.length-1] = childObj;
4362                     return new TreePath(objChildPath);
4363                 }
4364             }
4365 
4366             /**
4367              * Get the AccessibleContext associated with this tree node.
4368              * In the implementation of the Java Accessibility API for
4369              * this class, return this object, which is its own
4370              * AccessibleContext.
4371              *
4372              * @return this object
4373              */
4374             public AccessibleContext getAccessibleContext() {
4375                 return this;
4376             }
4377 
4378             private AccessibleContext getCurrentAccessibleContext() {
4379                 Component c = getCurrentComponent();
4380                 if (c instanceof Accessible) {
4381                     return c.getAccessibleContext();
4382                 } else {
4383                     return null;
4384                 }
4385             }
4386 
4387             private Component getCurrentComponent() {
4388                 // is the object visible?
4389                 // if so, get row, selected, focus & leaf state,
4390                 // and then get the renderer component and return it
4391                 if (tree.isVisible(path)) {
4392                     TreeCellRenderer r = tree.getCellRenderer();
4393                     if (r == null) {
4394                         return null;
4395                     }
4396                     TreeUI ui = tree.getUI();
4397                     if (ui != null) {
4398                         int row = ui.getRowForPath(JTree.this, path);
4399                         boolean selected = tree.isPathSelected(path);
4400                         boolean expanded = tree.isExpanded(path);
4401                         boolean hasFocus = false; // how to tell?? -PK


4905                         return false;
4906                     }
4907                 }
4908             }
4909 
4910             public void setEnabled(boolean b) {
4911                 AccessibleContext ac = getCurrentAccessibleContext();
4912                 if (ac instanceof AccessibleComponent) {
4913                     ((AccessibleComponent) ac).setEnabled(b);
4914                 } else {
4915                     Component c = getCurrentComponent();
4916                     if (c != null) {
4917                         c.setEnabled(b);
4918                     }
4919                 }
4920             }
4921 
4922             public boolean isVisible() {
4923                 Rectangle pathBounds = tree.getPathBounds(path);
4924                 Rectangle parentBounds = tree.getVisibleRect();
4925                 return pathBounds != null && parentBounds != null &&
4926                         parentBounds.intersects(pathBounds);




4927             }
4928 
4929             public void setVisible(boolean b) {
4930             }
4931 
4932             public boolean isShowing() {
4933                 return (tree.isShowing() && isVisible());
4934             }
4935 
4936             public boolean contains(Point p) {
4937                 AccessibleContext ac = getCurrentAccessibleContext();
4938                 if (ac instanceof AccessibleComponent) {
4939                     Rectangle r = ((AccessibleComponent) ac).getBounds();
4940                     return r.contains(p);
4941                 } else {
4942                     Component c = getCurrentComponent();
4943                     if (c != null) {
4944                         Rectangle r = c.getBounds();
4945                         return r.contains(p);
4946                     } else {


< prev index next >