1. /*
  2. * @(#)JFileChooser.java 1.50 01/11/29
  3. *
  4. * Copyright 2002 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.Component;
  18. import java.awt.Container;
  19. import java.awt.BorderLayout;
  20. import java.awt.Frame;
  21. import java.awt.event.*;
  22. /**
  23. * JFileChooser provides a simple mechanism for the user to chooser a file.
  24. *
  25. * The following pops up a file chooser in the users home directory that
  26. * only sees .jpg and .gif images:
  27. * JFileChooser chooser = new JFileChooser();
  28. * // Note: source for ExtensionFileFilter can be found in the SwingSet demo
  29. * ExtensionFileFilter filter = new ExtensionFileFilter();
  30. * filter.addExtension("jpg");
  31. * filter.addExtension("gif");
  32. * filter.setDescription("JPG & GIF Images");
  33. * chooser.setFileFilter(filter);
  34. * int returnVal = chooser.showOpenDialog(parent);
  35. * if(returnVal == JFileChooser.APPROVE_OPTION) {
  36. * System.out.println("You chose to open this file: " +
  37. * chooser.getSelectedFile().getName());
  38. * }
  39. *
  40. * @beaninfo
  41. * attribute: isContainer false
  42. *
  43. * @version 1.50 11/29/01
  44. * @author Jeff Dinkins
  45. *
  46. */
  47. public class JFileChooser extends JComponent implements Accessible {
  48. /**
  49. * @see #getUIClassID
  50. * @see #readObject
  51. */
  52. private static final String uiClassID = "FileChooserUI";
  53. // ************************
  54. // ***** Dialog Types *****
  55. // ************************
  56. /**
  57. * Type value indicating that the FileChooser supports an "Open"
  58. * file operation.
  59. */
  60. public static final int OPEN_DIALOG = 0;
  61. /**
  62. * Type value indicating that the FileChooser supports a "Save"
  63. * file operation.
  64. */
  65. public static final int SAVE_DIALOG = 1;
  66. /**
  67. * Type value indicating that the FileChooser supports a developer
  68. * sepcified file operation.
  69. */
  70. public static final int CUSTOM_DIALOG = 2;
  71. // ********************************
  72. // ***** Dialog Return Values *****
  73. // ********************************
  74. /**
  75. * Return value if cancel is chosen.
  76. */
  77. public static final int CANCEL_OPTION = 1;
  78. /**
  79. * Return value if approve (yes, ok) is chosen.
  80. */
  81. public static final int APPROVE_OPTION = 0;
  82. /**
  83. * Return value if an error occured.
  84. */
  85. public static final int ERROR_OPTION = -1;
  86. // **********************************
  87. // ***** FileChooser properties *****
  88. // **********************************
  89. /** Instruction to display only files. */
  90. public static final int FILES_ONLY = 0;
  91. /** Instruction to display only directories. */
  92. public static final int DIRECTORIES_ONLY = 1;
  93. /** Instruction to display both files and directories. */
  94. public static final int FILES_AND_DIRECTORIES = 2;
  95. /** Instruction to cancel the current selection. */
  96. public static final String CANCEL_SELECTION = "CancelSelection";
  97. /** Instruction to approve the current selection (Same as pressing yes or ok.) */
  98. public static final String APPROVE_SELECTION = "ApproveSelection";
  99. /** Identifies change in the text on the approve (yes, ok) button. */
  100. public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty";
  101. /** Identifies change in the tooltip text for the approve (yes, ok) button . */
  102. public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty";
  103. /** Identifies change in the mnemonic for the approve (yes, ok) button . */
  104. public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = "ApproveButtonMnemonicChangedProperty";
  105. /** Identifies user's directory change. */
  106. public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
  107. /** Identifes change in user's single-file selection. */
  108. public static final String SELECTED_FILE_CHANGED_PROPERTY = "SelectedFileChangedProperty";
  109. /** Identifes change in user's multiple-file selection. */
  110. public static final String SELECTED_FILES_CHANGED_PROPERTY = "SelectedFilesChangedProperty";
  111. /** Enables multiple-file selections. */
  112. public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "fileFilterChanged";
  113. /** Says that a different object is being used to find available drives on the system. */
  114. public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged";
  115. /** Says that a different object is being used to retrieve file information. */
  116. public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
  117. /** Identifies a change in the display-hidden-files property. */
  118. public static final String FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged";
  119. /** User changed the kind of files to display.*/
  120. public static final String FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged";
  121. /** Identifies a change in the kind of selection (single, multiple, etc.). */
  122. public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged";
  123. /** Says that a different accessory component is in use. (For example, to preview files.) */
  124. public static final String ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty";
  125. /** Identifies whether a the AcceptAllFileFilter is used or not. */
  126. private static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = "AcceptAllFileFilterUsedChanged";
  127. /** Identifies a change in the dialog title. */
  128. public static final String DIALOG_TITLE_CHANGED_PROPERTY = "DialogTitleChangedProperty";
  129. /**
  130. * Identifies a change in the type of files displayed (files only,
  131. * directories only, or both files and directories.
  132. */
  133. public static final String DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty";
  134. /**
  135. * Identifies a change in the list of predefined file filters
  136. * the user can choose from
  137. */
  138. public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty";
  139. // ******************************
  140. // ***** instance variables *****
  141. // ******************************
  142. private String dialogTitle = null;
  143. private String approveButtonText = null;
  144. private String approveButtonToolTipText = null;
  145. private int approveButtonMnemonic = 0;
  146. private ActionListener actionListener = null;
  147. private Vector filters = new Vector(5);
  148. private JDialog dialog = null;
  149. private int dialogType = OPEN_DIALOG;
  150. private int returnValue = ERROR_OPTION;
  151. private JComponent accessory = null;
  152. private FileView fileView = null;
  153. private FileView uiFileView = null;
  154. private boolean useFileHiding = true;
  155. private int fileSelectionMode = FILES_ONLY;
  156. private boolean multiSelectionEnabled = false;
  157. private boolean useAcceptAllFileFilter = true;
  158. private FileFilter fileFilter = null;
  159. private FileSystemView fileSystemView = null;
  160. private File currentDirectory = null;
  161. private File selectedFile = null;
  162. private File[] selectedFiles;
  163. // *************************************
  164. // ***** JFileChooser Constructors *****
  165. // *************************************
  166. /**
  167. * Creates a JFileChooser pointing to the user's home directory.
  168. */
  169. public JFileChooser() {
  170. this((File) null, (FileSystemView) null);
  171. }
  172. /**
  173. * Creates a JFileChooser using the given path. Passing in a null
  174. * string causes the file chooser to point to the users home directory.
  175. *
  176. * @param path a String giving the path to a file or directory
  177. */
  178. public JFileChooser(String currentDirectoryPath) {
  179. this(currentDirectoryPath, (FileSystemView) null);
  180. }
  181. /**
  182. * Creates a JFileChooser using the given File as the path. Passing
  183. * in a null file causes the file chooser to point to the users's
  184. * home directory.
  185. *
  186. * @param directory a File object specifying the path to a file
  187. * or directory
  188. */
  189. public JFileChooser(File currentDirectory) {
  190. this(currentDirectory, (FileSystemView) null);
  191. }
  192. /**
  193. * Creates a JFileChooser using the given FileSystemView
  194. */
  195. public JFileChooser(FileSystemView fsv) {
  196. this((File) null, fsv);
  197. }
  198. /**
  199. * Creates a JFileChooser using the given current directory and FileSystemView
  200. */
  201. public JFileChooser(File currentDirectory, FileSystemView fsv) {
  202. setup(fsv);
  203. setCurrentDirectory(currentDirectory);
  204. }
  205. /**
  206. * Creates a JFileChooser using the given current directory path and FileSystemView
  207. */
  208. public JFileChooser(String currentDirectoryPath, FileSystemView fsv) {
  209. setup(fsv);
  210. if(currentDirectoryPath == null) {
  211. setCurrentDirectory(null);
  212. } else {
  213. setCurrentDirectory(fileSystemView.createFileObject(currentDirectoryPath));
  214. }
  215. }
  216. /**
  217. * Perform common constructor initialization and setup
  218. */
  219. protected void setup(FileSystemView view) {
  220. if(view == null) {
  221. view = FileSystemView.getFileSystemView();
  222. }
  223. setFileSystemView(view);
  224. updateUI();
  225. if(isAcceptAllFileFilterUsed()) {
  226. setFileFilter(getAcceptAllFileFilter());
  227. }
  228. }
  229. // *****************************
  230. // ****** File Operations ******
  231. // *****************************
  232. /**
  233. * Returns the selected file. This can be set either by the
  234. * programmer via setFile() or by a user action, such as
  235. * either typing the filename int the UI or selecting the
  236. * file from a list in the UI.
  237. *
  238. * @see #setSelectedFile
  239. * @return the selected file
  240. */
  241. public File getSelectedFile() {
  242. return selectedFile;
  243. }
  244. /**
  245. * Sets the selected file. If the file's parent directory is
  246. * not the current directory, changes the current directory
  247. * to be the file's parent directory.
  248. *
  249. * @beaninfo
  250. * preferred: true
  251. * bound: true
  252. *
  253. * @see #getSelectedFile
  254. *
  255. * @param selectedFile the selected file
  256. */
  257. public void setSelectedFile(File file) {
  258. // PENDING(jeff) - make sure that the file's path is
  259. // in the current directory. If not, change the current
  260. // directory to the file's path.
  261. File oldValue = selectedFile;
  262. selectedFile = file;
  263. if(selectedFile != null) {
  264. String parent = selectedFile.getParent();
  265. if(parent != null) {
  266. File parentF = getFileSystemView().createFileObject(parent);
  267. if(!parentF.equals(getCurrentDirectory())) {
  268. setCurrentDirectory(parentF);
  269. }
  270. }
  271. ensureFileIsVisible(selectedFile);
  272. }
  273. firePropertyChange(SELECTED_FILE_CHANGED_PROPERTY, oldValue, selectedFile);
  274. }
  275. /**
  276. * Returns a list of selected files if the filechooser is
  277. * set to allow multi-selection.
  278. */
  279. public File[] getSelectedFiles() {
  280. if(selectedFiles == null) {
  281. return new File[0];
  282. } else {
  283. return (File[]) selectedFiles.clone();
  284. }
  285. }
  286. /**
  287. * Sets the list of selected files if the filechooser is
  288. * set to allow multi-selection.
  289. *
  290. * @beaninfo
  291. * bound: true
  292. * description: the list of selected files if the chooser is in multi-selection mode
  293. */
  294. public void setSelectedFiles(File[] selectedFiles) {
  295. File[] oldValue = this.selectedFiles;
  296. this.selectedFiles = selectedFiles;
  297. firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, this.selectedFiles);
  298. }
  299. /**
  300. * Returns the current directory.
  301. *
  302. * @return the current directory
  303. * @see #setCurrentDirectory
  304. */
  305. public File getCurrentDirectory() {
  306. return currentDirectory;
  307. }
  308. /**
  309. * Sets the current directory. Passing in null sets the filechooser
  310. * to point to the users's home directory.
  311. *
  312. * If the file passed in as currentDirectory is not a directory, the
  313. * parent of the file will be used as the currentDirectory. If the
  314. * parent is not traversable, then it will walk up the parent tree
  315. * until it finds a traversable direcotry, or hits the root of the
  316. * file system.
  317. *
  318. * @beaninfo
  319. * preferred: true
  320. * bound: true
  321. * description: the directory that the FileChooser is showing files of
  322. *
  323. * @param currentDirectory the current directory to point to
  324. * @see #getCurrentDirectory
  325. */
  326. public void setCurrentDirectory(File dir) {
  327. File oldValue = currentDirectory;
  328. if(dir == null) {
  329. currentDirectory = getFileSystemView().getHomeDirectory();
  330. firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue, currentDirectory);
  331. return;
  332. }
  333. if (currentDirectory != null) {
  334. /* Verify the toString of object */
  335. if (this.currentDirectory.equals(dir)) {
  336. return;
  337. }
  338. }
  339. File prev = null;
  340. while(!isTraversable(dir) && prev != dir && !getFileSystemView().isRoot(dir)) {
  341. prev = dir;
  342. dir = getFileSystemView().getParentDirectory(dir);
  343. }
  344. currentDirectory = dir;
  345. firePropertyChange(DIRECTORY_CHANGED_PROPERTY, oldValue, currentDirectory);
  346. }
  347. /**
  348. * Changes the directory to be set to the parent of the
  349. * current directory.
  350. *
  351. * @see #getCurrentDirectory
  352. */
  353. public void changeToParentDirectory() {
  354. File oldValue = getCurrentDirectory();
  355. setCurrentDirectory(getFileSystemView().getParentDirectory(oldValue));
  356. }
  357. /**
  358. * Tells the UI to rescan it's files list from the current directory.
  359. */
  360. public void rescanCurrentDirectory() {
  361. getUI().rescanCurrentDirectory(this);
  362. }
  363. /**
  364. * Make sure that the specified file is viewable, and
  365. * not hidden.
  366. *
  367. * @param f a File object
  368. */
  369. public void ensureFileIsVisible(File f) {
  370. getUI().ensureFileIsVisible(this, f);
  371. }
  372. // **************************************
  373. // ***** FileChooser Dialog methods *****
  374. // **************************************
  375. /**
  376. * Pops up an "Open File" file chooser dialog. Note that the
  377. * text that appears in the approve button is determined by
  378. * the L&F.
  379. *
  380. *
  381. * @return the return state of the filechooser on popdown:
  382. * CANCEL_OPTION, APPROVE_OPTION
  383. */
  384. public int showOpenDialog(Component parent) {
  385. setDialogType(OPEN_DIALOG);
  386. return showDialog(parent, null);
  387. }
  388. /**
  389. * Pops up a "Save File" file chooser dialog. Note that the
  390. * text that appears in the approve button is determined by
  391. * the L&F.
  392. *
  393. * @return the return state of the filechooser on popdown:
  394. * CANCEL_OPTION, APPROVE_OPTION
  395. */
  396. public int showSaveDialog(Component parent) {
  397. setDialogType(SAVE_DIALOG);
  398. return showDialog(parent, null);
  399. }
  400. /**
  401. * Pops a custom file chooser dialog with a custom ApproveButton.
  402. *
  403. * e.g. filechooser.showDialog(parentWindow, "Run Application");
  404. * would pop up a filechooser with a "Run Application" button
  405. * (instead of the normal "Save" or "Open" button).
  406. *
  407. * Alternatively, the following code will do the same thing:
  408. * JFileChooser chooser = new JFileChooser(null);
  409. * chooser.setApproveButtonText("Run Application");
  410. * chooser.showDialog(this, null);
  411. *
  412. * PENDING(jeff) - the following method should be added to the api:
  413. * showDialog(Component parent);
  414. *
  415. * @param approveButtonText the text of the ApproveButton
  416. * @return the return state of the filechooser on popdown:
  417. * CANCEL_OPTION, APPROVE_OPTION
  418. */
  419. public int showDialog(Component parent, String approveButtonText) {
  420. if(approveButtonText != null) {
  421. setApproveButtonText(approveButtonText);
  422. setDialogType(CUSTOM_DIALOG);
  423. }
  424. Frame frame = parent instanceof Frame ? (Frame) parent
  425. : (Frame)SwingUtilities.getAncestorOfClass(Frame.class, parent);
  426. String title = null;
  427. if(getDialogTitle() != null) {
  428. title = dialogTitle;
  429. } else {
  430. title = getUI().getDialogTitle(this);
  431. }
  432. dialog = new JDialog(frame, title, true);
  433. Container contentPane = dialog.getContentPane();
  434. contentPane.setLayout(new BorderLayout());
  435. contentPane.add(this, BorderLayout.CENTER);
  436. dialog.pack();
  437. dialog.setLocationRelativeTo(parent);
  438. dialog.show();
  439. return returnValue;
  440. }
  441. // **************************
  442. // ***** Dialog Options *****
  443. // **************************
  444. /**
  445. * Returns the type of this dialog.
  446. *
  447. * @return the type of dialog to be displayed:
  448. * OPEN_DIALOG, SAVE_DIALOG, CUSTOM_DIALOG
  449. *
  450. * @see #setDialogType
  451. */
  452. public int getDialogType() {
  453. return dialogType;
  454. }
  455. /**
  456. * Sets the type of this dialog. Use OPEN_DIALOG when you want to
  457. * bring up a filechooser that the user can use to open a file. Likewise,
  458. * use SAVE_DIALOG for letting the user choose a file for saving.
  459. *
  460. * Use CUSTOM_DIALOG when you want to use the filechooser in a context
  461. * other than "Open" or "Save". For instance, you might want to bring up
  462. * a filechooser that allows the user to choose a file to execute. Note that
  463. * you normally would not need to set the FileChooser to use CUSTOM_DIALOG
  464. * since a call to setApproveButtonText does this for you.
  465. *
  466. * @param dialogType the type of dialog to be displayed:
  467. * OPEN_DIALOG, SAVE_DIALOG, CUSTOM_DIALOG
  468. *
  469. * @beaninfo
  470. * preferred: true
  471. * bound: true
  472. * description: The type (open, save, custom) of the FileChooser
  473. * enum:
  474. * OPEN_DIALOG JFileChooser.OPEN_DIALOG
  475. * SAVE_DIALOG JFileChooser.SAVE_DIALOG
  476. * CUSTOM_DIALOG JFileChooser.CUSTOM_DIALOG
  477. *
  478. * @see #getDialogType
  479. * @see #setApproveButtonText
  480. */
  481. // PENDING(jeff) - fire button text change property
  482. public void setDialogType(int dialogType) {
  483. if(this.dialogType == dialogType) {
  484. return;
  485. }
  486. if(!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || dialogType == CUSTOM_DIALOG)) {
  487. throw new IllegalArgumentException("Incorrect Dialog Type: " + dialogType);
  488. }
  489. int oldValue = this.dialogType;
  490. this.dialogType = dialogType;
  491. if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) {
  492. setApproveButtonText(null);
  493. }
  494. firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType);
  495. }
  496. /**
  497. * Sets the string that goes in the FileChooser window's title bar.
  498. *
  499. * @beaninfo
  500. * preferred: true
  501. * bound: true
  502. * description: The title of the FileChooser dialog window
  503. *
  504. * @see #getDialogTitle
  505. *
  506. */
  507. public void setDialogTitle(String dialogTitle) {
  508. String oldValue = this.dialogTitle;
  509. this.dialogTitle = dialogTitle;
  510. if(dialog != null) {
  511. dialog.setTitle(dialogTitle);
  512. }
  513. firePropertyChange(DIALOG_TITLE_CHANGED_PROPERTY, oldValue, dialogTitle);
  514. }
  515. /**
  516. * Gets the string that goes in the FileChooser's titlebar.
  517. *
  518. * @see #setDialogTitle
  519. */
  520. public String getDialogTitle() {
  521. return dialogTitle;
  522. }
  523. // ************************************
  524. // ***** FileChooser View Options *****
  525. // ************************************
  526. /**
  527. * Sets the tooltip text used in the ApproveButton.
  528. * If null, the UI object will determine the button's text.
  529. *
  530. * @beaninfo
  531. * preferred: true
  532. * bound: true
  533. * description: The tooltip text for the ApproveButton
  534. *
  535. * @return the text used in the ApproveButton
  536. *
  537. * @see #setApproveButtonText
  538. * @see #setDialogType
  539. * @see #showDialog
  540. */
  541. public void setApproveButtonToolTipText(String toolTipText) {
  542. if(approveButtonToolTipText == toolTipText) {
  543. return;
  544. }
  545. String oldValue = approveButtonToolTipText;
  546. approveButtonToolTipText = toolTipText;
  547. setDialogType(CUSTOM_DIALOG);
  548. firePropertyChange(APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY, oldValue, approveButtonToolTipText);
  549. }
  550. /**
  551. * Returns the tooltip text used in the ApproveButton.
  552. * If null, the UI object will determine the button's text.
  553. *
  554. * @return the text used in the ApproveButton
  555. *
  556. * @see #setApproveButtonText
  557. * @see #setDialogType
  558. * @see #showDialog
  559. */
  560. public String getApproveButtonToolTipText() {
  561. return approveButtonToolTipText;
  562. }
  563. /**
  564. * Returns the approve button's mnemonic.
  565. * @return an int value for the mnemonic key
  566. *
  567. * @see #setApproveButtonMnemonic
  568. */
  569. public int getApproveButtonMnemonic() {
  570. return approveButtonMnemonic;
  571. }
  572. /**
  573. * Sets the approve button's mnemonic using a numeric keycode.
  574. * @param an int value for the mnemonic key
  575. *
  576. * @beaninfo
  577. * preferred: true
  578. * bound: true
  579. * description: The mnemonic key accelerator for the ApproveButton
  580. *
  581. * @see #getApproveButtonMnemonic
  582. */
  583. public void setApproveButtonMnemonic(int mnemonic) {
  584. if(approveButtonMnemonic == mnemonic) {
  585. return;
  586. }
  587. int oldValue = approveButtonMnemonic;
  588. approveButtonMnemonic = mnemonic;
  589. firePropertyChange(APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY, oldValue, approveButtonMnemonic);
  590. }
  591. /**
  592. * Sets the approve button's mnemonic using a character.
  593. * @param an char value for the mnemonic key
  594. *
  595. * @see #getApproveButtonMnemonic
  596. */
  597. public void setApproveButtonMnemonic(char mnemonic) {
  598. int vk = (int) mnemonic;
  599. if(vk >= 'a' && vk <='z') {
  600. vk -= ('a' - 'A');
  601. }
  602. setApproveButtonMnemonic(vk);
  603. }
  604. /**
  605. * Sets the text used in the ApproveButton in the FileChooserUI.
  606. *
  607. * @beaninfo
  608. * preferred: true
  609. * bound: true
  610. * description: The text that goes in the AprroveButton
  611. *
  612. * @param approveButtonText the text used in the ApproveButton
  613. *
  614. * @see #getApproveButtonText
  615. * @see #setDialogType
  616. * @see #showDialog
  617. */
  618. // PENDING(jeff) - have ui set this on dialog type change
  619. public void setApproveButtonText(String approveButtonText) {
  620. if(this.approveButtonText == approveButtonText) {
  621. return;
  622. }
  623. String oldValue = this.approveButtonText;
  624. this.approveButtonText = approveButtonText;
  625. firePropertyChange(APPROVE_BUTTON_TEXT_CHANGED_PROPERTY, oldValue, approveButtonText);
  626. }
  627. /**
  628. * Returns the text used in the ApproveButton in the FileChooserUI.
  629. * If null, the UI object will determine the button's text.
  630. *
  631. * Typically, this would be "Open" or "Save".
  632. *
  633. * @return the text used in the ApproveButton
  634. *
  635. * @see #setApproveButtonText
  636. * @see #setDialogType
  637. * @see #showDialog
  638. */
  639. public String getApproveButtonText() {
  640. return approveButtonText;
  641. }
  642. /**
  643. * Gets the list of user choosable file filters
  644. *
  645. * @return a FileFilter array containing all the choosable
  646. * file filters
  647. *
  648. * @ see #addChoosableFileFilter
  649. * @ see #removeChoosableFileFilter
  650. * @ see #resetChoosableFileFilter
  651. */
  652. public FileFilter[] getChoosableFileFilters() {
  653. FileFilter[] filterArray = new FileFilter[filters.size()];
  654. filters.copyInto(filterArray);
  655. return filterArray;
  656. }
  657. /**
  658. * Adds a filter to the list of user choosable file filters.
  659. *
  660. * @param filter the FileFilter to add to the choosable file
  661. * filter list
  662. *
  663. * @beaninfo
  664. * preferred: true
  665. * bound: true
  666. * description: Adds a filter to the list of user choosable file filters.
  667. *
  668. * @ see #getChoosableFileFilters
  669. * @ see #removeChoosableFileFilter
  670. * @ see #resetChoosableFileFilter
  671. */
  672. public void addChoosableFileFilter(FileFilter filter) {
  673. if(filter != null && !filters.contains(filter)) {
  674. FileFilter[] oldValue = getChoosableFileFilters();
  675. filters.addElement(filter);
  676. firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
  677. }
  678. setFileFilter(filter);
  679. }
  680. /**
  681. * Removes a filter from the list of user choosable file filters. Returns
  682. * true if the file filter was removed;
  683. *
  684. * @ see #addChoosableFileFilter
  685. * @ see #getChoosableFileFilters
  686. * @ see #resetChoosableFileFilter
  687. */
  688. public boolean removeChoosableFileFilter(FileFilter f) {
  689. if(filters.contains(f)) {
  690. if(getFileFilter() == f) {
  691. setFileFilter(null);
  692. }
  693. FileFilter[] oldValue = getChoosableFileFilters();
  694. filters.removeElement(f);
  695. firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
  696. return true;
  697. } else {
  698. return false;
  699. }
  700. }
  701. /**
  702. * Resets the choosable file filter list to its starting state. Normally,
  703. * this removes all added file filters while leaving the AcceptAll file filter.
  704. *
  705. * @see #addChoosableFileFilter
  706. * @see #getChoosableFileFilters
  707. * @see #removeChoosableFileFilter
  708. */
  709. public void resetChoosableFileFilters() {
  710. FileFilter[] oldValue = getChoosableFileFilters();
  711. setFileFilter(null);
  712. filters.removeAllElements();
  713. if(isAcceptAllFileFilterUsed()) {
  714. addChoosableFileFilter(getAcceptAllFileFilter());
  715. }
  716. firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters());
  717. }
  718. /**
  719. * Returns the AcceptAll file filter (e.g. (All Files *.*) on windows).
  720. */
  721. public FileFilter getAcceptAllFileFilter() {
  722. FileFilter filter = null;
  723. if(getUI() != null) {
  724. filter = getUI().getAcceptAllFileFilter(this);
  725. }
  726. return filter;
  727. }
  728. /**
  729. * Returns whether the AcceptAll FileFilter is used.
  730. * @see setAcceptAllFileFilterUsed
  731. */
  732. private boolean isAcceptAllFileFilterUsed() {
  733. return useAcceptAllFileFilter;
  734. }
  735. /**
  736. * Determins if the AcceptAll FileFilter is used.
  737. * @see isAcceptAllFileFilterUsed
  738. *
  739. * PENDING(jeff) make this public in next major release
  740. * PENDING(jeff) fire property change event
  741. */
  742. private void setAcceptAllFileFilterUsed(boolean b) {
  743. boolean oldValue = useAcceptAllFileFilter;
  744. useAcceptAllFileFilter = b;
  745. if(!b) {
  746. removeChoosableFileFilter(getAcceptAllFileFilter());
  747. } else {
  748. removeChoosableFileFilter(getAcceptAllFileFilter());
  749. addChoosableFileFilter(getAcceptAllFileFilter());
  750. }
  751. firePropertyChange(ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY, oldValue, useAcceptAllFileFilter);
  752. }
  753. /**
  754. * Return the accessory component.
  755. *
  756. * @return this JFileChooser's accessory component, or null
  757. * @see #setAccessory
  758. */
  759. public JComponent getAccessory() {
  760. return accessory;
  761. }
  762. /**
  763. * Sets the accessory component. An accessory is often used to show a preview
  764. * image of the selected file; however, it can be used for anything that
  765. * the programmer wishes - such as extra custom file chooser controls.
  766. *
  767. * Note: if there was a previous accessory, you should unregister
  768. * any listeners that the accessory might have registered with the
  769. * file chooser.
  770. *
  771. * @beaninfo
  772. * preferred: true
  773. * bound: true
  774. * description: Sets the accessory component on the FileChooser.
  775. */
  776. public void setAccessory(JComponent newAccessory) {
  777. JComponent oldValue = accessory;
  778. accessory = newAccessory;
  779. firePropertyChange(ACCESSORY_CHANGED_PROPERTY, oldValue, accessory);
  780. }
  781. /**
  782. * Sets the FileChooser to allow the user to just select files, just select
  783. * directories, or select both files and directories.
  784. *
  785. * @beaninfo
  786. * preferred: true
  787. * bound: true
  788. * description: Sets the types of files that the FileChooser can choose.
  789. * enum: FILES_ONLY JFileChooser.FILES_ONLY
  790. * DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY
  791. * FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES
  792. *
  793. * @param dialogType the type of dialog to be displayed:
  794. * FILES_ONLY, DIRECTORIES_ONLY, FILES_AND_DIRECTORIES
  795. *
  796. * @see #getFileSelectionMode
  797. */
  798. public void setFileSelectionMode(int mode) {
  799. if(fileSelectionMode == mode) {
  800. return;
  801. }
  802. int oldValue = fileSelectionMode;
  803. fileSelectionMode = mode;
  804. firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode);
  805. }
  806. /**
  807. * Returns the current file-selection mode.
  808. *
  809. * @param an int indicating the type of dialog to be displayed:
  810. * FILES_ONLY, DIRECTORIES_ONLY, FILES_AND_DIRECTORIES
  811. * @see #setFileSelectionMode
  812. */
  813. public int getFileSelectionMode() {
  814. return fileSelectionMode;
  815. }
  816. /**
  817. * Convenience call that determines if files are selectable based on the current
  818. * file selection mode
  819. *
  820. * @see #setFileSelectionMode
  821. * @see #getFileSelectionMode
  822. */
  823. public boolean isFileSelectionEnabled() {
  824. return ((fileSelectionMode == FILES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
  825. }
  826. /**
  827. * Convenience call that determines if directories are selectable based on the current
  828. * file selection mode
  829. *
  830. * @see #setFileSelectionMode
  831. * @see #getFileSelectionMode
  832. */
  833. public boolean isDirectorySelectionEnabled() {
  834. return ((fileSelectionMode == DIRECTORIES_ONLY) || (fileSelectionMode == FILES_AND_DIRECTORIES));
  835. }
  836. /**
  837. * Sets the filechooser to allow multiple file selections.
  838. * NOTE: this functionality is not yet implemented in the current L&Fs.
  839. *
  840. * @beaninfo
  841. * bound: true
  842. * description: Sets multiple file selection mode
  843. *
  844. * @see #isMultiSelectionEnabled
  845. */
  846. public void setMultiSelectionEnabled(boolean b) {
  847. if(multiSelectionEnabled == b) {
  848. return;
  849. }
  850. boolean oldValue = multiSelectionEnabled;
  851. multiSelectionEnabled = b;
  852. firePropertyChange(MULTI_SELECTION_ENABLED_CHANGED_PROPERTY, oldValue, multiSelectionEnabled);
  853. }
  854. /**
  855. * Returns true if multiple files can be selected.
  856. * @return true if multiple files can be selected.
  857. * @see #setMultiSelectionEnabled
  858. */
  859. public boolean isMultiSelectionEnabled() {
  860. return multiSelectionEnabled;
  861. }
  862. /**
  863. * If true, hidden files are not shown in the filechooser
  864. *
  865. * @return the status of the file hiding property
  866. * @see #setFileHidingEnabled
  867. */
  868. public boolean isFileHidingEnabled() {
  869. return useFileHiding;
  870. }
  871. /**
  872. * Sets file hiding on or off. If true, hidden files are not shown
  873. * in the filechooser. The job of determining which files are
  874. * show is done by the FileView.
  875. *
  876. * @beaninfo
  877. * preferred: true
  878. * bound: true
  879. * description: Sets file hiding on or off.
  880. *
  881. * @param b the boolean value that determines whether file hiding is
  882. * turned on or not.
  883. * @see #isFileHidingEnabled
  884. */
  885. public void setFileHidingEnabled(boolean b) {
  886. boolean oldValue = useFileHiding;
  887. useFileHiding = b;
  888. firePropertyChange(FILE_HIDING_CHANGED_PROPERTY, oldValue, useFileHiding);
  889. }
  890. /**
  891. * Sets the current File Filter. The file filter is used by the
  892. * filechooser to filter out files from view from the user.
  893. *
  894. * @beaninfo
  895. * preferred: true
  896. * bound: true
  897. * description: Sets the File Filter used to filter out files of type.
  898. *
  899. * @param filter the new current file filter to use
  900. * @see #getFileFilter
  901. */
  902. public void setFileFilter(FileFilter filter) {
  903. FileFilter oldValue = fileFilter;
  904. fileFilter = filter;
  905. if(selectedFile != null && fileFilter != null && !filter.accept(selectedFile)) {
  906. setSelectedFile(null);
  907. }
  908. firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
  909. }
  910. /**
  911. * Returns the currently selected file filter.
  912. *
  913. * @return the current file filter.
  914. * @see #setFileFilter
  915. * @see #addChoosableFileFilter
  916. */
  917. public FileFilter getFileFilter() {
  918. return fileFilter;
  919. }
  920. /**
  921. * Sets the file view to used to retrieve UI information, such as
  922. * the icon that represents a file or the type description of a file.
  923. *
  924. * @beaninfo
  925. * preferred: true
  926. * bound: true
  927. * description: Sets the File View used to get file type information
  928. *
  929. * @see #getFileView
  930. */
  931. public void setFileView(FileView fileView) {
  932. FileView oldValue = this.fileView;
  933. this.fileView = fileView;
  934. firePropertyChange(FILE_VIEW_CHANGED_PROPERTY, oldValue, fileView);
  935. }
  936. /**
  937. * Returns the current file view.
  938. *
  939. * @see #setFileView
  940. */
  941. public FileView getFileView() {
  942. return fileView;
  943. }
  944. // ******************************
  945. // *****FileView delegation *****
  946. // ******************************
  947. // NOTE: all of the following methods attempt to delegate
  948. // first to the client set fileView, and if null is returned
  949. // (or there is now client defined fileView) then calls the
  950. // UI's default fileView.
  951. /**
  952. * Returns the file name.
  953. * @see FileView#getName
  954. */
  955. public String getName(File f) {
  956. String filename = null;
  957. if(getFileView() != null) {
  958. filename = getFileView().getName(f);
  959. }
  960. if(filename == null && uiFileView != null) {
  961. filename = uiFileView.getName(f);
  962. }
  963. return filename;
  964. }
  965. /**
  966. * Returns the file description.
  967. * @see FileView#getDescription
  968. */
  969. public String getDescription(File f) {
  970. String description = null;
  971. if(getFileView() != null) {
  972. description = getFileView().getDescription(f);
  973. }
  974. if(description == null && uiFileView != null) {
  975. description = uiFileView.getDescription(f);
  976. }
  977. return description;
  978. }
  979. /**
  980. * Returns the file type.
  981. * @see FileView#getTypeDescription
  982. */
  983. public String getTypeDescription(File f) {
  984. String typeDescription = null;
  985. if(getFileView() != null) {
  986. typeDescription = getFileView().getTypeDescription(f);
  987. }
  988. if(typeDescription == null && uiFileView != null) {
  989. typeDescription = uiFileView.getTypeDescription(f);
  990. }
  991. return typeDescription;
  992. }
  993. /**
  994. * Returns the icon for this file or type of file, depending
  995. * on the system.
  996. * @see FileView#getIcon
  997. */
  998. public Icon getIcon(File f) {
  999. Icon icon = null;
  1000. if(getFileView() != null) {
  1001. icon = getFileView().getIcon(f);
  1002. }
  1003. if(icon == null && uiFileView != null) {
  1004. icon = uiFileView.getIcon(f);
  1005. }
  1006. return icon;
  1007. }
  1008. /**
  1009. * Returns true if the file (directory) can be visited.
  1010. * Returns false if the directory cannot be traversed.
  1011. * @see FileView#isTraversable
  1012. */
  1013. public boolean isTraversable(File f) {
  1014. Boolean traversable = null;
  1015. if(getFileView() != null) {
  1016. traversable = getFileView().isTraversable(f);
  1017. }
  1018. if(traversable == null && uiFileView != null) {
  1019. traversable = uiFileView.isTraversable(f);
  1020. }
  1021. if(traversable == null && f != null) {
  1022. if(f.isDirectory()) {
  1023. traversable = Boolean.TRUE;
  1024. } else {
  1025. traversable = Boolean.FALSE;
  1026. }
  1027. } else if(traversable == null) {
  1028. return false;
  1029. }
  1030. return traversable.booleanValue();
  1031. }
  1032. /**
  1033. * Returns true if the file should be displayed.
  1034. * @see FileFilter#accept
  1035. */
  1036. public boolean accept(File f) {
  1037. boolean shown = true;
  1038. if(fileFilter != null) {
  1039. shown = fileFilter.accept(f);
  1040. }
  1041. return shown;
  1042. }
  1043. /**
  1044. * Sets the file system view which the JFileChooser uses to
  1045. * access and create file system resouces, such as finding
  1046. * the floppy drive and getting a list of root drives.
  1047. *
  1048. * @beaninfo
  1049. * expert: true
  1050. * bound: true
  1051. * description: Sets the FileSytemView used to get filesystem information
  1052. *
  1053. * @see FileSystemView
  1054. */
  1055. public void setFileSystemView(FileSystemView fsv) {
  1056. FileSystemView oldValue = fileSystemView;
  1057. fileSystemView = fsv;
  1058. firePropertyChange(FILE_SYSTEM_VIEW_CHANGED_PROPERTY, oldValue, fileSystemView);
  1059. }
  1060. /**
  1061. * Returns the file system view.
  1062. * @return the FileSystemView object
  1063. * @see #setFileSystemView
  1064. */
  1065. public FileSystemView getFileSystemView() {
  1066. return fileSystemView;
  1067. }
  1068. // **************************
  1069. // ***** Event Handling *****
  1070. // **************************
  1071. /**
  1072. * Called by the UI when the user hits the approve
  1073. * (AKA "Open" or "Save") button. This can also by
  1074. * called by the programmer.
  1075. */
  1076. public void approveSelection() {
  1077. returnValue = APPROVE_OPTION;
  1078. if(dialog != null) {
  1079. dialog.setVisible(false);
  1080. }
  1081. fireActionPerformed(APPROVE_SELECTION);
  1082. }
  1083. /**
  1084. * Called by the UI when the user hits the cancel button.
  1085. * This can also be called by the programmer.
  1086. */
  1087. public void cancelSelection() {
  1088. returnValue = CANCEL_OPTION;
  1089. if(dialog != null) {
  1090. dialog.setVisible(false);
  1091. }
  1092. fireActionPerformed(CANCEL_SELECTION);
  1093. }
  1094. /**
  1095. * adds an ActionListener to the button
  1096. */
  1097. public void addActionListener(ActionListener l) {
  1098. listenerList.add(ActionListener.class, l);
  1099. }
  1100. /**
  1101. * removes an ActionListener from the button
  1102. */
  1103. public void removeActionListener(ActionListener l) {
  1104. listenerList.remove(ActionListener.class, l);
  1105. }
  1106. /**
  1107. * Notify all listeners that have registered interest for
  1108. * notification on this event type. The event instance
  1109. * is lazily created using the parameters passed into
  1110. * the fire method.
  1111. * @see EventListenerList
  1112. */
  1113. protected void fireActionPerformed(String command) {
  1114. // Guaranteed to return a non-null array
  1115. Object[] listeners = listenerList.getListenerList();
  1116. ActionEvent e = null;
  1117. // Process the listeners last to first, notifying
  1118. // those that are interested in this event
  1119. for (int i = listeners.length-2; i>=0; i-=2) {
  1120. if (listeners[i]==ActionListener.class) {
  1121. // Lazily create the event:
  1122. if (e == null) {
  1123. e = new ActionEvent(this,
  1124. ActionEvent.ACTION_PERFORMED,
  1125. command);
  1126. }
  1127. ((ActionListener)listeners[i+1]).actionPerformed(e);
  1128. }
  1129. }
  1130. }
  1131. // *********************************
  1132. // ***** Pluggable L&F methods *****
  1133. // *********************************
  1134. /**
  1135. * Notification from the UIFactory that the L&F
  1136. * has changed.
  1137. *
  1138. * @see JComponent#updateUI
  1139. */
  1140. public void updateUI() {
  1141. FileChooserUI ui = ((FileChooserUI)UIManager.getUI(this));
  1142. setUI(ui);
  1143. uiFileView = getUI().getFileView(this);
  1144. if(isAcceptAllFileFilterUsed()) {
  1145. addChoosableFileFilter(getAcceptAllFileFilter());
  1146. }
  1147. }
  1148. /**
  1149. * Returns a string that specifies the name of the L&F class
  1150. * that renders this component.
  1151. *
  1152. * @return "ButtonUI"
  1153. * @see JComponent#getUIClassID
  1154. * @see UIDefaults#getUI
  1155. * @beaninfo
  1156. * expert: true
  1157. * description: A string that specifies the name of the L&F class.
  1158. */
  1159. public String getUIClassID() {
  1160. return uiClassID;
  1161. }
  1162. /**
  1163. * Gets the UI object which implements the L&F for this component.
  1164. *
  1165. * @return the FileChooserUI object that implements the FileChooserUI L&F
  1166. */
  1167. public FileChooserUI getUI() {
  1168. return (FileChooserUI) ui;
  1169. }
  1170. /**
  1171. * See readObject() and writeObject() in JComponent for more
  1172. * information about serialization in Swing.
  1173. */
  1174. private void writeObject(ObjectOutputStream s) throws IOException {
  1175. s.defaultWriteObject();
  1176. if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  1177. ui.installUI(this);
  1178. }
  1179. }
  1180. /**
  1181. * Returns a string representation of this JFileChooser. This method
  1182. * is intended to be used only for debugging purposes, and the
  1183. * content and format of the returned string may vary between
  1184. * implementations. The returned string may be empty but may not
  1185. * be <code>null</code>.
  1186. *
  1187. * @return a string representation of this JFileChooser.
  1188. */
  1189. protected String paramString() {
  1190. String approveButtonTextString = (approveButtonText != null ?
  1191. approveButtonText: "");
  1192. String dialogTitleString = (dialogTitle != null ?
  1193. dialogTitle: "");
  1194. String dialogTypeString;
  1195. if (dialogType == OPEN_DIALOG) {
  1196. dialogTypeString = "OPEN_DIALOG";
  1197. } else if (dialogType == SAVE_DIALOG) {
  1198. dialogTypeString = "SAVE_DIALOG";
  1199. } else if (dialogType == CUSTOM_DIALOG) {
  1200. dialogTypeString = "CUSTOM_DIALOG";
  1201. } else dialogTypeString = "";
  1202. String returnValueString;
  1203. if (returnValue == CANCEL_OPTION) {
  1204. returnValueString = "CANCEL_OPTION";
  1205. } else if (returnValue == APPROVE_OPTION) {
  1206. returnValueString = "APPROVE_OPTION";
  1207. } else if (returnValue == ERROR_OPTION) {
  1208. returnValueString = "ERROR_OPTION";
  1209. } else returnValueString = "";
  1210. String useFileHidingString = (useFileHiding ?
  1211. "true" : "false");
  1212. String fileSelectionModeString;
  1213. if (fileSelectionMode == FILES_ONLY) {
  1214. fileSelectionModeString = "FILES_ONLY";
  1215. } else if (fileSelectionMode == DIRECTORIES_ONLY) {
  1216. fileSelectionModeString = "DIRECTORIES_ONLY";
  1217. } else if (fileSelectionMode == FILES_AND_DIRECTORIES) {
  1218. fileSelectionModeString = "FILES_AND_DIRECTORIES";
  1219. } else fileSelectionModeString = "";
  1220. String currentDirectoryString = (currentDirectory != null ?
  1221. currentDirectory.toString() : "");
  1222. String selectedFileString = (selectedFile != null ?
  1223. selectedFile.toString() : "");
  1224. return super.paramString() +
  1225. ",approveButtonText=" + approveButtonTextString +
  1226. ",currentDirectory=" + currentDirectoryString +
  1227. ",dialogTitle=" + dialogTitleString +
  1228. ",dialogType=" + dialogTypeString +
  1229. ",fileSelectionMode=" + fileSelectionModeString +
  1230. ",returnValue=" + returnValueString +
  1231. ",selectedFile=" + selectedFileString +
  1232. ",useFileHiding=" + useFileHidingString;
  1233. }
  1234. /////////////////
  1235. // Accessibility support
  1236. ////////////////
  1237. protected AccessibleContext accessibleContext = null;
  1238. /**
  1239. * Get the AccessibleContext associated with this JFileChooser
  1240. *
  1241. * @return the AccessibleContext of this JFileChooser
  1242. */
  1243. public AccessibleContext getAccessibleContext() {
  1244. if (accessibleContext == null) {
  1245. accessibleContext = new AccessibleJFileChooser();
  1246. }
  1247. return accessibleContext;
  1248. }
  1249. /**
  1250. * The class used to obtain the accessible context for this object.
  1251. */
  1252. protected class AccessibleJFileChooser extends AccessibleJComponent {
  1253. /**
  1254. * Get the role of this object.
  1255. *
  1256. * @return an instance of AccessibleRole describing the role of the
  1257. * object
  1258. * @see AccessibleRole
  1259. */
  1260. public AccessibleRole getAccessibleRole() {
  1261. return AccessibleRole.FILE_CHOOSER;
  1262. }
  1263. } // inner class AccessibleJFileChooser
  1264. }