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