1. /*
  2. * @(#)SynthFileChooserUI.java 1.9 04/01/13
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.gtk;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.beans.*;
  11. import java.io.File;
  12. import java.io.IOException;
  13. import java.util.*;
  14. import java.util.regex.*;
  15. import javax.swing.*;
  16. import javax.swing.event.*;
  17. import javax.swing.filechooser.*;
  18. import javax.swing.plaf.*;
  19. import javax.swing.plaf.basic.BasicDirectoryModel;
  20. /**
  21. * Synth FileChooserUI.
  22. *
  23. * Note: This class is abstract. It does not actually create the file chooser GUI.
  24. *
  25. * @version 1.9, 01/13/04
  26. * @author Leif Samuelsson
  27. * @author Jeff Dinkins
  28. */
  29. abstract class SynthFileChooserUI extends FileChooserUI implements SynthUI {
  30. private JFileChooser filechooser = null;
  31. private JButton approveButton, cancelButton;
  32. private SynthStyle style;
  33. private SynthFileView fileView = new SynthFileView();
  34. private BasicDirectoryModel model = null;
  35. private PropertyChangeListener propertyChangeListener = null;
  36. private String saveButtonText = null;
  37. private String openButtonText = null;
  38. private String cancelButtonText = null;
  39. private String openDialogTitleText = null;
  40. private String saveDialogTitleText = null;
  41. private String saveButtonToolTipText = null;
  42. private String openButtonToolTipText = null;
  43. private String cancelButtonToolTipText = null;
  44. private int saveButtonMnemonic = 0;
  45. private int openButtonMnemonic = 0;
  46. private int cancelButtonMnemonic = 0;
  47. // Some generic FileChooser functions
  48. private Action approveSelectionAction = new ApproveSelectionAction();
  49. private Action cancelSelectionAction = new CancelSelectionAction();
  50. private Action newFolderAction = new NewFolderAction();
  51. private Action goHomeAction = new GoHomeAction();
  52. private Action changeToParentDirectoryAction = new ChangeToParentDirectoryAction();
  53. private Action fileNameCompletionAction = new FileNameCompletionAction();
  54. private String newFolderErrorSeparator = null;
  55. private String newFolderErrorText = null;
  56. private String fileDescriptionText = null;
  57. private String directoryDescriptionText = null;
  58. private AcceptAllFileFilter acceptAllFileFilter = new AcceptAllFileFilter();
  59. private boolean directorySelected = false;
  60. private File directory = null;
  61. private FileFilter actualFileFilter = null;
  62. private GlobFilter globFilter = null;
  63. public JFileChooser getFileChooser() {
  64. return filechooser;
  65. }
  66. public SynthContext getContext(JComponent c) {
  67. return getContext(c, SynthLookAndFeel.getComponentState(c));
  68. }
  69. private SynthContext getContext(JComponent c, int state) {
  70. Region region = SynthLookAndFeel.getRegion(c);
  71. return SynthContext.getContext(SynthContext.class, c, region,
  72. style, state);
  73. }
  74. private Region getRegion(JComponent c) {
  75. return SynthLookAndFeel.getRegion(c);
  76. }
  77. private int getComponentState(JComponent c) {
  78. return SynthLookAndFeel.getComponentState(c);
  79. }
  80. private void fetchStyle(JComponent c) {
  81. SynthContext context = getContext(c, ENABLED);
  82. style = SynthLookAndFeel.updateStyle(context, this);
  83. context.dispose();
  84. }
  85. public FileView getFileView(JFileChooser fc) {
  86. return fileView;
  87. }
  88. public String getApproveButtonToolTipText(JFileChooser fc) {
  89. String tooltipText = fc.getApproveButtonToolTipText();
  90. if (tooltipText != null) {
  91. return tooltipText;
  92. }
  93. if (fc.getDialogType() == JFileChooser.OPEN_DIALOG) {
  94. return openButtonToolTipText;
  95. } else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
  96. return saveButtonToolTipText;
  97. }
  98. return null;
  99. }
  100. public void installUI(JComponent c) {
  101. filechooser = (JFileChooser) c;
  102. createModel();
  103. installDefaults(filechooser);
  104. installComponents(filechooser);
  105. installListeners(filechooser);
  106. filechooser.applyComponentOrientation(filechooser.getComponentOrientation());
  107. }
  108. public void uninstallUI(JComponent c) {
  109. getFileChooser().removeAll();
  110. uninstallListeners((JFileChooser) filechooser);
  111. uninstallComponents((JFileChooser) filechooser);
  112. uninstallDefaults((JFileChooser) filechooser);
  113. }
  114. public void installComponents(JFileChooser fc) {
  115. SynthContext context = getContext(fc, ENABLED);
  116. cancelButton = new JButton(cancelButtonText);
  117. cancelButton.setName("SynthFileChooser.cancelButton");
  118. cancelButton.setIcon(context.getStyle().getIcon(context, "FileChooser.cancelIcon"));
  119. cancelButton.setMnemonic(cancelButtonMnemonic);
  120. cancelButton.setToolTipText(cancelButtonToolTipText);
  121. cancelButton.addActionListener(getCancelSelectionAction());
  122. approveButton = new JButton(getApproveButtonText(fc));
  123. approveButton.setName("SynthFileChooser.approveButton");
  124. approveButton.setIcon(context.getStyle().getIcon(context, "FileChooser.okIcon"));
  125. approveButton.setMnemonic(getApproveButtonMnemonic(fc));
  126. approveButton.setToolTipText(getApproveButtonToolTipText(fc));
  127. approveButton.addActionListener(getApproveSelectionAction());
  128. }
  129. public void uninstallComponents(JFileChooser fc) {
  130. fc.removeAll();
  131. }
  132. protected void installListeners(JFileChooser fc) {
  133. propertyChangeListener = createPropertyChangeListener(fc);
  134. if(propertyChangeListener != null) {
  135. fc.addPropertyChangeListener(propertyChangeListener);
  136. }
  137. fc.addPropertyChangeListener(getModel());
  138. InputMap inputMap = getInputMap(JComponent.
  139. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  140. SwingUtilities.replaceUIInputMap(fc, JComponent.
  141. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap);
  142. ActionMap actionMap = getActionMap();
  143. SwingUtilities.replaceUIActionMap(fc, actionMap);
  144. getModel().addListDataListener(new ListDataListener() {
  145. public void contentsChanged(ListDataEvent e) {
  146. // Update the selection after JList has been updated
  147. new DelayedSelectionUpdater();
  148. }
  149. public void intervalAdded(ListDataEvent e) {
  150. new DelayedSelectionUpdater();
  151. }
  152. public void intervalRemoved(ListDataEvent e) {
  153. }
  154. });
  155. }
  156. private class DelayedSelectionUpdater implements Runnable {
  157. DelayedSelectionUpdater() {
  158. SwingUtilities.invokeLater(this);
  159. }
  160. public void run() {
  161. updateFileNameCompletion();
  162. }
  163. }
  164. InputMap getInputMap(int condition) {
  165. if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
  166. SynthContext context = getContext(filechooser, ENABLED);
  167. InputMap inputMap = (InputMap)context.getStyle().get(context, "FileChooser.ancestorInputMap");
  168. context.dispose();
  169. return inputMap;
  170. }
  171. return null;
  172. }
  173. ActionMap getActionMap() {
  174. return createActionMap();
  175. }
  176. ActionMap createActionMap() {
  177. AbstractAction escAction = new AbstractAction() {
  178. public void actionPerformed(ActionEvent e) {
  179. getFileChooser().cancelSelection();
  180. }
  181. public boolean isEnabled(){
  182. return getFileChooser().isEnabled();
  183. }
  184. };
  185. ActionMap map = new ActionMapUIResource();
  186. map.put("approveSelection", getApproveSelectionAction());
  187. map.put("cancelSelection", escAction);
  188. map.put("Go Up", getChangeToParentDirectoryAction());
  189. map.put("fileNameCompletion", getFileNameCompletionAction());
  190. return map;
  191. }
  192. protected void uninstallListeners(JFileChooser fc) {
  193. if(propertyChangeListener != null) {
  194. fc.removePropertyChangeListener(propertyChangeListener);
  195. }
  196. fc.removePropertyChangeListener(getModel());
  197. SwingUtilities.replaceUIInputMap(fc, JComponent.
  198. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
  199. SwingUtilities.replaceUIActionMap(fc, null);
  200. }
  201. protected void installDefaults(JFileChooser fc) {
  202. fetchStyle(fc);
  203. installIcons(fc);
  204. installStrings(fc);
  205. }
  206. protected void uninstallDefaults(JFileChooser fc) {
  207. uninstallIcons(fc);
  208. uninstallStrings(fc);
  209. SynthContext context = getContext(filechooser, ENABLED);
  210. style.uninstallDefaults(context);
  211. context.dispose();
  212. style = null;
  213. }
  214. protected void installIcons(JFileChooser fc) {
  215. // No icons are installed by default
  216. }
  217. protected void uninstallIcons(JFileChooser fc) {
  218. // No icons are installed by default
  219. }
  220. protected void installStrings(JFileChooser fc) {
  221. Locale l = fc.getLocale();
  222. newFolderErrorText = UIManager.getString("FileChooser.newFolderErrorText",l);
  223. newFolderErrorSeparator = UIManager.getString("FileChooser.newFolderErrorSeparator",l);
  224. fileDescriptionText = UIManager.getString("FileChooser.fileDescriptionText",l);
  225. directoryDescriptionText = UIManager.getString("FileChooser.directoryDescriptionText",l);
  226. saveButtonText = UIManager.getString("FileChooser.saveButtonText",l);
  227. openButtonText = UIManager.getString("FileChooser.openButtonText",l);
  228. saveDialogTitleText = UIManager.getString("FileChooser.saveDialogTitleText",l);
  229. openDialogTitleText = UIManager.getString("FileChooser.openDialogTitleText",l);
  230. cancelButtonText = UIManager.getString("FileChooser.cancelButtonText",l);
  231. saveButtonMnemonic = UIManager.getInt("FileChooser.saveButtonMnemonic");
  232. openButtonMnemonic = UIManager.getInt("FileChooser.openButtonMnemonic");
  233. cancelButtonMnemonic = UIManager.getInt("FileChooser.cancelButtonMnemonic");
  234. saveButtonToolTipText = UIManager.getString("FileChooser.saveButtonToolTipText",l);
  235. openButtonToolTipText = UIManager.getString("FileChooser.openButtonToolTipText",l);
  236. cancelButtonToolTipText = UIManager.getString("FileChooser.cancelButtonToolTipText",l);
  237. }
  238. protected void uninstallStrings(JFileChooser fc) {
  239. saveButtonText = null;
  240. openButtonText = null;
  241. cancelButtonText = null;
  242. saveButtonToolTipText = null;
  243. openButtonToolTipText = null;
  244. cancelButtonToolTipText = null;
  245. }
  246. protected void createModel() {
  247. model = new BasicDirectoryModel(getFileChooser());
  248. }
  249. public BasicDirectoryModel getModel() {
  250. return model;
  251. }
  252. /**
  253. * Property to remember the directory that is currently selected in the UI.
  254. * This is normally called by the UI on a selection event.
  255. *
  256. * @param f the <code>File</code> object representing the directory that is
  257. * currently selected
  258. * @since 1.4
  259. */
  260. protected void setDirectory(File f) {
  261. directory = f;
  262. }
  263. abstract public void setFileName(String fileName);
  264. abstract public String getFileName();
  265. protected void doSelectedFileChanged(PropertyChangeEvent e) {
  266. }
  267. protected void doDirectoryChanged(PropertyChangeEvent e) {
  268. File currentDirectory = getFileChooser().getCurrentDirectory();
  269. if (currentDirectory != null) {
  270. getNewFolderAction().setEnabled(currentDirectory.canWrite());
  271. }
  272. }
  273. protected void doAccessoryChanged(PropertyChangeEvent e) {
  274. }
  275. protected void doFileSelectionModeChanged(PropertyChangeEvent e) {
  276. }
  277. protected void doMultiSelectionChanged(PropertyChangeEvent e) {
  278. if (!getFileChooser().isMultiSelectionEnabled()) {
  279. getFileChooser().setSelectedFiles(null);
  280. }
  281. }
  282. protected void doControlButtonsChanged(PropertyChangeEvent e) {
  283. if (filechooser.getControlButtonsAreShown()) {
  284. approveButton.setText(getApproveButtonText(getFileChooser()));
  285. approveButton.setToolTipText(getApproveButtonToolTipText(getFileChooser()));
  286. }
  287. }
  288. protected void doAncestorChanged(PropertyChangeEvent e) {
  289. }
  290. public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
  291. return new SynthFCPropertyChangeListener();
  292. }
  293. protected class SynthFCPropertyChangeListener implements PropertyChangeListener {
  294. public void propertyChange(PropertyChangeEvent e) {
  295. String prop = e.getPropertyName();
  296. if (prop.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
  297. doFileSelectionModeChanged(e);
  298. } else if (prop.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
  299. doSelectedFileChanged(e);
  300. } else if (prop.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
  301. doDirectoryChanged(e);
  302. } else if (prop == JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY) {
  303. doMultiSelectionChanged(e);
  304. } else if (prop == JFileChooser.ACCESSORY_CHANGED_PROPERTY) {
  305. doAccessoryChanged(e);
  306. } else if (prop == JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY ||
  307. prop == JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY ||
  308. prop == JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY ||
  309. prop == JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY) {
  310. doControlButtonsChanged(e);
  311. } else if (prop.equals("componentOrientation")) {
  312. ComponentOrientation o = (ComponentOrientation)e.getNewValue();
  313. JFileChooser cc = (JFileChooser)e.getSource();
  314. if (o != (ComponentOrientation)e.getOldValue()) {
  315. cc.applyComponentOrientation(o);
  316. }
  317. } else if (prop.equals("ancestor")) {
  318. doAncestorChanged(e);
  319. }
  320. }
  321. }
  322. /**
  323. * Property to remember whether a directory is currently selected in the UI.
  324. *
  325. * @return <code>true</code> iff a directory is currently selected.
  326. * @since 1.4
  327. */
  328. protected boolean isDirectorySelected() {
  329. return directorySelected;
  330. }
  331. /**
  332. * Property to remember whether a directory is currently selected in the UI.
  333. * This is normally called by the UI on a selection event.
  334. *
  335. * @param b iff a directory is currently selected.
  336. * @since 1.4
  337. */
  338. protected void setDirectorySelected(boolean b) {
  339. directorySelected = b;
  340. }
  341. /**
  342. * Property to remember the directory that is currently selected in the UI.
  343. *
  344. * @return the value of the <code>directory</code> property
  345. * @see #setDirectory
  346. * @since 1.4
  347. */
  348. protected File getDirectory() {
  349. return directory;
  350. }
  351. /**
  352. * Responds to an Open or Save request
  353. */
  354. protected class ApproveSelectionAction extends AbstractAction {
  355. protected ApproveSelectionAction() {
  356. super("approveSelection");
  357. }
  358. public void actionPerformed(ActionEvent e) {
  359. if (isDirectorySelected()) {
  360. File dir = getDirectory();
  361. if (dir != null) {
  362. try {
  363. // Strip trailing ".."
  364. dir = dir.getCanonicalFile();
  365. } catch (IOException ex) {
  366. // Ok, use f as is
  367. }
  368. getFileChooser().setCurrentDirectory(dir);
  369. return;
  370. }
  371. }
  372. JFileChooser chooser = getFileChooser();
  373. String fileName = getFileName();
  374. FileSystemView fs = chooser.getFileSystemView();
  375. File dir = chooser.getCurrentDirectory();
  376. if (fileName != null) {
  377. // Remove whitespace from beginning and end of filename
  378. fileName = fileName.trim();
  379. }
  380. if (fileName == null || fileName.equals("")) {
  381. // no file selected, multiple selection off, therefore cancel the approve action
  382. resetGlobFilter();
  383. return;
  384. }
  385. File selectedFile = null;
  386. File[] selectedFiles = null;
  387. if (fileName != null && !fileName.equals("")) {
  388. // Unix: Resolve '~' to user's home directory
  389. if (File.separatorChar == '/') {
  390. if (fileName.startsWith("~/")) {
  391. fileName = System.getProperty("user.home") + fileName.substring(1);
  392. } else if (fileName.equals("~")) {
  393. fileName = System.getProperty("user.home");
  394. }
  395. }
  396. if (chooser.isMultiSelectionEnabled() && fileName.startsWith("\"")) {
  397. ArrayList fList = new ArrayList();
  398. fileName = fileName.substring(1);
  399. if (fileName.endsWith("\"")) {
  400. fileName = fileName.substring(0, fileName.length()-1);
  401. }
  402. File[] children = null;
  403. int childIndex = 0;
  404. do {
  405. String str;
  406. int i = fileName.indexOf("\" \"");
  407. if (i > 0) {
  408. str = fileName.substring(0, i);
  409. fileName = fileName.substring(i+3);
  410. } else {
  411. str = fileName;
  412. fileName = "";
  413. }
  414. File file = fs.createFileObject(str);
  415. if (!file.isAbsolute()) {
  416. if (children == null) {
  417. children = fs.getFiles(dir, false);
  418. Arrays.sort(children);
  419. }
  420. for (int k = 0; k < children.length; k++) {
  421. int l = (childIndex + k) % children.length;
  422. if (children[l].getName().equals(str)) {
  423. file = children[l];
  424. childIndex = l + 1;
  425. break;
  426. }
  427. }
  428. }
  429. fList.add(file);
  430. } while (fileName.length() > 0);
  431. if (fList.size() > 0) {
  432. selectedFiles = (File[])fList.toArray(new File[fList.size()]);
  433. }
  434. resetGlobFilter();
  435. } else {
  436. selectedFile = fs.createFileObject(fileName);
  437. if(!selectedFile.isAbsolute()) {
  438. selectedFile = fs.getChild(dir, fileName);
  439. }
  440. // check for wildcard pattern
  441. FileFilter currentFilter = chooser.getFileFilter();
  442. if (!selectedFile.exists() && isGlobPattern(fileName)) {
  443. if (globFilter == null) {
  444. globFilter = new GlobFilter();
  445. }
  446. globFilter.setPattern(fileName);
  447. if (!(currentFilter instanceof GlobFilter)) {
  448. actualFileFilter = currentFilter;
  449. }
  450. chooser.setFileFilter(null);
  451. chooser.setFileFilter(globFilter);
  452. return;
  453. }
  454. resetGlobFilter();
  455. // Check for directory change action
  456. boolean isDir = (selectedFile != null && selectedFile.isDirectory());
  457. boolean isTrav = (selectedFile != null && chooser.isTraversable(selectedFile));
  458. boolean isDirSelEnabled = chooser.isDirectorySelectionEnabled();
  459. boolean isFileSelEnabled = chooser.isFileSelectionEnabled();
  460. if (isDir && isTrav && !isDirSelEnabled) {
  461. chooser.setCurrentDirectory(selectedFile);
  462. return;
  463. } else if ((isDir || !isFileSelEnabled)
  464. && (!isDir || !isDirSelEnabled)
  465. && (!isDirSelEnabled || selectedFile.exists())) {
  466. selectedFile = null;
  467. }
  468. }
  469. }
  470. if (selectedFiles != null || selectedFile != null) {
  471. if (selectedFiles != null) {
  472. chooser.setSelectedFiles(selectedFiles);
  473. } else if (chooser.isMultiSelectionEnabled()) {
  474. chooser.setSelectedFiles(new File[] { selectedFile });
  475. } else {
  476. chooser.setSelectedFile(selectedFile);
  477. }
  478. chooser.approveSelection();
  479. } else {
  480. if (chooser.isMultiSelectionEnabled()) {
  481. chooser.setSelectedFiles(null);
  482. } else {
  483. chooser.setSelectedFile(null);
  484. }
  485. chooser.cancelSelection();
  486. }
  487. }
  488. }
  489. /**
  490. * Responds to a File Name completion request (e.g. Tab)
  491. */
  492. protected class FileNameCompletionAction extends AbstractAction {
  493. protected FileNameCompletionAction() {
  494. super("fileNameCompletion");
  495. }
  496. public void actionPerformed(ActionEvent e) {
  497. JFileChooser chooser = getFileChooser();
  498. String fileName = getFileName();
  499. if (fileName != null) {
  500. // Remove whitespace from beginning and end of filename
  501. fileName = fileName.trim();
  502. }
  503. resetGlobFilter();
  504. if (fileName == null || fileName.equals("") ||
  505. (chooser.isMultiSelectionEnabled() && fileName.startsWith("\""))) {
  506. return;
  507. }
  508. FileFilter currentFilter = chooser.getFileFilter();
  509. if (globFilter == null) {
  510. globFilter = new GlobFilter();
  511. }
  512. globFilter.setPattern(fileName + "*");
  513. if (!(currentFilter instanceof GlobFilter)) {
  514. actualFileFilter = currentFilter;
  515. }
  516. chooser.setFileFilter(null);
  517. chooser.setFileFilter(globFilter);
  518. fileNameCompletionString = fileName;
  519. }
  520. }
  521. private String fileNameCompletionString;
  522. private void updateFileNameCompletion() {
  523. if (fileNameCompletionString != null) {
  524. if (fileNameCompletionString.equals(getFileName())) {
  525. File[] files = (File[])getModel().getFiles().toArray(new File[0]);
  526. String str = getCommonStartString(files);
  527. if (str != null && str.startsWith(fileNameCompletionString)) {
  528. setFileName(str);
  529. }
  530. fileNameCompletionString = null;
  531. }
  532. }
  533. }
  534. private String getCommonStartString(File[] files) {
  535. String str = null;
  536. String str2 = null;
  537. int i = 0;
  538. if (files.length == 0) {
  539. return null;
  540. }
  541. while (true) {
  542. for (int f = 0; f < files.length; f++) {
  543. String name = files[f].getName();
  544. if (f == 0) {
  545. if (name.length() == i) {
  546. return str;
  547. }
  548. str2 = name.substring(0, i+1);
  549. }
  550. if (!name.startsWith(str2)) {
  551. return str;
  552. }
  553. }
  554. str = str2;
  555. i++;
  556. }
  557. }
  558. private void resetGlobFilter() {
  559. if (actualFileFilter != null) {
  560. JFileChooser chooser = getFileChooser();
  561. FileFilter currentFilter = chooser.getFileFilter();
  562. if (currentFilter != null && currentFilter.equals(globFilter)) {
  563. chooser.setFileFilter(actualFileFilter);
  564. chooser.removeChoosableFileFilter(globFilter);
  565. }
  566. actualFileFilter = null;
  567. }
  568. }
  569. private static boolean isGlobPattern(String fileName) {
  570. return ((File.separatorChar == '\\' && fileName.indexOf('*') >= 0)
  571. || (File.separatorChar == '/' && (fileName.indexOf('*') >= 0
  572. || fileName.indexOf('?') >= 0
  573. || fileName.indexOf('[') >= 0)));
  574. }
  575. /* A file filter which accepts file patterns containing
  576. * the special wildcard '*' on windows, plus '?', and '[ ]' on Unix.
  577. */
  578. class GlobFilter extends FileFilter {
  579. Pattern pattern;
  580. String globPattern;
  581. public void setPattern(String globPattern) {
  582. char[] gPat = globPattern.toCharArray();
  583. char[] rPat = new char[gPat.length * 2];
  584. boolean isWin32 = (File.separatorChar == '\\');
  585. boolean inBrackets = false;
  586. StringBuffer buf = new StringBuffer();
  587. int j = 0;
  588. this.globPattern = globPattern;
  589. if (isWin32) {
  590. // On windows, a pattern ending with *.* is equal to ending with *
  591. int len = gPat.length;
  592. if (globPattern.endsWith("*.*")) {
  593. len -= 2;
  594. }
  595. for (int i = 0; i < len; i++) {
  596. if (gPat[i] == '*') {
  597. rPat[j++] = '.';
  598. }
  599. rPat[j++] = gPat[i];
  600. }
  601. } else {
  602. for (int i = 0; i < gPat.length; i++) {
  603. switch(gPat[i]) {
  604. case '*':
  605. if (!inBrackets) {
  606. rPat[j++] = '.';
  607. }
  608. rPat[j++] = '*';
  609. break;
  610. case '?':
  611. rPat[j++] = inBrackets ? '?' : '.';
  612. break;
  613. case '[':
  614. inBrackets = true;
  615. rPat[j++] = gPat[i];
  616. if (i < gPat.length - 1) {
  617. switch (gPat[i+1]) {
  618. case '!':
  619. case '^':
  620. rPat[j++] = '^';
  621. i++;
  622. break;
  623. case ']':
  624. rPat[j++] = gPat[++i];
  625. break;
  626. }
  627. }
  628. break;
  629. case ']':
  630. rPat[j++] = gPat[i];
  631. inBrackets = false;
  632. break;
  633. case '\\':
  634. if (i == 0 && gPat.length > 1 && gPat[1] == '~') {
  635. rPat[j++] = gPat[++i];
  636. } else {
  637. rPat[j++] = '\\';
  638. if (i < gPat.length - 1 && "*?[]".indexOf(gPat[i+1]) >= 0) {
  639. rPat[j++] = gPat[++i];
  640. } else {
  641. rPat[j++] = '\\';
  642. }
  643. }
  644. break;
  645. default:
  646. //if ("+()|^$.{}<>".indexOf(gPat[i]) >= 0) {
  647. if (!Character.isLetterOrDigit(gPat[i])) {
  648. rPat[j++] = '\\';
  649. }
  650. rPat[j++] = gPat[i];
  651. break;
  652. }
  653. }
  654. }
  655. this.pattern = Pattern.compile(new String(rPat, 0, j), Pattern.CASE_INSENSITIVE);
  656. }
  657. public boolean accept(File f) {
  658. if (f == null) {
  659. return false;
  660. }
  661. if (f.isDirectory()) {
  662. return true;
  663. }
  664. return pattern.matcher(f.getName()).matches();
  665. }
  666. public String getDescription() {
  667. return globPattern;
  668. }
  669. }
  670. // *******************************************************
  671. // ************ FileChooser UI PLAF methods **************
  672. // *******************************************************
  673. /**
  674. * Returns the default accept all file filter
  675. */
  676. public FileFilter getAcceptAllFileFilter(JFileChooser fc) {
  677. return acceptAllFileFilter;
  678. }
  679. /**
  680. * Returns the title of this dialog
  681. */
  682. public String getDialogTitle(JFileChooser fc) {
  683. String dialogTitle = fc.getDialogTitle();
  684. if (dialogTitle != null) {
  685. return dialogTitle;
  686. } else if (fc.getDialogType() == JFileChooser.OPEN_DIALOG) {
  687. return openDialogTitleText;
  688. } else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
  689. return saveDialogTitleText;
  690. } else {
  691. return getApproveButtonText(fc);
  692. }
  693. }
  694. public int getApproveButtonMnemonic(JFileChooser fc) {
  695. int mnemonic = fc.getApproveButtonMnemonic();
  696. if (mnemonic > 0) {
  697. return mnemonic;
  698. } else if (fc.getDialogType() == JFileChooser.OPEN_DIALOG) {
  699. return openButtonMnemonic;
  700. } else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
  701. return saveButtonMnemonic;
  702. } else {
  703. return mnemonic;
  704. }
  705. }
  706. public String getApproveButtonText(JFileChooser fc) {
  707. String buttonText = fc.getApproveButtonText();
  708. if (buttonText != null) {
  709. return buttonText;
  710. } else if (fc.getDialogType() == JFileChooser.OPEN_DIALOG) {
  711. return openButtonText;
  712. } else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) {
  713. return saveButtonText;
  714. } else {
  715. return null;
  716. }
  717. }
  718. // *****************************
  719. // ***** Directory Actions *****
  720. // *****************************
  721. public Action getNewFolderAction() {
  722. return newFolderAction;
  723. }
  724. public Action getGoHomeAction() {
  725. return goHomeAction;
  726. }
  727. public Action getChangeToParentDirectoryAction() {
  728. return changeToParentDirectoryAction;
  729. }
  730. public Action getApproveSelectionAction() {
  731. return approveSelectionAction;
  732. }
  733. public Action getCancelSelectionAction() {
  734. return cancelSelectionAction;
  735. }
  736. /**
  737. * Acts on the "home" key event or equivalent event.
  738. */
  739. protected class GoHomeAction extends AbstractAction {
  740. protected GoHomeAction() {
  741. super("Go Home");
  742. }
  743. public void actionPerformed(ActionEvent e) {
  744. JFileChooser fc = getFileChooser();
  745. fc.setCurrentDirectory(fc.getFileSystemView().getHomeDirectory());
  746. }
  747. }
  748. public Action getFileNameCompletionAction() {
  749. return fileNameCompletionAction;
  750. }
  751. protected class ChangeToParentDirectoryAction extends AbstractAction {
  752. protected ChangeToParentDirectoryAction() {
  753. super("Go Up");
  754. }
  755. public void actionPerformed(ActionEvent e) {
  756. Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
  757. if (focusOwner == null || !(focusOwner instanceof javax.swing.text.JTextComponent)) {
  758. getFileChooser().changeToParentDirectory();
  759. }
  760. }
  761. }
  762. /**
  763. * Responds to a cancel request.
  764. */
  765. protected class CancelSelectionAction extends AbstractAction {
  766. public void actionPerformed(ActionEvent e) {
  767. getFileChooser().cancelSelection();
  768. }
  769. }
  770. // *****************************************
  771. // ***** default AcceptAll file filter *****
  772. // *****************************************
  773. protected class AcceptAllFileFilter extends FileFilter {
  774. public AcceptAllFileFilter() {
  775. }
  776. public boolean accept(File f) {
  777. return true;
  778. }
  779. public String getDescription() {
  780. return UIManager.getString("FileChooser.acceptAllFileFilterText",
  781. getFileChooser().getLocale());
  782. }
  783. }
  784. /**
  785. * Creates a new folder.
  786. */
  787. protected class NewFolderAction extends AbstractAction {
  788. protected NewFolderAction() {
  789. super("New Folder");
  790. }
  791. public void actionPerformed(ActionEvent e) {
  792. JFileChooser fc = getFileChooser();
  793. File currentDirectory = fc.getCurrentDirectory();
  794. File newFolder = null;
  795. try {
  796. newFolder = fc.getFileSystemView().createNewFolder(currentDirectory);
  797. if (fc.isMultiSelectionEnabled()) {
  798. fc.setSelectedFiles(new File[] { newFolder });
  799. } else {
  800. fc.setSelectedFile(newFolder);
  801. }
  802. } catch (IOException exc) {
  803. JOptionPane.showMessageDialog(
  804. fc,
  805. newFolderErrorText + newFolderErrorSeparator + exc,
  806. newFolderErrorText, JOptionPane.ERROR_MESSAGE);
  807. return;
  808. }
  809. fc.rescanCurrentDirectory();
  810. }
  811. }
  812. protected JButton getApproveButton(JFileChooser fc) {
  813. return approveButton;
  814. }
  815. protected JButton getCancelButton(JFileChooser fc) {
  816. return cancelButton;
  817. }
  818. // ***********************
  819. // * FileView operations *
  820. // ***********************
  821. protected class SynthFileView extends FileView {
  822. public String getName(File f) {
  823. // Note: Returns display name rather than file name
  824. String fileName = null;
  825. if(f != null) {
  826. fileName = getFileChooser().getFileSystemView().getSystemDisplayName(f);
  827. }
  828. return fileName;
  829. }
  830. public String getDescription(File f) {
  831. return f.getName();
  832. }
  833. public String getTypeDescription(File f) {
  834. String type = getFileChooser().getFileSystemView().getSystemTypeDescription(f);
  835. if (type == null) {
  836. if (f.isDirectory()) {
  837. type = directoryDescriptionText;
  838. } else {
  839. type = fileDescriptionText;
  840. }
  841. }
  842. return type;
  843. }
  844. public Icon getIcon(File f) {
  845. return null;
  846. }
  847. public Boolean isHidden(File f) {
  848. String name = f.getName();
  849. if(name != null && name.charAt(0) == '.') {
  850. return Boolean.TRUE;
  851. } else {
  852. return Boolean.FALSE;
  853. }
  854. }
  855. }
  856. }