All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.javagimmicks.swing.model.ListTreeNode Maven / Gradle / Ivy

The newest version!
package net.sf.javagimmicks.swing.model;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import javax.swing.tree.TreeNode;

public class ListTreeNode implements TreeNode
{
	protected ArrayList> _children;
	protected ChildrenListView _childrenListView;
	protected ChildrenValueListView _childrenValueListView;
	
	protected ListTreeModel _model;
	protected ListTreeNode _parent;
	protected E _value;
	
	public ListTreeNode(E value, boolean leaf)
	{
		this(null, null, leaf, value);
	}
	
	protected ListTreeNode(ListTreeModel model, boolean leaf, E value)
	{
		this(model, null, leaf, value);
	}
	
	protected ListTreeNode(ListTreeNode parent, boolean leaf, E value)
	{
		this(parent._model, parent, leaf, value);
	}
	
	private ListTreeNode(ListTreeModel model, ListTreeNode parent, boolean leaf, E value)
	{
		_model = model;
		_parent = parent;
		setLeaf(leaf);
		_value = value;
		
		_childrenListView = new ChildrenListView();
		_childrenValueListView = new ChildrenValueListView();
	}
	
	public ListTreeNode addChildAt(int index, E value, boolean leaf)
	{
      ListTreeNode result = new ListTreeNode(value, leaf);
      getChildListView().add(index, result);
      
      return result;
	}
	
   public ListTreeNode addChildAt(int index, E value)
   {
      return addChildAt(index, value, false);
   }
	
	public ListTreeNode addChild(E value, boolean leaf)
	{
	   return addChildAt(getChildCount(), value, leaf);
	}
	
   public ListTreeNode addChild(E value)
   {
      return addChild(value, false);
   }
   
   public ListTreeNode removeChildAt(int index)
   {
      return getChildListView().remove(index);
   }
   
	public List> getChildListView()
	{
		return _childrenListView;
	}
	
	public List getChildValueListView()
	{
		return _childrenValueListView;
	}
	
	public E getValue()
	{
		return _value;
	}
	
	public void setValue(E value)
	{
		_value = value;
		
		if(_model != null)
		{
			_model.fireNodeChanged(_parent, _parent == null ? 0 : _parent._childrenListView.indexOf(this));
		}
	}
	
	public void setLeaf(boolean leaf)
	{
		if(isLeaf() == leaf)
		{
			return;
		}
		
		if(!leaf)
		{
			_children = new ArrayList>();
		}
		else if(_children.isEmpty())
		{
			_children = null;
		}
		else
		{
			throw new IllegalStateException("Node still has children. Remove them before setting the node to leaf mode.");
		}
	}

	@SuppressWarnings("unchecked")
	public Enumeration> children()
	{
		return Collections.enumeration(isLeaf() ? Collections.EMPTY_LIST : _children);
	}

	public boolean getAllowsChildren()
	{
		return !isLeaf();
	}

	public ListTreeNode getChildAt(int childIndex)
	{
		if(!getAllowsChildren())
		{
			throw new ArrayIndexOutOfBoundsException("Node allows no children!");
		}
		
		return _children.get(childIndex);
	}

	public int getChildCount()
	{
		return isLeaf() ? 0 : _children.size();
	}

	public int getIndex(TreeNode node)
	{
		return getAllowsChildren() ? _children.indexOf(node) : -1;
	}

	public ListTreeNode getParent()
	{
		return _parent;
	}

	public boolean isLeaf()
	{
		return _children == null;
	}
	
	public void detach()
	{
		if(_parent == null && _model == null)
		{
			throw new IllegalStateException("This node cannot be detached. It has no parent and is not a root node!");
		}
		
		if(_parent != null)
		{
			_parent._childrenListView.remove(this);
		}
		else if(_model != null)
		{
			updateModel(null);
			_model.fireNodesRemoved(null, 0, Collections.singleton(this));
		}
	}
	
	public String toString()
	{
		return _value == null ? null : _value.toString();
	}
	
	protected void updateModel(ListTreeModel model)
	{
		_model = model;
		
		if(!isLeaf())
		{
			for(ListTreeNode child : _children)
			{
				child.updateModel(model);
			}
		}
	}
	
	protected class ChildrenListView extends AbstractList>
	{
		public boolean addAll(int index, Collection> c)
		{
			checkLeaf();
			
			for(ListTreeNode newChild : c)
			{
				if(newChild._model != null)
				{
					throw new IllegalArgumentException("Cannot add a node which already belongs to a model!");
				}
				else if(newChild._parent != null)
				{
					throw new IllegalArgumentException("Cannot add a non-detached node!");
				}
				
				newChild._parent = ListTreeNode.this;
				newChild.updateModel(_model);
			}

			_children.addAll(index, c);
			
			if(_model != null)
			{
				_model.fireNodesInserted(ListTreeNode.this, index, c);
			}
			
			return true;
		}

		public boolean addAll(Collection> c)
		{
			return addAll(_children.size(), c);
		}

		public void add(int index, ListTreeNode element)
		{
			addAll(index, Collections.singleton(element));
		}

		public void clear()
		{
			checkLeaf();

			clear(true);
		}
		
		private void clear(boolean isTop)
		{
			if(isLeaf())
			{
				return;
			}
			
			for(ListTreeNode newChild : _children)
			{
				newChild._childrenListView.clear(false);

				newChild._model = null;
				newChild._parent = null;
			}

			
			if(isTop && _model != null)
			{
				ArrayList> oldChildren = new ArrayList>(_children);
				_children.clear();

				_model.fireNodesRemoved(ListTreeNode.this, 0, oldChildren);
			}
			else
			{
				_children.clear();
			}
		}

		public ListTreeNode get(int index)
		{
			checkLeaf();

			return _children.get(index);
		}

		public ListTreeNode remove(int index)
		{
			checkLeaf();

			ListTreeNode removedNode = _children.remove(index);
			removedNode.updateModel(null);
			removedNode._parent = null;
			
			if(_model != null)
			{
				_model.fireNodesRemoved(ListTreeNode.this, index, Collections.singleton(removedNode));
			}
			
			return removedNode;
		}

		public ListTreeNode set(int index, ListTreeNode element)
		{
			checkLeaf();
			
			ListTreeNode result = _children.set(index, element);
			
			if(_model != null)
			{
				_model.fireNodeChanged(ListTreeNode.this, index);
			}
			
			return result;
		}

		public int size()
		{
			if(isLeaf())
			{
				return 0;
			}

			return _children.size();
		}
		
		private void checkLeaf()
		{
			if(isLeaf())
			{
				throw new UnsupportedOperationException("Node is a leaf!");
			}
		}
	}

	protected class ChildrenValueListView extends AbstractList
	{
		public void add(int index, E element)
		{
			ListTreeNode newNode = new ListTreeNode(element, false);
			_childrenListView.add(index, newNode);
		}

		public boolean addAll(Collection c)
		{
			return addAll(_childrenListView.size(), c);
		}

		public boolean addAll(int index, Collection c)
		{
		    ArrayList> newNodeCollection = new ArrayList>(c.size());
            for(E element : c)
            {
                newNodeCollection.add(new ListTreeNode(element, false));
            }
            
			return _childrenListView.addAll(index, newNodeCollection);
		}
		
		public void clear()
		{
			_childrenListView.clear();
		}

		public E get(int index)
		{
			return _childrenListView.get(index).getValue();
		}

		public E remove(int index)
		{
			return _childrenListView.remove(index).getValue();
		}

		public E set(int index, E element)
		{
			ListTreeNode childNode = _childrenListView.get(index);
			
			E oldValue = childNode.getValue();
			
			childNode.setValue(element);
			
			return oldValue;
		}

		public int size()
		{
			return _childrenListView.size();
		}

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy