package org.freeplane.core.ui.ribbon; import java.io.Serializable; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.NoSuchElementException; import java.util.Vector; import javax.swing.tree.TreeNode; public class WeightedMutableTreeNode<T> implements Cloneable, TreeNode, Serializable { private static final long serialVersionUID = -9105945271097923126L; public static final int FIRST = Integer.MIN_VALUE+100; public static final int PREPEND = Integer.MIN_VALUE+100000; public static final int APPEND = Integer.MAX_VALUE-100000; public static final int LAST = Integer.MAX_VALUE-100; private transient Comparator<WeightedMutableTreeNode<T>> comparator = new Comparator<WeightedMutableTreeNode<T>>() { public int compare(WeightedMutableTreeNode<T> n1, WeightedMutableTreeNode<T> n2) { if(n1.getWeight() > n2.getWeight()) { return 1; } else if(n1.getWeight() < n2.getWeight()) { return -1; } return 0; } }; public final Enumeration<WeightedMutableTreeNode<T>> EMPTY_ENUMERATION = new Enumeration<WeightedMutableTreeNode<T>>() { public boolean hasMoreElements() { return false; } public WeightedMutableTreeNode<T> nextElement() { throw new NoSuchElementException("No more elements"); } }; private Vector<WeightedMutableTreeNode<T>> children; protected transient T userObject; protected WeightedMutableTreeNode<T> parent; private final int weight; /*********************************************************************************** * CONSTRUCTORS **********************************************************************************/ public WeightedMutableTreeNode() { this(null); } public WeightedMutableTreeNode(T userObject) { this(userObject, APPEND); } public WeightedMutableTreeNode(int weight) { this(null, weight); } public WeightedMutableTreeNode(T userObject, int weight) { this.userObject = userObject; this.weight = weight; } /*********************************************************************************** * METHODS **********************************************************************************/ public void addChild(WeightedMutableTreeNode<T> newChild) { if (newChild == null) { throw new IllegalArgumentException("new child is null"); } else if (isNodeAncestor(newChild)) { throw new IllegalArgumentException("new child is an ancestor"); } WeightedMutableTreeNode<T> oldParent = newChild.getParent(); if (oldParent != null) { oldParent.remove(newChild); } newChild.setParent(this); if (children == null) { children = new Vector<WeightedMutableTreeNode<T>>(); } children.add(newChild); Collections.sort(children, comparator); } public void remove(int childIndex) { WeightedMutableTreeNode<T> child = getChildAt(childIndex); children.removeElementAt(childIndex); child.setParent(null); } public void remove(WeightedMutableTreeNode<T> aChild) { if (aChild == null) { throw new IllegalArgumentException("argument is null"); } if (!isNodeChild(aChild)) { throw new IllegalArgumentException("argument is not a child"); } remove(getIndex(aChild)); } public void removeAllChildren() { for (int i = getChildCount() - 1; i >= 0; i--) { remove(i); } } void setParent(WeightedMutableTreeNode<T> parent) { this.parent = parent; } public int getWeight() { return weight; } public boolean isNodeAncestor(WeightedMutableTreeNode<T> anotherNode) { if (anotherNode == null) { return false; } TreeNode ancestor = this; do { if (ancestor == anotherNode) { return true; } } while ((ancestor = ancestor.getParent()) != null); return false; } public boolean isNodeDescendant(WeightedMutableTreeNode<T> anotherNode) { if (anotherNode == null) { return false; } return anotherNode.isNodeAncestor(this); } public boolean isNodeChild(TreeNode aNode) { boolean retval; if (aNode == null) { retval = false; } else { if (getChildCount() == 0) { retval = false; } else { retval = (aNode.getParent() == this); } } return retval; } public T getUserObject() { return this.userObject; } public void setUserObject(T o) { this.userObject = o; } /*********************************************************************************** * REQUIRED METHODS FOR INTERFACES **********************************************************************************/ public WeightedMutableTreeNode<T> getChildAt(int childIndex) { if (children == null) { throw new ArrayIndexOutOfBoundsException("node has no children"); } return children.get(childIndex); } public int getChildCount() { return children == null ? 0 : children.size(); } public WeightedMutableTreeNode<T> getParent() { return parent; } public int getIndex(TreeNode aChild) { if (aChild == null) { throw new IllegalArgumentException("argument is null"); } if (!isNodeChild(aChild)) { return -1; } return children.indexOf(aChild); } public boolean getAllowsChildren() { return true; } public boolean isLeaf() { return (getChildCount() == 0); } public Enumeration<WeightedMutableTreeNode<T>> children() { if (children == null) { return EMPTY_ENUMERATION; } else { return children.elements(); } } /*********************************************************************************** * NESTED TYPE DECLARATION **********************************************************************************/ }