/* * VFSDirectoryEntryTableModel.java - VFS directory entry table model * :tabSize=4:indentSize=4:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2003, 2005 Slava Pestov * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.jedit.browser; //{{{ Imports import javax.swing.table.*; import java.util.*; import org.gjt.sp.jedit.io.FileVFS; import org.gjt.sp.jedit.io.VFS; import org.gjt.sp.jedit.io.VFSFile; import org.gjt.sp.jedit.io.VFSManager; import org.gjt.sp.jedit.*; import org.gjt.sp.util.Log; import org.gjt.sp.util.StandardUtilities; //}}} /** * @author Slava Pestov * @version $Id: VFSDirectoryEntryTableModel.java 23336 2013-11-16 12:05:40Z ezust $ * @since jEdit 4.2pre1 */ public class VFSDirectoryEntryTableModel extends AbstractTableModel { //{{{ VFSDirectoryEntryTableModel constructor public VFSDirectoryEntryTableModel() { extAttrs = new ArrayList<ExtendedAttribute>(); sortColumn = 0; ascending = true; } //}}} //{{{ setRoot() method public void setRoot(VFS vfs, List<VFSFile> list) { extAttrs.clear(); addExtendedAttributes(vfs); /* if(files != null && files.length != 0) fireTableRowsDeleted(0,files.length - 1); */ files = new Entry[list.size()]; for(int i = 0; i < files.length; i++) { files[i] = new Entry(list.get(i),0); } /* if(files.length != 0) fireTableRowsInserted(0,files.length - 1); */ Arrays.sort(files, new EntryCompare(getSortAttribute(sortColumn), ascending)); fireTableStructureChanged(); } //}}} //{{{ expand() method public int expand(VFS vfs, Entry entry, List<VFSFile> list) { int startIndex = -1; for(int i = 0; i < files.length; i++) { if(files[i] == entry) startIndex = i; } if (startIndex != -1) collapse(vfs,startIndex); addExtendedAttributes(vfs); entry.expanded = true; if(list != null) { // make a large enough destination array Entry[] newFiles = new Entry[files.length + list.size()]; Entry[] subdirFiles = new Entry[list.size()]; for(int i = 0; i < list.size(); i++) { subdirFiles[i] = new Entry( list.get(i),entry.level + 1,entry); } // sort expanded entries according to current sort params Arrays.sort(subdirFiles, new EntryCompare( getSortAttribute(sortColumn), ascending)); // make room after expanded entry for subdir files int nextIndex = startIndex + 1; System.arraycopy(files,0,newFiles,0,nextIndex); System.arraycopy(subdirFiles,0,newFiles,nextIndex,list.size()); System.arraycopy(files,nextIndex,newFiles,nextIndex + list.size(), files.length - nextIndex); this.files = newFiles; /* fireTableRowsInserted(startIndex + 1, startIndex + list.size() + 1); */ } /* fireTableRowsUpdated(startIndex,startIndex); */ fireTableStructureChanged(); return startIndex; } //}}} //{{{ collapse() method public void collapse(VFS vfs, int index) { Entry entry = files[index]; if(!entry.expanded) return; entry.expanded = false; int lastIndex = index + 1; while(lastIndex < files.length) { Entry e = files[lastIndex]; if(e.level <= entry.level) break; lastIndex++; if(e.expanded) { removeExtendedAttributes(VFSManager.getVFSForPath( e.dirEntry.getPath())); } } removeExtendedAttributes(vfs); Entry[] newFiles = new Entry[files.length - lastIndex + index + 1]; System.arraycopy(files,0,newFiles,0,index + 1); System.arraycopy(files,lastIndex,newFiles,index + 1, files.length - lastIndex); files = newFiles; /* fireTableRowsUpdated(index,index); fireTableRowsDeleted(index + 1,lastIndex); */ fireTableStructureChanged(); } //}}} //{{{ getColumnCount() method public int getColumnCount() { return 1 + extAttrs.size(); } //}}} //{{{ getRowCount() method public int getRowCount() { if(files == null) return 0; else return files.length; } //}}} //{{{ getColumnName() method public String getColumnName(int col) { if(col == 0) return jEdit.getProperty("vfs.browser.name"); else return jEdit.getProperty("vfs.browser." + getExtendedAttribute(col)); } //}}} //{{{ getColumnClass() method public Class getColumnClass(int col) { return Entry.class; } //}}} //{{{ getValueAt() method public Object getValueAt(int row, int col) { if(files == null) return null; else return files[row]; } //}}} //{{{ getAscending() method public boolean getAscending() { return ascending; } //}}} //{{{ getSortColumn() method public int getSortColumn() { return sortColumn; } //}}} //{{{ getSortAttribute() method public String getSortAttribute(int column) { return column == 0 ? "name" : getExtendedAttribute(column); } //}}} //{{{ sortByColumn() method public boolean sortByColumn(int column) { // toggle ascending/descending if column was clicked again ascending = sortColumn != column || !ascending; // we don't sort by some attributes String sortBy = getSortAttribute(column); if(sortBy == VFS.EA_STATUS) return false; Arrays.sort(files, new EntryCompare(sortBy, ascending)); // remember column sortColumn = column; fireTableStructureChanged(); return true; } //}}} //{{{ getExtendedAttribute() method public String getExtendedAttribute(int index) { return extAttrs.get(index - 1).name; } //}}} //{{{ getColumnWidth() method /** * @param i The column index * @return A saved column width * @since jEdit 4.3pre2 */ public int getColumnWidth(int i) { String extAttr = getExtendedAttribute(i); return jEdit.getIntegerProperty("vfs.browser." + extAttr + ".width",100); } //}}} //{{{ setColumnWidth() method /** * @param i The column index * @param w The column width * @since jEdit 4.3pre2 */ public void setColumnWidth(int i, int w) { String extAttr = getExtendedAttribute(i); jEdit.setIntegerProperty("vfs.browser." + extAttr + ".width",w); } //}}} //{{{ getFiles() method public VFSFile[] getFiles() { VFSFile[] f = new VFSFile[files.length]; for(int i = 0; i < f.length; i++) f[i] = files[i].dirEntry; return f; } //}}} //{{{ Package-private members Entry[] files; //}}} //{{{ Private members private List<ExtendedAttribute> extAttrs; private int sortColumn; private boolean ascending; //{{{ addExtendedAttributes() method private void addExtendedAttributes(VFS vfs) { String[] attrs = vfs.getExtendedAttributes(); vfs_attr_loop: for(int i = 0; i < attrs.length; i++) { for (ExtendedAttribute attr : extAttrs) { if (attrs[i].equals(attr.name)) { attr.ref++; continue vfs_attr_loop; } } // this vfs has an extended attribute which is not // in the list. add it to the end with a ref count // of 1 extAttrs.add(new ExtendedAttribute(attrs[i])); } } //}}} //{{{ removeExtendedAttributes() method private void removeExtendedAttributes(VFS vfs) { String[] attrs = vfs.getExtendedAttributes(); vfs_attr_loop: for(int i = 0; i < attrs.length; i++) { Iterator<ExtendedAttribute> iter = extAttrs.iterator(); while(iter.hasNext()) { ExtendedAttribute attr = iter.next(); if(attrs[i].equals(attr.name)) { if(--attr.ref == 0) { // we no longer have any // dirs using this extended // attribute iter.remove(); } continue vfs_attr_loop; } } // this vfs has an extended attribute which is not // in the list ??? Log.log(Log.WARNING,this,"We forgot about " + attrs[i]); } } //}}} //}}} //{{{ Entry class static class Entry { VFSFile dirEntry; // is this branch an expanded dir? boolean expanded; // how deeply we are nested int level; // parent entry Entry parent; // file extension String extension; Entry(VFSFile dirEntry, int level, Entry parent) { this(dirEntry,level); this.parent = parent; } Entry(VFSFile dirEntry, int level) { this.dirEntry = dirEntry; this.level = level; this.extension = MiscUtilities.getFileExtension(dirEntry.getName()); } } //}}} //{{{ ExtendedAttribute class static class ExtendedAttribute { /* reference counter allows us to remove a column from * the table when no directory using this column is * visible */ int ref; String name; ExtendedAttribute(String name) { this.name = name; ref = 1; } } //}}} //{{{ EntryCompare class /** * Implementation of {@link Comparator} * interface that compares {@link VFSDirectoryEntryTableModel.Entry} instances. * For sorting columns in the VFS Browser. * @since jEdit 4.3pre7 */ static class EntryCompare implements Comparator<Entry> { private boolean sortIgnoreCase, sortMixFilesAndDirs, sortAscending; private String sortAttribute; /** * Creates a new <code>EntryCompare</code> * Expanded branches are sorted, too, but keep with their parent entries * @param sortBy The extended attribute by which to sort the entries. * @param ascending If false, sort order is reversed. */ EntryCompare(String sortBy, boolean ascending) { this.sortMixFilesAndDirs = jEdit.getBooleanProperty( "vfs.browser.sortMixFilesAndDirs"); this.sortIgnoreCase = jEdit.getBooleanProperty( "vfs.browser.sortIgnoreCase"); this.sortAscending = ascending; this.sortAttribute = sortBy; } public int compare(Entry entry1, Entry entry2) { // we want to compare sibling ancestors of the entries if(entry1.level < entry2.level) return compare(entry1, entry2.parent); if(entry1.level > entry2.level) return compare(entry1.parent, entry2); // here we have entries of the same level if(entry1.parent != entry2.parent) return compare(entry1.parent, entry2.parent); // here we have siblings with the same parents // let's do the real comparison VFSFile file1 = entry1.dirEntry; VFSFile file2 = entry2.dirEntry; if(!sortMixFilesAndDirs) { if(file1.getType() != file2.getType()) return file2.getType() - file1.getType(); } int result; // if the modified attribute is present, then we have a LocalFile if(sortAttribute == VFS.EA_MODIFIED) result = ( (Long)file1.getModified()) .compareTo( (Long)file2.getModified()); // sort by size else if(sortAttribute == VFS.EA_SIZE) result = ( (Long)file1.getLength()) .compareTo( (Long)file2.getLength()); // sort by type (= extension) else if(sortAttribute == VFS.EA_TYPE) result = StandardUtilities.compareStrings( entry1.extension, entry2.extension, sortIgnoreCase); // default: sort by name else result = StandardUtilities.compareStrings( file1.getName(), file2.getName(), sortIgnoreCase); return sortAscending ? result : -result; } } //}}} }