Source for javax.swing.plaf.basic.BasicFileChooserUI

   1: /* BasicFileChooserUI.java --
   2:    Copyright (C) 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package javax.swing.plaf.basic;
  39: 
  40: import java.awt.Window;
  41: import java.awt.event.ActionEvent;
  42: import java.awt.event.MouseAdapter;
  43: import java.awt.event.MouseEvent;
  44: import java.awt.event.MouseListener;
  45: import java.beans.PropertyChangeListener;
  46: import java.io.File;
  47: import java.io.IOException;
  48: import java.util.ArrayList;
  49: import java.util.Hashtable;
  50: 
  51: import javax.swing.AbstractAction;
  52: import javax.swing.Action;
  53: import javax.swing.Icon;
  54: import javax.swing.JButton;
  55: import javax.swing.JComponent;
  56: import javax.swing.JDialog;
  57: import javax.swing.JFileChooser;
  58: import javax.swing.JList;
  59: import javax.swing.JPanel;
  60: import javax.swing.JTextField;
  61: import javax.swing.SwingUtilities;
  62: import javax.swing.UIDefaults;
  63: import javax.swing.UIManager;
  64: import javax.swing.event.ListSelectionEvent;
  65: import javax.swing.event.ListSelectionListener;
  66: import javax.swing.filechooser.FileFilter;
  67: import javax.swing.filechooser.FileSystemView;
  68: import javax.swing.filechooser.FileView;
  69: import javax.swing.plaf.ComponentUI;
  70: import javax.swing.plaf.FileChooserUI;
  71: import javax.swing.plaf.metal.MetalIconFactory;
  72: 
  73: 
  74: /**
  75:  * A UI delegate for the {@link JFileChooser} component under the
  76:  * {@link BasicLookAndFeel}.
  77:  */
  78: public class BasicFileChooserUI extends FileChooserUI
  79: {
  80:   /**
  81:    * A file filter that accepts all files.
  82:    */
  83:   protected class AcceptAllFileFilter extends FileFilter
  84:   {
  85:     /**
  86:      * Creates a new instance.
  87:      */
  88:     public AcceptAllFileFilter()
  89:     {
  90:       // Nothing to do here.
  91:     }
  92: 
  93:     /**
  94:      * Returns <code>true</code> always, as all files are accepted by this
  95:      * filter.
  96:      *
  97:      * @param f  the file.
  98:      *
  99:      * @return Always <code>true</code>.
 100:      */
 101:     public boolean accept(File f)
 102:     {
 103:       return true;
 104:     }
 105: 
 106:     /**
 107:      * Returns a description for this filter.
 108:      *
 109:      * @return A description for the file filter.
 110:      */
 111:     public String getDescription()
 112:     {
 113:       return acceptAllFileFilterText;
 114:     }
 115:   }
 116: 
 117:   /**
 118:    * Handles a user action to approve the dialog selection.
 119:    *
 120:    * @see BasicFileChooserUI#getApproveSelectionAction()
 121:    */
 122:   protected class ApproveSelectionAction extends AbstractAction
 123:   {
 124:     /**
 125:      * Creates a new ApproveSelectionAction object.
 126:      */
 127:     protected ApproveSelectionAction()
 128:     {
 129:       super("approveSelection");
 130:     }
 131: 
 132:     /**
 133:      * Sets the current selection and closes the dialog.
 134:      *
 135:      * @param e  the action event.
 136:      */
 137:     public void actionPerformed(ActionEvent e)
 138:     {
 139:       Object obj = null;
 140:       if (parentPath != null)
 141:         obj = new String(parentPath + getFileName());
 142:       else
 143:         obj = filechooser.getSelectedFile();
 144:       if (obj != null)
 145:         {
 146:           File f = filechooser.getFileSystemView().createFileObject(obj.toString());
 147:           File currSelected = filechooser.getSelectedFile();
 148:           if (filechooser.isTraversable(f))
 149:             {
 150:               filechooser.setCurrentDirectory(currSelected);
 151:               filechooser.rescanCurrentDirectory();
 152:             }
 153:           else
 154:             {
 155:               filechooser.approveSelection();
 156:               closeDialog();
 157:             }
 158:         }
 159:       else
 160:         {
 161:           File f = new File(filechooser.getCurrentDirectory(), getFileName());
 162:           if ( selectedDir != null )
 163:             f = selectedDir;
 164:           if (filechooser.isTraversable(f))
 165:             {
 166:               filechooser.setCurrentDirectory(f);
 167:               filechooser.rescanCurrentDirectory();
 168:             }
 169:           else
 170:             {
 171:               filechooser.setSelectedFile(f);
 172:               filechooser.approveSelection();
 173:               closeDialog();
 174:             }
 175:         }
 176:     }
 177:   }
 178: 
 179:   /**
 180:    * Provides presentation information about files and directories.
 181:    */
 182:   protected class BasicFileView extends FileView
 183:   {
 184:     /** Storage for cached icons. */
 185:     protected Hashtable<File, Icon> iconCache = new Hashtable<File, Icon>();
 186: 
 187:     /**
 188:      * Creates a new instance.
 189:      */
 190:     public BasicFileView()
 191:     {
 192:       // Nothing to do here.
 193:     }
 194: 
 195:     /**
 196:      * Adds an icon to the cache, associating it with the given file/directory.
 197:      *
 198:      * @param f  the file/directory.
 199:      * @param i  the icon.
 200:      */
 201:     public void cacheIcon(File f, Icon i)
 202:     {
 203:       iconCache.put(f, i);
 204:     }
 205: 
 206:     /**
 207:      * Clears the icon cache.
 208:      */
 209:     public void clearIconCache()
 210:     {
 211:       iconCache.clear();
 212:     }
 213: 
 214:     /**
 215:      * Retrieves the icon associated with the specified file/directory, if
 216:      * there is one.
 217:      *
 218:      * @param f  the file/directory.
 219:      *
 220:      * @return The cached icon (or <code>null</code>).
 221:      */
 222:     public Icon getCachedIcon(File f)
 223:     {
 224:       return (Icon) iconCache.get(f);
 225:     }
 226: 
 227:     /**
 228:      * Returns a description of the given file/directory.  In this
 229:      * implementation, the description is the same as the name returned by
 230:      * {@link #getName(File)}.
 231:      *
 232:      * @param f  the file/directory.
 233:      *
 234:      * @return A description of the given file/directory.
 235:      */
 236:     public String getDescription(File f)
 237:     {
 238:       return getName(f);
 239:     }
 240: 
 241:     /**
 242:      * Returns an icon appropriate for the given file or directory.
 243:      *
 244:      * @param f  the file/directory.
 245:      *
 246:      * @return An icon.
 247:      */
 248:     public Icon getIcon(File f)
 249:     {
 250:       Icon val = getCachedIcon(f);
 251:       if (val != null)
 252:         return val;
 253:       if (filechooser.isTraversable(f))
 254:         val = directoryIcon;
 255:       else
 256:         val = fileIcon;
 257:       cacheIcon(f, val);
 258:       return val;
 259:     }
 260: 
 261:     /**
 262:      * Returns the name for the given file/directory.
 263:      *
 264:      * @param f  the file/directory.
 265:      *
 266:      * @return The name of the file/directory.
 267:      */
 268:     public String getName(File f)
 269:     {
 270:       String name = null;
 271:       if (f != null)
 272:         {
 273:           JFileChooser c = getFileChooser();
 274:           FileSystemView v = c.getFileSystemView();
 275:           name = v.getSystemDisplayName(f);
 276:         }
 277:       return name;
 278:     }
 279: 
 280:     /**
 281:      * Returns a localised description for the type of file/directory.
 282:      *
 283:      * @param f  the file/directory.
 284:      *
 285:      * @return A type description for the given file/directory.
 286:      */
 287:     public String getTypeDescription(File f)
 288:     {
 289:       if (filechooser.isTraversable(f))
 290:         return dirDescText;
 291:       else
 292:         return fileDescText;
 293:     }
 294: 
 295:     /**
 296:      * Returns {@link Boolean#TRUE} if the given file/directory is hidden,
 297:      * and {@link Boolean#FALSE} otherwise.
 298:      *
 299:      * @param f  the file/directory.
 300:      *
 301:      * @return {@link Boolean#TRUE} or {@link Boolean#FALSE}.
 302:      */
 303:     public Boolean isHidden(File f)
 304:     {
 305:       return Boolean.valueOf(filechooser.getFileSystemView().isHiddenFile(f));
 306:     }
 307:   }
 308: 
 309:   /**
 310:    * Handles an action to cancel the file chooser.
 311:    *
 312:    * @see BasicFileChooserUI#getCancelSelectionAction()
 313:    */
 314:   protected class CancelSelectionAction extends AbstractAction
 315:   {
 316:     /**
 317:      * Creates a new <code>CancelSelectionAction</code> object.
 318:      */
 319:     protected CancelSelectionAction()
 320:     {
 321:       super(null);
 322:     }
 323: 
 324:     /**
 325:      * Cancels the selection and closes the dialog.
 326:      *
 327:      * @param e  the action event (ignored).
 328:      */
 329:     public void actionPerformed(ActionEvent e)
 330:     {
 331:       filechooser.setSelectedFile(null);
 332:       filechooser.setSelectedFiles(null);
 333:       filechooser.cancelSelection();
 334:       closeDialog();
 335:     }
 336:   }
 337: 
 338:   /**
 339:    * An action to handle changes to the parent directory (for example, via
 340:    * a click on the "up folder" button).
 341:    *
 342:    * @see BasicFileChooserUI#getChangeToParentDirectoryAction()
 343:    */
 344:   protected class ChangeToParentDirectoryAction extends AbstractAction
 345:   {
 346:     /**
 347:      * Creates a new <code>ChangeToParentDirectoryAction</code> object.
 348:      */
 349:     protected ChangeToParentDirectoryAction()
 350:     {
 351:       super("Go Up");
 352:     }
 353: 
 354:     /**
 355:      * Handles the action event.
 356:      *
 357:      * @param e  the action event.
 358:      */
 359:     public void actionPerformed(ActionEvent e)
 360:     {
 361:       filechooser.changeToParentDirectory();
 362:       filechooser.revalidate();
 363:       filechooser.repaint();
 364:     }
 365:   }
 366: 
 367:   /**
 368:    * A mouse listener that handles double-click events.
 369:    *
 370:    * @see BasicFileChooserUI#createDoubleClickListener(JFileChooser, JList)
 371:    */
 372:   protected class DoubleClickListener extends MouseAdapter
 373:   {
 374: 
 375:     /** DOCUMENT ME! */
 376:     private Object lastSelected;
 377: 
 378:     /** DOCUMENT ME! */
 379:     private JList list;
 380: 
 381:     /**
 382:      * Creates a new DoubleClickListener object.
 383:      *
 384:      * @param list DOCUMENT ME!
 385:      */
 386:     public DoubleClickListener(JList list)
 387:     {
 388:       this.list = list;
 389:       lastSelected = list.getSelectedValue();
 390:       setDirectorySelected(false);
 391:     }
 392: 
 393:     /**
 394:      * Handles a mouse click event.
 395:      *
 396:      * @param e  the event.
 397:      */
 398:     public void mouseClicked(MouseEvent e)
 399:     {
 400:       Object p = list.getSelectedValue();
 401:       if (p == null)
 402:         return;
 403:       FileSystemView fsv = filechooser.getFileSystemView();
 404:       if (e.getClickCount() >= 2 && lastSelected != null &&
 405:           p.toString().equals(lastSelected.toString()))
 406:         {
 407:           File f = fsv.createFileObject(lastSelected.toString());
 408:           if (filechooser.isTraversable(f))
 409:             {
 410:               filechooser.setCurrentDirectory(f);
 411:               filechooser.rescanCurrentDirectory();
 412:             }
 413:           else
 414:             {
 415:               filechooser.setSelectedFile(f);
 416:               filechooser.approveSelection();
 417:               closeDialog();
 418:             }
 419:         }
 420:       else // single click
 421:         {
 422:           String path = p.toString();
 423:           File f = fsv.createFileObject(path);
 424:           filechooser.setSelectedFile(f);
 425: 
 426:           if (filechooser.isMultiSelectionEnabled())
 427:             {
 428:               int[] inds = list.getSelectedIndices();
 429:               File[] allFiles = new File[inds.length];
 430:               for (int i = 0; i < inds.length; i++)
 431:                 allFiles[i] = (File) list.getModel().getElementAt(inds[i]);
 432:               filechooser.setSelectedFiles(allFiles);
 433:             }
 434: 
 435:           if (filechooser.isTraversable(f))
 436:             {
 437:               setDirectorySelected(true);
 438:               setDirectory(f);
 439:             }
 440:           else
 441:             {
 442:               setDirectorySelected(false);
 443:               setDirectory(null);
 444:             }
 445:           lastSelected = path;
 446:           parentPath = f.getParent();
 447: 
 448:           if (f.isFile())
 449:             setFileName(f.getName());
 450:           else if (filechooser.getFileSelectionMode() !=
 451:                    JFileChooser.FILES_ONLY)
 452:             setFileName(path);
 453:         }
 454:     }
 455: 
 456:     /**
 457:      * Handles a mouse entered event (NOT IMPLEMENTED).
 458:      *
 459:      * @param e  the mouse event.
 460:      */
 461:     public void mouseEntered(MouseEvent e)
 462:     {
 463:       // FIXME: Implement
 464:     }
 465:   }
 466: 
 467:   /**
 468:    * An action that changes the file chooser to display the user's home
 469:    * directory.
 470:    *
 471:    * @see BasicFileChooserUI#getGoHomeAction()
 472:    */
 473:   protected class GoHomeAction extends AbstractAction
 474:   {
 475:     /**
 476:      * Creates a new <code>GoHomeAction</code> object.
 477:      */
 478:     protected GoHomeAction()
 479:     {
 480:       super("Go Home");
 481:     }
 482: 
 483:     /**
 484:      * Sets the directory to the user's home directory, and repaints the
 485:      * file chooser component.
 486:      *
 487:      * @param e  the action event (ignored).
 488:      */
 489:     public void actionPerformed(ActionEvent e)
 490:     {
 491:       filechooser.setCurrentDirectory(filechooser.getFileSystemView()
 492:                                                  .getHomeDirectory());
 493:       filechooser.revalidate();
 494:       filechooser.repaint();
 495:     }
 496:   }
 497: 
 498:   /**
 499:    * An action that handles the creation of a new folder/directory.
 500:    *
 501:    * @see BasicFileChooserUI#getNewFolderAction()
 502:    */
 503:   protected class NewFolderAction extends AbstractAction
 504:   {
 505:     /**
 506:      * Creates a new <code>NewFolderAction</code> object.
 507:      */
 508:     protected NewFolderAction()
 509:     {
 510:       super("New Folder");
 511:     }
 512: 
 513:     /**
 514:      * Handles the event by creating a new folder.
 515:      *
 516:      * @param e  the action event (ignored).
 517:      */
 518:     public void actionPerformed(ActionEvent e)
 519:     {
 520:       try
 521:         {
 522:           filechooser.getFileSystemView().createNewFolder(filechooser
 523:                                                           .getCurrentDirectory());
 524:         }
 525:       catch (IOException ioe)
 526:         {
 527:           return;
 528:         }
 529:       filechooser.rescanCurrentDirectory();
 530:       filechooser.repaint();
 531:     }
 532:   }
 533: 
 534:   /**
 535:    * A listener for selection events in the file list.
 536:    *
 537:    * @see BasicFileChooserUI#createListSelectionListener(JFileChooser)
 538:    */
 539:   protected class SelectionListener implements ListSelectionListener
 540:   {
 541:     /**
 542:      * Creates a new <code>SelectionListener</code> object.
 543:      */
 544:     protected SelectionListener()
 545:     {
 546:       // Nothing to do here.
 547:     }
 548: 
 549:     /**
 550:      * Sets the JFileChooser to the selected file on an update
 551:      *
 552:      * @param e DOCUMENT ME!
 553:      */
 554:     public void valueChanged(ListSelectionEvent e)
 555:     {
 556:       JList list = (JList) e.getSource();
 557:       Object f = list.getSelectedValue();
 558:       if (f == null)
 559:         return;
 560:       File file = filechooser.getFileSystemView().createFileObject(f.toString());
 561:       if (! filechooser.isTraversable(file))
 562:         {
 563:           selectedDir = null;
 564:           filechooser.setSelectedFile(file);
 565:         }
 566:       else
 567:         {
 568:           selectedDir = file;
 569:           filechooser.setSelectedFile(null);
 570:         }
 571:     }
 572:   }
 573: 
 574:   /**
 575:    * DOCUMENT ME!
 576:    *
 577:    * @see BasicFileChooserUI#getUpdateAction()
 578:    */
 579:   protected class UpdateAction extends AbstractAction
 580:   {
 581:     /**
 582:      * Creates a new UpdateAction object.
 583:      */
 584:     protected UpdateAction()
 585:     {
 586:       super(null);
 587:     }
 588: 
 589:     /**
 590:      * NOT YET IMPLEMENTED.
 591:      *
 592:      * @param e  the action event.
 593:      */
 594:     public void actionPerformed(ActionEvent e)
 595:     {
 596:       // FIXME: implement this
 597:     }
 598:   }
 599: 
 600:   /** The localised mnemonic for the cancel button. */
 601:   protected int cancelButtonMnemonic;
 602: 
 603:   /** The localised text for the cancel button. */
 604:   protected String cancelButtonText;
 605: 
 606:   /** The localised tool tip text for the cancel button. */
 607:   protected String cancelButtonToolTipText;
 608: 
 609:   /** An icon representing a computer. */
 610:   protected Icon computerIcon;
 611: 
 612:   /** An icon for the "details view" button. */
 613:   protected Icon detailsViewIcon;
 614: 
 615:   /** An icon representing a directory. */
 616:   protected Icon directoryIcon;
 617: 
 618:   /** The localised Mnemonic for the open button. */
 619:   protected int directoryOpenButtonMnemonic;
 620: 
 621:   /** The localised text for the open button. */
 622:   protected String directoryOpenButtonText;
 623: 
 624:   /** The localised tool tip text for the open button. */
 625:   protected String directoryOpenButtonToolTipText;
 626: 
 627:   /** An icon representing a file. */
 628:   protected Icon fileIcon;
 629: 
 630:   /** An icon representing a floppy drive. */
 631:   protected Icon floppyDriveIcon;
 632: 
 633:   /** An icon representing a hard drive. */
 634:   protected Icon hardDriveIcon;
 635: 
 636:   /** The localised mnemonic for the "help" button. */
 637:   protected int helpButtonMnemonic;
 638: 
 639:   /** The localised text for the "help" button. */
 640:   protected String helpButtonText;
 641: 
 642:   /** The localised tool tip text for the help button. */
 643:   protected String helpButtonToolTipText;
 644: 
 645:   /** An icon representing the user's home folder. */
 646:   protected Icon homeFolderIcon;
 647: 
 648:   /** An icon for the "list view" button. */
 649:   protected Icon listViewIcon;
 650: 
 651:   /** An icon for the "new folder" button. */
 652:   protected Icon newFolderIcon = directoryIcon;
 653: 
 654:   /** The localised mnemonic for the "open" button. */
 655:   protected int openButtonMnemonic;
 656: 
 657:   /** The localised text for the "open" button. */
 658:   protected String openButtonText;
 659: 
 660:   /** The localised tool tip text for the "open" button. */
 661:   protected String openButtonToolTipText;
 662: 
 663:   /** The localised mnemonic for the "save" button. */
 664:   protected int saveButtonMnemonic;
 665: 
 666:   /** The localised text for the "save" button. */
 667:   protected String saveButtonText;
 668: 
 669:   /** The localised tool tip text for the save button. */
 670:   protected String saveButtonToolTipText;
 671: 
 672:   /** The localised mnemonic for the "update" button. */
 673:   protected int updateButtonMnemonic;
 674: 
 675:   /** The localised text for the "update" button. */
 676:   protected String updateButtonText;
 677: 
 678:   /** The localised tool tip text for the "update" button. */
 679:   protected String updateButtonToolTipText;
 680: 
 681:   /** An icon for the "up folder" button. */
 682:   protected Icon upFolderIcon;
 683: 
 684:   // -- begin private, but package local since used in inner classes --
 685: 
 686:   /** The file chooser component represented by this UI delegate. */
 687:   JFileChooser filechooser;
 688: 
 689:   /** The model for the directory list. */
 690:   BasicDirectoryModel model;
 691: 
 692:   /** The file filter for all files. */
 693:   FileFilter acceptAll = new AcceptAllFileFilter();
 694: 
 695:   /** The default file view. */
 696:   FileView fv = new BasicFileView();
 697: 
 698:   /** The accept (open/save) button. */
 699:   JButton accept;
 700: 
 701:   /** An optional accessory panel. */
 702:   JPanel accessoryPanel = new JPanel();
 703: 
 704:   /** A property change listener. */
 705:   PropertyChangeListener propertyChangeListener;
 706: 
 707:   /** The text describing the filter for "all files". */
 708:   String acceptAllFileFilterText;
 709: 
 710:   /** The text describing a directory type. */
 711:   String dirDescText;
 712: 
 713:   /** The text describing a file type. */
 714:   String fileDescText;
 715: 
 716:   /** Is a directory selected? */
 717:   boolean dirSelected;
 718: 
 719:   /** The current directory. */
 720:   File currDir;
 721: 
 722:   // FIXME: describe what is contained in the bottom panel
 723:   /** The bottom panel. */
 724:   JPanel bottomPanel;
 725: 
 726:   /** The close panel. */
 727:   JPanel closePanel;
 728: 
 729:   /** Text box that displays file name */
 730:   JTextField entry;
 731: 
 732:   /** Current parent path */
 733:   String parentPath;
 734: 
 735:   /**
 736:    * The action for the 'approve' button.
 737:    * @see #getApproveSelectionAction()
 738:    */
 739:   private ApproveSelectionAction approveSelectionAction;
 740: 
 741:   /**
 742:    * The action for the 'cancel' button.
 743:    * @see #getCancelSelectionAction()
 744:    */
 745:   private CancelSelectionAction cancelSelectionAction;
 746: 
 747:   /**
 748:    * The action for the 'go home' control button.
 749:    * @see #getGoHomeAction()
 750:    */
 751:   private GoHomeAction goHomeAction;
 752: 
 753:   /**
 754:    * The action for the 'up folder' control button.
 755:    * @see #getChangeToParentDirectoryAction()
 756:    */
 757:   private ChangeToParentDirectoryAction changeToParentDirectoryAction;
 758: 
 759:   /**
 760:    * The action for the 'new folder' control button.
 761:    * @see #getNewFolderAction()
 762:    */
 763:   private NewFolderAction newFolderAction;
 764: 
 765:   /**
 766:    * The action for ???.  // FIXME: what is this?
 767:    * @see #getUpdateAction()
 768:    */
 769:   private UpdateAction updateAction;
 770: 
 771:   /**
 772:    * When in FILES_ONLY, mode a directory cannot be selected, so
 773:    * we save a reference to any it here. This is used to enter
 774:    * the directory on "Open" when in that mode.
 775:    */
 776:   private File selectedDir;
 777: 
 778:   // -- end private --
 779: 
 780:   /**
 781:    * Closes the dialog.
 782:    */
 783:   void closeDialog()
 784:   {
 785:     Window owner = SwingUtilities.windowForComponent(filechooser);
 786:     if (owner instanceof JDialog)
 787:       ((JDialog) owner).dispose();
 788:   }
 789: 
 790:   /**
 791:    * Creates a new <code>BasicFileChooserUI</code> object.
 792:    *
 793:    * @param b  the file chooser component.
 794:    */
 795:   public BasicFileChooserUI(JFileChooser b)
 796:   {
 797:   }
 798: 
 799:   /**
 800:    * Returns a UI delegate for the given component.
 801:    *
 802:    * @param c  the component (should be a {@link JFileChooser}).
 803:    *
 804:    * @return A new UI delegate.
 805:    */
 806:   public static ComponentUI createUI(JComponent c)
 807:   {
 808:     return new BasicFileChooserUI((JFileChooser) c);
 809:   }
 810: 
 811:   /**
 812:    * Installs the UI for the specified component.
 813:    *
 814:    * @param c  the component (should be a {@link JFileChooser}).
 815:    */
 816:   public void installUI(JComponent c)
 817:   {
 818:     if (c instanceof JFileChooser)
 819:       {
 820:         JFileChooser fc = (JFileChooser) c;
 821:         this.filechooser = fc;
 822:         fc.resetChoosableFileFilters();
 823:         createModel();
 824:         clearIconCache();
 825:         installDefaults(fc);
 826:         installComponents(fc);
 827:         installListeners(fc);
 828: 
 829:         File path = filechooser.getCurrentDirectory();
 830:         if (path != null)
 831:           parentPath = path.getParent();
 832:       }
 833:   }
 834: 
 835:   /**
 836:    * Uninstalls this UI from the given component.
 837:    *
 838:    * @param c  the component (should be a {@link JFileChooser}).
 839:    */
 840:   public void uninstallUI(JComponent c)
 841:   {
 842:     model = null;
 843:     uninstallListeners(filechooser);
 844:     uninstallComponents(filechooser);
 845:     uninstallDefaults(filechooser);
 846:     filechooser = null;
 847:   }
 848: 
 849:   // FIXME: Indent the entries in the combobox
 850:   // Made this method package private to access it from within inner classes
 851:   // with better performance
 852:   void boxEntries()
 853:   {
 854:     ArrayList parentFiles = new ArrayList();
 855:     File parent = filechooser.getCurrentDirectory();
 856:     if (parent == null)
 857:       parent = filechooser.getFileSystemView().getDefaultDirectory();
 858:     while (parent != null)
 859:       {
 860:         String name = parent.getName();
 861:         if (name.equals(""))
 862:           name = parent.getAbsolutePath();
 863: 
 864:         parentFiles.add(parentFiles.size(), name);
 865:         parent = parent.getParentFile();
 866:       }
 867: 
 868:     if (parentFiles.size() == 0)
 869:       return;
 870: 
 871:   }
 872: 
 873:   /**
 874:    * Creates and install the subcomponents for the file chooser.
 875:    *
 876:    * @param fc  the file chooser.
 877:    */
 878:   public void installComponents(JFileChooser fc)
 879:   {
 880:   }
 881: 
 882:   /**
 883:    * Uninstalls the components from the file chooser.
 884:    *
 885:    * @param fc  the file chooser.
 886:    */
 887:   public void uninstallComponents(JFileChooser fc)
 888:   {
 889:   }
 890: 
 891:   /**
 892:    * Installs the listeners required by this UI delegate.
 893:    *
 894:    * @param fc  the file chooser.
 895:    */
 896:   protected void installListeners(JFileChooser fc)
 897:   {
 898:     propertyChangeListener = createPropertyChangeListener(filechooser);
 899:     if (propertyChangeListener != null)
 900:       filechooser.addPropertyChangeListener(propertyChangeListener);
 901:     fc.addPropertyChangeListener(getModel());
 902:   }
 903: 
 904:   /**
 905:    * Uninstalls the listeners previously installed by this UI delegate.
 906:    *
 907:    * @param fc  the file chooser.
 908:    */
 909:   protected void uninstallListeners(JFileChooser fc)
 910:   {
 911:     if (propertyChangeListener != null)
 912:       {
 913:         filechooser.removePropertyChangeListener(propertyChangeListener);
 914:         propertyChangeListener = null;
 915:       }
 916:     fc.removePropertyChangeListener(getModel());
 917:   }
 918: 
 919:   /**
 920:    * Installs the defaults for this UI delegate.
 921:    *
 922:    * @param fc  the file chooser.
 923:    */
 924:   protected void installDefaults(JFileChooser fc)
 925:   {
 926:     installIcons(fc);
 927:     installStrings(fc);
 928:   }
 929: 
 930:   /**
 931:    * Uninstalls the defaults previously added by this UI delegate.
 932:    *
 933:    * @param fc  the file chooser.
 934:    */
 935:   protected void uninstallDefaults(JFileChooser fc)
 936:   {
 937:     uninstallStrings(fc);
 938:     uninstallIcons(fc);
 939:   }
 940: 
 941:   /**
 942:    * Installs the icons for this UI delegate.
 943:    *
 944:    * @param fc  the file chooser (ignored).
 945:    */
 946:   protected void installIcons(JFileChooser fc)
 947:   {
 948:     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
 949:     computerIcon = MetalIconFactory.getTreeComputerIcon();
 950:     detailsViewIcon = defaults.getIcon("FileChooser.detailsViewIcon");
 951:     directoryIcon = new MetalIconFactory.TreeFolderIcon();
 952:     fileIcon = new MetalIconFactory.TreeLeafIcon();
 953:     floppyDriveIcon = MetalIconFactory.getTreeFloppyDriveIcon();
 954:     hardDriveIcon = MetalIconFactory.getTreeHardDriveIcon();
 955:     homeFolderIcon = defaults.getIcon("FileChooser.homeFolderIcon");
 956:     listViewIcon = defaults.getIcon("FileChooser.listViewIcon");
 957:     newFolderIcon = defaults.getIcon("FileChooser.newFolderIcon");
 958:     upFolderIcon = defaults.getIcon("FileChooser.upFolderIcon");
 959:   }
 960: 
 961:   /**
 962:    * Uninstalls the icons previously added by this UI delegate.
 963:    *
 964:    * @param fc  the file chooser.
 965:    */
 966:   protected void uninstallIcons(JFileChooser fc)
 967:   {
 968:     computerIcon = null;
 969:     detailsViewIcon = null;
 970:     directoryIcon = null;
 971:     fileIcon = null;
 972:     floppyDriveIcon = null;
 973:     hardDriveIcon = null;
 974:     homeFolderIcon = null;
 975:     listViewIcon = null;
 976:     newFolderIcon = null;
 977:     upFolderIcon = null;
 978:   }
 979: 
 980:   /**
 981:    * Installs the strings used by this UI delegate.
 982:    *
 983:    * @param fc  the file chooser.
 984:    */
 985:   protected void installStrings(JFileChooser fc)
 986:   {
 987:     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
 988: 
 989:     dirDescText = defaults.getString("FileChooser.directoryDescriptionText");
 990:     fileDescText = defaults.getString("FileChooser.fileDescriptionText");
 991: 
 992:     acceptAllFileFilterText = defaults.getString("FileChooser.acceptAllFileFilterText");
 993:     cancelButtonText = "Cancel";
 994:     cancelButtonToolTipText = "Abort file chooser dialog";
 995:     cancelButtonMnemonic = new Integer((String) UIManager.get("FileChooser.cancelButtonMnemonic")).intValue();
 996: 
 997:     directoryOpenButtonText = "Open";
 998:     directoryOpenButtonToolTipText = "Open selected directory";
 999:     directoryOpenButtonMnemonic
1000:         = new Integer((String) UIManager.get("FileChooser.directoryOpenButtonMnemonic")).intValue();
1001: 
1002:     helpButtonText = "Help";
1003:     helpButtonToolTipText = "FileChooser help";
1004:     helpButtonMnemonic = new Integer((String) UIManager.get("FileChooser.helpButtonMnemonic")).intValue();
1005: 
1006:     openButtonText = "Open";
1007:     openButtonToolTipText = "Open selected file";
1008:     openButtonMnemonic = new Integer((String) UIManager.get("FileChooser.openButtonMnemonic")).intValue();
1009: 
1010:     saveButtonText = "Save";
1011:     saveButtonToolTipText = "Save selected file";
1012:     saveButtonMnemonic = new Integer((String) UIManager.get("FileChooser.saveButtonMnemonic")).intValue();
1013: 
1014:     updateButtonText = "Update";
1015:     updateButtonToolTipText = "Update directory listing";
1016:     updateButtonMnemonic = new Integer((String) UIManager.get("FileChooser.updateButtonMnemonic")).intValue();
1017:   }
1018: 
1019:   /**
1020:    * Uninstalls the strings previously added by this UI delegate.
1021:    *
1022:    * @param fc  the file chooser.
1023:    */
1024:   protected void uninstallStrings(JFileChooser fc)
1025:   {
1026:     acceptAllFileFilterText = null;
1027:     dirDescText = null;
1028:     fileDescText = null;
1029: 
1030:     cancelButtonText = null;
1031:     cancelButtonToolTipText = null;
1032: 
1033:     directoryOpenButtonText = null;
1034:     directoryOpenButtonToolTipText = null;
1035: 
1036:     helpButtonText = null;
1037:     helpButtonToolTipText = null;
1038: 
1039:     openButtonText = null;
1040:     openButtonToolTipText = null;
1041: 
1042:     saveButtonText = null;
1043:     saveButtonToolTipText = null;
1044: 
1045:     updateButtonText = null;
1046:     updateButtonToolTipText = null;
1047:   }
1048: 
1049:   /**
1050:    * Creates a new directory model.
1051:    */
1052:   protected void createModel()
1053:   {
1054:     model = new BasicDirectoryModel(filechooser);
1055:   }
1056: 
1057:   /**
1058:    * Returns the directory model.
1059:    *
1060:    * @return The directory model.
1061:    */
1062:   public BasicDirectoryModel getModel()
1063:   {
1064:     return model;
1065:   }
1066: 
1067:   /**
1068:    * Creates a listener to handle changes to the properties of the given
1069:    * file chooser component.
1070:    *
1071:    * @param fc  the file chooser component.
1072:    *
1073:    * @return A new listener.
1074:    */
1075:   public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
1076:   {
1077:     // The RI returns null here, so do we.
1078:     return null;
1079:   }
1080: 
1081:   /**
1082:    * Returns the current file name.
1083:    *
1084:    * @return The current file name.
1085:    */
1086:   public String getFileName()
1087:   {
1088:     return entry.getText();
1089:   }
1090: 
1091:   /**
1092:    * Returns the current directory name.
1093:    *
1094:    * @return The directory name.
1095:    *
1096:    * @see #setDirectoryName(String)
1097:    */
1098:   public String getDirectoryName()
1099:   {
1100:     // XXX: I don't see a case where the thing returns something non-null..
1101:     return null;
1102:   }
1103: 
1104:   /**
1105:    * Sets the file name.
1106:    *
1107:    * @param filename  the file name.
1108:    *
1109:    * @see #getFileName()
1110:    */
1111:   public void setFileName(String filename)
1112:   {
1113:     // FIXME:  it might be the case that this method provides an access
1114:     // point for the JTextField (or whatever) a subclass is using...
1115:     //this.filename = filename;
1116:   }
1117: 
1118:   /**
1119:    * Sets the directory name (NOT IMPLEMENTED).
1120:    *
1121:    * @param dirname  the directory name.
1122:    *
1123:    * @see #getDirectoryName()
1124:    */
1125:   public void setDirectoryName(String dirname)
1126:   {
1127:     // FIXME: Implement
1128:   }
1129: 
1130:   /**
1131:    * Rescans the current directory.
1132:    *
1133:    * @param fc  the file chooser.
1134:    */
1135:   public void rescanCurrentDirectory(JFileChooser fc)
1136:   {
1137:     getModel().validateFileCache();
1138:   }
1139: 
1140:   /**
1141:    * NOT YET IMPLEMENTED.
1142:    *
1143:    * @param fc  the file chooser.
1144:    * @param f  the file.
1145:    */
1146:   public void ensureFileIsVisible(JFileChooser fc, File f)
1147:   {
1148:     // XXX: Not sure what this does.
1149:   }
1150: 
1151:   /**
1152:    * Returns the {@link JFileChooser} component that this UI delegate
1153:    * represents.
1154:    *
1155:    * @return The component represented by this UI delegate.
1156:    */
1157:   public JFileChooser getFileChooser()
1158:   {
1159:     return filechooser;
1160:   }
1161: 
1162:   /**
1163:    * Returns the optional accessory panel.
1164:    *
1165:    * @return The optional accessory panel.
1166:    */
1167:   public JPanel getAccessoryPanel()
1168:   {
1169:     return accessoryPanel;
1170:   }
1171: 
1172:   /**
1173:    * Returns the approve (open or save) button for the dialog.
1174:    *
1175:    * @param fc  the file chooser.
1176:    *
1177:    * @return The button.
1178:    */
1179:   protected JButton getApproveButton(JFileChooser fc)
1180:   {
1181:     return accept;
1182:   }
1183: 
1184:   /**
1185:    * Returns the tool tip text for the approve (open/save) button.  This first
1186:    * checks the file chooser to see if a value has been explicitly set - if
1187:    * not, a default value appropriate for the type of file chooser is
1188:    * returned.
1189:    *
1190:    * @param fc  the file chooser.
1191:    *
1192:    * @return The tool tip text.
1193:    */
1194:   public String getApproveButtonToolTipText(JFileChooser fc)
1195:   {
1196:     if (fc.getApproveButtonToolTipText() != null)
1197:       return fc.getApproveButtonToolTipText();
1198:     else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
1199:       return saveButtonToolTipText;
1200:     else
1201:       return openButtonToolTipText;
1202:   }
1203: 
1204:   /**
1205:    * Clears the icon cache.
1206:    */
1207:   public void clearIconCache()
1208:   {
1209:     if (fv instanceof BasicFileView)
1210:       ((BasicFileView) fv).clearIconCache();
1211:   }
1212: 
1213:   /**
1214:    * Creates a new listener to handle selections in the file list.
1215:    *
1216:    * @param fc  the file chooser component.
1217:    *
1218:    * @return A new instance of {@link SelectionListener}.
1219:    */
1220:   public ListSelectionListener createListSelectionListener(JFileChooser fc)
1221:   {
1222:     return new SelectionListener();
1223:   }
1224: 
1225:   /**
1226:    * Creates a new listener to handle double-click events.
1227:    *
1228:    * @param fc  the file chooser component.
1229:    * @param list  the list.
1230:    *
1231:    * @return A new instance of {@link DoubleClickListener}.
1232:    */
1233:   protected MouseListener createDoubleClickListener(JFileChooser fc, JList list)
1234:   {
1235:     return new DoubleClickListener(list);
1236:   }
1237: 
1238:   /**
1239:    * Returns <code>true</code> if a directory is selected, and
1240:    * <code>false</code> otherwise.
1241:    *
1242:    * @return A boolean.
1243:    */
1244:   protected boolean isDirectorySelected()
1245:   {
1246:     return dirSelected;
1247:   }
1248: 
1249:   /**
1250:    * Sets the flag that indicates whether the current directory is selected.
1251:    *
1252:    * @param selected  the new flag value.
1253:    */
1254:   protected void setDirectorySelected(boolean selected)
1255:   {
1256:     dirSelected = selected;
1257:   }
1258: 
1259:   /**
1260:    * Returns the current directory.
1261:    *
1262:    * @return The current directory.
1263:    */
1264:   protected File getDirectory()
1265:   {
1266:     return currDir;
1267:   }
1268: 
1269:   /**
1270:    * Sets the current directory.
1271:    *
1272:    * @param f  the directory.
1273:    */
1274:   protected void setDirectory(File f)
1275:   {
1276:     currDir = f;
1277:   }
1278: 
1279:   /**
1280:    * Returns the "accept all" file filter.
1281:    *
1282:    * @param fc  the file chooser component.
1283:    *
1284:    * @return The "accept all" file filter.
1285:    */
1286:   public FileFilter getAcceptAllFileFilter(JFileChooser fc)
1287:   {
1288:     return acceptAll;
1289:   }
1290: 
1291:   /**
1292:    * Returns the default file view (NOT the file view from the file chooser,
1293:    * if there is one).
1294:    *
1295:    * @param fc  the file chooser component.
1296:    *
1297:    * @return The file view.
1298:    *
1299:    * @see JFileChooser#getFileView()
1300:    */
1301:   public FileView getFileView(JFileChooser fc)
1302:   {
1303:     return fv;
1304:   }
1305: 
1306:   /**
1307:    * Returns the dialog title.
1308:    *
1309:    * @param fc  the file chooser (<code>null</code> not permitted).
1310:    *
1311:    * @return The dialog title.
1312:    *
1313:    * @see JFileChooser#getDialogTitle()
1314:    */
1315:   public String getDialogTitle(JFileChooser fc)
1316:   {
1317:     String result = fc.getDialogTitle();
1318:     if (result == null)
1319:       result = getApproveButtonText(fc);
1320:     return result;
1321:   }
1322: 
1323:   /**
1324:    * Returns the approve button mnemonic.
1325:    *
1326:    * @param fc  the file chooser (<code>null</code> not permitted).
1327:    *
1328:    * @return The approve button mnemonic.
1329:    *
1330:    * @see JFileChooser#getApproveButtonMnemonic()
1331:    */
1332:   public int getApproveButtonMnemonic(JFileChooser fc)
1333:   {
1334:     if (fc.getApproveButtonMnemonic() != 0)
1335:       return fc.getApproveButtonMnemonic();
1336:     else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
1337:       return saveButtonMnemonic;
1338:     else
1339:       return openButtonMnemonic;
1340:   }
1341: 
1342:   /**
1343:    * Returns the approve button text.
1344:    *
1345:    * @param fc  the file chooser (<code>null</code> not permitted).
1346:    *
1347:    * @return The approve button text.
1348:    *
1349:    * @see JFileChooser#getApproveButtonText()
1350:    */
1351:   public String getApproveButtonText(JFileChooser fc)
1352:   {
1353:     String result = fc.getApproveButtonText();
1354:     if (result == null)
1355:       {
1356:         if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
1357:           result = saveButtonText;
1358:         else
1359:           result = openButtonText;
1360:       }
1361:     return result;
1362:   }
1363: 
1364:   /**
1365:    * Creates and returns a new action that will be used with the "new folder"
1366:    * button.
1367:    *
1368:    * @return A new instance of {@link NewFolderAction}.
1369:    */
1370:   public Action getNewFolderAction()
1371:   {
1372:     if (newFolderAction == null)
1373:       newFolderAction = new NewFolderAction();
1374:     return newFolderAction;
1375:   }
1376: 
1377:   /**
1378:    * Creates and returns a new action that will be used with the "home folder"
1379:    * button.
1380:    *
1381:    * @return A new instance of {@link GoHomeAction}.
1382:    */
1383:   public Action getGoHomeAction()
1384:   {
1385:     if (goHomeAction == null)
1386:       goHomeAction = new GoHomeAction();
1387:     return goHomeAction;
1388:   }
1389: 
1390:   /**
1391:    * Returns the action that handles events for the "up folder" control button.
1392:    *
1393:    * @return An instance of {@link ChangeToParentDirectoryAction}.
1394:    */
1395:   public Action getChangeToParentDirectoryAction()
1396:   {
1397:     if (changeToParentDirectoryAction == null)
1398:       changeToParentDirectoryAction = new ChangeToParentDirectoryAction();
1399:     return changeToParentDirectoryAction;
1400:   }
1401: 
1402:   /**
1403:    * Returns the action that handles events for the "approve" button.
1404:    *
1405:    * @return An instance of {@link ApproveSelectionAction}.
1406:    */
1407:   public Action getApproveSelectionAction()
1408:   {
1409:     if (approveSelectionAction == null)
1410:       approveSelectionAction = new ApproveSelectionAction();
1411:     return approveSelectionAction;
1412:   }
1413: 
1414:   /**
1415:    * Returns the action that handles events for the "cancel" button.
1416:    *
1417:    * @return An instance of {@link CancelSelectionAction}.
1418:    */
1419:   public Action getCancelSelectionAction()
1420:   {
1421:     if (cancelSelectionAction == null)
1422:       cancelSelectionAction = new CancelSelectionAction();
1423:     return cancelSelectionAction;
1424:   }
1425: 
1426:   /**
1427:    * Returns the update action (an instance of {@link UpdateAction}).
1428:    *
1429:    * @return An action.
1430:    */
1431:   public Action getUpdateAction()
1432:   {
1433:     if (updateAction == null)
1434:       updateAction = new UpdateAction();
1435:     return updateAction;
1436:   }
1437: }