/jEdit/tags/jedit-4-2-pre3/org/gjt/sp/jedit/browser/VFSDirectoryEntryTable.java

# · Java · 482 lines · 373 code · 53 blank · 56 comment · 74 complexity · c1e064c3aca6588b996b8f214686e408 MD5 · raw file

  1. /*
  2. * VFSDirectoryEntryTable.java - VFS directory entry table
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 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.table.*;
  25. import javax.swing.*;
  26. import java.awt.event.*;
  27. import java.awt.font.*;
  28. import java.awt.*;
  29. import java.util.ArrayList;
  30. import java.util.HashSet;
  31. import java.util.LinkedList;
  32. import java.util.Set;
  33. import org.gjt.sp.jedit.io.VFS;
  34. import org.gjt.sp.jedit.io.VFSManager;
  35. import org.gjt.sp.jedit.MiscUtilities;
  36. import org.gjt.sp.util.Log;
  37. //}}}
  38. /**
  39. * @author Slava Pestov
  40. * @version $Id: VFSDirectoryEntryTable.java 4808 2003-06-22 21:23:33Z spestov $
  41. * @since jEdit 4.2pre1
  42. */
  43. public class VFSDirectoryEntryTable extends JTable
  44. {
  45. //{{{ VFSDirectoryEntryTable constructor
  46. public VFSDirectoryEntryTable(BrowserView browserView)
  47. {
  48. super(new VFSDirectoryEntryTableModel());
  49. this.browserView = browserView;
  50. setShowGrid(false);
  51. setIntercellSpacing(new Dimension(0,0));
  52. /* TableColumn col1 = getColumnModel().getColumn(0);
  53. col1.setMinWidth(20);
  54. col1.setMaxWidth(20);
  55. col1.setPreferredWidth(20); */
  56. setDefaultRenderer(VFSDirectoryEntryTableModel.Entry.class,
  57. renderer = new FileCellRenderer());
  58. JTableHeader header = getTableHeader();
  59. header.setReorderingAllowed(false);
  60. setRowSelectionAllowed(true);
  61. //setColumnSelectionAllowed(true);
  62. //setCellSelectionEnabled(false);
  63. setAutoResizeMode(AUTO_RESIZE_OFF);
  64. } //}}}
  65. //{{{ selectFile() method
  66. public boolean selectFile(String path)
  67. {
  68. for(int i = 0; i < getRowCount(); i++)
  69. {
  70. VFSDirectoryEntryTableModel.Entry entry =
  71. (VFSDirectoryEntryTableModel.Entry)
  72. getValueAt(i,1);
  73. if(entry.dirEntry.path.equals(path))
  74. {
  75. setSelectedRow(i);
  76. return true;
  77. }
  78. }
  79. return false;
  80. } //}}}
  81. //{{{ doTypeSelect() method
  82. public void doTypeSelect(String str, boolean dirsOnly)
  83. {
  84. if(str.length() == 0)
  85. clearSelection();
  86. else if(getSelectedRow() == -1)
  87. doTypeSelect(str,0,getRowCount(),dirsOnly);
  88. else
  89. {
  90. int start = getSelectionModel().getMaxSelectionIndex();
  91. boolean retVal = doTypeSelect(str,start,getRowCount(),
  92. dirsOnly);
  93. if(!retVal)
  94. {
  95. // scan from selection to end failed, so
  96. // scan from start to selection
  97. doTypeSelect(str,0,start,dirsOnly);
  98. }
  99. }
  100. } //}}}
  101. //{{{ getSelectedFiles() method
  102. public VFS.DirectoryEntry[] getSelectedFiles()
  103. {
  104. VFSDirectoryEntryTableModel model
  105. = (VFSDirectoryEntryTableModel)getModel();
  106. LinkedList returnValue = new LinkedList();
  107. int[] selectedRows = getSelectedRows();
  108. for(int i = 0; i < selectedRows.length; i++)
  109. {
  110. returnValue.add(model.files[selectedRows[i]].dirEntry);
  111. }
  112. return (VFS.DirectoryEntry[])returnValue.toArray(new
  113. VFS.DirectoryEntry[returnValue.size()]);
  114. } //}}}
  115. //{{{ getExpandedDirectories() method
  116. public void getExpandedDirectories(Set set)
  117. {
  118. VFSDirectoryEntryTableModel model
  119. = (VFSDirectoryEntryTableModel)getModel();
  120. if(model.files != null)
  121. {
  122. for(int i = 0; i < model.files.length; i++)
  123. {
  124. if(model.files[i].expanded)
  125. set.add(model.files[i].dirEntry.path);
  126. }
  127. }
  128. } //}}}
  129. //{{{ toggleExpanded() method
  130. public void toggleExpanded(int row)
  131. {
  132. VFSDirectoryEntryTableModel model
  133. = (VFSDirectoryEntryTableModel)getModel();
  134. VFSDirectoryEntryTableModel.Entry entry = model.files[row];
  135. if(entry.dirEntry.type == VFS.DirectoryEntry.FILE)
  136. return;
  137. if(entry.expanded)
  138. {
  139. model.collapse(VFSManager.getVFSForPath(
  140. entry.dirEntry.path),row);
  141. resizeColumnsAppropriately();
  142. }
  143. else
  144. {
  145. browserView.clearExpansionState();
  146. browserView.loadDirectory(entry,entry.dirEntry.path);
  147. }
  148. } //}}}
  149. //{{{ setDirectory() method
  150. public void setDirectory(VFS vfs, Object node, ArrayList list,
  151. Set tmpExpanded)
  152. {
  153. timer.stop();
  154. typeSelectBuffer.setLength(0);
  155. VFSDirectoryEntryTableModel model = ((VFSDirectoryEntryTableModel)getModel());
  156. int startIndex;
  157. if(node == null)
  158. {
  159. startIndex = 0;
  160. model.setRoot(vfs,list);
  161. }
  162. else
  163. {
  164. startIndex =
  165. model.expand(
  166. vfs,
  167. (VFSDirectoryEntryTableModel.Entry)node,
  168. list);
  169. startIndex++;
  170. }
  171. for(int i = 0; i < list.size(); i++)
  172. {
  173. VFSDirectoryEntryTableModel.Entry e
  174. = model.files[startIndex + i];
  175. String path = e.dirEntry.path;
  176. if(tmpExpanded.contains(path))
  177. {
  178. browserView.loadDirectory(e,path);
  179. tmpExpanded.remove(path);
  180. }
  181. }
  182. resizeColumnsAppropriately();
  183. } //}}}
  184. //{{{ maybeReloadDirectory() method
  185. public void maybeReloadDirectory(String path)
  186. {
  187. VFSDirectoryEntryTableModel model
  188. = (VFSDirectoryEntryTableModel)getModel();
  189. for(int i = 0; i < model.files.length; i++)
  190. {
  191. VFSDirectoryEntryTableModel.Entry e = model.files[i];
  192. if(!e.expanded || e.dirEntry.type == VFS.DirectoryEntry.FILE)
  193. continue;
  194. if(VFSBrowser.pathsEqual(path,e.dirEntry.path))
  195. {
  196. browserView.saveExpansionState();
  197. browserView.loadDirectory(e,path);
  198. return;
  199. }
  200. }
  201. } //}}}
  202. //{{{ propertiesChanged() method
  203. public void propertiesChanged()
  204. {
  205. renderer.propertiesChanged();
  206. VFS.DirectoryEntry template = new VFS.DirectoryEntry(
  207. "foo","foo","foo",VFS.DirectoryEntry.FILE,0L,false);
  208. setRowHeight(renderer.getTableCellRendererComponent(
  209. this,new VFSDirectoryEntryTableModel.Entry(template,0),
  210. false,false,0,0).getPreferredSize().height);
  211. Dimension prefSize = getPreferredSize();
  212. setPreferredScrollableViewportSize(new Dimension(prefSize.width,
  213. getRowHeight() * 12));
  214. } //}}}
  215. //{{{ scrollRectToVisible() method
  216. public void scrollRectToVisible(Rectangle rect)
  217. {
  218. // avoid scrolling to the right
  219. rect.width = 0;
  220. super.scrollRectToVisible(rect);
  221. } //}}}
  222. //{{{ processKeyEvent() method
  223. public void processKeyEvent(KeyEvent evt)
  224. {
  225. if(evt.getID() == KeyEvent.KEY_PRESSED)
  226. {
  227. VFSDirectoryEntryTableModel model =
  228. (VFSDirectoryEntryTableModel)getModel();
  229. int row = getSelectedRow();
  230. switch(evt.getKeyCode())
  231. {
  232. case KeyEvent.VK_LEFT:
  233. evt.consume();
  234. if(row != -1)
  235. {
  236. if(model.files[row].expanded)
  237. {
  238. model.collapse(
  239. VFSManager.getVFSForPath(
  240. model.files[row].dirEntry.path),
  241. row);
  242. break;
  243. }
  244. for(int i = row - 1; i >= 0; i--)
  245. {
  246. if(model.files[i].expanded)
  247. {
  248. setSelectedRow(i);
  249. break;
  250. }
  251. }
  252. }
  253. String dir = browserView.getBrowser()
  254. .getDirectory();
  255. dir = MiscUtilities.getParentOfPath(dir);
  256. browserView.getBrowser().setDirectory(dir);
  257. break;
  258. case KeyEvent.VK_RIGHT:
  259. if(row != -1)
  260. {
  261. if(!model.files[row].expanded)
  262. toggleExpanded(row);
  263. }
  264. evt.consume();
  265. break;
  266. case KeyEvent.VK_DOWN:
  267. // stupid Swing
  268. if(row == -1 && getModel().getRowCount() != 0)
  269. {
  270. setSelectedRow(0);
  271. evt.consume();
  272. }
  273. break;
  274. case KeyEvent.VK_ENTER:
  275. browserView.getBrowser().filesActivated(
  276. (evt.isShiftDown()
  277. ? VFSBrowser.M_OPEN_NEW_VIEW
  278. : VFSBrowser.M_OPEN),false);
  279. evt.consume();
  280. break;
  281. }
  282. }
  283. else if(evt.getID() == KeyEvent.KEY_TYPED)
  284. {
  285. if(evt.isControlDown() || evt.isAltDown()
  286. || evt.isMetaDown())
  287. {
  288. return;
  289. }
  290. // hack...
  291. if(evt.isShiftDown() && evt.getKeyChar() == '\n')
  292. return;
  293. VFSBrowser browser = browserView.getBrowser();
  294. switch(evt.getKeyChar())
  295. {
  296. case '~':
  297. if(browser.getMode() == VFSBrowser.BROWSER)
  298. browser.setDirectory(System.getProperty(
  299. "user.home"));
  300. break;
  301. case '/':
  302. if(browser.getMode() == VFSBrowser.BROWSER)
  303. browser.rootDirectory();
  304. break;
  305. case '-':
  306. if(browser.getMode() == VFSBrowser.BROWSER)
  307. {
  308. browser.setDirectory(
  309. browser.getView().getBuffer()
  310. .getDirectory());
  311. }
  312. break;
  313. default:
  314. typeSelectBuffer.append(evt.getKeyChar());
  315. doTypeSelect(typeSelectBuffer.toString(),
  316. browser.getMode() == VFSBrowser
  317. .CHOOSE_DIRECTORY_DIALOG);
  318. timer.stop();
  319. timer.setInitialDelay(750);
  320. timer.setRepeats(false);
  321. timer.start();
  322. return;
  323. }
  324. }
  325. if(!evt.isConsumed())
  326. super.processKeyEvent(evt);
  327. } //}}}
  328. //{{{ setSelectedRow() method
  329. public void setSelectedRow(int row)
  330. {
  331. getSelectionModel().setSelectionInterval(row,row);
  332. scrollRectToVisible(getCellRect(row,0,true));
  333. } //}}}
  334. //{{{ Private members
  335. private BrowserView browserView;
  336. private FileCellRenderer renderer;
  337. private StringBuffer typeSelectBuffer = new StringBuffer();
  338. private Timer timer = new Timer(0,new ClearTypeSelect());
  339. //{{{ doTypeSelect() method
  340. private boolean doTypeSelect(String str, int start, int end,
  341. boolean dirsOnly)
  342. {
  343. for(int i = start; i < end; i++)
  344. {
  345. VFSDirectoryEntryTableModel.Entry entry =
  346. (VFSDirectoryEntryTableModel.Entry)getValueAt(i,1);
  347. if(dirsOnly && entry.dirEntry.type
  348. == VFS.DirectoryEntry.FILE)
  349. {
  350. continue;
  351. }
  352. String matchAgainst = (MiscUtilities.isAbsolutePath(str)
  353. ? entry.dirEntry.path : entry.dirEntry.name);
  354. if(matchAgainst.regionMatches(true,
  355. 0,str,0,str.length()))
  356. {
  357. setSelectedRow(i);
  358. return true;
  359. }
  360. }
  361. return false;
  362. } //}}}
  363. //{{{ resizeColumnsAppropriately() method
  364. private void resizeColumnsAppropriately()
  365. {
  366. VFSDirectoryEntryTableModel model
  367. = (VFSDirectoryEntryTableModel)getModel();
  368. FontRenderContext fontRenderContext = new FontRenderContext(
  369. null,false,false);
  370. int[] widths = new int[model.getColumnCount()];
  371. for(int i = 0; i < widths.length; i++)
  372. {
  373. String columnName = model.getColumnName(i);
  374. if(columnName != null)
  375. {
  376. widths[i] = (int)renderer.plainFont
  377. .getStringBounds(columnName,
  378. fontRenderContext).getWidth();
  379. }
  380. }
  381. for(int i = 0; i < model.files.length; i++)
  382. {
  383. VFSDirectoryEntryTableModel.Entry entry
  384. = model.files[i];
  385. Font font = (entry.dirEntry.type
  386. == VFS.DirectoryEntry.FILE
  387. ? renderer.plainFont : renderer.boldFont);
  388. widths[0] = Math.max(widths[0],renderer.getEntryWidth(
  389. entry,font,fontRenderContext));
  390. for(int j = 1; j < widths.length; j++)
  391. {
  392. String extAttr = model.getExtendedAttribute(
  393. j - 1);
  394. String attr = entry.dirEntry
  395. .getExtendedAttribute(
  396. extAttr);
  397. if(attr != null)
  398. {
  399. widths[j] = Math.max(widths[j],
  400. (int)font.getStringBounds(
  401. attr,fontRenderContext)
  402. .getWidth());
  403. }
  404. }
  405. }
  406. for(int i = 0; i < widths.length; i++)
  407. {
  408. int width = widths[i];
  409. if(i != widths.length - 1 && width != 0)
  410. width += 10;
  411. else
  412. width += 2;
  413. getColumnModel().getColumn(i).setPreferredWidth(width);
  414. getColumnModel().getColumn(i).setMinWidth(width);
  415. getColumnModel().getColumn(i).setMaxWidth(width);
  416. getColumnModel().getColumn(i).setWidth(width);
  417. }
  418. doLayout();
  419. } //}}}
  420. //}}}
  421. //{{{ ClearTypeSelect class
  422. class ClearTypeSelect implements ActionListener
  423. {
  424. public void actionPerformed(ActionEvent evt)
  425. {
  426. typeSelectBuffer.setLength(0);
  427. }
  428. } //}}}
  429. }