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