Source for javax.swing.JFileChooser

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