PageRenderTime 25ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/browser/VFSDirectoryEntryTableModel.java

#
Java | 473 lines | 288 code | 71 blank | 114 comment | 46 complexity | e727d0e9e26874f7b7782b75bde3c093 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. * VFSDirectoryEntryTableModel.java - VFS directory entry table model
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2003, 2005 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 java.util.*;
  26. import org.gjt.sp.jedit.io.FileVFS;
  27. import org.gjt.sp.jedit.io.VFS;
  28. import org.gjt.sp.jedit.io.VFSFile;
  29. import org.gjt.sp.jedit.io.VFSManager;
  30. import org.gjt.sp.jedit.*;
  31. import org.gjt.sp.util.Log;
  32. import org.gjt.sp.util.StandardUtilities;
  33. //}}}
  34. /**
  35. * @author Slava Pestov
  36. * @version $Id: VFSDirectoryEntryTableModel.java 14450 2009-01-24 22:56:40Z kpouer $
  37. * @since jEdit 4.2pre1
  38. */
  39. public class VFSDirectoryEntryTableModel extends AbstractTableModel
  40. {
  41. //{{{ VFSDirectoryEntryTableModel constructor
  42. public VFSDirectoryEntryTableModel()
  43. {
  44. extAttrs = new ArrayList<ExtendedAttribute>();
  45. sortColumn = 0;
  46. ascending = true;
  47. } //}}}
  48. //{{{ setRoot() method
  49. public void setRoot(VFS vfs, List<VFSFile> list)
  50. {
  51. extAttrs.clear();
  52. addExtendedAttributes(vfs);
  53. /* if(files != null && files.length != 0)
  54. fireTableRowsDeleted(0,files.length - 1); */
  55. files = new Entry[list.size()];
  56. for(int i = 0; i < files.length; i++)
  57. {
  58. files[i] = new Entry(list.get(i),0);
  59. }
  60. /* if(files.length != 0)
  61. fireTableRowsInserted(0,files.length - 1); */
  62. Arrays.sort(files, new EntryCompare(getSortAttribute(sortColumn), ascending));
  63. fireTableStructureChanged();
  64. } //}}}
  65. //{{{ expand() method
  66. public int expand(VFS vfs, Entry entry, List<VFSFile> list)
  67. {
  68. int startIndex = -1;
  69. for(int i = 0; i < files.length; i++)
  70. {
  71. if(files[i] == entry)
  72. startIndex = i;
  73. }
  74. if (startIndex != -1)
  75. collapse(vfs,startIndex);
  76. addExtendedAttributes(vfs);
  77. entry.expanded = true;
  78. if(list != null)
  79. {
  80. // make a large enough destination array
  81. Entry[] newFiles = new Entry[files.length + list.size()];
  82. Entry[] subdirFiles = new Entry[list.size()];
  83. for(int i = 0; i < list.size(); i++)
  84. {
  85. subdirFiles[i] = new Entry(
  86. list.get(i),entry.level + 1,entry);
  87. }
  88. // sort expanded entries according to current sort params
  89. Arrays.sort(subdirFiles, new EntryCompare(
  90. getSortAttribute(sortColumn), ascending));
  91. // make room after expanded entry for subdir files
  92. int nextIndex = startIndex + 1;
  93. System.arraycopy(files,0,newFiles,0,nextIndex);
  94. System.arraycopy(subdirFiles,0,newFiles,nextIndex,list.size());
  95. System.arraycopy(files,nextIndex,newFiles,nextIndex + list.size(),
  96. files.length - nextIndex);
  97. this.files = newFiles;
  98. /* fireTableRowsInserted(startIndex + 1,
  99. startIndex + list.size() + 1); */
  100. }
  101. /* fireTableRowsUpdated(startIndex,startIndex); */
  102. fireTableStructureChanged();
  103. return startIndex;
  104. } //}}}
  105. //{{{ collapse() method
  106. public void collapse(VFS vfs, int index)
  107. {
  108. Entry entry = files[index];
  109. if(!entry.expanded)
  110. return;
  111. entry.expanded = false;
  112. int lastIndex = index + 1;
  113. while(lastIndex < files.length)
  114. {
  115. Entry e = files[lastIndex];
  116. if(e.level <= entry.level)
  117. break;
  118. lastIndex++;
  119. if(e.expanded)
  120. {
  121. removeExtendedAttributes(VFSManager.getVFSForPath(
  122. e.dirEntry.getPath()));
  123. }
  124. }
  125. removeExtendedAttributes(vfs);
  126. Entry[] newFiles = new Entry[files.length - lastIndex + index + 1];
  127. System.arraycopy(files,0,newFiles,0,index + 1);
  128. System.arraycopy(files,lastIndex,newFiles,index + 1,
  129. files.length - lastIndex);
  130. files = newFiles;
  131. /* fireTableRowsUpdated(index,index);
  132. fireTableRowsDeleted(index + 1,lastIndex); */
  133. fireTableStructureChanged();
  134. } //}}}
  135. //{{{ getColumnCount() method
  136. public int getColumnCount()
  137. {
  138. return 1 + extAttrs.size();
  139. } //}}}
  140. //{{{ getRowCount() method
  141. public int getRowCount()
  142. {
  143. if(files == null)
  144. return 0;
  145. else
  146. return files.length;
  147. } //}}}
  148. //{{{ getColumnName() method
  149. public String getColumnName(int col)
  150. {
  151. if(col == 0)
  152. return jEdit.getProperty("vfs.browser.name");
  153. else
  154. return jEdit.getProperty("vfs.browser." + getExtendedAttribute(col));
  155. } //}}}
  156. //{{{ getColumnClass() method
  157. public Class getColumnClass(int col)
  158. {
  159. return Entry.class;
  160. } //}}}
  161. //{{{ getValueAt() method
  162. public Object getValueAt(int row, int col)
  163. {
  164. if(files == null)
  165. return null;
  166. else
  167. return files[row];
  168. } //}}}
  169. //{{{ getAscending() method
  170. public boolean getAscending()
  171. {
  172. return ascending;
  173. } //}}}
  174. //{{{ getSortColumn() method
  175. public int getSortColumn()
  176. {
  177. return sortColumn;
  178. } //}}}
  179. //{{{ getSortAttribute() method
  180. public String getSortAttribute(int column)
  181. {
  182. return column == 0 ? "name" : getExtendedAttribute(column);
  183. } //}}}
  184. //{{{ sortByColumn() method
  185. public boolean sortByColumn(int column)
  186. {
  187. // toggle ascending/descending if column was clicked again
  188. ascending = sortColumn != column || !ascending;
  189. // we don't sort by some attributes
  190. String sortBy = getSortAttribute(column);
  191. if(sortBy == VFS.EA_STATUS)
  192. return false;
  193. Arrays.sort(files, new EntryCompare(sortBy, ascending));
  194. // remember column
  195. sortColumn = column;
  196. fireTableStructureChanged();
  197. return true;
  198. } //}}}
  199. //{{{ getExtendedAttribute() method
  200. public String getExtendedAttribute(int index)
  201. {
  202. return extAttrs.get(index - 1).name;
  203. } //}}}
  204. //{{{ getColumnWidth() method
  205. /**
  206. * @param i The column index
  207. * @return A saved column width
  208. * @since jEdit 4.3pre2
  209. */
  210. public int getColumnWidth(int i)
  211. {
  212. String extAttr = getExtendedAttribute(i);
  213. return jEdit.getIntegerProperty("vfs.browser."
  214. + extAttr + ".width",100);
  215. } //}}}
  216. //{{{ setColumnWidth() method
  217. /**
  218. * @param i The column index
  219. * @param w The column width
  220. * @since jEdit 4.3pre2
  221. */
  222. public void setColumnWidth(int i, int w)
  223. {
  224. String extAttr = getExtendedAttribute(i);
  225. jEdit.setIntegerProperty("vfs.browser."
  226. + extAttr + ".width",w);
  227. } //}}}
  228. //{{{ getFiles() method
  229. public VFSFile[] getFiles()
  230. {
  231. VFSFile[] f = new VFSFile[files.length];
  232. for(int i = 0; i < f.length; i++)
  233. f[i] = files[i].dirEntry;
  234. return f;
  235. } //}}}
  236. //{{{ Package-private members
  237. Entry[] files;
  238. //}}}
  239. //{{{ Private members
  240. private List<ExtendedAttribute> extAttrs;
  241. private int sortColumn;
  242. private boolean ascending;
  243. //{{{ addExtendedAttributes() method
  244. private void addExtendedAttributes(VFS vfs)
  245. {
  246. String[] attrs = vfs.getExtendedAttributes();
  247. vfs_attr_loop: for(int i = 0; i < attrs.length; i++)
  248. {
  249. for (ExtendedAttribute attr : extAttrs)
  250. {
  251. if (attrs[i].equals(attr.name))
  252. {
  253. attr.ref++;
  254. continue vfs_attr_loop;
  255. }
  256. }
  257. // this vfs has an extended attribute which is not
  258. // in the list. add it to the end with a ref count
  259. // of 1
  260. extAttrs.add(new ExtendedAttribute(attrs[i]));
  261. }
  262. } //}}}
  263. //{{{ removeExtendedAttributes() method
  264. private void removeExtendedAttributes(VFS vfs)
  265. {
  266. String[] attrs = vfs.getExtendedAttributes();
  267. vfs_attr_loop: for(int i = 0; i < attrs.length; i++)
  268. {
  269. Iterator<ExtendedAttribute> iter = extAttrs.iterator();
  270. while(iter.hasNext())
  271. {
  272. ExtendedAttribute attr = iter.next();
  273. if(attrs[i].equals(attr.name))
  274. {
  275. if(--attr.ref == 0)
  276. {
  277. // we no longer have any
  278. // dirs using this extended
  279. // attribute
  280. iter.remove();
  281. }
  282. continue vfs_attr_loop;
  283. }
  284. }
  285. // this vfs has an extended attribute which is not
  286. // in the list ???
  287. Log.log(Log.WARNING,this,"We forgot about " + attrs[i]);
  288. }
  289. } //}}}
  290. //}}}
  291. //{{{ Entry class
  292. static class Entry
  293. {
  294. VFSFile dirEntry;
  295. // is this branch an expanded dir?
  296. boolean expanded;
  297. // how deeply we are nested
  298. int level;
  299. // parent entry
  300. Entry parent;
  301. // file extension
  302. String extension;
  303. Entry(VFSFile dirEntry, int level, Entry parent)
  304. {
  305. this(dirEntry,level);
  306. this.parent = parent;
  307. }
  308. Entry(VFSFile dirEntry, int level)
  309. {
  310. this.dirEntry = dirEntry;
  311. this.level = level;
  312. this.extension = MiscUtilities.getFileExtension(dirEntry.getName());
  313. }
  314. } //}}}
  315. //{{{ ExtendedAttribute class
  316. static class ExtendedAttribute
  317. {
  318. /* reference counter allows us to remove a column from
  319. * the table when no directory using this column is
  320. * visible */
  321. int ref;
  322. String name;
  323. ExtendedAttribute(String name)
  324. {
  325. this.name = name;
  326. ref = 1;
  327. }
  328. } //}}}
  329. //{{{ EntryCompare class
  330. /**
  331. * Implementation of {@link Comparator}
  332. * interface that compares {@link VFSDirectoryEntryTableModel.Entry} instances.
  333. * For sorting columns in the VFS Browser.
  334. * @since jEdit 4.3pre7
  335. */
  336. static class EntryCompare implements Comparator<Entry>
  337. {
  338. private boolean sortIgnoreCase, sortMixFilesAndDirs, sortAscending;
  339. private String sortAttribute;
  340. /**
  341. * Creates a new <code>EntryCompare</code>
  342. * Expanded branches are sorted, too, but keep with their parent entries
  343. * @param sortBy The extended attribute by which to sort the entries.
  344. * @param ascending If false, sort order is reversed.
  345. */
  346. EntryCompare(String sortBy, boolean ascending)
  347. {
  348. this.sortMixFilesAndDirs = jEdit.getBooleanProperty(
  349. "vfs.browser.sortMixFilesAndDirs");
  350. this.sortIgnoreCase = jEdit.getBooleanProperty(
  351. "vfs.browser.sortIgnoreCase");
  352. this.sortAscending = ascending;
  353. this.sortAttribute = sortBy;
  354. }
  355. public int compare(Entry entry1, Entry entry2)
  356. {
  357. // we want to compare sibling ancestors of the entries
  358. if(entry1.level < entry2.level)
  359. return compare(entry1, entry2.parent);
  360. if(entry1.level > entry2.level)
  361. return compare(entry1.parent, entry2);
  362. // here we have entries of the same level
  363. if(entry1.parent != entry2.parent)
  364. return compare(entry1.parent, entry2.parent);
  365. // here we have siblings with the same parents
  366. // let's do the real comparison
  367. VFSFile file1 = entry1.dirEntry;
  368. VFSFile file2 = entry2.dirEntry;
  369. if(!sortMixFilesAndDirs)
  370. {
  371. if(file1.getType() != file2.getType())
  372. return file2.getType() - file1.getType();
  373. }
  374. int result;
  375. // if the modified attribute is present, then we have a LocalFile
  376. if(sortAttribute == VFS.EA_MODIFIED)
  377. result = (
  378. (Long)((FileVFS.LocalFile)file1).getModified())
  379. .compareTo(
  380. (Long)((FileVFS.LocalFile)file2).getModified());
  381. // sort by size
  382. else if(sortAttribute == VFS.EA_SIZE)
  383. result = (
  384. (Long)file1.getLength())
  385. .compareTo(
  386. (Long)file2.getLength());
  387. // sort by type (= extension)
  388. else if(sortAttribute == VFS.EA_TYPE)
  389. result = StandardUtilities.compareStrings(
  390. entry1.extension,
  391. entry2.extension,
  392. sortIgnoreCase);
  393. // default: sort by name
  394. else
  395. result = StandardUtilities.compareStrings(
  396. file1.getName(),
  397. file2.getName(),
  398. sortIgnoreCase);
  399. return sortAscending ? result : -result;
  400. }
  401. } //}}}
  402. }