package net.vhati.modmanager.ui.tree;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* An implementation-agnostic model to pass between the GUI thread and the
* (de)serializer.
*/
public class TreeState {
protected TreeNodeState rootNodeState = null;
public TreeState() {
}
public void setRootNodeState( TreeNodeState rootNodeState ) {
this.rootNodeState = rootNodeState;
}
public TreeNodeState getRootNodeState() {
return rootNodeState;
}
public List<TreeNodeState> findNodeStates( TreeNodeStateFilter filter ) {
return findNodeStates( getRootNodeState(), filter );
}
/**
* Returns a list of descendant node states which match a given filter.
*/
public List<TreeNodeState> findNodeStates( TreeNodeState currentNodeState, TreeNodeStateFilter filter ) {
List<TreeNodeState> results = new ArrayList<TreeNodeState>( 1 );
collectNodeStates( currentNodeState, filter, results );
return results;
}
public boolean collectNodeStates( TreeNodeState currentNodeState, TreeNodeStateFilter filter, List<TreeNodeState> results ) {
int maxResultCount = filter.getMaxResultCount();
boolean found = false;
if ( filter.accept( currentNodeState ) ) {
results.add( currentNodeState );
if ( maxResultCount > 0 && maxResultCount >= results.size() ) return true;
}
if ( currentNodeState.getAllowsChildren() ) {
for ( Iterator<TreeNodeState> it = currentNodeState.children(); it.hasNext(); ) {
TreeNodeState childNodeState = it.next();
found = collectNodeStates( childNodeState, filter, results );
if ( found && maxResultCount > 0 && maxResultCount >= results.size() ) return true;
}
}
return found;
}
public boolean containsUserObject( Object o ) {
UserObjectTreeNodeStateFilter filter = new UserObjectTreeNodeStateFilter( o );
filter.setMaxResultCount( 1 );
List<TreeNodeState> results = findNodeStates( filter );
return ( !results.isEmpty() );
}
public static interface TreeNodeStateFilter {
public int getMaxResultCount();
public boolean accept( TreeNodeState nodeState );
}
public static class UserObjectTreeNodeStateFilter implements TreeNodeStateFilter {
private Class objectClass = null;
private Object o = null;
private int maxResultCount = 0;
/**
* Constructs a filter matching objects of a given class (or subclass).
*/
public UserObjectTreeNodeStateFilter( Class objectClass ) {
this.objectClass = objectClass;
}
/**
* Constructs a filter matching objects equal to a given object.
*/
public UserObjectTreeNodeStateFilter( Object o ) {
this.o = o;
}
public void setMaxResultCount( int n ) { maxResultCount = n; }
@Override
public int getMaxResultCount() { return maxResultCount; }
@Override
public boolean accept( TreeNodeState nodeState ) {
Object nodeObject = nodeState.getUserObject();
if ( objectClass != null && nodeObject != null ) {
return ( objectClass.isAssignableFrom( nodeObject.getClass() ) );
}
else if ( o != null ) {
return ( o.equals( nodeState.getUserObject() ) );
}
return false;
}
}
public static class TreeNodeState {
protected Object userObject = null;
protected boolean expand = false;
protected List<TreeNodeState> children = null;
private TreeNodeState parentNodeState = null;
public TreeNodeState() {
this( false, false );
}
public TreeNodeState( boolean allowsChildren, boolean expand ) {
if ( allowsChildren ) {
this.expand = expand;
children = new ArrayList<TreeNodeState>();
}
}
/**
* Sets this node's parent to newParent but does not change the
* parent's child array.
*/
public void setParent( TreeNodeState nodeState ) {
parentNodeState = nodeState;
}
public TreeNodeState getParent() {
return parentNodeState;
}
public boolean getAllowsChildren() {
return ( children != null );
}
public void addChild( TreeNodeState childNodeState ) {
TreeNodeState oldParent = childNodeState.getParent();
if ( oldParent != null ) oldParent.removeChild( childNodeState );
childNodeState.setParent( this );
children.add( childNodeState );
}
public void removeChild( TreeNodeState childNodeState ) {
children.remove( childNodeState );
childNodeState.setParent( null );
}
/**
* Returns an iterator over this node state's children.
*/
public Iterator<TreeNodeState> children() {
return children.iterator();
}
public void setUserObject( Object userObject ) {
this.userObject = userObject;
}
public Object getUserObject() {
return userObject;
}
}
}