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