Coverage Report - net.wotonomy.ui.swing.components.TreeChooser
 
Classes in this File Line Coverage Branch Coverage Complexity
TreeChooser
0% 
0% 
1.725
 
 1  0
 /*
 2  
 Wotonomy: OpenStep design patterns for pure Java applications.
 3  
 Copyright (C) 2000 Intersect Software Corporation
 4  
 
 5  
 This library is free software; you can redistribute it and/or
 6  
 modify it under the terms of the GNU Lesser General Public
 7  
 License as published by the Free Software Foundation; either
 8  
 version 2.1 of the License, or (at your option) any later version.
 9  
 
 10  
 This library is distributed in the hope that it will be useful,
 11  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 Lesser General Public License for more details.
 14  
 
 15  
 You should have received a copy of the GNU Lesser General Public
 16  
 License along with this library; if not, see http://www.gnu.org
 17  
 */
 18  
 
 19  
 package net.wotonomy.ui.swing.components;
 20  
 
 21  
 import java.awt.BorderLayout;
 22  
 import java.awt.Component;
 23  
 import java.awt.Cursor;
 24  
 import java.awt.Dimension;
 25  
 import java.awt.GridBagConstraints;
 26  
 import java.awt.GridBagLayout;
 27  
 import java.awt.event.ActionEvent;
 28  
 import java.awt.event.ActionListener;
 29  
 import java.awt.event.MouseAdapter;
 30  
 import java.awt.event.MouseEvent;
 31  
 import java.util.Enumeration;
 32  
 import java.util.LinkedList;
 33  
 import java.util.List;
 34  
 import java.util.Stack;
 35  
 import java.util.Vector;
 36  
 
 37  
 import javax.swing.ComboBoxModel;
 38  
 import javax.swing.JButton;
 39  
 import javax.swing.JComboBox;
 40  
 import javax.swing.JComponent;
 41  
 import javax.swing.JList;
 42  
 import javax.swing.JPanel;
 43  
 import javax.swing.JScrollPane;
 44  
 import javax.swing.JToolBar;
 45  
 import javax.swing.JTree;
 46  
 import javax.swing.ListCellRenderer;
 47  
 import javax.swing.ListSelectionModel;
 48  
 import javax.swing.UIManager;
 49  
 import javax.swing.event.ListDataEvent;
 50  
 import javax.swing.event.ListDataListener;
 51  
 import javax.swing.event.ListSelectionEvent;
 52  
 import javax.swing.event.ListSelectionListener;
 53  
 import javax.swing.event.TreeModelEvent;
 54  
 import javax.swing.event.TreeModelListener;
 55  
 import javax.swing.event.TreeSelectionEvent;
 56  
 import javax.swing.event.TreeSelectionListener;
 57  
 import javax.swing.tree.DefaultMutableTreeNode;
 58  
 import javax.swing.tree.DefaultTreeCellRenderer;
 59  
 import javax.swing.tree.DefaultTreeModel;
 60  
 import javax.swing.tree.DefaultTreeSelectionModel;
 61  
 import javax.swing.tree.TreeCellRenderer;
 62  
 import javax.swing.tree.TreeModel;
 63  
 import javax.swing.tree.TreePath;
 64  
 import javax.swing.tree.TreeSelectionModel;
 65  
 
 66  
 import net.wotonomy.foundation.internal.WotonomyException;
 67  
 
 68  
 /**
 69  
 * TreeChooser is a FileChooser-like panel that
 70  
 * uses a TreeModel as a data source.  It basically
 71  
 * provides an alternative to JTree for rendering 
 72  
 * and manipulating tree-like data.
 73  
 *
 74  
 * @author michael@mpowers.net
 75  
 * @author $Author: cgruber $
 76  
 * @version $Revision: 904 $
 77  
 */
 78  
 public class TreeChooser extends JPanel 
 79  
     implements ActionListener, ListSelectionListener, 
 80  
         TreeSelectionListener, TreeModelListener, ListCellRenderer
 81  
 {   
 82  
     /**
 83  
     * The TreeChooser responds to this action command
 84  
     * by calling displayPrevious().
 85  
     */
 86  
         public static final String BACK = "Back";
 87  
 
 88  
     /**
 89  
     * The TreeChooser responds to this action command
 90  
     * by calling displayHome().
 91  
     */
 92  
         public static final String HOME = "Home";
 93  
 
 94  
     /**
 95  
     * The TreeChooser responds to this action command
 96  
     * by calling displayParent().
 97  
     */
 98  
         public static final String UP = "Up";
 99  
 
 100  
     /**
 101  
     * The TreeChooser responds to this action command
 102  
     * by attempting to navigate to the first node in
 103  
     * the current selection and display that node's children.
 104  
     */
 105  
         public static final String SELECT = "Select";
 106  
 
 107  
         protected JList contents;
 108  
         protected JComboBox pathCombo; 
 109  
         protected JToolBar toolBar;
 110  
         
 111  
         protected TreeModel model;
 112  
         protected TreeSelectionModel selectionModel;
 113  
     protected TreeCellRenderer renderer;
 114  
     protected TreePath displayPath;
 115  
     protected Stack pathStack;
 116  
     protected int pathIndent;        
 117  
     
 118  
     private ChooserComboBoxModel comboBoxModel;
 119  
     private JTree bogusJTree; // needed for tree cell renderer
 120  
     private Dimension preferredSize;
 121  
         
 122  0
     public TreeChooser()
 123  0
     {
 124  0
         preferredSize = new Dimension( 300, 200 );
 125  0
         model = new DefaultTreeModel( new DefaultMutableTreeNode( "Root" ) );
 126  0
         displayPath = new TreePath( model.getRoot() );
 127  0
         selectionModel = new DefaultTreeSelectionModel();
 128  0
         renderer = new DefaultTreeCellRenderer();
 129  0
         pathStack = new Stack();
 130  0
         pathIndent = 0; // 16;
 131  0
         comboBoxModel = new ChooserComboBoxModel( this );
 132  
         
 133  0
         bogusJTree = new JTree();
 134  0
         bogusJTree.setModel( model );
 135  
 
 136  0
                 init();
 137  0
         displayHome();
 138  
         
 139  0
         stopListening(); // clear existing listeners
 140  0
         startListening();
 141  0
         }
 142  
     
 143  
     public Dimension getPreferredSize()
 144  
     {
 145  0
         return preferredSize;
 146  
     }
 147  
     
 148  
         protected void init()
 149  
         {
 150  0
                 this.setLayout( new BorderLayout( 10, 10 ) );        
 151  
                 
 152  0
                 contents = initList();
 153  0
         contents.getSelectionModel().setSelectionMode( 
 154  0
                 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
 155  
                 // synchs with DefaultTreeSelectionModel
 156  
 
 157  0
                 JScrollPane scrollPane = new JScrollPane( contents );
 158  0
                 scrollPane.setPreferredSize( new Dimension( 200, 150 ) );
 159  0
                 this.add( scrollPane, BorderLayout.CENTER );
 160  
 
 161  0
         Component previewPane = initPreviewPane();
 162  0
         if ( previewPane != null )
 163  
         {
 164  0
             this.add( previewPane, BorderLayout.EAST );
 165  
         }
 166  
                 
 167  0
                 JPanel navigationPanel = new JPanel();
 168  0
                 navigationPanel.setLayout( new BorderLayout( 10, 10 ) );
 169  0
                 this.add( navigationPanel, BorderLayout.NORTH );
 170  
         
 171  0
                 pathCombo = initComboBox();
 172  0
         if ( pathCombo != null )
 173  
         {
 174  0
             pathCombo.setModel( comboBoxModel );
 175  
 
 176  
                         // put combo in a grid bag to handle varying
 177  
                         //  heights of JToolBars across platforms
 178  0
                         JPanel panel = new JPanel();
 179  0
                         panel.setLayout( new GridBagLayout() );
 180  0
                         GridBagConstraints gbc = new GridBagConstraints();
 181  0
                         gbc.fill = GridBagConstraints.HORIZONTAL;
 182  0
                         gbc.weightx = 1.0;
 183  0
                         panel.add( pathCombo, gbc );
 184  0
             navigationPanel.add( panel, BorderLayout.CENTER );
 185  
         }
 186  
                 
 187  0
                 Component toolBar = initToolBar();
 188  0
         if ( toolBar != null )
 189  
         {
 190  0
             navigationPanel.add( toolBar, BorderLayout.EAST );
 191  
         }
 192  
                 
 193  0
         }
 194  
     
 195  
     /**
 196  
     * Creates tool bar or return null if no tool bar is desired.
 197  
     * This implementation returns a JToolBar containing buttons
 198  
     * for BACK, UP, and HOME.
 199  
     */ 
 200  
     protected Component initToolBar()
 201  
     {
 202  0
                 JToolBar toolBar = new JToolBar();
 203  0
                 toolBar.setFloatable( false );
 204  
         JButton button;
 205  0
                 button = new JButton( UIManager.getIcon("FileChooser.upFolderIcon") );
 206  0
         button.setActionCommand( UP );
 207  0
         button.addActionListener( this );
 208  0
         toolBar.add( button );
 209  0
                 button = new JButton( UIManager.getIcon("FileChooser.homeFolderIcon") );
 210  0
         button.setActionCommand( HOME );
 211  0
         button.addActionListener( this );
 212  0
         toolBar.add( button );
 213  
 /*        
 214  
                 button = new JButton( UIManager.getIcon("FileChooser.newFolderIcon") );
 215  
         button.setActionCommand( BACK );
 216  
         button.addActionListener( this );
 217  
         toolBar.add( button );
 218  
 */        
 219  0
         return toolBar;
 220  
     }
 221  
     
 222  
     /**
 223  
     * Creates the component that is used to display a preview of the
 224  
     * selected item(s) in the content area.  This component would listen
 225  
     * to the selection model to update itself when the selected items change.
 226  
     * Return null to omit this component.
 227  
     * This implementation returns null.
 228  
     */ 
 229  
     protected Component initPreviewPane()
 230  
     {
 231  0
         return null;
 232  
     }
 233  
     
 234  
     /**
 235  
     * Creates the JComboBox that is used to render the path leading to
 236  
     * the displayed contents.  Return null to omit this combo box.
 237  
     * This implementation returns a stock JComboBox that uses this
 238  
     * class as its cell renderer.
 239  
     */ 
 240  
     protected JComboBox initComboBox()
 241  
     {
 242  0
         JComboBox comboBox = new JComboBox();
 243  0
         comboBox.setRenderer( this );
 244  0
         return comboBox;
 245  
     }
 246  
     
 247  
     /**
 248  
     * Creates the JList that is used to render the path leading to
 249  
     * the displayed contents.  This method may not return null.
 250  
     * This implementation returns a stock JList that uses this
 251  
     * class as its cell renderer and fires a SELECT action event
 252  
     * on double click.
 253  
     */ 
 254  
     protected JList initList()
 255  
     {
 256  0
         JList list = new JList();
 257  0
         list.setCellRenderer( this );
 258  0
         list.addMouseListener( new MouseAdapter() 
 259  
         {
 260  0
             public void mouseClicked( MouseEvent evt )
 261  
             {
 262  0
                 if ( evt.getClickCount() > 1 )
 263  
                 {   
 264  0
                     actionPerformed( new ActionEvent( this, 0, SELECT ) );
 265  
                 }
 266  0
             }
 267  
         });
 268  0
         return list;
 269  
     }
 270  
     
 271  
     /**
 272  
     * Begins listening to the specified tree model 
 273  
     * and tree selection model.
 274  
     */
 275  
     protected void startListening()
 276  
     {
 277  0
         model.addTreeModelListener( this );
 278  0
         selectionModel.addTreeSelectionListener( this );
 279  0
         contents.addListSelectionListener( this );
 280  0
     }
 281  
     
 282  
     /**
 283  
     * Stops listening to the specified tree model 
 284  
     * and tree selection model.
 285  
     */
 286  
     protected void stopListening()
 287  
     {
 288  0
         model.removeTreeModelListener( this );
 289  0
         selectionModel.removeTreeSelectionListener( this );
 290  0
         contents.removeListSelectionListener( this );
 291  0
     }
 292  
     
 293  
     /**
 294  
     * Returns the TreeModel used by the TreeChooser.
 295  
     */ 
 296  
     public TreeModel getModel()
 297  
     {
 298  0
         return model;
 299  
     }
 300  
     
 301  
     /**
 302  
     * Sets the TreeModel used by the TreeChooser.
 303  
     */ 
 304  
     public void setModel( TreeModel aTreeModel )
 305  
     {
 306  0
         stopListening();
 307  0
         model = aTreeModel;
 308  0
         bogusJTree.setModel( aTreeModel );
 309  0
         pathStack.removeAllElements();
 310  0
         startListening();
 311  0
         displayHome();
 312  0
     }
 313  
     
 314  
     /**
 315  
     * Returns the TreeSelectionModel used by the TreeChooser.
 316  
     */ 
 317  
     public TreeSelectionModel getSelectionModel()
 318  
     {
 319  0
         return selectionModel;
 320  
     }
 321  
     
 322  
     /**
 323  
     * Sets the TreeSelectionModel used by the TreeChooser.
 324  
     */ 
 325  
     public void setSelectionModel( TreeSelectionModel aSelectionModel )
 326  
     {
 327  0
         selectionModel = aSelectionModel;
 328  0
         if ( aSelectionModel.getSelectionMode() == 
 329  0
             TreeSelectionModel.SINGLE_TREE_SELECTION )
 330  
         {
 331  0
             contents.getSelectionModel().setSelectionMode( 
 332  0
                 ListSelectionModel.SINGLE_SELECTION );
 333  0
         }
 334  
         else
 335  
         {
 336  0
             contents.getSelectionModel().setSelectionMode( 
 337  0
                 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
 338  
         }
 339  0
         updateSelection();
 340  0
     }
 341  
     
 342  
     /**
 343  
     * Returns the TreeCellRenderer used by the TreeChooser.
 344  
     */ 
 345  
     public TreeCellRenderer getRenderer()
 346  
     {
 347  0
         return renderer;
 348  
     }
 349  
     
 350  
     /**
 351  
     * Sets the TreeCellRenderer used by the TreeChooser.
 352  
     */ 
 353  
     public void setRenderer( TreeCellRenderer aRenderer )
 354  
     {
 355  0
         renderer = aRenderer;
 356  0
         updateContents();
 357  0
     }
 358  
         
 359  
     /**
 360  
     * Displays the "home" directory.
 361  
     * This implementation displays the root node's children.
 362  
     */
 363  
     public void displayHome()
 364  
     {
 365  0
         setDisplayPath( null );        
 366  0
     }
 367  
     
 368  
     /**
 369  
     * Displays the parent path of the currently displayed path.
 370  
     */
 371  
     public void displayParent()
 372  
     {
 373  0
         setDisplayPath( displayPath.getParentPath() );    
 374  0
     }
 375  
     
 376  
     /**
 377  
     * Displays the last displayed path before the current one,
 378  
     * emulating the behavior of a "back" button.
 379  
     */
 380  
     public void displayPrevious()
 381  
     {
 382  0
         if ( pathStack.empty() )
 383  
         {
 384  0
             displayHome();   
 385  0
         }
 386  
         else
 387  
         {
 388  0
             setDisplayPathDirect( (TreePath) pathStack.pop() );
 389  0
             updateContents();
 390  
         }
 391  0
     }
 392  
     
 393  
     /**
 394  
     * Pushes the previous item onto the stack, sets
 395  
     * the display path, and then updates the contents.
 396  
     * If aPath is null, the root node's children are displayed.
 397  
     */
 398  
     public void setDisplayPath( TreePath aPath )
 399  
     {
 400  0
         if ( aPath == null )
 401  
         {
 402  0
             aPath = new TreePath( getModel().getRoot() );
 403  
         }
 404  0
         if ( ! displayPath.equals ( aPath ) )
 405  
         {
 406  0
             pathStack.push( displayPath );
 407  0
             setDisplayPathDirect( aPath );
 408  
         }
 409  0
         updateContents();
 410  0
     }
 411  
     
 412  
     /**
 413  
     * Sets the displayPath field and does not
 414  
     * update the stack nor update the contents.
 415  
     */
 416  
     protected void setDisplayPathDirect( TreePath aPath )
 417  
     {
 418  0
         displayPath = aPath;   
 419  0
     }
 420  
     
 421  
     /**
 422  
     * Gets the currently displayed path.
 423  
     */
 424  
     public TreePath getDisplayPath()
 425  
     {
 426  0
         return displayPath;   
 427  
     }
 428  
 
 429  
     /**
 430  
     * Called when selected path changes or when model indicates
 431  
     * that the displayed path has changed.
 432  
     */
 433  
     protected void updateContents()
 434  
     {
 435  0
         stopListening();
 436  
 
 437  
         // update combo box        
 438  0
         comboBoxModel.fireContentsChanged();
 439  
         
 440  
         // update list contents
 441  0
         Object displayedObject = displayPath.getLastPathComponent();
 442  
 /*
 443  
 //FIXME: this display group doesn't seem to be getting the sort orderings from parent        
 444  
 if ( displayedObject instanceof net.wotonomy.ui.EODisplayGroup )        
 445  
 System.out.println( ((net.wotonomy.ui.EODisplayGroup)displayedObject).displayedObjects() );            
 446  
 */
 447  0
         int count = model.getChildCount( displayedObject );
 448  0
         Object[] children = new Object[ count ];
 449  0
         for ( int i = 0; i < count; i++ )
 450  
         {
 451  0
             children[i] = model.getChild( displayedObject, i );
 452  
         }
 453  0
         contents.setListData( children );
 454  
         
 455  0
         startListening();
 456  
 
 457  
         // synchronize the selection        
 458  0
         updateSelection();
 459  0
     }
 460  
     
 461  
     /**
 462  
     * Updates the selection in the list to reflect the
 463  
     * selection in the tree selection model.
 464  
     */
 465  
     public void updateSelection()
 466  
     {
 467  
         int index;
 468  0
         Object last = displayPath.getLastPathComponent();
 469  0
         TreePath[] selectionPaths = selectionModel.getSelectionPaths();
 470  0
         if ( selectionPaths != null )
 471  
         {
 472  0
             List selectedIndices = new LinkedList();
 473  0
             for ( int i = 0; i < selectionPaths.length; i++ )
 474  
             {
 475  0
                 if ( displayPath.equals( selectionPaths[i].getParentPath() ) )
 476  
                 {
 477  0
                     index = getModel().getIndexOfChild( 
 478  0
                         last, selectionPaths[i].getLastPathComponent() );
 479  0
                     if ( index != -1 ) 
 480  
                     {
 481  0
                         selectedIndices.add( new Integer( index ) );
 482  0
                     }
 483  
                     else // should never happen
 484  
                     {
 485  0
                         throw new WotonomyException( 
 486  0
                             "Could not find child of displayed node." );
 487  
                     }
 488  
                 }
 489  
             }
 490  0
             int[] selected = new int[ selectedIndices.size() ];
 491  0
             for ( int i = 0; i < selected.length; i++ )
 492  
             {
 493  0
                 selected[i] = ((Integer)selectedIndices.get(i)).intValue();   
 494  
             }
 495  0
             stopListening();
 496  0
             contents.setSelectedIndices( selected );
 497  0
             startListening();
 498  
         }
 499  0
     }
 500  
     
 501  
     // interface TreeModelListener
 502  
     
 503  
     public void treeNodesChanged( TreeModelEvent evt )
 504  
     { 
 505  
 /*            
 506  
         if ( displayPath.getLastPathComponent().toString().equals( 
 507  
             evt.getTreePath().getLastPathComponent().toString() ) )
 508  
         {
 509  
 System.out.println( "TreeChooser.treeNodesChanged: " + count++ );  
 510  
 */
 511  0
             updateContents();
 512  
 /*            
 513  
         }
 514  
         else
 515  
         {
 516  
             System.out.println( evt.getTreePath() + " != " + displayPath );
 517  
         }
 518  
 */        
 519  0
     }
 520  
     
 521  
     public void treeNodesInserted( TreeModelEvent evt )
 522  
     { 
 523  
 //            updateContents();
 524  0
     }
 525  
     
 526  
     public void treeNodesRemoved( TreeModelEvent evt )
 527  
     { 
 528  
 //            updateContents();
 529  0
     }
 530  
     
 531  
     public void treeStructureChanged( TreeModelEvent evt )
 532  
     {  
 533  0
         if ( ( evt.getTreePath().equals( displayPath ) )
 534  0
         || ( evt.getTreePath().isDescendant( displayPath ) ) )
 535  
         {
 536  
 //            setDisplayPath( evt.getTreePath() );
 537  
         }
 538  
         
 539  0
         displayHome();
 540  0
     }
 541  
     
 542  
     // interface TreeSelectionListener
 543  
     
 544  
     /**
 545  
     * Called when the tree selection model's value changes.
 546  
     * This is presumably an external change, so this calls
 547  
     * updateSelection.
 548  
     */
 549  
     public void valueChanged( TreeSelectionEvent evt )
 550  
     {
 551  0
         updateSelection();   
 552  0
     }
 553  
 
 554  
     // interface ListSelectionListener
 555  
     
 556  
     /**
 557  
     * Called when user changes the selection in the list.
 558  
     * This implementation updates the tree selection model
 559  
     * with the corresponding selection.
 560  
     */
 561  
     public void valueChanged( ListSelectionEvent evt )
 562  
     {
 563  0
         if ( ! evt.getValueIsAdjusting() )
 564  
         {
 565  0
             Object last = displayPath.getLastPathComponent();
 566  0
             int[] selection = contents.getSelectedIndices();
 567  0
             TreePath[] selectionPaths = new TreePath[ selection.length ];
 568  0
             for ( int i = 0; i < selection.length; i++ )
 569  
             {
 570  0
                 selectionPaths[i] = displayPath.pathByAddingChild(
 571  0
                     getModel().getChild( last, selection[i] ) );
 572  
             }
 573  0
             selectionModel.setSelectionPaths( selectionPaths );
 574  
         }
 575  
               
 576  0
     }
 577  
     
 578  
     // interface ListCellRenderer
 579  
 
 580  
     /**
 581  
     * This method returns the component returned by the tree cell renderer.
 582  
     */
 583  
     public Component getListCellRendererComponent(
 584  
         JList list,
 585  
         Object value,
 586  
         int index,
 587  
         boolean isSelected,
 588  
         boolean cellHasFocus )
 589  
     {
 590  0
         boolean isLeaf = ( model.isLeaf( value ) );
 591  
         
 592  0
         bogusJTree.setForeground( list.getForeground() );
 593  0
         bogusJTree.setBackground( list.getBackground() );
 594  
         
 595  0
         JComponent result = (JComponent) renderer.getTreeCellRendererComponent(
 596  0
             bogusJTree, value, isSelected, (list != contents), 
 597  0
                 isLeaf, index, cellHasFocus );
 598  
 /*
 599  
         if ( ( list != contents ) && ( index > -1 ) )
 600  
         {
 601  
             result.setBorder( 
 602  
                 BorderFactory.createEmptyBorder( 0, index*pathIndent, 0, 0 ) );
 603  
         }
 604  
         else
 605  
         {
 606  
             result.setBorder( 
 607  
                 BorderFactory.createEmptyBorder() );
 608  
         }
 609  
 */        
 610  0
         return result;
 611  
     }
 612  
     
 613  
     // interface ActionListener
 614  
         
 615  
     public void actionPerformed( ActionEvent evt )
 616  
     {
 617  0
         String command = evt.getActionCommand();
 618  
         
 619  0
         if ( HOME.equals( command ) )
 620  
         {
 621  0
             displayHome();
 622  0
         }
 623  
         else
 624  0
         if ( UP.equals( command ) )
 625  
         {
 626  0
             displayParent();
 627  0
         }
 628  
         else
 629  0
         if ( BACK.equals( command ) )
 630  
         {
 631  0
             displayPrevious();
 632  0
         }
 633  
         else
 634  0
         if ( SELECT.equals( command ) )
 635  
         {
 636  0
             Cursor oldCursor = getCursor();
 637  0
             setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );
 638  
             
 639  0
             int index = contents.getSelectedIndex();
 640  
             // if selection 
 641  0
             if ( index != -1 )
 642  
             {
 643  0
                 Object parent = displayPath.getLastPathComponent();
 644  0
                 Object child = getModel().getChild( parent, index );
 645  
                 // if selected item is not a leaf
 646  0
                 if ( getModel().getChildCount( child ) > 0 )
 647  
                 {
 648  
                     // navigate to selected item
 649  0
                     setDisplayPath( displayPath.pathByAddingChild( child ) );
 650  
                 }
 651  
             }
 652  
             
 653  0
             setCursor( oldCursor );
 654  
         }
 655  
     
 656  0
     }
 657  
     
 658  
     private class ChooserComboBoxModel implements ComboBoxModel
 659  
     {
 660  
         TreeChooser treeChooser;
 661  
         Vector listeners;
 662  
         
 663  0
         ChooserComboBoxModel( TreeChooser aTreeChooser )
 664  0
         {
 665  0
             treeChooser = aTreeChooser; 
 666  0
             listeners = new Vector();
 667  0
         }
 668  
         
 669  
         public int getSize()
 670  
         {
 671  0
             return treeChooser.displayPath.getPathCount(); 
 672  
         }
 673  
         
 674  
         public Object getElementAt(int index)
 675  
         {
 676  0
             return treeChooser.displayPath.getPathComponent( index );    
 677  
         }
 678  
         
 679  
         public Object getSelectedItem()
 680  
         {
 681  0
             return treeChooser.displayPath.getLastPathComponent();
 682  
         }
 683  
         
 684  
         public void setSelectedItem(Object anItem)
 685  
         {
 686  0
             if ( ! ( 
 687  0
                 treeChooser.displayPath.getLastPathComponent().equals( anItem ) ) )
 688  
             {
 689  0
                 Object[] items = treeChooser.displayPath.getPath();
 690  0
                 TreePath path = new TreePath( getModel().getRoot() );
 691  0
                 for ( int i = 1; i < items.length; i++ )
 692  
                 {
 693  0
                     if ( path.getLastPathComponent() == anItem )
 694  
                     {
 695  0
                         treeChooser.setDisplayPath( path );
 696  0
                         return;
 697  
                     }
 698  0
                     path = path.pathByAddingChild( items[i] );
 699  
                 }
 700  
             }
 701  0
         }
 702  
         
 703  
         public void addListDataListener(ListDataListener l) 
 704  
         {
 705  0
             listeners.add( l );
 706  0
         }
 707  
         
 708  
         public void removeListDataListener(ListDataListener l) 
 709  
         {
 710  0
             listeners.remove( l );
 711  0
         }
 712  
         
 713  
         public void fireContentsChanged()
 714  
         {
 715  0
             Enumeration e = listeners.elements();
 716  0
             while ( e.hasMoreElements() )
 717  
             {
 718  0
                 ((ListDataListener)e.nextElement()).contentsChanged( 
 719  0
                     new ListDataEvent( 
 720  0
                     this, ListDataEvent.CONTENTS_CHANGED, 0, getSize() ) );
 721  0
             }
 722  0
         }   
 723  
     }
 724  
     
 725  
 }
 726  
 
 727