From b086f57f56bf0eb9dab9cf321a0f69aaaae84347 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Wed, 30 May 2012 08:37:45 +0200 Subject: Initial Maven Conversion --- .../java/com/c2kernel/gui/DynamicTreeBuilder.java | 183 +++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 src/main/java/com/c2kernel/gui/DynamicTreeBuilder.java (limited to 'src/main/java/com/c2kernel/gui/DynamicTreeBuilder.java') diff --git a/src/main/java/com/c2kernel/gui/DynamicTreeBuilder.java b/src/main/java/com/c2kernel/gui/DynamicTreeBuilder.java new file mode 100644 index 0000000..050a76a --- /dev/null +++ b/src/main/java/com/c2kernel/gui/DynamicTreeBuilder.java @@ -0,0 +1,183 @@ +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.NodeItem; +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 final 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 final DefaultMutableTreeNode loading; + private static ImageIcon loadIcon = Resource.findImage("loading.gif"); + private static ImageIcon pauseIcon = Resource.findImage("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. + */ + @Override + 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; + } + + @Override + 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; + } + @Override + 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= 0) { + // if the next string is 'greater than' ours, insert the node before + treeModel.insertNodeInto(newTreeNode, parent, i); + inserted = true; + break; + } + + } + // if we haven't inserted yet, it must go at the end. + + if (!inserted) + treeModel.insertNodeInto(newTreeNode, parent, parent.getChildCount()); + } + + } + + class TreeRemoveThread implements Runnable { + DefaultMutableTreeNode oldNode; + TreeRemoveThread(DefaultMutableTreeNode oldNode) { + this.oldNode = oldNode; + } + + @Override + public void run() { + treeModel.removeNodeFromParent(oldNode); + } + } + + @Override + public void end(boolean more) { + if (more) { + state = PARTIAL; + } + else { + state = FINISHED; + synchronized(treeModel) { + if (loading.getParent() != null) + SwingUtilities.invokeLater(new TreeRemoveThread(loading)); + } + } + } + + @Override + public void remove(Path path) { + synchronized (treeModel) { + for (int i=0; i