Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.swing;
   27   
   28   import javax.swing.event;
   29   import javax.swing.filechooser;
   30   import javax.swing.plaf.FileChooserUI;
   31   
   32   import javax.accessibility;
   33   
   34   import java.io.File;
   35   import java.io.ObjectOutputStream;
   36   import java.io.IOException;
   37   
   38   import java.util.Vector;
   39   import java.awt.AWTEvent;
   40   import java.awt.Component;
   41   import java.awt.Container;
   42   import java.awt.BorderLayout;
   43   import java.awt.Window;
   44   import java.awt.Dialog;
   45   import java.awt.Frame;
   46   import java.awt.GraphicsEnvironment;
   47   import java.awt.HeadlessException;
   48   import java.awt.EventQueue;
   49   import java.awt.Toolkit;
   50   import java.awt.event;
   51   import java.beans.PropertyChangeListener;
   52   import java.beans.PropertyChangeEvent;
   53   import java.lang.ref.WeakReference;
   54   
   55   /**
   56    * <code>JFileChooser</code> provides a simple mechanism for the user to
   57    * choose a file.
   58    * For information about using <code>JFileChooser</code>, see
   59    * <a
   60    href="http://java.sun.com/docs/books/tutorial/uiswing/components/filechooser.html">How to Use File Choosers</a>,
   61    * a section in <em>The Java Tutorial</em>.
   62    *
   63    * <p>
   64    *
   65    * The following code pops up a file chooser for the user's home directory that
   66    * sees only .jpg and .gif images:
   67    * <pre>
   68    *    JFileChooser chooser = new JFileChooser();
   69    *    FileNameExtensionFilter filter = new FileNameExtensionFilter(
   70    *        "JPG & GIF Images", "jpg", "gif");
   71    *    chooser.setFileFilter(filter);
   72    *    int returnVal = chooser.showOpenDialog(parent);
   73    *    if(returnVal == JFileChooser.APPROVE_OPTION) {
   74    *       System.out.println("You chose to open this file: " +
   75    *            chooser.getSelectedFile().getName());
   76    *    }
   77    * </pre>
   78    * <p>
   79    * <strong>Warning:</strong> Swing is not thread safe. For more
   80    * information see <a
   81    * href="package-summary.html#threading">Swing's Threading
   82    * Policy</a>.
   83    *
   84    * @beaninfo
   85    *   attribute: isContainer false
   86    * description: A component which allows for the interactive selection of a file.
   87    *
   88    * @author Jeff Dinkins
   89    *
   90    */
   91   public class JFileChooser extends JComponent implements Accessible {
   92   
   93       /**
   94        * @see #getUIClassID
   95        * @see #readObject
   96        */
   97       private static final String uiClassID = "FileChooserUI";
   98   
   99       // ************************
  100       // ***** Dialog Types *****
  101       // ************************
  102   
  103       /**
  104        * Type value indicating that the <code>JFileChooser</code> supports an
  105        * "Open" file operation.
  106        */
  107       public static final int OPEN_DIALOG = 0;
  108   
  109       /**
  110        * Type value indicating that the <code>JFileChooser</code> supports a
  111        * "Save" file operation.
  112        */
  113       public static final int SAVE_DIALOG = 1;
  114   
  115       /**
  116        * Type value indicating that the <code>JFileChooser</code> supports a
  117        * developer-specified file operation.
  118        */
  119       public static final int CUSTOM_DIALOG = 2;
  120   
  121   
  122       // ********************************
  123       // ***** Dialog Return Values *****
  124       // ********************************
  125   
  126       /**
  127        * Return value if cancel is chosen.
  128        */
  129       public static final int CANCEL_OPTION = 1;
  130   
  131       /**
  132        * Return value if approve (yes, ok) is chosen.
  133        */
  134       public static final int APPROVE_OPTION = 0;
  135   
  136       /**
  137        * Return value if an error occured.
  138        */
  139       public static final int ERROR_OPTION = -1;
  140   
  141   
  142       // **********************************
  143       // ***** JFileChooser properties *****
  144       // **********************************
  145   
  146   
  147       /** Instruction to display only files. */
  148       public static final int FILES_ONLY = 0;
  149   
  150       /** Instruction to display only directories. */
  151       public static final int DIRECTORIES_ONLY = 1;
  152   
  153       /** Instruction to display both files and directories. */
  154       public static final int FILES_AND_DIRECTORIES = 2;
  155   
  156       /** Instruction to cancel the current selection. */
  157       public static final String CANCEL_SELECTION = "CancelSelection";
  158   
  159       /**
  160        * Instruction to approve the current selection
  161        * (same as pressing yes or ok).
  162        */
  163       public static final String APPROVE_SELECTION = "ApproveSelection";
  164   
  165       /** Identifies change in the text on the approve (yes, ok) button. */
  166       public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty";
  167   
  168       /**
  169        * Identifies change in the tooltip text for the approve (yes, ok)
  170        * button.
  171        */
  172       public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty";
  173   
  174       /** Identifies change in the mnemonic for the approve (yes, ok) button. */
  175       public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = "ApproveButtonMnemonicChangedProperty";
  176   
  177       /** Instruction to display the control buttons. */
  178       public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY = "ControlButtonsAreShownChangedProperty";
  179   
  180       /** Identifies user's directory change. */
  181       public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
  182   
  183       /** Identifies change in user's single-file selection. */
  184       public static final String SELECTED_FILE_CHANGED_PROPERTY = "SelectedFileChangedProperty";
  185   
  186       /** Identifies change in user's multiple-file selection. */
  187       public static final String SELECTED_FILES_CHANGED_PROPERTY = "SelectedFilesChangedProperty";
  188   
  189       /** Enables multiple-file selections. */
  190       public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "MultiSelectionEnabledChangedProperty";
  191   
  192       /**
  193        * Says that a different object is being used to find available drives
  194        * on the system.
  195        */
  196       public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged";
  197   
  198       /**
  199        * Says that a different object is being used to retrieve file
  200        * information.
  201        */
  202       public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
  203   
  204       /** Identifies a change in the display-hidden-files property. */
  205       public static final String FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged";
  206   
  207       /** User changed the kind of files to display. */
  208       public static final String FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged";
  209   
  210       /**
  211        * Identifies a change in the kind of selection (single,
  212        * multiple, etc.).
  213        */
  214       public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged";
  215   
  216       /**
  217        * Says that a different accessory component is in use
  218        * (for example, to preview files).
  219        */
  220       public static final String ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty";
  221   
  222       /**
  223        * Identifies whether a the AcceptAllFileFilter is used or not.
  224        */
  225       public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = "acceptAllFileFilterUsedChanged";
  226   
  227       /** Identifies a change in the dialog title. */
  228       public static final String DIALOG_TITLE_CHANGED_PROPERTY = "DialogTitleChangedProperty";
  229   
  230       /**
  231        * Identifies a change in the type of files displayed (files only,
  232        * directories only, or both files and directories).
  233        */
  234       public static final String DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty";
  235   
  236       /**
  237        * Identifies a change in the list of predefined file filters
  238        * the user can choose from.
  239        */
  240       public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty";
  241   
  242       // ******************************
  243       // ***** instance variables *****
  244       // ******************************
  245   
  246       private String dialogTitle = null;
  247       private String approveButtonText = null;
  248       private String approveButtonToolTipText = null;
  249       private int approveButtonMnemonic = 0;
  250   
  251       private Vector filters = new Vector(5);
  252       private JDialog dialog = null;
  253       private int dialogType = OPEN_DIALOG;
  254       private int returnValue = ERROR_OPTION;
  255       private JComponent accessory = null;
  256   
  257       private FileView fileView = null;
  258   
  259       // uiFileView is not serialized, as it is initialized
  260       // by updateUI() after deserialization
  261       private transient FileView uiFileView = null;
  262   
  263       private boolean controlsShown = true;
  264   
  265       private boolean useFileHiding = true;
  266       private static final String SHOW_HIDDEN_PROP = "awt.file.showHiddenFiles";
  267   
  268       // Listens to changes in the native setting for showing hidden files.
  269       // The Listener is removed and the native setting is ignored if
  270       // setFileHidingEnabled() is ever called.
  271       private transient PropertyChangeListener showFilesListener = null;
  272   
  273       private int fileSelectionMode = FILES_ONLY;
  274   
  275       private boolean multiSelectionEnabled = false;
  276   
  277       private boolean useAcceptAllFileFilter = true;
  278   
  279       private boolean dragEnabled = false;
  280   
  281       private FileFilter fileFilter = null;
  282   
  283       private FileSystemView fileSystemView = null;
  284   
  285       private File currentDirectory = null;
  286       private File selectedFile = null;
  287       private File[] selectedFiles;
  288   
  289       // *************************************
  290       // ***** JFileChooser Constructors *****
  291       // *************************************
  292   
  293       /**
  294        * Constructs a <code>JFileChooser</code> pointing to the user's
  295        * default directory. This default depends on the operating system.
  296        * It is typically the "My Documents" folder on Windows, and the
  297        * user's home directory on Unix.
  298        */
  299       public JFileChooser() {
  300           this((File) null, (FileSystemView) null);
  301       }
  302   
  303       /**
  304        * Constructs a <code>JFileChooser</code> using the given path.
  305        * Passing in a <code>null</code>
  306        * string causes the file chooser to point to the user's default directory.
  307        * This default depends on the operating system. It is
  308        * typically the "My Documents" folder on Windows, and the user's
  309        * home directory on Unix.
  310        *
  311        * @param currentDirectoryPath  a <code>String</code> giving the path
  312        *                          to a file or directory
  313        */
  314       public JFileChooser(String currentDirectoryPath) {
  315           this(currentDirectoryPath, (FileSystemView) null);
  316       }
  317   
  318       /**
  319        * Constructs a <code>JFileChooser</code> using the given <code>File</code>
  320        * as the path. Passing in a <code>null</code> file
  321        * causes the file chooser to point to the user's default directory.
  322        * This default depends on the operating system. It is
  323        * typically the "My Documents" folder on Windows, and the user's
  324        * home directory on Unix.
  325        *
  326        * @param currentDirectory  a <code>File</code> object specifying
  327        *                          the path to a file or directory
  328        */
  329       public JFileChooser(File currentDirectory) {
  330           this(currentDirectory, (FileSystemView) null);
  331       }
  332   
  333       /**
  334        * Constructs a <code>JFileChooser</code> using the given
  335        * <code>FileSystemView</code>.
  336        */
  337       public JFileChooser(FileSystemView fsv) {
  338           this((File) null, fsv);
  339       }
  340   
  341   
  342       /**
  343        * Constructs a <code>JFileChooser</code> using the given current directory
  344        * and <code>FileSystemView</code>.
  345        */
  346       public JFileChooser(File currentDirectory, FileSystemView fsv) {
  347           setup(fsv);
  348           setCurrentDirectory(currentDirectory);
  349       }
  350   
  351       /**
  352        * Constructs a <code>JFileChooser</code> using the given current directory
  353        * path and <code>FileSystemView</code>.
  354        */
  355       public JFileChooser(String currentDirectoryPath, FileSystemView fsv) {
  356           setup(fsv);
  357           if(currentDirectoryPath == null) {
  358               setCurrentDirectory(null);
  359           } else {
  360               setCurrentDirectory(fileSystemView.createFileObject(currentDirectoryPath));
  361           }
  362       }
  363   
  364       /**
  365        * Performs common constructor initialization and setup.
  366        */
  367       protected void setup(FileSystemView view) {
  368           installShowFilesListener();
  369   
  370           if(view == null) {
  371               view = FileSystemView.getFileSystemView();
  372           }
  373           setFileSystemView(view);
  374           updateUI();
  375           if(isAcceptAllFileFilterUsed()) {
  376               setFileFilter(getAcceptAllFileFilter());
  377           }
  378           enableEvents(AWTEvent.MOUSE_EVENT_MASK);
  379       }
  380   
  381       private void installShowFilesListener() {
  382           // Track native setting for showing hidden files
  383           Toolkit tk = Toolkit.getDefaultToolkit();
  384           Object showHiddenProperty = tk.getDesktopProperty(SHOW_HIDDEN_PROP);
  385           if (showHiddenProperty instanceof Boolean) {
  386               useFileHiding = !((Boolean)showHiddenProperty).booleanValue();
  387               showFilesListener = new WeakPCL(this);
  388               tk.addPropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener);
  389           }
  390       }
  391   
  392       /**
  393        * Sets the <code>dragEnabled</code> property,
  394        * which must be <code>true</code> to enable
  395        * automatic drag handling (the first part of drag and drop)
  396        * on this component.
  397        * The <code>transferHandler</code> property needs to be set
  398        * to a non-<code>null</code> value for the drag to do
  399        * anything.  The default value of the <code>dragEnabled</code>
  400        * property
  401        * is <code>false</code>.
  402        *
  403        * <p>
  404        *
  405        * When automatic drag handling is enabled,
  406        * most look and feels begin a drag-and-drop operation
  407        * whenever the user presses the mouse button over an item
  408        * and then moves the mouse a few pixels.
  409        * Setting this property to <code>true</code>
  410        * can therefore have a subtle effect on
  411        * how selections behave.
  412        *
  413        * <p>
  414        *
  415        * Some look and feels might not support automatic drag and drop;
  416        * they will ignore this property.  You can work around such
  417        * look and feels by modifying the component
  418        * to directly call the <code>exportAsDrag</code> method of a
  419        * <code>TransferHandler</code>.
  420        *
  421        * @param b the value to set the <code>dragEnabled</code> property to
  422        * @exception HeadlessException if
  423        *            <code>b</code> is <code>true</code> and
  424        *            <code>GraphicsEnvironment.isHeadless()</code>
  425        *            returns <code>true</code>
  426        * @see java.awt.GraphicsEnvironment#isHeadless
  427        * @see #getDragEnabled
  428        * @see #setTransferHandler
  429        * @see TransferHandler
  430        * @since 1.4
  431        *
  432        * @beaninfo
  433        *  description: determines whether automatic drag handling is enabled
  434        *        bound: false
  435        */
  436       public void setDragEnabled(boolean b) {
  437           if (b && GraphicsEnvironment.isHeadless()) {
  438               throw new HeadlessException();
  439           }
  440           dragEnabled = b;
  441       }
  442   
  443       /**
  444        * Gets the value of the <code>dragEnabled</code> property.
  445        *
  446        * @return  the value of the <code>dragEnabled</code> property
  447        * @see #setDragEnabled
  448        * @since 1.4
  449        */
  450       public boolean getDragEnabled() {
  451           return dragEnabled;
  452       }
  453   
  454       // *****************************
  455       // ****** File Operations ******
  456       // *****************************
  457   
  458       /**
  459        * Returns the selected file. This can be set either by the
  460        * programmer via <code>setSelectedFile</code> or by a user action, such as
  461        * either typing the filename into the UI or selecting the
  462        * file from a list in the UI.
  463        *
  464        * @see #setSelectedFile
  465        * @return the selected file
  466        */
  467       public File getSelectedFile() {
  468           return selectedFile;
  469       }
  470   
  471       /**
  472        * Sets the selected file. If the file's parent directory is
  473        * not the current directory, changes the current directory
  474        * to be the file's parent directory.
  475        *
  476        * @beaninfo
  477        *   preferred: true
  478        *       bound: true
  479        *
  480        * @see #getSelectedFile
  481        *
  482        * @param file the selected file
  483        */
  484       public void setSelectedFile(File file) {
  485           File oldValue = selectedFile;
  486           selectedFile = file;
  487           if(selectedFile != null) {
  488               if (file.isAbsolute() && !getFileSystemView().isParent(getCurrentDirectory(), selectedFile)) {
  489                   setCurrentDirectory(selectedFile.getParentFile());
  490               }
  491               if (!isMultiSelectionEnabled() || selectedFiles == null || selectedFiles.length == 1) {
  492                   ensureFileIsVisible(selectedFile);
  493               }
  494           }
  495           firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, oldValue, selectedFile);
  496       }
  497   
  498       /**
  499        * Returns a list of selected files if the file chooser is
  500        * set to allow multiple selection.
  501        */
  502       public File[] getSelectedFiles() {
  503           if(selectedFiles == null) {
  504               return new File[0];
  505           } else {
  506               return (File[]) selectedFiles.clone();
  507           }
  508       }
  509   
  510       /**
  511        * Sets the list of selected files if the file chooser is
  512        * set to allow multiple selection.
  513        *
  514        * @beaninfo
  515        *       bound: true
  516        * description: The list of selected files if the chooser is in multiple selection mode.
  517        */
  518       public void setSelectedFiles(File[] selectedFiles) {
  519           File[] oldValue = this.selectedFiles;
  520           if (selectedFiles == null || selectedFiles.length == 0) {
  521               selectedFiles = null;
  522               this.selectedFiles = null;
  523               setSelectedFile(null);
  524           } else {
  525               this.selectedFiles = selectedFiles.clone();
  526               setSelectedFile(this.selectedFiles[0]);
  527           }
  528           firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, selectedFiles);
  529       }
  530   
  531       /**
  532        * Returns the current directory.
  533        *
  534        * @return the current directory
  535        * @see #setCurrentDirectory
  536        */
  537       public File getCurrentDirectory() {
  538           return currentDirectory;
  539       }
  540   
  541       /**
  542        * Sets the current directory. Passing in <code>null</code> sets the
  543        * file chooser to point to the user's default directory.
  544        * This default depends on the operating system. It is
  545        * typically the "My Documents" folder on Windows, and the user's
  546        * home directory on Unix.
  547        *
  548        * If the file passed in as <code>currentDirectory</code> is not a
  549        * directory, the parent of the file will be used as the currentDirectory.
  550        * If the parent is not traversable, then it will walk up the parent tree
  551        * until it finds a traversable directory, or hits the root of the
  552        * file system.
  553        *
  554        * @beaninfo
  555        *   preferred: true
  556        *       bound: true
  557        * description: The directory that the JFileChooser is showing files of.
  558        *
  559        * @param dir the current directory to point to
  560        * @see #getCurrentDirectory
  561        */
  562       public void setCurrentDirectory(File dir) {
  563           File oldValue = currentDirectory;
  564   
  565           if (dir != null && !dir.exists()) {
  566               dir = currentDirectory;
  567           }
  568           if (dir == null) {
  569               dir = getFileSystemView().getDefaultDirectory();
  570           }
  571           if (currentDirectory != null) {
  572               /* Verify the toString of object */
  573               if (this.currentDirectory.equals(dir)) {
  574                   return;
  575               }
  576           }
  577   
  578           File prev = null;
  579           while (!isTraversable(dir) && prev != dir) {
  580               prev = dir;
  581               dir = getFileSystemView().getParentDirectory(dir);
  582           }
  583           currentDirectory = dir;
  584   
  585           firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue, currentDirectory);
  586       }
  587   
  588       /**
  589        * Changes the directory to be set to the parent of the
  590        * current directory.
  591        *
  592        * @see #getCurrentDirectory
  593        */
  594       public void changeToParentDirectory() {
  595           selectedFile = null;
  596           File oldValue = getCurrentDirectory();
  597           setCurrentDirectory(getFileSystemView().getParentDirectory(oldValue));
  598       }
  599   
  600       /**
  601        * Tells the UI to rescan its files list from the current directory.
  602        */
  603       public void rescanCurrentDirectory() {
  604           getUI().rescanCurrentDirectory(this);
  605       }
  606   
  607       /**
  608        * Makes sure that the specified file is viewable, and
  609        * not hidden.
  610        *
  611        * @param f  a File object
  612        */
  613       public void ensureFileIsVisible(File f) {
  614           getUI().ensureFileIsVisible(this, f);
  615       }
  616   
  617       // **************************************
  618       // ***** JFileChooser Dialog methods *****
  619       // **************************************
  620   
  621       /**
  622        * Pops up an "Open File" file chooser dialog. Note that the
  623        * text that appears in the approve button is determined by
  624        * the L&F.
  625        *
  626        * @param    parent  the parent component of the dialog,
  627        *                  can be <code>null</code>;
  628        *                  see <code>showDialog</code> for details
  629        * @return   the return state of the file chooser on popdown:
  630        * <ul>
  631        * <li>JFileChooser.CANCEL_OPTION
  632        * <li>JFileChooser.APPROVE_OPTION
  633        * <li>JFileChooser.ERROR_OPTION if an error occurs or the
  634        *                  dialog is dismissed
  635        * </ul>
  636        * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  637        * returns true.
  638        * @see java.awt.GraphicsEnvironment#isHeadless
  639        * @see #showDialog
  640        */
  641       public int showOpenDialog(Component parent) throws HeadlessException {
  642           setDialogType(OPEN_DIALOG);
  643           return showDialog(parent, null);
  644       }
  645   
  646       /**
  647        * Pops up a "Save File" file chooser dialog. Note that the
  648        * text that appears in the approve button is determined by
  649        * the L&F.
  650        *
  651        * @param    parent  the parent component of the dialog,
  652        *                  can be <code>null</code>;
  653        *                  see <code>showDialog</code> for details
  654        * @return   the return state of the file chooser on popdown:
  655        * <ul>
  656        * <li>JFileChooser.CANCEL_OPTION
  657        * <li>JFileChooser.APPROVE_OPTION
  658        * <li>JFileChooser.ERROR_OPTION if an error occurs or the
  659        *                  dialog is dismissed
  660        * </ul>
  661        * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  662        * returns true.
  663        * @see java.awt.GraphicsEnvironment#isHeadless
  664        * @see #showDialog
  665        */
  666       public int showSaveDialog(Component parent) throws HeadlessException {
  667           setDialogType(SAVE_DIALOG);
  668           return showDialog(parent, null);
  669       }
  670   
  671       /**
  672        * Pops a custom file chooser dialog with a custom approve button.
  673        * For example, the following code
  674        * pops up a file chooser with a "Run Application" button
  675        * (instead of the normal "Save" or "Open" button):
  676        * <pre>
  677        * filechooser.showDialog(parentFrame, "Run Application");
  678        * </pre>
  679        *
  680        * Alternatively, the following code does the same thing:
  681        * <pre>
  682        *    JFileChooser chooser = new JFileChooser(null);
  683        *    chooser.setApproveButtonText("Run Application");
  684        *    chooser.showDialog(parentFrame, null);
  685        * </pre>
  686        *
  687        * <!--PENDING(jeff) - the following method should be added to the api:
  688        *      showDialog(Component parent);-->
  689        * <!--PENDING(kwalrath) - should specify modality and what
  690        *      "depends" means.-->
  691        *
  692        * <p>
  693        *
  694        * The <code>parent</code> argument determines two things:
  695        * the frame on which the open dialog depends and
  696        * the component whose position the look and feel
  697        * should consider when placing the dialog.  If the parent
  698        * is a <code>Frame</code> object (such as a <code>JFrame</code>)
  699        * then the dialog depends on the frame and
  700        * the look and feel positions the dialog
  701        * relative to the frame (for example, centered over the frame).
  702        * If the parent is a component, then the dialog
  703        * depends on the frame containing the component,
  704        * and is positioned relative to the component
  705        * (for example, centered over the component).
  706        * If the parent is <code>null</code>, then the dialog depends on
  707        * no visible window, and it's placed in a
  708        * look-and-feel-dependent position
  709        * such as the center of the screen.
  710        *
  711        * @param   parent  the parent component of the dialog;
  712        *                  can be <code>null</code>
  713        * @param   approveButtonText the text of the <code>ApproveButton</code>
  714        * @return  the return state of the file chooser on popdown:
  715        * <ul>
  716        * <li>JFileChooser.CANCEL_OPTION
  717        * <li>JFileChooser.APPROVE_OPTION
  718        * <li>JFileCHooser.ERROR_OPTION if an error occurs or the
  719        *                  dialog is dismissed
  720        * </ul>
  721        * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  722        * returns true.
  723        * @see java.awt.GraphicsEnvironment#isHeadless
  724        */
  725       public int showDialog(Component parent, String approveButtonText)
  726           throws HeadlessException {
  727           if(approveButtonText != null) {
  728               setApproveButtonText(approveButtonText);
  729               setDialogType(CUSTOM_DIALOG);
  730           }
  731           dialog = createDialog(parent);
  732           dialog.addWindowListener(new WindowAdapter() {
  733               public void windowClosing(WindowEvent e) {
  734                   returnValue = CANCEL_OPTION;
  735               }
  736           });
  737           returnValue = ERROR_OPTION;
  738           rescanCurrentDirectory();
  739   
  740           dialog.show();
  741           firePropertyChange("JFileChooserDialogIsClosingProperty", dialog, null);
  742           dialog.dispose();
  743           dialog = null;
  744           return returnValue;
  745       }
  746   
  747       /**
  748        * Creates and returns a new <code>JDialog</code> wrapping
  749        * <code>this</code> centered on the <code>parent</code>
  750        * in the <code>parent</code>'s frame.
  751        * This method can be overriden to further manipulate the dialog,
  752        * to disable resizing, set the location, etc. Example:
  753        * <pre>
  754        *     class MyFileChooser extends JFileChooser {
  755        *         protected JDialog createDialog(Component parent) throws HeadlessException {
  756        *             JDialog dialog = super.createDialog(parent);
  757        *             dialog.setLocation(300, 200);
  758        *             dialog.setResizable(false);
  759        *             return dialog;
  760        *         }
  761        *     }
  762        * </pre>
  763        *
  764        * @param   parent  the parent component of the dialog;
  765        *                  can be <code>null</code>
  766        * @return a new <code>JDialog</code> containing this instance
  767        * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  768        * returns true.
  769        * @see java.awt.GraphicsEnvironment#isHeadless
  770        * @since 1.4
  771        */
  772       protected JDialog createDialog(Component parent) throws HeadlessException {
  773           String title = getUI().getDialogTitle(this);
  774           putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY,
  775                             title);
  776   
  777           JDialog dialog;
  778           Window window = JOptionPane.getWindowForComponent(parent);
  779           if (window instanceof Frame) {
  780               dialog = new JDialog((Frame)window, title, true);
  781           } else {
  782               dialog = new JDialog((Dialog)window, title, true);
  783           }
  784           dialog.setComponentOrientation(this.getComponentOrientation());
  785   
  786           Container contentPane = dialog.getContentPane();
  787           contentPane.setLayout(new BorderLayout());
  788           contentPane.add(this, BorderLayout.CENTER);
  789   
  790           if (JDialog.isDefaultLookAndFeelDecorated()) {
  791               boolean supportsWindowDecorations =
  792               UIManager.getLookAndFeel().getSupportsWindowDecorations();
  793               if (supportsWindowDecorations) {
  794                   dialog.getRootPane().setWindowDecorationStyle(JRootPane.FILE_CHOOSER_DIALOG);
  795               }
  796           }
  797           dialog.pack();
  798           dialog.setLocationRelativeTo(parent);
  799   
  800           return dialog;
  801       }
  802   
  803       // **************************
  804       // ***** Dialog Options *****
  805       // **************************
  806   
  807       /**
  808        * Returns the value of the <code>controlButtonsAreShown</code>
  809        * property.
  810        *
  811        * @return   the value of the <code>controlButtonsAreShown</code>
  812        *     property
  813        *
  814        * @see #setControlButtonsAreShown
  815        * @since 1.3
  816        */
  817       public boolean getControlButtonsAreShown() {
  818           return controlsShown;
  819       }
  820   
  821   
  822       /**
  823        * Sets the property
  824        * that indicates whether the <i>approve</i> and <i>cancel</i>
  825        * buttons are shown in the file chooser.  This property
  826        * is <code>true</code> by default.  Look and feels
  827        * that always show these buttons will ignore the value
  828        * of this property.
  829        * This method fires a property-changed event,
  830        * using the string value of
  831        * <code>CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY</code>
  832        * as the name of the property.
  833        *
  834        * @param b <code>false</code> if control buttons should not be
  835        *    shown; otherwise, <code>true</code>
  836        *
  837        * @beaninfo
  838        *   preferred: true
  839        *       bound: true
  840        * description: Sets whether the approve & cancel buttons are shown.
  841        *
  842        * @see #getControlButtonsAreShown
  843        * @see #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY
  844        * @since 1.3
  845        */
  846       public void setControlButtonsAreShown(boolean b) {
  847           if(controlsShown == b) {
  848               return;
  849           }
  850           boolean oldValue = controlsShown;
  851           controlsShown = b;
  852           firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY, oldValue, controlsShown);
  853       }
  854   
  855       /**
  856        * Returns the type of this dialog.  The default is
  857        * <code>JFileChooser.OPEN_DIALOG</code>.
  858        *
  859        * @return   the type of dialog to be displayed:
  860        * <ul>
  861        * <li>JFileChooser.OPEN_DIALOG
  862        * <li>JFileChooser.SAVE_DIALOG
  863        * <li>JFileChooser.CUSTOM_DIALOG
  864        * </ul>
  865        *
  866        * @see #setDialogType
  867        */
  868       public int getDialogType() {
  869           return dialogType;
  870       }
  871   
  872       /**
  873        * Sets the type of this dialog. Use <code>OPEN_DIALOG</code> when you
  874        * want to bring up a file chooser that the user can use to open a file.
  875        * Likewise, use <code>SAVE_DIALOG</code> for letting the user choose
  876        * a file for saving.
  877        * Use <code>CUSTOM_DIALOG</code> when you want to use the file
  878        * chooser in a context other than "Open" or "Save".
  879        * For instance, you might want to bring up a file chooser that allows
  880        * the user to choose a file to execute. Note that you normally would not
  881        * need to set the <code>JFileChooser</code> to use
  882        * <code>CUSTOM_DIALOG</code>
  883        * since a call to <code>setApproveButtonText</code> does this for you.
  884        * The default dialog type is <code>JFileChooser.OPEN_DIALOG</code>.
  885        *
  886        * @param dialogType the type of dialog to be displayed:
  887        * <ul>
  888        * <li>JFileChooser.OPEN_DIALOG
  889        * <li>JFileChooser.SAVE_DIALOG
  890        * <li>JFileChooser.CUSTOM_DIALOG
  891        * </ul>
  892        *
  893        * @exception IllegalArgumentException if <code>dialogType</code> is
  894        *                          not legal
  895        * @beaninfo
  896        *   preferred: true
  897        *       bound: true
  898        * description: The type (open, save, custom) of the JFileChooser.
  899        *        enum:
  900        *              OPEN_DIALOG JFileChooser.OPEN_DIALOG
  901        *              SAVE_DIALOG JFileChooser.SAVE_DIALOG
  902        *              CUSTOM_DIALOG JFileChooser.CUSTOM_DIALOG
  903        *
  904        * @see #getDialogType
  905        * @see #setApproveButtonText
  906        */
  907       // PENDING(jeff) - fire button text change property
  908       public void setDialogType(int dialogType) {
  909           if(this.dialogType == dialogType) {
  910               return;
  911           }
  912           if(!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || dialogType == CUSTOM_DIALOG)) {
  913               throw new IllegalArgumentException("Incorrect Dialog Type: " + dialogType);
  914           }
  915           int oldValue = this.dialogType;
  916           this.dialogType = dialogType;
  917           if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) {
  918               setApproveButtonText(null);
  919           }
  920           firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType);
  921       }
  922   
  923       /**
  924        * Sets the string that goes in the <code>JFileChooser</code> window's
  925        * title bar.
  926        *
  927        * @param dialogTitle the new <code>String</code> for the title bar
  928        *
  929        * @beaninfo
  930        *   preferred: true
  931        *       bound: true
  932        * description: The title of the JFileChooser dialog window.
  933        *
  934        * @see #getDialogTitle
  935        *
  936        */
  937       public void setDialogTitle(String dialogTitle) {
  938           String oldValue = this.dialogTitle;
  939           this.dialogTitle = dialogTitle;
  940           if(dialog != null) {
  941               dialog.setTitle(dialogTitle);
  942           }
  943           firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue, dialogTitle);
  944       }
  945   
  946       /**
  947        * Gets the string that goes in the <code>JFileChooser</code>'s titlebar.
  948        *
  949        * @see #setDialogTitle
  950        */
  951       public String getDialogTitle() {
  952           return dialogTitle;
  953       }
  954   
  955       // ************************************
  956       // ***** JFileChooser View Options *****
  957       // ************************************
  958   
  959   
  960   
  961       /**
  962        * Sets the tooltip text used in the <code>ApproveButton</code>.
  963        * If <code>null</code>, the UI object will determine the button's text.
  964        *
  965        * @beaninfo
  966        *   preferred: true
  967        *       bound: true
  968        * description: The tooltip text for the ApproveButton.
  969        *
  970        * @param toolTipText the tooltip text for the approve button
  971        * @see #setApproveButtonText
  972        * @see #setDialogType
  973        * @see #showDialog
  974        */
  975       public void setApproveButtonToolTipText(String toolTipText) {
  976           if(approveButtonToolTipText == toolTipText) {
  977               return;
  978           }
  979           String oldValue = approveButtonToolTipText;
  980           approveButtonToolTipText = toolTipText;
  981           firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, oldValue, approveButtonToolTipText);
  982       }
  983   
  984   
  985       /**
  986        * Returns the tooltip text used in the <code>ApproveButton</code>.
  987        * If <code>null</code>, the UI object will determine the button's text.
  988        *
  989        * @return the tooltip text used for the approve button
  990        *
  991        * @see #setApproveButtonText
  992        * @see #setDialogType
  993        * @see #showDialog
  994        */
  995       public String getApproveButtonToolTipText() {
  996           return approveButtonToolTipText;
  997       }
  998   
  999       /**
 1000        * Returns the approve button's mnemonic.
 1001        * @return an integer value for the mnemonic key
 1002        *
 1003        * @see #setApproveButtonMnemonic
 1004        */
 1005       public int getApproveButtonMnemonic() {
 1006           return approveButtonMnemonic;
 1007       }
 1008   
 1009       /**
 1010        * Sets the approve button's mnemonic using a numeric keycode.
 1011        *
 1012        * @param mnemonic  an integer value for the mnemonic key
 1013        *
 1014        * @beaninfo
 1015        *   preferred: true
 1016        *       bound: true
 1017        * description: The mnemonic key accelerator for the ApproveButton.
 1018        *
 1019        * @see #getApproveButtonMnemonic
 1020        */
 1021       public void setApproveButtonMnemonic(int mnemonic) {
 1022           if(approveButtonMnemonic == mnemonic) {
 1023              return;
 1024           }
 1025           int oldValue = approveButtonMnemonic;
 1026           approveButtonMnemonic = mnemonic;
 1027           firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY, oldValue, approveButtonMnemonic);
 1028       }
 1029   
 1030       /**
 1031        * Sets the approve button's mnemonic using a character.
 1032        * @param mnemonic  a character value for the mnemonic key
 1033        *
 1034        * @see #getApproveButtonMnemonic
 1035        */
 1036       public void setApproveButtonMnemonic(char mnemonic) {
 1037           int vk = (int) mnemonic;
 1038           if(vk >= 'a' && vk <='z') {
 1039               vk -= ('a' - 'A');
 1040           }
 1041           setApproveButtonMnemonic(vk);
 1042       }
 1043   
 1044   
 1045       /**
 1046        * Sets the text used in the <code>ApproveButton</code> in the
 1047        * <code>FileChooserUI</code>.
 1048        *
 1049        * @beaninfo
 1050        *   preferred: true
 1051        *       bound: true
 1052        * description: The text that goes in the ApproveButton.
 1053        *
 1054        * @param approveButtonText the text used in the <code>ApproveButton</code>
 1055        *
 1056        * @see #getApproveButtonText
 1057        * @see #setDialogType
 1058        * @see #showDialog
 1059        */
 1060       // PENDING(jeff) - have ui set this on dialog type change
 1061       public void setApproveButtonText(String approveButtonText) {
 1062           if(this.approveButtonText == approveButtonText) {
 1063               return;
 1064           }
 1065           String oldValue = this.approveButtonText;
 1066           this.approveButtonText = approveButtonText;
 1067           firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldValue, approveButtonText);
 1068       }
 1069   
 1070       /**
 1071        * Returns the text used in the <code>ApproveButton</code> in the
 1072        * <code>FileChooserUI</code>.
 1073        * If <code>null</code>, the UI object will determine the button's text.
 1074        *
 1075        * Typically, this would be "Open" or "Save".
 1076        *
 1077        * @return the text used in the <code>ApproveButton</code>
 1078        *
 1079        * @see #setApproveButtonText
 1080        * @see #setDialogType
 1081        * @see #showDialog
 1082        */
 1083       public String getApproveButtonText() {
 1084           return approveButtonText;
 1085       }
 1086   
 1087       /**
 1088        * Gets the list of user choosable file filters.
 1089        *
 1090        * @return a <code>FileFilter</code> array containing all the choosable
 1091        *         file filters
 1092        *
 1093        * @see #addChoosableFileFilter
 1094        * @see #removeChoosableFileFilter
 1095        * @see #resetChoosableFileFilters
 1096        */
 1097       public FileFilter[] getChoosableFileFilters() {
 1098           FileFilter[] filterArray = new FileFilter[filters.size()];
 1099           filters.copyInto(filterArray);
 1100           return filterArray;
 1101       }
 1102   
 1103       /**
 1104        * Adds a filter to the list of user choosable file filters.
 1105        * For information on setting the file selection mode, see
 1106        * {@link #setFileSelectionMode setFileSelectionMode}.
 1107        *
 1108        * @param filter the <code>FileFilter</code> to add to the choosable file
 1109        *               filter list
 1110        *
 1111        * @beaninfo
 1112        *   preferred: true
 1113        *       bound: true
 1114        * description: Adds a filter to the list of user choosable file filters.
 1115        *
 1116        * @see #getChoosableFileFilters
 1117        * @see #removeChoosableFileFilter
 1118        * @see #resetChoosableFileFilters
 1119        * @see #setFileSelectionMode
 1120        */
 1121       public void addChoosableFileFilter(FileFilter filter) {
 1122           if(filter != null && !filters.contains(filter)) {
 1123               FileFilter[] oldValue = getChoosableFileFilters();
 1124               filters.addElement(filter);
 1125               firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
 1126               if (fileFilter == null && filters.size() == 1) {
 1127                   setFileFilter(filter);
 1128               }
 1129           }
 1130       }
 1131   
 1132       /**
 1133        * Removes a filter from the list of user choosable file filters. Returns
 1134        * true if the file filter was removed.
 1135        *
 1136        * @see #addChoosableFileFilter
 1137        * @see #getChoosableFileFilters
 1138        * @see #resetChoosableFileFilters
 1139        */
 1140       public boolean removeChoosableFileFilter(FileFilter f) {
 1141           if(filters.contains(f)) {
 1142               if(getFileFilter() == f) {
 1143                   setFileFilter(null);
 1144               }
 1145               FileFilter[] oldValue = getChoosableFileFilters();
 1146               filters.removeElement(f);
 1147               firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
 1148               return true;
 1149           } else {
 1150               return false;
 1151           }
 1152       }
 1153   
 1154       /**
 1155        * Resets the choosable file filter list to its starting state. Normally,
 1156        * this removes all added file filters while leaving the
 1157        * <code>AcceptAll</code> file filter.
 1158        *
 1159        * @see #addChoosableFileFilter
 1160        * @see #getChoosableFileFilters
 1161        * @see #removeChoosableFileFilter
 1162        */
 1163       public void resetChoosableFileFilters() {
 1164           FileFilter[] oldValue = getChoosableFileFilters();
 1165           setFileFilter(null);
 1166           filters.removeAllElements();
 1167           if(isAcceptAllFileFilterUsed()) {
 1168              addChoosableFileFilter(getAcceptAllFileFilter());
 1169           }
 1170           firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
 1171       }
 1172   
 1173       /**
 1174        * Returns the <code>AcceptAll</code> file filter.
 1175        * For example, on Microsoft Windows this would be All Files (*.*).
 1176        */
 1177       public FileFilter getAcceptAllFileFilter() {
 1178           FileFilter filter = null;
 1179           if(getUI() != null) {
 1180               filter = getUI().getAcceptAllFileFilter(this);
 1181           }
 1182           return filter;
 1183       }
 1184   
 1185      /**
 1186       * Returns whether the <code>AcceptAll FileFilter</code> is used.
 1187       * @return true if the <code>AcceptAll FileFilter</code> is used
 1188       * @see #setAcceptAllFileFilterUsed
 1189       * @since 1.3
 1190       */
 1191       public boolean isAcceptAllFileFilterUsed() {
 1192           return useAcceptAllFileFilter;
 1193       }
 1194   
 1195      /**
 1196       * Determines whether the <code>AcceptAll FileFilter</code> is used
 1197       * as an available choice in the choosable filter list.
 1198       * If false, the <code>AcceptAll</code> file filter is removed from
 1199       * the list of available file filters.
 1200       * If true, the <code>AcceptAll</code> file filter will become the
 1201       * the actively used file filter.
 1202       *
 1203       * @beaninfo
 1204       *   preferred: true
 1205       *       bound: true
 1206       * description: Sets whether the AcceptAll FileFilter is used as an available choice in the choosable filter list.
 1207       *
 1208       * @see #isAcceptAllFileFilterUsed
 1209       * @see #getAcceptAllFileFilter
 1210       * @see #setFileFilter
 1211       * @since 1.3
 1212       */
 1213       public void setAcceptAllFileFilterUsed(boolean b) {
 1214           boolean oldValue = useAcceptAllFileFilter;
 1215           useAcceptAllFileFilter = b;
 1216           if(!b) {
 1217               removeChoosableFileFilter(getAcceptAllFileFilter());
 1218           } else {
 1219               removeChoosableFileFilter(getAcceptAllFileFilter());
 1220               addChoosableFileFilter(getAcceptAllFileFilter());
 1221           }
 1222           firePropertyChange(ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY, oldValue, useAcceptAllFileFilter);
 1223       }
 1224   
 1225       /**
 1226        * Returns the accessory component.
 1227        *
 1228        * @return this JFileChooser's accessory component, or null
 1229        * @see #setAccessory
 1230        */
 1231       public JComponent getAccessory() {
 1232           return accessory;
 1233       }
 1234   
 1235       /**
 1236        * Sets the accessory component. An accessory is often used to show a
 1237        * preview image of the selected file; however, it can be used for anything
 1238        * that the programmer wishes, such as extra custom file chooser controls.
 1239        *
 1240        * <p>
 1241        * Note: if there was a previous accessory, you should unregister
 1242        * any listeners that the accessory might have registered with the
 1243        * file chooser.
 1244        *
 1245        * @beaninfo
 1246        *   preferred: true
 1247        *       bound: true
 1248        * description: Sets the accessory component on the JFileChooser.
 1249        */
 1250       public void setAccessory(JComponent newAccessory) {
 1251           JComponent oldValue = accessory;
 1252           accessory = newAccessory;
 1253           firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue, accessory);
 1254       }
 1255   
 1256       /**
 1257        * Sets the <code>JFileChooser</code> to allow the user to just
 1258        * select files, just select
 1259        * directories, or select both files and directories.  The default is
 1260        * <code>JFilesChooser.FILES_ONLY</code>.
 1261        *
 1262        * @param mode the type of files to be displayed:
 1263        * <ul>
 1264        * <li>JFileChooser.FILES_ONLY
 1265        * <li>JFileChooser.DIRECTORIES_ONLY
 1266        * <li>JFileChooser.FILES_AND_DIRECTORIES
 1267        * </ul>
 1268        *
 1269        * @exception IllegalArgumentException  if <code>mode</code> is an
 1270        *                          illegal file selection mode
 1271        * @beaninfo
 1272        *   preferred: true
 1273        *       bound: true
 1274        * description: Sets the types of files that the JFileChooser can choose.
 1275        *        enum: FILES_ONLY JFileChooser.FILES_ONLY
 1276        *              DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY
 1277        *              FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES
 1278        *
 1279        *
 1280        * @see #getFileSelectionMode
 1281        */
 1282       public void setFileSelectionMode(int mode) {
 1283           if(fileSelectionMode == mode) {
 1284               return;
 1285           }
 1286   
 1287           if ((mode == FILES_ONLY) || (mode == DIRECTORIES_ONLY) || (mode == FILES_AND_DIRECTORIES)) {
 1288              int oldValue = fileSelectionMode;
 1289              fileSelectionMode = mode;
 1290              firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode);
 1291           } else {
 1292              throw new IllegalArgumentException("Incorrect Mode for file selection: " + mode);
 1293           }
 1294       }
 1295   
 1296       /**
 1297        * Returns the current file-selection mode.  The default is
 1298        * <code>JFilesChooser.FILES_ONLY</code>.
 1299        *
 1300        * @return the type of files to be displayed, one of the following:
 1301        * <ul>
 1302        * <li>JFileChooser.FILES_ONLY
 1303        * <li>JFileChooser.DIRECTORIES_ONLY
 1304        * <li>JFileChooser.FILES_AND_DIRECTORIES
 1305        * </ul>
 1306        * @see #setFileSelectionMode
 1307        */
 1308       public int getFileSelectionMode() {
 1309           return fileSelectionMode;
 1310       }
 1311   
 1312       /**
 1313        * Convenience call that determines if files are selectable based on the
 1314        * current file selection mode.
 1315        *
 1316        * @see #setFileSelectionMode
 1317        * @see #getFileSelectionMode
 1318        */
 1319       public boolean isFileSelectionEnabled() {
 1320           return ((fileSelectionMode == FILES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
 1321       }
 1322   
 1323       /**
 1324        * Convenience call that determines if directories are selectable based
 1325        * on the current file selection mode.
 1326        *
 1327        * @see #setFileSelectionMode
 1328        * @see #getFileSelectionMode
 1329        */
 1330       public boolean isDirectorySelectionEnabled() {
 1331           return ((fileSelectionMode == DIRECTORIES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
 1332       }
 1333   
 1334       /**
 1335        * Sets the file chooser to allow multiple file selections.
 1336        *
 1337        * @param b true if multiple files may be selected
 1338        * @beaninfo
 1339        *       bound: true
 1340        * description: Sets multiple file selection mode.
 1341        *
 1342        * @see #isMultiSelectionEnabled
 1343        */
 1344       public void setMultiSelectionEnabled(boolean b) {
 1345           if(multiSelectionEnabled == b) {
 1346               return;
 1347           }
 1348           boolean oldValue = multiSelectionEnabled;
 1349           multiSelectionEnabled = b;
 1350           firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY, oldValue, multiSelectionEnabled);
 1351       }
 1352   
 1353       /**
 1354        * Returns true if multiple files can be selected.
 1355        * @return true if multiple files can be selected
 1356        * @see #setMultiSelectionEnabled
 1357        */
 1358       public boolean isMultiSelectionEnabled() {
 1359           return multiSelectionEnabled;
 1360       }
 1361   
 1362   
 1363       /**
 1364        * Returns true if hidden files are not shown in the file chooser;
 1365        * otherwise, returns false.
 1366        *
 1367        * @return the status of the file hiding property
 1368        * @see #setFileHidingEnabled
 1369        */
 1370       public boolean isFileHidingEnabled() {
 1371           return useFileHiding;
 1372       }
 1373   
 1374       /**
 1375        * Sets file hiding on or off. If true, hidden files are not shown
 1376        * in the file chooser. The job of determining which files are
 1377        * shown is done by the <code>FileView</code>.
 1378        *
 1379        * @beaninfo
 1380        *   preferred: true
 1381        *       bound: true
 1382        * description: Sets file hiding on or off.
 1383        *
 1384        * @param b the boolean value that determines whether file hiding is
 1385        *          turned on
 1386        * @see #isFileHidingEnabled
 1387        */
 1388       public void setFileHidingEnabled(boolean b) {
 1389           // Dump showFilesListener since we'll ignore it from now on
 1390           if (showFilesListener != null) {
 1391               Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener);
 1392               showFilesListener = null;
 1393           }
 1394           boolean oldValue = useFileHiding;
 1395           useFileHiding = b;
 1396           firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, useFileHiding);
 1397       }
 1398   
 1399       /**
 1400        * Sets the current file filter. The file filter is used by the
 1401        * file chooser to filter out files from the user's view.
 1402        *
 1403        * @beaninfo
 1404        *   preferred: true
 1405        *       bound: true
 1406        * description: Sets the File Filter used to filter out files of type.
 1407        *
 1408        * @param filter the new current file filter to use
 1409        * @see #getFileFilter
 1410        */
 1411       public void setFileFilter(FileFilter filter) {
 1412           FileFilter oldValue = fileFilter;
 1413           fileFilter = filter;
 1414           if (filter != null) {
 1415               if (isMultiSelectionEnabled() && selectedFiles != null && selectedFiles.length > 0) {
 1416                   Vector fList = new Vector();
 1417                   boolean failed = false;
 1418                   for (int i = 0; i < selectedFiles.length; i++) {
 1419                       if (filter.accept(selectedFiles[i])) {
 1420                           fList.add(selectedFiles[i]);
 1421                       } else {
 1422                           failed = true;
 1423                       }
 1424                   }
 1425                   if (failed) {
 1426                       setSelectedFiles((fList.size() == 0) ? null : (File[])fList.toArray(new File[fList.size()]));
 1427                   }
 1428               } else if (selectedFile != null && !filter.accept(selectedFile)) {
 1429                   setSelectedFile(null);
 1430               }
 1431           }
 1432           firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
 1433       }
 1434   
 1435   
 1436       /**
 1437        * Returns the currently selected file filter.
 1438        *
 1439        * @return the current file filter
 1440        * @see #setFileFilter
 1441        * @see #addChoosableFileFilter
 1442        */
 1443       public FileFilter getFileFilter() {
 1444           return fileFilter;
 1445       }
 1446   
 1447       /**
 1448        * Sets the file view to used to retrieve UI information, such as
 1449        * the icon that represents a file or the type description of a file.
 1450        *
 1451        * @beaninfo
 1452        *   preferred: true
 1453        *       bound: true
 1454        * description: Sets the File View used to get file type information.
 1455        *
 1456        * @see #getFileView
 1457        */
 1458       public void setFileView(FileView fileView) {
 1459           FileView oldValue = this.fileView;
 1460           this.fileView = fileView;
 1461           firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue, fileView);
 1462       }
 1463   
 1464       /**
 1465        * Returns the current file view.
 1466        *
 1467        * @see #setFileView
 1468        */
 1469       public FileView getFileView() {
 1470           return fileView;
 1471       }
 1472   
 1473       // ******************************
 1474       // *****FileView delegation *****
 1475       // ******************************
 1476   
 1477       // NOTE: all of the following methods attempt to delegate
 1478       // first to the client set fileView, and if <code>null</code> is returned
 1479       // (or there is now client defined fileView) then calls the
 1480       // UI's default fileView.
 1481   
 1482       /**
 1483        * Returns the filename.
 1484        * @param f the <code>File</code>
 1485        * @return the <code>String</code> containing the filename for
 1486        *          <code>f</code>
 1487        * @see FileView#getName
 1488        */
 1489       public String getName(File f) {
 1490           String filename = null;
 1491           if(f != null) {
 1492               if(getFileView() != null) {
 1493                   filename = getFileView().getName(f);
 1494               }
 1495               if(filename == null && uiFileView != null) {
 1496                   filename = uiFileView.getName(f);
 1497               }
 1498           }
 1499           return filename;
 1500       }
 1501   
 1502       /**
 1503        * Returns the file description.
 1504        * @param f the <code>File</code>
 1505        * @return the <code>String</code> containing the file description for
 1506        *          <code>f</code>
 1507        * @see FileView#getDescription
 1508        */
 1509       public String getDescription(File f) {
 1510           String description = null;
 1511           if(f != null) {
 1512               if(getFileView() != null) {
 1513                   description = getFileView().getDescription(f);
 1514               }
 1515               if(description == null && uiFileView != null) {
 1516                   description = uiFileView.getDescription(f);
 1517               }
 1518           }
 1519           return description;
 1520       }
 1521   
 1522       /**
 1523        * Returns the file type.
 1524        * @param f the <code>File</code>
 1525        * @return the <code>String</code> containing the file type description for
 1526        *          <code>f</code>
 1527        * @see FileView#getTypeDescription
 1528        */
 1529       public String getTypeDescription(File f) {
 1530           String typeDescription = null;
 1531           if(f != null) {
 1532               if(getFileView() != null) {
 1533                   typeDescription = getFileView().getTypeDescription(f);
 1534               }
 1535               if(typeDescription == null && uiFileView != null) {
 1536                   typeDescription = uiFileView.getTypeDescription(f);
 1537               }
 1538           }
 1539           return typeDescription;
 1540       }
 1541   
 1542       /**
 1543        * Returns the icon for this file or type of file, depending
 1544        * on the system.
 1545        * @param f the <code>File</code>
 1546        * @return the <code>Icon</code> for this file, or type of file
 1547        * @see FileView#getIcon
 1548        */
 1549       public Icon getIcon(File f) {
 1550           Icon icon = null;
 1551           if (f != null) {
 1552               if(getFileView() != null) {
 1553                   icon = getFileView().getIcon(f);
 1554               }
 1555               if(icon == null && uiFileView != null) {
 1556                   icon = uiFileView.getIcon(f);
 1557               }
 1558           }
 1559           return icon;
 1560       }
 1561   
 1562       /**
 1563        * Returns true if the file (directory) can be visited.
 1564        * Returns false if the directory cannot be traversed.
 1565        * @param f the <code>File</code>
 1566        * @return true if the file/directory can be traversed, otherwise false
 1567        * @see FileView#isTraversable
 1568        */
 1569       public boolean isTraversable(File f) {
 1570           Boolean traversable = null;
 1571           if (f != null) {
 1572               if (getFileView() != null) {
 1573                   traversable = getFileView().isTraversable(f);
 1574               }
 1575               if (traversable == null && uiFileView != null) {
 1576                   traversable = uiFileView.isTraversable(f);
 1577               }
 1578               if (traversable == null) {
 1579                   traversable = getFileSystemView().isTraversable(f);
 1580               }
 1581           }
 1582           return (traversable != null && traversable.booleanValue());
 1583       }
 1584   
 1585       /**
 1586        * Returns true if the file should be displayed.
 1587        * @param f the <code>File</code>
 1588        * @return true if the file should be displayed, otherwise false
 1589        * @see FileFilter#accept
 1590        */
 1591       public boolean accept(File f) {
 1592           boolean shown = true;
 1593           if(f != null && fileFilter != null) {
 1594               shown = fileFilter.accept(f);
 1595           }
 1596           return shown;
 1597       }
 1598   
 1599       /**
 1600        * Sets the file system view that the <code>JFileChooser</code> uses for
 1601        * accessing and creating file system resources, such as finding
 1602        * the floppy drive and getting a list of root drives.
 1603        * @param fsv  the new <code>FileSystemView</code>
 1604        *
 1605        * @beaninfo
 1606        *      expert: true
 1607        *       bound: true
 1608        * description: Sets the FileSytemView used to get filesystem information.
 1609        *
 1610        * @see FileSystemView
 1611        */
 1612       public void setFileSystemView(FileSystemView fsv) {
 1613           FileSystemView oldValue = fileSystemView;
 1614           fileSystemView = fsv;
 1615           firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue, fileSystemView);
 1616       }
 1617   
 1618       /**
 1619        * Returns the file system view.
 1620        * @return the <code>FileSystemView</code> object
 1621        * @see #setFileSystemView
 1622        */
 1623       public FileSystemView getFileSystemView() {
 1624           return fileSystemView;
 1625       }
 1626   
 1627       // **************************
 1628       // ***** Event Handling *****
 1629       // **************************
 1630   
 1631       /**
 1632        * Called by the UI when the user hits the Approve button
 1633        * (labeled "Open" or "Save", by default). This can also be
 1634        * called by the programmer.
 1635        * This method causes an action event to fire
 1636        * with the command string equal to
 1637        * <code>APPROVE_SELECTION</code>.
 1638        *
 1639        * @see #APPROVE_SELECTION
 1640        */
 1641       public void approveSelection() {
 1642           returnValue = APPROVE_OPTION;
 1643           if(dialog != null) {
 1644               dialog.setVisible(false);
 1645           }
 1646           fireActionPerformed(APPROVE_SELECTION);
 1647       }
 1648   
 1649       /**
 1650        * Called by the UI when the user chooses the Cancel button.
 1651        * This can also be called by the programmer.
 1652        * This method causes an action event to fire
 1653        * with the command string equal to
 1654        * <code>CANCEL_SELECTION</code>.
 1655        *
 1656        * @see #CANCEL_SELECTION
 1657        */
 1658       public void cancelSelection() {
 1659           returnValue = CANCEL_OPTION;
 1660           if(dialog != null) {
 1661               dialog.setVisible(false);
 1662           }
 1663           fireActionPerformed(CANCEL_SELECTION);
 1664       }
 1665   
 1666       /**
 1667        * Adds an <code>ActionListener</code> to the file chooser.
 1668        *
 1669        * @param l  the listener to be added
 1670        *
 1671        * @see #approveSelection
 1672        * @see #cancelSelection
 1673        */
 1674       public void addActionListener(ActionListener l) {
 1675           listenerList.add(ActionListener.class, l);
 1676       }
 1677   
 1678       /**
 1679        * Removes an <code>ActionListener</code> from the file chooser.
 1680        *
 1681        * @param l  the listener to be removed
 1682        *
 1683        * @see #addActionListener
 1684        */
 1685       public void removeActionListener(ActionListener l) {
 1686           listenerList.remove(ActionListener.class, l);
 1687       }
 1688   
 1689       /**
 1690        * Returns an array of all the action listeners
 1691        * registered on this file chooser.
 1692        *
 1693        * @return all of this file chooser's <code>ActionListener</code>s
 1694        *         or an empty
 1695        *         array if no action listeners are currently registered
 1696        *
 1697        * @see #addActionListener
 1698        * @see #removeActionListener
 1699        *
 1700        * @since 1.4
 1701        */
 1702       public ActionListener[] getActionListeners() {
 1703           return (ActionListener[])listenerList.getListeners(
 1704                   ActionListener.class);
 1705       }
 1706   
 1707       /**
 1708        * Notifies all listeners that have registered interest for
 1709        * notification on this event type. The event instance
 1710        * is lazily created using the <code>command</code> parameter.
 1711        *
 1712        * @see EventListenerList
 1713        */
 1714       protected void fireActionPerformed(String command) {
 1715           // Guaranteed to return a non-null array
 1716           Object[] listeners = listenerList.getListenerList();
 1717           long mostRecentEventTime = EventQueue.getMostRecentEventTime();
 1718           int modifiers = 0;
 1719           AWTEvent currentEvent = EventQueue.getCurrentEvent();
 1720           if (currentEvent instanceof InputEvent) {
 1721               modifiers = ((InputEvent)currentEvent).getModifiers();
 1722           } else if (currentEvent instanceof ActionEvent) {
 1723               modifiers = ((ActionEvent)currentEvent).getModifiers();
 1724           }
 1725           ActionEvent e = null;
 1726           // Process the listeners last to first, notifying
 1727           // those that are interested in this event
 1728           for (int i = listeners.length-2; i>=0; i-=2) {
 1729               if (listeners[i]==ActionListener.class) {
 1730                   // Lazily create the event:
 1731                   if (e == null) {
 1732                       e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
 1733                                           command, mostRecentEventTime,
 1734                                           modifiers);
 1735                   }
 1736                   ((ActionListener)listeners[i+1]).actionPerformed(e);
 1737               }
 1738           }
 1739       }
 1740   
 1741       private static class WeakPCL implements PropertyChangeListener {
 1742           WeakReference<JFileChooser> jfcRef;
 1743   
 1744           public WeakPCL(JFileChooser jfc) {
 1745               jfcRef = new WeakReference(jfc);
 1746           }
 1747           public void propertyChange(PropertyChangeEvent ev) {
 1748               assert ev.getPropertyName().equals(SHOW_HIDDEN_PROP);
 1749               JFileChooser jfc = jfcRef.get();
 1750               if (jfc == null) {
 1751                   // Our JFileChooser is no longer around, so we no longer need to
 1752                   // listen for PropertyChangeEvents.
 1753                   Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, this);
 1754               }
 1755               else {
 1756                   boolean oldValue = jfc.useFileHiding;
 1757                   jfc.useFileHiding = !((Boolean)ev.getNewValue()).booleanValue();
 1758                   jfc.firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, jfc.useFileHiding);
 1759               }
 1760           }
 1761       }
 1762   
 1763       // *********************************
 1764       // ***** Pluggable L&F methods *****
 1765       // *********************************
 1766   
 1767       /**
 1768        * Resets the UI property to a value from the current look and feel.
 1769        *
 1770        * @see JComponent#updateUI
 1771        */
 1772       public void updateUI() {
 1773           if (isAcceptAllFileFilterUsed()) {
 1774               removeChoosableFileFilter(getAcceptAllFileFilter());
 1775           }
 1776           FileChooserUI ui = ((FileChooserUI)UIManager.getUI(this));
 1777           if (fileSystemView == null) {
 1778               // We were probably deserialized
 1779               setFileSystemView(FileSystemView.getFileSystemView());
 1780           }
 1781           setUI(ui);
 1782   
 1783           uiFileView = getUI().getFileView(this);
 1784           if(isAcceptAllFileFilterUsed()) {
 1785               addChoosableFileFilter(getAcceptAllFileFilter());
 1786           }
 1787       }
 1788   
 1789       /**
 1790        * Returns a string that specifies the name of the L&F class
 1791        * that renders this component.
 1792        *
 1793        * @return the string "FileChooserUI"
 1794        * @see JComponent#getUIClassID
 1795        * @see UIDefaults#getUI
 1796        * @beaninfo
 1797        *        expert: true
 1798        *   description: A string that specifies the name of the L&F class.
 1799        */
 1800       public String getUIClassID() {
 1801           return uiClassID;
 1802       }
 1803   
 1804       /**
 1805        * Gets the UI object which implements the L&F for this component.
 1806        *
 1807        * @return the FileChooserUI object that implements the FileChooserUI L&F
 1808        */
 1809       public FileChooserUI getUI() {
 1810           return (FileChooserUI) ui;
 1811       }
 1812   
 1813       /**
 1814        * See <code>readObject</code> and <code>writeObject</code> in
 1815        * <code>JComponent</code> for more
 1816        * information about serialization in Swing.
 1817        */
 1818       private void readObject(java.io.ObjectInputStream in)
 1819               throws IOException, ClassNotFoundException {
 1820           in.defaultReadObject();
 1821           installShowFilesListener();
 1822       }
 1823   
 1824       /**
 1825        * See <code>readObject</code> and <code>writeObject</code> in
 1826        * <code>JComponent</code> for more
 1827        * information about serialization in Swing.
 1828        */
 1829       private void writeObject(ObjectOutputStream s) throws IOException {
 1830           FileSystemView fsv = null;
 1831   
 1832           if (isAcceptAllFileFilterUsed()) {
 1833               //The AcceptAllFileFilter is UI specific, it will be reset by
 1834               //updateUI() after deserialization
 1835               removeChoosableFileFilter(getAcceptAllFileFilter());
 1836           }
 1837           if (fileSystemView.equals(FileSystemView.getFileSystemView())) {
 1838               //The default FileSystemView is platform specific, it will be
 1839               //reset by updateUI() after deserialization
 1840               fsv = fileSystemView;
 1841               fileSystemView = null;
 1842           }
 1843           s.defaultWriteObject();
 1844           if (fsv != null) {
 1845               fileSystemView = fsv;
 1846           }
 1847           if (isAcceptAllFileFilterUsed()) {
 1848               addChoosableFileFilter(getAcceptAllFileFilter());
 1849           }
 1850           if (getUIClassID().equals(uiClassID)) {
 1851               byte count = JComponent.getWriteObjCounter(this);
 1852               JComponent.setWriteObjCounter(this, --count);
 1853               if (count == 0 && ui != null) {
 1854                   ui.installUI(this);
 1855               }
 1856           }
 1857       }
 1858   
 1859   
 1860       /**
 1861        * Returns a string representation of this <code>JFileChooser</code>.
 1862        * This method
 1863        * is intended to be used only for debugging purposes, and the
 1864        * content and format of the returned string may vary between
 1865        * implementations. The returned string may be empty but may not
 1866        * be <code>null</code>.
 1867        *
 1868        * @return  a string representation of this <code>JFileChooser</code>
 1869        */
 1870       protected String paramString() {
 1871           String approveButtonTextString = (approveButtonText != null ?
 1872                                             approveButtonText: "");
 1873           String dialogTitleString = (dialogTitle != null ?
 1874                                       dialogTitle: "");
 1875           String dialogTypeString;
 1876           if (dialogType == OPEN_DIALOG) {
 1877               dialogTypeString = "OPEN_DIALOG";
 1878           } else if (dialogType == SAVE_DIALOG) {
 1879               dialogTypeString = "SAVE_DIALOG";
 1880           } else if (dialogType == CUSTOM_DIALOG) {
 1881               dialogTypeString = "CUSTOM_DIALOG";
 1882           } else dialogTypeString = "";
 1883           String returnValueString;
 1884           if (returnValue == CANCEL_OPTION) {
 1885               returnValueString = "CANCEL_OPTION";
 1886           } else if (returnValue == APPROVE_OPTION) {
 1887               returnValueString = "APPROVE_OPTION";
 1888           } else if (returnValue == ERROR_OPTION) {
 1889               returnValueString = "ERROR_OPTION";
 1890           } else returnValueString = "";
 1891           String useFileHidingString = (useFileHiding ?
 1892                                       "true" : "false");
 1893           String fileSelectionModeString;
 1894           if (fileSelectionMode == FILES_ONLY) {
 1895               fileSelectionModeString = "FILES_ONLY";
 1896           } else if (fileSelectionMode == DIRECTORIES_ONLY) {
 1897               fileSelectionModeString = "DIRECTORIES_ONLY";
 1898           } else if (fileSelectionMode == FILES_AND_DIRECTORIES) {
 1899               fileSelectionModeString = "FILES_AND_DIRECTORIES";
 1900           } else fileSelectionModeString = "";
 1901           String currentDirectoryString = (currentDirectory != null ?
 1902                                            currentDirectory.toString() : "");
 1903           String selectedFileString = (selectedFile != null ?
 1904                                        selectedFile.toString() : "");
 1905   
 1906           return super.paramString() +
 1907           ",approveButtonText=" + approveButtonTextString +
 1908           ",currentDirectory=" + currentDirectoryString +
 1909           ",dialogTitle=" + dialogTitleString +
 1910           ",dialogType=" + dialogTypeString +
 1911           ",fileSelectionMode=" + fileSelectionModeString +
 1912           ",returnValue=" + returnValueString +
 1913           ",selectedFile=" + selectedFileString +
 1914           ",useFileHiding=" + useFileHidingString;
 1915       }
 1916   
 1917   /////////////////
 1918   // Accessibility support
 1919   ////////////////
 1920   
 1921       protected AccessibleContext accessibleContext = null;
 1922   
 1923       /**
 1924        * Gets the AccessibleContext associated with this JFileChooser.
 1925        * For file choosers, the AccessibleContext takes the form of an
 1926        * AccessibleJFileChooser.
 1927        * A new AccessibleJFileChooser instance is created if necessary.
 1928        *
 1929        * @return an AccessibleJFileChooser that serves as the
 1930        *         AccessibleContext of this JFileChooser
 1931        */
 1932       public AccessibleContext getAccessibleContext() {
 1933           if (accessibleContext == null) {
 1934               accessibleContext = new AccessibleJFileChooser();
 1935           }
 1936           return accessibleContext;
 1937       }
 1938   
 1939       /**
 1940        * This class implements accessibility support for the
 1941        * <code>JFileChooser</code> class.  It provides an implementation of the
 1942        * Java Accessibility API appropriate to file chooser user-interface
 1943        * elements.
 1944        */
 1945       protected class AccessibleJFileChooser extends AccessibleJComponent {
 1946   
 1947           /**
 1948            * Gets the role of this object.
 1949            *
 1950            * @return an instance of AccessibleRole describing the role of the
 1951            * object
 1952            * @see AccessibleRole
 1953            */
 1954           public AccessibleRole getAccessibleRole() {
 1955               return AccessibleRole.FILE_CHOOSER;
 1956           }
 1957   
 1958       } // inner class AccessibleJFileChooser
 1959   
 1960   }

Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]