1. /*
  2. * @(#)BasicFileChooserUI.java 1.26 01/02/09
  3. *
  4. * Copyright 1998-2001 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.swing.plaf.basic;
  11. import javax.swing.*;
  12. import javax.swing.filechooser.*;
  13. import javax.swing.event.*;
  14. import javax.swing.plaf.*;
  15. import java.awt.*;
  16. import java.awt.event.*;
  17. import java.beans.*;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.util.*;
  21. /**
  22. * Basic L&F implementation of a FileChooser.
  23. *
  24. * @version %i% %g%
  25. * @author Jeff Dinkins
  26. */
  27. public class BasicFileChooserUI extends FileChooserUI {
  28. /* FileView icons */
  29. protected Icon directoryIcon = null;
  30. protected Icon fileIcon = null;
  31. protected Icon computerIcon = null;
  32. protected Icon hardDriveIcon = null;
  33. protected Icon floppyDriveIcon = null;
  34. protected Icon newFolderIcon = null;
  35. protected Icon upFolderIcon = null;
  36. protected Icon homeFolderIcon = null;
  37. protected Icon listViewIcon = null;
  38. protected Icon detailsViewIcon = null;
  39. protected int saveButtonMnemonic = 0;
  40. protected int openButtonMnemonic = 0;
  41. protected int cancelButtonMnemonic = 0;
  42. protected int updateButtonMnemonic = 0;
  43. protected int helpButtonMnemonic = 0;
  44. protected String saveButtonText = null;
  45. protected String openButtonText = null;
  46. protected String cancelButtonText = null;
  47. protected String updateButtonText = null;
  48. protected String helpButtonText = null;
  49. private String openDialogTitleText = null;
  50. private String saveDialogTitleText = null;
  51. protected String saveButtonToolTipText = null;
  52. protected String openButtonToolTipText = null;
  53. protected String cancelButtonToolTipText = null;
  54. protected String updateButtonToolTipText = null;
  55. protected String helpButtonToolTipText = null;
  56. // Some generic FileChooser functions
  57. private Action approveSelectionAction = new ApproveSelectionAction();
  58. private Action cancelSelectionAction = new CancelSelectionAction();
  59. private Action updateAction = new UpdateAction();
  60. private Action newFolderAction = new NewFolderAction();
  61. private Action goHomeAction = new GoHomeAction();
  62. private Action changeToParentDirectoryAction = new ChangeToParentDirectoryAction();
  63. private String newFolderErrorSeparator = null;
  64. private String newFolderErrorText = null;
  65. private String fileDescriptionText = null;
  66. private String directoryDescriptionText = null;
  67. private JFileChooser filechooser = null;
  68. private PropertyChangeListener propertyChangeListener = null;
  69. private AncestorListener ancestorListener = null;
  70. private AcceptAllFileFilter acceptAllFileFilter = new AcceptAllFileFilter();
  71. private BasicDirectoryModel model = null;
  72. private BasicFileView fileView = new BasicFileView();
  73. // The accessoryPanel is a container to place the JFileChooser accessory component
  74. private JPanel accessoryPanel = null;
  75. public BasicFileChooserUI(JFileChooser b) {
  76. }
  77. public void installUI(JComponent c) {
  78. accessoryPanel = new JPanel(new BorderLayout());
  79. filechooser = (JFileChooser) c;
  80. createModel();
  81. installDefaults(filechooser);
  82. installComponents(filechooser);
  83. installListeners(filechooser);
  84. }
  85. public void uninstallUI(JComponent c) {
  86. uninstallListeners((JFileChooser) filechooser);
  87. uninstallComponents((JFileChooser) filechooser);
  88. uninstallDefaults((JFileChooser) filechooser);
  89. if(accessoryPanel != null) {
  90. accessoryPanel.removeAll();
  91. }
  92. accessoryPanel = null;
  93. getFileChooser().removeAll();
  94. }
  95. public void installComponents(JFileChooser fc) {
  96. }
  97. public void uninstallComponents(JFileChooser fc) {
  98. }
  99. protected void installListeners(JFileChooser fc) {
  100. propertyChangeListener = createPropertyChangeListener(fc);
  101. if(propertyChangeListener != null) {
  102. fc.addPropertyChangeListener(propertyChangeListener);
  103. }
  104. fc.addPropertyChangeListener(model);
  105. ancestorListener = new AncestorListener() {
  106. public void ancestorAdded(AncestorEvent e) {
  107. JButton approveButton = getApproveButton(getFileChooser());
  108. if(approveButton != null) {
  109. approveButton.requestFocus();
  110. }
  111. }
  112. public void ancestorRemoved(AncestorEvent e) {
  113. }
  114. public void ancestorMoved(AncestorEvent e) {
  115. }
  116. };
  117. fc.addAncestorListener(ancestorListener);
  118. InputMap inputMap = getInputMap(JComponent.
  119. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  120. SwingUtilities.replaceUIInputMap(fc, JComponent.
  121. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap);
  122. ActionMap actionMap = getActionMap();
  123. SwingUtilities.replaceUIActionMap(fc, actionMap);
  124. }
  125. InputMap getInputMap(int condition) {
  126. if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
  127. return (InputMap)UIManager.get("FileChooser.ancestorInputMap");
  128. }
  129. return null;
  130. }
  131. ActionMap getActionMap() {
  132. return createActionMap();
  133. }
  134. ActionMap createActionMap() {
  135. AbstractAction escAction = new AbstractAction() {
  136. public void actionPerformed(ActionEvent e) {
  137. getFileChooser().cancelSelection();
  138. }
  139. public boolean isEnabled(){
  140. return getFileChooser().isEnabled();
  141. }
  142. };
  143. ActionMap map = new ActionMapUIResource();
  144. map.put("cancelSelection", escAction);
  145. return map;
  146. }
  147. protected void uninstallListeners(JFileChooser fc) {
  148. if(propertyChangeListener != null) {
  149. fc.removePropertyChangeListener(propertyChangeListener);
  150. }
  151. fc.removePropertyChangeListener(model);
  152. SwingUtilities.replaceUIInputMap(fc, JComponent.
  153. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
  154. SwingUtilities.replaceUIActionMap(fc, null);
  155. fc.removeAncestorListener(ancestorListener);
  156. ancestorListener = null;
  157. }
  158. protected void installDefaults(JFileChooser fc) {
  159. installIcons(fc);
  160. installStrings(fc);
  161. }
  162. protected void installIcons(JFileChooser fc) {
  163. directoryIcon = UIManager.getIcon("FileView.directoryIcon");
  164. fileIcon = UIManager.getIcon("FileView.fileIcon");
  165. computerIcon = UIManager.getIcon("FileView.computerIcon");
  166. hardDriveIcon = UIManager.getIcon("FileView.hardDriveIcon");
  167. floppyDriveIcon = UIManager.getIcon("FileView.floppyDriveIcon");
  168. newFolderIcon = UIManager.getIcon("FileChooser.newFolderIcon");
  169. upFolderIcon = UIManager.getIcon("FileChooser.upFolderIcon");
  170. homeFolderIcon = UIManager.getIcon("FileChooser.homeFolderIcon");
  171. detailsViewIcon = UIManager.getIcon("FileChooser.detailsViewIcon");
  172. listViewIcon = UIManager.getIcon("FileChooser.listViewIcon");
  173. }
  174. protected void installStrings(JFileChooser fc) {
  175. newFolderErrorText = UIManager.getString("FileChooser.newFolderErrorText");
  176. newFolderErrorSeparator = UIManager.getString("FileChooser.newFolderErrorSeparator");
  177. fileDescriptionText = UIManager.getString("FileChooser.fileDescriptionText");
  178. directoryDescriptionText = UIManager.getString("FileChooser.directoryDescriptionText");
  179. saveButtonText = UIManager.getString("FileChooser.saveButtonText");
  180. openButtonText = UIManager.getString("FileChooser.openButtonText");
  181. saveDialogTitleText = UIManager.getString("FileChooser.saveDialogTitleText");
  182. openDialogTitleText = UIManager.getString("FileChooser.openDialogTitleText");
  183. cancelButtonText = UIManager.getString("FileChooser.cancelButtonText");
  184. updateButtonText = UIManager.getString("FileChooser.updateButtonText");
  185. helpButtonText = UIManager.getString("FileChooser.helpButtonText");
  186. saveButtonMnemonic = UIManager.getInt("FileChooser.saveButtonMnemonic");
  187. openButtonMnemonic = UIManager.getInt("FileChooser.openButtonMnemonic");
  188. cancelButtonMnemonic = UIManager.getInt("FileChooser.cancelButtonMnemonic");
  189. updateButtonMnemonic = UIManager.getInt("FileChooser.updateButtonMnemonic");
  190. helpButtonMnemonic = UIManager.getInt("FileChooser.helpButtonMnemonic");
  191. saveButtonToolTipText = UIManager.getString("FileChooser.saveButtonToolTipText");
  192. openButtonToolTipText = UIManager.getString("FileChooser.openButtonToolTipText");
  193. cancelButtonToolTipText = UIManager.getString("FileChooser.cancelButtonToolTipText");
  194. updateButtonToolTipText = UIManager.getString("FileChooser.updateButtonToolTipText");
  195. helpButtonToolTipText = UIManager.getString("FileChooser.helpButtonToolTipText");
  196. }
  197. protected void uninstallDefaults(JFileChooser fc) {
  198. uninstallIcons(fc);
  199. uninstallStrings(fc);
  200. }
  201. protected void uninstallIcons(JFileChooser fc) {
  202. directoryIcon = null;
  203. fileIcon = null;
  204. computerIcon = null;
  205. hardDriveIcon = null;
  206. floppyDriveIcon = null;
  207. newFolderIcon = null;
  208. upFolderIcon = null;
  209. homeFolderIcon = null;
  210. detailsViewIcon = null;
  211. listViewIcon = null;
  212. }
  213. protected void uninstallStrings(JFileChooser fc) {
  214. saveButtonText = null;
  215. openButtonText = null;
  216. cancelButtonText = null;
  217. updateButtonText = null;
  218. helpButtonText = null;
  219. saveButtonToolTipText = null;
  220. openButtonToolTipText = null;
  221. cancelButtonToolTipText = null;
  222. updateButtonToolTipText = null;
  223. helpButtonToolTipText = null;
  224. }
  225. protected void createModel() {
  226. model = new BasicDirectoryModel(getFileChooser());
  227. }
  228. public BasicDirectoryModel getModel() {
  229. return model;
  230. }
  231. public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
  232. return null;
  233. }
  234. public String getFileName() {
  235. return null;
  236. }
  237. public String getDirectoryName() {
  238. return null;
  239. }
  240. public void setFileName(String filename) {
  241. }
  242. public void setDirectoryName(String dirname) {
  243. }
  244. public void rescanCurrentDirectory(JFileChooser fc) {
  245. }
  246. public void ensureFileIsVisible(JFileChooser fc, File f) {
  247. }
  248. public JFileChooser getFileChooser() {
  249. return filechooser;
  250. }
  251. public JPanel getAccessoryPanel() {
  252. return accessoryPanel;
  253. }
  254. protected JButton getApproveButton(JFileChooser fc) {
  255. return null;
  256. }
  257. public String getApproveButtonToolTipText(JFileChooser fc) {
  258. String tooltipText = fc.getApproveButtonToolTipText();
  259. if(tooltipText != null) {
  260. return tooltipText;
  261. }
  262. if(fc.getDialogType() == JFileChooser.OPEN_DIALOG) {
  263. return openButtonToolTipText;
  264. } else if(fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
  265. return saveButtonToolTipText;
  266. }
  267. return null;
  268. }
  269. public void clearIconCache() {
  270. fileView.clearIconCache();
  271. }
  272. // ********************************************
  273. // ************ Create Listeners **************
  274. // ********************************************
  275. public ListSelectionListener createListSelectionListener(JFileChooser fc) {
  276. return new SelectionListener();
  277. }
  278. protected class DoubleClickListener extends MouseAdapter {
  279. JList list;
  280. public DoubleClickListener(JList list) {
  281. this.list = list;
  282. }
  283. public void mouseClicked(MouseEvent e) {
  284. if (e.getClickCount() == 2) {
  285. int index = list.locationToIndex(e.getPoint());
  286. if(index >= 0) {
  287. File f = (File) list.getModel().getElementAt(index);
  288. try {
  289. // Strip trailing ".."
  290. f = f.getCanonicalFile();
  291. } catch (IOException ex) {
  292. // That's ok, we'll use f as is
  293. }
  294. if(getFileChooser().isTraversable(f)) {
  295. list.clearSelection();
  296. getFileChooser().setCurrentDirectory(f);
  297. } else {
  298. getFileChooser().approveSelection();
  299. }
  300. }
  301. }
  302. }
  303. }
  304. protected MouseListener createDoubleClickListener(JFileChooser fc, JList list) {
  305. return new DoubleClickListener(list);
  306. }
  307. protected class SelectionListener implements ListSelectionListener {
  308. public void valueChanged(ListSelectionEvent e) {
  309. if(!e.getValueIsAdjusting()) {
  310. JFileChooser chooser = getFileChooser();
  311. JList list = (JList) e.getSource();
  312. File file = (File) list.getSelectedValue();
  313. if(file != null) {
  314. chooser.setSelectedFile(file);
  315. }
  316. if(chooser.isMultiSelectionEnabled()) {
  317. Object[] objects = list.getSelectedValues();
  318. if(objects != null) {
  319. File[] files = new File[objects.length];
  320. for(int i = 0; i < objects.length; i++) {
  321. files[i] = (File) objects[i];
  322. }
  323. chooser.setSelectedFiles(files);
  324. }
  325. }
  326. }
  327. }
  328. }
  329. // *******************************************************
  330. // ************ FileChooser UI PLAF methods **************
  331. // *******************************************************
  332. /**
  333. * Returns the default accept all file filter
  334. */
  335. public FileFilter getAcceptAllFileFilter(JFileChooser fc) {
  336. return acceptAllFileFilter;
  337. }
  338. public FileView getFileView(JFileChooser fc) {
  339. return fileView;
  340. }
  341. /**
  342. * Returns the title of this dialog
  343. */
  344. public String getDialogTitle(JFileChooser fc) {
  345. String dialogTitle = fc.getDialogTitle();
  346. if (dialogTitle != null) {
  347. return dialogTitle;
  348. } else if (fc.getDialogType() == JFileChooser.OPEN_DIALOG) {
  349. return openDialogTitleText;
  350. } else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
  351. return saveDialogTitleText;
  352. } else {
  353. return getApproveButtonText(fc);
  354. }
  355. }
  356. public int getApproveButtonMnemonic(JFileChooser fc) {
  357. if(getFileChooser().getDialogType() == JFileChooser.OPEN_DIALOG) {
  358. return openButtonMnemonic;
  359. } else if(getFileChooser().getDialogType() == JFileChooser.SAVE_DIALOG) {
  360. return saveButtonMnemonic;
  361. }
  362. int mnemonic = getFileChooser().getApproveButtonMnemonic();
  363. return mnemonic;
  364. }
  365. public String getApproveButtonText(JFileChooser fc) {
  366. String buttonText = getFileChooser().getApproveButtonText();
  367. if(buttonText != null) {
  368. return buttonText;
  369. }
  370. if(getFileChooser().getDialogType() == JFileChooser.OPEN_DIALOG) {
  371. return openButtonText;
  372. } else if(getFileChooser().getDialogType() == JFileChooser.SAVE_DIALOG) {
  373. return saveButtonText;
  374. }
  375. return null;
  376. }
  377. // *****************************
  378. // ***** Directory Actions *****
  379. // *****************************
  380. public Action getNewFolderAction() {
  381. return newFolderAction;
  382. }
  383. public Action getGoHomeAction() {
  384. return goHomeAction;
  385. }
  386. public Action getChangeToParentDirectoryAction() {
  387. return changeToParentDirectoryAction;
  388. }
  389. public Action getApproveSelectionAction() {
  390. return approveSelectionAction;
  391. }
  392. public Action getCancelSelectionAction() {
  393. return cancelSelectionAction;
  394. }
  395. public Action getUpdateAction() {
  396. return updateAction;
  397. }
  398. /**
  399. * Creates a new folder.
  400. */
  401. protected class NewFolderAction extends AbstractAction {
  402. protected NewFolderAction() {
  403. super("New Folder");
  404. }
  405. public void actionPerformed(ActionEvent e) {
  406. JFileChooser fc = getFileChooser();
  407. File currentDirectory = fc.getCurrentDirectory();
  408. File newFolder = null;
  409. try {
  410. newFolder = fc.getFileSystemView().createNewFolder(currentDirectory);
  411. } catch (IOException exc) {
  412. JOptionPane.showMessageDialog(
  413. fc,
  414. newFolderErrorText + newFolderErrorSeparator + exc,
  415. newFolderErrorText, JOptionPane.ERROR_MESSAGE);
  416. return;
  417. }
  418. fc.rescanCurrentDirectory();
  419. fc.ensureFileIsVisible(newFolder);
  420. }
  421. }
  422. /**
  423. * Acts on the "home" key event or equivalent event.
  424. */
  425. protected class GoHomeAction extends AbstractAction {
  426. protected GoHomeAction() {
  427. super("Go Home");
  428. }
  429. public void actionPerformed(ActionEvent e) {
  430. getFileChooser().setCurrentDirectory(null);
  431. }
  432. }
  433. protected class ChangeToParentDirectoryAction extends AbstractAction {
  434. protected ChangeToParentDirectoryAction() {
  435. super("Go Up");
  436. }
  437. public void actionPerformed(ActionEvent e) {
  438. getFileChooser().changeToParentDirectory();
  439. }
  440. }
  441. /**
  442. * Responds to an Open or Save request
  443. */
  444. protected class ApproveSelectionAction extends AbstractAction {
  445. public void actionPerformed(ActionEvent e) {
  446. JFileChooser chooser = getFileChooser();
  447. String filename = getFileName();
  448. FileSystemView fs = chooser.getFileSystemView();
  449. File dir = chooser.getCurrentDirectory();
  450. if(filename == null || filename.equals("")) {
  451. // no file selected, multiple selection off, therefore cancel the approve action
  452. return;
  453. }
  454. if(filename != null) {
  455. // Remove whitespace from beginning and end of filename
  456. filename = filename.trim();
  457. }
  458. if(filename != null && !filename.equals("")) {
  459. // check for directory change action
  460. File selectedFile = fs.createFileObject(filename);
  461. if(!selectedFile.isAbsolute()) {
  462. selectedFile = fs.createFileObject(dir, filename);
  463. }
  464. boolean isDir = selectedFile.isDirectory();
  465. boolean isTrav = chooser.isTraversable(selectedFile);
  466. boolean isDirSelEnabled = chooser.isDirectorySelectionEnabled();
  467. boolean isFileSelEnabled = chooser.isFileSelectionEnabled();
  468. if(isDir && isTrav && !isDirSelEnabled) {
  469. chooser.setCurrentDirectory(selectedFile);
  470. } else if ((!isDir && isFileSelEnabled) || (isDir && isDirSelEnabled)) {
  471. chooser.setSelectedFile(selectedFile);
  472. chooser.approveSelection();
  473. }
  474. return;
  475. }
  476. chooser.setSelectedFile(null);
  477. chooser.setSelectedFiles(null);
  478. chooser.cancelSelection();
  479. }
  480. }
  481. /**
  482. * Responds to a cancel request.
  483. */
  484. protected class CancelSelectionAction extends AbstractAction {
  485. public void actionPerformed(ActionEvent e) {
  486. getFileChooser().cancelSelection();
  487. }
  488. }
  489. /**
  490. * Rescans the files in the current directory
  491. */
  492. protected class UpdateAction extends AbstractAction {
  493. public void actionPerformed(ActionEvent e) {
  494. JFileChooser fc = getFileChooser();
  495. fc.setCurrentDirectory(fc.getFileSystemView().createFileObject(getDirectoryName()));
  496. fc.rescanCurrentDirectory();
  497. }
  498. }
  499. // *****************************************
  500. // ***** default AcceptAll file filter *****
  501. // *****************************************
  502. protected class AcceptAllFileFilter extends FileFilter {
  503. public AcceptAllFileFilter() {
  504. }
  505. public boolean accept(File f) {
  506. return true;
  507. }
  508. public String getDescription() {
  509. return UIManager.getString("FileChooser.acceptAllFileFilterText");
  510. }
  511. }
  512. // ***********************
  513. // * FileView operations *
  514. // ***********************
  515. protected class BasicFileView extends FileView {
  516. /* FileView type descriptions */
  517. // PENDING(jeff) - pass in the icon cache size
  518. protected Hashtable iconCache = new Hashtable();
  519. public BasicFileView() {
  520. }
  521. public void clearIconCache() {
  522. iconCache = new Hashtable();
  523. }
  524. public String getName(File f) {
  525. String fileName = null;
  526. if(f != null) {
  527. fileName = f.getName();
  528. if (fileName.equals("")) {
  529. fileName = f.getPath();
  530. }
  531. }
  532. return fileName;
  533. }
  534. public String getDescription(File f) {
  535. return f.getName();
  536. }
  537. public String getTypeDescription(File f) {
  538. if (f.isDirectory()) {
  539. return directoryDescriptionText;
  540. } else {
  541. return fileDescriptionText;
  542. }
  543. }
  544. public Icon getCachedIcon(File f) {
  545. return (Icon) iconCache.get(f);
  546. }
  547. public void cacheIcon(File f, Icon i) {
  548. if(f == null || i == null) {
  549. return;
  550. }
  551. iconCache.put(f, i);
  552. }
  553. public Icon getIcon(File f) {
  554. Icon icon = getCachedIcon(f);
  555. if(icon != null) {
  556. return icon;
  557. }
  558. if (f != null && f.isDirectory()) {
  559. if(getFileChooser().getFileSystemView().isRoot(f)) {
  560. icon = hardDriveIcon;
  561. } else {
  562. icon = directoryIcon;
  563. }
  564. } else {
  565. icon = fileIcon;
  566. }
  567. cacheIcon(f, icon);
  568. return icon;
  569. }
  570. public Boolean isTraversable(File f) {
  571. if (f.isDirectory()) {
  572. return Boolean.TRUE;
  573. } else {
  574. return Boolean.FALSE;
  575. }
  576. }
  577. public Boolean isHidden(File f) {
  578. String name = f.getName();
  579. if(name != null && name.charAt(0) == '.') {
  580. return Boolean.TRUE;
  581. } else {
  582. return Boolean.FALSE;
  583. }
  584. }
  585. }
  586. }