| /* |
| * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package javax.swing; |
| |
| import javax.swing.event.*; |
| import javax.swing.filechooser.*; |
| import javax.swing.plaf.FileChooserUI; |
| |
| import javax.accessibility.*; |
| |
| import java.io.File; |
| import java.io.ObjectOutputStream; |
| import java.io.IOException; |
| |
| import java.util.Vector; |
| import java.awt.AWTEvent; |
| import java.awt.Component; |
| import java.awt.Container; |
| import java.awt.BorderLayout; |
| import java.awt.Window; |
| import java.awt.Dialog; |
| import java.awt.Frame; |
| import java.awt.GraphicsEnvironment; |
| import java.awt.HeadlessException; |
| import java.awt.EventQueue; |
| import java.awt.Toolkit; |
| import java.awt.event.*; |
| import java.beans.JavaBean; |
| import java.beans.BeanProperty; |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeEvent; |
| import java.io.InvalidObjectException; |
| import java.io.ObjectInputStream; |
| import java.lang.ref.WeakReference; |
| |
| /** |
| * <code>JFileChooser</code> provides a simple mechanism for the user to |
| * choose a file. |
| * For information about using <code>JFileChooser</code>, see |
| * <a |
| href="http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html">How to Use File Choosers</a>, |
| * a section in <em>The Java Tutorial</em>. |
| * |
| * <p> |
| * |
| * The following code pops up a file chooser for the user's home directory that |
| * sees only .jpg and .gif images: |
| * <pre> |
| * JFileChooser chooser = new JFileChooser(); |
| * FileNameExtensionFilter filter = new FileNameExtensionFilter( |
| * "JPG & GIF Images", "jpg", "gif"); |
| * chooser.setFileFilter(filter); |
| * int returnVal = chooser.showOpenDialog(parent); |
| * if(returnVal == JFileChooser.APPROVE_OPTION) { |
| * System.out.println("You chose to open this file: " + |
| * chooser.getSelectedFile().getName()); |
| * } |
| * </pre> |
| * <p> |
| * <strong>Warning:</strong> Swing is not thread safe. For more |
| * information see <a |
| * href="package-summary.html#threading">Swing's Threading |
| * Policy</a>. |
| * |
| * @author Jeff Dinkins |
| * @since 1.2 |
| */ |
| @JavaBean(defaultProperty = "UI", description = "A component which allows for the interactive selection of a file.") |
| @SwingContainer(false) |
| @SuppressWarnings("serial") // Superclass is not serializable across versions |
| public class JFileChooser extends JComponent implements Accessible { |
| |
| /** |
| * @see #getUIClassID |
| * @see #readObject |
| */ |
| private static final String uiClassID = "FileChooserUI"; |
| |
| // ************************ |
| // ***** Dialog Types ***** |
| // ************************ |
| |
| /** |
| * Type value indicating that the <code>JFileChooser</code> supports an |
| * "Open" file operation. |
| */ |
| public static final int OPEN_DIALOG = 0; |
| |
| /** |
| * Type value indicating that the <code>JFileChooser</code> supports a |
| * "Save" file operation. |
| */ |
| public static final int SAVE_DIALOG = 1; |
| |
| /** |
| * Type value indicating that the <code>JFileChooser</code> supports a |
| * developer-specified file operation. |
| */ |
| public static final int CUSTOM_DIALOG = 2; |
| |
| |
| // ******************************** |
| // ***** Dialog Return Values ***** |
| // ******************************** |
| |
| /** |
| * Return value if cancel is chosen. |
| */ |
| public static final int CANCEL_OPTION = 1; |
| |
| /** |
| * Return value if approve (yes, ok) is chosen. |
| */ |
| public static final int APPROVE_OPTION = 0; |
| |
| /** |
| * Return value if an error occurred. |
| */ |
| public static final int ERROR_OPTION = -1; |
| |
| |
| // ********************************** |
| // ***** JFileChooser properties ***** |
| // ********************************** |
| |
| |
| /** Instruction to display only files. */ |
| public static final int FILES_ONLY = 0; |
| |
| /** Instruction to display only directories. */ |
| public static final int DIRECTORIES_ONLY = 1; |
| |
| /** Instruction to display both files and directories. */ |
| public static final int FILES_AND_DIRECTORIES = 2; |
| |
| /** Instruction to cancel the current selection. */ |
| public static final String CANCEL_SELECTION = "CancelSelection"; |
| |
| /** |
| * Instruction to approve the current selection |
| * (same as pressing yes or ok). |
| */ |
| public static final String APPROVE_SELECTION = "ApproveSelection"; |
| |
| /** Identifies change in the text on the approve (yes, ok) button. */ |
| public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty"; |
| |
| /** |
| * Identifies change in the tooltip text for the approve (yes, ok) |
| * button. |
| */ |
| public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty"; |
| |
| /** Identifies change in the mnemonic for the approve (yes, ok) button. */ |
| public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = "ApproveButtonMnemonicChangedProperty"; |
| |
| /** Instruction to display the control buttons. */ |
| public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY = "ControlButtonsAreShownChangedProperty"; |
| |
| /** Identifies user's directory change. */ |
| public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged"; |
| |
| /** Identifies change in user's single-file selection. */ |
| public static final String SELECTED_FILE_CHANGED_PROPERTY = "SelectedFileChangedProperty"; |
| |
| /** Identifies change in user's multiple-file selection. */ |
| public static final String SELECTED_FILES_CHANGED_PROPERTY = "SelectedFilesChangedProperty"; |
| |
| /** Enables multiple-file selections. */ |
| public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "MultiSelectionEnabledChangedProperty"; |
| |
| /** |
| * Says that a different object is being used to find available drives |
| * on the system. |
| */ |
| public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged"; |
| |
| /** |
| * Says that a different object is being used to retrieve file |
| * information. |
| */ |
| public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged"; |
| |
| /** Identifies a change in the display-hidden-files property. */ |
| public static final String FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged"; |
| |
| /** User changed the kind of files to display. */ |
| public static final String FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged"; |
| |
| /** |
| * Identifies a change in the kind of selection (single, |
| * multiple, etc.). |
| */ |
| public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged"; |
| |
| /** |
| * Says that a different accessory component is in use |
| * (for example, to preview files). |
| */ |
| public static final String ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty"; |
| |
| /** |
| * Identifies whether a the AcceptAllFileFilter is used or not. |
| */ |
| public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = "acceptAllFileFilterUsedChanged"; |
| |
| /** Identifies a change in the dialog title. */ |
| public static final String DIALOG_TITLE_CHANGED_PROPERTY = "DialogTitleChangedProperty"; |
| |
| /** |
| * Identifies a change in the type of files displayed (files only, |
| * directories only, or both files and directories). |
| */ |
| public static final String DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty"; |
| |
| /** |
| * Identifies a change in the list of predefined file filters |
| * the user can choose from. |
| */ |
| public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty"; |
| |
| // ****************************** |
| // ***** instance variables ***** |
| // ****************************** |
| |
| private String dialogTitle = null; |
| private String approveButtonText = null; |
| private String approveButtonToolTipText = null; |
| private int approveButtonMnemonic = 0; |
| |
| private Vector<FileFilter> filters = new Vector<FileFilter>(5); |
| private JDialog dialog = null; |
| private int dialogType = OPEN_DIALOG; |
| private int returnValue = ERROR_OPTION; |
| private JComponent accessory = null; |
| |
| private FileView fileView = null; |
| |
| private boolean controlsShown = true; |
| |
| private boolean useFileHiding = true; |
| private static final String SHOW_HIDDEN_PROP = "awt.file.showHiddenFiles"; |
| |
| // Listens to changes in the native setting for showing hidden files. |
| // The Listener is removed and the native setting is ignored if |
| // setFileHidingEnabled() is ever called. |
| private transient PropertyChangeListener showFilesListener = null; |
| |
| private int fileSelectionMode = FILES_ONLY; |
| |
| private boolean multiSelectionEnabled = false; |
| |
| private boolean useAcceptAllFileFilter = true; |
| |
| private boolean dragEnabled = false; |
| |
| private FileFilter fileFilter = null; |
| |
| private FileSystemView fileSystemView = null; |
| |
| private File currentDirectory = null; |
| private File selectedFile = null; |
| private File[] selectedFiles; |
| |
| // ************************************* |
| // ***** JFileChooser Constructors ***** |
| // ************************************* |
| |
| /** |
| * Constructs a <code>JFileChooser</code> pointing to the user's |
| * default directory. This default depends on the operating system. |
| * It is typically the "My Documents" folder on Windows, and the |
| * user's home directory on Unix. |
| */ |
| public JFileChooser() { |
| this((File) null, (FileSystemView) null); |
| } |
| |
| /** |
| * Constructs a <code>JFileChooser</code> using the given path. |
| * Passing in a <code>null</code> |
| * string causes the file chooser to point to the user's default directory. |
| * This default depends on the operating system. It is |
| * typically the "My Documents" folder on Windows, and the user's |
| * home directory on Unix. |
| * |
| * @param currentDirectoryPath a <code>String</code> giving the path |
| * to a file or directory |
| */ |
| public JFileChooser(String currentDirectoryPath) { |
| this(currentDirectoryPath, (FileSystemView) null); |
| } |
| |
| /** |
| * Constructs a <code>JFileChooser</code> using the given <code>File</code> |
| * as the path. Passing in a <code>null</code> file |
| * causes the file chooser to point to the user's default directory. |
| * This default depends on the operating system. It is |
| * typically the "My Documents" folder on Windows, and the user's |
| * home directory on Unix. |
| * |
| * @param currentDirectory a <code>File</code> object specifying |
| * the path to a file or directory |
| */ |
| public JFileChooser(File currentDirectory) { |
| this(currentDirectory, (FileSystemView) null); |
| } |
| |
| /** |
| * Constructs a <code>JFileChooser</code> using the given |
| * <code>FileSystemView</code>. |
| * |
| * @param fsv a {@code FileSystemView} |
| */ |
| public JFileChooser(FileSystemView fsv) { |
| this((File) null, fsv); |
| } |
| |
| |
| /** |
| * Constructs a <code>JFileChooser</code> using the given current directory |
| * and <code>FileSystemView</code>. |
| * |
| * @param currentDirectory a {@code File} object specifying the path to a |
| * file or directory |
| * @param fsv a {@code FileSystemView} |
| */ |
| public JFileChooser(File currentDirectory, FileSystemView fsv) { |
| setup(fsv); |
| setCurrentDirectory(currentDirectory); |
| } |
| |
| /** |
| * Constructs a <code>JFileChooser</code> using the given current directory |
| * path and <code>FileSystemView</code>. |
| * |
| * @param currentDirectoryPath a {@code String} specifying the path to a file |
| * or directory |
| * @param fsv a {@code FileSystemView} |
| */ |
| public JFileChooser(String currentDirectoryPath, FileSystemView fsv) { |
| setup(fsv); |
| if(currentDirectoryPath == null) { |
| setCurrentDirectory(null); |
| } else { |
| setCurrentDirectory(fileSystemView.createFileObject(currentDirectoryPath)); |
| } |
| } |
| |
| /** |
| * Performs common constructor initialization and setup. |
| * |
| * @param view the {@code FileSystemView} used for setup |
| */ |
| protected void setup(FileSystemView view) { |
| installShowFilesListener(); |
| installHierarchyListener(); |
| |
| if(view == null) { |
| view = FileSystemView.getFileSystemView(); |
| } |
| setFileSystemView(view); |
| updateUI(); |
| if(isAcceptAllFileFilterUsed()) { |
| setFileFilter(getAcceptAllFileFilter()); |
| } |
| enableEvents(AWTEvent.MOUSE_EVENT_MASK); |
| } |
| |
| private void installHierarchyListener() { |
| addHierarchyListener(new HierarchyListener() { |
| @Override |
| public void hierarchyChanged(HierarchyEvent e) { |
| if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) |
| == HierarchyEvent.PARENT_CHANGED) { |
| JFileChooser fc = JFileChooser.this; |
| JRootPane rootPane = SwingUtilities.getRootPane(fc); |
| if (rootPane != null) { |
| rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc)); |
| } |
| } |
| } |
| }); |
| } |
| |
| private void installShowFilesListener() { |
| // Track native setting for showing hidden files |
| Toolkit tk = Toolkit.getDefaultToolkit(); |
| Object showHiddenProperty = tk.getDesktopProperty(SHOW_HIDDEN_PROP); |
| if (showHiddenProperty instanceof Boolean) { |
| useFileHiding = !((Boolean)showHiddenProperty).booleanValue(); |
| showFilesListener = new WeakPCL(this); |
| tk.addPropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener); |
| } |
| } |
| |
| /** |
| * Sets the <code>dragEnabled</code> property, |
| * which must be <code>true</code> to enable |
| * automatic drag handling (the first part of drag and drop) |
| * on this component. |
| * The <code>transferHandler</code> property needs to be set |
| * to a non-<code>null</code> value for the drag to do |
| * anything. The default value of the <code>dragEnabled</code> |
| * property |
| * is <code>false</code>. |
| * |
| * <p> |
| * |
| * When automatic drag handling is enabled, |
| * most look and feels begin a drag-and-drop operation |
| * whenever the user presses the mouse button over an item |
| * and then moves the mouse a few pixels. |
| * Setting this property to <code>true</code> |
| * can therefore have a subtle effect on |
| * how selections behave. |
| * |
| * <p> |
| * |
| * Some look and feels might not support automatic drag and drop; |
| * they will ignore this property. You can work around such |
| * look and feels by modifying the component |
| * to directly call the <code>exportAsDrag</code> method of a |
| * <code>TransferHandler</code>. |
| * |
| * @param b the value to set the <code>dragEnabled</code> property to |
| * @exception HeadlessException if |
| * <code>b</code> is <code>true</code> and |
| * <code>GraphicsEnvironment.isHeadless()</code> |
| * returns <code>true</code> |
| * @see java.awt.GraphicsEnvironment#isHeadless |
| * @see #getDragEnabled |
| * @see #setTransferHandler |
| * @see TransferHandler |
| * @since 1.4 |
| */ |
| @BeanProperty(bound = false, description |
| = "determines whether automatic drag handling is enabled") |
| public void setDragEnabled(boolean b) { |
| checkDragEnabled(b); |
| dragEnabled = b; |
| } |
| |
| private static void checkDragEnabled(boolean b) { |
| if (b && GraphicsEnvironment.isHeadless()) { |
| throw new HeadlessException(); |
| } |
| } |
| |
| /** |
| * Gets the value of the <code>dragEnabled</code> property. |
| * |
| * @return the value of the <code>dragEnabled</code> property |
| * @see #setDragEnabled |
| * @since 1.4 |
| */ |
| public boolean getDragEnabled() { |
| return dragEnabled; |
| } |
| |
| // ***************************** |
| // ****** File Operations ****** |
| // ***************************** |
| |
| /** |
| * Returns the selected file. This can be set either by the |
| * programmer via <code>setSelectedFile</code> or by a user action, such as |
| * either typing the filename into the UI or selecting the |
| * file from a list in the UI. |
| * |
| * @see #setSelectedFile |
| * @return the selected file |
| */ |
| public File getSelectedFile() { |
| return selectedFile; |
| } |
| |
| /** |
| * Sets the selected file. If the file's parent directory is |
| * not the current directory, changes the current directory |
| * to be the file's parent directory. |
| * |
| * @see #getSelectedFile |
| * |
| * @param file the selected file |
| */ |
| @BeanProperty(preferred = true) |
| public void setSelectedFile(File file) { |
| File oldValue = selectedFile; |
| selectedFile = file; |
| if(selectedFile != null) { |
| if (file.isAbsolute() && !getFileSystemView().isParent(getCurrentDirectory(), selectedFile)) { |
| setCurrentDirectory(selectedFile.getParentFile()); |
| } |
| if (!isMultiSelectionEnabled() || selectedFiles == null || selectedFiles.length == 1) { |
| ensureFileIsVisible(selectedFile); |
| } |
| } |
| firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, oldValue, selectedFile); |
| } |
| |
| /** |
| * Returns a list of selected files if the file chooser is |
| * set to allow multiple selection. |
| * |
| * @return an array of selected {@code File}s |
| */ |
| public File[] getSelectedFiles() { |
| if(selectedFiles == null) { |
| return new File[0]; |
| } else { |
| return selectedFiles.clone(); |
| } |
| } |
| |
| /** |
| * Sets the list of selected files if the file chooser is |
| * set to allow multiple selection. |
| * |
| * @param selectedFiles an array {@code File}s to be selected |
| */ |
| @BeanProperty(description |
| = "The list of selected files if the chooser is in multiple selection mode.") |
| public void setSelectedFiles(File[] selectedFiles) { |
| File[] oldValue = this.selectedFiles; |
| if (selectedFiles == null || selectedFiles.length == 0) { |
| selectedFiles = null; |
| this.selectedFiles = null; |
| setSelectedFile(null); |
| } else { |
| this.selectedFiles = selectedFiles.clone(); |
| setSelectedFile(this.selectedFiles[0]); |
| } |
| firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, selectedFiles); |
| } |
| |
| /** |
| * Returns the current directory. |
| * |
| * @return the current directory |
| * @see #setCurrentDirectory |
| */ |
| public File getCurrentDirectory() { |
| return currentDirectory; |
| } |
| |
| /** |
| * Sets the current directory. Passing in <code>null</code> sets the |
| * file chooser to point to the user's default directory. |
| * This default depends on the operating system. It is |
| * typically the "My Documents" folder on Windows, and the user's |
| * home directory on Unix. |
| * |
| * If the file passed in as <code>currentDirectory</code> is not a |
| * directory, the parent of the file will be used as the currentDirectory. |
| * If the parent is not traversable, then it will walk up the parent tree |
| * until it finds a traversable directory, or hits the root of the |
| * file system. |
| * |
| * @param dir the current directory to point to |
| * @see #getCurrentDirectory |
| */ |
| @BeanProperty(preferred = true, description |
| = "The directory that the JFileChooser is showing files of.") |
| public void setCurrentDirectory(File dir) { |
| File oldValue = currentDirectory; |
| |
| if (dir != null && !dir.exists()) { |
| dir = currentDirectory; |
| } |
| if (dir == null) { |
| dir = getFileSystemView().getDefaultDirectory(); |
| } |
| if (currentDirectory != null) { |
| /* Verify the toString of object */ |
| if (this.currentDirectory.equals(dir)) { |
| return; |
| } |
| } |
| |
| File prev = null; |
| while (!isTraversable(dir) && prev != dir) { |
| prev = dir; |
| dir = getFileSystemView().getParentDirectory(dir); |
| } |
| currentDirectory = dir; |
| |
| firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue, currentDirectory); |
| } |
| |
| /** |
| * Changes the directory to be set to the parent of the |
| * current directory. |
| * |
| * @see #getCurrentDirectory |
| */ |
| public void changeToParentDirectory() { |
| selectedFile = null; |
| File oldValue = getCurrentDirectory(); |
| setCurrentDirectory(getFileSystemView().getParentDirectory(oldValue)); |
| } |
| |
| /** |
| * Tells the UI to rescan its files list from the current directory. |
| */ |
| public void rescanCurrentDirectory() { |
| getUI().rescanCurrentDirectory(this); |
| } |
| |
| /** |
| * Makes sure that the specified file is viewable, and |
| * not hidden. |
| * |
| * @param f a File object |
| */ |
| public void ensureFileIsVisible(File f) { |
| getUI().ensureFileIsVisible(this, f); |
| } |
| |
| // ************************************** |
| // ***** JFileChooser Dialog methods ***** |
| // ************************************** |
| |
| /** |
| * Pops up an "Open File" file chooser dialog. Note that the |
| * text that appears in the approve button is determined by |
| * the L&F. |
| * |
| * @param parent the parent component of the dialog, |
| * can be <code>null</code>; |
| * see <code>showDialog</code> for details |
| * @return the return state of the file chooser on popdown: |
| * <ul> |
| * <li>JFileChooser.CANCEL_OPTION |
| * <li>JFileChooser.APPROVE_OPTION |
| * <li>JFileChooser.ERROR_OPTION if an error occurs or the |
| * dialog is dismissed |
| * </ul> |
| * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| * returns true. |
| * @see java.awt.GraphicsEnvironment#isHeadless |
| * @see #showDialog |
| */ |
| public int showOpenDialog(Component parent) throws HeadlessException { |
| setDialogType(OPEN_DIALOG); |
| return showDialog(parent, null); |
| } |
| |
| /** |
| * Pops up a "Save File" file chooser dialog. Note that the |
| * text that appears in the approve button is determined by |
| * the L&F. |
| * |
| * @param parent the parent component of the dialog, |
| * can be <code>null</code>; |
| * see <code>showDialog</code> for details |
| * @return the return state of the file chooser on popdown: |
| * <ul> |
| * <li>JFileChooser.CANCEL_OPTION |
| * <li>JFileChooser.APPROVE_OPTION |
| * <li>JFileChooser.ERROR_OPTION if an error occurs or the |
| * dialog is dismissed |
| * </ul> |
| * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| * returns true. |
| * @see java.awt.GraphicsEnvironment#isHeadless |
| * @see #showDialog |
| */ |
| public int showSaveDialog(Component parent) throws HeadlessException { |
| setDialogType(SAVE_DIALOG); |
| return showDialog(parent, null); |
| } |
| |
| /** |
| * Pops a custom file chooser dialog with a custom approve button. |
| * For example, the following code |
| * pops up a file chooser with a "Run Application" button |
| * (instead of the normal "Save" or "Open" button): |
| * <pre> |
| * filechooser.showDialog(parentFrame, "Run Application"); |
| * </pre> |
| * |
| * Alternatively, the following code does the same thing: |
| * <pre> |
| * JFileChooser chooser = new JFileChooser(null); |
| * chooser.setApproveButtonText("Run Application"); |
| * chooser.showDialog(parentFrame, null); |
| * </pre> |
| * |
| * <!--PENDING(jeff) - the following method should be added to the api: |
| * showDialog(Component parent);--> |
| * <!--PENDING(kwalrath) - should specify modality and what |
| * "depends" means.--> |
| * |
| * <p> |
| * |
| * The <code>parent</code> argument determines two things: |
| * the frame on which the open dialog depends and |
| * the component whose position the look and feel |
| * should consider when placing the dialog. If the parent |
| * is a <code>Frame</code> object (such as a <code>JFrame</code>) |
| * then the dialog depends on the frame and |
| * the look and feel positions the dialog |
| * relative to the frame (for example, centered over the frame). |
| * If the parent is a component, then the dialog |
| * depends on the frame containing the component, |
| * and is positioned relative to the component |
| * (for example, centered over the component). |
| * If the parent is <code>null</code>, then the dialog depends on |
| * no visible window, and it's placed in a |
| * look-and-feel-dependent position |
| * such as the center of the screen. |
| * |
| * @param parent the parent component of the dialog; |
| * can be <code>null</code> |
| * @param approveButtonText the text of the <code>ApproveButton</code> |
| * @return the return state of the file chooser on popdown: |
| * <ul> |
| * <li>JFileChooser.CANCEL_OPTION |
| * <li>JFileChooser.APPROVE_OPTION |
| * <li>JFileChooser.ERROR_OPTION if an error occurs or the |
| * dialog is dismissed |
| * </ul> |
| * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| * returns true. |
| * @see java.awt.GraphicsEnvironment#isHeadless |
| */ |
| @SuppressWarnings("deprecation") |
| public int showDialog(Component parent, String approveButtonText) |
| throws HeadlessException { |
| if (dialog != null) { |
| // Prevent to show second instance of dialog if the previous one still exists |
| return JFileChooser.ERROR_OPTION; |
| } |
| |
| if(approveButtonText != null) { |
| setApproveButtonText(approveButtonText); |
| setDialogType(CUSTOM_DIALOG); |
| } |
| dialog = createDialog(parent); |
| dialog.addWindowListener(new WindowAdapter() { |
| public void windowClosing(WindowEvent e) { |
| returnValue = CANCEL_OPTION; |
| } |
| }); |
| returnValue = ERROR_OPTION; |
| rescanCurrentDirectory(); |
| |
| dialog.show(); |
| firePropertyChange("JFileChooserDialogIsClosingProperty", dialog, null); |
| |
| // Remove all components from dialog. The MetalFileChooserUI.installUI() method (and other LAFs) |
| // registers AWT listener for dialogs and produces memory leaks. It happens when |
| // installUI invoked after the showDialog method. |
| dialog.getContentPane().removeAll(); |
| dialog.dispose(); |
| dialog = null; |
| return returnValue; |
| } |
| |
| /** |
| * Creates and returns a new <code>JDialog</code> wrapping |
| * <code>this</code> centered on the <code>parent</code> |
| * in the <code>parent</code>'s frame. |
| * This method can be overriden to further manipulate the dialog, |
| * to disable resizing, set the location, etc. Example: |
| * <pre> |
| * class MyFileChooser extends JFileChooser { |
| * protected JDialog createDialog(Component parent) throws HeadlessException { |
| * JDialog dialog = super.createDialog(parent); |
| * dialog.setLocation(300, 200); |
| * dialog.setResizable(false); |
| * return dialog; |
| * } |
| * } |
| * </pre> |
| * |
| * @param parent the parent component of the dialog; |
| * can be <code>null</code> |
| * @return a new <code>JDialog</code> containing this instance |
| * @exception HeadlessException if GraphicsEnvironment.isHeadless() |
| * returns true. |
| * @see java.awt.GraphicsEnvironment#isHeadless |
| * @since 1.4 |
| */ |
| protected JDialog createDialog(Component parent) throws HeadlessException { |
| FileChooserUI ui = getUI(); |
| String title = ui.getDialogTitle(this); |
| putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY, |
| title); |
| |
| JDialog dialog; |
| Window window = JOptionPane.getWindowForComponent(parent); |
| if (window instanceof Frame) { |
| dialog = new JDialog((Frame)window, title, true); |
| } else { |
| dialog = new JDialog((Dialog)window, title, true); |
| } |
| dialog.setComponentOrientation(this.getComponentOrientation()); |
| |
| Container contentPane = dialog.getContentPane(); |
| contentPane.setLayout(new BorderLayout()); |
| contentPane.add(this, BorderLayout.CENTER); |
| |
| if (JDialog.isDefaultLookAndFeelDecorated()) { |
| boolean supportsWindowDecorations = |
| UIManager.getLookAndFeel().getSupportsWindowDecorations(); |
| if (supportsWindowDecorations) { |
| dialog.getRootPane().setWindowDecorationStyle(JRootPane.FILE_CHOOSER_DIALOG); |
| } |
| } |
| dialog.pack(); |
| dialog.setLocationRelativeTo(parent); |
| |
| return dialog; |
| } |
| |
| // ************************** |
| // ***** Dialog Options ***** |
| // ************************** |
| |
| /** |
| * Returns the value of the <code>controlButtonsAreShown</code> |
| * property. |
| * |
| * @return the value of the <code>controlButtonsAreShown</code> |
| * property |
| * |
| * @see #setControlButtonsAreShown |
| * @since 1.3 |
| */ |
| public boolean getControlButtonsAreShown() { |
| return controlsShown; |
| } |
| |
| |
| /** |
| * Sets the property |
| * that indicates whether the <i>approve</i> and <i>cancel</i> |
| * buttons are shown in the file chooser. This property |
| * is <code>true</code> by default. Look and feels |
| * that always show these buttons will ignore the value |
| * of this property. |
| * This method fires a property-changed event, |
| * using the string value of |
| * <code>CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY</code> |
| * as the name of the property. |
| * |
| * @param b <code>false</code> if control buttons should not be |
| * shown; otherwise, <code>true</code> |
| * |
| * @see #getControlButtonsAreShown |
| * @see #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY |
| * @since 1.3 |
| */ |
| @BeanProperty(preferred = true, description |
| = "Sets whether the approve & cancel buttons are shown.") |
| public void setControlButtonsAreShown(boolean b) { |
| if(controlsShown == b) { |
| return; |
| } |
| boolean oldValue = controlsShown; |
| controlsShown = b; |
| firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY, oldValue, controlsShown); |
| } |
| |
| /** |
| * Returns the type of this dialog. The default is |
| * <code>JFileChooser.OPEN_DIALOG</code>. |
| * |
| * @return the type of dialog to be displayed: |
| * <ul> |
| * <li>JFileChooser.OPEN_DIALOG |
| * <li>JFileChooser.SAVE_DIALOG |
| * <li>JFileChooser.CUSTOM_DIALOG |
| * </ul> |
| * |
| * @see #setDialogType |
| */ |
| public int getDialogType() { |
| return dialogType; |
| } |
| |
| /** |
| * Sets the type of this dialog. Use <code>OPEN_DIALOG</code> when you |
| * want to bring up a file chooser that the user can use to open a file. |
| * Likewise, use <code>SAVE_DIALOG</code> for letting the user choose |
| * a file for saving. |
| * Use <code>CUSTOM_DIALOG</code> when you want to use the file |
| * chooser in a context other than "Open" or "Save". |
| * For instance, you might want to bring up a file chooser that allows |
| * the user to choose a file to execute. Note that you normally would not |
| * need to set the <code>JFileChooser</code> to use |
| * <code>CUSTOM_DIALOG</code> |
| * since a call to <code>setApproveButtonText</code> does this for you. |
| * The default dialog type is <code>JFileChooser.OPEN_DIALOG</code>. |
| * |
| * @param dialogType the type of dialog to be displayed: |
| * <ul> |
| * <li>JFileChooser.OPEN_DIALOG |
| * <li>JFileChooser.SAVE_DIALOG |
| * <li>JFileChooser.CUSTOM_DIALOG |
| * </ul> |
| * |
| * @exception IllegalArgumentException if <code>dialogType</code> is |
| * not legal |
| * |
| * @see #getDialogType |
| * @see #setApproveButtonText |
| */ |
| // PENDING(jeff) - fire button text change property |
| @BeanProperty(preferred = true, enumerationValues = { |
| "JFileChooser.OPEN_DIALOG", |
| "JFileChooser.SAVE_DIALOG", |
| "JFileChooser.CUSTOM_DIALOG"}, description |
| = "The type (open, save, custom) of the JFileChooser.") |
| public void setDialogType(int dialogType) { |
| if(this.dialogType == dialogType) { |
| return; |
| } |
| checkDialogType(dialogType); |
| int oldValue = this.dialogType; |
| this.dialogType = dialogType; |
| if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) { |
| setApproveButtonText(null); |
| } |
| firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType); |
| } |
| |
| private static void checkDialogType(int dialogType) { |
| if (!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG |
| || dialogType == CUSTOM_DIALOG)) { |
| throw new IllegalArgumentException( |
| "Incorrect Dialog Type: " + dialogType); |
| } |
| } |
| |
| /** |
| * Sets the string that goes in the <code>JFileChooser</code> window's |
| * title bar. |
| * |
| * @param dialogTitle the new <code>String</code> for the title bar |
| * |
| * @see #getDialogTitle |
| * |
| */ |
| @BeanProperty(preferred = true, description |
| = "The title of the JFileChooser dialog window.") |
| public void setDialogTitle(String dialogTitle) { |
| String oldValue = this.dialogTitle; |
| this.dialogTitle = dialogTitle; |
| if(dialog != null) { |
| dialog.setTitle(dialogTitle); |
| } |
| firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue, dialogTitle); |
| } |
| |
| /** |
| * Gets the string that goes in the <code>JFileChooser</code>'s titlebar. |
| * |
| * @return the string from the {@code JFileChooser} window's title bar |
| * @see #setDialogTitle |
| */ |
| public String getDialogTitle() { |
| return dialogTitle; |
| } |
| |
| // ************************************ |
| // ***** JFileChooser View Options ***** |
| // ************************************ |
| |
| |
| |
| /** |
| * Sets the tooltip text used in the <code>ApproveButton</code>. |
| * If <code>null</code>, the UI object will determine the button's text. |
| * |
| * @param toolTipText the tooltip text for the approve button |
| * @see #setApproveButtonText |
| * @see #setDialogType |
| * @see #showDialog |
| */ |
| @BeanProperty(preferred = true, description |
| = "The tooltip text for the ApproveButton.") |
| public void setApproveButtonToolTipText(String toolTipText) { |
| if(approveButtonToolTipText == toolTipText) { |
| return; |
| } |
| String oldValue = approveButtonToolTipText; |
| approveButtonToolTipText = toolTipText; |
| firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, oldValue, approveButtonToolTipText); |
| } |
| |
| |
| /** |
| * Returns the tooltip text used in the <code>ApproveButton</code>. |
| * If <code>null</code>, the UI object will determine the button's text. |
| * |
| * @return the tooltip text used for the approve button |
| * |
| * @see #setApproveButtonText |
| * @see #setDialogType |
| * @see #showDialog |
| */ |
| public String getApproveButtonToolTipText() { |
| return approveButtonToolTipText; |
| } |
| |
| /** |
| * Returns the approve button's mnemonic. |
| * @return an integer value for the mnemonic key |
| * |
| * @see #setApproveButtonMnemonic |
| */ |
| public int getApproveButtonMnemonic() { |
| return approveButtonMnemonic; |
| } |
| |
| /** |
| * Sets the approve button's mnemonic using a numeric keycode. |
| * |
| * @param mnemonic an integer value for the mnemonic key |
| * |
| * @see #getApproveButtonMnemonic |
| */ |
| @BeanProperty(preferred = true, description |
| = "The mnemonic key accelerator for the ApproveButton.") |
| public void setApproveButtonMnemonic(int mnemonic) { |
| if(approveButtonMnemonic == mnemonic) { |
| return; |
| } |
| int oldValue = approveButtonMnemonic; |
| approveButtonMnemonic = mnemonic; |
| firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY, oldValue, approveButtonMnemonic); |
| } |
| |
| /** |
| * Sets the approve button's mnemonic using a character. |
| * @param mnemonic a character value for the mnemonic key |
| * |
| * @see #getApproveButtonMnemonic |
| */ |
| public void setApproveButtonMnemonic(char mnemonic) { |
| int vk = (int) mnemonic; |
| if(vk >= 'a' && vk <='z') { |
| vk -= ('a' - 'A'); |
| } |
| setApproveButtonMnemonic(vk); |
| } |
| |
| |
| /** |
| * Sets the text used in the <code>ApproveButton</code> in the |
| * <code>FileChooserUI</code>. |
| * |
| * @param approveButtonText the text used in the <code>ApproveButton</code> |
| * |
| * @see #getApproveButtonText |
| * @see #setDialogType |
| * @see #showDialog |
| */ |
| // PENDING(jeff) - have ui set this on dialog type change |
| @BeanProperty(preferred = true, description |
| = "The text that goes in the ApproveButton.") |
| public void setApproveButtonText(String approveButtonText) { |
| if(this.approveButtonText == approveButtonText) { |
| return; |
| } |
| String oldValue = this.approveButtonText; |
| this.approveButtonText = approveButtonText; |
| firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldValue, approveButtonText); |
| } |
| |
| /** |
| * Returns the text used in the <code>ApproveButton</code> in the |
| * <code>FileChooserUI</code>. |
| * If <code>null</code>, the UI object will determine the button's text. |
| * |
| * Typically, this would be "Open" or "Save". |
| * |
| * @return the text used in the <code>ApproveButton</code> |
| * |
| * @see #setApproveButtonText |
| * @see #setDialogType |
| * @see #showDialog |
| */ |
| public String getApproveButtonText() { |
| return approveButtonText; |
| } |
| |
| /** |
| * Gets the list of user choosable file filters. |
| * |
| * @return a <code>FileFilter</code> array containing all the choosable |
| * file filters |
| * |
| * @see #addChoosableFileFilter |
| * @see #removeChoosableFileFilter |
| * @see #resetChoosableFileFilters |
| */ |
| @BeanProperty(bound = false) |
| public FileFilter[] getChoosableFileFilters() { |
| FileFilter[] filterArray = new FileFilter[filters.size()]; |
| filters.copyInto(filterArray); |
| return filterArray; |
| } |
| |
| /** |
| * Adds a filter to the list of user choosable file filters. |
| * For information on setting the file selection mode, see |
| * {@link #setFileSelectionMode setFileSelectionMode}. |
| * |
| * @param filter the <code>FileFilter</code> to add to the choosable file |
| * filter list |
| * |
| * @see #getChoosableFileFilters |
| * @see #removeChoosableFileFilter |
| * @see #resetChoosableFileFilters |
| * @see #setFileSelectionMode |
| */ |
| @BeanProperty(preferred = true, description |
| = "Adds a filter to the list of user choosable file filters.") |
| public void addChoosableFileFilter(FileFilter filter) { |
| if(filter != null && !filters.contains(filter)) { |
| FileFilter[] oldValue = getChoosableFileFilters(); |
| filters.addElement(filter); |
| firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters()); |
| if (fileFilter == null && filters.size() == 1) { |
| setFileFilter(filter); |
| } |
| } |
| } |
| |
| /** |
| * Removes a filter from the list of user choosable file filters. Returns |
| * true if the file filter was removed. |
| * |
| * @param f the file filter to be removed |
| * @return true if the file filter was removed, false otherwise |
| * @see #addChoosableFileFilter |
| * @see #getChoosableFileFilters |
| * @see #resetChoosableFileFilters |
| */ |
| public boolean removeChoosableFileFilter(FileFilter f) { |
| int index = filters.indexOf(f); |
| if (index >= 0) { |
| if(getFileFilter() == f) { |
| FileFilter aaff = getAcceptAllFileFilter(); |
| if (isAcceptAllFileFilterUsed() && (aaff != f)) { |
| // choose default filter if it is used |
| setFileFilter(aaff); |
| } |
| else if (index > 0) { |
| // choose the first filter, because it is not removed |
| setFileFilter(filters.get(0)); |
| } |
| else if (filters.size() > 1) { |
| // choose the second filter, because the first one is removed |
| setFileFilter(filters.get(1)); |
| } |
| else { |
| // no more filters |
| setFileFilter(null); |
| } |
| } |
| FileFilter[] oldValue = getChoosableFileFilters(); |
| filters.removeElement(f); |
| firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters()); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /** |
| * Resets the choosable file filter list to its starting state. Normally, |
| * this removes all added file filters while leaving the |
| * <code>AcceptAll</code> file filter. |
| * |
| * @see #addChoosableFileFilter |
| * @see #getChoosableFileFilters |
| * @see #removeChoosableFileFilter |
| */ |
| public void resetChoosableFileFilters() { |
| FileFilter[] oldValue = getChoosableFileFilters(); |
| setFileFilter(null); |
| filters.removeAllElements(); |
| if(isAcceptAllFileFilterUsed()) { |
| addChoosableFileFilter(getAcceptAllFileFilter()); |
| } |
| firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters()); |
| } |
| |
| /** |
| * Returns the <code>AcceptAll</code> file filter. |
| * For example, on Microsoft Windows this would be All Files (*.*). |
| * |
| * @return the {@code AcceptAll} file filter |
| */ |
| @BeanProperty(bound = false) |
| public FileFilter getAcceptAllFileFilter() { |
| FileFilter filter = null; |
| if(getUI() != null) { |
| filter = getUI().getAcceptAllFileFilter(this); |
| } |
| return filter; |
| } |
| |
| /** |
| * Returns whether the <code>AcceptAll FileFilter</code> is used. |
| * @return true if the <code>AcceptAll FileFilter</code> is used |
| * @see #setAcceptAllFileFilterUsed |
| * @since 1.3 |
| */ |
| public boolean isAcceptAllFileFilterUsed() { |
| return useAcceptAllFileFilter; |
| } |
| |
| /** |
| * Determines whether the <code>AcceptAll FileFilter</code> is used |
| * as an available choice in the choosable filter list. |
| * If false, the <code>AcceptAll</code> file filter is removed from |
| * the list of available file filters. |
| * If true, the <code>AcceptAll</code> file filter will become the |
| * actively used file filter. |
| * |
| * @param b a {@code boolean} which determines whether the {@code AcceptAll} |
| * file filter is an available choice in the choosable filter list |
| * |
| * @see #isAcceptAllFileFilterUsed |
| * @see #getAcceptAllFileFilter |
| * @see #setFileFilter |
| * @since 1.3 |
| */ |
| @BeanProperty(preferred = true, description |
| = "Sets whether the AcceptAll FileFilter is used as an available choice in the choosable filter list.") |
| public void setAcceptAllFileFilterUsed(boolean b) { |
| boolean oldValue = useAcceptAllFileFilter; |
| useAcceptAllFileFilter = b; |
| if(!b) { |
| removeChoosableFileFilter(getAcceptAllFileFilter()); |
| } else { |
| removeChoosableFileFilter(getAcceptAllFileFilter()); |
| addChoosableFileFilter(getAcceptAllFileFilter()); |
| } |
| firePropertyChange(ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY, oldValue, useAcceptAllFileFilter); |
| } |
| |
| /** |
| * Returns the accessory component. |
| * |
| * @return this JFileChooser's accessory component, or null |
| * @see #setAccessory |
| */ |
| public JComponent getAccessory() { |
| return accessory; |
| } |
| |
| /** |
| * Sets the accessory component. An accessory is often used to show a |
| * preview image of the selected file; however, it can be used for anything |
| * that the programmer wishes, such as extra custom file chooser controls. |
| * |
| * <p> |
| * Note: if there was a previous accessory, you should unregister |
| * any listeners that the accessory might have registered with the |
| * file chooser. |
| * |
| * @param newAccessory the accessory component to be set |
| */ |
| @BeanProperty(preferred = true, description |
| = "Sets the accessory component on the JFileChooser.") |
| public void setAccessory(JComponent newAccessory) { |
| JComponent oldValue = accessory; |
| accessory = newAccessory; |
| firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue, accessory); |
| } |
| |
| /** |
| * Sets the <code>JFileChooser</code> to allow the user to just |
| * select files, just select |
| * directories, or select both files and directories. The default is |
| * <code>JFilesChooser.FILES_ONLY</code>. |
| * |
| * @param mode the type of files to be displayed: |
| * <ul> |
| * <li>JFileChooser.FILES_ONLY |
| * <li>JFileChooser.DIRECTORIES_ONLY |
| * <li>JFileChooser.FILES_AND_DIRECTORIES |
| * </ul> |
| * |
| * @exception IllegalArgumentException if <code>mode</code> is an |
| * illegal file selection mode |
| * |
| * @see #getFileSelectionMode |
| */ |
| @BeanProperty(preferred = true, enumerationValues = { |
| "JFileChooser.FILES_ONLY", |
| "JFileChooser.DIRECTORIES_ONLY", |
| "JFileChooser.FILES_AND_DIRECTORIES"}, description |
| = "Sets the types of files that the JFileChooser can choose.") |
| public void setFileSelectionMode(int mode) { |
| if(fileSelectionMode == mode) { |
| return; |
| } |
| |
| checkFileSelectionMode(mode); |
| int oldValue = fileSelectionMode; |
| fileSelectionMode = mode; |
| firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode); |
| } |
| |
| private static void checkFileSelectionMode(int mode) { |
| if ((mode != FILES_ONLY) && (mode != DIRECTORIES_ONLY) |
| && (mode != FILES_AND_DIRECTORIES)) { |
| throw new IllegalArgumentException( |
| "Incorrect Mode for file selection: " + mode); |
| } |
| } |
| |
| /** |
| * Returns the current file-selection mode. The default is |
| * <code>JFilesChooser.FILES_ONLY</code>. |
| * |
| * @return the type of files to be displayed, one of the following: |
| * <ul> |
| * <li>JFileChooser.FILES_ONLY |
| * <li>JFileChooser.DIRECTORIES_ONLY |
| * <li>JFileChooser.FILES_AND_DIRECTORIES |
| * </ul> |
| * @see #setFileSelectionMode |
| */ |
| public int getFileSelectionMode() { |
| return fileSelectionMode; |
| } |
| |
| /** |
| * Convenience call that determines if files are selectable based on the |
| * current file selection mode. |
| * |
| * @return true if files are selectable, false otherwise |
| * @see #setFileSelectionMode |
| * @see #getFileSelectionMode |
| */ |
| @BeanProperty(bound = false) |
| public boolean isFileSelectionEnabled() { |
| return ((fileSelectionMode == FILES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES)); |
| } |
| |
| /** |
| * Convenience call that determines if directories are selectable based |
| * on the current file selection mode. |
| * |
| * @return true if directories are selectable, false otherwise |
| * @see #setFileSelectionMode |
| * @see #getFileSelectionMode |
| */ |
| @BeanProperty(bound = false) |
| public boolean isDirectorySelectionEnabled() { |
| return ((fileSelectionMode == DIRECTORIES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES)); |
| } |
| |
| /** |
| * Sets the file chooser to allow multiple file selections. |
| * |
| * @param b true if multiple files may be selected |
| * |
| * @see #isMultiSelectionEnabled |
| */ |
| @BeanProperty(description |
| = "Sets multiple file selection mode.") |
| public void setMultiSelectionEnabled(boolean b) { |
| if(multiSelectionEnabled == b) { |
| return; |
| } |
| boolean oldValue = multiSelectionEnabled; |
| multiSelectionEnabled = b; |
| firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY, oldValue, multiSelectionEnabled); |
| } |
| |
| /** |
| * Returns true if multiple files can be selected. |
| * @return true if multiple files can be selected |
| * @see #setMultiSelectionEnabled |
| */ |
| public boolean isMultiSelectionEnabled() { |
| return multiSelectionEnabled; |
| } |
| |
| |
| /** |
| * Returns true if hidden files are not shown in the file chooser; |
| * otherwise, returns false. |
| * |
| * @return the status of the file hiding property |
| * @see #setFileHidingEnabled |
| */ |
| public boolean isFileHidingEnabled() { |
| return useFileHiding; |
| } |
| |
| /** |
| * Sets file hiding on or off. If true, hidden files are not shown |
| * in the file chooser. The job of determining which files are |
| * shown is done by the <code>FileView</code>. |
| * |
| * @param b the boolean value that determines whether file hiding is |
| * turned on |
| * @see #isFileHidingEnabled |
| */ |
| @BeanProperty(preferred = true, description |
| = "Sets file hiding on or off.") |
| public void setFileHidingEnabled(boolean b) { |
| // Dump showFilesListener since we'll ignore it from now on |
| if (showFilesListener != null) { |
| Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener); |
| showFilesListener = null; |
| } |
| boolean oldValue = useFileHiding; |
| useFileHiding = b; |
| firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, useFileHiding); |
| } |
| |
| /** |
| * Sets the current file filter. The file filter is used by the |
| * file chooser to filter out files from the user's view. |
| * |
| * @param filter the new current file filter to use |
| * @see #getFileFilter |
| */ |
| @BeanProperty(preferred = true, description |
| = "Sets the File Filter used to filter out files of type.") |
| public void setFileFilter(FileFilter filter) { |
| FileFilter oldValue = fileFilter; |
| fileFilter = filter; |
| if (filter != null) { |
| if (isMultiSelectionEnabled() && selectedFiles != null && selectedFiles.length > 0) { |
| Vector<File> fList = new Vector<File>(); |
| boolean failed = false; |
| for (File file : selectedFiles) { |
| if (filter.accept(file)) { |
| fList.add(file); |
| } else { |
| failed = true; |
| } |
| } |
| if (failed) { |
| setSelectedFiles((fList.size() == 0) ? null : fList.toArray(new File[fList.size()])); |
| } |
| } else if (selectedFile != null && !filter.accept(selectedFile)) { |
| setSelectedFile(null); |
| } |
| } |
| firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter); |
| } |
| |
| |
| /** |
| * Returns the currently selected file filter. |
| * |
| * @return the current file filter |
| * @see #setFileFilter |
| * @see #addChoosableFileFilter |
| */ |
| public FileFilter getFileFilter() { |
| return fileFilter; |
| } |
| |
| /** |
| * Sets the file view to be used to retrieve UI information, such as |
| * the icon that represents a file or the type description of a file. |
| * |
| * @param fileView a {@code FileView} to be used to retrieve UI information |
| * |
| * @see #getFileView |
| */ |
| @BeanProperty(preferred = true, description |
| = "Sets the File View used to get file type information.") |
| public void setFileView(FileView fileView) { |
| FileView oldValue = this.fileView; |
| this.fileView = fileView; |
| firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue, fileView); |
| } |
| |
| /** |
| * Returns the current file view. |
| * |
| * @return the current file view |
| * @see #setFileView |
| */ |
| public FileView getFileView() { |
| return fileView; |
| } |
| |
| // ****************************** |
| // *****FileView delegation ***** |
| // ****************************** |
| |
| // NOTE: all of the following methods attempt to delegate |
| // first to the client set fileView, and if <code>null</code> is returned |
| // (or there is now client defined fileView) then calls the |
| // UI's default fileView. |
| |
| /** |
| * Returns the filename. |
| * @param f the <code>File</code> |
| * @return the <code>String</code> containing the filename for |
| * <code>f</code> |
| * @see FileView#getName |
| */ |
| public String getName(File f) { |
| String filename = null; |
| if(f != null) { |
| if(getFileView() != null) { |
| filename = getFileView().getName(f); |
| } |
| |
| FileView uiFileView = getUI().getFileView(this); |
| |
| if(filename == null && uiFileView != null) { |
| filename = uiFileView.getName(f); |
| } |
| } |
| return filename; |
| } |
| |
| /** |
| * Returns the file description. |
| * @param f the <code>File</code> |
| * @return the <code>String</code> containing the file description for |
| * <code>f</code> |
| * @see FileView#getDescription |
| */ |
| public String getDescription(File f) { |
| String description = null; |
| if(f != null) { |
| if(getFileView() != null) { |
| description = getFileView().getDescription(f); |
| } |
| |
| FileView uiFileView = getUI().getFileView(this); |
| |
| if(description == null && uiFileView != null) { |
| description = uiFileView.getDescription(f); |
| } |
| } |
| return description; |
| } |
| |
| /** |
| * Returns the file type. |
| * @param f the <code>File</code> |
| * @return the <code>String</code> containing the file type description for |
| * <code>f</code> |
| * @see FileView#getTypeDescription |
| */ |
| public String getTypeDescription(File f) { |
| String typeDescription = null; |
| if(f != null) { |
| if(getFileView() != null) { |
| typeDescription = getFileView().getTypeDescription(f); |
| } |
| |
| FileView uiFileView = getUI().getFileView(this); |
| |
| if(typeDescription == null && uiFileView != null) { |
| typeDescription = uiFileView.getTypeDescription(f); |
| } |
| } |
| return typeDescription; |
| } |
| |
| /** |
| * Returns the icon for this file or type of file, depending |
| * on the system. |
| * @param f the <code>File</code> |
| * @return the <code>Icon</code> for this file, or type of file |
| * @see FileView#getIcon |
| */ |
| public Icon getIcon(File f) { |
| Icon icon = null; |
| if (f != null) { |
| if(getFileView() != null) { |
| icon = getFileView().getIcon(f); |
| } |
| |
| FileView uiFileView = getUI().getFileView(this); |
| |
| if(icon == null && uiFileView != null) { |
| icon = uiFileView.getIcon(f); |
| } |
| } |
| return icon; |
| } |
| |
| /** |
| * Returns true if the file (directory) can be visited. |
| * Returns false if the directory cannot be traversed. |
| * @param f the <code>File</code> |
| * @return true if the file/directory can be traversed, otherwise false |
| * @see FileView#isTraversable |
| */ |
| public boolean isTraversable(File f) { |
| Boolean traversable = null; |
| if (f != null) { |
| if (getFileView() != null) { |
| traversable = getFileView().isTraversable(f); |
| } |
| |
| FileView uiFileView = getUI().getFileView(this); |
| |
| if (traversable == null && uiFileView != null) { |
| traversable = uiFileView.isTraversable(f); |
| } |
| if (traversable == null) { |
| traversable = getFileSystemView().isTraversable(f); |
| } |
| } |
| return (traversable != null && traversable.booleanValue()); |
| } |
| |
| /** |
| * Returns true if the file should be displayed. |
| * @param f the <code>File</code> |
| * @return true if the file should be displayed, otherwise false |
| * @see FileFilter#accept |
| */ |
| public boolean accept(File f) { |
| boolean shown = true; |
| if(f != null && fileFilter != null) { |
| shown = fileFilter.accept(f); |
| } |
| return shown; |
| } |
| |
| /** |
| * Sets the file system view that the <code>JFileChooser</code> uses for |
| * accessing and creating file system resources, such as finding |
| * the floppy drive and getting a list of root drives. |
| * @param fsv the new <code>FileSystemView</code> |
| * |
| * @see FileSystemView |
| */ |
| @BeanProperty(expert = true, description |
| = "Sets the FileSytemView used to get filesystem information.") |
| public void setFileSystemView(FileSystemView fsv) { |
| FileSystemView oldValue = fileSystemView; |
| fileSystemView = fsv; |
| firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue, fileSystemView); |
| } |
| |
| /** |
| * Returns the file system view. |
| * @return the <code>FileSystemView</code> object |
| * @see #setFileSystemView |
| */ |
| public FileSystemView getFileSystemView() { |
| return fileSystemView; |
| } |
| |
| // ************************** |
| // ***** Event Handling ***** |
| // ************************** |
| |
| /** |
| * Called by the UI when the user hits the Approve button |
| * (labeled "Open" or "Save", by default). This can also be |
| * called by the programmer. |
| * This method causes an action event to fire |
| * with the command string equal to |
| * <code>APPROVE_SELECTION</code>. |
| * |
| * @see #APPROVE_SELECTION |
| */ |
| public void approveSelection() { |
| returnValue = APPROVE_OPTION; |
| if(dialog != null) { |
| dialog.setVisible(false); |
| } |
| fireActionPerformed(APPROVE_SELECTION); |
| } |
| |
| /** |
| * Called by the UI when the user chooses the Cancel button. |
| * This can also be called by the programmer. |
| * This method causes an action event to fire |
| * with the command string equal to |
| * <code>CANCEL_SELECTION</code>. |
| * |
| * @see #CANCEL_SELECTION |
| */ |
| public void cancelSelection() { |
| returnValue = CANCEL_OPTION; |
| if(dialog != null) { |
| dialog.setVisible(false); |
| } |
| fireActionPerformed(CANCEL_SELECTION); |
| } |
| |
| /** |
| * Adds an <code>ActionListener</code> to the file chooser. |
| * |
| * @param l the listener to be added |
| * |
| * @see #approveSelection |
| * @see #cancelSelection |
| */ |
| public void addActionListener(ActionListener l) { |
| listenerList.add(ActionListener.class, l); |
| } |
| |
| /** |
| * Removes an <code>ActionListener</code> from the file chooser. |
| * |
| * @param l the listener to be removed |
| * |
| * @see #addActionListener |
| */ |
| public void removeActionListener(ActionListener l) { |
| listenerList.remove(ActionListener.class, l); |
| } |
| |
| /** |
| * Returns an array of all the action listeners |
| * registered on this file chooser. |
| * |
| * @return all of this file chooser's <code>ActionListener</code>s |
| * or an empty |
| * array if no action listeners are currently registered |
| * |
| * @see #addActionListener |
| * @see #removeActionListener |
| * |
| * @since 1.4 |
| */ |
| @BeanProperty(bound = false) |
| public ActionListener[] getActionListeners() { |
| return listenerList.getListeners(ActionListener.class); |
| } |
| |
| /** |
| * Notifies all listeners that have registered interest for |
| * notification on this event type. The event instance |
| * is lazily created using the <code>command</code> parameter. |
| * |
| * @param command a string that may specify a command associated with |
| * the event |
| * @see EventListenerList |
| */ |
| protected void fireActionPerformed(String command) { |
| // Guaranteed to return a non-null array |
| Object[] listeners = listenerList.getListenerList(); |
| long mostRecentEventTime = EventQueue.getMostRecentEventTime(); |
| int modifiers = 0; |
| AWTEvent currentEvent = EventQueue.getCurrentEvent(); |
| if (currentEvent instanceof InputEvent) { |
| modifiers = ((InputEvent)currentEvent).getModifiers(); |
| } else if (currentEvent instanceof ActionEvent) { |
| modifiers = ((ActionEvent)currentEvent).getModifiers(); |
| } |
| ActionEvent e = null; |
| // Process the listeners last to first, notifying |
| // those that are interested in this event |
| for (int i = listeners.length-2; i>=0; i-=2) { |
| if (listeners[i]==ActionListener.class) { |
| // Lazily create the event: |
| if (e == null) { |
| e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, |
| command, mostRecentEventTime, |
| modifiers); |
| } |
| ((ActionListener)listeners[i+1]).actionPerformed(e); |
| } |
| } |
| } |
| |
| private static class WeakPCL implements PropertyChangeListener { |
| WeakReference<JFileChooser> jfcRef; |
| |
| public WeakPCL(JFileChooser jfc) { |
| jfcRef = new WeakReference<JFileChooser>(jfc); |
| } |
| public void propertyChange(PropertyChangeEvent ev) { |
| assert ev.getPropertyName().equals(SHOW_HIDDEN_PROP); |
| JFileChooser jfc = jfcRef.get(); |
| if (jfc == null) { |
| // Our JFileChooser is no longer around, so we no longer need to |
| // listen for PropertyChangeEvents. |
| Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, this); |
| } |
| else { |
| boolean oldValue = jfc.useFileHiding; |
| jfc.useFileHiding = !((Boolean)ev.getNewValue()).booleanValue(); |
| jfc.firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, jfc.useFileHiding); |
| } |
| } |
| } |
| |
| // ********************************* |
| // ***** Pluggable L&F methods ***** |
| // ********************************* |
| |
| /** |
| * Resets the UI property to a value from the current look and feel. |
| * |
| * @see JComponent#updateUI |
| */ |
| public void updateUI() { |
| if (isAcceptAllFileFilterUsed()) { |
| removeChoosableFileFilter(getAcceptAllFileFilter()); |
| } |
| FileChooserUI ui = ((FileChooserUI)UIManager.getUI(this)); |
| if (fileSystemView == null) { |
| // We were probably deserialized |
| setFileSystemView(FileSystemView.getFileSystemView()); |
| } |
| setUI(ui); |
| |
| if(isAcceptAllFileFilterUsed()) { |
| addChoosableFileFilter(getAcceptAllFileFilter()); |
| } |
| } |
| |
| /** |
| * Returns a string that specifies the name of the L&F class |
| * that renders this component. |
| * |
| * @return the string "FileChooserUI" |
| * @see JComponent#getUIClassID |
| * @see UIDefaults#getUI |
| */ |
| @BeanProperty(bound = false, expert = true, description |
| = "A string that specifies the name of the L&F class.") |
| public String getUIClassID() { |
| return uiClassID; |
| } |
| |
| /** |
| * Gets the UI object which implements the L&F for this component. |
| * |
| * @return the FileChooserUI object that implements the FileChooserUI L&F |
| */ |
| @BeanProperty(bound = false) |
| public FileChooserUI getUI() { |
| return (FileChooserUI) ui; |
| } |
| |
| /** |
| * See <code>readObject</code> and <code>writeObject</code> in |
| * <code>JComponent</code> for more |
| * information about serialization in Swing. |
| */ |
| private void readObject(java.io.ObjectInputStream in) |
| throws IOException, ClassNotFoundException { |
| ObjectInputStream.GetField f = in.readFields(); |
| |
| dialogTitle = (String) f.get("dialogTitle", null); |
| approveButtonText = (String) f.get("approveButtonText", null); |
| approveButtonToolTipText = |
| (String) f.get("approveButtonToolTipText", null); |
| approveButtonMnemonic = f.get("approveButtonMnemonic", 0); |
| @SuppressWarnings("unchecked") |
| Vector<FileFilter> newFilters = (Vector<FileFilter>) f.get("filters", null); |
| if (newFilters == null) { |
| throw new InvalidObjectException("Null filters"); |
| } |
| filters = newFilters; |
| dialog = (JDialog) f.get("dialog", null); |
| int newDialogType = f.get("dialogType", OPEN_DIALOG); |
| checkDialogType(newDialogType); |
| dialogType = newDialogType; |
| returnValue = f.get("returnValue", 0); |
| accessory = (JComponent) f.get("accessory", null); |
| fileView = (FileView) f.get("fileView", null); |
| controlsShown = f.get("controlsShown", false); |
| useFileHiding = f.get("useFileHiding", false); |
| int newFileSelectionMode = f.get("fileSelectionMode", FILES_ONLY); |
| checkFileSelectionMode(newFileSelectionMode); |
| fileSelectionMode = newFileSelectionMode; |
| multiSelectionEnabled = f.get("multiSelectionEnabled", false); |
| useAcceptAllFileFilter = f.get("useAcceptAllFileFilter", false); |
| boolean newDragEnabled = f.get("dragEnabled", false); |
| checkDragEnabled(newDragEnabled); |
| dragEnabled = newDragEnabled; |
| fileFilter = (FileFilter) f.get("fileFilter", null); |
| fileSystemView = (FileSystemView) f.get("fileSystemView", null); |
| currentDirectory = (File) f.get("currentDirectory", null); |
| selectedFile = (File) f.get("selectedFile", null); |
| selectedFiles = (File[]) f.get("selectedFiles", null); |
| accessibleContext = (AccessibleContext) f.get("accessibleContext", null); |
| |
| installShowFilesListener(); |
| } |
| |
| /** |
| * See <code>readObject</code> and <code>writeObject</code> in |
| * <code>JComponent</code> for more |
| * information about serialization in Swing. |
| */ |
| private void writeObject(ObjectOutputStream s) throws IOException { |
| FileSystemView fsv = null; |
| |
| if (isAcceptAllFileFilterUsed()) { |
| //The AcceptAllFileFilter is UI specific, it will be reset by |
| //updateUI() after deserialization |
| removeChoosableFileFilter(getAcceptAllFileFilter()); |
| } |
| if (fileSystemView.equals(FileSystemView.getFileSystemView())) { |
| //The default FileSystemView is platform specific, it will be |
| //reset by updateUI() after deserialization |
| fsv = fileSystemView; |
| fileSystemView = null; |
| } |
| s.defaultWriteObject(); |
| if (fsv != null) { |
| fileSystemView = fsv; |
| } |
| if (isAcceptAllFileFilterUsed()) { |
| addChoosableFileFilter(getAcceptAllFileFilter()); |
| } |
| if (getUIClassID().equals(uiClassID)) { |
| byte count = JComponent.getWriteObjCounter(this); |
| JComponent.setWriteObjCounter(this, --count); |
| if (count == 0 && ui != null) { |
| ui.installUI(this); |
| } |
| } |
| } |
| |
| |
| /** |
| * Returns a string representation of this <code>JFileChooser</code>. |
| * This method |
| * is intended to be used only for debugging purposes, and the |
| * content and format of the returned string may vary between |
| * implementations. The returned string may be empty but may not |
| * be <code>null</code>. |
| * |
| * @return a string representation of this <code>JFileChooser</code> |
| */ |
| protected String paramString() { |
| String approveButtonTextString = (approveButtonText != null ? |
| approveButtonText: ""); |
| String dialogTitleString = (dialogTitle != null ? |
| dialogTitle: ""); |
| String dialogTypeString; |
| if (dialogType == OPEN_DIALOG) { |
| dialogTypeString = "OPEN_DIALOG"; |
| } else if (dialogType == SAVE_DIALOG) { |
| dialogTypeString = "SAVE_DIALOG"; |
| } else if (dialogType == CUSTOM_DIALOG) { |
| dialogTypeString = "CUSTOM_DIALOG"; |
| } else dialogTypeString = ""; |
| String returnValueString; |
| if (returnValue == CANCEL_OPTION) { |
| returnValueString = "CANCEL_OPTION"; |
| } else if (returnValue == APPROVE_OPTION) { |
| returnValueString = "APPROVE_OPTION"; |
| } else if (returnValue == ERROR_OPTION) { |
| returnValueString = "ERROR_OPTION"; |
| } else returnValueString = ""; |
| String useFileHidingString = (useFileHiding ? |
| "true" : "false"); |
| String fileSelectionModeString; |
| if (fileSelectionMode == FILES_ONLY) { |
| fileSelectionModeString = "FILES_ONLY"; |
| } else if (fileSelectionMode == DIRECTORIES_ONLY) { |
| fileSelectionModeString = "DIRECTORIES_ONLY"; |
| } else if (fileSelectionMode == FILES_AND_DIRECTORIES) { |
| fileSelectionModeString = "FILES_AND_DIRECTORIES"; |
| } else fileSelectionModeString = ""; |
| String currentDirectoryString = (currentDirectory != null ? |
| currentDirectory.toString() : ""); |
| String selectedFileString = (selectedFile != null ? |
| selectedFile.toString() : ""); |
| |
| return super.paramString() + |
| ",approveButtonText=" + approveButtonTextString + |
| ",currentDirectory=" + currentDirectoryString + |
| ",dialogTitle=" + dialogTitleString + |
| ",dialogType=" + dialogTypeString + |
| ",fileSelectionMode=" + fileSelectionModeString + |
| ",returnValue=" + returnValueString + |
| ",selectedFile=" + selectedFileString + |
| ",useFileHiding=" + useFileHidingString; |
| } |
| |
| ///////////////// |
| // Accessibility support |
| //////////////// |
| |
| /** |
| * {@code AccessibleContext} associated with this {@code JFileChooser} |
| */ |
| protected AccessibleContext accessibleContext = null; |
| |
| /** |
| * Gets the AccessibleContext associated with this JFileChooser. |
| * For file choosers, the AccessibleContext takes the form of an |
| * AccessibleJFileChooser. |
| * A new AccessibleJFileChooser instance is created if necessary. |
| * |
| * @return an AccessibleJFileChooser that serves as the |
| * AccessibleContext of this JFileChooser |
| */ |
| @BeanProperty(bound = false) |
| public AccessibleContext getAccessibleContext() { |
| if (accessibleContext == null) { |
| accessibleContext = new AccessibleJFileChooser(); |
| } |
| return accessibleContext; |
| } |
| |
| /** |
| * This class implements accessibility support for the |
| * <code>JFileChooser</code> class. It provides an implementation of the |
| * Java Accessibility API appropriate to file chooser user-interface |
| * elements. |
| */ |
| @SuppressWarnings("serial") // Superclass is not serializable across versions |
| protected class AccessibleJFileChooser extends AccessibleJComponent { |
| |
| /** |
| * Gets the role of this object. |
| * |
| * @return an instance of AccessibleRole describing the role of the |
| * object |
| * @see AccessibleRole |
| */ |
| public AccessibleRole getAccessibleRole() { |
| return AccessibleRole.FILE_CHOOSER; |
| } |
| |
| } // inner class AccessibleJFileChooser |
| |
| } |