org.jdesktop.swingx.tree.TreeUtilities Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swingx-all Show documentation
Show all versions of swingx-all Show documentation
Fork of the inactive swingx-all library
package org.jdesktop.swingx.tree;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.Enumeration;
import java.util.List;
import java.util.Queue;
/**
* Contains convenience classes/methods for handling hierarchical Swing structures.
*
* @author Jeanette Winzenburg, Berlin
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class TreeUtilities {
/**
* An enumeration that is always empty.
*/
public static final Enumeration EMPTY_ENUMERATION = Collections.emptyEnumeration();
/**
* Implementation of a preorder traversal of a TreeModel.
*/
public static class PreorderModelEnumeration implements Enumeration {
protected Deque stack;
protected TreeModel model;
// the last component is the current subtree to travers
private TreePath path;
/**
* Instantiates a preorder traversal starting from the root of the
* TreeModel.
*
* @param model the TreeModel to travers.
*/
public PreorderModelEnumeration(TreeModel model) {
this(model, model.getRoot());
}
/**
* Instantiates a preorder traversal of the TreeModel which
* starts at the given node. It iterates over all nodes of the
* subtree, only.
*
* @param model the TreeModel to travers.
* @param node the node to start
*/
public PreorderModelEnumeration(TreeModel model, Object node) {
this.model = model;
stack = new ArrayDeque<>();
pushNodeAsEnumeration(node);
}
/**
* Instantiates a preorder traversal of the TreeModel which starts at the
* last path component of the given TreePath. It iterates over all nodes
* of the subtree and all of its siblings, with the same end as a traversal
* starting at the model's roolt would have.
*
* @param model the TreeModel to travers.
* @param path the TreePath to start from
*/
public PreorderModelEnumeration(TreeModel model, TreePath path) {
this(model, path.getLastPathComponent());
this.path = path;
}
@Override
public boolean hasMoreElements() {
return !stack.isEmpty() && stack.peek().hasMoreElements();
}
@Override
public Object nextElement() {
Enumeration enumer = stack.peek();
Object node = enumer.nextElement();
Enumeration children = children(model, node);
if (!enumer.hasMoreElements()) {
stack.pop();
}
if (children.hasMoreElements()) {
stack.push(children);
}
if (!hasMoreElements()) {
// check if there are more subtrees to travers
// and update internal state accordingly
updateSubtree();
}
return node;
}
/**
*
*/
private void updateSubtree() {
if (path == null)
return;
TreePath parentPath = path.getParentPath();
if (parentPath == null) {
// root
path = null;
return;
}
Object parent = parentPath.getLastPathComponent();
Object currentNode = path.getLastPathComponent();
int currentIndex = model.getIndexOfChild(parent, currentNode);
if (currentIndex + 1 < model.getChildCount(parent)) {
// use sibling
Object child = model.getChild(parent, currentIndex + 1);
path = parentPath.pathByAddingChild(child);
pushNodeAsEnumeration(child);
} else {
path = parentPath;
// up one level
updateSubtree();
}
}
private void pushNodeAsEnumeration(Object node) {
// single element enum
List