0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.swing;
0027
0028 import javax.swing.event.*;
0029 import javax.swing.filechooser.*;
0030 import javax.swing.plaf.FileChooserUI;
0031
0032 import javax.accessibility.*;
0033
0034 import java.io.File;
0035 import java.io.ObjectOutputStream;
0036 import java.io.IOException;
0037
0038 import java.util.Vector;
0039 import java.awt.AWTEvent;
0040 import java.awt.Component;
0041 import java.awt.Container;
0042 import java.awt.BorderLayout;
0043 import java.awt.Window;
0044 import java.awt.Dialog;
0045 import java.awt.Frame;
0046 import java.awt.GraphicsEnvironment;
0047 import java.awt.HeadlessException;
0048 import java.awt.EventQueue;
0049 import java.awt.Toolkit;
0050 import java.awt.event.*;
0051 import java.beans.PropertyChangeListener;
0052 import java.beans.PropertyChangeEvent;
0053 import java.lang.ref.WeakReference;
0054
0055 /**
0056 * <code>JFileChooser</code> provides a simple mechanism for the user to
0057 * choose a file.
0058 * For information about using <code>JFileChooser</code>, see
0059 * <a
0060 href="http://java.sun.com/docs/books/tutorial/uiswing/components/filechooser.html">How to Use File Choosers</a>,
0061 * a section in <em>The Java Tutorial</em>.
0062 *
0063 * <p>
0064 *
0065 * The following code pops up a file chooser for the user's home directory that
0066 * sees only .jpg and .gif images:
0067 * <pre>
0068 * JFileChooser chooser = new JFileChooser();
0069 * FileNameExtensionFilter filter = new FileNameExtensionFilter(
0070 * "JPG & GIF Images", "jpg", "gif");
0071 * chooser.setFileFilter(filter);
0072 * int returnVal = chooser.showOpenDialog(parent);
0073 * if(returnVal == JFileChooser.APPROVE_OPTION) {
0074 * System.out.println("You chose to open this file: " +
0075 * chooser.getSelectedFile().getName());
0076 * }
0077 * </pre>
0078 * <p>
0079 * <strong>Warning:</strong> Swing is not thread safe. For more
0080 * information see <a
0081 * href="package-summary.html#threading">Swing's Threading
0082 * Policy</a>.
0083 *
0084 * @beaninfo
0085 * attribute: isContainer false
0086 * description: A component which allows for the interactive selection of a file.
0087 *
0088 * @version 1.123 05/09/07
0089 * @author Jeff Dinkins
0090 *
0091 */
0092 public class JFileChooser extends JComponent implements Accessible {
0093
0094 /**
0095 * @see #getUIClassID
0096 * @see #readObject
0097 */
0098 private static final String uiClassID = "FileChooserUI";
0099
0100 // ************************
0101 // ***** Dialog Types *****
0102 // ************************
0103
0104 /**
0105 * Type value indicating that the <code>JFileChooser</code> supports an
0106 * "Open" file operation.
0107 */
0108 public static final int OPEN_DIALOG = 0;
0109
0110 /**
0111 * Type value indicating that the <code>JFileChooser</code> supports a
0112 * "Save" file operation.
0113 */
0114 public static final int SAVE_DIALOG = 1;
0115
0116 /**
0117 * Type value indicating that the <code>JFileChooser</code> supports a
0118 * developer-specified file operation.
0119 */
0120 public static final int CUSTOM_DIALOG = 2;
0121
0122 // ********************************
0123 // ***** Dialog Return Values *****
0124 // ********************************
0125
0126 /**
0127 * Return value if cancel is chosen.
0128 */
0129 public static final int CANCEL_OPTION = 1;
0130
0131 /**
0132 * Return value if approve (yes, ok) is chosen.
0133 */
0134 public static final int APPROVE_OPTION = 0;
0135
0136 /**
0137 * Return value if an error occured.
0138 */
0139 public static final int ERROR_OPTION = -1;
0140
0141 // **********************************
0142 // ***** JFileChooser properties *****
0143 // **********************************
0144
0145 /** Instruction to display only files. */
0146 public static final int FILES_ONLY = 0;
0147
0148 /** Instruction to display only directories. */
0149 public static final int DIRECTORIES_ONLY = 1;
0150
0151 /** Instruction to display both files and directories. */
0152 public static final int FILES_AND_DIRECTORIES = 2;
0153
0154 /** Instruction to cancel the current selection. */
0155 public static final String CANCEL_SELECTION = "CancelSelection";
0156
0157 /**
0158 * Instruction to approve the current selection
0159 * (same as pressing yes or ok).
0160 */
0161 public static final String APPROVE_SELECTION = "ApproveSelection";
0162
0163 /** Identifies change in the text on the approve (yes, ok) button. */
0164 public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty";
0165
0166 /**
0167 * Identifies change in the tooltip text for the approve (yes, ok)
0168 * button.
0169 */
0170 public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty";
0171
0172 /** Identifies change in the mnemonic for the approve (yes, ok) button. */
0173 public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = "ApproveButtonMnemonicChangedProperty";
0174
0175 /** Instruction to display the control buttons. */
0176 public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY = "ControlButtonsAreShownChangedProperty";
0177
0178 /** Identifies user's directory change. */
0179 public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
0180
0181 /** Identifies change in user's single-file selection. */
0182 public static final String SELECTED_FILE_CHANGED_PROPERTY = "SelectedFileChangedProperty";
0183
0184 /** Identifies change in user's multiple-file selection. */
0185 public static final String SELECTED_FILES_CHANGED_PROPERTY = "SelectedFilesChangedProperty";
0186
0187 /** Enables multiple-file selections. */
0188 public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "MultiSelectionEnabledChangedProperty";
0189
0190 /**
0191 * Says that a different object is being used to find available drives
0192 * on the system.
0193 */
0194 public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged";
0195
0196 /**
0197 * Says that a different object is being used to retrieve file
0198 * information.
0199 */
0200 public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
0201
0202 /** Identifies a change in the display-hidden-files property. */
0203 public static final String FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged";
0204
0205 /** User changed the kind of files to display. */
0206 public static final String FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged";
0207
0208 /**
0209 * Identifies a change in the kind of selection (single,
0210 * multiple, etc.).
0211 */
0212 public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged";
0213
0214 /**
0215 * Says that a different accessory component is in use
0216 * (for example, to preview files).
0217 */
0218 public static final String ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty";
0219
0220 /**
0221 * Identifies whether a the AcceptAllFileFilter is used or not.
0222 */
0223 public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = "acceptAllFileFilterUsedChanged";
0224
0225 /** Identifies a change in the dialog title. */
0226 public static final String DIALOG_TITLE_CHANGED_PROPERTY = "DialogTitleChangedProperty";
0227
0228 /**
0229 * Identifies a change in the type of files displayed (files only,
0230 * directories only, or both files and directories).
0231 */
0232 public static final String DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty";
0233
0234 /**
0235 * Identifies a change in the list of predefined file filters
0236 * the user can choose from.
0237 */
0238 public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty";
0239
0240 // ******************************
0241 // ***** instance variables *****
0242 // ******************************
0243
0244 private String dialogTitle = null;
0245 private String approveButtonText = null;
0246 private String approveButtonToolTipText = null;
0247 private int approveButtonMnemonic = 0;
0248
0249 private Vector filters = new Vector(5);
0250 private JDialog dialog = null;
0251 private int dialogType = OPEN_DIALOG;
0252 private int returnValue = ERROR_OPTION;
0253 private JComponent accessory = null;
0254
0255 private FileView fileView = null;
0256
0257 // uiFileView is not serialized, as it is initialized
0258 // by updateUI() after deserialization
0259 private transient FileView uiFileView = null;
0260
0261 private boolean controlsShown = true;
0262
0263 private boolean useFileHiding = true;
0264 private static final String SHOW_HIDDEN_PROP = "awt.file.showHiddenFiles";
0265
0266 // Listens to changes in the native setting for showing hidden files.
0267 // The Listener is removed and the native setting is ignored if
0268 // setFileHidingEnabled() is ever called.
0269 private transient PropertyChangeListener showFilesListener = null;
0270
0271 private int fileSelectionMode = FILES_ONLY;
0272
0273 private boolean multiSelectionEnabled = false;
0274
0275 private boolean useAcceptAllFileFilter = true;
0276
0277 private boolean dragEnabled = false;
0278
0279 private FileFilter fileFilter = null;
0280
0281 private FileSystemView fileSystemView = null;
0282
0283 private File currentDirectory = null;
0284 private File selectedFile = null;
0285 private File[] selectedFiles;
0286
0287 // *************************************
0288 // ***** JFileChooser Constructors *****
0289 // *************************************
0290
0291 /**
0292 * Constructs a <code>JFileChooser</code> pointing to the user's
0293 * default directory. This default depends on the operating system.
0294 * It is typically the "My Documents" folder on Windows, and the
0295 * user's home directory on Unix.
0296 */
0297 public JFileChooser() {
0298 this ((File) null, (FileSystemView) null);
0299 }
0300
0301 /**
0302 * Constructs a <code>JFileChooser</code> using the given path.
0303 * Passing in a <code>null</code>
0304 * string causes the file chooser to point to the user's default directory.
0305 * This default depends on the operating system. It is
0306 * typically the "My Documents" folder on Windows, and the user's
0307 * home directory on Unix.
0308 *
0309 * @param currentDirectoryPath a <code>String</code> giving the path
0310 * to a file or directory
0311 */
0312 public JFileChooser(String currentDirectoryPath) {
0313 this (currentDirectoryPath, (FileSystemView) null);
0314 }
0315
0316 /**
0317 * Constructs a <code>JFileChooser</code> using the given <code>File</code>
0318 * as the path. Passing in a <code>null</code> file
0319 * causes the file chooser to point to the user's default directory.
0320 * This default depends on the operating system. It is
0321 * typically the "My Documents" folder on Windows, and the user's
0322 * home directory on Unix.
0323 *
0324 * @param currentDirectory a <code>File</code> object specifying
0325 * the path to a file or directory
0326 */
0327 public JFileChooser(File currentDirectory) {
0328 this (currentDirectory, (FileSystemView) null);
0329 }
0330
0331 /**
0332 * Constructs a <code>JFileChooser</code> using the given
0333 * <code>FileSystemView</code>.
0334 */
0335 public JFileChooser(FileSystemView fsv) {
0336 this ((File) null, fsv);
0337 }
0338
0339 /**
0340 * Constructs a <code>JFileChooser</code> using the given current directory
0341 * and <code>FileSystemView</code>.
0342 */
0343 public JFileChooser(File currentDirectory, FileSystemView fsv) {
0344 setup(fsv);
0345 setCurrentDirectory(currentDirectory);
0346 }
0347
0348 /**
0349 * Constructs a <code>JFileChooser</code> using the given current directory
0350 * path and <code>FileSystemView</code>.
0351 */
0352 public JFileChooser(String currentDirectoryPath, FileSystemView fsv) {
0353 setup(fsv);
0354 if (currentDirectoryPath == null) {
0355 setCurrentDirectory(null);
0356 } else {
0357 setCurrentDirectory(fileSystemView
0358 .createFileObject(currentDirectoryPath));
0359 }
0360 }
0361
0362 /**
0363 * Performs common constructor initialization and setup.
0364 */
0365 protected void setup(FileSystemView view) {
0366 installShowFilesListener();
0367
0368 if (view == null) {
0369 view = FileSystemView.getFileSystemView();
0370 }
0371 setFileSystemView(view);
0372 updateUI();
0373 if (isAcceptAllFileFilterUsed()) {
0374 setFileFilter(getAcceptAllFileFilter());
0375 }
0376 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
0377 }
0378
0379 private void installShowFilesListener() {
0380 // Track native setting for showing hidden files
0381 Toolkit tk = Toolkit.getDefaultToolkit();
0382 Object showHiddenProperty = tk
0383 .getDesktopProperty(SHOW_HIDDEN_PROP);
0384 if (showHiddenProperty instanceof Boolean) {
0385 useFileHiding = !((Boolean) showHiddenProperty)
0386 .booleanValue();
0387 showFilesListener = new WeakPCL(this );
0388 tk.addPropertyChangeListener(SHOW_HIDDEN_PROP,
0389 showFilesListener);
0390 }
0391 }
0392
0393 /**
0394 * Sets the <code>dragEnabled</code> property,
0395 * which must be <code>true</code> to enable
0396 * automatic drag handling (the first part of drag and drop)
0397 * on this component.
0398 * The <code>transferHandler</code> property needs to be set
0399 * to a non-<code>null</code> value for the drag to do
0400 * anything. The default value of the <code>dragEnabled</code>
0401 * property
0402 * is <code>false</code>.
0403 *
0404 * <p>
0405 *
0406 * When automatic drag handling is enabled,
0407 * most look and feels begin a drag-and-drop operation
0408 * whenever the user presses the mouse button over an item
0409 * and then moves the mouse a few pixels.
0410 * Setting this property to <code>true</code>
0411 * can therefore have a subtle effect on
0412 * how selections behave.
0413 *
0414 * <p>
0415 *
0416 * Some look and feels might not support automatic drag and drop;
0417 * they will ignore this property. You can work around such
0418 * look and feels by modifying the component
0419 * to directly call the <code>exportAsDrag</code> method of a
0420 * <code>TransferHandler</code>.
0421 *
0422 * @param b the value to set the <code>dragEnabled</code> property to
0423 * @exception HeadlessException if
0424 * <code>b</code> is <code>true</code> and
0425 * <code>GraphicsEnvironment.isHeadless()</code>
0426 * returns <code>true</code>
0427 * @see java.awt.GraphicsEnvironment#isHeadless
0428 * @see #getDragEnabled
0429 * @see #setTransferHandler
0430 * @see TransferHandler
0431 * @since 1.4
0432 *
0433 * @beaninfo
0434 * description: determines whether automatic drag handling is enabled
0435 * bound: false
0436 */
0437 public void setDragEnabled(boolean b) {
0438 if (b && GraphicsEnvironment.isHeadless()) {
0439 throw new HeadlessException();
0440 }
0441 dragEnabled = b;
0442 }
0443
0444 /**
0445 * Gets the value of the <code>dragEnabled</code> property.
0446 *
0447 * @return the value of the <code>dragEnabled</code> property
0448 * @see #setDragEnabled
0449 * @since 1.4
0450 */
0451 public boolean getDragEnabled() {
0452 return dragEnabled;
0453 }
0454
0455 // *****************************
0456 // ****** File Operations ******
0457 // *****************************
0458
0459 /**
0460 * Returns the selected file. This can be set either by the
0461 * programmer via <code>setSelectedFile</code> or by a user action, such as
0462 * either typing the filename into the UI or selecting the
0463 * file from a list in the UI.
0464 *
0465 * @see #setSelectedFile
0466 * @return the selected file
0467 */
0468 public File getSelectedFile() {
0469 return selectedFile;
0470 }
0471
0472 /**
0473 * Sets the selected file. If the file's parent directory is
0474 * not the current directory, changes the current directory
0475 * to be the file's parent directory.
0476 *
0477 * @beaninfo
0478 * preferred: true
0479 * bound: true
0480 *
0481 * @see #getSelectedFile
0482 *
0483 * @param file the selected file
0484 */
0485 public void setSelectedFile(File file) {
0486 File oldValue = selectedFile;
0487 selectedFile = file;
0488 if (selectedFile != null) {
0489 if (file.isAbsolute()
0490 && !getFileSystemView().isParent(
0491 getCurrentDirectory(), selectedFile)) {
0492 setCurrentDirectory(selectedFile.getParentFile());
0493 }
0494 if (!isMultiSelectionEnabled() || selectedFiles == null
0495 || selectedFiles.length == 1) {
0496 ensureFileIsVisible(selectedFile);
0497 }
0498 }
0499 firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, oldValue,
0500 selectedFile);
0501 }
0502
0503 /**
0504 * Returns a list of selected files if the file chooser is
0505 * set to allow multiple selection.
0506 */
0507 public File[] getSelectedFiles() {
0508 if (selectedFiles == null) {
0509 return new File[0];
0510 } else {
0511 return (File[]) selectedFiles.clone();
0512 }
0513 }
0514
0515 /**
0516 * Sets the list of selected files if the file chooser is
0517 * set to allow multiple selection.
0518 *
0519 * @beaninfo
0520 * bound: true
0521 * description: The list of selected files if the chooser is in multiple selection mode.
0522 */
0523 public void setSelectedFiles(File[] selectedFiles) {
0524 File[] oldValue = this .selectedFiles;
0525 if (selectedFiles == null || selectedFiles.length == 0) {
0526 selectedFiles = null;
0527 this .selectedFiles = null;
0528 setSelectedFile(null);
0529 } else {
0530 this .selectedFiles = selectedFiles.clone();
0531 setSelectedFile(this .selectedFiles[0]);
0532 }
0533 firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue,
0534 selectedFiles);
0535 }
0536
0537 /**
0538 * Returns the current directory.
0539 *
0540 * @return the current directory
0541 * @see #setCurrentDirectory
0542 */
0543 public File getCurrentDirectory() {
0544 return currentDirectory;
0545 }
0546
0547 /**
0548 * Sets the current directory. Passing in <code>null</code> sets the
0549 * file chooser to point to the user's default directory.
0550 * This default depends on the operating system. It is
0551 * typically the "My Documents" folder on Windows, and the user's
0552 * home directory on Unix.
0553 *
0554 * If the file passed in as <code>currentDirectory</code> is not a
0555 * directory, the parent of the file will be used as the currentDirectory.
0556 * If the parent is not traversable, then it will walk up the parent tree
0557 * until it finds a traversable directory, or hits the root of the
0558 * file system.
0559 *
0560 * @beaninfo
0561 * preferred: true
0562 * bound: true
0563 * description: The directory that the JFileChooser is showing files of.
0564 *
0565 * @param dir the current directory to point to
0566 * @see #getCurrentDirectory
0567 */
0568 public void setCurrentDirectory(File dir) {
0569 File oldValue = currentDirectory;
0570
0571 if (dir != null && !dir.exists()) {
0572 dir = currentDirectory;
0573 }
0574 if (dir == null) {
0575 dir = getFileSystemView().getDefaultDirectory();
0576 }
0577 if (currentDirectory != null) {
0578 /* Verify the toString of object */
0579 if (this .currentDirectory.equals(dir)) {
0580 return;
0581 }
0582 }
0583
0584 File prev = null;
0585 while (!isTraversable(dir) && prev != dir) {
0586 prev = dir;
0587 dir = getFileSystemView().getParentDirectory(dir);
0588 }
0589 currentDirectory = dir;
0590
0591 firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue,
0592 currentDirectory);
0593 }
0594
0595 /**
0596 * Changes the directory to be set to the parent of the
0597 * current directory.
0598 *
0599 * @see #getCurrentDirectory
0600 */
0601 public void changeToParentDirectory() {
0602 selectedFile = null;
0603 File oldValue = getCurrentDirectory();
0604 setCurrentDirectory(getFileSystemView().getParentDirectory(
0605 oldValue));
0606 }
0607
0608 /**
0609 * Tells the UI to rescan its files list from the current directory.
0610 */
0611 public void rescanCurrentDirectory() {
0612 getUI().rescanCurrentDirectory(this );
0613 }
0614
0615 /**
0616 * Makes sure that the specified file is viewable, and
0617 * not hidden.
0618 *
0619 * @param f a File object
0620 */
0621 public void ensureFileIsVisible(File f) {
0622 getUI().ensureFileIsVisible(this , f);
0623 }
0624
0625 // **************************************
0626 // ***** JFileChooser Dialog methods *****
0627 // **************************************
0628
0629 /**
0630 * Pops up an "Open File" file chooser dialog. Note that the
0631 * text that appears in the approve button is determined by
0632 * the L&F.
0633 *
0634 * @param parent the parent component of the dialog,
0635 * can be <code>null</code>;
0636 * see <code>showDialog</code> for details
0637 * @return the return state of the file chooser on popdown:
0638 * <ul>
0639 * <li>JFileChooser.CANCEL_OPTION
0640 * <li>JFileChooser.APPROVE_OPTION
0641 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
0642 * dialog is dismissed
0643 * </ul>
0644 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0645 * returns true.
0646 * @see java.awt.GraphicsEnvironment#isHeadless
0647 * @see #showDialog
0648 */
0649 public int showOpenDialog(Component parent)
0650 throws HeadlessException {
0651 setDialogType(OPEN_DIALOG);
0652 return showDialog(parent, null);
0653 }
0654
0655 /**
0656 * Pops up a "Save File" file chooser dialog. Note that the
0657 * text that appears in the approve button is determined by
0658 * the L&F.
0659 *
0660 * @param parent the parent component of the dialog,
0661 * can be <code>null</code>;
0662 * see <code>showDialog</code> for details
0663 * @return the return state of the file chooser on popdown:
0664 * <ul>
0665 * <li>JFileChooser.CANCEL_OPTION
0666 * <li>JFileChooser.APPROVE_OPTION
0667 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
0668 * dialog is dismissed
0669 * </ul>
0670 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0671 * returns true.
0672 * @see java.awt.GraphicsEnvironment#isHeadless
0673 * @see #showDialog
0674 */
0675 public int showSaveDialog(Component parent)
0676 throws HeadlessException {
0677 setDialogType(SAVE_DIALOG);
0678 return showDialog(parent, null);
0679 }
0680
0681 /**
0682 * Pops a custom file chooser dialog with a custom approve button.
0683 * For example, the following code
0684 * pops up a file chooser with a "Run Application" button
0685 * (instead of the normal "Save" or "Open" button):
0686 * <pre>
0687 * filechooser.showDialog(parentFrame, "Run Application");
0688 * </pre>
0689 *
0690 * Alternatively, the following code does the same thing:
0691 * <pre>
0692 * JFileChooser chooser = new JFileChooser(null);
0693 * chooser.setApproveButtonText("Run Application");
0694 * chooser.showDialog(parentFrame, null);
0695 * </pre>
0696 *
0697 * <!--PENDING(jeff) - the following method should be added to the api:
0698 * showDialog(Component parent);-->
0699 * <!--PENDING(kwalrath) - should specify modality and what
0700 * "depends" means.-->
0701 *
0702 * <p>
0703 *
0704 * The <code>parent</code> argument determines two things:
0705 * the frame on which the open dialog depends and
0706 * the component whose position the look and feel
0707 * should consider when placing the dialog. If the parent
0708 * is a <code>Frame</code> object (such as a <code>JFrame</code>)
0709 * then the dialog depends on the frame and
0710 * the look and feel positions the dialog
0711 * relative to the frame (for example, centered over the frame).
0712 * If the parent is a component, then the dialog
0713 * depends on the frame containing the component,
0714 * and is positioned relative to the component
0715 * (for example, centered over the component).
0716 * If the parent is <code>null</code>, then the dialog depends on
0717 * no visible window, and it's placed in a
0718 * look-and-feel-dependent position
0719 * such as the center of the screen.
0720 *
0721 * @param parent the parent component of the dialog;
0722 * can be <code>null</code>
0723 * @param approveButtonText the text of the <code>ApproveButton</code>
0724 * @return the return state of the file chooser on popdown:
0725 * <ul>
0726 * <li>JFileChooser.CANCEL_OPTION
0727 * <li>JFileChooser.APPROVE_OPTION
0728 * <li>JFileCHooser.ERROR_OPTION if an error occurs or the
0729 * dialog is dismissed
0730 * </ul>
0731 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0732 * returns true.
0733 * @see java.awt.GraphicsEnvironment#isHeadless
0734 */
0735 public int showDialog(Component parent, String approveButtonText)
0736 throws HeadlessException {
0737 if (approveButtonText != null) {
0738 setApproveButtonText(approveButtonText);
0739 setDialogType(CUSTOM_DIALOG);
0740 }
0741 dialog = createDialog(parent);
0742 dialog.addWindowListener(new WindowAdapter() {
0743 public void windowClosing(WindowEvent e) {
0744 returnValue = CANCEL_OPTION;
0745 }
0746 });
0747 returnValue = ERROR_OPTION;
0748 rescanCurrentDirectory();
0749
0750 dialog.show();
0751 firePropertyChange("JFileChooserDialogIsClosingProperty",
0752 dialog, null);
0753 dialog.dispose();
0754 dialog = null;
0755 return returnValue;
0756 }
0757
0758 /**
0759 * Creates and returns a new <code>JDialog</code> wrapping
0760 * <code>this</code> centered on the <code>parent</code>
0761 * in the <code>parent</code>'s frame.
0762 * This method can be overriden to further manipulate the dialog,
0763 * to disable resizing, set the location, etc. Example:
0764 * <pre>
0765 * class MyFileChooser extends JFileChooser {
0766 * protected JDialog createDialog(Component parent) throws HeadlessException {
0767 * JDialog dialog = super.createDialog(parent);
0768 * dialog.setLocation(300, 200);
0769 * dialog.setResizable(false);
0770 * return dialog;
0771 * }
0772 * }
0773 * </pre>
0774 *
0775 * @param parent the parent component of the dialog;
0776 * can be <code>null</code>
0777 * @return a new <code>JDialog</code> containing this instance
0778 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0779 * returns true.
0780 * @see java.awt.GraphicsEnvironment#isHeadless
0781 * @since 1.4
0782 */
0783 protected JDialog createDialog(Component parent)
0784 throws HeadlessException {
0785 String title = getUI().getDialogTitle(this );
0786 putClientProperty(
0787 AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY,
0788 title);
0789
0790 JDialog dialog;
0791 Window window = JOptionPane.getWindowForComponent(parent);
0792 if (window instanceof Frame) {
0793 dialog = new JDialog((Frame) window, title, true);
0794 } else {
0795 dialog = new JDialog((Dialog) window, title, true);
0796 }
0797 dialog.setComponentOrientation(this .getComponentOrientation());
0798
0799 Container contentPane = dialog.getContentPane();
0800 contentPane.setLayout(new BorderLayout());
0801 contentPane.add(this , BorderLayout.CENTER);
0802
0803 if (JDialog.isDefaultLookAndFeelDecorated()) {
0804 boolean supportsWindowDecorations = UIManager
0805 .getLookAndFeel().getSupportsWindowDecorations();
0806 if (supportsWindowDecorations) {
0807 dialog.getRootPane().setWindowDecorationStyle(
0808 JRootPane.FILE_CHOOSER_DIALOG);
0809 }
0810 }
0811 dialog.pack();
0812 dialog.setLocationRelativeTo(parent);
0813
0814 return dialog;
0815 }
0816
0817 // **************************
0818 // ***** Dialog Options *****
0819 // **************************
0820
0821 /**
0822 * Returns the value of the <code>controlButtonsAreShown</code>
0823 * property.
0824 *
0825 * @return the value of the <code>controlButtonsAreShown</code>
0826 * property
0827 *
0828 * @see #setControlButtonsAreShown
0829 * @since 1.3
0830 */
0831 public boolean getControlButtonsAreShown() {
0832 return controlsShown;
0833 }
0834
0835 /**
0836 * Sets the property
0837 * that indicates whether the <i>approve</i> and <i>cancel</i>
0838 * buttons are shown in the file chooser. This property
0839 * is <code>true</code> by default. Look and feels
0840 * that always show these buttons will ignore the value
0841 * of this property.
0842 * This method fires a property-changed event,
0843 * using the string value of
0844 * <code>CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY</code>
0845 * as the name of the property.
0846 *
0847 * @param b <code>false</code> if control buttons should not be
0848 * shown; otherwise, <code>true</code>
0849 *
0850 * @beaninfo
0851 * preferred: true
0852 * bound: true
0853 * description: Sets whether the approve & cancel buttons are shown.
0854 *
0855 * @see #getControlButtonsAreShown
0856 * @see #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY
0857 * @since 1.3
0858 */
0859 public void setControlButtonsAreShown(boolean b) {
0860 if (controlsShown == b) {
0861 return;
0862 }
0863 boolean oldValue = controlsShown;
0864 controlsShown = b;
0865 firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY,
0866 oldValue, controlsShown);
0867 }
0868
0869 /**
0870 * Returns the type of this dialog. The default is
0871 * <code>JFileChooser.OPEN_DIALOG</code>.
0872 *
0873 * @return the type of dialog to be displayed:
0874 * <ul>
0875 * <li>JFileChooser.OPEN_DIALOG
0876 * <li>JFileChooser.SAVE_DIALOG
0877 * <li>JFileChooser.CUSTOM_DIALOG
0878 * </ul>
0879 *
0880 * @see #setDialogType
0881 */
0882 public int getDialogType() {
0883 return dialogType;
0884 }
0885
0886 /**
0887 * Sets the type of this dialog. Use <code>OPEN_DIALOG</code> when you
0888 * want to bring up a file chooser that the user can use to open a file.
0889 * Likewise, use <code>SAVE_DIALOG</code> for letting the user choose
0890 * a file for saving.
0891 * Use <code>CUSTOM_DIALOG</code> when you want to use the file
0892 * chooser in a context other than "Open" or "Save".
0893 * For instance, you might want to bring up a file chooser that allows
0894 * the user to choose a file to execute. Note that you normally would not
0895 * need to set the <code>JFileChooser</code> to use
0896 * <code>CUSTOM_DIALOG</code>
0897 * since a call to <code>setApproveButtonText</code> does this for you.
0898 * The default dialog type is <code>JFileChooser.OPEN_DIALOG</code>.
0899 *
0900 * @param dialogType the type of dialog to be displayed:
0901 * <ul>
0902 * <li>JFileChooser.OPEN_DIALOG
0903 * <li>JFileChooser.SAVE_DIALOG
0904 * <li>JFileChooser.CUSTOM_DIALOG
0905 * </ul>
0906 *
0907 * @exception IllegalArgumentException if <code>dialogType</code> is
0908 * not legal
0909 * @beaninfo
0910 * preferred: true
0911 * bound: true
0912 * description: The type (open, save, custom) of the JFileChooser.
0913 * enum:
0914 * OPEN_DIALOG JFileChooser.OPEN_DIALOG
0915 * SAVE_DIALOG JFileChooser.SAVE_DIALOG
0916 * CUSTOM_DIALOG JFileChooser.CUSTOM_DIALOG
0917 *
0918 * @see #getDialogType
0919 * @see #setApproveButtonText
0920 */
0921 // PENDING(jeff) - fire button text change property
0922 public void setDialogType(int dialogType) {
0923 if (this .dialogType == dialogType) {
0924 return;
0925 }
0926 if (!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || dialogType == CUSTOM_DIALOG)) {
0927 throw new IllegalArgumentException(
0928 "Incorrect Dialog Type: " + dialogType);
0929 }
0930 int oldValue = this .dialogType;
0931 this .dialogType = dialogType;
0932 if (dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) {
0933 setApproveButtonText(null);
0934 }
0935 firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue,
0936 dialogType);
0937 }
0938
0939 /**
0940 * Sets the string that goes in the <code>JFileChooser</code> window's
0941 * title bar.
0942 *
0943 * @param dialogTitle the new <code>String</code> for the title bar
0944 *
0945 * @beaninfo
0946 * preferred: true
0947 * bound: true
0948 * description: The title of the JFileChooser dialog window.
0949 *
0950 * @see #getDialogTitle
0951 *
0952 */
0953 public void setDialogTitle(String dialogTitle) {
0954 String oldValue = this .dialogTitle;
0955 this .dialogTitle = dialogTitle;
0956 if (dialog != null) {
0957 dialog.setTitle(dialogTitle);
0958 }
0959 firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue,
0960 dialogTitle);
0961 }
0962
0963 /**
0964 * Gets the string that goes in the <code>JFileChooser</code>'s titlebar.
0965 *
0966 * @see #setDialogTitle
0967 */
0968 public String getDialogTitle() {
0969 return dialogTitle;
0970 }
0971
0972 // ************************************
0973 // ***** JFileChooser View Options *****
0974 // ************************************
0975
0976 /**
0977 * Sets the tooltip text used in the <code>ApproveButton</code>.
0978 * If <code>null</code>, the UI object will determine the button's text.
0979 *
0980 * @beaninfo
0981 * preferred: true
0982 * bound: true
0983 * description: The tooltip text for the ApproveButton.
0984 *
0985 * @param toolTipText the tooltip text for the approve button
0986 * @see #setApproveButtonText
0987 * @see #setDialogType
0988 * @see #showDialog
0989 */
0990 public void setApproveButtonToolTipText(String toolTipText) {
0991 if (approveButtonToolTipText == toolTipText) {
0992 return;
0993 }
0994 String oldValue = approveButtonToolTipText;
0995 approveButtonToolTipText = toolTipText;
0996 firePropertyChange(
0997 APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY,
0998 oldValue, approveButtonToolTipText);
0999 }
1000
1001 /**
1002 * Returns the tooltip text used in the <code>ApproveButton</code>.
1003 * If <code>null</code>, the UI object will determine the button's text.
1004 *
1005 * @return the tooltip text used for the approve button
1006 *
1007 * @see #setApproveButtonText
1008 * @see #setDialogType
1009 * @see #showDialog
1010 */
1011 public String getApproveButtonToolTipText() {
1012 return approveButtonToolTipText;
1013 }
1014
1015 /**
1016 * Returns the approve button's mnemonic.
1017 * @return an integer value for the mnemonic key
1018 *
1019 * @see #setApproveButtonMnemonic
1020 */
1021 public int getApproveButtonMnemonic() {
1022 return approveButtonMnemonic;
1023 }
1024
1025 /**
1026 * Sets the approve button's mnemonic using a numeric keycode.
1027 *
1028 * @param mnemonic an integer value for the mnemonic key
1029 *
1030 * @beaninfo
1031 * preferred: true
1032 * bound: true
1033 * description: The mnemonic key accelerator for the ApproveButton.
1034 *
1035 * @see #getApproveButtonMnemonic
1036 */
1037 public void setApproveButtonMnemonic(int mnemonic) {
1038 if (approveButtonMnemonic == mnemonic) {
1039 return;
1040 }
1041 int oldValue = approveButtonMnemonic;
1042 approveButtonMnemonic = mnemonic;
1043 firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY,
1044 oldValue, approveButtonMnemonic);
1045 }
1046
1047 /**
1048 * Sets the approve button's mnemonic using a character.
1049 * @param mnemonic a character value for the mnemonic key
1050 *
1051 * @see #getApproveButtonMnemonic
1052 */
1053 public void setApproveButtonMnemonic(char mnemonic) {
1054 int vk = (int) mnemonic;
1055 if (vk >= 'a' && vk <= 'z') {
1056 vk -= ('a' - 'A');
1057 }
1058 setApproveButtonMnemonic(vk);
1059 }
1060
1061 /**
1062 * Sets the text used in the <code>ApproveButton</code> in the
1063 * <code>FileChooserUI</code>.
1064 *
1065 * @beaninfo
1066 * preferred: true
1067 * bound: true
1068 * description: The text that goes in the ApproveButton.
1069 *
1070 * @param approveButtonText the text used in the <code>ApproveButton</code>
1071 *
1072 * @see #getApproveButtonText
1073 * @see #setDialogType
1074 * @see #showDialog
1075 */
1076 // PENDING(jeff) - have ui set this on dialog type change
1077 public void setApproveButtonText(String approveButtonText) {
1078 if (this .approveButtonText == approveButtonText) {
1079 return;
1080 }
1081 String oldValue = this .approveButtonText;
1082 this .approveButtonText = approveButtonText;
1083 firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY,
1084 oldValue, approveButtonText);
1085 }
1086
1087 /**
1088 * Returns the text used in the <code>ApproveButton</code> in the
1089 * <code>FileChooserUI</code>.
1090 * If <code>null</code>, the UI object will determine the button's text.
1091 *
1092 * Typically, this would be "Open" or "Save".
1093 *
1094 * @return the text used in the <code>ApproveButton</code>
1095 *
1096 * @see #setApproveButtonText
1097 * @see #setDialogType
1098 * @see #showDialog
1099 */
1100 public String getApproveButtonText() {
1101 return approveButtonText;
1102 }
1103
1104 /**
1105 * Gets the list of user choosable file filters.
1106 *
1107 * @return a <code>FileFilter</code> array containing all the choosable
1108 * file filters
1109 *
1110 * @see #addChoosableFileFilter
1111 * @see #removeChoosableFileFilter
1112 * @see #resetChoosableFileFilters
1113 */
1114 public FileFilter[] getChoosableFileFilters() {
1115 FileFilter[] filterArray = new FileFilter[filters.size()];
1116 filters.copyInto(filterArray);
1117 return filterArray;
1118 }
1119
1120 /**
1121 * Adds a filter to the list of user choosable file filters.
1122 * For information on setting the file selection mode, see
1123 * {@link #setFileSelectionMode setFileSelectionMode}.
1124 *
1125 * @param filter the <code>FileFilter</code> to add to the choosable file
1126 * filter list
1127 *
1128 * @beaninfo
1129 * preferred: true
1130 * bound: true
1131 * description: Adds a filter to the list of user choosable file filters.
1132 *
1133 * @see #getChoosableFileFilters
1134 * @see #removeChoosableFileFilter
1135 * @see #resetChoosableFileFilters
1136 * @see #setFileSelectionMode
1137 */
1138 public void addChoosableFileFilter(FileFilter filter) {
1139 if (filter != null && !filters.contains(filter)) {
1140 FileFilter[] oldValue = getChoosableFileFilters();
1141 filters.addElement(filter);
1142 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY,
1143 oldValue, getChoosableFileFilters());
1144 if (fileFilter == null && filters.size() == 1) {
1145 setFileFilter(filter);
1146 }
1147 }
1148 }
1149
1150 /**
1151 * Removes a filter from the list of user choosable file filters. Returns
1152 * true if the file filter was removed.
1153 *
1154 * @see #addChoosableFileFilter
1155 * @see #getChoosableFileFilters
1156 * @see #resetChoosableFileFilters
1157 */
1158 public boolean removeChoosableFileFilter(FileFilter f) {
1159 if (filters.contains(f)) {
1160 if (getFileFilter() == f) {
1161 setFileFilter(null);
1162 }
1163 FileFilter[] oldValue = getChoosableFileFilters();
1164 filters.removeElement(f);
1165 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY,
1166 oldValue, getChoosableFileFilters());
1167 return true;
1168 } else {
1169 return false;
1170 }
1171 }
1172
1173 /**
1174 * Resets the choosable file filter list to its starting state. Normally,
1175 * this removes all added file filters while leaving the
1176 * <code>AcceptAll</code> file filter.
1177 *
1178 * @see #addChoosableFileFilter
1179 * @see #getChoosableFileFilters
1180 * @see #removeChoosableFileFilter
1181 */
1182 public void resetChoosableFileFilters() {
1183 FileFilter[] oldValue = getChoosableFileFilters();
1184 setFileFilter(null);
1185 filters.removeAllElements();
1186 if (isAcceptAllFileFilterUsed()) {
1187 addChoosableFileFilter(getAcceptAllFileFilter());
1188 }
1189 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY,
1190 oldValue, getChoosableFileFilters());
1191 }
1192
1193 /**
1194 * Returns the <code>AcceptAll</code> file filter.
1195 * For example, on Microsoft Windows this would be All Files (*.*).
1196 */
1197 public FileFilter getAcceptAllFileFilter() {
1198 FileFilter filter = null;
1199 if (getUI() != null) {
1200 filter = getUI().getAcceptAllFileFilter(this );
1201 }
1202 return filter;
1203 }
1204
1205 /**
1206 * Returns whether the <code>AcceptAll FileFilter</code> is used.
1207 * @return true if the <code>AcceptAll FileFilter</code> is used
1208 * @see #setAcceptAllFileFilterUsed
1209 * @since 1.3
1210 */
1211 public boolean isAcceptAllFileFilterUsed() {
1212 return useAcceptAllFileFilter;
1213 }
1214
1215 /**
1216 * Determines whether the <code>AcceptAll FileFilter</code> is used
1217 * as an available choice in the choosable filter list.
1218 * If false, the <code>AcceptAll</code> file filter is removed from
1219 * the list of available file filters.
1220 * If true, the <code>AcceptAll</code> file filter will become the
1221 * the actively used file filter.
1222 *
1223 * @beaninfo
1224 * preferred: true
1225 * bound: true
1226 * description: Sets whether the AcceptAll FileFilter is used as an available choice in the choosable filter list.
1227 *
1228 * @see #isAcceptAllFileFilterUsed
1229 * @see #getAcceptAllFileFilter
1230 * @see #setFileFilter
1231 * @since 1.3
1232 */
1233 public void setAcceptAllFileFilterUsed(boolean b) {
1234 boolean oldValue = useAcceptAllFileFilter;
1235 useAcceptAllFileFilter = b;
1236 if (!b) {
1237 removeChoosableFileFilter(getAcceptAllFileFilter());
1238 } else {
1239 removeChoosableFileFilter(getAcceptAllFileFilter());
1240 addChoosableFileFilter(getAcceptAllFileFilter());
1241 }
1242 firePropertyChange(
1243 ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY, oldValue,
1244 useAcceptAllFileFilter);
1245 }
1246
1247 /**
1248 * Returns the accessory component.
1249 *
1250 * @return this JFileChooser's accessory component, or null
1251 * @see #setAccessory
1252 */
1253 public JComponent getAccessory() {
1254 return accessory;
1255 }
1256
1257 /**
1258 * Sets the accessory component. An accessory is often used to show a
1259 * preview image of the selected file; however, it can be used for anything
1260 * that the programmer wishes, such as extra custom file chooser controls.
1261 *
1262 * <p>
1263 * Note: if there was a previous accessory, you should unregister
1264 * any listeners that the accessory might have registered with the
1265 * file chooser.
1266 *
1267 * @beaninfo
1268 * preferred: true
1269 * bound: true
1270 * description: Sets the accessory component on the JFileChooser.
1271 */
1272 public void setAccessory(JComponent newAccessory) {
1273 JComponent oldValue = accessory;
1274 accessory = newAccessory;
1275 firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue,
1276 accessory);
1277 }
1278
1279 /**
1280 * Sets the <code>JFileChooser</code> to allow the user to just
1281 * select files, just select
1282 * directories, or select both files and directories. The default is
1283 * <code>JFilesChooser.FILES_ONLY</code>.
1284 *
1285 * @param mode the type of files to be displayed:
1286 * <ul>
1287 * <li>JFileChooser.FILES_ONLY
1288 * <li>JFileChooser.DIRECTORIES_ONLY
1289 * <li>JFileChooser.FILES_AND_DIRECTORIES
1290 * </ul>
1291 *
1292 * @exception IllegalArgumentException if <code>mode</code> is an
1293 * illegal file selection mode
1294 * @beaninfo
1295 * preferred: true
1296 * bound: true
1297 * description: Sets the types of files that the JFileChooser can choose.
1298 * enum: FILES_ONLY JFileChooser.FILES_ONLY
1299 * DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY
1300 * FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES
1301 *
1302 *
1303 * @see #getFileSelectionMode
1304 */
1305 public void setFileSelectionMode(int mode) {
1306 if (fileSelectionMode == mode) {
1307 return;
1308 }
1309
1310 if ((mode == FILES_ONLY) || (mode == DIRECTORIES_ONLY)
1311 || (mode == FILES_AND_DIRECTORIES)) {
1312 int oldValue = fileSelectionMode;
1313 fileSelectionMode = mode;
1314 firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY,
1315 oldValue, fileSelectionMode);
1316 } else {
1317 throw new IllegalArgumentException(
1318 "Incorrect Mode for file selection: " + mode);
1319 }
1320 }
1321
1322 /**
1323 * Returns the current file-selection mode. The default is
1324 * <code>JFilesChooser.FILES_ONLY</code>.
1325 *
1326 * @return the type of files to be displayed, one of the following:
1327 * <ul>
1328 * <li>JFileChooser.FILES_ONLY
1329 * <li>JFileChooser.DIRECTORIES_ONLY
1330 * <li>JFileChooser.FILES_AND_DIRECTORIES
1331 * </ul>
1332 * @see #setFileSelectionMode
1333 */
1334 public int getFileSelectionMode() {
1335 return fileSelectionMode;
1336 }
1337
1338 /**
1339 * Convenience call that determines if files are selectable based on the
1340 * current file selection mode.
1341 *
1342 * @see #setFileSelectionMode
1343 * @see #getFileSelectionMode
1344 */
1345 public boolean isFileSelectionEnabled() {
1346 return ((fileSelectionMode == FILES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
1347 }
1348
1349 /**
1350 * Convenience call that determines if directories are selectable based
1351 * on the current file selection mode.
1352 *
1353 * @see #setFileSelectionMode
1354 * @see #getFileSelectionMode
1355 */
1356 public boolean isDirectorySelectionEnabled() {
1357 return ((fileSelectionMode == DIRECTORIES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
1358 }
1359
1360 /**
1361 * Sets the file chooser to allow multiple file selections.
1362 *
1363 * @param b true if multiple files may be selected
1364 * @beaninfo
1365 * bound: true
1366 * description: Sets multiple file selection mode.
1367 *
1368 * @see #isMultiSelectionEnabled
1369 */
1370 public void setMultiSelectionEnabled(boolean b) {
1371 if (multiSelectionEnabled == b) {
1372 return;
1373 }
1374 boolean oldValue = multiSelectionEnabled;
1375 multiSelectionEnabled = b;
1376 firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY,
1377 oldValue, multiSelectionEnabled);
1378 }
1379
1380 /**
1381 * Returns true if multiple files can be selected.
1382 * @return true if multiple files can be selected
1383 * @see #setMultiSelectionEnabled
1384 */
1385 public boolean isMultiSelectionEnabled() {
1386 return multiSelectionEnabled;
1387 }
1388
1389 /**
1390 * Returns true if hidden files are not shown in the file chooser;
1391 * otherwise, returns false.
1392 *
1393 * @return the status of the file hiding property
1394 * @see #setFileHidingEnabled
1395 */
1396 public boolean isFileHidingEnabled() {
1397 return useFileHiding;
1398 }
1399
1400 /**
1401 * Sets file hiding on or off. If true, hidden files are not shown
1402 * in the file chooser. The job of determining which files are
1403 * shown is done by the <code>FileView</code>.
1404 *
1405 * @beaninfo
1406 * preferred: true
1407 * bound: true
1408 * description: Sets file hiding on or off.
1409 *
1410 * @param b the boolean value that determines whether file hiding is
1411 * turned on
1412 * @see #isFileHidingEnabled
1413 */
1414 public void setFileHidingEnabled(boolean b) {
1415 // Dump showFilesListener since we'll ignore it from now on
1416 if (showFilesListener != null) {
1417 Toolkit.getDefaultToolkit().removePropertyChangeListener(
1418 SHOW_HIDDEN_PROP, showFilesListener);
1419 showFilesListener = null;
1420 }
1421 boolean oldValue = useFileHiding;
1422 useFileHiding = b;
1423 firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue,
1424 useFileHiding);
1425 }
1426
1427 /**
1428 * Sets the current file filter. The file filter is used by the
1429 * file chooser to filter out files from the user's view.
1430 *
1431 * @beaninfo
1432 * preferred: true
1433 * bound: true
1434 * description: Sets the File Filter used to filter out files of type.
1435 *
1436 * @param filter the new current file filter to use
1437 * @see #getFileFilter
1438 */
1439 public void setFileFilter(FileFilter filter) {
1440 FileFilter oldValue = fileFilter;
1441 fileFilter = filter;
1442 if (filter != null) {
1443 if (isMultiSelectionEnabled() && selectedFiles != null
1444 && selectedFiles.length > 0) {
1445 Vector fList = new Vector();
1446 boolean failed = false;
1447 for (int i = 0; i < selectedFiles.length; i++) {
1448 if (filter.accept(selectedFiles[i])) {
1449 fList.add(selectedFiles[i]);
1450 } else {
1451 failed = true;
1452 }
1453 }
1454 if (failed) {
1455 setSelectedFiles((fList.size() == 0) ? null
1456 : (File[]) fList.toArray(new File[fList
1457 .size()]));
1458 }
1459 } else if (selectedFile != null
1460 && !filter.accept(selectedFile)) {
1461 setSelectedFile(null);
1462 }
1463 }
1464 firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue,
1465 fileFilter);
1466 }
1467
1468 /**
1469 * Returns the currently selected file filter.
1470 *
1471 * @return the current file filter
1472 * @see #setFileFilter
1473 * @see #addChoosableFileFilter
1474 */
1475 public FileFilter getFileFilter() {
1476 return fileFilter;
1477 }
1478
1479 /**
1480 * Sets the file view to used to retrieve UI information, such as
1481 * the icon that represents a file or the type description of a file.
1482 *
1483 * @beaninfo
1484 * preferred: true
1485 * bound: true
1486 * description: Sets the File View used to get file type information.
1487 *
1488 * @see #getFileView
1489 */
1490 public void setFileView(FileView fileView) {
1491 FileView oldValue = this .fileView;
1492 this .fileView = fileView;
1493 firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue,
1494 fileView);
1495 }
1496
1497 /**
1498 * Returns the current file view.
1499 *
1500 * @see #setFileView
1501 */
1502 public FileView getFileView() {
1503 return fileView;
1504 }
1505
1506 // ******************************
1507 // *****FileView delegation *****
1508 // ******************************
1509
1510 // NOTE: all of the following methods attempt to delegate
1511 // first to the client set fileView, and if <code>null</code> is returned
1512 // (or there is now client defined fileView) then calls the
1513 // UI's default fileView.
1514
1515 /**
1516 * Returns the filename.
1517 * @param f the <code>File</code>
1518 * @return the <code>String</code> containing the filename for
1519 * <code>f</code>
1520 * @see FileView#getName
1521 */
1522 public String getName(File f) {
1523 String filename = null;
1524 if (f != null) {
1525 if (getFileView() != null) {
1526 filename = getFileView().getName(f);
1527 }
1528 if (filename == null && uiFileView != null) {
1529 filename = uiFileView.getName(f);
1530 }
1531 }
1532 return filename;
1533 }
1534
1535 /**
1536 * Returns the file description.
1537 * @param f the <code>File</code>
1538 * @return the <code>String</code> containing the file description for
1539 * <code>f</code>
1540 * @see FileView#getDescription
1541 */
1542 public String getDescription(File f) {
1543 String description = null;
1544 if (f != null) {
1545 if (getFileView() != null) {
1546 description = getFileView().getDescription(f);
1547 }
1548 if (description == null && uiFileView != null) {
1549 description = uiFileView.getDescription(f);
1550 }
1551 }
1552 return description;
1553 }
1554
1555 /**
1556 * Returns the file type.
1557 * @param f the <code>File</code>
1558 * @return the <code>String</code> containing the file type description for
1559 * <code>f</code>
1560 * @see FileView#getTypeDescription
1561 */
1562 public String getTypeDescription(File f) {
1563 String typeDescription = null;
1564 if (f != null) {
1565 if (getFileView() != null) {
1566 typeDescription = getFileView().getTypeDescription(f);
1567 }
1568 if (typeDescription == null && uiFileView != null) {
1569 typeDescription = uiFileView.getTypeDescription(f);
1570 }
1571 }
1572 return typeDescription;
1573 }
1574
1575 /**
1576 * Returns the icon for this file or type of file, depending
1577 * on the system.
1578 * @param f the <code>File</code>
1579 * @return the <code>Icon</code> for this file, or type of file
1580 * @see FileView#getIcon
1581 */
1582 public Icon getIcon(File f) {
1583 Icon icon = null;
1584 if (f != null) {
1585 if (getFileView() != null) {
1586 icon = getFileView().getIcon(f);
1587 }
1588 if (icon == null && uiFileView != null) {
1589 icon = uiFileView.getIcon(f);
1590 }
1591 }
1592 return icon;
1593 }
1594
1595 /**
1596 * Returns true if the file (directory) can be visited.
1597 * Returns false if the directory cannot be traversed.
1598 * @param f the <code>File</code>
1599 * @return true if the file/directory can be traversed, otherwise false
1600 * @see FileView#isTraversable
1601 */
1602 public boolean isTraversable(File f) {
1603 Boolean traversable = null;
1604 if (f != null) {
1605 if (getFileView() != null) {
1606 traversable = getFileView().isTraversable(f);
1607 }
1608 if (traversable == null && uiFileView != null) {
1609 traversable = uiFileView.isTraversable(f);
1610 }
1611 if (traversable == null) {
1612 traversable = getFileSystemView().isTraversable(f);
1613 }
1614 }
1615 return (traversable != null && traversable.booleanValue());
1616 }
1617
1618 /**
1619 * Returns true if the file should be displayed.
1620 * @param f the <code>File</code>
1621 * @return true if the file should be displayed, otherwise false
1622 * @see FileFilter#accept
1623 */
1624 public boolean accept(File f) {
1625 boolean shown = true;
1626 if (f != null && fileFilter != null) {
1627 shown = fileFilter.accept(f);
1628 }
1629 return shown;
1630 }
1631
1632 /**
1633 * Sets the file system view that the <code>JFileChooser</code> uses for
1634 * accessing and creating file system resources, such as finding
1635 * the floppy drive and getting a list of root drives.
1636 * @param fsv the new <code>FileSystemView</code>
1637 *
1638 * @beaninfo
1639 * expert: true
1640 * bound: true
1641 * description: Sets the FileSytemView used to get filesystem information.
1642 *
1643 * @see FileSystemView
1644 */
1645 public void setFileSystemView(FileSystemView fsv) {
1646 FileSystemView oldValue = fileSystemView;
1647 fileSystemView = fsv;
1648 firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue,
1649 fileSystemView);
1650 }
1651
1652 /**
1653 * Returns the file system view.
1654 * @return the <code>FileSystemView</code> object
1655 * @see #setFileSystemView
1656 */
1657 public FileSystemView getFileSystemView() {
1658 return fileSystemView;
1659 }
1660
1661 // **************************
1662 // ***** Event Handling *****
1663 // **************************
1664
1665 /**
1666 * Called by the UI when the user hits the Approve button
1667 * (labeled "Open" or "Save", by default). This can also be
1668 * called by the programmer.
1669 * This method causes an action event to fire
1670 * with the command string equal to
1671 * <code>APPROVE_SELECTION</code>.
1672 *
1673 * @see #APPROVE_SELECTION
1674 */
1675 public void approveSelection() {
1676 returnValue = APPROVE_OPTION;
1677 if (dialog != null) {
1678 dialog.setVisible(false);
1679 }
1680 fireActionPerformed(APPROVE_SELECTION);
1681 }
1682
1683 /**
1684 * Called by the UI when the user chooses the Cancel button.
1685 * This can also be called by the programmer.
1686 * This method causes an action event to fire
1687 * with the command string equal to
1688 * <code>CANCEL_SELECTION</code>.
1689 *
1690 * @see #CANCEL_SELECTION
1691 */
1692 public void cancelSelection() {
1693 returnValue = CANCEL_OPTION;
1694 if (dialog != null) {
1695 dialog.setVisible(false);
1696 }
1697 fireActionPerformed(CANCEL_SELECTION);
1698 }
1699
1700 /**
1701 * Adds an <code>ActionListener</code> to the file chooser.
1702 *
1703 * @param l the listener to be added
1704 *
1705 * @see #approveSelection
1706 * @see #cancelSelection
1707 */
1708 public void addActionListener(ActionListener l) {
1709 listenerList.add(ActionListener.class, l);
1710 }
1711
1712 /**
1713 * Removes an <code>ActionListener</code> from the file chooser.
1714 *
1715 * @param l the listener to be removed
1716 *
1717 * @see #addActionListener
1718 */
1719 public void removeActionListener(ActionListener l) {
1720 listenerList.remove(ActionListener.class, l);
1721 }
1722
1723 /**
1724 * Returns an array of all the action listeners
1725 * registered on this file chooser.
1726 *
1727 * @return all of this file chooser's <code>ActionListener</code>s
1728 * or an empty
1729 * array if no action listeners are currently registered
1730 *
1731 * @see #addActionListener
1732 * @see #removeActionListener
1733 *
1734 * @since 1.4
1735 */
1736 public ActionListener[] getActionListeners() {
1737 return (ActionListener[]) listenerList
1738 .getListeners(ActionListener.class);
1739 }
1740
1741 /**
1742 * Notifies all listeners that have registered interest for
1743 * notification on this event type. The event instance
1744 * is lazily created using the <code>command</code> parameter.
1745 *
1746 * @see EventListenerList
1747 */
1748 protected void fireActionPerformed(String command) {
1749 // Guaranteed to return a non-null array
1750 Object[] listeners = listenerList.getListenerList();
1751 long mostRecentEventTime = EventQueue.getMostRecentEventTime();
1752 int modifiers = 0;
1753 AWTEvent currentEvent = EventQueue.getCurrentEvent();
1754 if (currentEvent instanceof InputEvent) {
1755 modifiers = ((InputEvent) currentEvent).getModifiers();
1756 } else if (currentEvent instanceof ActionEvent) {
1757 modifiers = ((ActionEvent) currentEvent).getModifiers();
1758 }
1759 ActionEvent e = null;
1760 // Process the listeners last to first, notifying
1761 // those that are interested in this event
1762 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1763 if (listeners[i] == ActionListener.class) {
1764 // Lazily create the event:
1765 if (e == null) {
1766 e = new ActionEvent(this ,
1767 ActionEvent.ACTION_PERFORMED, command,
1768 mostRecentEventTime, modifiers);
1769 }
1770 ((ActionListener) listeners[i + 1]).actionPerformed(e);
1771 }
1772 }
1773 }
1774
1775 private static class WeakPCL implements PropertyChangeListener {
1776 WeakReference<JFileChooser> jfcRef;
1777
1778 public WeakPCL(JFileChooser jfc) {
1779 jfcRef = new WeakReference(jfc);
1780 }
1781
1782 public void propertyChange(PropertyChangeEvent ev) {
1783 assert ev.getPropertyName().equals(SHOW_HIDDEN_PROP);
1784 JFileChooser jfc = jfcRef.get();
1785 if (jfc == null) {
1786 // Our JFileChooser is no longer around, so we no longer need to
1787 // listen for PropertyChangeEvents.
1788 Toolkit.getDefaultToolkit()
1789 .removePropertyChangeListener(SHOW_HIDDEN_PROP,
1790 this );
1791 } else {
1792 boolean oldValue = jfc.useFileHiding;
1793 jfc.useFileHiding = !((Boolean) ev.getNewValue())
1794 .booleanValue();
1795 jfc.firePropertyChange(FILE_HIDING_CHANGED_PROPERTY,
1796 oldValue, jfc.useFileHiding);
1797 }
1798 }
1799 }
1800
1801 // *********************************
1802 // ***** Pluggable L&F methods *****
1803 // *********************************
1804
1805 /**
1806 * Resets the UI property to a value from the current look and feel.
1807 *
1808 * @see JComponent#updateUI
1809 */
1810 public void updateUI() {
1811 if (isAcceptAllFileFilterUsed()) {
1812 removeChoosableFileFilter(getAcceptAllFileFilter());
1813 }
1814 FileChooserUI ui = ((FileChooserUI) UIManager.getUI(this ));
1815 if (fileSystemView == null) {
1816 // We were probably deserialized
1817 setFileSystemView(FileSystemView.getFileSystemView());
1818 }
1819 setUI(ui);
1820
1821 uiFileView = getUI().getFileView(this );
1822 if (isAcceptAllFileFilterUsed()) {
1823 addChoosableFileFilter(getAcceptAllFileFilter());
1824 }
1825 }
1826
1827 /**
1828 * Returns a string that specifies the name of the L&F class
1829 * that renders this component.
1830 *
1831 * @return the string "FileChooserUI"
1832 * @see JComponent#getUIClassID
1833 * @see UIDefaults#getUI
1834 * @beaninfo
1835 * expert: true
1836 * description: A string that specifies the name of the L&F class.
1837 */
1838 public String getUIClassID() {
1839 return uiClassID;
1840 }
1841
1842 /**
1843 * Gets the UI object which implements the L&F for this component.
1844 *
1845 * @return the FileChooserUI object that implements the FileChooserUI L&F
1846 */
1847 public FileChooserUI getUI() {
1848 return (FileChooserUI) ui;
1849 }
1850
1851 /**
1852 * See <code>readObject</code> and <code>writeObject</code> in
1853 * <code>JComponent</code> for more
1854 * information about serialization in Swing.
1855 */
1856 private void readObject(java.io.ObjectInputStream in)
1857 throws IOException, ClassNotFoundException {
1858 in.defaultReadObject();
1859 installShowFilesListener();
1860 }
1861
1862 /**
1863 * See <code>readObject</code> and <code>writeObject</code> in
1864 * <code>JComponent</code> for more
1865 * information about serialization in Swing.
1866 */
1867 private void writeObject(ObjectOutputStream s) throws IOException {
1868 FileSystemView fsv = null;
1869
1870 if (isAcceptAllFileFilterUsed()) {
1871 //The AcceptAllFileFilter is UI specific, it will be reset by
1872 //updateUI() after deserialization
1873 removeChoosableFileFilter(getAcceptAllFileFilter());
1874 }
1875 if (fileSystemView.equals(FileSystemView.getFileSystemView())) {
1876 //The default FileSystemView is platform specific, it will be
1877 //reset by updateUI() after deserialization
1878 fsv = fileSystemView;
1879 fileSystemView = null;
1880 }
1881 s.defaultWriteObject();
1882 if (fsv != null) {
1883 fileSystemView = fsv;
1884 }
1885 if (isAcceptAllFileFilterUsed()) {
1886 addChoosableFileFilter(getAcceptAllFileFilter());
1887 }
1888 if (getUIClassID().equals(uiClassID)) {
1889 byte count = JComponent.getWriteObjCounter(this );
1890 JComponent.setWriteObjCounter(this , --count);
1891 if (count == 0 && ui != null) {
1892 ui.installUI(this );
1893 }
1894 }
1895 }
1896
1897 /**
1898 * Returns a string representation of this <code>JFileChooser</code>.
1899 * This method
1900 * is intended to be used only for debugging purposes, and the
1901 * content and format of the returned string may vary between
1902 * implementations. The returned string may be empty but may not
1903 * be <code>null</code>.
1904 *
1905 * @return a string representation of this <code>JFileChooser</code>
1906 */
1907 protected String paramString() {
1908 String approveButtonTextString = (approveButtonText != null ? approveButtonText
1909 : "");
1910 String dialogTitleString = (dialogTitle != null ? dialogTitle
1911 : "");
1912 String dialogTypeString;
1913 if (dialogType == OPEN_DIALOG) {
1914 dialogTypeString = "OPEN_DIALOG";
1915 } else if (dialogType == SAVE_DIALOG) {
1916 dialogTypeString = "SAVE_DIALOG";
1917 } else if (dialogType == CUSTOM_DIALOG) {
1918 dialogTypeString = "CUSTOM_DIALOG";
1919 } else
1920 dialogTypeString = "";
1921 String returnValueString;
1922 if (returnValue == CANCEL_OPTION) {
1923 returnValueString = "CANCEL_OPTION";
1924 } else if (returnValue == APPROVE_OPTION) {
1925 returnValueString = "APPROVE_OPTION";
1926 } else if (returnValue == ERROR_OPTION) {
1927 returnValueString = "ERROR_OPTION";
1928 } else
1929 returnValueString = "";
1930 String useFileHidingString = (useFileHiding ? "true" : "false");
1931 String fileSelectionModeString;
1932 if (fileSelectionMode == FILES_ONLY) {
1933 fileSelectionModeString = "FILES_ONLY";
1934 } else if (fileSelectionMode == DIRECTORIES_ONLY) {
1935 fileSelectionModeString = "DIRECTORIES_ONLY";
1936 } else if (fileSelectionMode == FILES_AND_DIRECTORIES) {
1937 fileSelectionModeString = "FILES_AND_DIRECTORIES";
1938 } else
1939 fileSelectionModeString = "";
1940 String currentDirectoryString = (currentDirectory != null ? currentDirectory
1941 .toString()
1942 : "");
1943 String selectedFileString = (selectedFile != null ? selectedFile
1944 .toString()
1945 : "");
1946
1947 return super .paramString() + ",approveButtonText="
1948 + approveButtonTextString + ",currentDirectory="
1949 + currentDirectoryString + ",dialogTitle="
1950 + dialogTitleString + ",dialogType=" + dialogTypeString
1951 + ",fileSelectionMode=" + fileSelectionModeString
1952 + ",returnValue=" + returnValueString
1953 + ",selectedFile=" + selectedFileString
1954 + ",useFileHiding=" + useFileHidingString;
1955 }
1956
1957 /////////////////
1958 // Accessibility support
1959 ////////////////
1960
1961 protected AccessibleContext accessibleContext = null;
1962
1963 /**
1964 * Gets the AccessibleContext associated with this JFileChooser.
1965 * For file choosers, the AccessibleContext takes the form of an
1966 * AccessibleJFileChooser.
1967 * A new AccessibleJFileChooser instance is created if necessary.
1968 *
1969 * @return an AccessibleJFileChooser that serves as the
1970 * AccessibleContext of this JFileChooser
1971 */
1972 public AccessibleContext getAccessibleContext() {
1973 if (accessibleContext == null) {
1974 accessibleContext = new AccessibleJFileChooser();
1975 }
1976 return accessibleContext;
1977 }
1978
1979 /**
1980 * This class implements accessibility support for the
1981 * <code>JFileChooser</code> class. It provides an implementation of the
1982 * Java Accessibility API appropriate to file chooser user-interface
1983 * elements.
1984 */
1985 protected class AccessibleJFileChooser extends AccessibleJComponent {
1986
1987 /**
1988 * Gets the role of this object.
1989 *
1990 * @return an instance of AccessibleRole describing the role of the
1991 * object
1992 * @see AccessibleRole
1993 */
1994 public AccessibleRole getAccessibleRole() {
1995 return AccessibleRole.FILE_CHOOSER;
1996 }
1997
1998 } // inner class AccessibleJFileChooser
1999
2000 }
|