Source for javax.swing.JFileChooser

   1: /* JFileChooser.java --
   2:    Copyright (C) 2002, 2004, 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;
  39: 
  40: import gnu.classpath.NotImplementedException;
  41: 
  42: import java.awt.Component;
  43: import java.awt.Frame;
  44: import java.awt.HeadlessException;
  45: import java.awt.event.ActionEvent;
  46: import java.awt.event.ActionListener;
  47: import java.beans.PropertyChangeEvent;
  48: import java.io.File;
  49: import java.util.ArrayList;
  50: 
  51: import javax.accessibility.Accessible;
  52: import javax.accessibility.AccessibleContext;
  53: import javax.accessibility.AccessibleRole;
  54: import javax.swing.filechooser.FileFilter;
  55: import javax.swing.filechooser.FileSystemView;
  56: import javax.swing.filechooser.FileView;
  57: import javax.swing.plaf.FileChooserUI;
  58: 
  59: 
  60: /**
  61:  * A component that provides the user a dialog box to browse through a
  62:  * filesystem and choose one or more files or directories.
  63:  *
  64:  * A JFileChooser can be configured to filter the displayed file list
  65:  * by adding a {@link FileFilter} instance using
  66:  * {@link #addChoosableFileFilter(FileFilter)}. Additional components can
  67:  * be embedded in the file chooser using {@link #setAccessory(JComponent)}.
  68:  * The JFileChooser properties also provide mechanisms to customize the
  69:  * behaviour of the file chooser.
  70:  *
  71:  * @author Kim Ho (kho@luxsci.net)
  72:  */
  73: public class JFileChooser extends JComponent implements Accessible
  74: {
  75:   private static final long serialVersionUID = 3162921138695327837L;
  76: 
  77:   /** 
  78:    * A dialog type for selecting a file to open. 
  79:    * @see #setDialogType(int)
  80:    */
  81:   public static final int OPEN_DIALOG = 0;
  82: 
  83:   /** 
  84:    * A dialog type for selecting a file to save.  
  85:    * @see #setDialogType(int)
  86:    */
  87:   public static final int SAVE_DIALOG = 1;
  88: 
  89:   /** 
  90:    * A dialog type for some custom purpose.
  91:    * @see #setDialogType(int)
  92:    */
  93:   public static final int CUSTOM_DIALOG = 2;
  94: 
  95:   /** 
  96:    * A return value indicating the file chooser has been closed by cancelling.
  97:    * 
  98:    * @see #showOpenDialog(Component)
  99:    * @see #showSaveDialog(Component) 
 100:    */
 101:   public static final int CANCEL_OPTION = 1;
 102: 
 103:   /** 
 104:    * A return value indicating the file chooser has been closed by approving
 105:    * the selection.
 106:    * @see #showOpenDialog(Component)
 107:    * @see #showSaveDialog(Component) 
 108:    */
 109:   public static final int APPROVE_OPTION = 0;
 110: 
 111:   /** 
 112:    * A return value indicating the file chooser has been closed by some error.
 113:    * @see #showOpenDialog(Component)
 114:    * @see #showSaveDialog(Component) 
 115:    */
 116:   public static final int ERROR_OPTION = -1;
 117: 
 118:   /** 
 119:    * A selection mode constant indicating acceptance of files only.
 120:    * @see #setFileSelectionMode(int)
 121:    */
 122:   public static final int FILES_ONLY = 0;
 123: 
 124:   /** 
 125:    * A selection mode constant indicating acceptance of directories only. 
 126:    * @see #setFileSelectionMode(int)
 127:    */
 128:   public static final int DIRECTORIES_ONLY = 1;
 129: 
 130:   /** 
 131:    * A selection mode constant indicating acceptance of files and directories.
 132:    * @see #setFileSelectionMode(int)
 133:    */
 134:   public static final int FILES_AND_DIRECTORIES = 2;
 135: 
 136:   /** 
 137:    * Action command string for cancelling the current selection.
 138:    * @see #cancelSelection()
 139:    */
 140:   public static final String CANCEL_SELECTION = "CancelSelection";
 141: 
 142:   /** 
 143:    * Action command string for approving the current selection.
 144:    * @see #cancelSelection()
 145:    */
 146:   public static final String APPROVE_SELECTION = "ApproveSelection";
 147: 
 148:   /**
 149:    * The name of the property for the approve button text.
 150:    * @see #setApproveButtonText(String) 
 151:    */
 152:   public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY =
 153:     "ApproveButtonTextChangedProperty";
 154: 
 155:   /**
 156:    * The name of the property for the approve button tool tip text.
 157:    * @see #setApproveButtonToolTipText(String)
 158:    */
 159:   public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY =
 160:     "ApproveButtonToolTipTextChangedProperty";
 161: 
 162:   /**
 163:    * The name of the property for the approve button mnemonic.
 164:    * @see #setApproveButtonMnemonic(int)
 165:    */
 166:   public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY =
 167:     "ApproveButtonMnemonicChangedProperty";
 168: 
 169:   /**
 170:    * The name of the property for control button visibility.
 171:    * @see #setControlButtonsAreShown(boolean)
 172:    */
 173:   public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY =
 174:     "ControlButtonsAreShownChangedProperty";
 175: 
 176:   /**
 177:    * The name of the property for the current directory.
 178:    * @see #setCurrentDirectory(File)  
 179:    */
 180:   public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
 181: 
 182:   /**
 183:    * The name of the property for the selected file.
 184:    * @see #setSelectedFile(File)
 185:    */
 186:   public static final String SELECTED_FILE_CHANGED_PROPERTY =
 187:     "SelectedFileChangedProperty";
 188: 
 189:   /**
 190:    * The name of the property for the selected files.
 191:    * @see #setSelectedFiles(File[])
 192:    */
 193:   public static final String SELECTED_FILES_CHANGED_PROPERTY =
 194:     "SelectedFilesChangedProperty";
 195: 
 196:   /** 
 197:    * The name of the property for multi-selection.
 198:    * @see #setMultiSelectionEnabled(boolean) 
 199:    */
 200:   public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY =
 201:     "MultiSelectionEnabledChangedProperty";
 202: 
 203:   /**
 204:    * The name of the 'file system view' property.
 205:    * @see #setFileSystemView(FileSystemView) 
 206:    */
 207:   public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY =
 208:     "FileSystemViewChanged";
 209: 
 210:   /**
 211:    * The name of the 'file view' property.
 212:    * @see #setFileView(FileView) 
 213:    */
 214:   public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
 215: 
 216:   /**
 217:    * The name of the 'file hiding enabled' property.
 218:    * @see #setFileHidingEnabled(boolean)
 219:    */
 220:   public static final String FILE_HIDING_CHANGED_PROPERTY =
 221:     "FileHidingChanged";
 222: 
 223:   /**
 224:    * The name of the 'file filter' property.
 225:    * @see #setFileFilter(FileFilter)
 226:    */
 227:   public static final String FILE_FILTER_CHANGED_PROPERTY =
 228:     "fileFilterChanged";
 229: 
 230:   /**
 231:    * The name of the 'file selection mode' property.
 232:    * @see #setFileSelectionMode(int)
 233:    */
 234:   public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY =
 235:     "fileSelectionChanged";
 236: 
 237:   /**
 238:    * The name of the 'accessory' property.
 239:    * @see #setAccessory(JComponent)
 240:    */
 241:   public static final String ACCESSORY_CHANGED_PROPERTY =
 242:     "AccessoryChangedProperty";
 243: 
 244:   /**
 245:    * The name of the 'accept all file filter used' property.
 246:    * @see #setAcceptAllFileFilterUsed(boolean)
 247:    */
 248:   public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY =
 249:     "acceptAllFileFilterUsedChanged";
 250: 
 251:   /**
 252:    * The name of the 'dialog title' property.
 253:    * @see #setDialogTitle(String)
 254:    */
 255:   public static final String DIALOG_TITLE_CHANGED_PROPERTY =
 256:     "DialogTitleChangedProperty";
 257: 
 258:   /**
 259:    * The name of the 'dialog type' property.
 260:    * @see #setDialogType(int)
 261:    */
 262:   public static final String DIALOG_TYPE_CHANGED_PROPERTY =
 263:     "DialogTypeChangedProperty";
 264: 
 265:   /**
 266:    * The name of the 'choosable file filters' property.
 267:    * @see #addChoosableFileFilter(FileFilter)
 268:    */
 269:   public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY =
 270:     "ChoosableFileFilterChangedProperty";
 271: 
 272:   /** 
 273:    * The accessible context. 
 274:    * @see #getAccessibleContext()
 275:    */
 276:   protected AccessibleContext accessibleContext;
 277: 
 278:   /** 
 279:    * The file system view.
 280:    * @see #setFileSystemView(FileSystemView)
 281:    */
 282:   private FileSystemView fsv;
 283: 
 284:   /**
 285:    * The accessory component.
 286:    * @see #setAccessory(JComponent)
 287:    */
 288:   private JComponent accessory;
 289: 
 290:   /**
 291:    * The approve button mnemonic.
 292:    * @see #setApproveButtonMnemonic(int)
 293:    */
 294:   private int approveButtonMnemonic = 0;
 295: 
 296:   /**
 297:    * The approve button text.
 298:    * @see #setApproveButtonText(String)
 299:    */
 300:   private String approveButtonText;
 301: 
 302:   /**
 303:    * The approve button tool tip text.
 304:    * @see #setApproveButtonToolTipText(String)
 305:    */
 306:   private String approveButtonToolTipText;
 307: 
 308:   /**
 309:    * The choosable file filters.
 310:    * @see #addChoosableFileFilter(FileFilter)
 311:    */
 312:   private ArrayList choosableFilters = new ArrayList();
 313: 
 314:   /**
 315:    * A flag controlling whether the accept all file filter is used.
 316:    * @see #setAcceptAllFileFilterUsed(boolean)
 317:    */
 318:   private boolean isAcceptAll = true;
 319: 
 320:   /**
 321:    * The dialog title.
 322:    * @see #setDialogTitle(String)
 323:    */
 324:   private String dialogTitle;
 325: 
 326:   /**
 327:    * The dialog type.
 328:    * @see #setDialogType(int)
 329:    */
 330:   private int dialogType = OPEN_DIALOG;
 331: 
 332:   /**
 333:    * The return value for the dialog.
 334:    * @see #showOpenDialog(Component)
 335:    * @see #showSaveDialog(Component)
 336:    */
 337:   private int retval = ERROR_OPTION;
 338: 
 339:   /**
 340:    * A flag indicating whether the file chooser allows multiple selection.
 341:    * @see #isMultiSelectionEnabled()
 342:    */
 343:   private boolean multiSelection = false;
 344: 
 345:   /**
 346:    * A flag indicating whether file hiding is enabled.
 347:    * @see #isFileHidingEnabled()
 348:    */
 349:   private boolean fileHiding = true;
 350: 
 351:   /**
 352:    * The file selection mode.
 353:    * @see #setFileSelectionMode(int) 
 354:    */
 355:   private int fileSelectionMode = FILES_AND_DIRECTORIES;
 356: 
 357:   /** 
 358:    * The file view.
 359:    * @see #setFileView(FileView)
 360:    */
 361:   private FileView fv = null;
 362: 
 363:   /** 
 364:    * A flag controlling whether or not the control buttons are visible. 
 365:    * @see #setControlButtonsAreShown(boolean) 
 366:    */
 367:   private boolean controlButtonsShown = true;
 368: 
 369:   /** 
 370:    * The current directory. 
 371:    * @see #setCurrentDirectory(File)
 372:    */
 373:   private File currentDir = null;
 374: 
 375:   /** 
 376:    * The current file filter.
 377:    * @see #setFileFilter(FileFilter)
 378:    */
 379:   private FileFilter currentFilter = null;
 380: 
 381:   /** 
 382:    * An array of selected files.
 383:    * @see #setSelectedFiles(File[]) 
 384:    */
 385:   private File[] selectedFiles;
 386: 
 387:   /** 
 388:    * The selected file. 
 389:    * @see #setSelectedFile(File)
 390:    */
 391:   private File selectedFile;
 392: 
 393:   /**
 394:    * Creates a new <code>JFileChooser</code> object.
 395:    */
 396:   public JFileChooser()
 397:   {
 398:     setup(null);
 399:     setCurrentDirectory(null);
 400:   }
 401: 
 402:   /**
 403:    * Creates a new <code>JFileChooser</code> object.
 404:    *
 405:    * @param currentDirectoryPath the directory that should initially be
 406:    *        shown in the filechooser (if <code>null</code>, the user's home 
 407:    *        directory is used).
 408:    */
 409:   public JFileChooser(String currentDirectoryPath)
 410:   {
 411:     this(currentDirectoryPath, null);
 412:   }
 413: 
 414:   /**
 415:    * Creates a new <code>JFileChooser</code> object with the specified 
 416:    * directory and {@link FileSystemView}.
 417:    *
 418:    * @param currentDirectoryPath  the directory that should initially be
 419:    *        shown in the filechooser (if <code>null</code>, the user's home 
 420:    *        directory is used).
 421:    * @param fsv  the file system view (if <code>null</code>, the default file
 422:    *             system view is used).
 423:    */
 424:   public JFileChooser(String currentDirectoryPath, FileSystemView fsv)
 425:   {
 426:     setup(fsv);
 427:     File dir = null;
 428:     if (currentDirectoryPath != null)
 429:       dir = getFileSystemView().createFileObject(currentDirectoryPath);
 430:     setCurrentDirectory(dir);
 431:   }
 432: 
 433:   /**
 434:    * Creates a new <code>JFileChooser</code> object.
 435:    *
 436:    * @param currentDirectory  the directory that should initially be
 437:    *        shown in the filechooser (if <code>null</code>, the user's home 
 438:    *        directory is used).
 439:    */
 440:   public JFileChooser(File currentDirectory)
 441:   {
 442:     setup(null);
 443:     setCurrentDirectory(currentDirectory);
 444:   }
 445: 
 446:   /**
 447:    * Creates a new <code>JFileChooser</code> object.
 448:    *
 449:    * @param fsv  the file system view (if <code>null</code>, the default file
 450:    *             system view is used).
 451:    */
 452:   public JFileChooser(FileSystemView fsv)
 453:   {
 454:     setup(fsv);
 455:     setCurrentDirectory(null);
 456:   }
 457: 
 458:   /**
 459:    * Creates a new <code>JFileChooser</code> object.
 460:    *
 461:    * @param currentDirectory  the directory that should initially be
 462:    *        shown in the filechooser (if <code>null</code>, the user's home 
 463:    *        directory is used).
 464:    * @param fsv  the file system view (if <code>null</code>, the default file
 465:    *             system view is used).
 466:    */
 467:   public JFileChooser(File currentDirectory, FileSystemView fsv)
 468:   {
 469:     setup(fsv);
 470:     setCurrentDirectory(currentDirectory);
 471:   }
 472: 
 473:   /**
 474:    * Sets up the file chooser.  This method is called by all the constructors.
 475:    *
 476:    * @param view  the file system view (if <code>null</code>, the default file
 477:    *              system view is used).
 478:    * 
 479:    * @see FileSystemView#getFileSystemView()
 480:    */
 481:   protected void setup(FileSystemView view)
 482:   {
 483:     if (view == null)
 484:       view = FileSystemView.getFileSystemView();
 485:     setFileSystemView(view);
 486:     updateUI();
 487:   }
 488: 
 489:   /**
 490:    * DOCUMENT ME!
 491:    *
 492:    * @param b DOCUMENT ME!
 493:    */
 494:   public void setDragEnabled(boolean b)
 495:     throws NotImplementedException
 496:   {
 497:     // FIXME: Implement
 498:   }
 499: 
 500:   /**
 501:    * DOCUMENT ME!
 502:    *
 503:    * @return DOCUMENT ME!
 504:    */
 505:   public boolean getDragEnabled()
 506:     throws NotImplementedException
 507:   {
 508:     // FIXME: Implement
 509:     return false;
 510:   }
 511: 
 512:   /**
 513:    * Returns the selected file, if there is one.
 514:    *
 515:    * @return The selected file (possibly <code>null</code>).
 516:    * 
 517:    * @see #setSelectedFile(File)
 518:    */
 519:   public File getSelectedFile()
 520:   {
 521:     return selectedFile;
 522:   }
 523: 
 524:   /**
 525:    * Sets the selected file and sends a {@link PropertyChangeEvent} to all
 526:    * registered listeners.  The property name is 
 527:    * {@link #SELECTED_FILE_CHANGED_PROPERTY}.
 528:    *
 529:    * @param file  the file (<code>null</code> permitted).
 530:    */
 531:   public void setSelectedFile(File file)
 532:   {
 533:     if (selectedFile == null || !selectedFile.equals(file))
 534:       {
 535:     File old = selectedFile;
 536:     selectedFile = file;
 537:     firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, old, selectedFile);
 538:       }
 539:   }
 540: 
 541:   /**
 542:    * Returns the selected file or files in an array.  If no files are selected,
 543:    * an empty array is returned.
 544:    *
 545:    * @return An array of the selected files (possibly empty).
 546:    */
 547:   public File[] getSelectedFiles()
 548:   {
 549:     if (selectedFiles != null)
 550:       return selectedFiles;
 551:     if (selectedFile != null)
 552:       return new File[] { selectedFile };
 553:     return new File[0];
 554:   }
 555: 
 556:   /**
 557:    * Sets the selected files and sends a {@link PropertyChangeEvent} (with the 
 558:    * name {@link #SELECTED_FILES_CHANGED_PROPERTY}) to all registered 
 559:    * listeners.  
 560:    *
 561:    * @param selectedFiles  the selected files (<code>null</code> permitted).
 562:    */
 563:   public void setSelectedFiles(File[] selectedFiles)
 564:   {
 565:     if (selectedFiles == null)
 566:       selectedFiles = new File[0];
 567:     if (selectedFiles.length > 0)
 568:       setSelectedFile(selectedFiles[0]);
 569:     else
 570:       setSelectedFile(null);
 571:     if (this.selectedFiles != selectedFiles)
 572:       {
 573:     File[] old = this.selectedFiles;
 574:     this.selectedFiles = selectedFiles;
 575:     firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, old, selectedFiles);
 576:       }
 577: 
 578:   }
 579: 
 580:   /**
 581:    * Returns the current directory.
 582:    *
 583:    * @return The current directory.
 584:    */
 585:   public File getCurrentDirectory()
 586:   {
 587:     return currentDir;
 588:   }
 589: 
 590:   /**
 591:    * Sets the current directory and fires a {@link PropertyChangeEvent} (with 
 592:    * the property name {@link #DIRECTORY_CHANGED_PROPERTY}) to all registered 
 593:    * listeners.  If <code>dir</code> is <code>null</code>, the current 
 594:    * directory is set to the default directory returned by the file system
 595:    * view.
 596:    *
 597:    * @param dir  the new directory (<code>null</code> permitted).
 598:    * 
 599:    * @see FileSystemView#getDefaultDirectory()
 600:    */
 601:   public void setCurrentDirectory(File dir)
 602:   {
 603:     if (currentDir != dir || dir == null)
 604:       {
 605:     if (dir == null)
 606:       dir = fsv.getDefaultDirectory();
 607: 
 608:     File old = currentDir;
 609:     currentDir = dir;
 610:     firePropertyChange(DIRECTORY_CHANGED_PROPERTY, old, currentDir);
 611:       }
 612:   }
 613: 
 614:   /**
 615:    * Called by the UI delegate when the parent directory is changed.
 616:    */
 617:   public void changeToParentDirectory()
 618:   {
 619:     setCurrentDirectory(fsv.getParentDirectory(currentDir));
 620:   }
 621: 
 622:   /**
 623:    * Rescans the current directory (this is handled by the UI delegate).
 624:    */
 625:   public void rescanCurrentDirectory()
 626:   {
 627:     getUI().rescanCurrentDirectory(this);
 628:   }
 629: 
 630:   /**
 631:    * Ensures the the specified file is visible (this is handled by the 
 632:    * UI delegate).
 633:    *
 634:    * @param f  the file.
 635:    */
 636:   public void ensureFileIsVisible(File f)
 637:   {
 638:     getUI().ensureFileIsVisible(this, f);
 639:   }
 640: 
 641:   /**
 642:    * Displays the file chooser in a modal dialog using the 
 643:    * {@link #OPEN_DIALOG} type.
 644:    *
 645:    * @param parent  the parent component.
 646:    *
 647:    * @return A return value indicating how the dialog was closed (one of 
 648:    *         {@link #APPROVE_OPTION}, {@link #CANCEL_OPTION} and 
 649:    *         {@link #ERROR_OPTION}).
 650:    *
 651:    * @throws HeadlessException DOCUMENT ME!
 652:    */
 653:   public int showOpenDialog(Component parent) throws HeadlessException
 654:   {
 655:     JDialog d = createDialog(parent);
 656: 
 657:     // FIXME: Remove when we get ancestor property
 658:     d.setTitle("Open");
 659:     setDialogType(OPEN_DIALOG);
 660: 
 661:     retval = ERROR_OPTION;
 662: 
 663:     d.pack();
 664:     d.show();
 665:     return retval;
 666:   }
 667: 
 668:   /**
 669:    * Displays the file chooser in a modal dialog using the 
 670:    * {@link #SAVE_DIALOG} type.
 671:    *
 672:    * @param parent  the parent component.
 673:    *
 674:    * @return A return value indicating how the dialog was closed (one of 
 675:    *         {@link #APPROVE_OPTION}, {@link #CANCEL_OPTION} and 
 676:    *         {@link #ERROR_OPTION}).
 677:    *
 678:    * @throws HeadlessException DOCUMENT ME!
 679:    */
 680:   public int showSaveDialog(Component parent) throws HeadlessException
 681:   {
 682:     JDialog d = createDialog(parent);
 683:     setDialogType(SAVE_DIALOG);
 684: 
 685:     retval = ERROR_OPTION;
 686: 
 687:     d.pack();
 688:     d.show();
 689:     return retval;
 690:   }
 691: 
 692:   /**
 693:    * Displays the file chooser in a modal dialog using the 
 694:    * {@link #CUSTOM_DIALOG} type.
 695:    *
 696:    * @param parent  the parent component.
 697:    *
 698:    * @return A return value indicating how the dialog was closed (one of 
 699:    *         {@link #APPROVE_OPTION}, {@link #CANCEL_OPTION} and 
 700:    *         {@link #ERROR_OPTION}).
 701:    *
 702:    * @throws HeadlessException DOCUMENT ME!
 703:    */
 704:   public int showDialog(Component parent, String approveButtonText)
 705:                  throws HeadlessException
 706:   {
 707:     JDialog d = createDialog(parent);
 708:     setApproveButtonText(approveButtonText);
 709:     setDialogType(CUSTOM_DIALOG);
 710: 
 711:     retval = ERROR_OPTION;
 712: 
 713:     d.pack();
 714:     d.show();
 715:     return retval;
 716:   }
 717: 
 718:   /**
 719:    * Creates a modal dialog in which to display the file chooser.
 720:    *
 721:    * @param parent  the parent component.
 722:    *
 723:    * @return The dialog.
 724:    *
 725:    * @throws HeadlessException DOCUMENT ME!
 726:    */
 727:   protected JDialog createDialog(Component parent) throws HeadlessException
 728:   {
 729:     Frame toUse = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, parent);
 730:     if (toUse == null)
 731:       toUse = (Frame) SwingUtilities.getOwnerFrame(null);
 732: 
 733:     JDialog dialog = new JDialog(toUse);
 734:     setSelectedFile(null);
 735:     dialog.getContentPane().add(this);
 736:     dialog.setModal(true);
 737:     dialog.invalidate();
 738:     dialog.repaint();
 739: 
 740:     return dialog;
 741:   }
 742: 
 743:   /**
 744:    * Returns the flag that controls whether or not the control buttons are
 745:    * shown on the file chooser.
 746:    *
 747:    * @return A boolean.
 748:    * 
 749:    * @see #setControlButtonsAreShown(boolean)
 750:    */
 751:   public boolean getControlButtonsAreShown()
 752:   {
 753:     return controlButtonsShown;
 754:   }
 755: 
 756:   /**
 757:    * Sets the flag that controls whether or not the control buttons are
 758:    * shown and, if it changes, sends a {@link PropertyChangeEvent} (with the
 759:    * property name {@link #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY}) to
 760:    * all registered listeners.
 761:    *
 762:    * @param b  the new value for the flag.
 763:    */
 764:   public void setControlButtonsAreShown(boolean b)
 765:   {
 766:     if (controlButtonsShown != b)
 767:       {
 768:     controlButtonsShown = b;
 769:     firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY,
 770:                        ! controlButtonsShown, controlButtonsShown);
 771:       }
 772:   }
 773: 
 774:   /**
 775:    * Returns the type of file chooser.
 776:    *
 777:    * @return {@link #OPEN_DIALOG}, {@link #SAVE_DIALOG} or 
 778:    * {@link #CUSTOM_DIALOG}.
 779:    * 
 780:    * @see #setDialogType(int)
 781:    */
 782:   public int getDialogType()
 783:   {
 784:     return dialogType;
 785:   }
 786: 
 787:   /**
 788:    * Sets the dialog type and fires a {@link PropertyChangeEvent} (with the
 789:    * property name {@link #DIALOG_TYPE_CHANGED_PROPERTY}) to all 
 790:    * registered listeners.
 791:    *
 792:    * @param dialogType  the dialog type (one of: {@link #OPEN_DIALOG},
 793:    * {@link #SAVE_DIALOG}, {@link #CUSTOM_DIALOG}).
 794:    * 
 795:    * @throws IllegalArgumentException if <code>dialogType</code> is not valid.
 796:    */
 797:   public void setDialogType(int dialogType)
 798:   {
 799:     if (dialogType != OPEN_DIALOG && dialogType != SAVE_DIALOG
 800:         && dialogType != CUSTOM_DIALOG)
 801:       throw new IllegalArgumentException("Choose allowable dialogType.");
 802: 
 803:     if (this.dialogType != dialogType)
 804:       {
 805:     int old = this.dialogType;
 806:     this.dialogType = dialogType;
 807:     firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, old, this.dialogType);
 808:       }
 809:   }
 810: 
 811:   /**
 812:    * Sets the dialog title and sends a {@link PropertyChangeEvent} (with the 
 813:    * property name {@link #DIALOG_TITLE_CHANGED_PROPERTY}) to all 
 814:    * registered listeners.
 815:    *
 816:    * @param dialogTitle  the dialog title (<code>null</code> permitted).
 817:    * 
 818:    * @see #getDialogTitle()
 819:    */
 820:   public void setDialogTitle(String dialogTitle)
 821:   {
 822:     if (this.dialogTitle != dialogTitle)
 823:       {
 824:     String old = this.dialogTitle;
 825:     this.dialogTitle = dialogTitle;
 826:     firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, old, this.dialogTitle);
 827:       }
 828:   }
 829: 
 830:   /**
 831:    * Returns the dialog title.
 832:    *
 833:    * @return The dialog title (possibly <code>null</code>).
 834:    * 
 835:    * @see #setDialogTitle(String)
 836:    */
 837:   public String getDialogTitle()
 838:   {
 839:     return dialogTitle;
 840:   }
 841: 
 842:   /**
 843:    * Sets the tool tip text for the approve button and sends a 
 844:    * {@link PropertyChangeEvent} (with the property name
 845:    * {@link #APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY}) to all 
 846:    * registered listeners.
 847:    *
 848:    * @param toolTipText  the text.
 849:    */
 850:   public void setApproveButtonToolTipText(String toolTipText)
 851:   {
 852:     if (approveButtonToolTipText != toolTipText)
 853:       {
 854:     String oldText = approveButtonToolTipText;
 855:     approveButtonToolTipText = toolTipText;
 856:     firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY,
 857:                        oldText, approveButtonToolTipText);
 858:       }
 859:   }
 860: 
 861:   /**
 862:    * Returns the tool tip text for the approve button.
 863:    *
 864:    * @return The tool tip text for the approve button.
 865:    * 
 866:    * @see #setApproveButtonToolTipText(String)
 867:    */
 868:   public String getApproveButtonToolTipText()
 869:   {
 870:     return approveButtonToolTipText;
 871:   }
 872: 
 873:   /**
 874:    * Returns the approve button mnemonic, or zero if no mnemonic has been set.
 875:    *
 876:    * @return The approve button mnemonic.
 877:    * 
 878:    * @see #setApproveButtonMnemonic(int)
 879:    */
 880:   public int getApproveButtonMnemonic()
 881:   {
 882:     return approveButtonMnemonic;
 883:   }
 884: 
 885:   /**
 886:    * Sets the mnemonic for the approve button and sends a 
 887:    * {@link PropertyChangeEvent} (with the property name 
 888:    * {@link #APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY}) to all registered 
 889:    * listeners.
 890:    *
 891:    * @param mnemonic  the mnemonic.
 892:    * 
 893:    * @see #setApproveButtonMnemonic(char)
 894:    */
 895:   public void setApproveButtonMnemonic(int mnemonic)
 896:   {
 897:     if (approveButtonMnemonic != mnemonic)
 898:       {
 899:     int oldMnemonic = approveButtonMnemonic;
 900:     approveButtonMnemonic = mnemonic;
 901:     firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY,
 902:                        oldMnemonic, approveButtonMnemonic);
 903:       }
 904:   }
 905: 
 906:   /**
 907:    * Sets the mnemonic for the approve button and sends a 
 908:    * {@link PropertyChangeEvent} (with the property name 
 909:    * {@link #APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY}) to all registered 
 910:    * listeners.
 911:    *
 912:    * @param mnemonic  the mnemonic.
 913:    * 
 914:    * @see #setApproveButtonMnemonic(int)
 915:    */
 916:   public void setApproveButtonMnemonic(char mnemonic)
 917:   {
 918:     setApproveButtonMnemonic((int) Character.toUpperCase(mnemonic));
 919:   }
 920: 
 921:   /**
 922:    * Sets the approve button text and fires a {@link PropertyChangeEvent} 
 923:    * (with the property name {@link #APPROVE_BUTTON_TEXT_CHANGED_PROPERTY}) to 
 924:    * all registered listeners.
 925:    *
 926:    * @param approveButtonText  the text (<code>null</code> permitted).
 927:    * 
 928:    * @see #getApproveButtonText()
 929:    */
 930:   public void setApproveButtonText(String approveButtonText)
 931:   {
 932:     if (this.approveButtonText != approveButtonText)
 933:       {
 934:     String oldText = this.approveButtonText;
 935:     this.approveButtonText = approveButtonText;
 936:     firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldText,
 937:                        this.approveButtonText);
 938:       }
 939:   }
 940: 
 941:   /**
 942:    * Returns the approve button text.
 943:    *
 944:    * @return The approve button text (possibly <code>null</code>).
 945:    * 
 946:    * @see #setApproveButtonText(String)
 947:    */
 948:   public String getApproveButtonText()
 949:   {
 950:     return approveButtonText;
 951:   }
 952: 
 953:   /**
 954:    * Returns the available file filters for this file chooser.
 955:    *
 956:    * @return The available file filters.
 957:    */
 958:   public FileFilter[] getChoosableFileFilters()
 959:   {
 960:     return (FileFilter[]) choosableFilters.toArray(new FileFilter[choosableFilters.size()]);
 961:   }
 962: 
 963:   /**
 964:    * Adds a file filter to the list of available filters and sends a 
 965:    * {@link PropertyChangeEvent} (with the property name 
 966:    * {@link #CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY}) to all registered 
 967:    * listeners.
 968:    *
 969:    * @param filter  the filter (<code>null</code> permitted).
 970:    */
 971:   public void addChoosableFileFilter(FileFilter filter)
 972:   {
 973:     if (filter != null)
 974:       {
 975:         FileFilter[] old = getChoosableFileFilters();
 976:         choosableFilters.add(filter);
 977:         FileFilter[] newFilters = getChoosableFileFilters();
 978:         firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, old, 
 979:               newFilters);
 980:       }
 981:     setFileFilter(filter);
 982:   }
 983: 
 984:   /**
 985:    * Removes a file filter from the list of available filters and sends a 
 986:    * {@link PropertyChangeEvent} (with the property name 
 987:    * {@link #CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY}) to all registered 
 988:    * listeners.
 989:    *
 990:    * @param f  the file filter.
 991:    *
 992:    * @return <code>true</code> if the filter was removed and 
 993:    *         <code>false</code> otherwise.
 994:    */
 995:   public boolean removeChoosableFileFilter(FileFilter f)
 996:   {
 997:     if (f == currentFilter)
 998:       setFileFilter(null);
 999:     FileFilter[] old = getChoosableFileFilters();
1000:     if (! choosableFilters.remove(f))
1001:       return false;
1002:     FileFilter[] newFilters = getChoosableFileFilters();
1003:     firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, old, newFilters);
1004:     return true;
1005:   }
1006: 
1007:   /**
1008:    * Clears the list of choosable file filters and installs the 'accept all'
1009:    * filter from the UI delegate.
1010:    */
1011:   public void resetChoosableFileFilters()
1012:   {
1013:     choosableFilters.clear();
1014:     choosableFilters.add(getUI().getAcceptAllFileFilter(this));
1015:     setFileFilter((FileFilter) choosableFilters.get(0));
1016:   }
1017: 
1018:   /**
1019:    * Returns the 'accept all' file filter from the UI delegate.
1020:    *
1021:    * @return The 'accept all' file filter.
1022:    */
1023:   public FileFilter getAcceptAllFileFilter()
1024:   {
1025:     return getUI().getAcceptAllFileFilter(this);
1026:   }
1027: 
1028:   /**
1029:    * Returns the flag that controls whether or not the 'accept all' file 
1030:    * filter is included in the list of filters.
1031:    *
1032:    * @return A boolean.
1033:    * 
1034:    * @see #setAcceptAllFileFilterUsed(boolean)
1035:    */
1036:   public boolean isAcceptAllFileFilterUsed()
1037:   {
1038:     return isAcceptAll;
1039:   }
1040: 
1041:   /**
1042:    * Sets the flag that controls whether or not the 'accept all' file filter
1043:    * is included in the list of filters, and sends a 
1044:    * {@link PropertyChangeEvent} (with the property name 
1045:    * {@link #ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY}) to all registered 
1046:    * listeners.
1047:    *
1048:    * @param b  the new value of the flag.
1049:    */
1050:   public void setAcceptAllFileFilterUsed(boolean b)
1051:   {
1052:     if (isAcceptAll != b)
1053:       {
1054:     isAcceptAll = b;
1055:         if (b)
1056:           addChoosableFileFilter(getAcceptAllFileFilter());
1057:         else 
1058:           removeChoosableFileFilter(getAcceptAllFileFilter());
1059:     firePropertyChange(ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY,
1060:                        ! isAcceptAll, isAcceptAll);
1061:       }
1062:   }
1063: 
1064:   /**
1065:    * Returns the accessory component for the file chooser.  The default
1066:    * value is <code>null</code>.
1067:    *
1068:    * @return The accessory component (possibly <code>null</code>).
1069:    * 
1070:    * @see #setAccessory(JComponent)
1071:    */
1072:   public JComponent getAccessory()
1073:   {
1074:     return accessory;
1075:   }
1076: 
1077:   /**
1078:    * Sets the accessory component for the file chooser and sends a 
1079:    * {@link PropertyChangeEvent} to all registered listeners.  The property
1080:    * name is {@link #ACCESSORY_CHANGED_PROPERTY}.
1081:    *
1082:    * @param newAccessory  the accessory component.
1083:    */
1084:   public void setAccessory(JComponent newAccessory)
1085:   {
1086:     if (accessory != newAccessory)
1087:       {
1088:     JComponent old = accessory;
1089:     accessory = newAccessory;
1090:     firePropertyChange(ACCESSORY_CHANGED_PROPERTY, old, accessory);
1091:       }
1092:   }
1093: 
1094:   /**
1095:    * Sets the file selection mode and sends a {@link PropertyChangeEvent}
1096:    * to all registered listeners.  The property name is 
1097:    * {@link #FILE_SELECTION_MODE_CHANGED_PROPERTY}.
1098:    *
1099:    * @param mode  the mode ({@link #FILES_ONLY}, {@link #DIRECTORIES_ONLY} or
1100:    *              {@link #FILES_AND_DIRECTORIES}).
1101:    * 
1102:    * @throws IllegalArgumentException if the mode is invalid.
1103:    */
1104:   public void setFileSelectionMode(int mode)
1105:   {
1106:     if (mode != FILES_ONLY && mode != DIRECTORIES_ONLY
1107:         && mode != FILES_AND_DIRECTORIES)
1108:       throw new IllegalArgumentException("Choose a correct file selection mode.");
1109:     if (fileSelectionMode != mode)
1110:       {
1111:     int old = fileSelectionMode;
1112:     fileSelectionMode = mode;
1113:     firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, old,
1114:                        fileSelectionMode);
1115:       }
1116:   }
1117: 
1118:   /**
1119:    * Returns the file selection mode, one of: {@link #FILES_ONLY}, 
1120:    * {@link #DIRECTORIES_ONLY} or {@link #FILES_AND_DIRECTORIES}.  The
1121:    * default is {@link #FILES_ONLY}.
1122:    *
1123:    * @return The file selection mode.
1124:    * 
1125:    * @see #setFileSelectionMode(int)
1126:    */
1127:   public int getFileSelectionMode()
1128:   {
1129:     return fileSelectionMode;
1130:   }
1131: 
1132:   /**
1133:    * Returns <code>true</code> if file selection is enabled, and 
1134:    * <code>false</code> otherwise.  File selection is enabled when the
1135:    * file selection mode is {@link #FILES_ONLY} or 
1136:    * {@link #FILES_AND_DIRECTORIES}.
1137:    *
1138:    * @return <code>true</code> if file selection is enabled.
1139:    * 
1140:    * @see #getFileSelectionMode()
1141:    */
1142:   public boolean isFileSelectionEnabled()
1143:   {
1144:     return (fileSelectionMode == FILES_ONLY
1145:            || fileSelectionMode == FILES_AND_DIRECTORIES);
1146:   }
1147: 
1148:   /**
1149:    * Returns <code>true</code> if directory selection is enabled, and 
1150:    * <code>false</code> otherwise.  Directory selection is enabled when the
1151:    * file selection mode is {@link #DIRECTORIES_ONLY} or 
1152:    * {@link #FILES_AND_DIRECTORIES}.
1153:    *
1154:    * @return <code>true</code> if file selection is enabled.
1155:    * 
1156:    * @see #getFileSelectionMode()
1157:    */
1158:   public boolean isDirectorySelectionEnabled()
1159:   {
1160:     return (fileSelectionMode == DIRECTORIES_ONLY
1161:            || fileSelectionMode == FILES_AND_DIRECTORIES);
1162:   }
1163: 
1164:   /**
1165:    * Sets the flag that controls whether multiple selections are allowed in 
1166:    * this filechooser and sends a {@link PropertyChangeEvent} (with the 
1167:    * property name {@link #MULTI_SELECTION_ENABLED_CHANGED_PROPERTY}) to all 
1168:    * registered listeners.
1169:    *
1170:    * @param b  the new value of the flag.
1171:    */
1172:   public void setMultiSelectionEnabled(boolean b)
1173:   {
1174:     if (multiSelection != b)
1175:       {
1176:     multiSelection = b;
1177:     firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY,
1178:                        ! multiSelection, multiSelection);
1179:       }
1180:   }
1181: 
1182:   /**
1183:    * Returns <code>true</code> if multiple selections are allowed within this
1184:    * file chooser, and <code>false</code> otherwise.
1185:    *
1186:    * @return A boolean.
1187:    * 
1188:    * @see #setMultiSelectionEnabled(boolean)
1189:    */
1190:   public boolean isMultiSelectionEnabled()
1191:   {
1192:     return multiSelection;
1193:   }
1194: 
1195:   /**
1196:    * Returns <code>true</code> if hidden files are to be hidden, and 
1197:    * <code>false</code> otherwise.
1198:    *
1199:    * @return A boolean.
1200:    * 
1201:    * @see #setFileHidingEnabled(boolean)
1202:    */
1203:   public boolean isFileHidingEnabled()
1204:   {
1205:     return fileHiding;
1206:   }
1207: 
1208:   /**
1209:    * Sets the flag that controls whether or not hidden files are displayed,
1210:    * and sends a {@link PropertyChangeEvent} (with the property name
1211:    * {@link #FILE_HIDING_CHANGED_PROPERTY}) to all registered listeners.
1212:    *
1213:    * @param b  the new value of the flag.
1214:    */
1215:   public void setFileHidingEnabled(boolean b)
1216:   {
1217:     if (fileHiding != b)
1218:       {
1219:     fileHiding = b;
1220:     firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, ! fileHiding,
1221:                        fileHiding);
1222:       }
1223:   }
1224: 
1225:   /**
1226:    * Sets the file filter and sends a {@link PropertyChangeEvent} (with the
1227:    * property name {@link #FILE_FILTER_CHANGED_PROPERTY}) to all registered 
1228:    * listeners.
1229:    *
1230:    * @param filter  the filter (<code>null</code> permitted).
1231:    */
1232:   public void setFileFilter(FileFilter filter)
1233:   {
1234:     if (currentFilter != filter)
1235:       {
1236:         if (filter != null && !choosableFilters.contains(filter))
1237:           addChoosableFileFilter(filter);
1238:         FileFilter old = currentFilter;
1239:         currentFilter = filter;
1240:         firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, old, currentFilter);
1241:       }
1242:   }
1243: 
1244:   /**
1245:    * Returns the file filter.
1246:    *
1247:    * @return The file filter.
1248:    * 
1249:    * @see #setFileFilter(FileFilter)
1250:    */
1251:   public FileFilter getFileFilter()
1252:   {
1253:     return currentFilter;
1254:   }
1255: 
1256:   /**
1257:    * Sets a custom {@link FileView} for the file chooser and sends a 
1258:    * {@link PropertyChangeEvent} to all registered listeners.  The property
1259:    * name is {@link #FILE_VIEW_CHANGED_PROPERTY}.
1260:    *
1261:    * @param fileView  the file view (<code>null</code> permitted).
1262:    *
1263:    * @see #getFileView()
1264:    */
1265:   public void setFileView(FileView fileView)
1266:   {
1267:     if (fv != fileView)
1268:       {
1269:     FileView old = fv;
1270:     fv = fileView;
1271:     firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, old, fv);
1272:       }
1273:   }
1274: 
1275:   /**
1276:    * Returns the custom {@link FileView} for the file chooser.
1277:    *
1278:    * @return The file view (possibly <code>null</code>).
1279:    */
1280:   public FileView getFileView()
1281:   {
1282:     return fv;
1283:   }
1284: 
1285:   /**
1286:    * Returns the name of the file, generated by the current (or default)
1287:    * {@link FileView}.
1288:    *
1289:    * @param f  the file.
1290:    *
1291:    * @return The file name.
1292:    */
1293:   public String getName(File f)
1294:   {
1295:     String name = null;
1296:     if (fv != null)
1297:       name = fv.getName(f);
1298:     if (name == null)
1299:       name = getUI().getFileView(this).getName(f);
1300:     return name;
1301:   }
1302: 
1303:   /**
1304:    * Returns the description of the file, generated by the current (or default)
1305:    * {@link FileView}.
1306:    *
1307:    * @param f  the file.
1308:    *
1309:    * @return The file description.
1310:    */
1311:   public String getDescription(File f)
1312:   {
1313:     String result = null;
1314:     if (fv != null)
1315:       result = fv.getDescription(f);
1316:     if (result == null)
1317:       result = getUI().getFileView(this).getDescription(f);
1318:     return result;
1319:   }
1320: 
1321:   /**
1322:    * Returns the type description for the file, generated by the current (or 
1323:    * default) {@link FileView}.
1324:    *
1325:    * @param f  the file.
1326:    *
1327:    * @return The file type description.
1328:    */
1329:   public String getTypeDescription(File f)
1330:   {
1331:     String result = null;
1332:     if (fv != null)
1333:       result = getFileView().getTypeDescription(f);
1334:     if (result == null)
1335:       result = getUI().getFileView(this).getTypeDescription(f);
1336:     return result;
1337:   }
1338: 
1339:   /**
1340:    * Returns the icon provided by the current (or default) {@link FileView}.
1341:    *
1342:    * @param f  the file.
1343:    *
1344:    * @return An icon representing the file.
1345:    */
1346:   public Icon getIcon(File f)
1347:   {
1348:     Icon result = null;
1349:     if (fv != null)
1350:       result = fv.getIcon(f);
1351:     if (result == null)
1352:       result = getUI().getFileView(this).getIcon(f);
1353:     return result;
1354:   }
1355: 
1356:   /**
1357:    * Returns <code>true</code> if the file is traversable, and 
1358:    * <code>false</code> otherwise.
1359:    *
1360:    * @param f  the file or directory.
1361:    *
1362:    * @return A boolean.
1363:    */
1364:   public boolean isTraversable(File f)
1365:   {
1366:     return getFileSystemView().isTraversable(f).booleanValue();
1367:   }
1368: 
1369:   /**
1370:    * Returns <code>true</code> if the file is accepted by the current
1371:    * file filter.
1372:    *
1373:    * @param f  the file.
1374:    *
1375:    * @return A boolean.
1376:    */
1377:   public boolean accept(File f)
1378:   {
1379:     if (f == null)
1380:       return true;
1381:     FileFilter ff = getFileFilter();
1382:     if (ff != null) 
1383:       return ff.accept(f);
1384:     else
1385:       return true;
1386:   }
1387: 
1388:   /**
1389:    * Sets the file system view for the file chooser and sends a 
1390:    * {@link PropertyChangeEvent} to all registered listeners.
1391:    *
1392:    * @param fsv  the file system view.
1393:    */
1394:   public void setFileSystemView(FileSystemView fsv)
1395:   {
1396:     if (this.fsv != fsv)
1397:       {
1398:     FileSystemView old = this.fsv;
1399:     this.fsv = fsv;
1400:     firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, old, this.fsv);
1401:       }
1402:   }
1403: 
1404:   /**
1405:    * Returns the file system view being used by this file chooser.
1406:    *
1407:    * @return The file system view.
1408:    * 
1409:    * @see #setFileSystemView(FileSystemView)
1410:    */
1411:   public FileSystemView getFileSystemView()
1412:   {
1413:     return fsv;
1414:   }
1415: 
1416:   /**
1417:    * Approves the selection.  An {@link ActionEvent} is sent to all registered
1418:    * listeners.
1419:    */
1420:   public void approveSelection()
1421:   {
1422:     retval = APPROVE_OPTION;
1423:     fireActionPerformed(APPROVE_SELECTION);
1424:   }
1425: 
1426:   /**
1427:    * Cancels the selection. An {@link ActionEvent} is sent to all registered
1428:    * listeners.
1429:    */
1430:   public void cancelSelection()
1431:   {
1432:     retval = CANCEL_OPTION;
1433:     fireActionPerformed(CANCEL_SELECTION);
1434:   }
1435: 
1436:   /**
1437:    * Adds an {@link ActionListener} to the file chooser.
1438:    *
1439:    * @param l  the listener.
1440:    */
1441:   public void addActionListener(ActionListener l)
1442:   {
1443:     listenerList.add(ActionListener.class, l);
1444:   }
1445: 
1446:   /**
1447:    * Removes an {@link ActionListener} from this file chooser.
1448:    *
1449:    * @param l  the listener.
1450:    */
1451:   public void removeActionListener(ActionListener l)
1452:   {
1453:     try
1454:       {
1455:     listenerList.remove(ActionListener.class, l);
1456:       }
1457:     catch (IllegalArgumentException e)
1458:       {
1459:     e.printStackTrace();
1460:       }
1461:   }
1462: 
1463:   /**
1464:    * Returns the action listeners registered with this file chooser.
1465:    *
1466:    * @return An array of listeners.
1467:    */
1468:   public ActionListener[] getActionListeners()
1469:   {
1470:     return (ActionListener[]) getListeners(ActionListener.class);
1471:   }
1472: 
1473:   /**
1474:    * Sends an @link {ActionEvent} to all registered listeners.
1475:    *
1476:    * @param command  the action command.
1477:    */
1478:   protected void fireActionPerformed(String command)
1479:   {
1480:     ActionListener[] list = getActionListeners();
1481:     ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
1482:                                         command);
1483: 
1484:     for (int i = 0; i < list.length; i++)
1485:       list[i].actionPerformed(event);
1486:   }
1487: 
1488:   /**
1489:    * Installs the UI delegate for the current look and feel.
1490:    */
1491:   public void updateUI()
1492:   {
1493:     setUI((FileChooserUI) UIManager.getUI(this));
1494:   }
1495: 
1496:   /**
1497:    * Returns the UI delegate class identifier.
1498:    *
1499:    * @return <code>FileChooserUI</code>.
1500:    */
1501:   public String getUIClassID()
1502:   {
1503:     return "FileChooserUI";
1504:   }
1505: 
1506:   /**
1507:    * Returns the UI delegate for the component.
1508:    *
1509:    * @return The UI delegate.
1510:    */
1511:   public FileChooserUI getUI()
1512:   {
1513:     return (FileChooserUI) ui;
1514:   }
1515: 
1516:   /**
1517:    * DOCUMENT ME!
1518:    *
1519:    * @return DOCUMENT ME!
1520:    */
1521:   protected String paramString()
1522:   {
1523:     return "JFileChooser";
1524:   }
1525: 
1526:   /**
1527:    * Returns the accessible context.
1528:    *
1529:    * @return The accessible context.
1530:    */
1531:   public AccessibleContext getAccessibleContext()
1532:   {
1533:     if (accessibleContext == null)
1534:       accessibleContext = new AccessibleJFileChooser();
1535:     return accessibleContext;
1536:   }
1537: 
1538:   /**
1539:    * Accessibility support for JFileChooser
1540:    */
1541:   protected class AccessibleJFileChooser 
1542:     extends JComponent.AccessibleJComponent
1543:   {
1544:     protected AccessibleJFileChooser()
1545:     {
1546:       // Nothing to do here.
1547:     }
1548:     
1549:     public AccessibleRole getAccessibleRole()
1550:     {
1551:       return AccessibleRole.FILE_CHOOSER;
1552:     }
1553:   }
1554: }