PageRenderTime 30ms CodeModel.GetById 2ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/browser/BrowserView.java

#
Java | 540 lines | 389 code | 72 blank | 79 comment | 77 complexity | fb2ec8723ea409465c9487e6500f6d1f 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. * BrowserView.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2000, 2003 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 javax.swing.border.EmptyBorder;
  25. import javax.swing.event.*;
  26. import javax.swing.*;
  27. import java.awt.event.*;
  28. import java.awt.*;
  29. import java.io.File;
  30. import java.util.*;
  31. import org.gjt.sp.jedit.io.*;
  32. import org.gjt.sp.jedit.*;
  33. //}}}
  34. /**
  35. * VFS browser tree view.
  36. * @author Slava Pestov
  37. * @version $Id: BrowserView.java 4805 2003-06-22 01:09:47Z spestov $
  38. */
  39. class BrowserView extends JPanel
  40. {
  41. //{{{ BrowserView constructor
  42. public BrowserView(final VFSBrowser browser)
  43. {
  44. this.browser = browser;
  45. tmpExpanded = new HashSet();
  46. parentDirectories = new JList();
  47. parentDirectories.getSelectionModel().setSelectionMode(
  48. ListSelectionModel.SINGLE_SELECTION);
  49. parentDirectories.setCellRenderer(new ParentDirectoryRenderer());
  50. parentDirectories.setVisibleRowCount(5);
  51. parentDirectories.addMouseListener(new ParentMouseHandler());
  52. final JScrollPane parentScroller = new JScrollPane(parentDirectories);
  53. parentScroller.setMinimumSize(new Dimension(0,0));
  54. table = new VFSDirectoryEntryTable(this);
  55. table.addMouseListener(new TableMouseHandler());
  56. JScrollPane tableScroller = new JScrollPane(table);
  57. tableScroller.setMinimumSize(new Dimension(0,0));
  58. tableScroller.getViewport().setBackground(table.getBackground());
  59. tableScroller.getViewport().addMouseListener(new TableMouseHandler());
  60. splitPane = new JSplitPane(
  61. browser.isHorizontalLayout()
  62. ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT,
  63. parentScroller,tableScroller);
  64. splitPane.setOneTouchExpandable(true);
  65. SwingUtilities.invokeLater(new Runnable()
  66. {
  67. public void run()
  68. {
  69. String prop = browser.isHorizontalLayout() ? "vfs.browser.horizontalSplitter" : "vfs.browser.splitter";
  70. int loc = jEdit.getIntegerProperty(prop,-1);
  71. if(loc == -1)
  72. loc = parentScroller.getPreferredSize().height;
  73. splitPane.setDividerLocation(loc);
  74. parentDirectories.ensureIndexIsVisible(
  75. parentDirectories.getModel()
  76. .getSize());
  77. }
  78. });
  79. if(browser.isMultipleSelectionEnabled())
  80. table.getSelectionModel().setSelectionMode(
  81. ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  82. else
  83. table.getSelectionModel().setSelectionMode(
  84. ListSelectionModel.SINGLE_SELECTION);
  85. setLayout(new BorderLayout());
  86. add(BorderLayout.CENTER,splitPane);
  87. propertiesChanged();
  88. } //}}}
  89. //{{{ focusOnFileView() method
  90. public void focusOnFileView()
  91. {
  92. table.requestFocus();
  93. } //}}}
  94. //{{{ removeNotify() method
  95. public void removeNotify()
  96. {
  97. String prop = browser.isHorizontalLayout() ? "vfs.browser.horizontalSplitter" : "vfs.browser.splitter";
  98. jEdit.setIntegerProperty(prop,splitPane.getDividerLocation());
  99. super.removeNotify();
  100. } //}}}
  101. //{{{ getSelectedFiles() method
  102. public VFS.DirectoryEntry[] getSelectedFiles()
  103. {
  104. return table.getSelectedFiles();
  105. } //}}}
  106. //{{{ selectNone() method
  107. public void selectNone()
  108. {
  109. table.clearSelection();
  110. } //}}}
  111. //{{{ saveExpansionState() method
  112. public void saveExpansionState()
  113. {
  114. tmpExpanded.clear();
  115. table.getExpandedDirectories(tmpExpanded);
  116. } //}}}
  117. //{{{ clearExpansionState() method
  118. public void clearExpansionState()
  119. {
  120. tmpExpanded.clear();
  121. } //}}}
  122. //{{{ loadDirectory() method
  123. public void loadDirectory(Object node, String path)
  124. {
  125. path = MiscUtilities.constructPath(browser.getDirectory(),path);
  126. VFS vfs = VFSManager.getVFSForPath(path);
  127. Object session = vfs.createVFSSession(path,this);
  128. if(session == null)
  129. return;
  130. if(node == null)
  131. {
  132. parentDirectories.setListData(new Object[] {
  133. new LoadingPlaceholder() });
  134. }
  135. Object[] loadInfo = new Object[2];
  136. VFSManager.runInWorkThread(new BrowserIORequest(
  137. BrowserIORequest.LIST_DIRECTORY,browser,
  138. session,vfs,path,null,node,loadInfo));
  139. browser.directoryLoaded(node,loadInfo);
  140. } //}}}
  141. //{{{ directoryLoaded() method
  142. public void directoryLoaded(Object node, String path, ArrayList directory)
  143. {
  144. //{{{ If reloading root, update parent directory list
  145. if(node == null)
  146. {
  147. DefaultListModel parentList = new DefaultListModel();
  148. String parent = path;
  149. for(;;)
  150. {
  151. VFS _vfs = VFSManager.getVFSForPath(
  152. parent);
  153. // create a DirectoryEntry manually
  154. // instead of using _vfs._getDirectoryEntry()
  155. // since so many VFS's have broken
  156. // implementations of this method
  157. parentList.insertElementAt(new VFS.DirectoryEntry(
  158. _vfs.getFileName(parent),
  159. parent,parent,
  160. VFS.DirectoryEntry.DIRECTORY,
  161. 0L,false),0);
  162. String newParent = _vfs.getParentOfPath(parent);
  163. if(newParent == null ||
  164. VFSBrowser.pathsEqual(parent,newParent))
  165. break;
  166. else
  167. parent = newParent;
  168. }
  169. parentDirectories.setModel(parentList);
  170. int index = parentList.getSize() - 1;
  171. parentDirectories.setSelectedIndex(index);
  172. parentDirectories.ensureIndexIsVisible(index);
  173. } //}}}
  174. table.setDirectory(VFSManager.getVFSForPath(path),
  175. node,directory,tmpExpanded);
  176. } //}}}
  177. //{{{ updateFileView() method
  178. public void updateFileView()
  179. {
  180. table.repaint();
  181. } //}}}
  182. //{{{ maybeReloadDirectory() method
  183. public void maybeReloadDirectory(String path)
  184. {
  185. String browserDir = browser.getDirectory();
  186. if(VFSBrowser.pathsEqual(path,browserDir))
  187. {
  188. saveExpansionState();
  189. loadDirectory(null,path);
  190. }
  191. // because this method is called for *every* VFS update,
  192. // we don't want to scan the tree all the time. So we
  193. // use the following algorithm to determine if the path
  194. // might be part of the tree:
  195. // - if the path starts with the browser's current directory,
  196. // we do the tree scan
  197. // - if the browser's directory is 'favorites:' -- we have to
  198. // do the tree scan, as every path can appear under the
  199. // favorites list
  200. // - if the browser's directory is 'roots:' and path is on
  201. // the local filesystem, do a tree scan
  202. if(!browserDir.startsWith(FavoritesVFS.PROTOCOL)
  203. && !browserDir.startsWith(FileRootsVFS.PROTOCOL)
  204. && !path.startsWith(browserDir))
  205. return;
  206. if(browserDir.startsWith(FileRootsVFS.PROTOCOL)
  207. && MiscUtilities.isURL(path)
  208. && !MiscUtilities.getProtocolOfURL(path)
  209. .equals("file"))
  210. return;
  211. table.maybeReloadDirectory(path);
  212. } //}}}
  213. //{{{ propertiesChanged() method
  214. public void propertiesChanged()
  215. {
  216. showIcons = jEdit.getBooleanProperty("vfs.browser.showIcons");
  217. table.propertiesChanged();
  218. splitPane.setBorder(null);
  219. } //}}}
  220. //{{{ getBrowser() method
  221. /**
  222. * Returns the associated <code>VFSBrowser</code> instance.
  223. * @since jEdit 4.2pre1
  224. */
  225. public VFSBrowser getBrowser()
  226. {
  227. return browser;
  228. } //}}}
  229. //{{{ getTable() method
  230. public VFSDirectoryEntryTable getTable()
  231. {
  232. return table;
  233. } //}}}
  234. //{{{ getParentDirectoryList() method
  235. public JList getParentDirectoryList()
  236. {
  237. return parentDirectories;
  238. } //}}}
  239. //{{{ Private members
  240. //{{{ Instance variables
  241. private VFSBrowser browser;
  242. private JSplitPane splitPane;
  243. private JList parentDirectories;
  244. private VFSDirectoryEntryTable table;
  245. private Set tmpExpanded;
  246. private BrowserCommandsMenu popup;
  247. private boolean showIcons;
  248. //}}}
  249. //{{{ showFilePopup() method
  250. private void showFilePopup(VFS.DirectoryEntry[] files, Component comp,
  251. Point point)
  252. {
  253. popup = new BrowserCommandsMenu(browser,files);
  254. // for the parent directory right-click; on the click we select
  255. // the clicked item, but when the popup goes away we select the
  256. // currently showing directory.
  257. popup.addPopupMenuListener(new PopupMenuListener()
  258. {
  259. public void popupMenuCanceled(PopupMenuEvent e) {}
  260. public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
  261. public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
  262. {
  263. int index = parentDirectories.getModel().getSize() - 1;
  264. parentDirectories.setSelectedIndex(index);
  265. }
  266. });
  267. GUIUtilities.showPopupMenu(popup,comp,point.x,point.y);
  268. } //}}}
  269. //}}}
  270. //{{{ Inner classes
  271. //{{{ ParentDirectoryRenderer class
  272. class ParentDirectoryRenderer extends DefaultListCellRenderer
  273. {
  274. Font plainFont, boldFont;
  275. ParentDirectoryRenderer()
  276. {
  277. plainFont = UIManager.getFont("Tree.font");
  278. if(plainFont == null)
  279. plainFont = jEdit.getFontProperty("metal.secondary.font");
  280. boldFont = new Font(plainFont.getName(),Font.BOLD,plainFont.getSize());
  281. }
  282. public Component getListCellRendererComponent(
  283. JList list,
  284. Object value,
  285. int index,
  286. boolean isSelected,
  287. boolean cellHasFocus)
  288. {
  289. super.getListCellRendererComponent(list,value,index,
  290. isSelected,cellHasFocus);
  291. ParentDirectoryRenderer.this.setBorder(new EmptyBorder(
  292. 1,index * 5 + 1,1,1));
  293. if(value instanceof LoadingPlaceholder)
  294. {
  295. ParentDirectoryRenderer.this.setFont(plainFont);
  296. setIcon(showIcons ? FileCellRenderer.loadingIcon : null);
  297. setText(jEdit.getProperty("vfs.browser.tree.loading"));
  298. }
  299. else if(value instanceof VFS.DirectoryEntry)
  300. {
  301. VFS.DirectoryEntry dirEntry = (VFS.DirectoryEntry)value;
  302. ParentDirectoryRenderer.this.setFont(boldFont);
  303. setIcon(showIcons ? FileCellRenderer.getIconForFile(dirEntry,true)
  304. : null);
  305. setText(dirEntry.name);
  306. }
  307. else if(value == null)
  308. setText("VFS does not follow VFS API");
  309. return this;
  310. }
  311. } //}}}
  312. //{{{ ParentMouseHandler class
  313. class ParentMouseHandler extends MouseAdapter
  314. {
  315. public void mousePressed(MouseEvent evt)
  316. {
  317. int row = parentDirectories.locationToIndex(evt.getPoint());
  318. if(row != -1)
  319. {
  320. Object obj = parentDirectories.getModel()
  321. .getElementAt(row);
  322. if(obj instanceof VFS.DirectoryEntry)
  323. {
  324. VFS.DirectoryEntry dirEntry = ((VFS.DirectoryEntry)obj);
  325. if(GUIUtilities.isPopupTrigger(evt))
  326. {
  327. if(popup != null && popup.isVisible())
  328. {
  329. popup.setVisible(false);
  330. popup = null;
  331. }
  332. else
  333. {
  334. parentDirectories.setSelectedIndex(row);
  335. showFilePopup(new VFS.DirectoryEntry[] {
  336. dirEntry },parentDirectories,
  337. evt.getPoint());
  338. }
  339. }
  340. }
  341. }
  342. }
  343. public void mouseReleased(MouseEvent evt)
  344. {
  345. if(evt.getClickCount() % 2 != 0 &&
  346. !GUIUtilities.isMiddleButton(evt.getModifiers()))
  347. return;
  348. int row = parentDirectories.locationToIndex(evt.getPoint());
  349. if(row != -1)
  350. {
  351. Object obj = parentDirectories.getModel()
  352. .getElementAt(row);
  353. if(obj instanceof VFS.DirectoryEntry)
  354. {
  355. VFS.DirectoryEntry dirEntry = ((VFS.DirectoryEntry)obj);
  356. if(!GUIUtilities.isPopupTrigger(evt))
  357. {
  358. browser.setDirectory(dirEntry.path);
  359. if(browser.getMode() == VFSBrowser.BROWSER)
  360. focusOnFileView();
  361. }
  362. }
  363. }
  364. }
  365. } //}}}
  366. //{{{ TableMouseHandler class
  367. class TableMouseHandler extends MouseAdapter
  368. {
  369. //{{{ mouseClicked() method
  370. public void mouseClicked(MouseEvent evt)
  371. {
  372. Point p = evt.getPoint();
  373. int row = table.rowAtPoint(p);
  374. int column = table.columnAtPoint(p);
  375. if(row == -1)
  376. return;
  377. if(column == 0)
  378. {
  379. VFSDirectoryEntryTableModel.Entry entry
  380. = (VFSDirectoryEntryTableModel.Entry)
  381. table.getModel().getValueAt(row,0);
  382. if(FileCellRenderer.ExpansionToggleBorder
  383. .isExpansionToggle(entry.level,p.x))
  384. {
  385. return;
  386. }
  387. }
  388. if((evt.getModifiers() & MouseEvent.BUTTON1_MASK) != 0
  389. && evt.getClickCount() % 2 == 0)
  390. {
  391. browser.filesActivated((evt.isShiftDown()
  392. ? VFSBrowser.M_OPEN_NEW_VIEW
  393. : VFSBrowser.M_OPEN),true);
  394. }
  395. else if(GUIUtilities.isMiddleButton(evt.getModifiers()))
  396. {
  397. if(evt.isShiftDown())
  398. table.getSelectionModel().addSelectionInterval(row,row);
  399. else
  400. table.getSelectionModel().setSelectionInterval(row,row);
  401. browser.filesActivated((evt.isShiftDown()
  402. ? VFSBrowser.M_OPEN_NEW_VIEW
  403. : VFSBrowser.M_OPEN),true);
  404. }
  405. } //}}}
  406. //{{{ mousePressed() method
  407. public void mousePressed(MouseEvent evt)
  408. {
  409. Point p = evt.getPoint();
  410. if(evt.getSource() != table)
  411. {
  412. p.x -= table.getX();
  413. p.y -= table.getY();
  414. }
  415. int row = table.rowAtPoint(p);
  416. int column = table.columnAtPoint(p);
  417. if(column == 0 && row != -1)
  418. {
  419. VFSDirectoryEntryTableModel.Entry entry
  420. = (VFSDirectoryEntryTableModel.Entry)
  421. table.getModel().getValueAt(row,0);
  422. if(FileCellRenderer.ExpansionToggleBorder
  423. .isExpansionToggle(entry.level,p.x))
  424. {
  425. table.toggleExpanded(row);
  426. return;
  427. }
  428. }
  429. if(GUIUtilities.isMiddleButton(evt.getModifiers()))
  430. {
  431. if(row == -1)
  432. /* nothing */;
  433. else if(evt.isShiftDown())
  434. table.getSelectionModel().addSelectionInterval(row,row);
  435. else
  436. table.getSelectionModel().setSelectionInterval(row,row);
  437. }
  438. else if(GUIUtilities.isPopupTrigger(evt))
  439. {
  440. if(popup != null && popup.isVisible())
  441. {
  442. popup.setVisible(false);
  443. popup = null;
  444. return;
  445. }
  446. if(row == -1)
  447. showFilePopup(null,table,evt.getPoint());
  448. else
  449. {
  450. if(!table.getSelectionModel().isSelectedIndex(row))
  451. table.getSelectionModel().setSelectionInterval(row,row);
  452. showFilePopup(getSelectedFiles(),table,evt.getPoint());
  453. }
  454. }
  455. } //}}}
  456. //{{{ mouseReleased() method
  457. public void mouseReleased(MouseEvent evt)
  458. {
  459. if(!GUIUtilities.isPopupTrigger(evt)
  460. && table.getSelectedRow() != -1)
  461. {
  462. browser.filesSelected();
  463. }
  464. } //}}}
  465. } //}}}
  466. static class LoadingPlaceholder {}
  467. //}}}
  468. }