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.io.InvalidObjectException;
54 import java.io.ObjectInputStream;
55 import java.lang.ref.WeakReference;
56
57 /**
58 * <code>JFileChooser</code> provides a simple mechanism for the user to
59 * choose a file.
60 * For information about using <code>JFileChooser</code>, see
61 * <a
62 href="http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html">How to Use File Choosers</a>,
63 * a section in <em>The Java Tutorial</em>.
64 *
65 * <p>
66 *
67 * The following code pops up a file chooser for the user's home directory that
68 * sees only .jpg and .gif images:
69 * <pre>
70 * JFileChooser chooser = new JFileChooser();
71 * FileNameExtensionFilter filter = new FileNameExtensionFilter(
72 * "JPG & GIF Images", "jpg", "gif");
73 * chooser.setFileFilter(filter);
74 * int returnVal = chooser.showOpenDialog(parent);
75 * if(returnVal == JFileChooser.APPROVE_OPTION) {
76 * System.out.println("You chose to open this file: " +
77 * chooser.getSelectedFile().getName());
78 * }
79 * </pre>
80 * <p>
87 * attribute: isContainer false
88 * description: A component which allows for the interactive selection of a file.
89 *
90 * @author Jeff Dinkins
91 * @since 1.2
92 */
93 @SuppressWarnings("serial") // Superclass is not serializable across versions
94 public class JFileChooser extends JComponent implements Accessible {
95
96 /**
97 * @see #getUIClassID
98 * @see #readObject
99 */
100 private static final String uiClassID = "FileChooserUI";
101
102 // ************************
103 // ***** Dialog Types *****
104 // ************************
105
106 /**
107 * Type value indicating that the <code>JFileChooser</code> supports an
108 * "Open" file operation.
109 */
110 public static final int OPEN_DIALOG = 0;
111
112 /**
113 * Type value indicating that the <code>JFileChooser</code> supports a
114 * "Save" file operation.
115 */
116 public static final int SAVE_DIALOG = 1;
117
118 /**
119 * Type value indicating that the <code>JFileChooser</code> supports a
120 * developer-specified file operation.
121 */
122 public static final int CUSTOM_DIALOG = 2;
123
124
125 // ********************************
126 // ***** Dialog Return Values *****
127 // ********************************
128
129 /**
130 * Return value if cancel is chosen.
131 */
132 public static final int CANCEL_OPTION = 1;
133
134 /**
135 * Return value if approve (yes, ok) is chosen.
136 */
137 public static final int APPROVE_OPTION = 0;
138
139 /**
273
274 private boolean multiSelectionEnabled = false;
275
276 private boolean useAcceptAllFileFilter = true;
277
278 private boolean dragEnabled = false;
279
280 private FileFilter fileFilter = null;
281
282 private FileSystemView fileSystemView = null;
283
284 private File currentDirectory = null;
285 private File selectedFile = null;
286 private File[] selectedFiles;
287
288 // *************************************
289 // ***** JFileChooser Constructors *****
290 // *************************************
291
292 /**
293 * Constructs a <code>JFileChooser</code> pointing to the user's
294 * default directory. This default depends on the operating system.
295 * It is typically the "My Documents" folder on Windows, and the
296 * user's home directory on Unix.
297 */
298 public JFileChooser() {
299 this((File) null, (FileSystemView) null);
300 }
301
302 /**
303 * Constructs a <code>JFileChooser</code> using the given path.
304 * Passing in a <code>null</code>
305 * string causes the file chooser to point to the user's default directory.
306 * This default depends on the operating system. It is
307 * typically the "My Documents" folder on Windows, and the user's
308 * home directory on Unix.
309 *
310 * @param currentDirectoryPath a <code>String</code> giving the path
311 * to a file or directory
312 */
313 public JFileChooser(String currentDirectoryPath) {
314 this(currentDirectoryPath, (FileSystemView) null);
315 }
316
317 /**
318 * Constructs a <code>JFileChooser</code> using the given <code>File</code>
319 * as the path. Passing in a <code>null</code> file
320 * causes the file chooser to point to the user's default directory.
321 * This default depends on the operating system. It is
322 * typically the "My Documents" folder on Windows, and the user's
323 * home directory on Unix.
324 *
325 * @param currentDirectory a <code>File</code> object specifying
326 * the path to a file or directory
327 */
328 public JFileChooser(File currentDirectory) {
329 this(currentDirectory, (FileSystemView) null);
330 }
331
332 /**
333 * Constructs a <code>JFileChooser</code> using the given
334 * <code>FileSystemView</code>.
335 *
336 * @param fsv a {@code FileSystemView}
337 */
338 public JFileChooser(FileSystemView fsv) {
339 this((File) null, fsv);
340 }
341
342
343 /**
344 * Constructs a <code>JFileChooser</code> using the given current directory
345 * and <code>FileSystemView</code>.
346 *
347 * @param currentDirectory a {@code File} object specifying the path to a
348 * file or directory
349 * @param fsv a {@code FileSystemView}
350 */
351 public JFileChooser(File currentDirectory, FileSystemView fsv) {
352 setup(fsv);
353 setCurrentDirectory(currentDirectory);
354 }
355
356 /**
357 * Constructs a <code>JFileChooser</code> using the given current directory
358 * path and <code>FileSystemView</code>.
359 *
360 * @param currentDirectoryPath a {@code String} specifying the path to a file
361 * or directory
362 * @param fsv a {@code FileSystemView}
363 */
364 public JFileChooser(String currentDirectoryPath, FileSystemView fsv) {
365 setup(fsv);
366 if(currentDirectoryPath == null) {
367 setCurrentDirectory(null);
368 } else {
369 setCurrentDirectory(fileSystemView.createFileObject(currentDirectoryPath));
370 }
371 }
372
373 /**
374 * Performs common constructor initialization and setup.
375 *
376 * @param view the {@code FileSystemView} used for setup
377 */
378 protected void setup(FileSystemView view) {
401 if (rootPane != null) {
402 rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc));
403 }
404 }
405 }
406 });
407 }
408
409 private void installShowFilesListener() {
410 // Track native setting for showing hidden files
411 Toolkit tk = Toolkit.getDefaultToolkit();
412 Object showHiddenProperty = tk.getDesktopProperty(SHOW_HIDDEN_PROP);
413 if (showHiddenProperty instanceof Boolean) {
414 useFileHiding = !((Boolean)showHiddenProperty).booleanValue();
415 showFilesListener = new WeakPCL(this);
416 tk.addPropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener);
417 }
418 }
419
420 /**
421 * Sets the <code>dragEnabled</code> property,
422 * which must be <code>true</code> to enable
423 * automatic drag handling (the first part of drag and drop)
424 * on this component.
425 * The <code>transferHandler</code> property needs to be set
426 * to a non-<code>null</code> value for the drag to do
427 * anything. The default value of the <code>dragEnabled</code>
428 * property
429 * is <code>false</code>.
430 *
431 * <p>
432 *
433 * When automatic drag handling is enabled,
434 * most look and feels begin a drag-and-drop operation
435 * whenever the user presses the mouse button over an item
436 * and then moves the mouse a few pixels.
437 * Setting this property to <code>true</code>
438 * can therefore have a subtle effect on
439 * how selections behave.
440 *
441 * <p>
442 *
443 * Some look and feels might not support automatic drag and drop;
444 * they will ignore this property. You can work around such
445 * look and feels by modifying the component
446 * to directly call the <code>exportAsDrag</code> method of a
447 * <code>TransferHandler</code>.
448 *
449 * @param b the value to set the <code>dragEnabled</code> property to
450 * @exception HeadlessException if
451 * <code>b</code> is <code>true</code> and
452 * <code>GraphicsEnvironment.isHeadless()</code>
453 * returns <code>true</code>
454 * @see java.awt.GraphicsEnvironment#isHeadless
455 * @see #getDragEnabled
456 * @see #setTransferHandler
457 * @see TransferHandler
458 * @since 1.4
459 *
460 * @beaninfo
461 * description: determines whether automatic drag handling is enabled
462 * bound: false
463 */
464 public void setDragEnabled(boolean b) {
465 checkDragEnabled(b);
466 dragEnabled = b;
467 }
468
469 private static void checkDragEnabled(boolean b) {
470 if (b && GraphicsEnvironment.isHeadless()) {
471 throw new HeadlessException();
472 }
473 }
474
475 /**
476 * Gets the value of the <code>dragEnabled</code> property.
477 *
478 * @return the value of the <code>dragEnabled</code> property
479 * @see #setDragEnabled
480 * @since 1.4
481 */
482 public boolean getDragEnabled() {
483 return dragEnabled;
484 }
485
486 // *****************************
487 // ****** File Operations ******
488 // *****************************
489
490 /**
491 * Returns the selected file. This can be set either by the
492 * programmer via <code>setSelectedFile</code> or by a user action, such as
493 * either typing the filename into the UI or selecting the
494 * file from a list in the UI.
495 *
496 * @see #setSelectedFile
497 * @return the selected file
498 */
499 public File getSelectedFile() {
500 return selectedFile;
501 }
502
503 /**
504 * Sets the selected file. If the file's parent directory is
505 * not the current directory, changes the current directory
506 * to be the file's parent directory.
507 *
508 * @beaninfo
509 * preferred: true
510 * bound: true
511 *
512 * @see #getSelectedFile
557 this.selectedFiles = null;
558 setSelectedFile(null);
559 } else {
560 this.selectedFiles = selectedFiles.clone();
561 setSelectedFile(this.selectedFiles[0]);
562 }
563 firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, selectedFiles);
564 }
565
566 /**
567 * Returns the current directory.
568 *
569 * @return the current directory
570 * @see #setCurrentDirectory
571 */
572 public File getCurrentDirectory() {
573 return currentDirectory;
574 }
575
576 /**
577 * Sets the current directory. Passing in <code>null</code> sets the
578 * file chooser to point to the user's default directory.
579 * This default depends on the operating system. It is
580 * typically the "My Documents" folder on Windows, and the user's
581 * home directory on Unix.
582 *
583 * If the file passed in as <code>currentDirectory</code> is not a
584 * directory, the parent of the file will be used as the currentDirectory.
585 * If the parent is not traversable, then it will walk up the parent tree
586 * until it finds a traversable directory, or hits the root of the
587 * file system.
588 *
589 * @beaninfo
590 * preferred: true
591 * bound: true
592 * description: The directory that the JFileChooser is showing files of.
593 *
594 * @param dir the current directory to point to
595 * @see #getCurrentDirectory
596 */
597 public void setCurrentDirectory(File dir) {
598 File oldValue = currentDirectory;
599
600 if (dir != null && !dir.exists()) {
601 dir = currentDirectory;
602 }
603 if (dir == null) {
642 /**
643 * Makes sure that the specified file is viewable, and
644 * not hidden.
645 *
646 * @param f a File object
647 */
648 public void ensureFileIsVisible(File f) {
649 getUI().ensureFileIsVisible(this, f);
650 }
651
652 // **************************************
653 // ***** JFileChooser Dialog methods *****
654 // **************************************
655
656 /**
657 * Pops up an "Open File" file chooser dialog. Note that the
658 * text that appears in the approve button is determined by
659 * the L&F.
660 *
661 * @param parent the parent component of the dialog,
662 * can be <code>null</code>;
663 * see <code>showDialog</code> for details
664 * @return the return state of the file chooser on popdown:
665 * <ul>
666 * <li>JFileChooser.CANCEL_OPTION
667 * <li>JFileChooser.APPROVE_OPTION
668 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
669 * dialog is dismissed
670 * </ul>
671 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
672 * returns true.
673 * @see java.awt.GraphicsEnvironment#isHeadless
674 * @see #showDialog
675 */
676 public int showOpenDialog(Component parent) throws HeadlessException {
677 setDialogType(OPEN_DIALOG);
678 return showDialog(parent, null);
679 }
680
681 /**
682 * Pops up a "Save File" file chooser dialog. Note that the
683 * text that appears in the approve button is determined by
684 * the L&F.
685 *
686 * @param parent the parent component of the dialog,
687 * can be <code>null</code>;
688 * see <code>showDialog</code> for details
689 * @return the return state of the file chooser on popdown:
690 * <ul>
691 * <li>JFileChooser.CANCEL_OPTION
692 * <li>JFileChooser.APPROVE_OPTION
693 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
694 * dialog is dismissed
695 * </ul>
696 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
697 * returns true.
698 * @see java.awt.GraphicsEnvironment#isHeadless
699 * @see #showDialog
700 */
701 public int showSaveDialog(Component parent) throws HeadlessException {
702 setDialogType(SAVE_DIALOG);
703 return showDialog(parent, null);
704 }
705
706 /**
707 * Pops a custom file chooser dialog with a custom approve button.
708 * For example, the following code
709 * pops up a file chooser with a "Run Application" button
710 * (instead of the normal "Save" or "Open" button):
711 * <pre>
712 * filechooser.showDialog(parentFrame, "Run Application");
713 * </pre>
714 *
715 * Alternatively, the following code does the same thing:
716 * <pre>
717 * JFileChooser chooser = new JFileChooser(null);
718 * chooser.setApproveButtonText("Run Application");
719 * chooser.showDialog(parentFrame, null);
720 * </pre>
721 *
722 * <!--PENDING(jeff) - the following method should be added to the api:
723 * showDialog(Component parent);-->
724 * <!--PENDING(kwalrath) - should specify modality and what
725 * "depends" means.-->
726 *
727 * <p>
728 *
729 * The <code>parent</code> argument determines two things:
730 * the frame on which the open dialog depends and
731 * the component whose position the look and feel
732 * should consider when placing the dialog. If the parent
733 * is a <code>Frame</code> object (such as a <code>JFrame</code>)
734 * then the dialog depends on the frame and
735 * the look and feel positions the dialog
736 * relative to the frame (for example, centered over the frame).
737 * If the parent is a component, then the dialog
738 * depends on the frame containing the component,
739 * and is positioned relative to the component
740 * (for example, centered over the component).
741 * If the parent is <code>null</code>, then the dialog depends on
742 * no visible window, and it's placed in a
743 * look-and-feel-dependent position
744 * such as the center of the screen.
745 *
746 * @param parent the parent component of the dialog;
747 * can be <code>null</code>
748 * @param approveButtonText the text of the <code>ApproveButton</code>
749 * @return the return state of the file chooser on popdown:
750 * <ul>
751 * <li>JFileChooser.CANCEL_OPTION
752 * <li>JFileChooser.APPROVE_OPTION
753 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
754 * dialog is dismissed
755 * </ul>
756 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
757 * returns true.
758 * @see java.awt.GraphicsEnvironment#isHeadless
759 */
760 @SuppressWarnings("deprecation")
761 public int showDialog(Component parent, String approveButtonText)
762 throws HeadlessException {
763 if (dialog != null) {
764 // Prevent to show second instance of dialog if the previous one still exists
765 return JFileChooser.ERROR_OPTION;
766 }
767
768 if(approveButtonText != null) {
774 public void windowClosing(WindowEvent e) {
775 returnValue = CANCEL_OPTION;
776 }
777 });
778 returnValue = ERROR_OPTION;
779 rescanCurrentDirectory();
780
781 dialog.show();
782 firePropertyChange("JFileChooserDialogIsClosingProperty", dialog, null);
783
784 // Remove all components from dialog. The MetalFileChooserUI.installUI() method (and other LAFs)
785 // registers AWT listener for dialogs and produces memory leaks. It happens when
786 // installUI invoked after the showDialog method.
787 dialog.getContentPane().removeAll();
788 dialog.dispose();
789 dialog = null;
790 return returnValue;
791 }
792
793 /**
794 * Creates and returns a new <code>JDialog</code> wrapping
795 * <code>this</code> centered on the <code>parent</code>
796 * in the <code>parent</code>'s frame.
797 * This method can be overriden to further manipulate the dialog,
798 * to disable resizing, set the location, etc. Example:
799 * <pre>
800 * class MyFileChooser extends JFileChooser {
801 * protected JDialog createDialog(Component parent) throws HeadlessException {
802 * JDialog dialog = super.createDialog(parent);
803 * dialog.setLocation(300, 200);
804 * dialog.setResizable(false);
805 * return dialog;
806 * }
807 * }
808 * </pre>
809 *
810 * @param parent the parent component of the dialog;
811 * can be <code>null</code>
812 * @return a new <code>JDialog</code> containing this instance
813 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
814 * returns true.
815 * @see java.awt.GraphicsEnvironment#isHeadless
816 * @since 1.4
817 */
818 protected JDialog createDialog(Component parent) throws HeadlessException {
819 FileChooserUI ui = getUI();
820 String title = ui.getDialogTitle(this);
821 putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY,
822 title);
823
824 JDialog dialog;
825 Window window = JOptionPane.getWindowForComponent(parent);
826 if (window instanceof Frame) {
827 dialog = new JDialog((Frame)window, title, true);
828 } else {
829 dialog = new JDialog((Dialog)window, title, true);
830 }
831 dialog.setComponentOrientation(this.getComponentOrientation());
832
835 contentPane.add(this, BorderLayout.CENTER);
836
837 if (JDialog.isDefaultLookAndFeelDecorated()) {
838 boolean supportsWindowDecorations =
839 UIManager.getLookAndFeel().getSupportsWindowDecorations();
840 if (supportsWindowDecorations) {
841 dialog.getRootPane().setWindowDecorationStyle(JRootPane.FILE_CHOOSER_DIALOG);
842 }
843 }
844 dialog.pack();
845 dialog.setLocationRelativeTo(parent);
846
847 return dialog;
848 }
849
850 // **************************
851 // ***** Dialog Options *****
852 // **************************
853
854 /**
855 * Returns the value of the <code>controlButtonsAreShown</code>
856 * property.
857 *
858 * @return the value of the <code>controlButtonsAreShown</code>
859 * property
860 *
861 * @see #setControlButtonsAreShown
862 * @since 1.3
863 */
864 public boolean getControlButtonsAreShown() {
865 return controlsShown;
866 }
867
868
869 /**
870 * Sets the property
871 * that indicates whether the <i>approve</i> and <i>cancel</i>
872 * buttons are shown in the file chooser. This property
873 * is <code>true</code> by default. Look and feels
874 * that always show these buttons will ignore the value
875 * of this property.
876 * This method fires a property-changed event,
877 * using the string value of
878 * <code>CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY</code>
879 * as the name of the property.
880 *
881 * @param b <code>false</code> if control buttons should not be
882 * shown; otherwise, <code>true</code>
883 *
884 * @beaninfo
885 * preferred: true
886 * bound: true
887 * description: Sets whether the approve & cancel buttons are shown.
888 *
889 * @see #getControlButtonsAreShown
890 * @see #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY
891 * @since 1.3
892 */
893 public void setControlButtonsAreShown(boolean b) {
894 if(controlsShown == b) {
895 return;
896 }
897 boolean oldValue = controlsShown;
898 controlsShown = b;
899 firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY, oldValue, controlsShown);
900 }
901
902 /**
903 * Returns the type of this dialog. The default is
904 * <code>JFileChooser.OPEN_DIALOG</code>.
905 *
906 * @return the type of dialog to be displayed:
907 * <ul>
908 * <li>JFileChooser.OPEN_DIALOG
909 * <li>JFileChooser.SAVE_DIALOG
910 * <li>JFileChooser.CUSTOM_DIALOG
911 * </ul>
912 *
913 * @see #setDialogType
914 */
915 public int getDialogType() {
916 return dialogType;
917 }
918
919 /**
920 * Sets the type of this dialog. Use <code>OPEN_DIALOG</code> when you
921 * want to bring up a file chooser that the user can use to open a file.
922 * Likewise, use <code>SAVE_DIALOG</code> for letting the user choose
923 * a file for saving.
924 * Use <code>CUSTOM_DIALOG</code> when you want to use the file
925 * chooser in a context other than "Open" or "Save".
926 * For instance, you might want to bring up a file chooser that allows
927 * the user to choose a file to execute. Note that you normally would not
928 * need to set the <code>JFileChooser</code> to use
929 * <code>CUSTOM_DIALOG</code>
930 * since a call to <code>setApproveButtonText</code> does this for you.
931 * The default dialog type is <code>JFileChooser.OPEN_DIALOG</code>.
932 *
933 * @param dialogType the type of dialog to be displayed:
934 * <ul>
935 * <li>JFileChooser.OPEN_DIALOG
936 * <li>JFileChooser.SAVE_DIALOG
937 * <li>JFileChooser.CUSTOM_DIALOG
938 * </ul>
939 *
940 * @exception IllegalArgumentException if <code>dialogType</code> is
941 * not legal
942 * @beaninfo
943 * preferred: true
944 * bound: true
945 * description: The type (open, save, custom) of the JFileChooser.
946 * enum:
947 * OPEN_DIALOG JFileChooser.OPEN_DIALOG
948 * SAVE_DIALOG JFileChooser.SAVE_DIALOG
949 * CUSTOM_DIALOG JFileChooser.CUSTOM_DIALOG
950 *
951 * @see #getDialogType
952 * @see #setApproveButtonText
953 */
954 // PENDING(jeff) - fire button text change property
955 public void setDialogType(int dialogType) {
956 if(this.dialogType == dialogType) {
957 return;
958 }
959 checkDialogType(dialogType);
960 int oldValue = this.dialogType;
961 this.dialogType = dialogType;
962 if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) {
963 setApproveButtonText(null);
964 }
965 firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType);
966 }
967
968 private static void checkDialogType(int dialogType) {
969 if (!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG
970 || dialogType == CUSTOM_DIALOG)) {
971 throw new IllegalArgumentException(
972 "Incorrect Dialog Type: " + dialogType);
973 }
974 }
975
976 /**
977 * Sets the string that goes in the <code>JFileChooser</code> window's
978 * title bar.
979 *
980 * @param dialogTitle the new <code>String</code> for the title bar
981 *
982 * @beaninfo
983 * preferred: true
984 * bound: true
985 * description: The title of the JFileChooser dialog window.
986 *
987 * @see #getDialogTitle
988 *
989 */
990 public void setDialogTitle(String dialogTitle) {
991 String oldValue = this.dialogTitle;
992 this.dialogTitle = dialogTitle;
993 if(dialog != null) {
994 dialog.setTitle(dialogTitle);
995 }
996 firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue, dialogTitle);
997 }
998
999 /**
1000 * Gets the string that goes in the <code>JFileChooser</code>'s titlebar.
1001 *
1002 * @return the string from the {@code JFileChooser} window's title bar
1003 * @see #setDialogTitle
1004 */
1005 public String getDialogTitle() {
1006 return dialogTitle;
1007 }
1008
1009 // ************************************
1010 // ***** JFileChooser View Options *****
1011 // ************************************
1012
1013
1014
1015 /**
1016 * Sets the tooltip text used in the <code>ApproveButton</code>.
1017 * If <code>null</code>, the UI object will determine the button's text.
1018 *
1019 * @beaninfo
1020 * preferred: true
1021 * bound: true
1022 * description: The tooltip text for the ApproveButton.
1023 *
1024 * @param toolTipText the tooltip text for the approve button
1025 * @see #setApproveButtonText
1026 * @see #setDialogType
1027 * @see #showDialog
1028 */
1029 public void setApproveButtonToolTipText(String toolTipText) {
1030 if(approveButtonToolTipText == toolTipText) {
1031 return;
1032 }
1033 String oldValue = approveButtonToolTipText;
1034 approveButtonToolTipText = toolTipText;
1035 firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, oldValue, approveButtonToolTipText);
1036 }
1037
1038
1039 /**
1040 * Returns the tooltip text used in the <code>ApproveButton</code>.
1041 * If <code>null</code>, the UI object will determine the button's text.
1042 *
1043 * @return the tooltip text used for the approve button
1044 *
1045 * @see #setApproveButtonText
1046 * @see #setDialogType
1047 * @see #showDialog
1048 */
1049 public String getApproveButtonToolTipText() {
1050 return approveButtonToolTipText;
1051 }
1052
1053 /**
1054 * Returns the approve button's mnemonic.
1055 * @return an integer value for the mnemonic key
1056 *
1057 * @see #setApproveButtonMnemonic
1058 */
1059 public int getApproveButtonMnemonic() {
1060 return approveButtonMnemonic;
1061 }
1080 approveButtonMnemonic = mnemonic;
1081 firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY, oldValue, approveButtonMnemonic);
1082 }
1083
1084 /**
1085 * Sets the approve button's mnemonic using a character.
1086 * @param mnemonic a character value for the mnemonic key
1087 *
1088 * @see #getApproveButtonMnemonic
1089 */
1090 public void setApproveButtonMnemonic(char mnemonic) {
1091 int vk = (int) mnemonic;
1092 if(vk >= 'a' && vk <='z') {
1093 vk -= ('a' - 'A');
1094 }
1095 setApproveButtonMnemonic(vk);
1096 }
1097
1098
1099 /**
1100 * Sets the text used in the <code>ApproveButton</code> in the
1101 * <code>FileChooserUI</code>.
1102 *
1103 * @beaninfo
1104 * preferred: true
1105 * bound: true
1106 * description: The text that goes in the ApproveButton.
1107 *
1108 * @param approveButtonText the text used in the <code>ApproveButton</code>
1109 *
1110 * @see #getApproveButtonText
1111 * @see #setDialogType
1112 * @see #showDialog
1113 */
1114 // PENDING(jeff) - have ui set this on dialog type change
1115 public void setApproveButtonText(String approveButtonText) {
1116 if(this.approveButtonText == approveButtonText) {
1117 return;
1118 }
1119 String oldValue = this.approveButtonText;
1120 this.approveButtonText = approveButtonText;
1121 firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldValue, approveButtonText);
1122 }
1123
1124 /**
1125 * Returns the text used in the <code>ApproveButton</code> in the
1126 * <code>FileChooserUI</code>.
1127 * If <code>null</code>, the UI object will determine the button's text.
1128 *
1129 * Typically, this would be "Open" or "Save".
1130 *
1131 * @return the text used in the <code>ApproveButton</code>
1132 *
1133 * @see #setApproveButtonText
1134 * @see #setDialogType
1135 * @see #showDialog
1136 */
1137 public String getApproveButtonText() {
1138 return approveButtonText;
1139 }
1140
1141 /**
1142 * Gets the list of user choosable file filters.
1143 *
1144 * @return a <code>FileFilter</code> array containing all the choosable
1145 * file filters
1146 *
1147 * @see #addChoosableFileFilter
1148 * @see #removeChoosableFileFilter
1149 * @see #resetChoosableFileFilters
1150 */
1151 public FileFilter[] getChoosableFileFilters() {
1152 FileFilter[] filterArray = new FileFilter[filters.size()];
1153 filters.copyInto(filterArray);
1154 return filterArray;
1155 }
1156
1157 /**
1158 * Adds a filter to the list of user choosable file filters.
1159 * For information on setting the file selection mode, see
1160 * {@link #setFileSelectionMode setFileSelectionMode}.
1161 *
1162 * @param filter the <code>FileFilter</code> to add to the choosable file
1163 * filter list
1164 *
1165 * @beaninfo
1166 * preferred: true
1167 * bound: true
1168 * description: Adds a filter to the list of user choosable file filters.
1169 *
1170 * @see #getChoosableFileFilters
1171 * @see #removeChoosableFileFilter
1172 * @see #resetChoosableFileFilters
1173 * @see #setFileSelectionMode
1174 */
1175 public void addChoosableFileFilter(FileFilter filter) {
1176 if(filter != null && !filters.contains(filter)) {
1177 FileFilter[] oldValue = getChoosableFileFilters();
1178 filters.addElement(filter);
1179 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
1180 if (fileFilter == null && filters.size() == 1) {
1181 setFileFilter(filter);
1182 }
1210 // choose the second filter, because the first one is removed
1211 setFileFilter(filters.get(1));
1212 }
1213 else {
1214 // no more filters
1215 setFileFilter(null);
1216 }
1217 }
1218 FileFilter[] oldValue = getChoosableFileFilters();
1219 filters.removeElement(f);
1220 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
1221 return true;
1222 } else {
1223 return false;
1224 }
1225 }
1226
1227 /**
1228 * Resets the choosable file filter list to its starting state. Normally,
1229 * this removes all added file filters while leaving the
1230 * <code>AcceptAll</code> file filter.
1231 *
1232 * @see #addChoosableFileFilter
1233 * @see #getChoosableFileFilters
1234 * @see #removeChoosableFileFilter
1235 */
1236 public void resetChoosableFileFilters() {
1237 FileFilter[] oldValue = getChoosableFileFilters();
1238 setFileFilter(null);
1239 filters.removeAllElements();
1240 if(isAcceptAllFileFilterUsed()) {
1241 addChoosableFileFilter(getAcceptAllFileFilter());
1242 }
1243 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
1244 }
1245
1246 /**
1247 * Returns the <code>AcceptAll</code> file filter.
1248 * For example, on Microsoft Windows this would be All Files (*.*).
1249 *
1250 * @return the {@code AcceptAll} file filter
1251 */
1252 public FileFilter getAcceptAllFileFilter() {
1253 FileFilter filter = null;
1254 if(getUI() != null) {
1255 filter = getUI().getAcceptAllFileFilter(this);
1256 }
1257 return filter;
1258 }
1259
1260 /**
1261 * Returns whether the <code>AcceptAll FileFilter</code> is used.
1262 * @return true if the <code>AcceptAll FileFilter</code> is used
1263 * @see #setAcceptAllFileFilterUsed
1264 * @since 1.3
1265 */
1266 public boolean isAcceptAllFileFilterUsed() {
1267 return useAcceptAllFileFilter;
1268 }
1269
1270 /**
1271 * Determines whether the <code>AcceptAll FileFilter</code> is used
1272 * as an available choice in the choosable filter list.
1273 * If false, the <code>AcceptAll</code> file filter is removed from
1274 * the list of available file filters.
1275 * If true, the <code>AcceptAll</code> file filter will become the
1276 * actively used file filter.
1277 *
1278 * @param b a {@code boolean} which determines whether the {@code AcceptAll}
1279 * file filter is an available choice in the choosable filter list
1280 * @beaninfo
1281 * preferred: true
1282 * bound: true
1283 * description: Sets whether the AcceptAll FileFilter is used as an available choice in the choosable filter list.
1284 *
1285 * @see #isAcceptAllFileFilterUsed
1286 * @see #getAcceptAllFileFilter
1287 * @see #setFileFilter
1288 * @since 1.3
1289 */
1290 public void setAcceptAllFileFilterUsed(boolean b) {
1291 boolean oldValue = useAcceptAllFileFilter;
1292 useAcceptAllFileFilter = b;
1293 if(!b) {
1294 removeChoosableFileFilter(getAcceptAllFileFilter());
1295 } else {
1315 * that the programmer wishes, such as extra custom file chooser controls.
1316 *
1317 * <p>
1318 * Note: if there was a previous accessory, you should unregister
1319 * any listeners that the accessory might have registered with the
1320 * file chooser.
1321 *
1322 * @param newAccessory the accessory component to be set
1323 * @beaninfo
1324 * preferred: true
1325 * bound: true
1326 * description: Sets the accessory component on the JFileChooser.
1327 */
1328 public void setAccessory(JComponent newAccessory) {
1329 JComponent oldValue = accessory;
1330 accessory = newAccessory;
1331 firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue, accessory);
1332 }
1333
1334 /**
1335 * Sets the <code>JFileChooser</code> to allow the user to just
1336 * select files, just select
1337 * directories, or select both files and directories. The default is
1338 * <code>JFilesChooser.FILES_ONLY</code>.
1339 *
1340 * @param mode the type of files to be displayed:
1341 * <ul>
1342 * <li>JFileChooser.FILES_ONLY
1343 * <li>JFileChooser.DIRECTORIES_ONLY
1344 * <li>JFileChooser.FILES_AND_DIRECTORIES
1345 * </ul>
1346 *
1347 * @exception IllegalArgumentException if <code>mode</code> is an
1348 * illegal file selection mode
1349 * @beaninfo
1350 * preferred: true
1351 * bound: true
1352 * description: Sets the types of files that the JFileChooser can choose.
1353 * enum: FILES_ONLY JFileChooser.FILES_ONLY
1354 * DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY
1355 * FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES
1356 *
1357 *
1358 * @see #getFileSelectionMode
1359 */
1360 public void setFileSelectionMode(int mode) {
1361 if(fileSelectionMode == mode) {
1362 return;
1363 }
1364
1365 checkFileSelectionMode(mode);
1366 int oldValue = fileSelectionMode;
1367 fileSelectionMode = mode;
1368 firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode);
1369 }
1370
1371 private static void checkFileSelectionMode(int mode) {
1372 if ((mode != FILES_ONLY) && (mode != DIRECTORIES_ONLY)
1373 && (mode != FILES_AND_DIRECTORIES)) {
1374 throw new IllegalArgumentException(
1375 "Incorrect Mode for file selection: " + mode);
1376 }
1377 }
1378
1379 /**
1380 * Returns the current file-selection mode. The default is
1381 * <code>JFilesChooser.FILES_ONLY</code>.
1382 *
1383 * @return the type of files to be displayed, one of the following:
1384 * <ul>
1385 * <li>JFileChooser.FILES_ONLY
1386 * <li>JFileChooser.DIRECTORIES_ONLY
1387 * <li>JFileChooser.FILES_AND_DIRECTORIES
1388 * </ul>
1389 * @see #setFileSelectionMode
1390 */
1391 public int getFileSelectionMode() {
1392 return fileSelectionMode;
1393 }
1394
1395 /**
1396 * Convenience call that determines if files are selectable based on the
1397 * current file selection mode.
1398 *
1399 * @return true if files are selectable, false otherwise
1400 * @see #setFileSelectionMode
1401 * @see #getFileSelectionMode
1442 */
1443 public boolean isMultiSelectionEnabled() {
1444 return multiSelectionEnabled;
1445 }
1446
1447
1448 /**
1449 * Returns true if hidden files are not shown in the file chooser;
1450 * otherwise, returns false.
1451 *
1452 * @return the status of the file hiding property
1453 * @see #setFileHidingEnabled
1454 */
1455 public boolean isFileHidingEnabled() {
1456 return useFileHiding;
1457 }
1458
1459 /**
1460 * Sets file hiding on or off. If true, hidden files are not shown
1461 * in the file chooser. The job of determining which files are
1462 * shown is done by the <code>FileView</code>.
1463 *
1464 * @beaninfo
1465 * preferred: true
1466 * bound: true
1467 * description: Sets file hiding on or off.
1468 *
1469 * @param b the boolean value that determines whether file hiding is
1470 * turned on
1471 * @see #isFileHidingEnabled
1472 */
1473 public void setFileHidingEnabled(boolean b) {
1474 // Dump showFilesListener since we'll ignore it from now on
1475 if (showFilesListener != null) {
1476 Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener);
1477 showFilesListener = null;
1478 }
1479 boolean oldValue = useFileHiding;
1480 useFileHiding = b;
1481 firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, useFileHiding);
1482 }
1551 * Returns the current file view.
1552 *
1553 * @return the current file view
1554 * @see #setFileView
1555 */
1556 public FileView getFileView() {
1557 return fileView;
1558 }
1559
1560 // ******************************
1561 // *****FileView delegation *****
1562 // ******************************
1563
1564 // NOTE: all of the following methods attempt to delegate
1565 // first to the client set fileView, and if <code>null</code> is returned
1566 // (or there is now client defined fileView) then calls the
1567 // UI's default fileView.
1568
1569 /**
1570 * Returns the filename.
1571 * @param f the <code>File</code>
1572 * @return the <code>String</code> containing the filename for
1573 * <code>f</code>
1574 * @see FileView#getName
1575 */
1576 public String getName(File f) {
1577 String filename = null;
1578 if(f != null) {
1579 if(getFileView() != null) {
1580 filename = getFileView().getName(f);
1581 }
1582
1583 FileView uiFileView = getUI().getFileView(this);
1584
1585 if(filename == null && uiFileView != null) {
1586 filename = uiFileView.getName(f);
1587 }
1588 }
1589 return filename;
1590 }
1591
1592 /**
1593 * Returns the file description.
1594 * @param f the <code>File</code>
1595 * @return the <code>String</code> containing the file description for
1596 * <code>f</code>
1597 * @see FileView#getDescription
1598 */
1599 public String getDescription(File f) {
1600 String description = null;
1601 if(f != null) {
1602 if(getFileView() != null) {
1603 description = getFileView().getDescription(f);
1604 }
1605
1606 FileView uiFileView = getUI().getFileView(this);
1607
1608 if(description == null && uiFileView != null) {
1609 description = uiFileView.getDescription(f);
1610 }
1611 }
1612 return description;
1613 }
1614
1615 /**
1616 * Returns the file type.
1617 * @param f the <code>File</code>
1618 * @return the <code>String</code> containing the file type description for
1619 * <code>f</code>
1620 * @see FileView#getTypeDescription
1621 */
1622 public String getTypeDescription(File f) {
1623 String typeDescription = null;
1624 if(f != null) {
1625 if(getFileView() != null) {
1626 typeDescription = getFileView().getTypeDescription(f);
1627 }
1628
1629 FileView uiFileView = getUI().getFileView(this);
1630
1631 if(typeDescription == null && uiFileView != null) {
1632 typeDescription = uiFileView.getTypeDescription(f);
1633 }
1634 }
1635 return typeDescription;
1636 }
1637
1638 /**
1639 * Returns the icon for this file or type of file, depending
1640 * on the system.
1641 * @param f the <code>File</code>
1642 * @return the <code>Icon</code> for this file, or type of file
1643 * @see FileView#getIcon
1644 */
1645 public Icon getIcon(File f) {
1646 Icon icon = null;
1647 if (f != null) {
1648 if(getFileView() != null) {
1649 icon = getFileView().getIcon(f);
1650 }
1651
1652 FileView uiFileView = getUI().getFileView(this);
1653
1654 if(icon == null && uiFileView != null) {
1655 icon = uiFileView.getIcon(f);
1656 }
1657 }
1658 return icon;
1659 }
1660
1661 /**
1662 * Returns true if the file (directory) can be visited.
1663 * Returns false if the directory cannot be traversed.
1664 * @param f the <code>File</code>
1665 * @return true if the file/directory can be traversed, otherwise false
1666 * @see FileView#isTraversable
1667 */
1668 public boolean isTraversable(File f) {
1669 Boolean traversable = null;
1670 if (f != null) {
1671 if (getFileView() != null) {
1672 traversable = getFileView().isTraversable(f);
1673 }
1674
1675 FileView uiFileView = getUI().getFileView(this);
1676
1677 if (traversable == null && uiFileView != null) {
1678 traversable = uiFileView.isTraversable(f);
1679 }
1680 if (traversable == null) {
1681 traversable = getFileSystemView().isTraversable(f);
1682 }
1683 }
1684 return (traversable != null && traversable.booleanValue());
1685 }
1686
1687 /**
1688 * Returns true if the file should be displayed.
1689 * @param f the <code>File</code>
1690 * @return true if the file should be displayed, otherwise false
1691 * @see FileFilter#accept
1692 */
1693 public boolean accept(File f) {
1694 boolean shown = true;
1695 if(f != null && fileFilter != null) {
1696 shown = fileFilter.accept(f);
1697 }
1698 return shown;
1699 }
1700
1701 /**
1702 * Sets the file system view that the <code>JFileChooser</code> uses for
1703 * accessing and creating file system resources, such as finding
1704 * the floppy drive and getting a list of root drives.
1705 * @param fsv the new <code>FileSystemView</code>
1706 *
1707 * @beaninfo
1708 * expert: true
1709 * bound: true
1710 * description: Sets the FileSytemView used to get filesystem information.
1711 *
1712 * @see FileSystemView
1713 */
1714 public void setFileSystemView(FileSystemView fsv) {
1715 FileSystemView oldValue = fileSystemView;
1716 fileSystemView = fsv;
1717 firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue, fileSystemView);
1718 }
1719
1720 /**
1721 * Returns the file system view.
1722 * @return the <code>FileSystemView</code> object
1723 * @see #setFileSystemView
1724 */
1725 public FileSystemView getFileSystemView() {
1726 return fileSystemView;
1727 }
1728
1729 // **************************
1730 // ***** Event Handling *****
1731 // **************************
1732
1733 /**
1734 * Called by the UI when the user hits the Approve button
1735 * (labeled "Open" or "Save", by default). This can also be
1736 * called by the programmer.
1737 * This method causes an action event to fire
1738 * with the command string equal to
1739 * <code>APPROVE_SELECTION</code>.
1740 *
1741 * @see #APPROVE_SELECTION
1742 */
1743 public void approveSelection() {
1744 returnValue = APPROVE_OPTION;
1745 if(dialog != null) {
1746 dialog.setVisible(false);
1747 }
1748 fireActionPerformed(APPROVE_SELECTION);
1749 }
1750
1751 /**
1752 * Called by the UI when the user chooses the Cancel button.
1753 * This can also be called by the programmer.
1754 * This method causes an action event to fire
1755 * with the command string equal to
1756 * <code>CANCEL_SELECTION</code>.
1757 *
1758 * @see #CANCEL_SELECTION
1759 */
1760 public void cancelSelection() {
1761 returnValue = CANCEL_OPTION;
1762 if(dialog != null) {
1763 dialog.setVisible(false);
1764 }
1765 fireActionPerformed(CANCEL_SELECTION);
1766 }
1767
1768 /**
1769 * Adds an <code>ActionListener</code> to the file chooser.
1770 *
1771 * @param l the listener to be added
1772 *
1773 * @see #approveSelection
1774 * @see #cancelSelection
1775 */
1776 public void addActionListener(ActionListener l) {
1777 listenerList.add(ActionListener.class, l);
1778 }
1779
1780 /**
1781 * Removes an <code>ActionListener</code> from the file chooser.
1782 *
1783 * @param l the listener to be removed
1784 *
1785 * @see #addActionListener
1786 */
1787 public void removeActionListener(ActionListener l) {
1788 listenerList.remove(ActionListener.class, l);
1789 }
1790
1791 /**
1792 * Returns an array of all the action listeners
1793 * registered on this file chooser.
1794 *
1795 * @return all of this file chooser's <code>ActionListener</code>s
1796 * or an empty
1797 * array if no action listeners are currently registered
1798 *
1799 * @see #addActionListener
1800 * @see #removeActionListener
1801 *
1802 * @since 1.4
1803 */
1804 public ActionListener[] getActionListeners() {
1805 return listenerList.getListeners(ActionListener.class);
1806 }
1807
1808 /**
1809 * Notifies all listeners that have registered interest for
1810 * notification on this event type. The event instance
1811 * is lazily created using the <code>command</code> parameter.
1812 *
1813 * @param command a string that may specify a command associated with
1814 * the event
1815 * @see EventListenerList
1816 */
1817 protected void fireActionPerformed(String command) {
1818 // Guaranteed to return a non-null array
1819 Object[] listeners = listenerList.getListenerList();
1820 long mostRecentEventTime = EventQueue.getMostRecentEventTime();
1821 int modifiers = 0;
1822 AWTEvent currentEvent = EventQueue.getCurrentEvent();
1823 if (currentEvent instanceof InputEvent) {
1824 modifiers = ((InputEvent)currentEvent).getModifiers();
1825 } else if (currentEvent instanceof ActionEvent) {
1826 modifiers = ((ActionEvent)currentEvent).getModifiers();
1827 }
1828 ActionEvent e = null;
1829 // Process the listeners last to first, notifying
1830 // those that are interested in this event
1831 for (int i = listeners.length-2; i>=0; i-=2) {
1896 * @see JComponent#getUIClassID
1897 * @see UIDefaults#getUI
1898 * @beaninfo
1899 * expert: true
1900 * description: A string that specifies the name of the L&F class.
1901 */
1902 public String getUIClassID() {
1903 return uiClassID;
1904 }
1905
1906 /**
1907 * Gets the UI object which implements the L&F for this component.
1908 *
1909 * @return the FileChooserUI object that implements the FileChooserUI L&F
1910 */
1911 public FileChooserUI getUI() {
1912 return (FileChooserUI) ui;
1913 }
1914
1915 /**
1916 * See <code>readObject</code> and <code>writeObject</code> in
1917 * <code>JComponent</code> for more
1918 * information about serialization in Swing.
1919 */
1920 private void readObject(java.io.ObjectInputStream in)
1921 throws IOException, ClassNotFoundException {
1922 ObjectInputStream.GetField f = in.readFields();
1923
1924 dialogTitle = (String) f.get("dialogTitle", null);
1925 approveButtonText = (String) f.get("approveButtonText", null);
1926 approveButtonToolTipText =
1927 (String) f.get("approveButtonToolTipText", null);
1928 approveButtonMnemonic = f.get("approveButtonMnemonic", 0);
1929 @SuppressWarnings("unchecked")
1930 Vector<FileFilter> newFilters = (Vector<FileFilter>) f.get("filters", null);
1931 if (newFilters == null) {
1932 throw new InvalidObjectException("Null filters");
1933 }
1934 filters = newFilters;
1935 dialog = (JDialog) f.get("dialog", null);
1936 int newDialogType = f.get("dialogType", OPEN_DIALOG);
1937 checkDialogType(newDialogType);
1943 useFileHiding = f.get("useFileHiding", false);
1944 int newFileSelectionMode = f.get("fileSelectionMode", FILES_ONLY);
1945 checkFileSelectionMode(newFileSelectionMode);
1946 fileSelectionMode = newFileSelectionMode;
1947 multiSelectionEnabled = f.get("multiSelectionEnabled", false);
1948 useAcceptAllFileFilter = f.get("useAcceptAllFileFilter", false);
1949 boolean newDragEnabled = f.get("dragEnabled", false);
1950 checkDragEnabled(newDragEnabled);
1951 dragEnabled = newDragEnabled;
1952 fileFilter = (FileFilter) f.get("fileFilter", null);
1953 fileSystemView = (FileSystemView) f.get("fileSystemView", null);
1954 currentDirectory = (File) f.get("currentDirectory", null);
1955 selectedFile = (File) f.get("selectedFile", null);
1956 selectedFiles = (File[]) f.get("selectedFiles", null);
1957 accessibleContext = (AccessibleContext) f.get("accessibleContext", null);
1958
1959 installShowFilesListener();
1960 }
1961
1962 /**
1963 * See <code>readObject</code> and <code>writeObject</code> in
1964 * <code>JComponent</code> for more
1965 * information about serialization in Swing.
1966 */
1967 private void writeObject(ObjectOutputStream s) throws IOException {
1968 FileSystemView fsv = null;
1969
1970 if (isAcceptAllFileFilterUsed()) {
1971 //The AcceptAllFileFilter is UI specific, it will be reset by
1972 //updateUI() after deserialization
1973 removeChoosableFileFilter(getAcceptAllFileFilter());
1974 }
1975 if (fileSystemView.equals(FileSystemView.getFileSystemView())) {
1976 //The default FileSystemView is platform specific, it will be
1977 //reset by updateUI() after deserialization
1978 fsv = fileSystemView;
1979 fileSystemView = null;
1980 }
1981 s.defaultWriteObject();
1982 if (fsv != null) {
1983 fileSystemView = fsv;
1984 }
1985 if (isAcceptAllFileFilterUsed()) {
1986 addChoosableFileFilter(getAcceptAllFileFilter());
1987 }
1988 if (getUIClassID().equals(uiClassID)) {
1989 byte count = JComponent.getWriteObjCounter(this);
1990 JComponent.setWriteObjCounter(this, --count);
1991 if (count == 0 && ui != null) {
1992 ui.installUI(this);
1993 }
1994 }
1995 }
1996
1997
1998 /**
1999 * Returns a string representation of this <code>JFileChooser</code>.
2000 * This method
2001 * is intended to be used only for debugging purposes, and the
2002 * content and format of the returned string may vary between
2003 * implementations. The returned string may be empty but may not
2004 * be <code>null</code>.
2005 *
2006 * @return a string representation of this <code>JFileChooser</code>
2007 */
2008 protected String paramString() {
2009 String approveButtonTextString = (approveButtonText != null ?
2010 approveButtonText: "");
2011 String dialogTitleString = (dialogTitle != null ?
2012 dialogTitle: "");
2013 String dialogTypeString;
2014 if (dialogType == OPEN_DIALOG) {
2015 dialogTypeString = "OPEN_DIALOG";
2016 } else if (dialogType == SAVE_DIALOG) {
2017 dialogTypeString = "SAVE_DIALOG";
2018 } else if (dialogType == CUSTOM_DIALOG) {
2019 dialogTypeString = "CUSTOM_DIALOG";
2020 } else dialogTypeString = "";
2021 String returnValueString;
2022 if (returnValue == CANCEL_OPTION) {
2023 returnValueString = "CANCEL_OPTION";
2024 } else if (returnValue == APPROVE_OPTION) {
2025 returnValueString = "APPROVE_OPTION";
2026 } else if (returnValue == ERROR_OPTION) {
2062 protected AccessibleContext accessibleContext = null;
2063
2064 /**
2065 * Gets the AccessibleContext associated with this JFileChooser.
2066 * For file choosers, the AccessibleContext takes the form of an
2067 * AccessibleJFileChooser.
2068 * A new AccessibleJFileChooser instance is created if necessary.
2069 *
2070 * @return an AccessibleJFileChooser that serves as the
2071 * AccessibleContext of this JFileChooser
2072 */
2073 public AccessibleContext getAccessibleContext() {
2074 if (accessibleContext == null) {
2075 accessibleContext = new AccessibleJFileChooser();
2076 }
2077 return accessibleContext;
2078 }
2079
2080 /**
2081 * This class implements accessibility support for the
2082 * <code>JFileChooser</code> class. It provides an implementation of the
2083 * Java Accessibility API appropriate to file chooser user-interface
2084 * elements.
2085 */
2086 @SuppressWarnings("serial") // Superclass is not serializable across versions
2087 protected class AccessibleJFileChooser extends AccessibleJComponent {
2088
2089 /**
2090 * Gets the role of this object.
2091 *
2092 * @return an instance of AccessibleRole describing the role of the
2093 * object
2094 * @see AccessibleRole
2095 */
2096 public AccessibleRole getAccessibleRole() {
2097 return AccessibleRole.FILE_CHOOSER;
2098 }
2099
2100 } // inner class AccessibleJFileChooser
2101
2102 }
|
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.io.InvalidObjectException;
54 import java.io.ObjectInputStream;
55 import java.lang.ref.WeakReference;
56
57 /**
58 * {@code JFileChooser} provides a simple mechanism for the user to
59 * choose a file.
60 * For information about using {@code JFileChooser}, see
61 * <a
62 href="http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html">How to Use File Choosers</a>,
63 * a section in <em>The Java Tutorial</em>.
64 *
65 * <p>
66 *
67 * The following code pops up a file chooser for the user's home directory that
68 * sees only .jpg and .gif images:
69 * <pre>
70 * JFileChooser chooser = new JFileChooser();
71 * FileNameExtensionFilter filter = new FileNameExtensionFilter(
72 * "JPG & GIF Images", "jpg", "gif");
73 * chooser.setFileFilter(filter);
74 * int returnVal = chooser.showOpenDialog(parent);
75 * if(returnVal == JFileChooser.APPROVE_OPTION) {
76 * System.out.println("You chose to open this file: " +
77 * chooser.getSelectedFile().getName());
78 * }
79 * </pre>
80 * <p>
87 * attribute: isContainer false
88 * description: A component which allows for the interactive selection of a file.
89 *
90 * @author Jeff Dinkins
91 * @since 1.2
92 */
93 @SuppressWarnings("serial") // Superclass is not serializable across versions
94 public class JFileChooser extends JComponent implements Accessible {
95
96 /**
97 * @see #getUIClassID
98 * @see #readObject
99 */
100 private static final String uiClassID = "FileChooserUI";
101
102 // ************************
103 // ***** Dialog Types *****
104 // ************************
105
106 /**
107 * Type value indicating that the {@code JFileChooser} supports an
108 * "Open" file operation.
109 */
110 public static final int OPEN_DIALOG = 0;
111
112 /**
113 * Type value indicating that the {@code JFileChooser} supports a
114 * "Save" file operation.
115 */
116 public static final int SAVE_DIALOG = 1;
117
118 /**
119 * Type value indicating that the {@code JFileChooser} supports a
120 * developer-specified file operation.
121 */
122 public static final int CUSTOM_DIALOG = 2;
123
124
125 // ********************************
126 // ***** Dialog Return Values *****
127 // ********************************
128
129 /**
130 * Return value if cancel is chosen.
131 */
132 public static final int CANCEL_OPTION = 1;
133
134 /**
135 * Return value if approve (yes, ok) is chosen.
136 */
137 public static final int APPROVE_OPTION = 0;
138
139 /**
273
274 private boolean multiSelectionEnabled = false;
275
276 private boolean useAcceptAllFileFilter = true;
277
278 private boolean dragEnabled = false;
279
280 private FileFilter fileFilter = null;
281
282 private FileSystemView fileSystemView = null;
283
284 private File currentDirectory = null;
285 private File selectedFile = null;
286 private File[] selectedFiles;
287
288 // *************************************
289 // ***** JFileChooser Constructors *****
290 // *************************************
291
292 /**
293 * Constructs a {@code JFileChooser} pointing to the user's
294 * default directory. This default depends on the operating system.
295 * It is typically the "My Documents" folder on Windows, and the
296 * user's home directory on Unix.
297 */
298 public JFileChooser() {
299 this((File) null, (FileSystemView) null);
300 }
301
302 /**
303 * Constructs a {@code JFileChooser} using the given path.
304 * Passing in a {@code null}
305 * string causes the file chooser to point to the user's default directory.
306 * This default depends on the operating system. It is
307 * typically the "My Documents" folder on Windows, and the user's
308 * home directory on Unix.
309 *
310 * @param currentDirectoryPath a {@code String} giving the path
311 * to a file or directory
312 */
313 public JFileChooser(String currentDirectoryPath) {
314 this(currentDirectoryPath, (FileSystemView) null);
315 }
316
317 /**
318 * Constructs a {@code JFileChooser} using the given {@code File}
319 * as the path. Passing in a {@code null} file
320 * causes the file chooser to point to the user's default directory.
321 * This default depends on the operating system. It is
322 * typically the "My Documents" folder on Windows, and the user's
323 * home directory on Unix.
324 *
325 * @param currentDirectory a {@code File} object specifying
326 * the path to a file or directory
327 */
328 public JFileChooser(File currentDirectory) {
329 this(currentDirectory, (FileSystemView) null);
330 }
331
332 /**
333 * Constructs a {@code JFileChooser} using the given
334 * {@code FileSystemView}.
335 *
336 * @param fsv a {@code FileSystemView}
337 */
338 public JFileChooser(FileSystemView fsv) {
339 this((File) null, fsv);
340 }
341
342
343 /**
344 * Constructs a {@code JFileChooser} using the given current directory
345 * and {@code FileSystemView}.
346 *
347 * @param currentDirectory a {@code File} object specifying the path to a
348 * file or directory
349 * @param fsv a {@code FileSystemView}
350 */
351 public JFileChooser(File currentDirectory, FileSystemView fsv) {
352 setup(fsv);
353 setCurrentDirectory(currentDirectory);
354 }
355
356 /**
357 * Constructs a {@code JFileChooser} using the given current directory
358 * path and {@code FileSystemView}.
359 *
360 * @param currentDirectoryPath a {@code String} specifying the path to a file
361 * or directory
362 * @param fsv a {@code FileSystemView}
363 */
364 public JFileChooser(String currentDirectoryPath, FileSystemView fsv) {
365 setup(fsv);
366 if(currentDirectoryPath == null) {
367 setCurrentDirectory(null);
368 } else {
369 setCurrentDirectory(fileSystemView.createFileObject(currentDirectoryPath));
370 }
371 }
372
373 /**
374 * Performs common constructor initialization and setup.
375 *
376 * @param view the {@code FileSystemView} used for setup
377 */
378 protected void setup(FileSystemView view) {
401 if (rootPane != null) {
402 rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc));
403 }
404 }
405 }
406 });
407 }
408
409 private void installShowFilesListener() {
410 // Track native setting for showing hidden files
411 Toolkit tk = Toolkit.getDefaultToolkit();
412 Object showHiddenProperty = tk.getDesktopProperty(SHOW_HIDDEN_PROP);
413 if (showHiddenProperty instanceof Boolean) {
414 useFileHiding = !((Boolean)showHiddenProperty).booleanValue();
415 showFilesListener = new WeakPCL(this);
416 tk.addPropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener);
417 }
418 }
419
420 /**
421 * Sets the {@code dragEnabled} property,
422 * which must be {@code true} to enable
423 * automatic drag handling (the first part of drag and drop)
424 * on this component.
425 * The {@code transferHandler} property needs to be set
426 * to a non-{@code null} value for the drag to do
427 * anything. The default value of the {@code dragEnabled}
428 * property
429 * is {@code false}.
430 *
431 * <p>
432 *
433 * When automatic drag handling is enabled,
434 * most look and feels begin a drag-and-drop operation
435 * whenever the user presses the mouse button over an item
436 * and then moves the mouse a few pixels.
437 * Setting this property to {@code true}
438 * can therefore have a subtle effect on
439 * how selections behave.
440 *
441 * <p>
442 *
443 * Some look and feels might not support automatic drag and drop;
444 * they will ignore this property. You can work around such
445 * look and feels by modifying the component
446 * to directly call the {@code exportAsDrag} method of a
447 * {@code TransferHandler}.
448 *
449 * @param b the value to set the {@code dragEnabled} property to
450 * @exception HeadlessException if
451 * {@code b} is {@code true} and
452 * {@code GraphicsEnvironment.isHeadless()}
453 * returns {@code true}
454 * @see java.awt.GraphicsEnvironment#isHeadless
455 * @see #getDragEnabled
456 * @see #setTransferHandler
457 * @see TransferHandler
458 * @since 1.4
459 *
460 * @beaninfo
461 * description: determines whether automatic drag handling is enabled
462 * bound: false
463 */
464 public void setDragEnabled(boolean b) {
465 checkDragEnabled(b);
466 dragEnabled = b;
467 }
468
469 private static void checkDragEnabled(boolean b) {
470 if (b && GraphicsEnvironment.isHeadless()) {
471 throw new HeadlessException();
472 }
473 }
474
475 /**
476 * Gets the value of the {@code dragEnabled} property.
477 *
478 * @return the value of the {@code dragEnabled} property
479 * @see #setDragEnabled
480 * @since 1.4
481 */
482 public boolean getDragEnabled() {
483 return dragEnabled;
484 }
485
486 // *****************************
487 // ****** File Operations ******
488 // *****************************
489
490 /**
491 * Returns the selected file. This can be set either by the
492 * programmer via {@code setSelectedFile} or by a user action, such as
493 * either typing the filename into the UI or selecting the
494 * file from a list in the UI.
495 *
496 * @see #setSelectedFile
497 * @return the selected file
498 */
499 public File getSelectedFile() {
500 return selectedFile;
501 }
502
503 /**
504 * Sets the selected file. If the file's parent directory is
505 * not the current directory, changes the current directory
506 * to be the file's parent directory.
507 *
508 * @beaninfo
509 * preferred: true
510 * bound: true
511 *
512 * @see #getSelectedFile
557 this.selectedFiles = null;
558 setSelectedFile(null);
559 } else {
560 this.selectedFiles = selectedFiles.clone();
561 setSelectedFile(this.selectedFiles[0]);
562 }
563 firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, selectedFiles);
564 }
565
566 /**
567 * Returns the current directory.
568 *
569 * @return the current directory
570 * @see #setCurrentDirectory
571 */
572 public File getCurrentDirectory() {
573 return currentDirectory;
574 }
575
576 /**
577 * Sets the current directory. Passing in {@code null} sets the
578 * file chooser to point to the user's default directory.
579 * This default depends on the operating system. It is
580 * typically the "My Documents" folder on Windows, and the user's
581 * home directory on Unix.
582 *
583 * If the file passed in as {@code currentDirectory} is not a
584 * directory, the parent of the file will be used as the currentDirectory.
585 * If the parent is not traversable, then it will walk up the parent tree
586 * until it finds a traversable directory, or hits the root of the
587 * file system.
588 *
589 * @beaninfo
590 * preferred: true
591 * bound: true
592 * description: The directory that the JFileChooser is showing files of.
593 *
594 * @param dir the current directory to point to
595 * @see #getCurrentDirectory
596 */
597 public void setCurrentDirectory(File dir) {
598 File oldValue = currentDirectory;
599
600 if (dir != null && !dir.exists()) {
601 dir = currentDirectory;
602 }
603 if (dir == null) {
642 /**
643 * Makes sure that the specified file is viewable, and
644 * not hidden.
645 *
646 * @param f a File object
647 */
648 public void ensureFileIsVisible(File f) {
649 getUI().ensureFileIsVisible(this, f);
650 }
651
652 // **************************************
653 // ***** JFileChooser Dialog methods *****
654 // **************************************
655
656 /**
657 * Pops up an "Open File" file chooser dialog. Note that the
658 * text that appears in the approve button is determined by
659 * the L&F.
660 *
661 * @param parent the parent component of the dialog,
662 * can be {@code null};
663 * see {@code showDialog} for details
664 * @return the return state of the file chooser on popdown:
665 * <ul>
666 * <li>JFileChooser.CANCEL_OPTION
667 * <li>JFileChooser.APPROVE_OPTION
668 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
669 * dialog is dismissed
670 * </ul>
671 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
672 * returns true.
673 * @see java.awt.GraphicsEnvironment#isHeadless
674 * @see #showDialog
675 */
676 public int showOpenDialog(Component parent) throws HeadlessException {
677 setDialogType(OPEN_DIALOG);
678 return showDialog(parent, null);
679 }
680
681 /**
682 * Pops up a "Save File" file chooser dialog. Note that the
683 * text that appears in the approve button is determined by
684 * the L&F.
685 *
686 * @param parent the parent component of the dialog,
687 * can be {@code null};
688 * see {@code showDialog} for details
689 * @return the return state of the file chooser on popdown:
690 * <ul>
691 * <li>JFileChooser.CANCEL_OPTION
692 * <li>JFileChooser.APPROVE_OPTION
693 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
694 * dialog is dismissed
695 * </ul>
696 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
697 * returns true.
698 * @see java.awt.GraphicsEnvironment#isHeadless
699 * @see #showDialog
700 */
701 public int showSaveDialog(Component parent) throws HeadlessException {
702 setDialogType(SAVE_DIALOG);
703 return showDialog(parent, null);
704 }
705
706 /**
707 * Pops a custom file chooser dialog with a custom approve button.
708 * For example, the following code
709 * pops up a file chooser with a "Run Application" button
710 * (instead of the normal "Save" or "Open" button):
711 * <pre>
712 * filechooser.showDialog(parentFrame, "Run Application");
713 * </pre>
714 *
715 * Alternatively, the following code does the same thing:
716 * <pre>
717 * JFileChooser chooser = new JFileChooser(null);
718 * chooser.setApproveButtonText("Run Application");
719 * chooser.showDialog(parentFrame, null);
720 * </pre>
721 *
722 * <!--PENDING(jeff) - the following method should be added to the api:
723 * showDialog(Component parent);-->
724 * <!--PENDING(kwalrath) - should specify modality and what
725 * "depends" means.-->
726 *
727 * <p>
728 *
729 * The {@code parent} argument determines two things:
730 * the frame on which the open dialog depends and
731 * the component whose position the look and feel
732 * should consider when placing the dialog. If the parent
733 * is a {@code Frame} object (such as a {@code JFrame})
734 * then the dialog depends on the frame and
735 * the look and feel positions the dialog
736 * relative to the frame (for example, centered over the frame).
737 * If the parent is a component, then the dialog
738 * depends on the frame containing the component,
739 * and is positioned relative to the component
740 * (for example, centered over the component).
741 * If the parent is {@code null}, then the dialog depends on
742 * no visible window, and it's placed in a
743 * look-and-feel-dependent position
744 * such as the center of the screen.
745 *
746 * @param parent the parent component of the dialog;
747 * can be {@code null}
748 * @param approveButtonText the text of the {@code ApproveButton}
749 * @return the return state of the file chooser on popdown:
750 * <ul>
751 * <li>JFileChooser.CANCEL_OPTION
752 * <li>JFileChooser.APPROVE_OPTION
753 * <li>JFileChooser.ERROR_OPTION if an error occurs or the
754 * dialog is dismissed
755 * </ul>
756 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
757 * returns true.
758 * @see java.awt.GraphicsEnvironment#isHeadless
759 */
760 @SuppressWarnings("deprecation")
761 public int showDialog(Component parent, String approveButtonText)
762 throws HeadlessException {
763 if (dialog != null) {
764 // Prevent to show second instance of dialog if the previous one still exists
765 return JFileChooser.ERROR_OPTION;
766 }
767
768 if(approveButtonText != null) {
774 public void windowClosing(WindowEvent e) {
775 returnValue = CANCEL_OPTION;
776 }
777 });
778 returnValue = ERROR_OPTION;
779 rescanCurrentDirectory();
780
781 dialog.show();
782 firePropertyChange("JFileChooserDialogIsClosingProperty", dialog, null);
783
784 // Remove all components from dialog. The MetalFileChooserUI.installUI() method (and other LAFs)
785 // registers AWT listener for dialogs and produces memory leaks. It happens when
786 // installUI invoked after the showDialog method.
787 dialog.getContentPane().removeAll();
788 dialog.dispose();
789 dialog = null;
790 return returnValue;
791 }
792
793 /**
794 * Creates and returns a new {@code JDialog} wrapping
795 * {@code this} centered on the {@code parent}
796 * in the {@code parent}'s frame.
797 * This method can be overriden to further manipulate the dialog,
798 * to disable resizing, set the location, etc. Example:
799 * <pre>
800 * class MyFileChooser extends JFileChooser {
801 * protected JDialog createDialog(Component parent) throws HeadlessException {
802 * JDialog dialog = super.createDialog(parent);
803 * dialog.setLocation(300, 200);
804 * dialog.setResizable(false);
805 * return dialog;
806 * }
807 * }
808 * </pre>
809 *
810 * @param parent the parent component of the dialog;
811 * can be {@code null}
812 * @return a new {@code JDialog} containing this instance
813 * @exception HeadlessException if GraphicsEnvironment.isHeadless()
814 * returns true.
815 * @see java.awt.GraphicsEnvironment#isHeadless
816 * @since 1.4
817 */
818 protected JDialog createDialog(Component parent) throws HeadlessException {
819 FileChooserUI ui = getUI();
820 String title = ui.getDialogTitle(this);
821 putClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY,
822 title);
823
824 JDialog dialog;
825 Window window = JOptionPane.getWindowForComponent(parent);
826 if (window instanceof Frame) {
827 dialog = new JDialog((Frame)window, title, true);
828 } else {
829 dialog = new JDialog((Dialog)window, title, true);
830 }
831 dialog.setComponentOrientation(this.getComponentOrientation());
832
835 contentPane.add(this, BorderLayout.CENTER);
836
837 if (JDialog.isDefaultLookAndFeelDecorated()) {
838 boolean supportsWindowDecorations =
839 UIManager.getLookAndFeel().getSupportsWindowDecorations();
840 if (supportsWindowDecorations) {
841 dialog.getRootPane().setWindowDecorationStyle(JRootPane.FILE_CHOOSER_DIALOG);
842 }
843 }
844 dialog.pack();
845 dialog.setLocationRelativeTo(parent);
846
847 return dialog;
848 }
849
850 // **************************
851 // ***** Dialog Options *****
852 // **************************
853
854 /**
855 * Returns the value of the {@code controlButtonsAreShown}
856 * property.
857 *
858 * @return the value of the {@code controlButtonsAreShown}
859 * property
860 *
861 * @see #setControlButtonsAreShown
862 * @since 1.3
863 */
864 public boolean getControlButtonsAreShown() {
865 return controlsShown;
866 }
867
868
869 /**
870 * Sets the property
871 * that indicates whether the <i>approve</i> and <i>cancel</i>
872 * buttons are shown in the file chooser. This property
873 * is {@code true} by default. Look and feels
874 * that always show these buttons will ignore the value
875 * of this property.
876 * This method fires a property-changed event,
877 * using the string value of
878 * {@code CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY}
879 * as the name of the property.
880 *
881 * @param b {@code false} if control buttons should not be
882 * shown; otherwise, {@code true}
883 *
884 * @beaninfo
885 * preferred: true
886 * bound: true
887 * description: Sets whether the approve & cancel buttons are shown.
888 *
889 * @see #getControlButtonsAreShown
890 * @see #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY
891 * @since 1.3
892 */
893 public void setControlButtonsAreShown(boolean b) {
894 if(controlsShown == b) {
895 return;
896 }
897 boolean oldValue = controlsShown;
898 controlsShown = b;
899 firePropertyChange(CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY, oldValue, controlsShown);
900 }
901
902 /**
903 * Returns the type of this dialog. The default is
904 * {@code JFileChooser.OPEN_DIALOG}.
905 *
906 * @return the type of dialog to be displayed:
907 * <ul>
908 * <li>JFileChooser.OPEN_DIALOG
909 * <li>JFileChooser.SAVE_DIALOG
910 * <li>JFileChooser.CUSTOM_DIALOG
911 * </ul>
912 *
913 * @see #setDialogType
914 */
915 public int getDialogType() {
916 return dialogType;
917 }
918
919 /**
920 * Sets the type of this dialog. Use {@code OPEN_DIALOG} when you
921 * want to bring up a file chooser that the user can use to open a file.
922 * Likewise, use {@code SAVE_DIALOG} for letting the user choose
923 * a file for saving.
924 * Use {@code CUSTOM_DIALOG} when you want to use the file
925 * chooser in a context other than "Open" or "Save".
926 * For instance, you might want to bring up a file chooser that allows
927 * the user to choose a file to execute. Note that you normally would not
928 * need to set the {@code JFileChooser} to use
929 * {@code CUSTOM_DIALOG}
930 * since a call to {@code setApproveButtonText} does this for you.
931 * The default dialog type is {@code JFileChooser.OPEN_DIALOG}.
932 *
933 * @param dialogType the type of dialog to be displayed:
934 * <ul>
935 * <li>JFileChooser.OPEN_DIALOG
936 * <li>JFileChooser.SAVE_DIALOG
937 * <li>JFileChooser.CUSTOM_DIALOG
938 * </ul>
939 *
940 * @exception IllegalArgumentException if {@code dialogType} is
941 * not legal
942 * @beaninfo
943 * preferred: true
944 * bound: true
945 * description: The type (open, save, custom) of the JFileChooser.
946 * enum:
947 * OPEN_DIALOG JFileChooser.OPEN_DIALOG
948 * SAVE_DIALOG JFileChooser.SAVE_DIALOG
949 * CUSTOM_DIALOG JFileChooser.CUSTOM_DIALOG
950 *
951 * @see #getDialogType
952 * @see #setApproveButtonText
953 */
954 // PENDING(jeff) - fire button text change property
955 public void setDialogType(int dialogType) {
956 if(this.dialogType == dialogType) {
957 return;
958 }
959 checkDialogType(dialogType);
960 int oldValue = this.dialogType;
961 this.dialogType = dialogType;
962 if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) {
963 setApproveButtonText(null);
964 }
965 firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType);
966 }
967
968 private static void checkDialogType(int dialogType) {
969 if (!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG
970 || dialogType == CUSTOM_DIALOG)) {
971 throw new IllegalArgumentException(
972 "Incorrect Dialog Type: " + dialogType);
973 }
974 }
975
976 /**
977 * Sets the string that goes in the {@code JFileChooser} window's
978 * title bar.
979 *
980 * @param dialogTitle the new {@code String} for the title bar
981 *
982 * @beaninfo
983 * preferred: true
984 * bound: true
985 * description: The title of the JFileChooser dialog window.
986 *
987 * @see #getDialogTitle
988 *
989 */
990 public void setDialogTitle(String dialogTitle) {
991 String oldValue = this.dialogTitle;
992 this.dialogTitle = dialogTitle;
993 if(dialog != null) {
994 dialog.setTitle(dialogTitle);
995 }
996 firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue, dialogTitle);
997 }
998
999 /**
1000 * Gets the string that goes in the {@code JFileChooser}'s titlebar.
1001 *
1002 * @return the string from the {@code JFileChooser} window's title bar
1003 * @see #setDialogTitle
1004 */
1005 public String getDialogTitle() {
1006 return dialogTitle;
1007 }
1008
1009 // ************************************
1010 // ***** JFileChooser View Options *****
1011 // ************************************
1012
1013
1014
1015 /**
1016 * Sets the tooltip text used in the {@code ApproveButton}.
1017 * If {@code null}, the UI object will determine the button's text.
1018 *
1019 * @beaninfo
1020 * preferred: true
1021 * bound: true
1022 * description: The tooltip text for the ApproveButton.
1023 *
1024 * @param toolTipText the tooltip text for the approve button
1025 * @see #setApproveButtonText
1026 * @see #setDialogType
1027 * @see #showDialog
1028 */
1029 public void setApproveButtonToolTipText(String toolTipText) {
1030 if(approveButtonToolTipText == toolTipText) {
1031 return;
1032 }
1033 String oldValue = approveButtonToolTipText;
1034 approveButtonToolTipText = toolTipText;
1035 firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, oldValue, approveButtonToolTipText);
1036 }
1037
1038
1039 /**
1040 * Returns the tooltip text used in the {@code ApproveButton}.
1041 * If {@code null}, the UI object will determine the button's text.
1042 *
1043 * @return the tooltip text used for the approve button
1044 *
1045 * @see #setApproveButtonText
1046 * @see #setDialogType
1047 * @see #showDialog
1048 */
1049 public String getApproveButtonToolTipText() {
1050 return approveButtonToolTipText;
1051 }
1052
1053 /**
1054 * Returns the approve button's mnemonic.
1055 * @return an integer value for the mnemonic key
1056 *
1057 * @see #setApproveButtonMnemonic
1058 */
1059 public int getApproveButtonMnemonic() {
1060 return approveButtonMnemonic;
1061 }
1080 approveButtonMnemonic = mnemonic;
1081 firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY, oldValue, approveButtonMnemonic);
1082 }
1083
1084 /**
1085 * Sets the approve button's mnemonic using a character.
1086 * @param mnemonic a character value for the mnemonic key
1087 *
1088 * @see #getApproveButtonMnemonic
1089 */
1090 public void setApproveButtonMnemonic(char mnemonic) {
1091 int vk = (int) mnemonic;
1092 if(vk >= 'a' && vk <='z') {
1093 vk -= ('a' - 'A');
1094 }
1095 setApproveButtonMnemonic(vk);
1096 }
1097
1098
1099 /**
1100 * Sets the text used in the {@code ApproveButton} in the
1101 * {@code FileChooserUI}.
1102 *
1103 * @beaninfo
1104 * preferred: true
1105 * bound: true
1106 * description: The text that goes in the ApproveButton.
1107 *
1108 * @param approveButtonText the text used in the {@code ApproveButton}
1109 *
1110 * @see #getApproveButtonText
1111 * @see #setDialogType
1112 * @see #showDialog
1113 */
1114 // PENDING(jeff) - have ui set this on dialog type change
1115 public void setApproveButtonText(String approveButtonText) {
1116 if(this.approveButtonText == approveButtonText) {
1117 return;
1118 }
1119 String oldValue = this.approveButtonText;
1120 this.approveButtonText = approveButtonText;
1121 firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldValue, approveButtonText);
1122 }
1123
1124 /**
1125 * Returns the text used in the {@code ApproveButton} in the
1126 * {@code FileChooserUI}.
1127 * If {@code null}, the UI object will determine the button's text.
1128 *
1129 * Typically, this would be "Open" or "Save".
1130 *
1131 * @return the text used in the {@code ApproveButton}
1132 *
1133 * @see #setApproveButtonText
1134 * @see #setDialogType
1135 * @see #showDialog
1136 */
1137 public String getApproveButtonText() {
1138 return approveButtonText;
1139 }
1140
1141 /**
1142 * Gets the list of user choosable file filters.
1143 *
1144 * @return a {@code FileFilter} array containing all the choosable
1145 * file filters
1146 *
1147 * @see #addChoosableFileFilter
1148 * @see #removeChoosableFileFilter
1149 * @see #resetChoosableFileFilters
1150 */
1151 public FileFilter[] getChoosableFileFilters() {
1152 FileFilter[] filterArray = new FileFilter[filters.size()];
1153 filters.copyInto(filterArray);
1154 return filterArray;
1155 }
1156
1157 /**
1158 * Adds a filter to the list of user choosable file filters.
1159 * For information on setting the file selection mode, see
1160 * {@link #setFileSelectionMode setFileSelectionMode}.
1161 *
1162 * @param filter the {@code FileFilter} to add to the choosable file
1163 * filter list
1164 *
1165 * @beaninfo
1166 * preferred: true
1167 * bound: true
1168 * description: Adds a filter to the list of user choosable file filters.
1169 *
1170 * @see #getChoosableFileFilters
1171 * @see #removeChoosableFileFilter
1172 * @see #resetChoosableFileFilters
1173 * @see #setFileSelectionMode
1174 */
1175 public void addChoosableFileFilter(FileFilter filter) {
1176 if(filter != null && !filters.contains(filter)) {
1177 FileFilter[] oldValue = getChoosableFileFilters();
1178 filters.addElement(filter);
1179 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
1180 if (fileFilter == null && filters.size() == 1) {
1181 setFileFilter(filter);
1182 }
1210 // choose the second filter, because the first one is removed
1211 setFileFilter(filters.get(1));
1212 }
1213 else {
1214 // no more filters
1215 setFileFilter(null);
1216 }
1217 }
1218 FileFilter[] oldValue = getChoosableFileFilters();
1219 filters.removeElement(f);
1220 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
1221 return true;
1222 } else {
1223 return false;
1224 }
1225 }
1226
1227 /**
1228 * Resets the choosable file filter list to its starting state. Normally,
1229 * this removes all added file filters while leaving the
1230 * {@code AcceptAll} file filter.
1231 *
1232 * @see #addChoosableFileFilter
1233 * @see #getChoosableFileFilters
1234 * @see #removeChoosableFileFilter
1235 */
1236 public void resetChoosableFileFilters() {
1237 FileFilter[] oldValue = getChoosableFileFilters();
1238 setFileFilter(null);
1239 filters.removeAllElements();
1240 if(isAcceptAllFileFilterUsed()) {
1241 addChoosableFileFilter(getAcceptAllFileFilter());
1242 }
1243 firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
1244 }
1245
1246 /**
1247 * Returns the {@code AcceptAll} file filter.
1248 * For example, on Microsoft Windows this would be All Files (*.*).
1249 *
1250 * @return the {@code AcceptAll} file filter
1251 */
1252 public FileFilter getAcceptAllFileFilter() {
1253 FileFilter filter = null;
1254 if(getUI() != null) {
1255 filter = getUI().getAcceptAllFileFilter(this);
1256 }
1257 return filter;
1258 }
1259
1260 /**
1261 * Returns whether the {@code AcceptAll FileFilter} is used.
1262 * @return true if the {@code AcceptAll FileFilter} is used
1263 * @see #setAcceptAllFileFilterUsed
1264 * @since 1.3
1265 */
1266 public boolean isAcceptAllFileFilterUsed() {
1267 return useAcceptAllFileFilter;
1268 }
1269
1270 /**
1271 * Determines whether the {@code AcceptAll FileFilter} is used
1272 * as an available choice in the choosable filter list.
1273 * If false, the {@code AcceptAll} file filter is removed from
1274 * the list of available file filters.
1275 * If true, the {@code AcceptAll} file filter will become the
1276 * actively used file filter.
1277 *
1278 * @param b a {@code boolean} which determines whether the {@code AcceptAll}
1279 * file filter is an available choice in the choosable filter list
1280 * @beaninfo
1281 * preferred: true
1282 * bound: true
1283 * description: Sets whether the AcceptAll FileFilter is used as an available choice in the choosable filter list.
1284 *
1285 * @see #isAcceptAllFileFilterUsed
1286 * @see #getAcceptAllFileFilter
1287 * @see #setFileFilter
1288 * @since 1.3
1289 */
1290 public void setAcceptAllFileFilterUsed(boolean b) {
1291 boolean oldValue = useAcceptAllFileFilter;
1292 useAcceptAllFileFilter = b;
1293 if(!b) {
1294 removeChoosableFileFilter(getAcceptAllFileFilter());
1295 } else {
1315 * that the programmer wishes, such as extra custom file chooser controls.
1316 *
1317 * <p>
1318 * Note: if there was a previous accessory, you should unregister
1319 * any listeners that the accessory might have registered with the
1320 * file chooser.
1321 *
1322 * @param newAccessory the accessory component to be set
1323 * @beaninfo
1324 * preferred: true
1325 * bound: true
1326 * description: Sets the accessory component on the JFileChooser.
1327 */
1328 public void setAccessory(JComponent newAccessory) {
1329 JComponent oldValue = accessory;
1330 accessory = newAccessory;
1331 firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue, accessory);
1332 }
1333
1334 /**
1335 * Sets the {@code JFileChooser} to allow the user to just
1336 * select files, just select
1337 * directories, or select both files and directories. The default is
1338 * {@code JFilesChooser.FILES_ONLY}.
1339 *
1340 * @param mode the type of files to be displayed:
1341 * <ul>
1342 * <li>JFileChooser.FILES_ONLY
1343 * <li>JFileChooser.DIRECTORIES_ONLY
1344 * <li>JFileChooser.FILES_AND_DIRECTORIES
1345 * </ul>
1346 *
1347 * @exception IllegalArgumentException if {@code mode} is an
1348 * illegal file selection mode
1349 * @beaninfo
1350 * preferred: true
1351 * bound: true
1352 * description: Sets the types of files that the JFileChooser can choose.
1353 * enum: FILES_ONLY JFileChooser.FILES_ONLY
1354 * DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY
1355 * FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES
1356 *
1357 *
1358 * @see #getFileSelectionMode
1359 */
1360 public void setFileSelectionMode(int mode) {
1361 if(fileSelectionMode == mode) {
1362 return;
1363 }
1364
1365 checkFileSelectionMode(mode);
1366 int oldValue = fileSelectionMode;
1367 fileSelectionMode = mode;
1368 firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode);
1369 }
1370
1371 private static void checkFileSelectionMode(int mode) {
1372 if ((mode != FILES_ONLY) && (mode != DIRECTORIES_ONLY)
1373 && (mode != FILES_AND_DIRECTORIES)) {
1374 throw new IllegalArgumentException(
1375 "Incorrect Mode for file selection: " + mode);
1376 }
1377 }
1378
1379 /**
1380 * Returns the current file-selection mode. The default is
1381 * {@code JFilesChooser.FILES_ONLY}.
1382 *
1383 * @return the type of files to be displayed, one of the following:
1384 * <ul>
1385 * <li>JFileChooser.FILES_ONLY
1386 * <li>JFileChooser.DIRECTORIES_ONLY
1387 * <li>JFileChooser.FILES_AND_DIRECTORIES
1388 * </ul>
1389 * @see #setFileSelectionMode
1390 */
1391 public int getFileSelectionMode() {
1392 return fileSelectionMode;
1393 }
1394
1395 /**
1396 * Convenience call that determines if files are selectable based on the
1397 * current file selection mode.
1398 *
1399 * @return true if files are selectable, false otherwise
1400 * @see #setFileSelectionMode
1401 * @see #getFileSelectionMode
1442 */
1443 public boolean isMultiSelectionEnabled() {
1444 return multiSelectionEnabled;
1445 }
1446
1447
1448 /**
1449 * Returns true if hidden files are not shown in the file chooser;
1450 * otherwise, returns false.
1451 *
1452 * @return the status of the file hiding property
1453 * @see #setFileHidingEnabled
1454 */
1455 public boolean isFileHidingEnabled() {
1456 return useFileHiding;
1457 }
1458
1459 /**
1460 * Sets file hiding on or off. If true, hidden files are not shown
1461 * in the file chooser. The job of determining which files are
1462 * shown is done by the {@code FileView}.
1463 *
1464 * @beaninfo
1465 * preferred: true
1466 * bound: true
1467 * description: Sets file hiding on or off.
1468 *
1469 * @param b the boolean value that determines whether file hiding is
1470 * turned on
1471 * @see #isFileHidingEnabled
1472 */
1473 public void setFileHidingEnabled(boolean b) {
1474 // Dump showFilesListener since we'll ignore it from now on
1475 if (showFilesListener != null) {
1476 Toolkit.getDefaultToolkit().removePropertyChangeListener(SHOW_HIDDEN_PROP, showFilesListener);
1477 showFilesListener = null;
1478 }
1479 boolean oldValue = useFileHiding;
1480 useFileHiding = b;
1481 firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, useFileHiding);
1482 }
1551 * Returns the current file view.
1552 *
1553 * @return the current file view
1554 * @see #setFileView
1555 */
1556 public FileView getFileView() {
1557 return fileView;
1558 }
1559
1560 // ******************************
1561 // *****FileView delegation *****
1562 // ******************************
1563
1564 // NOTE: all of the following methods attempt to delegate
1565 // first to the client set fileView, and if <code>null</code> is returned
1566 // (or there is now client defined fileView) then calls the
1567 // UI's default fileView.
1568
1569 /**
1570 * Returns the filename.
1571 * @param f the {@code File}
1572 * @return the {@code String} containing the filename for
1573 * {@code f}
1574 * @see FileView#getName
1575 */
1576 public String getName(File f) {
1577 String filename = null;
1578 if(f != null) {
1579 if(getFileView() != null) {
1580 filename = getFileView().getName(f);
1581 }
1582
1583 FileView uiFileView = getUI().getFileView(this);
1584
1585 if(filename == null && uiFileView != null) {
1586 filename = uiFileView.getName(f);
1587 }
1588 }
1589 return filename;
1590 }
1591
1592 /**
1593 * Returns the file description.
1594 * @param f the {@code File}
1595 * @return the {@code String} containing the file description for
1596 * {@code f}
1597 * @see FileView#getDescription
1598 */
1599 public String getDescription(File f) {
1600 String description = null;
1601 if(f != null) {
1602 if(getFileView() != null) {
1603 description = getFileView().getDescription(f);
1604 }
1605
1606 FileView uiFileView = getUI().getFileView(this);
1607
1608 if(description == null && uiFileView != null) {
1609 description = uiFileView.getDescription(f);
1610 }
1611 }
1612 return description;
1613 }
1614
1615 /**
1616 * Returns the file type.
1617 * @param f the {@code File}
1618 * @return the {@code String} containing the file type description for
1619 * {@code f}
1620 * @see FileView#getTypeDescription
1621 */
1622 public String getTypeDescription(File f) {
1623 String typeDescription = null;
1624 if(f != null) {
1625 if(getFileView() != null) {
1626 typeDescription = getFileView().getTypeDescription(f);
1627 }
1628
1629 FileView uiFileView = getUI().getFileView(this);
1630
1631 if(typeDescription == null && uiFileView != null) {
1632 typeDescription = uiFileView.getTypeDescription(f);
1633 }
1634 }
1635 return typeDescription;
1636 }
1637
1638 /**
1639 * Returns the icon for this file or type of file, depending
1640 * on the system.
1641 * @param f the {@code File}
1642 * @return the {@code Icon} for this file, or type of file
1643 * @see FileView#getIcon
1644 */
1645 public Icon getIcon(File f) {
1646 Icon icon = null;
1647 if (f != null) {
1648 if(getFileView() != null) {
1649 icon = getFileView().getIcon(f);
1650 }
1651
1652 FileView uiFileView = getUI().getFileView(this);
1653
1654 if(icon == null && uiFileView != null) {
1655 icon = uiFileView.getIcon(f);
1656 }
1657 }
1658 return icon;
1659 }
1660
1661 /**
1662 * Returns true if the file (directory) can be visited.
1663 * Returns false if the directory cannot be traversed.
1664 * @param f the {@code File}
1665 * @return true if the file/directory can be traversed, otherwise false
1666 * @see FileView#isTraversable
1667 */
1668 public boolean isTraversable(File f) {
1669 Boolean traversable = null;
1670 if (f != null) {
1671 if (getFileView() != null) {
1672 traversable = getFileView().isTraversable(f);
1673 }
1674
1675 FileView uiFileView = getUI().getFileView(this);
1676
1677 if (traversable == null && uiFileView != null) {
1678 traversable = uiFileView.isTraversable(f);
1679 }
1680 if (traversable == null) {
1681 traversable = getFileSystemView().isTraversable(f);
1682 }
1683 }
1684 return (traversable != null && traversable.booleanValue());
1685 }
1686
1687 /**
1688 * Returns true if the file should be displayed.
1689 * @param f the {@code File}
1690 * @return true if the file should be displayed, otherwise false
1691 * @see FileFilter#accept
1692 */
1693 public boolean accept(File f) {
1694 boolean shown = true;
1695 if(f != null && fileFilter != null) {
1696 shown = fileFilter.accept(f);
1697 }
1698 return shown;
1699 }
1700
1701 /**
1702 * Sets the file system view that the {@code JFileChooser} uses for
1703 * accessing and creating file system resources, such as finding
1704 * the floppy drive and getting a list of root drives.
1705 * @param fsv the new {@code FileSystemView}
1706 *
1707 * @beaninfo
1708 * expert: true
1709 * bound: true
1710 * description: Sets the FileSytemView used to get filesystem information.
1711 *
1712 * @see FileSystemView
1713 */
1714 public void setFileSystemView(FileSystemView fsv) {
1715 FileSystemView oldValue = fileSystemView;
1716 fileSystemView = fsv;
1717 firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue, fileSystemView);
1718 }
1719
1720 /**
1721 * Returns the file system view.
1722 * @return the {@code FileSystemView} object
1723 * @see #setFileSystemView
1724 */
1725 public FileSystemView getFileSystemView() {
1726 return fileSystemView;
1727 }
1728
1729 // **************************
1730 // ***** Event Handling *****
1731 // **************************
1732
1733 /**
1734 * Called by the UI when the user hits the Approve button
1735 * (labeled "Open" or "Save", by default). This can also be
1736 * called by the programmer.
1737 * This method causes an action event to fire
1738 * with the command string equal to
1739 * {@code APPROVE_SELECTION}.
1740 *
1741 * @see #APPROVE_SELECTION
1742 */
1743 public void approveSelection() {
1744 returnValue = APPROVE_OPTION;
1745 if(dialog != null) {
1746 dialog.setVisible(false);
1747 }
1748 fireActionPerformed(APPROVE_SELECTION);
1749 }
1750
1751 /**
1752 * Called by the UI when the user chooses the Cancel button.
1753 * This can also be called by the programmer.
1754 * This method causes an action event to fire
1755 * with the command string equal to
1756 * {@code CANCEL_SELECTION}.
1757 *
1758 * @see #CANCEL_SELECTION
1759 */
1760 public void cancelSelection() {
1761 returnValue = CANCEL_OPTION;
1762 if(dialog != null) {
1763 dialog.setVisible(false);
1764 }
1765 fireActionPerformed(CANCEL_SELECTION);
1766 }
1767
1768 /**
1769 * Adds an {@code ActionListener} to the file chooser.
1770 *
1771 * @param l the listener to be added
1772 *
1773 * @see #approveSelection
1774 * @see #cancelSelection
1775 */
1776 public void addActionListener(ActionListener l) {
1777 listenerList.add(ActionListener.class, l);
1778 }
1779
1780 /**
1781 * Removes an {@code ActionListener} from the file chooser.
1782 *
1783 * @param l the listener to be removed
1784 *
1785 * @see #addActionListener
1786 */
1787 public void removeActionListener(ActionListener l) {
1788 listenerList.remove(ActionListener.class, l);
1789 }
1790
1791 /**
1792 * Returns an array of all the action listeners
1793 * registered on this file chooser.
1794 *
1795 * @return all of this file chooser's {@code ActionListener}s
1796 * or an empty
1797 * array if no action listeners are currently registered
1798 *
1799 * @see #addActionListener
1800 * @see #removeActionListener
1801 *
1802 * @since 1.4
1803 */
1804 public ActionListener[] getActionListeners() {
1805 return listenerList.getListeners(ActionListener.class);
1806 }
1807
1808 /**
1809 * Notifies all listeners that have registered interest for
1810 * notification on this event type. The event instance
1811 * is lazily created using the {@code command} parameter.
1812 *
1813 * @param command a string that may specify a command associated with
1814 * the event
1815 * @see EventListenerList
1816 */
1817 protected void fireActionPerformed(String command) {
1818 // Guaranteed to return a non-null array
1819 Object[] listeners = listenerList.getListenerList();
1820 long mostRecentEventTime = EventQueue.getMostRecentEventTime();
1821 int modifiers = 0;
1822 AWTEvent currentEvent = EventQueue.getCurrentEvent();
1823 if (currentEvent instanceof InputEvent) {
1824 modifiers = ((InputEvent)currentEvent).getModifiers();
1825 } else if (currentEvent instanceof ActionEvent) {
1826 modifiers = ((ActionEvent)currentEvent).getModifiers();
1827 }
1828 ActionEvent e = null;
1829 // Process the listeners last to first, notifying
1830 // those that are interested in this event
1831 for (int i = listeners.length-2; i>=0; i-=2) {
1896 * @see JComponent#getUIClassID
1897 * @see UIDefaults#getUI
1898 * @beaninfo
1899 * expert: true
1900 * description: A string that specifies the name of the L&F class.
1901 */
1902 public String getUIClassID() {
1903 return uiClassID;
1904 }
1905
1906 /**
1907 * Gets the UI object which implements the L&F for this component.
1908 *
1909 * @return the FileChooserUI object that implements the FileChooserUI L&F
1910 */
1911 public FileChooserUI getUI() {
1912 return (FileChooserUI) ui;
1913 }
1914
1915 /**
1916 * See {@code readObject} and {@code writeObject} in
1917 * {@code JComponent} for more
1918 * information about serialization in Swing.
1919 */
1920 private void readObject(java.io.ObjectInputStream in)
1921 throws IOException, ClassNotFoundException {
1922 ObjectInputStream.GetField f = in.readFields();
1923
1924 dialogTitle = (String) f.get("dialogTitle", null);
1925 approveButtonText = (String) f.get("approveButtonText", null);
1926 approveButtonToolTipText =
1927 (String) f.get("approveButtonToolTipText", null);
1928 approveButtonMnemonic = f.get("approveButtonMnemonic", 0);
1929 @SuppressWarnings("unchecked")
1930 Vector<FileFilter> newFilters = (Vector<FileFilter>) f.get("filters", null);
1931 if (newFilters == null) {
1932 throw new InvalidObjectException("Null filters");
1933 }
1934 filters = newFilters;
1935 dialog = (JDialog) f.get("dialog", null);
1936 int newDialogType = f.get("dialogType", OPEN_DIALOG);
1937 checkDialogType(newDialogType);
1943 useFileHiding = f.get("useFileHiding", false);
1944 int newFileSelectionMode = f.get("fileSelectionMode", FILES_ONLY);
1945 checkFileSelectionMode(newFileSelectionMode);
1946 fileSelectionMode = newFileSelectionMode;
1947 multiSelectionEnabled = f.get("multiSelectionEnabled", false);
1948 useAcceptAllFileFilter = f.get("useAcceptAllFileFilter", false);
1949 boolean newDragEnabled = f.get("dragEnabled", false);
1950 checkDragEnabled(newDragEnabled);
1951 dragEnabled = newDragEnabled;
1952 fileFilter = (FileFilter) f.get("fileFilter", null);
1953 fileSystemView = (FileSystemView) f.get("fileSystemView", null);
1954 currentDirectory = (File) f.get("currentDirectory", null);
1955 selectedFile = (File) f.get("selectedFile", null);
1956 selectedFiles = (File[]) f.get("selectedFiles", null);
1957 accessibleContext = (AccessibleContext) f.get("accessibleContext", null);
1958
1959 installShowFilesListener();
1960 }
1961
1962 /**
1963 * See {@code readObject} and {@code writeObject} in
1964 * {@code JComponent} for more
1965 * information about serialization in Swing.
1966 */
1967 private void writeObject(ObjectOutputStream s) throws IOException {
1968 FileSystemView fsv = null;
1969
1970 if (isAcceptAllFileFilterUsed()) {
1971 //The AcceptAllFileFilter is UI specific, it will be reset by
1972 //updateUI() after deserialization
1973 removeChoosableFileFilter(getAcceptAllFileFilter());
1974 }
1975 if (fileSystemView.equals(FileSystemView.getFileSystemView())) {
1976 //The default FileSystemView is platform specific, it will be
1977 //reset by updateUI() after deserialization
1978 fsv = fileSystemView;
1979 fileSystemView = null;
1980 }
1981 s.defaultWriteObject();
1982 if (fsv != null) {
1983 fileSystemView = fsv;
1984 }
1985 if (isAcceptAllFileFilterUsed()) {
1986 addChoosableFileFilter(getAcceptAllFileFilter());
1987 }
1988 if (getUIClassID().equals(uiClassID)) {
1989 byte count = JComponent.getWriteObjCounter(this);
1990 JComponent.setWriteObjCounter(this, --count);
1991 if (count == 0 && ui != null) {
1992 ui.installUI(this);
1993 }
1994 }
1995 }
1996
1997
1998 /**
1999 * Returns a string representation of this {@code JFileChooser}.
2000 * This method
2001 * is intended to be used only for debugging purposes, and the
2002 * content and format of the returned string may vary between
2003 * implementations. The returned string may be empty but may not
2004 * be {@code null}.
2005 *
2006 * @return a string representation of this {@code JFileChooser}
2007 */
2008 protected String paramString() {
2009 String approveButtonTextString = (approveButtonText != null ?
2010 approveButtonText: "");
2011 String dialogTitleString = (dialogTitle != null ?
2012 dialogTitle: "");
2013 String dialogTypeString;
2014 if (dialogType == OPEN_DIALOG) {
2015 dialogTypeString = "OPEN_DIALOG";
2016 } else if (dialogType == SAVE_DIALOG) {
2017 dialogTypeString = "SAVE_DIALOG";
2018 } else if (dialogType == CUSTOM_DIALOG) {
2019 dialogTypeString = "CUSTOM_DIALOG";
2020 } else dialogTypeString = "";
2021 String returnValueString;
2022 if (returnValue == CANCEL_OPTION) {
2023 returnValueString = "CANCEL_OPTION";
2024 } else if (returnValue == APPROVE_OPTION) {
2025 returnValueString = "APPROVE_OPTION";
2026 } else if (returnValue == ERROR_OPTION) {
2062 protected AccessibleContext accessibleContext = null;
2063
2064 /**
2065 * Gets the AccessibleContext associated with this JFileChooser.
2066 * For file choosers, the AccessibleContext takes the form of an
2067 * AccessibleJFileChooser.
2068 * A new AccessibleJFileChooser instance is created if necessary.
2069 *
2070 * @return an AccessibleJFileChooser that serves as the
2071 * AccessibleContext of this JFileChooser
2072 */
2073 public AccessibleContext getAccessibleContext() {
2074 if (accessibleContext == null) {
2075 accessibleContext = new AccessibleJFileChooser();
2076 }
2077 return accessibleContext;
2078 }
2079
2080 /**
2081 * This class implements accessibility support for the
2082 * {@code JFileChooser} class. It provides an implementation of the
2083 * Java Accessibility API appropriate to file chooser user-interface
2084 * elements.
2085 */
2086 @SuppressWarnings("serial") // Superclass is not serializable across versions
2087 protected class AccessibleJFileChooser extends AccessibleJComponent {
2088
2089 /**
2090 * Gets the role of this object.
2091 *
2092 * @return an instance of AccessibleRole describing the role of the
2093 * object
2094 * @see AccessibleRole
2095 */
2096 public AccessibleRole getAccessibleRole() {
2097 return AccessibleRole.FILE_CHOOSER;
2098 }
2099
2100 } // inner class AccessibleJFileChooser
2101
2102 }
|