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