History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/JFileChooser.java (1 of 18352 files). Show all

Unified · Split

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