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