package tijmp.ui;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Arrays;
import java.util.Comparator;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
/** A panel that shows strings in a tree.
*/
public class StringTree extends JPanel {
public StringTree (Object[] objects) {
Arrays.sort (objects, new CharArrayComparator ());
JTree jt = new JTree (getModel (objects));
JScrollPane sp = new JScrollPane (jt);
GridBagLayout gb = new GridBagLayout ();
GridBagConstraints c = new GridBagConstraints ();
setLayout (gb);
c.insets = new Insets (2, 2, 2, 2);
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
add (sp, c);
}
private static final class CharArrayComparator implements Comparator<Object> {
public int compare (Object o1, Object o2) {
char[] c1 = (char[])o1;
char[] c2 = (char[])o2;
String s1 = new String (c1);
String s2 = new String (c2);
return s1.compareTo (s2);
}
}
private TreeModel getModel (Object[] objects) {
DefaultMutableTreeNode root =
new DefaultMutableTreeNode (new SimpleNode (""));
DefaultMutableTreeNode last = root;
for (Object o : objects) {
char[] ca = (char[])o;
String s = new String (ca);
StringNode sn = (StringNode)last.getUserObject ();
if (sn.getString ().equals (s)) {
last.setUserObject (sn.incrementCount ());
} else {
if (s.length () == 1) {
last = new DefaultMutableTreeNode (new SimpleNode (s));
root.add (last);
} else if (s.length () == 2) {
last = handle2 (s, sn, last, root);
} else {
last = handleLong (s, sn, last, root);
}
}
updateChildCounts (last, 0);
}
return new DefaultTreeModel (root);
}
private void updateChildCounts (DefaultMutableTreeNode n, int count) {
while (n != null) {
StringNode sn = (StringNode)n.getUserObject ();
sn.incrementChildrenCount (count);
count = 1;
n = (DefaultMutableTreeNode)n.getParent ();
}
}
private DefaultMutableTreeNode handleLong (String s, StringNode sn,
DefaultMutableTreeNode last,
DefaultMutableTreeNode root) {
String p1 = s.substring (0, 1);
String p2 = s.substring (0, 2);
if (sn.getString ().length () > 2) {
last = (DefaultMutableTreeNode)last.getParent ();
sn = (StringNode)last.getUserObject ();
}
DefaultMutableTreeNode dm2 = last;
DefaultMutableTreeNode dm1 = last;
StringNode sn1 = (StringNode)dm1.getUserObject ();
if (sn1.getString ().length () > 1) {
dm1 = (DefaultMutableTreeNode)last.getParent ();
}
if (sn.getString ().startsWith (p2)) {
// nothing
} else if (sn.getString ().startsWith (p1)) {
dm2 = new DefaultMutableTreeNode (new FakeNode (p2));
dm1.add (dm2);
} else {
dm1 = new DefaultMutableTreeNode (new FakeNode (p1));
root.add (dm1);
dm2 = new DefaultMutableTreeNode (new FakeNode (p2));
dm1.add (dm2);
}
DefaultMutableTreeNode dms =
new DefaultMutableTreeNode (new SimpleNode (s));
dm2.add (dms);
last = dms;
return last;
}
private DefaultMutableTreeNode handle2 (String s, StringNode sn,
DefaultMutableTreeNode last,
DefaultMutableTreeNode root) {
String p = s.substring (0, 1);
DefaultMutableTreeNode dm = last;
if (sn.getString ().equals (p)) {
dm = last;
} else {
dm = (DefaultMutableTreeNode)last.getParent ();
String sp = sn.getString ();
if (sp.length () > 2)
dm = (DefaultMutableTreeNode)dm.getParent ();
if (!sp.startsWith (p)) {
dm = new DefaultMutableTreeNode (new FakeNode (p));
root.add (dm);
}
}
DefaultMutableTreeNode dms =
new DefaultMutableTreeNode (new SimpleNode (s));
dm.add (dms);
last = dms;
return last;
}
private static interface StringNode {
String getString ();
StringNode incrementCount ();
void incrementChildrenCount (int n);
}
private abstract static class BaseNode implements StringNode {
private String s;
private int childCount;
public BaseNode (String s) {
this.s = s;
}
public String getString () {
return s;
}
public void incrementChildrenCount (int n) {
childCount += n;
}
public String getChildCountString () {
if (childCount == 0)
return "";
return ", " + childCount;
}
}
private static class FakeNode extends BaseNode {
public FakeNode (String s) {
super (s);
}
public String toString () {
return getString () + ": 0" + getChildCountString ();
}
public StringNode incrementCount () {
String err = "can not incrementCount on a fake node";
throw new IllegalStateException (err);
}
}
private static class SimpleNode extends BaseNode {
public SimpleNode (String s) {
super (s);
}
public String toString () {
return getString () + ": 1" + getChildCountString ();
}
public StringNode incrementCount () {
return new MultiNode (getString (), 2);
}
}
private static class MultiNode extends BaseNode {
private int count;
public MultiNode (String s, int count) {
super (s);
this.count = count;
}
public StringNode incrementCount () {
count++;
return this;
}
public String toString () {
return getString () + ": " + count + getChildCountString ();
}
}
}
|