package com.c2kernel.gui; import javax.swing.ImageIcon; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import com.c2kernel.gui.data.Node; import com.c2kernel.gui.data.NodeSubscriber; import com.c2kernel.lookup.Path; import com.c2kernel.utils.Language; import com.c2kernel.utils.Logger; import com.c2kernel.utils.Resource; /** * Installed as the user object on a single child node of a new node known to be composite. *
Shows 'Loading . . .' when the branch is opened, but a TreeExpansionListener attempts to fire this thread off in the first child node.
*
When started, this thread will retrieve all of the real child nodes and add them to its parent while removing itself (hopefully for garbage collection)
*
* @version $Revision: 1.24 $ $Date: 2004/12/15 12:12:06 $
* @author $Author: abranson $
*/
public class DynamicTreeBuilder implements NodeSubscriber {
private DefaultTreeModel treeModel;
private DefaultMutableTreeNode parent;
public short state = IDLE;
public static final short IDLE = 0;
public static final short LOADING = 1;
public static final short PARTIAL = 2;
public static final short FINISHED = 3;
private DefaultMutableTreeNode loading;
private static ImageIcon loadIcon = Resource.getImageResource("loading.gif");
private static ImageIcon pauseIcon = Resource.getImageResource("reload.gif");
/**
* The newly created DynamicTreeBuilder records its parent node - the one for which it will build child nodes for.
* @param nodeClicked The Parent Tree Node that will be populated.
* @see NodeItem
* @see TreeDisplay*/
public DynamicTreeBuilder(DefaultMutableTreeNode parent) {
this.parent = parent;
loading = new DefaultMutableTreeNode(this);
}
/**
* Before the tree builder can execute, it needs to be given references to the tree and NodeFactory needed to create the new nodes.
* @param myNodeFactory The NodeFactory that can be queried for new NodeItems.
* @param parentTree The JTree in which this node is currently contained.
*/
public void buildInfo(JTree parentTree) {
this.treeModel = (DefaultTreeModel)parentTree.getModel();
}
public void start() {
// find the clicked tree node
Node parentNode = (Node)parent.getUserObject();
Logger.msg(2, "DynamicTreeBuilder.start() - Filling in children of '"+parentNode.toString()+"'");
if (state == IDLE)
parentNode.subscribeNode(this);
else
parentNode.loadMore();
state = LOADING;
}
/**
* Used by the JTree to find the text representation of the node.
*/
public String toString() {
switch (state) {
case IDLE:
return Language.translate("Initializing Tree Node Loader");
case LOADING:
return Language.translate("Loading . . .");
case PARTIAL:
return Language.translate("Double-click to load more");
case FINISHED:
return Language.translate("Done");
default:
return "";
}
}
public ImageIcon getIcon() {
if (state == LOADING)
return loadIcon;
else
return pauseIcon;
}
public DefaultMutableTreeNode getTreeNode() {
return loading;
}
public void add(Node newNode) {
Logger.msg(2, "DynamicTreeBuilder.add() - Received item for tree. Name: "+newNode);
// have we inserted the node yet?
SwingUtilities.invokeLater(new TreeAddThread(newNode));
}
class TreeAddThread implements Runnable {
Node newNode;
TreeAddThread(Node newNode) {
this.newNode = newNode;
}
public void run() {
boolean inserted = false;
DefaultMutableTreeNode newTreeNode = newNode.getTreeNode();
// loop though all children unless we have done the insertion
for (int i=0; i