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