package yuku.atree.nodes;
import java.io.*;
import java.util.*;
import yuku.atree.*;
public abstract class BaseFileTreeNode extends BaseMutableTreeNode implements Comparable<BaseFileTreeNode> {
public static final String TAG = BaseFileTreeNode.class.getSimpleName();
protected final File file;
protected final File[] virtualChildren;
public BaseFileTreeNode(File file) {
this.file = file;
this.virtualChildren = null;
}
public BaseFileTreeNode(File[] virtualChildren) {
this.file = null;
this.virtualChildren = virtualChildren;
}
@Override public void setExpanded(boolean expanded) {
super.setExpanded(expanded);
if (expanded) {
File[] files;
if (file != null && file.isDirectory()) {
files = file.listFiles(fileFilter);
if (files != null) Arrays.sort(files, fileComparator);
} else if (virtualChildren != null) {
files = virtualChildren;
} else {
files = null;
}
if (files == null) {
this.removeAllChildren();
} else {
HashMap<String, BaseFileTreeNode> existing = new HashMap<String, BaseFileTreeNode>();
for (int i = 0; i < this.getChildCount(); i++) {
BaseFileTreeNode child = this.getChildAt(i);
existing.put(child.file.getName(), child);
}
this.removeAllChildren();
for (File file : files) {
BaseFileTreeNode existingNode = existing.get(file.getName());
if (existingNode != null) {
this.add(existingNode);
} else {
this.add(generateForFile(file));
}
}
}
}
}
private FileFilter fileFilter = new FileFilter() {
@Override public boolean accept(File pathname) {
if (showDirectoriesOnly()) {
if (!pathname.isDirectory()) {
return false;
}
}
if (!showHidden()) {
if (pathname.isHidden()) {
return false;
}
}
return true;
}
};
static Comparator<File> fileComparator = new Comparator<File>() {
@Override public int compare(File a, File b) {
// virtual first
if (a == null) {
return -1;
} else if (b == null) {
return +1;
}
if (a.isDirectory() && !b.isDirectory()) {
return -1;
} else if (!a.isDirectory() && b.isDirectory()) {
return +1;
}
// both files or both dirs
String aname = a.getName();
String bname = b.getName();
// dot-files are later
if (aname.startsWith(".") && !bname.startsWith(".")) { //$NON-NLS-1$ //$NON-NLS-2$
return +1;
} else if (!aname.startsWith(".") && bname.startsWith(".")) { //$NON-NLS-1$ //$NON-NLS-2$
return -1;
}
return aname.compareToIgnoreCase(bname);
}
};
@Override public int compareTo(BaseFileTreeNode another) {
File a = this.file;
File b = another.file;
return fileComparator.compare(a, b);
}
protected abstract BaseFileTreeNode generateForFile(File file);
protected boolean showDirectoriesOnly() {
return false;
}
protected boolean showHidden() {
return true;
}
public File getFile() {
return file;
}
public File[] getVirtualChildren() {
return virtualChildren;
}
}