PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre3/org/gjt/sp/jedit/browser/VFSBrowser.java

#
Java | 1345 lines | 1011 code | 170 blank | 164 comment | 238 complexity | 2b2f1867f6821289df8128720c2cd8ab MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * VFSBrowser.java - VFS browser
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2000, 2001 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package org.gjt.sp.jedit.browser;
  23. //{{{ Imports
  24. import gnu.regexp.*;
  25. import javax.swing.border.EmptyBorder;
  26. import javax.swing.event.*;
  27. import javax.swing.*;
  28. import java.awt.event.*;
  29. import java.awt.*;
  30. import java.io.File;
  31. import java.util.Enumeration;
  32. import java.util.Hashtable;
  33. import java.util.Vector;
  34. import org.gjt.sp.jedit.io.*;
  35. import org.gjt.sp.jedit.gui.*;
  36. import org.gjt.sp.jedit.msg.*;
  37. import org.gjt.sp.jedit.search.*;
  38. import org.gjt.sp.jedit.*;
  39. import org.gjt.sp.util.Log;
  40. //}}}
  41. /**
  42. * The main class of the VFS browser.
  43. * @author Slava Pestov
  44. * @version $Id: VFSBrowser.java 3931 2001-12-02 11:40:51Z spestov $
  45. */
  46. public class VFSBrowser extends JPanel implements EBComponent
  47. {
  48. public static final String NAME = "vfs.browser";
  49. //{{{ Browser types
  50. /**
  51. * Open file dialog mode. Equals JFileChooser.OPEN_DIALOG for
  52. * backwards compatibility.
  53. */
  54. public static final int OPEN_DIALOG = 0;
  55. /**
  56. * Save file dialog mode. Equals JFileChooser.SAVE_DIALOG for
  57. * backwards compatibility.
  58. */
  59. public static final int SAVE_DIALOG = 1;
  60. /**
  61. * Stand-alone browser mode.
  62. */
  63. public static final int BROWSER = 2;
  64. //}}}
  65. //{{{ browseDirectory() method
  66. /**
  67. * Opens the specified directory in a file system browser.
  68. * @param view The view
  69. * @param path The directory's path
  70. * @since jEdit 4.0pre3
  71. */
  72. public static void browseDirectory(View view, String path)
  73. {
  74. DockableWindowManager wm = view.getDockableWindowManager();
  75. VFSBrowser browser = (VFSBrowser)wm.getDockable(NAME);
  76. if(browser != null)
  77. {
  78. wm.showDockableWindow(NAME);
  79. browser.setDirectory(path);
  80. }
  81. else
  82. {
  83. if(path != null)
  84. {
  85. // this is such a bad way of doing it, but oh well...
  86. jEdit.setTemporaryProperty("vfs.browser.path.tmp",path);
  87. }
  88. wm.addDockableWindow("vfs.browser");
  89. jEdit.unsetProperty("vfs.browser.path.tmp");
  90. }
  91. } //}}}
  92. //{{{ VFSBrowser constructor
  93. /**
  94. * Creates a new VFS browser.
  95. * @param view The view to open buffers in by default
  96. * @param path The path to display
  97. * @param mode The browser mode
  98. * @param multipleSelection True if multiple selection should be allowed
  99. * @param floating True if this browser instance is floating
  100. */
  101. public VFSBrowser(View view, String path, int mode, boolean multipleSelection,
  102. boolean floating)
  103. {
  104. super(new BorderLayout());
  105. listenerList = new EventListenerList();
  106. this.mode = mode;
  107. this.multipleSelection = multipleSelection;
  108. this.floating = floating;
  109. this.view = view;
  110. ActionHandler actionHandler = new ActionHandler();
  111. Box topBox = new Box(BoxLayout.Y_AXIS);
  112. // this is tricky, because in BROWSER mode, the menu bar
  113. // and tool bar are stacked on top of each other, and
  114. // the user can toggle the tool bar. In dialog modes,
  115. // the two are side by side and the tool bar is always
  116. // visible.
  117. toolbarBox = new Box(mode == BROWSER
  118. ? BoxLayout.Y_AXIS
  119. : BoxLayout.X_AXIS);
  120. JToolBar menuBar = createMenuBar();
  121. if(mode == BROWSER)
  122. menuBar.add(Box.createGlue());
  123. toolbarBox.add(menuBar);
  124. if(mode != BROWSER)
  125. {
  126. toolbarBox.add(Box.createHorizontalStrut(6));
  127. toolbarBox.add(createToolBar());
  128. toolbarBox.add(Box.createGlue());
  129. }
  130. topBox.add(toolbarBox);
  131. GridBagLayout layout = new GridBagLayout();
  132. JPanel pathAndFilterPanel = new JPanel(layout);
  133. GridBagConstraints cons = new GridBagConstraints();
  134. cons.gridwidth = cons.gridheight = 1;
  135. cons.gridx = cons.gridy = 0;
  136. cons.fill = GridBagConstraints.BOTH;
  137. cons.anchor = GridBagConstraints.EAST;
  138. JLabel label = new JLabel(jEdit.getProperty("vfs.browser.path"),
  139. SwingConstants.RIGHT);
  140. label.setBorder(new EmptyBorder(0,0,0,12));
  141. layout.setConstraints(label,cons);
  142. pathAndFilterPanel.add(label);
  143. pathField = new HistoryTextField("vfs.browser.path");
  144. pathField.setInstantPopups(true);
  145. pathField.setEnterAddsToHistory(false);
  146. pathField.setSelectAllOnFocus(true);
  147. if(floating)
  148. {
  149. label.setDisplayedMnemonic(jEdit.getProperty(
  150. "vfs.browser.path.mnemonic").charAt(0));
  151. label.setLabelFor(pathField);
  152. }
  153. // because its preferred size can be quite wide, we
  154. // don't want it to make the browser way too big,
  155. // so set the preferred width to 0.
  156. Dimension prefSize = pathField.getPreferredSize();
  157. prefSize.width = 0;
  158. pathField.setPreferredSize(prefSize);
  159. pathField.addActionListener(actionHandler);
  160. pathField.addFocusListener(new FocusHandler());
  161. cons.gridx = 1;
  162. cons.weightx = 1.0f;
  163. layout.setConstraints(pathField,cons);
  164. pathAndFilterPanel.add(pathField);
  165. filterCheckbox = new JCheckBox(jEdit.getProperty("vfs.browser.filter"));
  166. filterCheckbox.setMargin(new Insets(0,0,0,0));
  167. filterCheckbox.setRequestFocusEnabled(false);
  168. filterCheckbox.setBorder(new EmptyBorder(0,0,0,12));
  169. filterCheckbox.setSelected(mode != BROWSER ||
  170. jEdit.getBooleanProperty("vfs.browser.filter-enabled"));
  171. filterCheckbox.addActionListener(actionHandler);
  172. cons.gridx = 0;
  173. cons.weightx = 0.0f;
  174. cons.gridy = 1;
  175. layout.setConstraints(filterCheckbox,cons);
  176. pathAndFilterPanel.add(filterCheckbox);
  177. filterField = new HistoryTextField("vfs.browser.filter");
  178. filterField.setInstantPopups(true);
  179. filterField.setSelectAllOnFocus(true);
  180. filterField.addActionListener(actionHandler);
  181. cons.gridx = 1;
  182. cons.weightx = 1.0f;
  183. layout.setConstraints(filterField,cons);
  184. pathAndFilterPanel.add(filterField);
  185. topBox.add(pathAndFilterPanel);
  186. add(BorderLayout.NORTH,topBox);
  187. add(BorderLayout.CENTER,browserView = new BrowserView(this));
  188. propertiesChanged();
  189. HistoryModel filterModel = HistoryModel.getModel("vfs.browser.filter");
  190. String filter;
  191. if(mode == BROWSER || view == null || !jEdit.getBooleanProperty(
  192. "vfs.browser.currentBufferFilter"))
  193. {
  194. filter = jEdit.getProperty("vfs.browser.last-filter");
  195. if(filter == null)
  196. filter = jEdit.getProperty("vfs.browser.default-filter");
  197. }
  198. else
  199. {
  200. String name = view.getBuffer().getName();
  201. int index = name.lastIndexOf('.');
  202. if(index == -1)
  203. filter = jEdit.getProperty("vfs.browser.default-filter");
  204. else
  205. {
  206. String ext = name.substring(index);
  207. filter = "*" + ext;
  208. }
  209. }
  210. filterField.setText(filter);
  211. filterField.addCurrentToHistory();
  212. updateFilterEnabled();
  213. // see VFSBrowser.browseDirectory()
  214. if(path == null)
  215. path = jEdit.getProperty("vfs.browser.path.tmp");
  216. if(path == null || path.length() == 0)
  217. {
  218. String userHome = System.getProperty("user.home");
  219. String defaultPath = jEdit.getProperty("vfs.browser.defaultPath");
  220. if(defaultPath.equals("home"))
  221. path = userHome;
  222. else if(defaultPath.equals("buffer"))
  223. {
  224. if(view != null)
  225. {
  226. Buffer buffer = view.getBuffer();
  227. path = buffer.getVFS().getParentOfPath(
  228. buffer.getPath());
  229. }
  230. else
  231. path = userHome;
  232. }
  233. else if(defaultPath.equals("last"))
  234. {
  235. HistoryModel pathModel = HistoryModel.getModel("vfs.browser.path");
  236. if(pathModel.getSize() == 0)
  237. path = "~";
  238. else
  239. path = pathModel.getItem(0);
  240. }
  241. else if(defaultPath.equals("favorites"))
  242. path = "favorites:";
  243. else
  244. {
  245. // unknown value??!!!
  246. path = userHome;
  247. }
  248. }
  249. setDirectory(path);
  250. } //}}}
  251. //{{{ requestDefaultFocus() method
  252. public boolean requestDefaultFocus()
  253. {
  254. return browserView.requestDefaultFocus();
  255. } //}}}
  256. //{{{ addNotify() method
  257. public void addNotify()
  258. {
  259. super.addNotify();
  260. EditBus.addToBus(this);
  261. } //}}}
  262. //{{{ removeNotify() method
  263. public void removeNotify()
  264. {
  265. super.removeNotify();
  266. jEdit.setBooleanProperty("vfs.browser.filter-enabled",
  267. filterCheckbox.isSelected());
  268. if(mode == BROWSER || !jEdit.getBooleanProperty(
  269. "vfs.browser.currentBufferFilter"))
  270. {
  271. jEdit.setProperty("vfs.browser.last-filter",
  272. filterField.getText());
  273. }
  274. EditBus.removeFromBus(this);
  275. } //}}}
  276. //{{{ handleMessage() method
  277. public void handleMessage(EBMessage msg)
  278. {
  279. if(msg instanceof ViewUpdate)
  280. handleViewUpdate((ViewUpdate)msg);
  281. else if(msg instanceof BufferUpdate)
  282. handleBufferUpdate((BufferUpdate)msg);
  283. else if(msg instanceof PropertiesChanged)
  284. propertiesChanged();
  285. else if(msg instanceof VFSUpdate)
  286. {
  287. // this is a dirty hack and it relies on the fact
  288. // that updates for parents are sent before updates
  289. // for the changed nodes themselves (if this was not
  290. // the case, the browser wouldn't be updated properly
  291. // on delete, etc).
  292. //
  293. // to avoid causing '> 1 request' errors, don't reload
  294. // directory if request already active
  295. if(requestRunning)
  296. return;
  297. browserView.maybeReloadDirectory(((VFSUpdate)msg).getPath());
  298. }
  299. } //}}}
  300. //{{{ getView() method
  301. public View getView()
  302. {
  303. return view;
  304. } //}}}
  305. //{{{ getMode() method
  306. public int getMode()
  307. {
  308. return mode;
  309. } //}}}
  310. //{{{ isMultipleSelectionEnabled() method
  311. public boolean isMultipleSelectionEnabled()
  312. {
  313. return multipleSelection;
  314. } //}}}
  315. //{{{ getShowHiddenFiles() method
  316. public boolean getShowHiddenFiles()
  317. {
  318. return showHiddenFiles;
  319. } //}}}
  320. //{{{ setShowHiddenFiles() method
  321. public void setShowHiddenFiles(boolean showHiddenFiles)
  322. {
  323. this.showHiddenFiles = showHiddenFiles;
  324. } //}}}
  325. //{{{ getFilenameFilter() method
  326. /**
  327. * Returns the file name filter glob.
  328. * @since jEdit 3.2pre2
  329. */
  330. public String getFilenameFilter()
  331. {
  332. if(filterCheckbox.isSelected())
  333. {
  334. String filter = filterField.getText();
  335. if(filter.length() == 0)
  336. return "*";
  337. else
  338. return filter;
  339. }
  340. else
  341. return "*";
  342. } //}}}
  343. //{{{ setFilenameFilter() method
  344. public void setFilenameFilter(String filter)
  345. {
  346. if(filter == null || filter.length() == 0 || filter.equals("*"))
  347. filterCheckbox.setSelected(false);
  348. else
  349. {
  350. filterCheckbox.setSelected(true);
  351. filterField.setText(filter);
  352. }
  353. } //}}}
  354. //{{{ getDirectory() method
  355. public String getDirectory()
  356. {
  357. return path;
  358. } //}}}
  359. //{{{ setDirectory() method
  360. public void setDirectory(String path)
  361. {
  362. // have to do this hack until VFSPath class is written
  363. if(path.length() != 1 && (path.endsWith("/")
  364. || path.endsWith(java.io.File.separator)))
  365. path = path.substring(0,path.length() - 1);
  366. if(path.startsWith("file:"))
  367. path = path.substring(5);
  368. pathField.setText(path);
  369. browserView.loadDirectory(path);
  370. } //}}}
  371. //{{{ reloadDirectory() method
  372. public void reloadDirectory()
  373. {
  374. // used by FTP plugin to clear directory cache
  375. VFSManager.getVFSForPath(path).reloadDirectory(path);
  376. browserView.loadDirectory(path);
  377. } //}}}
  378. //{{{ delete() method
  379. public void delete(String path)
  380. {
  381. if(MiscUtilities.isURL(path) && FavoritesVFS.PROTOCOL.equals(
  382. MiscUtilities.getProtocolOfURL(path)))
  383. {
  384. Object[] args = { path.substring(FavoritesVFS.PROTOCOL.length() + 1) };
  385. int result = GUIUtilities.confirm(this,
  386. "vfs.browser.delete-favorites",args,
  387. JOptionPane.YES_NO_OPTION,
  388. JOptionPane.WARNING_MESSAGE);
  389. if(result != JOptionPane.YES_OPTION)
  390. return;
  391. }
  392. else
  393. {
  394. Object[] args = { path };
  395. int result = GUIUtilities.confirm(this,
  396. "vfs.browser.delete-confirm",args,
  397. JOptionPane.YES_NO_OPTION,
  398. JOptionPane.WARNING_MESSAGE);
  399. if(result != JOptionPane.YES_OPTION)
  400. return;
  401. }
  402. VFS vfs = VFSManager.getVFSForPath(path);
  403. Object session = vfs.createVFSSession(path,this);
  404. if(session == null)
  405. return;
  406. if(!startRequest())
  407. return;
  408. VFSManager.runInWorkThread(new BrowserIORequest(
  409. BrowserIORequest.DELETE,this,
  410. session,vfs,path,null));
  411. } //}}}
  412. //{{{ rename() method
  413. public void rename(String from)
  414. {
  415. VFS vfs = VFSManager.getVFSForPath(from);
  416. String filename = vfs.getFileName(from);
  417. String[] args = { filename };
  418. String to = GUIUtilities.input(this,"vfs.browser.rename",
  419. args,filename);
  420. if(to == null)
  421. return;
  422. to = vfs.constructPath(vfs.getParentOfPath(from),to);
  423. Object session = vfs.createVFSSession(from,this);
  424. if(session == null)
  425. return;
  426. if(!startRequest())
  427. return;
  428. VFSManager.runInWorkThread(new BrowserIORequest(
  429. BrowserIORequest.RENAME,this,
  430. session,vfs,from,to));
  431. } //}}}
  432. //{{{ mkdir() method
  433. public void mkdir()
  434. {
  435. String newDirectory = GUIUtilities.input(this,"vfs.browser.mkdir",null);
  436. if(newDirectory == null)
  437. return;
  438. // if a directory is selected, create new dir in there.
  439. // if a file is selected, create new dir inside its parent.
  440. VFS.DirectoryEntry[] selected = getSelectedFiles();
  441. String parent;
  442. if(selected.length == 0)
  443. parent = path;
  444. else if(selected[0].type == VFS.DirectoryEntry.FILE)
  445. {
  446. parent = selected[0].path;
  447. parent = VFSManager.getVFSForPath(parent)
  448. .getParentOfPath(parent);
  449. }
  450. else
  451. parent = selected[0].path;
  452. VFS vfs = VFSManager.getVFSForPath(parent);
  453. // path is the currently viewed directory in the browser
  454. newDirectory = vfs.constructPath(parent,newDirectory);
  455. Object session = vfs.createVFSSession(newDirectory,this);
  456. if(session == null)
  457. return;
  458. if(!startRequest())
  459. return;
  460. VFSManager.runInWorkThread(new BrowserIORequest(
  461. BrowserIORequest.MKDIR,this,
  462. session,vfs,newDirectory,null));
  463. } //}}}
  464. //{{{ newFile() method
  465. /**
  466. * Creates a new file in the current directory.
  467. * @since jEdit 4.0pre2
  468. */
  469. public void newFile()
  470. {
  471. VFS.DirectoryEntry[] selected = getSelectedFiles();
  472. if(selected.length >= 1)
  473. {
  474. VFS.DirectoryEntry file = selected[0];
  475. if(file.type == VFS.DirectoryEntry.DIRECTORY)
  476. jEdit.newFile(view,file.path);
  477. else
  478. {
  479. VFS vfs = VFSManager.getVFSForPath(file.path);
  480. jEdit.newFile(view,vfs.getParentOfPath(file.path));
  481. }
  482. }
  483. else
  484. jEdit.newFile(view,path);
  485. } //}}}
  486. //{{{ searchInDirectory() method
  487. /**
  488. * Opens a directory search in the current directory.
  489. * @since jEdit 4.0pre2
  490. */
  491. public void searchInDirectory()
  492. {
  493. String path, filter;
  494. VFS.DirectoryEntry[] selected = getSelectedFiles();
  495. if(selected.length >= 1)
  496. {
  497. VFS.DirectoryEntry file = selected[0];
  498. if(file.type == VFS.DirectoryEntry.DIRECTORY)
  499. {
  500. path = file.path;
  501. filter = getFilenameFilter();
  502. }
  503. else
  504. {
  505. VFS vfs = VFSManager.getVFSForPath(file.path);
  506. path = vfs.getParentOfPath(file.path);
  507. String name = MiscUtilities.getFileName(path);
  508. String ext = MiscUtilities.getFileExtension(name);
  509. filter = (ext == null || ext.length() == 0
  510. ? getFilenameFilter()
  511. : "*." + ext);
  512. }
  513. }
  514. else
  515. {
  516. path = this.path;
  517. filter = getFilenameFilter();
  518. }
  519. if(!(VFSManager.getVFSForPath(path) instanceof FileVFS))
  520. {
  521. getToolkit().beep();
  522. return;
  523. }
  524. SearchAndReplace.setSearchFileSet(new DirectoryListSet(
  525. path,filter,true));
  526. new SearchDialog(view,null,SearchDialog.DIRECTORY);
  527. } //}}}
  528. //{{{ getBrowserView() method
  529. public BrowserView getBrowserView()
  530. {
  531. return browserView;
  532. } //}}}
  533. //{{{ getSelectedFiles() method
  534. public VFS.DirectoryEntry[] getSelectedFiles()
  535. {
  536. return browserView.getSelectedFiles();
  537. } //}}}
  538. //{{{ addBrowserListener() method
  539. public void addBrowserListener(BrowserListener l)
  540. {
  541. listenerList.add(BrowserListener.class,l);
  542. } //}}}
  543. //{{{ removeBrowserListener() method
  544. public void removeBrowserListener(BrowserListener l)
  545. {
  546. listenerList.remove(BrowserListener.class,l);
  547. } //}}}
  548. //{{{ Package-private members
  549. //{{{ loadDirectory() method
  550. void loadDirectory(String path, boolean root)
  551. {
  552. loadingRoot = root;
  553. try
  554. {
  555. String filter = filterField.getText();
  556. if(filter.length() == 0)
  557. filter = "*";
  558. filenameFilter = new RE(MiscUtilities.globToRE(filter),RE.REG_ICASE);
  559. }
  560. catch(Exception e)
  561. {
  562. Log.log(Log.ERROR,VFSBrowser.this,e);
  563. String[] args = { filterField.getText(),
  564. e.getMessage() };
  565. GUIUtilities.error(this,"vfs.browser.bad-filter",args);
  566. }
  567. path = MiscUtilities.constructPath(this.path,path);
  568. VFS vfs = VFSManager.getVFSForPath(path);
  569. Object session = vfs.createVFSSession(path,this);
  570. if(session == null)
  571. return;
  572. if(!startRequest())
  573. return;
  574. VFSManager.runInWorkThread(new BrowserIORequest(
  575. BrowserIORequest.LIST_DIRECTORY,this,
  576. session,vfs,path,null));
  577. } //}}}
  578. //{{{ directoryLoaded() method
  579. void directoryLoaded(final String path, final VFS.DirectoryEntry[] list)
  580. {
  581. SwingUtilities.invokeLater(new Runnable()
  582. {
  583. public void run()
  584. {
  585. if(loadingRoot)
  586. {
  587. // This is the new, canonical path
  588. VFSBrowser.this.path = path;
  589. if(!pathField.getText().equals(path))
  590. pathField.setText(path);
  591. pathField.addCurrentToHistory();
  592. }
  593. boolean filterEnabled = filterCheckbox.isSelected();
  594. Vector directoryVector = new Vector();
  595. int directories = 0;
  596. int files = 0;
  597. int invisible = 0;
  598. if(list != null)
  599. {
  600. for(int i = 0; i < list.length; i++)
  601. {
  602. VFS.DirectoryEntry file = list[i];
  603. if(file.hidden && !showHiddenFiles)
  604. {
  605. invisible++;
  606. continue;
  607. }
  608. if(file.type == VFS.DirectoryEntry.FILE
  609. && filterEnabled
  610. && filenameFilter != null
  611. && !filenameFilter.isMatch(file.name))
  612. {
  613. invisible++;
  614. continue;
  615. }
  616. if(file.type == VFS.DirectoryEntry.FILE)
  617. files++;
  618. else
  619. directories++;
  620. directoryVector.addElement(file);
  621. }
  622. if(sortFiles)
  623. {
  624. MiscUtilities.quicksort(directoryVector,
  625. new FileCompare());
  626. }
  627. }
  628. browserView.directoryLoaded(path,directoryVector);
  629. }
  630. });
  631. } //}}}
  632. //{{{ FileCompare class
  633. class FileCompare implements MiscUtilities.Compare
  634. {
  635. public int compare(Object obj1, Object obj2)
  636. {
  637. VFS.DirectoryEntry file1 = (VFS.DirectoryEntry)obj1;
  638. VFS.DirectoryEntry file2 = (VFS.DirectoryEntry)obj2;
  639. if(!sortMixFilesAndDirs)
  640. {
  641. if(file1.type != file2.type)
  642. return file2.type - file1.type;
  643. }
  644. return MiscUtilities.compareStrings(file1.name,
  645. file2.name,sortIgnoreCase);
  646. }
  647. } //}}}
  648. //{{{ filesSelected() method
  649. void filesSelected()
  650. {
  651. VFS.DirectoryEntry[] selectedFiles = browserView.getSelectedFiles();
  652. if(mode == BROWSER)
  653. {
  654. for(int i = 0; i < selectedFiles.length; i++)
  655. {
  656. VFS.DirectoryEntry file = selectedFiles[i];
  657. Buffer buffer = jEdit.getBuffer(file.path);
  658. if(buffer != null && view != null)
  659. view.setBuffer(buffer);
  660. }
  661. }
  662. Object[] listeners = listenerList.getListenerList();
  663. for(int i = 0; i < listeners.length; i++)
  664. {
  665. if(listeners[i] == BrowserListener.class)
  666. {
  667. BrowserListener l = (BrowserListener)listeners[i+1];
  668. l.filesSelected(this,selectedFiles);
  669. }
  670. }
  671. } //}}}
  672. //{{{ filesActivated() method
  673. void filesActivated()
  674. {
  675. VFS.DirectoryEntry[] selectedFiles = browserView.getSelectedFiles();
  676. for(int i = 0; i < selectedFiles.length; i++)
  677. {
  678. VFS.DirectoryEntry file = selectedFiles[i];
  679. if(file.type == VFS.DirectoryEntry.DIRECTORY
  680. || file.type == VFS.DirectoryEntry.FILESYSTEM)
  681. setDirectory(file.path);
  682. else if(mode == BROWSER)
  683. {
  684. Buffer buffer = jEdit.getBuffer(file.path);
  685. if(buffer == null)
  686. buffer = jEdit.openFile(null,file.path);
  687. else if(doubleClickClose)
  688. {
  689. jEdit.closeBuffer(view,buffer);
  690. break;
  691. }
  692. if(buffer != null)
  693. {
  694. if(view == null)
  695. view = jEdit.newView(null,buffer);
  696. else
  697. view.setBuffer(buffer);
  698. }
  699. }
  700. else
  701. {
  702. // if a file is selected in OPEN_DIALOG or
  703. // SAVE_DIALOG mode, just let the listener(s)
  704. // handle it
  705. }
  706. }
  707. Object[] listeners = listenerList.getListenerList();
  708. for(int i = 0; i < listeners.length; i++)
  709. {
  710. if(listeners[i] == BrowserListener.class)
  711. {
  712. BrowserListener l = (BrowserListener)listeners[i+1];
  713. l.filesActivated(this,selectedFiles);
  714. }
  715. }
  716. } //}}}
  717. //{{{ endRequest() method
  718. void endRequest()
  719. {
  720. requestRunning = false;
  721. } //}}}
  722. //}}}
  723. //{{{ Private members
  724. //{{{ Instance variables
  725. private EventListenerList listenerList;
  726. private View view;
  727. private boolean floating;
  728. private String path;
  729. private HistoryTextField pathField;
  730. private JCheckBox filterCheckbox;
  731. private HistoryTextField filterField;
  732. private Box toolbarBox;
  733. private JToolBar toolbar;
  734. private JButton up, reload, roots, home, synchronize,
  735. newFile, newDirectory, searchInDirectory;
  736. private BrowserView browserView;
  737. private RE filenameFilter;
  738. private int mode;
  739. private boolean multipleSelection;
  740. private boolean showHiddenFiles;
  741. private boolean sortFiles;
  742. private boolean sortMixFilesAndDirs;
  743. private boolean sortIgnoreCase;
  744. private boolean doubleClickClose;
  745. private boolean requestRunning;
  746. private boolean loadingRoot;
  747. //}}}
  748. //{{{ createMenuBar() method
  749. private JToolBar createMenuBar()
  750. {
  751. JToolBar toolBar = new JToolBar();
  752. toolBar.setFloatable(false);
  753. toolBar.putClientProperty("JToolBar.isRollover",Boolean.TRUE);
  754. toolBar.add(new CommandsMenuButton());
  755. toolBar.add(Box.createHorizontalStrut(3));
  756. toolBar.add(new PluginsMenuButton());
  757. toolBar.add(Box.createHorizontalStrut(3));
  758. toolBar.add(new FavoritesMenuButton());
  759. return toolBar;
  760. } //}}}
  761. //{{{ createToolBar() method
  762. private JToolBar createToolBar()
  763. {
  764. JToolBar toolBar = new JToolBar();
  765. toolBar.setFloatable(false);
  766. toolBar.putClientProperty("JToolBar.isRollover",Boolean.TRUE);
  767. toolBar.add(up = createToolButton("up"));
  768. toolBar.add(reload = createToolButton("reload"));
  769. toolBar.add(roots = createToolButton("roots"));
  770. toolBar.add(home = createToolButton("home"));
  771. toolBar.add(synchronize = createToolButton("synchronize"));
  772. if(mode == BROWSER)
  773. toolBar.add(newFile = createToolButton("new-file"));
  774. toolBar.add(newDirectory = createToolButton("new-directory"));
  775. if(mode == BROWSER)
  776. toolBar.add(searchInDirectory = createToolButton("search-in-directory"));
  777. return toolBar;
  778. } //}}}
  779. //{{{ createToolButton() method
  780. private JButton createToolButton(String name)
  781. {
  782. JButton button = new JButton();
  783. String prefix = "vfs.browser.commands.";
  784. String iconName = jEdit.getProperty(
  785. prefix + name + ".icon");
  786. if(iconName != null)
  787. {
  788. Icon icon = GUIUtilities.loadIcon(iconName);
  789. if(icon != null)
  790. button.setIcon(icon);
  791. else
  792. {
  793. Log.log(Log.ERROR,this,"Missing icon: "
  794. + iconName);
  795. }
  796. }
  797. else
  798. Log.log(Log.ERROR,this,"Missing icon name: " + name);
  799. button.setToolTipText(jEdit.getProperty(prefix + name + ".label"));
  800. button.setRequestFocusEnabled(false);
  801. button.setMargin(new Insets(0,0,0,0));
  802. button.addActionListener(new ActionHandler());
  803. return button;
  804. } //}}}
  805. //{{{ handleViewUpdate() method
  806. private void handleViewUpdate(ViewUpdate vmsg)
  807. {
  808. if(vmsg.getWhat() == ViewUpdate.CLOSED
  809. && vmsg.getView() == view)
  810. view = null;
  811. } //}}}
  812. //{{{ handleBufferUpdate() method
  813. private void handleBufferUpdate(BufferUpdate bmsg)
  814. {
  815. if(bmsg.getWhat() == BufferUpdate.CREATED
  816. || bmsg.getWhat() == BufferUpdate.CLOSED)
  817. browserView.updateFileView();
  818. else if(bmsg.getWhat() == BufferUpdate.DIRTY_CHANGED)
  819. {
  820. // if a buffer becomes clean, it means it was
  821. // saved. So we repaint the browser view, in
  822. // case it was a 'save as'
  823. if(!bmsg.getBuffer().isDirty())
  824. browserView.updateFileView();
  825. }
  826. } //}}}
  827. //{{{ propertiesChanged() method
  828. private void propertiesChanged()
  829. {
  830. showHiddenFiles = jEdit.getBooleanProperty("vfs.browser.showHiddenFiles");
  831. sortFiles = jEdit.getBooleanProperty("vfs.browser.sortFiles");
  832. sortMixFilesAndDirs = jEdit.getBooleanProperty("vfs.browser.sortMixFilesAndDirs");
  833. sortIgnoreCase = jEdit.getBooleanProperty("vfs.browser.sortIgnoreCase");
  834. doubleClickClose = jEdit.getBooleanProperty("vfs.browser.doubleClickClose");
  835. browserView.propertiesChanged();
  836. if(mode == BROWSER)
  837. {
  838. boolean showToolbar = jEdit.getBooleanProperty("vfs.browser.showToolbar");
  839. if(showToolbar && toolbar == null)
  840. {
  841. toolbar = createToolBar();
  842. toolbar.add(Box.createGlue());
  843. toolbarBox.add(toolbar);
  844. revalidate();
  845. }
  846. else if(!showToolbar && toolbar != null)
  847. {
  848. toolbarBox.remove(toolbar);
  849. toolbar = null;
  850. revalidate();
  851. }
  852. }
  853. if(path != null)
  854. reloadDirectory();
  855. } //}}}
  856. /* We do this stuff because the browser is not able to handle
  857. * more than one request yet */
  858. //{{{ startRequest() method
  859. private boolean startRequest()
  860. {
  861. if(requestRunning)
  862. {
  863. // dump stack trace for debugging purposes
  864. Log.log(Log.DEBUG,this,new Throwable("For debugging purposes"));
  865. GUIUtilities.error(this,"browser-multiple-io",null);
  866. return false;
  867. }
  868. else
  869. {
  870. requestRunning = true;
  871. return true;
  872. }
  873. } //}}}
  874. //{{{ updateFilterEnabled() method
  875. private void updateFilterEnabled()
  876. {
  877. filterField.setEnabled(filterCheckbox.isSelected());
  878. } //}}}
  879. //}}}
  880. //{{{ Inner classes
  881. //{{{ ActionHandler class
  882. class ActionHandler implements ActionListener
  883. {
  884. public void actionPerformed(ActionEvent evt)
  885. {
  886. Object source = evt.getSource();
  887. if(source == pathField || source == filterField
  888. || source == filterCheckbox)
  889. {
  890. updateFilterEnabled();
  891. String path = pathField.getText();
  892. if(path != null)
  893. setDirectory(path);
  894. browserView.requestDefaultFocus();
  895. }
  896. else if(source == up)
  897. {
  898. VFS vfs = VFSManager.getVFSForPath(path);
  899. setDirectory(vfs.getParentOfPath(path));
  900. }
  901. else if(source == reload)
  902. reloadDirectory();
  903. else if(source == roots)
  904. setDirectory(FileRootsVFS.PROTOCOL + ":");
  905. else if(source == home)
  906. setDirectory(System.getProperty("user.home"));
  907. else if(source == synchronize)
  908. {
  909. Buffer buffer = view.getBuffer();
  910. setDirectory(buffer.getVFS().getParentOfPath(
  911. buffer.getPath()));
  912. }
  913. else if(source == newFile)
  914. newFile();
  915. else if(source == newDirectory)
  916. mkdir();
  917. else if(source == searchInDirectory)
  918. searchInDirectory();
  919. }
  920. } //}}}
  921. //{{{ FocusHandler class
  922. class FocusHandler extends FocusAdapter
  923. {
  924. public void focusLost(FocusEvent evt)
  925. {
  926. if(!requestRunning && !pathField.getText().equals(path))
  927. pathField.setText(path);
  928. }
  929. } //}}}
  930. //{{{ CommandsMenuButton class
  931. class CommandsMenuButton extends JButton
  932. {
  933. //{{{ CommandsMenuButton constructor
  934. CommandsMenuButton()
  935. {
  936. setText(jEdit.getProperty("vfs.browser.commands.label"));
  937. setIcon(GUIUtilities.loadIcon("ToolbarMenu.gif"));
  938. setHorizontalTextPosition(SwingConstants.LEADING);
  939. popup = new BrowserCommandsMenu(VFSBrowser.this,null);
  940. CommandsMenuButton.this.setRequestFocusEnabled(false);
  941. setMargin(new Insets(0,0,0,0));
  942. CommandsMenuButton.this.addMouseListener(new MouseHandler());
  943. } //}}}
  944. JPopupMenu popup;
  945. //{{{ MouseHandler class
  946. class MouseHandler extends MouseAdapter
  947. {
  948. public void mousePressed(MouseEvent evt)
  949. {
  950. if(!popup.isVisible())
  951. {
  952. GUIUtilities.showPopupMenu(
  953. popup,CommandsMenuButton.this,0,
  954. CommandsMenuButton.this.getHeight());
  955. }
  956. else
  957. {
  958. popup.setVisible(false);
  959. }
  960. }
  961. } //}}}
  962. } //}}}
  963. //{{{ PluginsMenuButton class
  964. class PluginsMenuButton extends JButton
  965. {
  966. //{{{ PluginsMenuButton constructor
  967. PluginsMenuButton()
  968. {
  969. setText(jEdit.getProperty("vfs.browser.plugins.label"));
  970. setIcon(GUIUtilities.loadIcon("ToolbarMenu.gif"));
  971. setHorizontalTextPosition(SwingConstants.LEADING);
  972. PluginsMenuButton.this.setRequestFocusEnabled(false);
  973. setMargin(new Insets(0,0,0,0));
  974. PluginsMenuButton.this.addMouseListener(new MouseHandler());
  975. popup = new JPopupMenu();
  976. ActionHandler actionHandler = new ActionHandler();
  977. JMenuItem mi = new JMenuItem(jEdit.getProperty(
  978. "vfs.browser.plugins.plugin-manager.label"));
  979. mi.setActionCommand("plugin-manager");
  980. mi.addActionListener(actionHandler);
  981. popup.add(mi);
  982. popup.addSeparator();
  983. // put them in a vector for sorting
  984. Vector vec = new Vector();
  985. Enumeration enum = VFSManager.getFilesystems();
  986. while(enum.hasMoreElements())
  987. {
  988. VFS vfs = (VFS)enum.nextElement();
  989. if((vfs.getCapabilities() & VFS.BROWSE_CAP) == 0)
  990. continue;
  991. JMenuItem menuItem = new JMenuItem(jEdit.getProperty(
  992. "vfs." + vfs.getName() + ".label"));
  993. menuItem.setActionCommand(vfs.getName());
  994. menuItem.addActionListener(actionHandler);
  995. vec.addElement(menuItem);
  996. }
  997. if(vec.size() != 0)
  998. {
  999. MiscUtilities.quicksort(vec,new MiscUtilities.MenuItemCompare());
  1000. for(int i = 0; i < vec.size(); i++)
  1001. popup.add((JMenuItem)vec.elementAt(i));
  1002. }
  1003. else
  1004. {
  1005. mi = new JMenuItem(jEdit.getProperty(
  1006. "vfs.browser.plugins.no-plugins.label"));
  1007. mi.setEnabled(false);
  1008. popup.add(mi);
  1009. }
  1010. } //}}}
  1011. JPopupMenu popup;
  1012. //{{{ ActionHandler class
  1013. class ActionHandler implements ActionListener
  1014. {
  1015. public void actionPerformed(ActionEvent evt)
  1016. {
  1017. if(evt.getActionCommand().equals("plugin-manager"))
  1018. {
  1019. new org.gjt.sp.jedit.pluginmgr.PluginManager(
  1020. JOptionPane.getFrameForComponent(
  1021. VFSBrowser.this));
  1022. }
  1023. else
  1024. {
  1025. VFS vfs = VFSManager.getVFSByName(evt.getActionCommand());
  1026. String directory = vfs.showBrowseDialog(null,
  1027. VFSBrowser.this);
  1028. if(directory != null)
  1029. setDirectory(directory);
  1030. }
  1031. }
  1032. } //}}}
  1033. //{{{ MouseHandler class
  1034. class MouseHandler extends MouseAdapter
  1035. {
  1036. public void mousePressed(MouseEvent evt)
  1037. {
  1038. if(!popup.isVisible())
  1039. {
  1040. GUIUtilities.showPopupMenu(
  1041. popup,PluginsMenuButton.this,0,
  1042. PluginsMenuButton.this.getHeight());
  1043. }
  1044. else
  1045. {
  1046. popup.setVisible(false);
  1047. }
  1048. }
  1049. } //}}}
  1050. } //}}}
  1051. //{{{ FavoritesMenuButton class
  1052. class FavoritesMenuButton extends JButton
  1053. {
  1054. //{{{ FavoritesMenuButton constructor
  1055. FavoritesMenuButton()
  1056. {
  1057. setText(jEdit.getProperty("vfs.browser.favorites.label"));
  1058. setIcon(GUIUtilities.loadIcon("ToolbarMenu.gif"));
  1059. setHorizontalTextPosition(SwingConstants.LEADING);
  1060. FavoritesMenuButton.this.setRequestFocusEnabled(false);
  1061. setMargin(new Insets(0,0,0,0));
  1062. FavoritesMenuButton.this.addMouseListener(new MouseHandler());
  1063. } //}}}
  1064. JPopupMenu popup;
  1065. //{{{ ActionHandler class
  1066. class ActionHandler implements ActionListener
  1067. {
  1068. public void actionPerformed(ActionEvent evt)
  1069. {
  1070. String actionCommand = evt.getActionCommand();
  1071. if(actionCommand.equals("add-to-favorites"))
  1072. {
  1073. // if any directories are selected, add
  1074. // them, otherwise add current directory
  1075. Vector toAdd = new Vector();
  1076. VFS.DirectoryEntry[] selected = getSelectedFiles();
  1077. for(int i = 0; i < selected.length; i++)
  1078. {
  1079. VFS.DirectoryEntry file = selected[i];
  1080. if(file.type == VFS.DirectoryEntry.FILE)
  1081. {
  1082. GUIUtilities.error(
  1083. VFSBrowser.this,
  1084. "vfs.browser.files-favorites",
  1085. null);
  1086. return;
  1087. }
  1088. else
  1089. toAdd.addElement(file.path);
  1090. }
  1091. if(toAdd.size() != 0)
  1092. {
  1093. for(int i = 0; i < toAdd.size(); i++)
  1094. {
  1095. FavoritesVFS.addToFavorites((String)toAdd.elementAt(i));
  1096. }
  1097. }
  1098. else
  1099. {
  1100. if(path.equals(FavoritesVFS.PROTOCOL + ":"))
  1101. {
  1102. GUIUtilities.error(VFSBrowser.this,
  1103. "vfs.browser.recurse-favorites",
  1104. null);
  1105. }
  1106. else
  1107. {
  1108. FavoritesVFS.addToFavorites(path);
  1109. }
  1110. }
  1111. }
  1112. else
  1113. setDirectory(actionCommand);
  1114. }
  1115. } //}}}
  1116. //{{{ MouseHandler class
  1117. class MouseHandler extends MouseAdapter
  1118. {
  1119. public void mousePressed(MouseEvent evt)
  1120. {
  1121. if(popup == null || !popup.isVisible())
  1122. {
  1123. popup = new JPopupMenu();
  1124. ActionHandler actionHandler = new ActionHandler();
  1125. JMenuItem mi = new JMenuItem(
  1126. jEdit.getProperty(
  1127. "vfs.browser.favorites"
  1128. + ".add-to-favorites.label"));
  1129. mi.setActionCommand("add-to-favorites");
  1130. mi.addActionListener(actionHandler);
  1131. popup.add(mi);
  1132. mi = new JMenuItem(
  1133. jEdit.getProperty(
  1134. "vfs.browser.favorites"
  1135. + ".edit-favorites.label"));
  1136. mi.setActionCommand("favorites:");
  1137. mi.addActionListener(actionHandler);
  1138. popup.add(mi);
  1139. popup.addSeparator();
  1140. String[] favorites = FavoritesVFS.getFavorites();
  1141. if(favorites.length == 0)
  1142. {
  1143. mi = new JMenuItem(
  1144. jEdit.getProperty(
  1145. "vfs.browser.favorites"
  1146. + ".no-favorites.label"));
  1147. mi.setEnabled(false);
  1148. popup.add(mi);
  1149. }
  1150. else
  1151. {
  1152. MiscUtilities.quicksort(favorites,
  1153. new MiscUtilities.StringCompare());
  1154. for(int i = 0; i < favorites.length; i++)
  1155. {
  1156. mi = new JMenuItem(favorites[i]);
  1157. mi.setIcon(FileCellRenderer.dirIcon);
  1158. mi.addActionListener(actionHandler);
  1159. popup.add(mi);
  1160. }
  1161. }
  1162. GUIUtilities.showPopupMenu(
  1163. popup,FavoritesMenuButton.this,0,
  1164. FavoritesMenuButton.this.getHeight());
  1165. }
  1166. else
  1167. {
  1168. popup.setVisible(false);
  1169. popup = null;
  1170. }
  1171. }
  1172. } //}}}
  1173. } //}}}
  1174. //}}}
  1175. }