/* |
|
* Copyright (c) 1997, 2013, 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.PropertyChangeListener; |
|
import java.beans.PropertyChangeEvent; |
|
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="https://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>. |
|
* |
|
* @beaninfo |
|
* attribute: isContainer false |
|
* description: A component which allows for the interactive selection of a file. |
|
* |
|
* @author Jeff Dinkins |
|
* |
|
*/ |
|
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>. |
|
*/ |
|
public JFileChooser(FileSystemView fsv) { |
|
this((File) null, fsv); |
|
} |
|
/** |
|
* Constructs a <code>JFileChooser</code> using the given current directory |
|
* and <code>FileSystemView</code>. |
|
*/ |
|
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>. |
|
*/ |
|
public JFileChooser(String currentDirectoryPath, FileSystemView fsv) { |
|
setup(fsv); |
|
if(currentDirectoryPath == null) { |
|
setCurrentDirectory(null); |
|
} else { |
|
setCurrentDirectory(fileSystemView.createFileObject(currentDirectoryPath)); |
|
} |
|
} |
|
/** |
|
* Performs common constructor initialization and 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 |
|
* |
|
* @beaninfo |
|
* description: determines whether automatic drag handling is enabled |
|
* bound: false |
|
*/ |
|
public void setDragEnabled(boolean b) { |
|
if (b && GraphicsEnvironment.isHeadless()) { |
|
throw new HeadlessException(); |
|
} |
|
dragEnabled = b; |
|
} |
|
/** |
|
* 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. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* |
|
* @see #getSelectedFile |
|
* |
|
* @param file the selected file |
|
*/ |
|
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. |
|
*/ |
|
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. |
|
* |
|
* @beaninfo |
|
* bound: true |
|
* 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. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: The directory that the JFileChooser is showing files of. |
|
* |
|
* @param dir the current directory to point to |
|
* @see #getCurrentDirectory |
|
*/ |
|
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 |
|
*/ |
|
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> |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: Sets whether the approve & cancel buttons are shown. |
|
* |
|
* @see #getControlButtonsAreShown |
|
* @see #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY |
|
* @since 1.3 |
|
*/ |
|
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 |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: The type (open, save, custom) of the JFileChooser. |
|
* enum: |
|
* OPEN_DIALOG JFileChooser.OPEN_DIALOG |
|
* SAVE_DIALOG JFileChooser.SAVE_DIALOG |
|
* CUSTOM_DIALOG JFileChooser.CUSTOM_DIALOG |
|
* |
|
* @see #getDialogType |
|
* @see #setApproveButtonText |
|
*/ |
|
// PENDING(jeff) - fire button text change property |
|
public void setDialogType(int dialogType) { |
|
if(this.dialogType == dialogType) { |
|
return; |
|
} |
|
if(!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || dialogType == CUSTOM_DIALOG)) { |
|
throw new IllegalArgumentException("Incorrect Dialog Type: " + dialogType); |
|
} |
|
int oldValue = this.dialogType; |
|
this.dialogType = dialogType; |
|
if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) { |
|
setApproveButtonText(null); |
|
} |
|
firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, 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 |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: The title of the JFileChooser dialog window. |
|
* |
|
* @see #getDialogTitle |
|
* |
|
*/ |
|
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. |
|
* |
|
* @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. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: The tooltip text for the ApproveButton. |
|
* |
|
* @param toolTipText the tooltip text for the approve button |
|
* @see #setApproveButtonText |
|
* @see #setDialogType |
|
* @see #showDialog |
|
*/ |
|
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 |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: The mnemonic key accelerator for the ApproveButton. |
|
* |
|
* @see #getApproveButtonMnemonic |
|
*/ |
|
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>. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: The text that goes in the ApproveButton. |
|
* |
|
* @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 |
|
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 |
|
*/ |
|
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 |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: Adds a filter to the list of user choosable file filters. |
|
* |
|
* @see #getChoosableFileFilters |
|
* @see #removeChoosableFileFilter |
|
* @see #resetChoosableFileFilters |
|
* @see #setFileSelectionMode |
|
*/ |
|
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. |
|
* |
|
* @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 (*.*). |
|
*/ |
|
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 |
|
* the actively used file filter. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: Sets whether the AcceptAll FileFilter is used as an available choice in the choosable filter list. |
|
* |
|
* @see #isAcceptAllFileFilterUsed |
|
* @see #getAcceptAllFileFilter |
|
* @see #setFileFilter |
|
* @since 1.3 |
|
*/ |
|
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. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: 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 |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: Sets the types of files that the JFileChooser can choose. |
|
* enum: FILES_ONLY JFileChooser.FILES_ONLY |
|
* DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY |
|
* FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES |
|
* |
|
* |
|
* @see #getFileSelectionMode |
|
*/ |
|
public void setFileSelectionMode(int mode) { |
|
if(fileSelectionMode == mode) { |
|
return; |
|
} |
|
if ((mode == FILES_ONLY) || (mode == DIRECTORIES_ONLY) || (mode == FILES_AND_DIRECTORIES)) { |
|
int oldValue = fileSelectionMode; |
|
fileSelectionMode = mode; |
|
firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode); |
|
} else { |
|
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. |
|
* |
|
* @see #setFileSelectionMode |
|
* @see #getFileSelectionMode |
|
*/ |
|
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. |
|
* |
|
* @see #setFileSelectionMode |
|
* @see #getFileSelectionMode |
|
*/ |
|
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 |
|
* @beaninfo |
|
* bound: true |
|
* description: Sets multiple file selection mode. |
|
* |
|
* @see #isMultiSelectionEnabled |
|
*/ |
|
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>. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: Sets file hiding on or off. |
|
* |
|
* @param b the boolean value that determines whether file hiding is |
|
* turned on |
|
* @see #isFileHidingEnabled |
|
*/ |
|
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. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: Sets the File Filter used to filter out files of type. |
|
* |
|
* @param filter the new current file filter to use |
|
* @see #getFileFilter |
|
*/ |
|
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 used to retrieve UI information, such as |
|
* the icon that represents a file or the type description of a file. |
|
* |
|
* @beaninfo |
|
* preferred: true |
|
* bound: true |
|
* description: Sets the File View used to get file type information. |
|
* |
|
* @see #getFileView |
|
*/ |
|
public void setFileView(FileView fileView) { |
|
FileView oldValue = this.fileView; |
|
this.fileView = fileView; |
|
firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue, fileView); |
|
} |
|
/** |
|
* Returns 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> |
|
* |
|
* @beaninfo |
|
* expert: true |
|
* bound: true |
|
* description: Sets the FileSytemView used to get filesystem information. |
|
* |
|
* @see FileSystemView |
|
*/ |
|
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 |
|
*/ |
|
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. |
|
* |
|
* @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 |
|
* @beaninfo |
|
* 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 |
|
*/ |
|
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 { |
|
in.defaultReadObject(); |
|
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 |
|
//////////////// |
|
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 |
|
*/ |
|
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. |
|
*/ |
|
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 |
|
} |