mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			3187 lines
		
	
	
		
			81 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			3187 lines
		
	
	
		
			81 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* JTree.java
 | |
|    Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package javax.swing;
 | |
| 
 | |
| import java.awt.Color;
 | |
| import java.awt.Cursor;
 | |
| import java.awt.Dimension;
 | |
| import java.awt.Font;
 | |
| import java.awt.FontMetrics;
 | |
| import java.awt.Point;
 | |
| import java.awt.Rectangle;
 | |
| import java.awt.event.FocusListener;
 | |
| import java.beans.PropertyChangeListener;
 | |
| import java.io.Serializable;
 | |
| import java.util.Enumeration;
 | |
| import java.util.Hashtable;
 | |
| import java.util.Iterator;
 | |
| import java.util.Locale;
 | |
| import java.util.Vector;
 | |
| 
 | |
| import javax.accessibility.Accessible;
 | |
| import javax.accessibility.AccessibleAction;
 | |
| import javax.accessibility.AccessibleComponent;
 | |
| import javax.accessibility.AccessibleContext;
 | |
| import javax.accessibility.AccessibleRole;
 | |
| import javax.accessibility.AccessibleSelection;
 | |
| import javax.accessibility.AccessibleState;
 | |
| import javax.accessibility.AccessibleStateSet;
 | |
| import javax.accessibility.AccessibleText;
 | |
| import javax.accessibility.AccessibleValue;
 | |
| import javax.swing.event.TreeExpansionEvent;
 | |
| import javax.swing.event.TreeExpansionListener;
 | |
| import javax.swing.event.TreeModelEvent;
 | |
| import javax.swing.event.TreeModelListener;
 | |
| import javax.swing.event.TreeSelectionEvent;
 | |
| import javax.swing.event.TreeSelectionListener;
 | |
| import javax.swing.event.TreeWillExpandListener;
 | |
| import javax.swing.plaf.TreeUI;
 | |
| import javax.swing.text.Position;
 | |
| import javax.swing.tree.DefaultMutableTreeNode;
 | |
| import javax.swing.tree.DefaultTreeModel;
 | |
| import javax.swing.tree.DefaultTreeSelectionModel;
 | |
| import javax.swing.tree.ExpandVetoException;
 | |
| import javax.swing.tree.TreeCellEditor;
 | |
| import javax.swing.tree.TreeCellRenderer;
 | |
| import javax.swing.tree.TreeModel;
 | |
| import javax.swing.tree.TreeNode;
 | |
| import javax.swing.tree.TreePath;
 | |
| import javax.swing.tree.TreeSelectionModel;
 | |
| 
 | |
| public class JTree extends JComponent implements Scrollable, Accessible
 | |
| {
 | |
| 
 | |
|   /**
 | |
|    * This class implements accessibility support for the JTree class. It
 | |
|    * provides an implementation of the Java Accessibility API appropriate
 | |
|    * to tree user-interface elements.
 | |
|    */
 | |
|   protected class AccessibleJTree extends JComponent.AccessibleJComponent
 | |
|       implements AccessibleSelection, TreeSelectionListener, TreeModelListener,
 | |
|       TreeExpansionListener
 | |
|   {
 | |
| 
 | |
|     /**
 | |
|      * This class implements accessibility support for the JTree child. It provides
 | |
|      * an implementation of the Java Accessibility API appropriate to tree nodes.
 | |
|      */
 | |
|     protected class AccessibleJTreeNode extends AccessibleContext
 | |
|        implements Accessible, AccessibleComponent, AccessibleSelection,
 | |
|        AccessibleAction
 | |
|     {
 | |
| 
 | |
|       private JTree tree;
 | |
|       private TreePath tp;
 | |
|       private Accessible acc;
 | |
|       private AccessibleStateSet states;
 | |
|       private Vector selectionList;
 | |
|       private Vector actionList;
 | |
|       private TreeModel mod;
 | |
|       private Cursor cursor;
 | |
| 
 | |
|       /**
 | |
|        * Constructs an AccessibleJTreeNode
 | |
|        *
 | |
|        * @param t - the current tree
 | |
|        * @param p - the current path to be dealt with
 | |
|        * @param ap - the accessible object to use
 | |
|        */
 | |
|       public AccessibleJTreeNode(JTree t, TreePath p, Accessible ap)
 | |
|       {
 | |
|         states = new AccessibleStateSet();
 | |
|         selectionList = new Vector();
 | |
|         actionList = new Vector();
 | |
|         mod = tree.getModel();
 | |
|         cursor = JTree.this.getCursor();
 | |
| 
 | |
|         tree = t;
 | |
|         tp = p;
 | |
|         acc = ap;
 | |
| 
 | |
|         // Add all the children of this path that may already be
 | |
|         // selected to the selection list.
 | |
|         TreePath[] selected = tree.getSelectionPaths();
 | |
|         for (int i = 0; i < selected.length; i++)
 | |
|           {
 | |
|             TreePath sel = selected[i];
 | |
|             if ((sel.getParentPath()).equals(tp))
 | |
|               selectionList.add(sel);
 | |
|           }
 | |
| 
 | |
|         // Add all the actions available for a node to
 | |
|         // the action list.
 | |
|         actionList.add("EXPAND");
 | |
|         actionList.add("COLLAPSE");
 | |
|         actionList.add("EDIT");
 | |
|         actionList.add("SELECT");
 | |
|         actionList.add("DESELECT");
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Adds the specified selected item in the object to the object's
 | |
|        * selection.
 | |
|        *
 | |
|        * @param i - the i-th child of this node.
 | |
|        */
 | |
|       public void addAccessibleSelection(int i)
 | |
|       {
 | |
|         if (mod != null)
 | |
|           {
 | |
|             Object child = mod.getChild(tp.getLastPathComponent(), i);
 | |
|             if (child != null)
 | |
|               {
 | |
|                 if (!states.contains(AccessibleState.MULTISELECTABLE))
 | |
|                   clearAccessibleSelection();
 | |
|                 selectionList.add(child);
 | |
|                 tree.addSelectionPath(tp.pathByAddingChild(child));
 | |
|               }
 | |
|           }
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Adds the specified focus listener to receive focus events
 | |
|        * from this component.
 | |
|        *
 | |
|        * @param l - the new focus listener
 | |
|        */
 | |
|       public void addFocusListener(FocusListener l)
 | |
|       {
 | |
|         tree.addFocusListener(l);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Add a PropertyChangeListener to the listener list.
 | |
|        *
 | |
|        * @param l - the new property change listener
 | |
|        */
 | |
|       public void addPropertyChangeListener(PropertyChangeListener l)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Clears the selection in the object, so that nothing in the
 | |
|        * object is selected.
 | |
|        */
 | |
|       public void clearAccessibleSelection()
 | |
|       {
 | |
|         selectionList.clear();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Checks whether the specified point is within this object's
 | |
|        * bounds, where the point's x and y coordinates are defined to be
 | |
|        * relative to the coordinate system of the object.
 | |
|        *
 | |
|        * @param p - the point to check
 | |
|        * @return true if p is in the bounds
 | |
|        */
 | |
|       public boolean contains(Point p)
 | |
|       {
 | |
|         return getBounds().contains(p);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Perform the specified Action on the tree node.
 | |
|        *
 | |
|        * @param i - the i-th action to perform
 | |
|        * @return true if the the action was performed; else false.
 | |
|        */
 | |
|       public boolean doAccessibleAction(int i)
 | |
|       {
 | |
|         if (i >= actionList.size() || i < 0)
 | |
|           return false;
 | |
| 
 | |
|         if (actionList.get(i).equals("EXPAND"))
 | |
|           tree.expandPath(tp);
 | |
|         else if (actionList.get(i).equals("COLLAPSE"))
 | |
|           tree.collapsePath(tp);
 | |
|         else if (actionList.get(i).equals("SELECT"))
 | |
|           tree.addSelectionPath(tp);
 | |
|         else if (actionList.get(i).equals("DESELECT"))
 | |
|           tree.removeSelectionPath(tp);
 | |
|         else if (actionList.get(i).equals("EDIT"))
 | |
|           tree.startEditingAtPath(tp);
 | |
|         else
 | |
|           return false;
 | |
|         return true;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the AccessibleAction associated with this object.
 | |
|        *
 | |
|        * @return the action
 | |
|        */
 | |
|       public AccessibleAction getAccessibleAction()
 | |
|       {
 | |
|         return this;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns the number of accessible actions available in this tree node.
 | |
|        *
 | |
|        * @return the number of actions
 | |
|        */
 | |
|       public int getAccessibleActionCount()
 | |
|       {
 | |
|         return actionList.size();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Return a description of the specified action of the tree node.
 | |
|        *
 | |
|        * @param i - the i-th action's description
 | |
|        * @return a description of the action
 | |
|        */
 | |
|       public String getAccessibleActionDescription(int i)
 | |
|       {
 | |
|         if (i < 0 || i >= actionList.size())
 | |
|           return (actionList.get(i)).toString();
 | |
|         return super.getAccessibleDescription();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns the Accessible child, if one exists, contained at the
 | |
|        * local coordinate Point.
 | |
|        *
 | |
|        * @param p - the point of the accessible
 | |
|        * @return the accessible at point p if it exists
 | |
|        */
 | |
|       public Accessible getAccessibleAt(Point p)
 | |
|       {
 | |
|         TreePath acc = tree.getClosestPathForLocation(p.x, p.y);
 | |
|         if (acc != null)
 | |
|           return new AccessibleJTreeNode(tree, acc, this);
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Return the specified Accessible child of the object.
 | |
|        *
 | |
|        * @param i - the i-th child of the current path
 | |
|        * @return the child if it exists
 | |
|        */
 | |
|       public Accessible getAccessibleChild(int i)
 | |
|       {
 | |
|         if (mod != null)
 | |
|           {
 | |
|             Object child = mod.getChild(tp.getLastPathComponent(), i);
 | |
|             if (child != null)
 | |
|               return new AccessibleJTreeNode(tree, tp.pathByAddingChild(child),
 | |
|                                              acc);
 | |
|           }
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns the number of accessible children in the object.
 | |
|        *
 | |
|        * @return the number of children the current node has
 | |
|        */
 | |
|       public int getAccessibleChildrenCount()
 | |
|       {
 | |
|         TreeModel mod = getModel();
 | |
|         if (mod != null)
 | |
|           return mod.getChildCount(tp.getLastPathComponent());
 | |
|         return 0;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the AccessibleComponent associated with this object.
 | |
|        *
 | |
|        * @return the accessible component if it is supported.
 | |
|        */
 | |
|       public AccessibleComponent getAccessibleComponent()
 | |
|       {
 | |
|         return this;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the AccessibleContext associated with this tree node.
 | |
|        *
 | |
|        * @return an instance of this class
 | |
|        */
 | |
|       public AccessibleContext getAccessibleContext()
 | |
|       {
 | |
|         return this;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the accessible description of this object.
 | |
|        *
 | |
|        * @return the accessible description
 | |
|        */
 | |
|       public String getAccessibleDescription()
 | |
|       {
 | |
|         return super.getAccessibleDescription();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the index of this object in its accessible parent.
 | |
|        *
 | |
|        * @return the index of this in the parent.
 | |
|        */
 | |
|       public int getAccessibleIndexInParent()
 | |
|       {
 | |
|         AccessibleContext parent = getAccessibleParent().getAccessibleContext();
 | |
|         if (parent != null)
 | |
|           for (int i = 0; i < parent.getAccessibleChildrenCount(); i++)
 | |
|             {
 | |
|               if ((parent.getAccessibleChild(i)).equals(this))
 | |
|                 return i;
 | |
|             }
 | |
|         return -1;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the accessible name of this object.
 | |
|        *
 | |
|        * @return the accessible name
 | |
|        */
 | |
|       public String getAccessibleName()
 | |
|       {
 | |
|         return super.getAccessibleName();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the Accessible parent of this object.
 | |
|        *
 | |
|        * @return the accessible parent if it exists.
 | |
|        */
 | |
|       public Accessible getAccessibleParent()
 | |
|       {
 | |
|         return super.getAccessibleParent();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the role of this object.
 | |
|        *
 | |
|        * @return the accessible role
 | |
|        */
 | |
|       public AccessibleRole getAccessibleRole()
 | |
|       {
 | |
|         return AccessibleJTree.this.getAccessibleRole();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the AccessibleSelection associated with this object if one exists.
 | |
|        *
 | |
|        * @return the accessible selection for this.
 | |
|        */
 | |
|       public AccessibleSelection getAccessibleSelection()
 | |
|       {
 | |
|         return this;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns an Accessible representing the specified selected item
 | |
|        * in the object.
 | |
|        *
 | |
|        * @return the accessible representing a certain selected item.
 | |
|        */
 | |
|       public Accessible getAccessibleSelection(int i)
 | |
|       {
 | |
|         if (i > 0 && i < getAccessibleSelectionCount())
 | |
|             return new AccessibleJTreeNode(tree,
 | |
|                   tp.pathByAddingChild(selectionList.get(i)), acc);
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns the number of items currently selected.
 | |
|        *
 | |
|        * @return the number of items selected.
 | |
|        */
 | |
|       public int getAccessibleSelectionCount()
 | |
|       {
 | |
|         return selectionList.size();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the state set of this object.
 | |
|        *
 | |
|        * @return the state set for this object
 | |
|        */
 | |
|       public AccessibleStateSet getAccessibleStateSet()
 | |
|       {
 | |
|         if (isVisible())
 | |
|           states.add(AccessibleState.VISIBLE);
 | |
|         if (tree.isCollapsed(tp))
 | |
|           states.add(AccessibleState.COLLAPSED);
 | |
|         if (tree.isEditable())
 | |
|           states.add(AccessibleState.EDITABLE);
 | |
|         if (mod != null &&
 | |
|             !mod.isLeaf(tp.getLastPathComponent()))
 | |
|           states.add(AccessibleState.EXPANDABLE);
 | |
|         if (tree.isExpanded(tp))
 | |
|           states.add(AccessibleState.EXPANDED);
 | |
|         if (isFocusable())
 | |
|           states.add(AccessibleState.FOCUSABLE);
 | |
|         if (hasFocus())
 | |
|           states.add(AccessibleState.FOCUSED);
 | |
|         if (tree.getSelectionModel().getSelectionMode() !=
 | |
|           TreeSelectionModel.SINGLE_TREE_SELECTION)
 | |
|           states.add(AccessibleState.MULTISELECTABLE);
 | |
|         if (tree.isOpaque())
 | |
|           states.add(AccessibleState.OPAQUE);
 | |
|         if (tree.isPathSelected(tp))
 | |
|           states.add(AccessibleState.SELECTED);
 | |
|         if (isShowing())
 | |
|           states.add(AccessibleState.SHOWING);
 | |
| 
 | |
|         states.add(AccessibleState.SELECTABLE);
 | |
|         return states;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the AccessibleText associated with this object if one exists.
 | |
|        *
 | |
|        * @return the accessible text
 | |
|        */
 | |
|       public AccessibleText getAccessibleText()
 | |
|       {
 | |
|         return super.getAccessibleText();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the AccessibleValue associated with this object if one exists.
 | |
|        *
 | |
|        * @return the accessible value if it exists
 | |
|        */
 | |
|       public AccessibleValue getAccessibleValue()
 | |
|       {
 | |
|         return super.getAccessibleValue();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the background color of this object.
 | |
|        *
 | |
|        * @return the color of the background.
 | |
|        */
 | |
|       public Color getBackground()
 | |
|       {
 | |
|         return tree.getBackground();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Gets the bounds of this object in the form of a Rectangle object.
 | |
|        *
 | |
|        * @return the bounds of the current node.
 | |
|        */
 | |
|       public Rectangle getBounds()
 | |
|       {
 | |
|         return tree.getPathBounds(tp);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Gets the Cursor of this object.
 | |
|        *
 | |
|        * @return the cursor for the current node
 | |
|        */
 | |
|       public Cursor getCursor()
 | |
|       {
 | |
|         return cursor;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Gets the Font of this object.
 | |
|        *
 | |
|        * @return the font for the current node
 | |
|        */
 | |
|       public Font getFont()
 | |
|       {
 | |
|         return tree.getFont();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Gets the FontMetrics of this object.
 | |
|        *
 | |
|        * @param f - the current font.
 | |
|        * @return the font metrics for the given font.
 | |
|        */
 | |
|       public FontMetrics getFontMetrics(Font f)
 | |
|       {
 | |
|         return tree.getFontMetrics(f);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Get the foreground color of this object.
 | |
|        *
 | |
|        * @return the foreground for this object.
 | |
|        */
 | |
|       public Color getForeground()
 | |
|       {
 | |
|         return tree.getForeground();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Gets the locale of the component.
 | |
|        *
 | |
|        * @return the locale of the component.
 | |
|        */
 | |
|       public Locale getLocale()
 | |
|       {
 | |
|         return tree.getLocale();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Gets the location of the object relative to the
 | |
|        * parent in the form of a point specifying the object's
 | |
|        * top-left corner in the screen's coordinate space.
 | |
|        *
 | |
|        * @return the location of the current node.
 | |
|        */
 | |
|       public Point getLocation()
 | |
|       {
 | |
|         return getLocationInJTree();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns the location in the tree.
 | |
|        *
 | |
|        * @return the location in the JTree.
 | |
|        */
 | |
|       protected Point getLocationInJTree()
 | |
|       {
 | |
|         Rectangle bounds = tree.getPathBounds(tp);
 | |
|         return new Point(bounds.x, bounds.y);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns the location of the object on the screen.
 | |
|        *
 | |
|        * @return the location of the object on the screen.
 | |
|        */
 | |
|       public Point getLocationOnScreen()
 | |
|       {
 | |
|         Point loc = getLocation();
 | |
|         SwingUtilities.convertPointToScreen(loc, tree);
 | |
|         return loc;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns the size of this object in the form of a Dimension object.
 | |
|        *
 | |
|        * @return the size of the object
 | |
|        */
 | |
|       public Dimension getSize()
 | |
|       {
 | |
|         Rectangle b = getBounds();
 | |
|         return b.getSize();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns true if the current child of this object is selected.
 | |
|        *
 | |
|        * @param i - the child of the current node
 | |
|        * @return true if the child is selected.
 | |
|        */
 | |
|       public boolean isAccessibleChildSelected(int i)
 | |
|       {
 | |
|         Object child = mod.getChild(tp.getLastPathComponent(), i);
 | |
|         if (child != null)
 | |
|           return tree.isPathSelected(tp.pathByAddingChild(child));
 | |
|         return false;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Determines if the object is enabled.
 | |
|        *
 | |
|        * @return true if the tree is enabled
 | |
|        */
 | |
|       public boolean isEnabled()
 | |
|       {
 | |
|         return tree.isEnabled();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Returns whether this object can accept focus or not.
 | |
|        *
 | |
|        * @return true, it is always focus traversable
 | |
|        */
 | |
|       public boolean isFocusTraversable()
 | |
|       {
 | |
|         return true;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Determines if the object is showing.
 | |
|        *
 | |
|        * @return true if the object is visible and the
 | |
|        * parent is visible.
 | |
|        */
 | |
|       public boolean isShowing()
 | |
|       {
 | |
|         return isVisible() && tree.isShowing();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Determines if the object is visible.
 | |
|        *
 | |
|        * @return true if the object is visible.
 | |
|        */
 | |
|       public boolean isVisible()
 | |
|       {
 | |
|         return tree.isVisible(tp);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Removes the specified selected item in the object from the
 | |
|        * object's selection.
 | |
|        *
 | |
|        * @param i - the specified item to remove
 | |
|        */
 | |
|       public void removeAccessibleSelection(int i)
 | |
|       {
 | |
|         if (mod != null)
 | |
|           {
 | |
|             Object child = mod.getChild(tp.getLastPathComponent(), i);
 | |
|             if (child != null)
 | |
|               {
 | |
|                 if (!states.contains(AccessibleState.MULTISELECTABLE))
 | |
|                   clearAccessibleSelection();
 | |
|                 if (selectionList.contains(child))
 | |
|                   {
 | |
|                     selectionList.remove(child);
 | |
|                     tree.removeSelectionPath(tp.pathByAddingChild(child));
 | |
|                   }
 | |
|               }
 | |
|           }
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Removes the specified focus listener so it no longer receives focus
 | |
|        * events from this component.
 | |
|        *
 | |
|        * @param l - the focus listener to remove
 | |
|        */
 | |
|       public void removeFocusListener(FocusListener l)
 | |
|       {
 | |
|         tree.removeFocusListener(l);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Remove a PropertyChangeListener from the listener list.
 | |
|        *
 | |
|        * @param l - the property change listener to remove.
 | |
|        */
 | |
|       public void removePropertyChangeListener(PropertyChangeListener l)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Requests focus for this object.
 | |
|        */
 | |
|       public void requestFocus()
 | |
|       {
 | |
|         tree.requestFocus();
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Causes every selected item in the object to be selected if the object
 | |
|        * supports multiple selections.
 | |
|        */
 | |
|       public void selectAllAccessibleSelection()
 | |
|       {
 | |
|         Object parent = tp.getLastPathComponent();
 | |
|         if (mod != null)
 | |
|           {
 | |
|             for (int i = 0; i < mod.getChildCount(parent); i++)
 | |
|               {
 | |
|                 Object child = mod.getChild(parent, i);
 | |
|                 if (child != null)
 | |
|                   {
 | |
|                     if (!states.contains(AccessibleState.MULTISELECTABLE))
 | |
|                       clearAccessibleSelection();
 | |
|                     if (selectionList.contains(child))
 | |
|                       {
 | |
|                         selectionList.add(child);
 | |
|                         tree.addSelectionPath(tp.pathByAddingChild(child));
 | |
|                       }
 | |
|                   }
 | |
|               }
 | |
|           }
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Set the accessible description of this object.
 | |
|        *
 | |
|        * @param s - the string to set the accessible description to.
 | |
|        */
 | |
|       public void setAccessibleDescription(String s)
 | |
|       {
 | |
|         super.setAccessibleDescription(s);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Set the localized accessible name of this object.
 | |
|        *
 | |
|        * @param s - the string to set the accessible name to.
 | |
|        */
 | |
|       public void setAccessibleName(String s)
 | |
|       {
 | |
|         super.setAccessibleName(s);
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Set the background color of this object.
 | |
|        *
 | |
|        * @param c - the color to set the background to.
 | |
|        */
 | |
|       public void setBackground(Color c)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Sets the bounds of this object in the form of a Rectangle object.
 | |
|        *
 | |
|        * @param r - the bounds to set the object o
 | |
|        */
 | |
|       public void setBounds(Rectangle r)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Sets the Cursor of this object.
 | |
|        *
 | |
|        * @param c - the new cursor
 | |
|        */
 | |
|       public void setCursor(Cursor c)
 | |
|       {
 | |
|         cursor = c;
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Sets the enabled state of the object.
 | |
|        *
 | |
|        * @param b - boolean to enable or disable object
 | |
|        */
 | |
|       public void setEnabled(boolean b)
 | |
|       {
 | |
|          // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Sets the Font of this object.
 | |
|        *
 | |
|        * @param f - the new font.
 | |
|        */
 | |
|       public void setFont(Font f)
 | |
|       {
 | |
|          // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Sets the foreground color of this object.
 | |
|        *
 | |
|        * @param c - the new foreground color.
 | |
|        */
 | |
|       public void setForeground(Color c)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Sets the location of the object relative to the parent.
 | |
|        *
 | |
|        * @param p - the new location for the object.
 | |
|        */
 | |
|       public void setLocation(Point p)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Resizes this object so that it has width and height.
 | |
|        *
 | |
|        * @param d - the new size for the object.
 | |
|        */
 | |
|       public void setSize(Dimension d)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
| 
 | |
|       /**
 | |
|        * Sets the visible state of the object.
 | |
|        *
 | |
|        * @param b - sets the objects visibility.
 | |
|        */
 | |
|       public void setVisible(boolean b)
 | |
|       {
 | |
|         // Nothing to do here.
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Constructor
 | |
|      */
 | |
|     public AccessibleJTree()
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds the specified selected item in the object to the object's selection.
 | |
|      *
 | |
|      * @param i - the row to add to the tree's selection
 | |
|      */
 | |
|     public void addAccessibleSelection(int i)
 | |
|     {
 | |
|       addSelectionInterval(i, i);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Clears the selection in the object, so that nothing in the object is selected.
 | |
|      */
 | |
|     public void clearAccessibleSelection()
 | |
|     {
 | |
|       clearSelection();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Fire a visible data property change notification.
 | |
|      */
 | |
|     public void fireVisibleDataPropertyChange()
 | |
|     {
 | |
|       treeDidChange();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the Accessible child, if one exists, contained at the local
 | |
|      * coordinate Point.
 | |
|      *
 | |
|      * @param p - the point of the accessible to get.
 | |
|      * @return the accessible at point p.
 | |
|      */
 | |
|     public Accessible getAccessibleAt(Point p)
 | |
|     {
 | |
|       TreePath tp = getClosestPathForLocation(p.x, p.y);
 | |
|       if (tp != null)
 | |
|         return new AccessibleJTreeNode(JTree.this, tp, null);
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the nth Accessible child of the object.
 | |
|      *
 | |
|      * @param i - the accessible child to get
 | |
|      * @return the i-th child
 | |
|      */
 | |
|     public Accessible getAccessibleChild(int i)
 | |
|     {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the number of top-level children nodes of this JTree.
 | |
|      *
 | |
|      * @return the number of top-level children
 | |
|      */
 | |
|     public int getAccessibleChildrenCount()
 | |
|     {
 | |
|       TreeModel model = getModel();
 | |
|       if (model != null)
 | |
|         return model.getChildCount(model.getRoot());
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the index of this object in its accessible parent.
 | |
|      *
 | |
|      * @return the index of this object.
 | |
|      */
 | |
|     public int getAccessibleIndexInParent()
 | |
|     {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the role of this object.
 | |
|      *
 | |
|      * @return the role of this object
 | |
|      */
 | |
|     public AccessibleRole getAccessibleRole()
 | |
|     {
 | |
|       return AccessibleRole.TREE;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the AccessibleSelection associated with this object.
 | |
|      *
 | |
|      * @return the accessible selection of the tree
 | |
|      */
 | |
|     public AccessibleSelection getAccessibleSelection()
 | |
|     {
 | |
|       TreeModel mod = getModel();
 | |
|       if (mod != null)
 | |
|         return (new AccessibleJTreeNode(JTree.this,
 | |
|                   new TreePath(mod.getRoot()), null)).getAccessibleSelection();
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns an Accessible representing the specified selected item in the object.
 | |
|      *
 | |
|      * @return the i-th accessible in the selection
 | |
|      */
 | |
|     public Accessible getAccessibleSelection(int i)
 | |
|     {
 | |
|       TreeModel mod = getModel();
 | |
|       if (mod != null)
 | |
|         return (new AccessibleJTreeNode(JTree.this,
 | |
|                   new TreePath(mod.getRoot()), null)).getAccessibleSelection(i);
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the number of items currently selected.
 | |
|      *
 | |
|      * @return the number of selected accessibles.
 | |
|      */
 | |
|     public int getAccessibleSelectionCount()
 | |
|     {
 | |
|       return getSelectionCount();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns true if the current child of this object is selected.
 | |
|      *
 | |
|      * @param i - the child of this object
 | |
|      * @return true if the i-th child is selected.
 | |
|      */
 | |
|     public boolean isAccessibleChildSelected(int i)
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|       return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Removes the specified selected item in the object from the object's
 | |
|      * selection.
 | |
|      *
 | |
|      * @param i - the i-th selected item to remove
 | |
|      */
 | |
|     public void removeAccessibleSelection(int i)
 | |
|     {
 | |
|       removeSelectionInterval(i, i);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Causes every selected item in the object to be selected if the object
 | |
|      * supports multiple selections.
 | |
|      */
 | |
|     public void selectAllAccessibleSelection()
 | |
|     {
 | |
|       if (getSelectionModel().getSelectionMode() !=
 | |
|         TreeSelectionModel.SINGLE_TREE_SELECTION)
 | |
|       addSelectionInterval(0, getVisibleRowCount());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tree Collapsed notification
 | |
|      *
 | |
|      * @param e - the event
 | |
|      */
 | |
|     public void treeCollapsed(TreeExpansionEvent e)
 | |
|     {
 | |
|       fireTreeCollapsed(e.getPath());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tree Model Expansion notification.
 | |
|      *
 | |
|      * @param e - the event
 | |
|      */
 | |
|     public void treeExpanded(TreeExpansionEvent e)
 | |
|     {
 | |
|       fireTreeExpanded(e.getPath());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tree Model Node change notification.
 | |
|      *
 | |
|      * @param e - the event
 | |
|      */
 | |
|     public void treeNodesChanged(TreeModelEvent e)
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tree Model Node change notification.
 | |
|      *
 | |
|      * @param e - the event
 | |
|      */
 | |
|     public void treeNodesInserted(TreeModelEvent e)
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tree Model Node change notification.
 | |
|      *
 | |
|      * @param e - the event
 | |
|      */
 | |
|     public void treeNodesRemoved(TreeModelEvent e)
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tree Model structure change change notification.
 | |
|      *
 | |
|      * @param e - the event
 | |
|      */
 | |
|     public void treeStructureChanged(TreeModelEvent e)
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tree Selection Listener value change method.
 | |
|      *
 | |
|      * @param e - the event
 | |
|      */
 | |
|     public void valueChanged(TreeSelectionEvent e)
 | |
|     {
 | |
|       fireValueChanged(e);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   public static class DynamicUtilTreeNode extends DefaultMutableTreeNode
 | |
|   {
 | |
|     protected Object childValue;
 | |
| 
 | |
|     protected boolean loadedChildren;
 | |
| 
 | |
|     /**
 | |
|      * Currently not set or used by this class. It might be set and used in
 | |
|      * later versions of this class.
 | |
|      */
 | |
|     protected boolean hasChildren;
 | |
| 
 | |
|     public DynamicUtilTreeNode(Object value, Object children)
 | |
|     {
 | |
|       super(value);
 | |
|       childValue = children;
 | |
|       loadedChildren = false;
 | |
|     }
 | |
| 
 | |
|     public int getChildCount()
 | |
|     {
 | |
|       loadChildren();
 | |
|       return super.getChildCount();
 | |
|     }
 | |
| 
 | |
|     protected void loadChildren()
 | |
|     {
 | |
|       if (!loadedChildren)
 | |
|         {
 | |
|           createChildren(this, childValue);
 | |
|           loadedChildren = true;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public Enumeration children()
 | |
|     {
 | |
|       loadChildren();
 | |
|       return super.children();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the child node at position <code>pos</code>. Subclassed
 | |
|      * here to load the children if necessary.
 | |
|      *
 | |
|      * @param pos the position of the child node to fetch
 | |
|      *
 | |
|      * @return the childnode at the specified position
 | |
|      */
 | |
|     public TreeNode getChildAt(int pos)
 | |
|     {
 | |
|       loadChildren();
 | |
|       return super.getChildAt(pos);
 | |
|     }
 | |
| 
 | |
|     public boolean isLeaf()
 | |
|     {
 | |
|       return childValue == null || !(childValue instanceof Hashtable
 | |
|           || childValue instanceof Vector
 | |
|           || childValue.getClass().isArray());
 | |
|     }
 | |
| 
 | |
|     public static void createChildren(DefaultMutableTreeNode parent,
 | |
|                                       Object children)
 | |
|     {
 | |
|       if (children instanceof Hashtable)
 | |
|         {
 | |
|           Hashtable tab = (Hashtable) children;
 | |
|           Enumeration e = tab.keys();
 | |
|           while (e.hasMoreElements())
 | |
|             {
 | |
|               Object key = e.nextElement();
 | |
|               Object val = tab.get(key);
 | |
|               parent.add(new DynamicUtilTreeNode(key, val));
 | |
|             }
 | |
|         }
 | |
|       else if (children instanceof Vector)
 | |
|         {
 | |
|           Iterator i = ((Vector) children).iterator();
 | |
|           while (i.hasNext())
 | |
|             {
 | |
|               Object n = i.next();
 | |
|               parent.add(new DynamicUtilTreeNode(n, n));
 | |
|             }
 | |
|         }
 | |
|       else if (children != null && children.getClass().isArray())
 | |
|         {
 | |
|           Object[] arr = (Object[]) children;
 | |
|           for (int i = 0; i < arr.length; ++i)
 | |
|             parent.add(new DynamicUtilTreeNode(arr[i], arr[i]));
 | |
|         }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Listens to the model of the JTree and updates the property
 | |
|    * <code>expandedState</code> if nodes are removed or changed.
 | |
|    */
 | |
|   protected class TreeModelHandler implements TreeModelListener
 | |
|   {
 | |
| 
 | |
|     /**
 | |
|      * Creates a new instance of TreeModelHandler.
 | |
|      */
 | |
|     protected TreeModelHandler()
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies when a node has changed in some ways. This does not include
 | |
|      * that a node has changed its location or changed it's children. It
 | |
|      * only means that some attributes of the node have changed that might
 | |
|      * affect its presentation.
 | |
|      *
 | |
|      * This method is called after the actual change occured.
 | |
|      *
 | |
|      * @param ev the TreeModelEvent describing the change
 | |
|      */
 | |
|     public void treeNodesChanged(TreeModelEvent ev)
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies when a node is inserted into the tree.
 | |
|      *
 | |
|      * This method is called after the actual change occured.
 | |
|      *
 | |
|      * @param ev the TreeModelEvent describing the change
 | |
|      */
 | |
|     public void treeNodesInserted(TreeModelEvent ev)
 | |
|     {
 | |
|       // nothing to do here
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies when a node is removed from the tree.
 | |
|      *
 | |
|      * This method is called after the actual change occured.
 | |
|      *
 | |
|      * @param ev the TreeModelEvent describing the change
 | |
|          */
 | |
|     public void treeNodesRemoved(TreeModelEvent ev)
 | |
|     {
 | |
|       if (ev != null)
 | |
|         {
 | |
|           TreePath parent = ev.getTreePath();
 | |
|           Object[] children = ev.getChildren();
 | |
|           TreeSelectionModel sm = getSelectionModel();
 | |
|           if (children != null)
 | |
|             {
 | |
|               TreePath path;
 | |
|               Vector toRemove = new Vector();
 | |
|               // Collect items that we must remove.
 | |
|               for (int i = children.length - 1; i >= 0; i--)
 | |
|                 {
 | |
|                   path = parent.pathByAddingChild(children[i]);
 | |
|                   if (nodeStates.containsKey(path))
 | |
|                     toRemove.add(path);
 | |
|                   // Clear selection while we are at it.
 | |
|                   if (sm != null)
 | |
|                     removeDescendantSelectedPaths(path, true);
 | |
|                 }
 | |
|               if (toRemove.size() > 0)
 | |
|                 removeDescendantToggledPaths(toRemove.elements());
 | |
|               TreeModel model = getModel();
 | |
|               if (model == null || model.isLeaf(parent.getLastPathComponent()))
 | |
|                 nodeStates.remove(parent);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies when the structure of the tree is changed.
 | |
|      *
 | |
|      * This method is called after the actual change occured.
 | |
|      *
 | |
|      * @param ev the TreeModelEvent describing the change
 | |
|      */
 | |
|     public void treeStructureChanged(TreeModelEvent ev)
 | |
|     {
 | |
|       if (ev != null)
 | |
|         {
 | |
|           TreePath parent = ev.getTreePath();
 | |
|           if (parent != null)
 | |
|             {
 | |
|               if (parent.getPathCount() == 1)
 | |
|                 {
 | |
|                   // We have a new root, clear everything.
 | |
|                   clearToggledPaths();
 | |
|                   Object root = treeModel.getRoot();
 | |
|                   if (root != null && treeModel.isLeaf(root))
 | |
|                     nodeStates.put(parent, Boolean.TRUE);
 | |
|                 }
 | |
|               else if (nodeStates.containsKey(parent))
 | |
|                 {
 | |
|                   Vector toRemove = new Vector();
 | |
|                   boolean expanded = isExpanded(parent);
 | |
|                   toRemove.add(parent);
 | |
|                   removeDescendantToggledPaths(toRemove.elements());
 | |
|                   if (expanded)
 | |
|                     {
 | |
|                       TreeModel model = getModel();
 | |
|                       if (model != null
 | |
|                           || model.isLeaf(parent.getLastPathComponent()))
 | |
|                         collapsePath(parent);
 | |
|                       else
 | |
|                         nodeStates.put(parent, Boolean.TRUE);
 | |
|                     }
 | |
|                 }
 | |
|               removeDescendantSelectedPaths(parent, false);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This redirects TreeSelectionEvents and rewrites the source of it to be
 | |
|    * this JTree. This is typically done when the tree model generates an
 | |
|    * event, but the JTree object associated with that model should be listed
 | |
|    * as the actual source of the event.
 | |
|    */
 | |
|   protected class TreeSelectionRedirector implements TreeSelectionListener,
 | |
|                                                      Serializable
 | |
|   {
 | |
|     /** The serial version UID. */
 | |
|     private static final long serialVersionUID = -3505069663646241664L;
 | |
| 
 | |
|     /**
 | |
|      * Creates a new instance of TreeSelectionRedirector
 | |
|      */
 | |
|     protected TreeSelectionRedirector()
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies when the tree selection changes.
 | |
|      *
 | |
|      * @param ev the TreeSelectionEvent that describes the change
 | |
|      */
 | |
|     public void valueChanged(TreeSelectionEvent ev)
 | |
|     {
 | |
|       TreeSelectionEvent rewritten =
 | |
|         (TreeSelectionEvent) ev.cloneWithSource(JTree.this);
 | |
|       fireValueChanged(rewritten);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * A TreeModel that does not allow anything to be selected.
 | |
|    */
 | |
|   protected static class EmptySelectionModel extends DefaultTreeSelectionModel
 | |
|   {
 | |
|     /** The serial version UID. */
 | |
|     private static final long serialVersionUID = -5815023306225701477L;
 | |
| 
 | |
|     /**
 | |
|      * The shared instance of this model.
 | |
|      */
 | |
|     protected static final EmptySelectionModel sharedInstance =
 | |
|       new EmptySelectionModel();
 | |
| 
 | |
|     /**
 | |
|      * Creates a new instance of EmptySelectionModel.
 | |
|      */
 | |
|     protected EmptySelectionModel()
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the shared instance of EmptySelectionModel.
 | |
|      *
 | |
|      * @return the shared instance of EmptySelectionModel
 | |
|      */
 | |
|     public static EmptySelectionModel sharedInstance()
 | |
|     {
 | |
|       return sharedInstance;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This catches attempts to set a selection and sets nothing instead.
 | |
|      *
 | |
|      * @param paths not used here
 | |
|      */
 | |
|     public void setSelectionPaths(TreePath[] paths)
 | |
|     {
 | |
|       // We don't allow selections in this class.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This catches attempts to add something to the selection.
 | |
|      *
 | |
|      * @param paths not used here
 | |
|      */
 | |
|     public void addSelectionPaths(TreePath[] paths)
 | |
|     {
 | |
|       // We don't allow selections in this class.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This catches attempts to remove something from the selection.
 | |
|      *
 | |
|      * @param paths not used here
 | |
|      */
 | |
|     public void removeSelectionPaths(TreePath[] paths)
 | |
|     {
 | |
|       // We don't allow selections in this class.
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static final long serialVersionUID = 7559816092864483649L;
 | |
| 
 | |
|   public static final String CELL_EDITOR_PROPERTY = "cellEditor";
 | |
| 
 | |
|   public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
 | |
| 
 | |
|   public static final String EDITABLE_PROPERTY = "editable";
 | |
| 
 | |
|   public static final String INVOKES_STOP_CELL_EDITING_PROPERTY =
 | |
|     "invokesStopCellEditing";
 | |
| 
 | |
|   public static final String LARGE_MODEL_PROPERTY = "largeModel";
 | |
| 
 | |
|   public static final String ROOT_VISIBLE_PROPERTY = "rootVisible";
 | |
| 
 | |
|   public static final String ROW_HEIGHT_PROPERTY = "rowHeight";
 | |
| 
 | |
|   public static final String SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";
 | |
| 
 | |
|   public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
 | |
| 
 | |
|   public static final String SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";
 | |
| 
 | |
|   public static final String TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";
 | |
| 
 | |
|   public static final String TREE_MODEL_PROPERTY = "model";
 | |
| 
 | |
|   public static final String VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";
 | |
| 
 | |
|   /** @since 1.3 */
 | |
|   public static final String ANCHOR_SELECTION_PATH_PROPERTY =
 | |
|     "anchorSelectionPath";
 | |
| 
 | |
|         /** @since 1.3 */
 | |
|   public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";
 | |
| 
 | |
|   /** @since 1.3 */
 | |
|   public static final String EXPANDS_SELECTED_PATHS_PROPERTY =
 | |
|     "expandsSelectedPaths";
 | |
| 
 | |
|   private static final Object EXPANDED = Boolean.TRUE;
 | |
| 
 | |
|   private static final Object COLLAPSED = Boolean.FALSE;
 | |
| 
 | |
|   private boolean dragEnabled;
 | |
| 
 | |
|   private boolean expandsSelectedPaths;
 | |
| 
 | |
|   private TreePath anchorSelectionPath;
 | |
| 
 | |
|   /**
 | |
|    * This contains the state of all nodes in the tree. Al/ entries map the
 | |
|    * TreePath of a note to to its state. Valid states are EXPANDED and
 | |
|    * COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
 | |
|    *
 | |
|    * This is package private to avoid accessor methods.
 | |
|    */
 | |
|   Hashtable nodeStates = new Hashtable();
 | |
| 
 | |
|   protected transient TreeCellEditor cellEditor;
 | |
| 
 | |
|   protected transient TreeCellRenderer cellRenderer;
 | |
| 
 | |
|   protected boolean editable;
 | |
| 
 | |
|   protected boolean invokesStopCellEditing;
 | |
| 
 | |
|   protected boolean largeModel;
 | |
| 
 | |
|   protected boolean rootVisible;
 | |
| 
 | |
|   protected int rowHeight;
 | |
| 
 | |
|   protected boolean scrollsOnExpand;
 | |
| 
 | |
|   protected transient TreeSelectionModel selectionModel;
 | |
| 
 | |
|   protected boolean showsRootHandles;
 | |
| 
 | |
|   protected int toggleClickCount;
 | |
| 
 | |
|   protected transient TreeModel treeModel;
 | |
| 
 | |
|   protected int visibleRowCount;
 | |
| 
 | |
|   /**
 | |
|    * Handles TreeModelEvents to update the expandedState.
 | |
|    */
 | |
|   protected transient TreeModelListener treeModelListener;
 | |
| 
 | |
|   /**
 | |
|    * Redirects TreeSelectionEvents so that the source is this JTree.
 | |
|    */
 | |
|   protected TreeSelectionRedirector selectionRedirector =
 | |
|     new TreeSelectionRedirector();
 | |
| 
 | |
|   /**
 | |
|    * Indicates if the rowHeight property has been set by a client
 | |
|    * program or by the UI.
 | |
|    *
 | |
|    * @see #setUIProperty(String, Object)
 | |
|    * @see LookAndFeel#installProperty(JComponent, String, Object)
 | |
|    */
 | |
|   private boolean clientRowHeightSet = false;
 | |
| 
 | |
|   /**
 | |
|    * Indicates if the scrollsOnExpand property has been set by a client
 | |
|    * program or by the UI.
 | |
|    *
 | |
|    * @see #setUIProperty(String, Object)
 | |
|    * @see LookAndFeel#installProperty(JComponent, String, Object)
 | |
|    */
 | |
|   private boolean clientScrollsOnExpandSet = false;
 | |
| 
 | |
|   /**
 | |
|    * Indicates if the showsRootHandles property has been set by a client
 | |
|    * program or by the UI.
 | |
|    *
 | |
|    * @see #setUIProperty(String, Object)
 | |
|    * @see LookAndFeel#installProperty(JComponent, String, Object)
 | |
|    */
 | |
|   private boolean clientShowsRootHandlesSet = false;
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>JTree</code> object.
 | |
|    */
 | |
|   public JTree()
 | |
|   {
 | |
|     this(getDefaultTreeModel());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>JTree</code> object.
 | |
|    *
 | |
|    * @param value the initial nodes in the tree
 | |
|    */
 | |
|   public JTree(Hashtable<?, ?> value)
 | |
|   {
 | |
|     this(createTreeModel(value));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>JTree</code> object.
 | |
|    *
 | |
|    * @param value the initial nodes in the tree
 | |
|    */
 | |
|   public JTree(Object[] value)
 | |
|   {
 | |
|     this(createTreeModel(value));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>JTree</code> object.
 | |
|    *
 | |
|    * @param model the model to use
 | |
|    */
 | |
|   public JTree(TreeModel model)
 | |
|   {
 | |
|     setRootVisible(true);
 | |
|     setSelectionModel( new DefaultTreeSelectionModel() );
 | |
| 
 | |
|     // The root node appears expanded by default.
 | |
|     nodeStates = new Hashtable();
 | |
| 
 | |
|     // The cell renderer gets set by the UI.
 | |
|     cellRenderer = null;
 | |
| 
 | |
|     // Install the UI before installing the model. This way we avoid double
 | |
|     // initialization of lots of UI and model stuff inside the UI and related
 | |
|     // classes. The necessary UI updates are performed via property change
 | |
|     // events to the UI.
 | |
|     updateUI();
 | |
|     setModel(model);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>JTree</code> object.
 | |
|    *
 | |
|    * @param root the root node
 | |
|    */
 | |
|   public JTree(TreeNode root)
 | |
|   {
 | |
|     this(root, false);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>JTree</code> object.
 | |
|    *
 | |
|    * @param root the root node
 | |
|    * @param asksAllowChildren if false, all nodes without children are leaf
 | |
|    *        nodes. If true, only nodes that do not allow children are leaf
 | |
|    *        nodes.
 | |
|    */
 | |
|   public JTree(TreeNode root, boolean asksAllowChildren)
 | |
|   {
 | |
|     this(new DefaultTreeModel(root, asksAllowChildren));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>JTree</code> object.
 | |
|    *
 | |
|    * @param value the initial nodes in the tree
 | |
|    */
 | |
|   public JTree(Vector<?> value)
 | |
|   {
 | |
|     this(createTreeModel(value));
 | |
|   }
 | |
| 
 | |
|   public int getRowForPath(TreePath path)
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui != null)
 | |
|       return ui.getRowForPath(this, path);
 | |
| 
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   public TreePath getPathForRow(int row)
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
|     return ui != null ? ui.getPathForRow(this, row) : null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get the pathes that are displayes between the two given rows.
 | |
|    *
 | |
|    * @param index0 the starting row, inclusive
 | |
|    * @param index1 the ending row, inclusive
 | |
|    *
 | |
|    * @return the array of the tree pathes
 | |
|    */
 | |
|   protected TreePath[] getPathBetweenRows(int index0, int index1)
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui == null)
 | |
|       return null;
 | |
| 
 | |
|     int minIndex = Math.min(index0, index1);
 | |
|     int maxIndex = Math.max(index0, index1);
 | |
|     TreePath[] paths = new TreePath[maxIndex - minIndex + 1];
 | |
| 
 | |
|     for (int i = minIndex; i <= maxIndex; ++i)
 | |
|       paths[i - minIndex] = ui.getPathForRow(this, i);
 | |
| 
 | |
|     return paths;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>TreeModel</code> object.
 | |
|    *
 | |
|    * @param value the values stored in the model
 | |
|    */
 | |
|   protected static TreeModel createTreeModel(Object value)
 | |
|   {
 | |
|     return new DefaultTreeModel(new DynamicUtilTreeNode(value, value));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the UI associated with this <code>JTree</code> object.
 | |
|    *
 | |
|    * @return the associated <code>TreeUI</code> object
 | |
|    */
 | |
|   public TreeUI getUI()
 | |
|   {
 | |
|     return (TreeUI) ui;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the UI associated with this <code>JTree</code> object.
 | |
|    *
 | |
|    * @param ui the <code>TreeUI</code> to associate
 | |
|    */
 | |
|   public void setUI(TreeUI ui)
 | |
|   {
 | |
|     super.setUI(ui);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This method resets the UI used to the Look and Feel defaults..
 | |
|    */
 | |
|   public void updateUI()
 | |
|   {
 | |
|     setUI((TreeUI) UIManager.getUI(this));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This method returns the String ID of the UI class of Separator.
 | |
|    *
 | |
|    * @return The UI class' String ID.
 | |
|    */
 | |
|   public String getUIClassID()
 | |
|   {
 | |
|     return "TreeUI";
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Gets the AccessibleContext associated with this
 | |
|    * <code>JTree</code>.
 | |
|    *
 | |
|    * @return the associated context
 | |
|    */
 | |
|   public AccessibleContext getAccessibleContext()
 | |
|   {
 | |
|     return new AccessibleJTree();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the preferred viewport size.
 | |
|    *
 | |
|    * @return the preferred size
 | |
|    */
 | |
|   public Dimension getPreferredScrollableViewportSize()
 | |
|   {
 | |
|     return getPreferredSize();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the preferred scrolling amount (in pixels) for the given scrolling
 | |
|    * direction and orientation. This method handles a partially exposed row by
 | |
|    * returning the distance required to completely expose the item.
 | |
|    *
 | |
|    * @param visibleRect the currently visible part of the component.
 | |
|    * @param orientation the scrolling orientation
 | |
|    * @param direction the scrolling direction (negative - up, positive -down).
 | |
|    *          The values greater than one means that more mouse wheel or similar
 | |
|    *          events were generated, and hence it is better to scroll the longer
 | |
|    *          distance.
 | |
|    * @author Audrius Meskauskas (audriusa@bioinformatics.org)
 | |
|    */
 | |
|   public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
 | |
|                                         int direction)
 | |
|   {
 | |
|     int delta = 0;
 | |
| 
 | |
|     // Round so that the top would start from the row boundary
 | |
|     if (orientation == SwingConstants.VERTICAL)
 | |
|       {
 | |
|         int row = getClosestRowForLocation(0, visibleRect.y);
 | |
|         if (row != -1)
 | |
|           {
 | |
|             Rectangle b = getRowBounds(row);
 | |
|             if (b.y != visibleRect.y)
 | |
|               {
 | |
|                 if (direction < 0)
 | |
|                   delta = Math.max(0, visibleRect.y - b.y);
 | |
|                 else
 | |
|                   delta = b.y + b.height - visibleRect.y;
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 if (direction < 0)
 | |
|                   {
 | |
|                     if (row != 0)
 | |
|                       {
 | |
|                         b = getRowBounds(row - 1);
 | |
|                         delta = b.height;
 | |
|                       }
 | |
|                   }
 | |
|                 else
 | |
|                   delta = b.height;
 | |
|               }
 | |
|           }
 | |
|       }
 | |
|     else
 | |
|       // The RI always  returns 4 for HORIZONTAL scrolling.
 | |
|       delta = 4;
 | |
|     return delta;
 | |
|   }
 | |
| 
 | |
|   public int getScrollableBlockIncrement(Rectangle visibleRect,
 | |
|                                          int orientation, int direction)
 | |
|   {
 | |
|     int block;
 | |
|     if (orientation == SwingConstants.VERTICAL)
 | |
|       block = visibleRect.height;
 | |
|     else
 | |
|       block = visibleRect.width;
 | |
|     return block;
 | |
|   }
 | |
| 
 | |
|   public boolean getScrollableTracksViewportHeight()
 | |
|   {
 | |
|     if (getParent() instanceof JViewport)
 | |
|       return ((JViewport) getParent()).getHeight() > getPreferredSize().height;
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   public boolean getScrollableTracksViewportWidth()
 | |
|   {
 | |
|     if (getParent() instanceof JViewport)
 | |
|       return ((JViewport) getParent()).getWidth() > getPreferredSize().width;
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds a <code>TreeExpansionListener</code> object to the tree.
 | |
|    *
 | |
|    * @param listener the listener to add
 | |
|    */
 | |
|   public void addTreeExpansionListener(TreeExpansionListener listener)
 | |
|   {
 | |
|     listenerList.add(TreeExpansionListener.class, listener);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes a <code>TreeExpansionListener</code> object from the tree.
 | |
|    *
 | |
|    * @param listener the listener to remove
 | |
|    */
 | |
|   public void removeTreeExpansionListener(TreeExpansionListener listener)
 | |
|   {
 | |
|     listenerList.remove(TreeExpansionListener.class, listener);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns all added <code>TreeExpansionListener</code> objects.
 | |
|    *
 | |
|    * @return an array of listeners
 | |
|    */
 | |
|   public TreeExpansionListener[] getTreeExpansionListeners()
 | |
|   {
 | |
|     return (TreeExpansionListener[]) getListeners(TreeExpansionListener.class);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Notifies all listeners that the tree was collapsed.
 | |
|    *
 | |
|    * @param path the path to the node that was collapsed
 | |
|    */
 | |
|   public void fireTreeCollapsed(TreePath path)
 | |
|   {
 | |
|     TreeExpansionEvent event = new TreeExpansionEvent(this, path);
 | |
|     TreeExpansionListener[] listeners = getTreeExpansionListeners();
 | |
| 
 | |
|     for (int index = 0; index < listeners.length; ++index)
 | |
|       listeners[index].treeCollapsed(event);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Notifies all listeners that the tree was expanded.
 | |
|    *
 | |
|    * @param path the path to the node that was expanded
 | |
|    */
 | |
|   public void fireTreeExpanded(TreePath path)
 | |
|   {
 | |
|     TreeExpansionEvent event = new TreeExpansionEvent(this, path);
 | |
|     TreeExpansionListener[] listeners = getTreeExpansionListeners();
 | |
| 
 | |
|     for (int index = 0; index < listeners.length; ++index)
 | |
|       listeners[index].treeExpanded(event);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds a <code>TreeSelctionListener</code> object to the tree.
 | |
|    *
 | |
|    * @param listener the listener to add
 | |
|    */
 | |
|   public void addTreeSelectionListener(TreeSelectionListener listener)
 | |
|   {
 | |
|     listenerList.add(TreeSelectionListener.class, listener);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes a <code>TreeSelectionListener</code> object from the tree.
 | |
|    *
 | |
|    * @param listener the listener to remove
 | |
|    */
 | |
|   public void removeTreeSelectionListener(TreeSelectionListener listener)
 | |
|   {
 | |
|     listenerList.remove(TreeSelectionListener.class, listener);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns all added <code>TreeSelectionListener</code> objects.
 | |
|    *
 | |
|    * @return an array of listeners
 | |
|    */
 | |
|   public TreeSelectionListener[] getTreeSelectionListeners()
 | |
|   {
 | |
|     return (TreeSelectionListener[])
 | |
|     getListeners(TreeSelectionListener.class);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Notifies all listeners when the selection of the tree changed.
 | |
|    *
 | |
|    * @param event the event to send
 | |
|    */
 | |
|   protected void fireValueChanged(TreeSelectionEvent event)
 | |
|   {
 | |
|     TreeSelectionListener[] listeners = getTreeSelectionListeners();
 | |
| 
 | |
|     for (int index = 0; index < listeners.length; ++index)
 | |
|       listeners[index].valueChanged(event);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds a <code>TreeWillExpandListener</code> object to the tree.
 | |
|    *
 | |
|    * @param listener the listener to add
 | |
|    */
 | |
|   public void addTreeWillExpandListener(TreeWillExpandListener listener)
 | |
|   {
 | |
|     listenerList.add(TreeWillExpandListener.class, listener);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes a <code>TreeWillExpandListener</code> object from the tree.
 | |
|    *
 | |
|    * @param listener the listener to remove
 | |
|    */
 | |
|   public void removeTreeWillExpandListener(TreeWillExpandListener listener)
 | |
|   {
 | |
|     listenerList.remove(TreeWillExpandListener.class, listener);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns all added <code>TreeWillExpandListener</code> objects.
 | |
|    *
 | |
|    * @return an array of listeners
 | |
|    */
 | |
|   public TreeWillExpandListener[] getTreeWillExpandListeners()
 | |
|   {
 | |
|     return (TreeWillExpandListener[])
 | |
|     getListeners(TreeWillExpandListener.class);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Notifies all listeners that the tree will collapse.
 | |
|    *
 | |
|    * @param path the path to the node that will collapse
 | |
|    */
 | |
|   public void fireTreeWillCollapse(TreePath path) throws ExpandVetoException
 | |
|   {
 | |
|     TreeExpansionEvent event = new TreeExpansionEvent(this, path);
 | |
|     TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
 | |
| 
 | |
|     for (int index = 0; index < listeners.length; ++index)
 | |
|       listeners[index].treeWillCollapse(event);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Notifies all listeners that the tree will expand.
 | |
|    *
 | |
|    * @param path the path to the node that will expand
 | |
|    */
 | |
|   public void fireTreeWillExpand(TreePath path) throws ExpandVetoException
 | |
|   {
 | |
|     TreeExpansionEvent event = new TreeExpansionEvent(this, path);
 | |
|     TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
 | |
| 
 | |
|     for (int index = 0; index < listeners.length; ++index)
 | |
|       listeners[index].treeWillExpand(event);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the model of this <code>JTree</code> object.
 | |
|    *
 | |
|    * @return the associated <code>TreeModel</code>
 | |
|    */
 | |
|   public TreeModel getModel()
 | |
|   {
 | |
|     return treeModel;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the model to use in <code>JTree</code>.
 | |
|    *
 | |
|    * @param model the <code>TreeModel</code> to use
 | |
|    */
 | |
|   public void setModel(TreeModel model)
 | |
|   {
 | |
|     if (treeModel == model)
 | |
|       return;
 | |
| 
 | |
|     // Remove listeners from old model.
 | |
|     if (treeModel != null && treeModelListener != null)
 | |
|       treeModel.removeTreeModelListener(treeModelListener);
 | |
| 
 | |
|     // add treeModelListener to the new model
 | |
|     if (treeModelListener == null)
 | |
|       treeModelListener = createTreeModelListener();
 | |
|     if (model != null) // as setModel(null) is allowed
 | |
|       model.addTreeModelListener(treeModelListener);
 | |
| 
 | |
|     TreeModel oldValue = treeModel;
 | |
|     treeModel = model;
 | |
|     clearToggledPaths();
 | |
| 
 | |
|     if (treeModel != null)
 | |
|       {
 | |
|         if (treeModelListener == null)
 | |
|           treeModelListener = createTreeModelListener();
 | |
|         if (treeModelListener != null)
 | |
|           treeModel.addTreeModelListener(treeModelListener);
 | |
|         Object root = treeModel.getRoot();
 | |
|         if (root != null && !treeModel.isLeaf(root))
 | |
|           {
 | |
|             nodeStates.put(new TreePath(root), Boolean.TRUE);
 | |
|           }
 | |
|       }
 | |
| 
 | |
|     firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if this <code>JTree</code> object is editable.
 | |
|    *
 | |
|    * @return <code>true</code> if this tree object is editable,
 | |
|    *         <code>false</code> otherwise
 | |
|    */
 | |
|   public boolean isEditable()
 | |
|   {
 | |
|     return editable;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the <code>editable</code> property.
 | |
|    *
 | |
|    * @param flag <code>true</code> to make this tree object editable,
 | |
|    *        <code>false</code> otherwise
 | |
|    */
 | |
|   public void setEditable(boolean flag)
 | |
|   {
 | |
|     if (editable == flag)
 | |
|       return;
 | |
| 
 | |
|     boolean oldValue = editable;
 | |
|     editable = flag;
 | |
|     firePropertyChange(EDITABLE_PROPERTY, oldValue, editable);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if the root element is visible.
 | |
|    *
 | |
|    * @return <code>true</code> if the root element is visible,
 | |
|    *         <code>false</code> otherwise
 | |
|    */
 | |
|   public boolean isRootVisible()
 | |
|   {
 | |
|     return rootVisible;
 | |
|   }
 | |
| 
 | |
|   public void setRootVisible(boolean flag)
 | |
|   {
 | |
|     if (rootVisible == flag)
 | |
|       return;
 | |
| 
 | |
|     // If the root is currently selected, unselect it
 | |
|     if (rootVisible && !flag)
 | |
|       {
 | |
|         TreeSelectionModel model = getSelectionModel();
 | |
|         // The root is always shown in the first row
 | |
|         TreePath rootPath = getPathForRow(0);
 | |
|         model.removeSelectionPath(rootPath);
 | |
|       }
 | |
| 
 | |
|     boolean oldValue = rootVisible;
 | |
|     rootVisible = flag;
 | |
|     firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   public boolean getShowsRootHandles()
 | |
|   {
 | |
|     return showsRootHandles;
 | |
|   }
 | |
| 
 | |
|   public void setShowsRootHandles(boolean flag)
 | |
|   {
 | |
|     clientShowsRootHandlesSet = true;
 | |
| 
 | |
|     if (showsRootHandles == flag)
 | |
|       return;
 | |
| 
 | |
|     boolean oldValue = showsRootHandles;
 | |
|     showsRootHandles = flag;
 | |
|     firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);
 | |
|   }
 | |
| 
 | |
|   public TreeCellEditor getCellEditor()
 | |
|   {
 | |
|     return cellEditor;
 | |
|   }
 | |
| 
 | |
|   public void setCellEditor(TreeCellEditor editor)
 | |
|   {
 | |
|     if (cellEditor == editor)
 | |
|       return;
 | |
| 
 | |
|     TreeCellEditor oldValue = cellEditor;
 | |
|     cellEditor = editor;
 | |
|     firePropertyChange(CELL_EDITOR_PROPERTY, oldValue, editor);
 | |
|   }
 | |
| 
 | |
|   public TreeCellRenderer getCellRenderer()
 | |
|   {
 | |
|     return cellRenderer;
 | |
|   }
 | |
| 
 | |
|   public void setCellRenderer(TreeCellRenderer newRenderer)
 | |
|   {
 | |
|     if (cellRenderer == newRenderer)
 | |
|       return;
 | |
| 
 | |
|     TreeCellRenderer oldValue = cellRenderer;
 | |
|     cellRenderer = newRenderer;
 | |
|     firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, newRenderer);
 | |
|   }
 | |
| 
 | |
|   public TreeSelectionModel getSelectionModel()
 | |
|   {
 | |
|     return selectionModel;
 | |
|   }
 | |
| 
 | |
|   public void setSelectionModel(TreeSelectionModel model)
 | |
|   {
 | |
|     if (selectionModel == model)
 | |
|       return;
 | |
| 
 | |
|     if( model == null )
 | |
|       model = EmptySelectionModel.sharedInstance();
 | |
| 
 | |
|     if (selectionModel != null)
 | |
|       selectionModel.removeTreeSelectionListener(selectionRedirector);
 | |
| 
 | |
|     TreeSelectionModel oldValue = selectionModel;
 | |
|     selectionModel = model;
 | |
| 
 | |
|     selectionModel.addTreeSelectionListener(selectionRedirector);
 | |
| 
 | |
|     firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);
 | |
|     revalidate();
 | |
|     repaint();
 | |
|   }
 | |
| 
 | |
|   public int getVisibleRowCount()
 | |
|   {
 | |
|     return visibleRowCount;
 | |
|   }
 | |
| 
 | |
|   public void setVisibleRowCount(int rows)
 | |
|   {
 | |
|     if (visibleRowCount == rows)
 | |
|       return;
 | |
| 
 | |
|     int oldValue = visibleRowCount;
 | |
|     visibleRowCount = rows;
 | |
|     firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY, oldValue, rows);
 | |
|   }
 | |
| 
 | |
|   public boolean isLargeModel()
 | |
|   {
 | |
|     return largeModel;
 | |
|   }
 | |
| 
 | |
|   public void setLargeModel(boolean large)
 | |
|   {
 | |
|     if (largeModel == large)
 | |
|       return;
 | |
| 
 | |
|     boolean oldValue = largeModel;
 | |
|     largeModel = large;
 | |
|     firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);
 | |
|   }
 | |
| 
 | |
|   public int getRowHeight()
 | |
|   {
 | |
|     return rowHeight;
 | |
|   }
 | |
| 
 | |
|   public void setRowHeight(int height)
 | |
|   {
 | |
|     clientRowHeightSet = true;
 | |
| 
 | |
|     if (rowHeight == height)
 | |
|       return;
 | |
| 
 | |
|     int oldValue = rowHeight;
 | |
|     rowHeight = height;
 | |
|     firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);
 | |
|   }
 | |
| 
 | |
|   public boolean isFixedRowHeight()
 | |
|   {
 | |
|     return rowHeight > 0;
 | |
|   }
 | |
| 
 | |
|   public boolean getInvokesStopCellEditing()
 | |
|   {
 | |
|     return invokesStopCellEditing;
 | |
|   }
 | |
| 
 | |
|   public void setInvokesStopCellEditing(boolean invoke)
 | |
|   {
 | |
|     if (invokesStopCellEditing == invoke)
 | |
|       return;
 | |
| 
 | |
|     boolean oldValue = invokesStopCellEditing;
 | |
|     invokesStopCellEditing = invoke;
 | |
|     firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY,
 | |
|                        oldValue, invoke);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public int getToggleClickCount()
 | |
|   {
 | |
|     return toggleClickCount;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public void setToggleClickCount(int count)
 | |
|   {
 | |
|     if (toggleClickCount == count)
 | |
|       return;
 | |
| 
 | |
|     int oldValue = toggleClickCount;
 | |
|     toggleClickCount = count;
 | |
|     firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldValue, count);
 | |
|   }
 | |
| 
 | |
|   public void scrollPathToVisible(TreePath path)
 | |
|   {
 | |
|     if (path == null)
 | |
|       return;
 | |
|     Rectangle rect = getPathBounds(path);
 | |
|     scrollRectToVisible(rect);
 | |
|   }
 | |
| 
 | |
|   public void scrollRowToVisible(int row)
 | |
|   {
 | |
|     scrollPathToVisible(getPathForRow(row));
 | |
|   }
 | |
| 
 | |
|   public boolean getScrollsOnExpand()
 | |
|   {
 | |
|     return scrollsOnExpand;
 | |
|   }
 | |
| 
 | |
|   public void setScrollsOnExpand(boolean scroll)
 | |
|   {
 | |
|     clientScrollsOnExpandSet = true;
 | |
|     if (scrollsOnExpand == scroll)
 | |
|       return;
 | |
| 
 | |
|     boolean oldValue = scrollsOnExpand;
 | |
|     scrollsOnExpand = scroll;
 | |
|     firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);
 | |
|   }
 | |
| 
 | |
|   public void setSelectionPath(TreePath path)
 | |
|   {
 | |
|     clearSelectionPathStates();
 | |
|     selectionModel.setSelectionPath(path);
 | |
|   }
 | |
| 
 | |
|   public void setSelectionPaths(TreePath[] paths)
 | |
|   {
 | |
|     clearSelectionPathStates();
 | |
|     selectionModel.setSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This method, and all calls to it, should be removed once the
 | |
|    * DefaultTreeModel fires events properly.  Maintenance of the nodeStates
 | |
|    * table should really be done in the TreeModelHandler.
 | |
|    */
 | |
|   private void clearSelectionPathStates()
 | |
|   {
 | |
|     TreePath[] oldPaths = selectionModel.getSelectionPaths();
 | |
|     if (oldPaths != null)
 | |
|       for (int i = 0; i < oldPaths.length; i++)
 | |
|         nodeStates.remove(oldPaths[i]);
 | |
|   }
 | |
| 
 | |
|   public void setSelectionRow(int row)
 | |
|   {
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       setSelectionPath(path);
 | |
|   }
 | |
| 
 | |
|   public void setSelectionRows(int[] rows)
 | |
|   {
 | |
|     // Make sure we have an UI so getPathForRow() does not return null.
 | |
|     if (rows == null || getUI() == null)
 | |
|       return;
 | |
| 
 | |
|     TreePath[] paths = new TreePath[rows.length];
 | |
| 
 | |
|     for (int i = rows.length - 1; i >= 0; --i)
 | |
|       paths[i] = getPathForRow(rows[i]);
 | |
| 
 | |
|     setSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   public void setSelectionInterval(int index0, int index1)
 | |
|   {
 | |
|     TreePath[] paths = getPathBetweenRows(index0, index1);
 | |
| 
 | |
|     if (paths != null)
 | |
|       setSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   public void addSelectionPath(TreePath path)
 | |
|   {
 | |
|     selectionModel.addSelectionPath(path);
 | |
|   }
 | |
| 
 | |
|   public void addSelectionPaths(TreePath[] paths)
 | |
|   {
 | |
|     selectionModel.addSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   public void addSelectionRow(int row)
 | |
|   {
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       selectionModel.addSelectionPath(path);
 | |
|   }
 | |
| 
 | |
|   public void addSelectionRows(int[] rows)
 | |
|   {
 | |
|     // Make sure we have an UI so getPathForRow() does not return null.
 | |
|     if (rows == null || getUI() == null)
 | |
|       return;
 | |
| 
 | |
|     TreePath[] paths = new TreePath[rows.length];
 | |
| 
 | |
|     for (int i = rows.length - 1; i >= 0; --i)
 | |
|       paths[i] = getPathForRow(rows[i]);
 | |
| 
 | |
|     addSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Select all rows between the two given indexes, inclusive. The method
 | |
|    * will not select the inner leaves and braches of the currently collapsed
 | |
|    * nodes in this interval.
 | |
|    *
 | |
|    * @param index0 the starting row, inclusive
 | |
|    * @param index1 the ending row, inclusive
 | |
|    */
 | |
|   public void addSelectionInterval(int index0, int index1)
 | |
|   {
 | |
|     TreePath[] paths = getPathBetweenRows(index0, index1);
 | |
| 
 | |
|     if (paths != null)
 | |
|       addSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   public void removeSelectionPath(TreePath path)
 | |
|   {
 | |
|     clearSelectionPathStates();
 | |
|     selectionModel.removeSelectionPath(path);
 | |
|   }
 | |
| 
 | |
|   public void removeSelectionPaths(TreePath[] paths)
 | |
|   {
 | |
|     clearSelectionPathStates();
 | |
|     selectionModel.removeSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   public void removeSelectionRow(int row)
 | |
|   {
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       removeSelectionPath(path);
 | |
|   }
 | |
| 
 | |
|   public void removeSelectionRows(int[] rows)
 | |
|   {
 | |
|     if (rows == null || getUI() == null)
 | |
|       return;
 | |
| 
 | |
|     TreePath[] paths = new TreePath[rows.length];
 | |
| 
 | |
|     for (int i = rows.length - 1; i >= 0; --i)
 | |
|       paths[i] = getPathForRow(rows[i]);
 | |
| 
 | |
|     removeSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   public void removeSelectionInterval(int index0, int index1)
 | |
|   {
 | |
|     TreePath[] paths = getPathBetweenRows(index0, index1);
 | |
| 
 | |
|     if (paths != null)
 | |
|       removeSelectionPaths(paths);
 | |
|   }
 | |
| 
 | |
|   public void clearSelection()
 | |
|   {
 | |
|     selectionModel.clearSelection();
 | |
|     setLeadSelectionPath(null);
 | |
|   }
 | |
| 
 | |
|   public TreePath getLeadSelectionPath()
 | |
|   {
 | |
|     if (selectionModel == null)
 | |
|       return null;
 | |
|     else
 | |
|       return selectionModel.getLeadSelectionPath();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public void setLeadSelectionPath(TreePath path)
 | |
|   {
 | |
|     if (selectionModel != null)
 | |
|       {
 | |
|         TreePath oldValue = selectionModel.getLeadSelectionPath();
 | |
|         if (path == oldValue || path != null && path.equals(oldValue))
 | |
|           return;
 | |
| 
 | |
|         // Repaint the previous and current rows with the lead selection path.
 | |
|         if (path != null)
 | |
|           {
 | |
|             repaint(getPathBounds(path));
 | |
|             selectionModel.addSelectionPath(path);
 | |
|           }
 | |
| 
 | |
|         if (oldValue != null)
 | |
|           repaint(getPathBounds(oldValue));
 | |
| 
 | |
|         firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public TreePath getAnchorSelectionPath()
 | |
|   {
 | |
|     return anchorSelectionPath;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public void setAnchorSelectionPath(TreePath path)
 | |
|   {
 | |
|     if (anchorSelectionPath == path)
 | |
|       return;
 | |
| 
 | |
|     TreePath oldValue = anchorSelectionPath;
 | |
|     anchorSelectionPath = path;
 | |
|     firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY, oldValue, path);
 | |
|   }
 | |
| 
 | |
|   public int getLeadSelectionRow()
 | |
|   {
 | |
|     return selectionModel.getLeadSelectionRow();
 | |
|   }
 | |
| 
 | |
|   public int getMaxSelectionRow()
 | |
|   {
 | |
|     return selectionModel.getMaxSelectionRow();
 | |
|   }
 | |
| 
 | |
|   public int getMinSelectionRow()
 | |
|   {
 | |
|     return selectionModel.getMinSelectionRow();
 | |
|   }
 | |
| 
 | |
|   public int getSelectionCount()
 | |
|   {
 | |
|     return selectionModel.getSelectionCount();
 | |
|   }
 | |
| 
 | |
|   public TreePath getSelectionPath()
 | |
|   {
 | |
|     return selectionModel.getSelectionPath();
 | |
|   }
 | |
| 
 | |
|   public TreePath[] getSelectionPaths()
 | |
|   {
 | |
|     return selectionModel.getSelectionPaths();
 | |
|   }
 | |
| 
 | |
|   public int[] getSelectionRows()
 | |
|   {
 | |
|     return selectionModel.getSelectionRows();
 | |
|   }
 | |
| 
 | |
|   public boolean isPathSelected(TreePath path)
 | |
|   {
 | |
|     return selectionModel.isPathSelected(path);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns <code>true</code> when the specified row is selected,
 | |
|    * <code>false</code> otherwise. This call is delegated to the
 | |
|    * {@link TreeSelectionModel#isRowSelected(int)} method.
 | |
|    *
 | |
|    * @param row the row to check
 | |
|    *
 | |
|    * @return <code>true</code> when the specified row is selected,
 | |
|    *         <code>false</code> otherwise
 | |
|    */
 | |
|   public boolean isRowSelected(int row)
 | |
|   {
 | |
|     return selectionModel.isRowSelected(row);
 | |
|   }
 | |
| 
 | |
|   public boolean isSelectionEmpty()
 | |
|   {
 | |
|     return selectionModel.isSelectionEmpty();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the value of the <code>dragEnabled</code> property.
 | |
|    *
 | |
|    * @return the value
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public boolean getDragEnabled()
 | |
|   {
 | |
|     return dragEnabled;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set the <code>dragEnabled</code> property.
 | |
|    *
 | |
|    * @param enabled new value
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public void setDragEnabled(boolean enabled)
 | |
|   {
 | |
|     dragEnabled = enabled;
 | |
|   }
 | |
| 
 | |
|   public int getRowCount()
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui != null)
 | |
|       return ui.getRowCount(this);
 | |
| 
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   public void collapsePath(TreePath path)
 | |
|   {
 | |
|     try
 | |
|       {
 | |
|         fireTreeWillCollapse(path);
 | |
|       }
 | |
|     catch (ExpandVetoException ev)
 | |
|       {
 | |
|         // We do nothing if attempt has been vetoed.
 | |
|       }
 | |
|     setExpandedState(path, false);
 | |
|     fireTreeCollapsed(path);
 | |
|   }
 | |
| 
 | |
|   public void collapseRow(int row)
 | |
|   {
 | |
|     if (row < 0 || row >= getRowCount())
 | |
|       return;
 | |
| 
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       collapsePath(path);
 | |
|   }
 | |
| 
 | |
|   public void expandPath(TreePath path)
 | |
|   {
 | |
|     // Don't expand if path is null
 | |
|     // or is already expanded.
 | |
|     if (path == null || isExpanded(path))
 | |
|       return;
 | |
| 
 | |
|     try
 | |
|       {
 | |
|         fireTreeWillExpand(path);
 | |
|       }
 | |
|     catch (ExpandVetoException ev)
 | |
|       {
 | |
|         // We do nothing if attempt has been vetoed.
 | |
|       }
 | |
| 
 | |
|     setExpandedState(path, true);
 | |
|     fireTreeExpanded(path);
 | |
|   }
 | |
| 
 | |
|   public void expandRow(int row)
 | |
|   {
 | |
|     if (row < 0 || row >= getRowCount())
 | |
|       return;
 | |
| 
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       expandPath(path);
 | |
|   }
 | |
| 
 | |
|   public boolean isCollapsed(TreePath path)
 | |
|   {
 | |
|     return !isExpanded(path);
 | |
|   }
 | |
| 
 | |
|   public boolean isCollapsed(int row)
 | |
|   {
 | |
|     if (row < 0 || row >= getRowCount())
 | |
|       return false;
 | |
| 
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       return isCollapsed(path);
 | |
| 
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   public boolean isExpanded(TreePath path)
 | |
|   {
 | |
|     if (path == null)
 | |
|       return false;
 | |
| 
 | |
|     Object state = nodeStates.get(path);
 | |
| 
 | |
|     if ((state == null) || (state != EXPANDED))
 | |
|       return false;
 | |
| 
 | |
|     TreePath parent = path.getParentPath();
 | |
| 
 | |
|     if (parent != null)
 | |
|       return isExpanded(parent);
 | |
| 
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   public boolean isExpanded(int row)
 | |
|   {
 | |
|     if (row < 0 || row >= getRowCount())
 | |
|       return false;
 | |
| 
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       return isExpanded(path);
 | |
| 
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public boolean getExpandsSelectedPaths()
 | |
|   {
 | |
|     return expandsSelectedPaths;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public void setExpandsSelectedPaths(boolean flag)
 | |
|   {
 | |
|     if (expandsSelectedPaths == flag)
 | |
|       return;
 | |
| 
 | |
|     boolean oldValue = expandsSelectedPaths;
 | |
|     expandsSelectedPaths = flag;
 | |
|     firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue, flag);
 | |
|   }
 | |
| 
 | |
|   public Rectangle getPathBounds(TreePath path)
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui == null)
 | |
|       return null;
 | |
| 
 | |
|     return ui.getPathBounds(this, path);
 | |
|   }
 | |
| 
 | |
|   public Rectangle getRowBounds(int row)
 | |
|   {
 | |
|     TreePath path = getPathForRow(row);
 | |
| 
 | |
|     if (path != null)
 | |
|       return getPathBounds(path);
 | |
| 
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   public boolean isEditing()
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui != null)
 | |
|       return ui.isEditing(this);
 | |
| 
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   public boolean stopEditing()
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (isEditing())
 | |
|       if (ui != null)
 | |
|         return ui.stopEditing(this);
 | |
| 
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   public void cancelEditing()
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (isEditing())
 | |
|       if (ui != null)
 | |
|         ui.cancelEditing(this);
 | |
|   }
 | |
| 
 | |
|   public void startEditingAtPath(TreePath path)
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui != null)
 | |
|       ui.startEditingAtPath(this, path);
 | |
|   }
 | |
| 
 | |
|   public TreePath getEditingPath()
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui != null)
 | |
|       return ui.getEditingPath(this);
 | |
| 
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   public TreePath getPathForLocation(int x, int y)
 | |
|   {
 | |
|     TreePath path = getClosestPathForLocation(x, y);
 | |
| 
 | |
|     if (path != null)
 | |
|       {
 | |
|         Rectangle rect = getPathBounds(path);
 | |
| 
 | |
|         if ((rect != null) && rect.contains(x, y))
 | |
|           return path;
 | |
|       }
 | |
| 
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   public int getRowForLocation(int x, int y)
 | |
|   {
 | |
|     TreePath path = getPathForLocation(x, y);
 | |
| 
 | |
|     if (path != null)
 | |
|       return getRowForPath(path);
 | |
| 
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   public TreePath getClosestPathForLocation(int x, int y)
 | |
|   {
 | |
|     TreeUI ui = getUI();
 | |
| 
 | |
|     if (ui != null)
 | |
|       return ui.getClosestPathForLocation(this, x, y);
 | |
| 
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   public int getClosestRowForLocation(int x, int y)
 | |
|   {
 | |
|     TreePath path = getClosestPathForLocation(x, y);
 | |
| 
 | |
|     if (path != null)
 | |
|       return getRowForPath(path);
 | |
| 
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   public Object getLastSelectedPathComponent()
 | |
|   {
 | |
|     TreePath path = getSelectionPath();
 | |
| 
 | |
|     if (path != null)
 | |
|       return path.getLastPathComponent();
 | |
| 
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   private void doExpandParents(TreePath path, boolean state)
 | |
|   {
 | |
|     TreePath parent = path.getParentPath();
 | |
| 
 | |
|     if (!isExpanded(parent) && parent != null)
 | |
|       doExpandParents(parent, false);
 | |
| 
 | |
|     nodeStates.put(path, state ? EXPANDED : COLLAPSED);
 | |
|   }
 | |
| 
 | |
|   protected void setExpandedState(TreePath path, boolean state)
 | |
|   {
 | |
|     if (path == null)
 | |
|       return;
 | |
| 
 | |
|     doExpandParents(path, state);
 | |
|   }
 | |
| 
 | |
|   protected void clearToggledPaths()
 | |
|   {
 | |
|     nodeStates.clear();
 | |
|   }
 | |
| 
 | |
|   protected Enumeration<TreePath> getDescendantToggledPaths(TreePath parent)
 | |
|   {
 | |
|     if (parent == null)
 | |
|       return null;
 | |
| 
 | |
|     Enumeration nodes = nodeStates.keys();
 | |
|     Vector result = new Vector();
 | |
| 
 | |
|     while (nodes.hasMoreElements())
 | |
|       {
 | |
|         TreePath path = (TreePath) nodes.nextElement();
 | |
| 
 | |
|         if (path.isDescendant(parent))
 | |
|           result.addElement(path);
 | |
|       }
 | |
| 
 | |
|     return result.elements();
 | |
|   }
 | |
| 
 | |
|   public boolean hasBeenExpanded(TreePath path)
 | |
|   {
 | |
|     if (path == null)
 | |
|       return false;
 | |
| 
 | |
|     return nodeStates.get(path) != null;
 | |
|   }
 | |
| 
 | |
|   public boolean isVisible(TreePath path)
 | |
|   {
 | |
|     if (path == null)
 | |
|       return false;
 | |
| 
 | |
|     TreePath parent = path.getParentPath();
 | |
| 
 | |
|     if (parent == null)
 | |
|       return true; // Is root node.
 | |
| 
 | |
|     return isExpanded(parent);
 | |
|   }
 | |
| 
 | |
|   public void makeVisible(TreePath path)
 | |
|   {
 | |
|     if (path == null)
 | |
|       return;
 | |
| 
 | |
|     expandPath(path.getParentPath());
 | |
|   }
 | |
| 
 | |
|   public boolean isPathEditable(TreePath path)
 | |
|   {
 | |
|     return isEditable();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates and returns an instance of {@link TreeModelHandler}.
 | |
|    *
 | |
|    * @return an instance of {@link TreeModelHandler}
 | |
|    */
 | |
|   protected TreeModelListener createTreeModelListener()
 | |
|   {
 | |
|     return new TreeModelHandler();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a sample TreeModel that can be used in a JTree. This can be used
 | |
|    * in Bean- or GUI-Builders to show something interesting.
 | |
|    *
 | |
|    * @return a sample TreeModel that can be used in a JTree
 | |
|    */
 | |
|   protected static TreeModel getDefaultTreeModel()
 | |
|   {
 | |
|     DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root node");
 | |
|     DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child node 1");
 | |
|     DefaultMutableTreeNode child11 =
 | |
|       new DefaultMutableTreeNode("Child node 1.1");
 | |
|     DefaultMutableTreeNode child12 =
 | |
|       new DefaultMutableTreeNode("Child node 1.2");
 | |
|     DefaultMutableTreeNode child13 =
 | |
|       new DefaultMutableTreeNode("Child node 1.3");
 | |
|     DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child node 2");
 | |
|     DefaultMutableTreeNode child21 =
 | |
|       new DefaultMutableTreeNode("Child node 2.1");
 | |
|     DefaultMutableTreeNode child22 =
 | |
|       new DefaultMutableTreeNode("Child node 2.2");
 | |
|     DefaultMutableTreeNode child23 =
 | |
|       new DefaultMutableTreeNode("Child node 2.3");
 | |
|     DefaultMutableTreeNode child24 =
 | |
|       new DefaultMutableTreeNode("Child node 2.4");
 | |
| 
 | |
|     DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Child node 3");
 | |
|     root.add(child1);
 | |
|     root.add(child2);
 | |
|     root.add(child3);
 | |
|     child1.add(child11);
 | |
|     child1.add(child12);
 | |
|     child1.add(child13);
 | |
|     child2.add(child21);
 | |
|     child2.add(child22);
 | |
|     child2.add(child23);
 | |
|     child2.add(child24);
 | |
|     return new DefaultTreeModel(root);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Converts the specified value to a String. This is used by the renderers
 | |
|    * of this JTree and its nodes.
 | |
|    *
 | |
|    * This implementation simply returns <code>value.toString()</code> and
 | |
|    * ignores all other parameters. Subclass this method to control the
 | |
|    * conversion.
 | |
|    *
 | |
|    * @param value the value that is converted to a String
 | |
|    * @param selected indicates if that value is selected or not
 | |
|    * @param expanded indicates if that value is expanded or not
 | |
|    * @param leaf indicates if that value is a leaf node or not
 | |
|    * @param row the row of the node
 | |
|    * @param hasFocus indicates if that node has focus or not
 | |
|    */
 | |
|   public String convertValueToText(Object value, boolean selected,
 | |
|                                    boolean expanded, boolean leaf, int row, boolean hasFocus)
 | |
|   {
 | |
|     return value.toString();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * A String representation of this JTree. This is intended to be used for
 | |
|    * debugging. The returned string may be empty but may not be
 | |
|    * <code>null</code>.
 | |
|    *
 | |
|    * @return a String representation of this JTree
 | |
|    */
 | |
|   protected String paramString()
 | |
|   {
 | |
|     // TODO: this is completely legal, but it would possibly be nice
 | |
|     // to return some more content, like the tree structure, some properties
 | |
|     // etc ...
 | |
|     return "";
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns all TreePath objects which are a descendants of the given path
 | |
|    * and are exapanded at the moment of the execution of this method. If the
 | |
|    * state of any node is beeing toggled while this method is executing this
 | |
|    * change may be left unaccounted.
 | |
|    *
 | |
|    * @param path The parent of this request
 | |
|    *
 | |
|    * @return An Enumeration containing TreePath objects
 | |
|    */
 | |
|   public Enumeration<TreePath> getExpandedDescendants(TreePath path)
 | |
|   {
 | |
|     Enumeration paths = nodeStates.keys();
 | |
|     Vector relevantPaths = new Vector();
 | |
|     while (paths.hasMoreElements())
 | |
|       {
 | |
|         TreePath nextPath = (TreePath) paths.nextElement();
 | |
|         if (nodeStates.get(nextPath) == EXPANDED
 | |
|             && path.isDescendant(nextPath))
 | |
|           {
 | |
|             relevantPaths.add(nextPath);
 | |
|           }
 | |
|       }
 | |
|     return relevantPaths.elements();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the next table element (beginning from the row
 | |
|    * <code>startingRow</code> that starts with <code>prefix</code>.
 | |
|    * Searching is done in the direction specified by <code>bias</code>.
 | |
|    *
 | |
|    * @param prefix the prefix to search for in the cell values
 | |
|    * @param startingRow the index of the row where to start searching from
 | |
|    * @param bias the search direction, either {@link Position.Bias#Forward} or
 | |
|    *        {@link Position.Bias#Backward}
 | |
|    *
 | |
|    * @return the path to the found element or -1 if no such element has been
 | |
|    *         found
 | |
|    *
 | |
|    * @throws IllegalArgumentException if prefix is <code>null</code> or
 | |
|    *         startingRow is not valid
 | |
|    *
 | |
|    * @since 1.4
 | |
|    */
 | |
|   public TreePath getNextMatch(String prefix, int startingRow,
 | |
|                                Position.Bias bias)
 | |
|   {
 | |
|     if (prefix == null)
 | |
|       throw new IllegalArgumentException("The argument 'prefix' must not be"
 | |
|                                          + " null.");
 | |
|     if (startingRow < 0)
 | |
|       throw new IllegalArgumentException("The argument 'startingRow' must not"
 | |
|                                          + " be less than zero.");
 | |
| 
 | |
|     int size = getRowCount();
 | |
|     if (startingRow > size)
 | |
|       throw new IllegalArgumentException("The argument 'startingRow' must not"
 | |
|                                          + " be greater than the number of"
 | |
|                                          + " elements in the TreeModel.");
 | |
| 
 | |
|     TreePath foundPath = null;
 | |
|     if (bias == Position.Bias.Forward)
 | |
|       {
 | |
|         for (int i = startingRow; i < size; i++)
 | |
|           {
 | |
|             TreePath path = getPathForRow(i);
 | |
|             Object o = path.getLastPathComponent();
 | |
|             // FIXME: in the following call to convertValueToText the
 | |
|             // last argument (hasFocus) should be done right.
 | |
|             String item = convertValueToText(o, isRowSelected(i),
 | |
|                                              isExpanded(i), treeModel.isLeaf(o),
 | |
|                                              i, false);
 | |
|             if (item.startsWith(prefix))
 | |
|               {
 | |
|                 foundPath = path;
 | |
|                 break;
 | |
|               }
 | |
|           }
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         for (int i = startingRow; i >= 0; i--)
 | |
|           {
 | |
|             TreePath path = getPathForRow(i);
 | |
|             Object o = path.getLastPathComponent();
 | |
|             // FIXME: in the following call to convertValueToText the
 | |
|             // last argument (hasFocus) should be done right.
 | |
|             String item = convertValueToText(o, isRowSelected(i),
 | |
|                                              isExpanded(i), treeModel.isLeaf(o), i, false);
 | |
|             if (item.startsWith(prefix))
 | |
|               {
 | |
|                 foundPath = path;
 | |
|                 break;
 | |
|               }
 | |
|           }
 | |
|       }
 | |
|     return foundPath;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes any paths in the current set of selected paths that are
 | |
|    * descendants of <code>path</code>. If <code>includePath</code> is set
 | |
|    * to <code>true</code> and <code>path</code> itself is selected, then
 | |
|    * it will be removed too.
 | |
|    *
 | |
|    * @param path the path from which selected descendants are to be removed
 | |
|    * @param includeSelected if <code>true</code> then <code>path</code> itself
 | |
|    *        will also be remove if it's selected
 | |
|    *
 | |
|    * @return <code>true</code> if something has been removed,
 | |
|    *         <code>false</code> otherwise
 | |
|    *
 | |
|    * @since 1.3
 | |
|    */
 | |
|   protected boolean removeDescendantSelectedPaths(TreePath path,
 | |
|                                                   boolean includeSelected)
 | |
|   {
 | |
|     boolean removedSomething = false;
 | |
|     TreePath[] selected = getSelectionPaths();
 | |
|     for (int index = 0; index < selected.length; index++)
 | |
|       {
 | |
|         if ((selected[index] == path && includeSelected)
 | |
|             || (selected[index].isDescendant(path)))
 | |
|           {
 | |
|             removeSelectionPath(selected[index]);
 | |
|             removedSomething = true;
 | |
|           }
 | |
|       }
 | |
|     return removedSomething;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes any descendants of the TreePaths in toRemove that have been
 | |
|    * expanded.
 | |
|    *
 | |
|    * @param toRemove - Enumeration of TreePaths that need to be removed from
 | |
|    * cache of toggled tree paths.
 | |
|    */
 | |
|   protected void removeDescendantToggledPaths(Enumeration<TreePath> toRemove)
 | |
|   {
 | |
|     while (toRemove.hasMoreElements())
 | |
|       {
 | |
|         TreePath current = toRemove.nextElement();
 | |
|         Enumeration descendants = getDescendantToggledPaths(current);
 | |
| 
 | |
|         while (descendants.hasMoreElements())
 | |
|           {
 | |
|             TreePath currentDes = (TreePath) descendants.nextElement();
 | |
|             if (isExpanded(currentDes))
 | |
|                 nodeStates.remove(currentDes);
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>
 | |
|    * Sent when the tree has changed enough that we need to resize the bounds,
 | |
|    * but not enough that we need to remove the expanded node set (e.g nodes were
 | |
|    * expanded or collapsed, or nodes were inserted into the tree). You should
 | |
|    * never have to invoke this, the UI will invoke this as it needs to.
 | |
|    * </p>
 | |
|    * <p>
 | |
|    * If the tree uses {@link DefaultTreeModel}, you must call
 | |
|    * {@link DefaultTreeModel#reload(TreeNode)} or
 | |
|    * {@link DefaultTreeModel#reload()} after adding or removing nodes. Following
 | |
|    * the official Java 1.5 API standard, just calling treeDidChange, repaint()
 | |
|    * or revalidate() does <i>not</i> update the tree appearance properly.
 | |
|    *
 | |
|    * @see DefaultTreeModel#reload()
 | |
|    */
 | |
|   public void treeDidChange()
 | |
|   {
 | |
|     repaint();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Helper method for
 | |
|    * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
 | |
|    *
 | |
|    * @param propertyName the name of the property
 | |
|    * @param value the value of the property
 | |
|    *
 | |
|    * @throws IllegalArgumentException if the specified property cannot be set
 | |
|    *         by this method
 | |
|    * @throws ClassCastException if the property value does not match the
 | |
|    *         property type
 | |
|    * @throws NullPointerException if <code>c</code> or
 | |
|    *         <code>propertyValue</code> is <code>null</code>
 | |
|    */
 | |
|   void setUIProperty(String propertyName, Object value)
 | |
|   {
 | |
|     if (propertyName.equals("rowHeight"))
 | |
|       {
 | |
|         if (! clientRowHeightSet)
 | |
|           {
 | |
|             setRowHeight(((Integer) value).intValue());
 | |
|             clientRowHeightSet = false;
 | |
|           }
 | |
|       }
 | |
|     else if (propertyName.equals("scrollsOnExpand"))
 | |
|       {
 | |
|         if (! clientScrollsOnExpandSet)
 | |
|           {
 | |
|             setScrollsOnExpand(((Boolean) value).booleanValue());
 | |
|             clientScrollsOnExpandSet = false;
 | |
|           }
 | |
|       }
 | |
|     else if (propertyName.equals("showsRootHandles"))
 | |
|       {
 | |
|         if (! clientShowsRootHandlesSet)
 | |
|           {
 | |
|             setShowsRootHandles(((Boolean) value).booleanValue());
 | |
|             clientShowsRootHandlesSet = false;
 | |
|           }
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         super.setUIProperty(propertyName, value);
 | |
|       }
 | |
|   }
 | |
| }
 |