Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / javax / swing / tree / DefaultMutableTreeNode.java
blobd9747729317fecc12cf9d1c3eb794d431d37abf8
1 /* DefaultMutableTreeNode.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing.tree;
41 import gnu.java.util.EmptyEnumeration;
43 import java.io.IOException;
44 import java.io.ObjectInputStream;
45 import java.io.ObjectOutputStream;
46 import java.io.Serializable;
47 import java.util.ArrayList;
48 import java.util.Enumeration;
49 import java.util.LinkedList;
50 import java.util.NoSuchElementException;
51 import java.util.Stack;
52 import java.util.Vector;
55 /**
56 * DefaultMutableTreeNode
58 * @author Andrew Selkirk
59 * @author Robert Schuster (robertschuster@fsfe.org)
61 public class DefaultMutableTreeNode
62 implements Cloneable, MutableTreeNode, Serializable
64 private static final long serialVersionUID = -4298474751201349152L;
66 /**
67 * EMPTY_ENUMERATION
69 public static final Enumeration EMPTY_ENUMERATION =
70 EmptyEnumeration.getInstance();
72 /**
73 * parent
75 protected MutableTreeNode parent;
77 /**
78 * children
80 protected Vector children = new Vector();
82 /**
83 * userObject
85 protected transient Object userObject;
87 /**
88 * allowsChildren
90 protected boolean allowsChildren;
92 /**
93 * Creates a <code>DefaultMutableTreeNode</code> object.
94 * This node allows to add child nodes.
96 public DefaultMutableTreeNode()
98 this(null, true);
102 * Creates a <code>DefaultMutableTreeNode</code> object with the given
103 * user object attached to it. This node allows to add child nodes.
105 * @param userObject the user object
107 public DefaultMutableTreeNode(Object userObject)
109 this(userObject, true);
113 * Creates a <code>DefaultMutableTreeNode</code> object with the given
114 * user object attached to it.
116 * @param userObject the user object
117 * @param allowsChildren <code>true</code> if the code allows to add child
118 * nodes, <code>false</code> otherwise
120 public DefaultMutableTreeNode(Object userObject, boolean allowsChildren)
122 this.userObject = userObject;
123 this.allowsChildren = allowsChildren;
127 * clone
129 * @return Object
131 public Object clone()
135 return super.clone();
136 // TODO: Do we need to do more here ?
138 catch (CloneNotSupportedException e)
140 // This never happens.
141 return null;
146 * Returns a string representation of this node
148 * @return a human-readable String representing this node
150 public String toString()
152 if (userObject == null)
153 return null;
155 return userObject.toString();
159 * Adds a new child node to this node.
161 * @param child the child node
163 * @throws IllegalArgumentException if <code>child</code> is null
164 * @throws IllegalStateException if the node does not allow children
166 public void add(MutableTreeNode child)
168 if (child == null)
169 throw new IllegalArgumentException();
171 if (! allowsChildren)
172 throw new IllegalStateException();
174 children.add(child);
175 child.setParent(this);
179 * Returns the parent node of this node.
181 * @return the parent node
183 public TreeNode getParent()
185 return parent;
189 * Removes the child with the given index from this node
191 * @param index the index
193 public void remove(int index)
195 children.remove(index);
199 * Removes the given child from this node.
201 * @param node the child node
203 public void remove(MutableTreeNode node)
205 children.remove(node);
209 * writeObject
211 * @param stream the output stream
213 * @exception IOException If an error occurs
215 private void writeObject(ObjectOutputStream stream)
216 throws IOException
218 // TODO: Implement me.
222 * readObject
224 * @param stream the input stream
226 * @exception IOException If an error occurs
227 * @exception ClassNotFoundException TODO
229 private void readObject(ObjectInputStream stream)
230 throws IOException, ClassNotFoundException
232 // TODO: Implement me.
236 * Inserts given child node at the given index.
238 * @param node the child node
239 * @param index the index.
241 public void insert(MutableTreeNode node, int index)
243 children.insertElementAt(node, index);
247 * Returns a path to this node from the root.
249 * @return an array of tree nodes
251 public TreeNode[] getPath()
253 return getPathToRoot(this, 0);
257 * Returns an enumeration containing all children of this node.
258 * <code>EMPTY_ENUMERATION</code> is returned if this node has no children.
260 * @return an enumeration of tree nodes
262 public Enumeration children()
264 if (children.size() == 0)
265 return EMPTY_ENUMERATION;
267 return children.elements();
271 * Set the parent node for this node.
273 * @param node the parent node
275 public void setParent(MutableTreeNode node)
277 parent = node;
281 * Returns the child node at a given index.
283 * @param index the index
285 * @return the child node
287 public TreeNode getChildAt(int index)
289 return (TreeNode) children.elementAt(index);
293 * Returns the number of children of this node.
295 * @return the number of children
297 public int getChildCount()
299 return children.size();
303 * Returns the child index for a given node.
305 * @param node this node
307 * @return the index
309 public int getIndex(TreeNode node)
311 return children.indexOf(node);
315 * setAllowsChildren
317 * @param allowsChildren TODO
319 public void setAllowsChildren(boolean allowsChildren)
321 this.allowsChildren = allowsChildren;
325 * getAllowsChildren
327 * @return boolean
329 public boolean getAllowsChildren()
331 return allowsChildren;
335 * Sets the user object for this node
337 * @param userObject the user object
339 public void setUserObject(Object userObject)
341 this.userObject = userObject;
345 * Returns the user object attached to this node. <code>null</code> is
346 * returned when no user object is set.
348 * @return the user object
350 public Object getUserObject()
352 return userObject;
356 * Removes this node from its parent.
358 public void removeFromParent()
360 parent.remove(this);
361 parent = null;
365 * Removes all child nodes from this node.
367 public void removeAllChildren()
369 children.removeAllElements();
373 * isNodeAncestor
375 * @param node TODO
377 * @return boolean
379 public boolean isNodeAncestor(TreeNode node)
381 if (node == null)
382 return false;
384 TreeNode current = this;
386 while (current != null
387 && current != node)
388 current = current.getParent();
390 return current == node;
394 * isNodeDescendant
396 * @param node TODO
398 * @return boolean
400 public boolean isNodeDescendant(DefaultMutableTreeNode node)
402 if (node == null)
403 return false;
405 TreeNode current = node;
407 while (current != null
408 && current != this)
409 current = current.getParent();
411 return current == this;
415 * getSharedAncestor
417 * @param node TODO
419 * @return TreeNode
421 public TreeNode getSharedAncestor(DefaultMutableTreeNode node)
423 TreeNode current = this;
424 ArrayList list = new ArrayList();
426 while (current != null)
428 list.add(current);
429 current = current.getParent();
432 current = node;
434 while (current != null)
436 if (list.contains(current))
437 return current;
439 current = current.getParent();
442 return null;
446 * isNodeRelated
448 * @param node TODO
450 * @return boolean
452 public boolean isNodeRelated(DefaultMutableTreeNode node)
454 if (node == null)
455 return false;
457 return node.getRoot() == getRoot();
461 * getDepth
463 * @return int
465 public int getDepth()
467 if ((! allowsChildren)
468 || children.size() == 0)
469 return 0;
471 Stack stack = new Stack();
472 stack.push(new Integer(0));
473 TreeNode node = getChildAt(0);
474 int depth = 0;
475 int current = 1;
477 while (! stack.empty())
479 if (node.getChildCount() != 0)
481 node = node.getChildAt(0);
482 stack.push(new Integer(0));
483 current++;
485 else
487 if (current > depth)
488 depth = current;
490 int size;
491 int index;
495 node = node.getParent();
496 size = node.getChildCount();
497 index = ((Integer) stack.pop()).intValue() + 1;
498 current--;
500 while (index >= size
501 && node != this);
503 if (index < size)
505 node = node.getChildAt(index);
506 stack.push(new Integer(index));
507 current++;
512 return depth;
516 * getLevel
518 * @return int
520 public int getLevel()
522 int count = -1;
523 TreeNode current = this;
527 current = current.getParent();
528 count++;
530 while (current != null);
532 return count;
536 * getPathToRoot
538 * @param node TODO
539 * @param depth TODO
541 * @return TreeNode[]
543 protected TreeNode[] getPathToRoot(TreeNode node, int depth)
545 if (node == null)
547 if (depth == 0)
548 return null;
550 return new TreeNode[depth];
553 TreeNode[] path = getPathToRoot(node.getParent(), depth + 1);
554 path[path.length - depth - 1] = node;
555 return path;
559 * getUserObjectPath
561 * @return Object[]
563 public Object[] getUserObjectPath()
565 TreeNode[] path = getPathToRoot(this, 0);
566 Object[] object = new Object[path.length];
568 for (int index = 0; index < path.length; ++index)
569 object[index] = ((DefaultMutableTreeNode) path[index]).getUserObject();
571 return object;
575 * Returns the root node by iterating the parents of this node.
577 * @return the root node
579 public TreeNode getRoot()
581 TreeNode current = this;
582 TreeNode check = current.getParent();
584 while (check != null)
586 current = check;
587 check = current.getParent();
590 return current;
594 * Tells whether this node is the root node or not.
596 * @return <code>true</code> if this is the root node,
597 * <code>false</code>otherwise
599 public boolean isRoot()
601 return parent == null;
605 * getNextNode
607 * @return DefaultMutableTreeNode
609 public DefaultMutableTreeNode getNextNode()
611 // Return first child.
612 if (getChildCount() != 0)
613 return (DefaultMutableTreeNode) getChildAt(0);
615 // Return next sibling (if needed the sibling of some parent).
616 DefaultMutableTreeNode node = this;
617 DefaultMutableTreeNode sibling;
621 sibling = node.getNextSibling();
622 node = (DefaultMutableTreeNode) node.getParent();
624 while (sibling == null &&
625 node != null);
627 // Return sibling.
628 return sibling;
632 * getPreviousNode
634 * @return DefaultMutableTreeNode
636 public DefaultMutableTreeNode getPreviousNode()
638 // Return null if no parent.
639 if (parent == null)
640 return null;
642 DefaultMutableTreeNode sibling = getPreviousSibling();
644 // Return parent if no sibling.
645 if (sibling == null)
646 return (DefaultMutableTreeNode) parent;
648 // Return last leaf of sibling.
649 if (sibling.getChildCount() != 0)
650 return sibling.getLastLeaf();
652 // Return sibling.
653 return sibling;
657 * preorderEnumeration
659 * @return Enumeration
661 public Enumeration preorderEnumeration()
663 return new PreorderEnumeration(this);
667 * postorderEnumeration
669 * @return Enumeration
671 public Enumeration postorderEnumeration()
673 return new PostorderEnumeration(this);
677 * breadthFirstEnumeration
679 * @return Enumeration
681 public Enumeration breadthFirstEnumeration()
683 return new BreadthFirstEnumeration(this);
687 * depthFirstEnumeration
689 * @return Enumeration
691 public Enumeration depthFirstEnumeration()
693 return postorderEnumeration();
697 * pathFromAncestorEnumeration
699 * @param node TODO
701 * @return Enumeration
703 public Enumeration pathFromAncestorEnumeration(TreeNode node)
705 if (node == null)
706 throw new IllegalArgumentException();
708 TreeNode parent = this;
709 Vector nodes = new Vector();
710 nodes.add(this);
712 while (parent != node && parent != null)
714 parent = parent.getParent();
715 nodes.add(0, parent);
718 if (parent != node)
719 throw new IllegalArgumentException();
721 return nodes.elements();
725 * isNodeChild
727 * @param node TODO
729 * @return boolean
731 public boolean isNodeChild(TreeNode node)
733 if (node == null)
734 return false;
736 return node.getParent() == this;
740 * getFirstChild
742 * @return TreeNode
744 public TreeNode getFirstChild()
746 return (TreeNode) children.firstElement();
750 * getLastChild
752 * @return TreeNode
754 public TreeNode getLastChild()
756 return (TreeNode) children.lastElement();
760 * getChildAfter
762 * @param node TODO
764 * @return TreeNode
766 public TreeNode getChildAfter(TreeNode node)
768 if (node == null
769 || node.getParent() != this)
770 throw new IllegalArgumentException();
772 int index = getIndex(node) + 1;
774 if (index == getChildCount())
775 return null;
777 return getChildAt(index);
781 * getChildBefore
783 * @param node TODO
785 * @return TreeNode
787 public TreeNode getChildBefore(TreeNode node)
789 if (node == null
790 || node.getParent() != this)
791 throw new IllegalArgumentException();
793 int index = getIndex(node) - 1;
795 if (index < 0)
796 return null;
798 return getChildAt(index);
802 * isNodeSibling
804 * @param node TODO
806 * @return boolean
808 public boolean isNodeSibling(TreeNode node)
810 if (node == null)
811 return false;
813 return (node.getParent() == getParent()
814 && getParent() != null);
818 * getSiblingCount
820 * @return int
822 public int getSiblingCount()
824 if (parent == null)
825 return 1;
827 return parent.getChildCount();
831 * getNextSibling
833 * @return DefaultMutableTreeNode
835 public DefaultMutableTreeNode getNextSibling()
837 if (parent == null)
838 return null;
840 int index = parent.getIndex(this) + 1;
842 if (index == parent.getChildCount())
843 return null;
845 return (DefaultMutableTreeNode) parent.getChildAt(index);
849 * getPreviousSibling
851 * @return DefaultMutableTreeNode
853 public DefaultMutableTreeNode getPreviousSibling()
855 if (parent == null)
856 return null;
858 int index = parent.getIndex(this) - 1;
860 if (index < 0)
861 return null;
863 return (DefaultMutableTreeNode) parent.getChildAt(index);
867 * isLeaf
869 * @return boolean
871 public boolean isLeaf()
873 return children.size() == 0;
877 * getFirstLeaf
879 * @return DefaultMutableTreeNode
881 public DefaultMutableTreeNode getFirstLeaf()
883 TreeNode current = this;
885 while (current.getChildCount() > 0)
886 current = current.getChildAt(0);
888 return (DefaultMutableTreeNode) current;
892 * getLastLeaf
894 * @return DefaultMutableTreeNode
896 public DefaultMutableTreeNode getLastLeaf()
898 TreeNode current = this;
899 int size = current.getChildCount();
901 while (size > 0)
903 current = current.getChildAt(size - 1);
904 size = current.getChildCount();
907 return (DefaultMutableTreeNode) current;
911 * getNextLeaf
913 * @return DefaultMutableTreeNode
915 public DefaultMutableTreeNode getNextLeaf()
917 if (parent == null)
918 return null;
920 // TODO: Fix implementation.
921 return null;
922 //return parent.getChildAfter(this);
926 * getPreviousLeaf
928 * @return DefaultMutableTreeNode
930 public DefaultMutableTreeNode getPreviousLeaf()
932 if (parent == null)
933 return null;
935 // TODO: Fix implementation.
936 return null;
937 //return parent.getChildBefore(this);
941 * getLeafCount
943 * @return int
945 public int getLeafCount()
947 int count = 0;
948 Enumeration e = depthFirstEnumeration();
950 while (e.hasMoreElements())
952 TreeNode current = (TreeNode) e.nextElement();
954 if (current.isLeaf())
955 count++;
958 return count;
961 /** Provides an enumeration of a tree in breadth-first traversal
962 * order.
964 static class BreadthFirstEnumeration implements Enumeration
967 LinkedList queue = new LinkedList();
969 BreadthFirstEnumeration(TreeNode node)
971 queue.add(node);
974 public boolean hasMoreElements()
976 return !queue.isEmpty();
979 public Object nextElement()
981 if(queue.isEmpty())
982 throw new NoSuchElementException("No more elements left.");
984 TreeNode node = (TreeNode) queue.removeFirst();
986 Enumeration children = node.children();
987 while (children.hasMoreElements())
988 queue.add(children.nextElement());
990 return node;
994 /** Provides an enumeration of a tree traversing it
995 * preordered.
997 static class PreorderEnumeration implements Enumeration
999 TreeNode next;
1001 Stack childrenEnums = new Stack();
1003 PreorderEnumeration(TreeNode node)
1005 next = node;
1006 childrenEnums.push(node.children());
1009 public boolean hasMoreElements()
1011 return next != null;
1014 public Object nextElement()
1016 if( next == null )
1017 throw new NoSuchElementException("No more elements left.");
1019 Object current = next;
1021 Enumeration children = (Enumeration) childrenEnums.peek();
1023 // Retrieves the next element.
1024 next = traverse(children);
1026 return current;
1029 private TreeNode traverse(Enumeration children)
1031 // If more children are available step down.
1032 if( children.hasMoreElements() )
1034 TreeNode child = (TreeNode) children.nextElement();
1035 childrenEnums.push(child.children());
1037 return child;
1040 // If no children are left, we return to a higher level.
1041 childrenEnums.pop();
1043 // If there are no more levels left, there is no next
1044 // element to return.
1045 if ( childrenEnums.isEmpty() )
1046 return null;
1047 else
1049 return traverse((Enumeration) childrenEnums.peek());
1054 /** Provides an enumeration of a tree traversing it
1055 * postordered (= depth-first).
1057 static class PostorderEnumeration implements Enumeration
1060 Stack nodes = new Stack();
1061 Stack childrenEnums = new Stack();
1063 PostorderEnumeration(TreeNode node)
1065 nodes.push(node);
1066 childrenEnums.push(node.children());
1069 public boolean hasMoreElements()
1071 return !nodes.isEmpty();
1074 public Object nextElement()
1076 if( nodes.isEmpty() )
1077 throw new NoSuchElementException("No more elements left!");
1079 Enumeration children = (Enumeration) childrenEnums.peek();
1081 return traverse(children);
1084 private Object traverse(Enumeration children)
1086 if ( children.hasMoreElements() )
1088 TreeNode node = (TreeNode) children.nextElement();
1089 nodes.push(node);
1091 Enumeration newChildren = node.children();
1092 childrenEnums.push(newChildren);
1094 return traverse(newChildren);
1096 else
1098 childrenEnums.pop();
1100 // Returns the node whose children
1101 // have all been visited. (= postorder)
1102 Object next = nodes.peek();
1103 nodes.pop();
1105 return next;