Java tutorial
/* Java Swing, 2nd Edition By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole ISBN: 0-596-00408-7 Publisher: O'Reilly */ // SortTreeDemo.java //This class creates a tree model using the SortTreeModel with //a File hierarchy as input. // import java.io.File; import java.util.Comparator; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; public class SortTreeDemo extends JFrame { public SortTreeDemo(String startDir) { super("SortTreeModel Demonstration"); setSize(300, 400); setDefaultCloseOperation(EXIT_ON_CLOSE); PrettyFile f = new PrettyFile(startDir); DefaultMutableTreeNode root = new DefaultMutableTreeNode(f); SortTreeModel model = new SortTreeModel(root, new TreeStringComparator()); fillModel(model, root); JTree tree = new JTree(model); getContentPane().add(new JScrollPane(tree)); } protected void fillModel(SortTreeModel model, DefaultMutableTreeNode current) { PrettyFile pf = (PrettyFile) current.getUserObject(); File f = pf.getFile(); if (f.isDirectory()) { String files[] = f.list(); // ignore "." files for (int i = 0; i < files.length; i++) { if (files[i].startsWith(".")) continue; PrettyFile tmp = new PrettyFile(pf, files[i]); DefaultMutableTreeNode node = new DefaultMutableTreeNode(tmp); model.insertNodeInto(node, current); if (tmp.getFile().isDirectory()) { fillModel(model, node); } } } } public class PrettyFile { File f; public PrettyFile(String s) { f = new File(s); } public PrettyFile(PrettyFile pf, String s) { f = new File(pf.f, s); } public File getFile() { return f; } public String toString() { return f.getName(); } } public static void main(String args[]) { SortTreeDemo demo = new SortTreeDemo(args.length == 1 ? args[0] : "."); demo.setVisible(true); } } //SortTreeModel.java //This class is similar to the DefaultTreeModel, but it keeps //a node's children in alphabetical order. // class SortTreeModel extends DefaultTreeModel { private Comparator comparator; public SortTreeModel(TreeNode node, Comparator c) { super(node); comparator = c; } public SortTreeModel(TreeNode node, boolean asksAllowsChildren, Comparator c) { super(node, asksAllowsChildren); comparator = c; } public void insertNodeInto(MutableTreeNode child, MutableTreeNode parent) { int index = findIndexFor(child, parent); super.insertNodeInto(child, parent, index); } public void insertNodeInto(MutableTreeNode child, MutableTreeNode par, int i) { // The index is useless in this model, so just ignore it. insertNodeInto(child, par); } // Perform a recursive binary search on the children to find the right // insertion point for the next node. private int findIndexFor(MutableTreeNode child, MutableTreeNode parent) { int cc = parent.getChildCount(); if (cc == 0) { return 0; } if (cc == 1) { return comparator.compare(child, parent.getChildAt(0)) <= 0 ? 0 : 1; } return findIndexFor(child, parent, 0, cc - 1); // First & last index } private int findIndexFor(MutableTreeNode child, MutableTreeNode parent, int i1, int i2) { if (i1 == i2) { return comparator.compare(child, parent.getChildAt(i1)) <= 0 ? i1 : i1 + 1; } int half = (i1 + i2) / 2; if (comparator.compare(child, parent.getChildAt(half)) <= 0) { return findIndexFor(child, parent, i1, half); } return findIndexFor(child, parent, half + 1, i2); } } //TreeStringComparator.java //This class compares the contents of the userObject as strings. //It's case-insensitive. // class TreeStringComparator implements Comparator { public int compare(Object o1, Object o2) { if (!(o1 instanceof DefaultMutableTreeNode && o2 instanceof DefaultMutableTreeNode)) { throw new IllegalArgumentException("Can only compare DefaultMutableTreeNode objects"); } String s1 = ((DefaultMutableTreeNode) o1).getUserObject().toString(); String s2 = ((DefaultMutableTreeNode) o2).getUserObject().toString(); return s1.compareToIgnoreCase(s2); } }