Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / swing / tree / DefaultMutableTreeNode.java
blobde34ee07250213e1e7e2e5fdd1f30849812e6178
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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.Stack;
50 import java.util.Vector;
52 /**
53 * DefaultMutableTreeNode
55 * @author Andrew Selkirk
57 public class DefaultMutableTreeNode
58 implements Cloneable, MutableTreeNode, Serializable
60 private static final long serialVersionUID = -4298474751201349152L;
62 /**
63 * EMPTY_ENUMERATION
65 public static final Enumeration EMPTY_ENUMERATION =
66 EmptyEnumeration.getInstance();
68 /**
69 * parent
71 protected MutableTreeNode parent;
73 /**
74 * children
76 protected Vector children = new Vector();
78 /**
79 * userObject
81 protected transient Object userObject;
83 /**
84 * allowsChildren
86 protected boolean allowsChildren;
88 /**
89 * Creates a <code>DefaultMutableTreeNode</code> object.
90 * This node allows to add child nodes.
92 public DefaultMutableTreeNode()
94 this(null, true);
97 /**
98 * Creates a <code>DefaultMutableTreeNode</code> object with the given
99 * user object attached to it. This node allows to add child nodes.
101 * @param userObject the user object
103 public DefaultMutableTreeNode(Object userObject)
105 this(userObject, true);
109 * Creates a <code>DefaultMutableTreeNode</code> object with the given
110 * user object attached to it.
112 * @param userObject the user object
113 * @param allowsChildren <code>true</code> if the code allows to add child
114 * nodes, <code>false</code> otherwise
116 public DefaultMutableTreeNode(Object userObject, boolean allowsChildren)
118 this.userObject = userObject;
119 this.allowsChildren = allowsChildren;
123 * clone
125 * @return Object
127 public Object clone()
131 return super.clone();
132 // TODO: Do we need to do more here ?
134 catch (CloneNotSupportedException e)
136 // This never happens.
137 return null;
142 * Returns a string representation of this node
144 * @return a human-readable String representing this node
146 public String toString()
148 if (userObject == null)
149 return null;
151 return userObject.toString();
155 * Adds a new child node to this node.
157 * @param child the child node
159 * @throws IllegalArgumentException if <code>child</code> is null
160 * @throws IllegalStateException if the node does not allow children
162 public void add(MutableTreeNode child)
164 if (child == null)
165 throw new IllegalArgumentException();
167 if (! allowsChildren)
168 throw new IllegalStateException();
170 children.add(child);
171 child.setParent(this);
175 * Returns the parent node of this node.
177 * @return the parent node
179 public TreeNode getParent()
181 return parent;
185 * Removes the child with the given index from this node
187 * @param index the index
189 public void remove(int index)
191 children.remove(index);
195 * Removes the given child from this node.
197 * @param node the child node
199 public void remove(MutableTreeNode node)
201 children.remove(node);
205 * writeObject
207 * @param stream the output stream
209 * @exception IOException If an error occurs
211 private void writeObject(ObjectOutputStream stream)
212 throws IOException
214 // TODO: Implement me.
218 * readObject
220 * @param stream the input stream
222 * @exception IOException If an error occurs
223 * @exception ClassNotFoundException TODO
225 private void readObject(ObjectInputStream stream)
226 throws IOException, ClassNotFoundException
228 // TODO: Implement me.
232 * Inserts given child node at the given index.
234 * @param node the child node
235 * @param value the index.
237 public void insert(MutableTreeNode node, int index)
239 children.insertElementAt(node, index);
243 * Returns a path to this node from the root.
245 * @return an array of tree nodes
247 public TreeNode[] getPath()
249 return getPathToRoot(this, 0);
253 * Returns an enumeration containing all children of this node.
254 * <code>EMPTY_ENUMERATION</code> is returned if this node has no children.
256 * @return an enumeration of tree nodes
258 public Enumeration children()
260 if (children.size() == 0)
261 return EMPTY_ENUMERATION;
263 return children.elements();
267 * Set the parent node for this node.
269 * @param node the parent node
271 public void setParent(MutableTreeNode node)
273 parent = node;
277 * Returns the child node at a given index.
279 * @param index the index
281 * @return the child node
283 public TreeNode getChildAt(int index)
285 return (TreeNode) children.elementAt(index);
289 * Returns the number of children of this node.
291 * @return the number of children
293 public int getChildCount()
295 return children.size();
299 * Returns the child index for a given node.
301 * @param node this node
303 * @return the index
305 public int getIndex(TreeNode node)
307 return children.indexOf(node);
311 * setAllowsChildren
313 * @param allowsChildren TODO
315 public void setAllowsChildren(boolean allowsChildren)
317 this.allowsChildren = allowsChildren;
321 * getAllowsChildren
323 * @return boolean
325 public boolean getAllowsChildren()
327 return allowsChildren;
331 * Sets the user object for this node
333 * @param userObject the user object
335 public void setUserObject(Object userObject)
337 this.userObject = userObject;
341 * Returns the user object attached to this node. <code>null</code> is
342 * returned when no user object is set.
344 * @return the user object
346 public Object getUserObject()
348 return userObject;
352 * Removes this node from its parent.
354 public void removeFromParent()
356 // FIXME: IS this implementation really correct ?
357 parent = null;
361 * Removes all child nodes from this node.
363 public void removeAllChildren()
365 children.removeAllElements();
369 * isNodeAncestor
371 * @param node TODO
373 * @return boolean
375 public boolean isNodeAncestor(TreeNode node)
377 if (node == null)
378 return false;
380 TreeNode current = this;
382 while (current != null
383 && current != node)
384 current = current.getParent();
386 return current == node;
390 * isNodeDescendant
392 * @param node0 TODO
394 * @return boolean
396 public boolean isNodeDescendant(DefaultMutableTreeNode node)
398 if (node == null)
399 return false;
401 TreeNode current = node;
403 while (current != null
404 && current != this)
405 current = current.getParent();
407 return current == this;
411 * getSharedAncestor
413 * @param node TODO
415 * @return TreeNode
417 public TreeNode getSharedAncestor(DefaultMutableTreeNode node)
419 TreeNode current = this;
420 ArrayList list = new ArrayList();
422 while (current != null)
424 list.add(current);
425 current = current.getParent();
428 current = node;
430 while (current != null)
432 if (list.contains(current))
433 return current;
435 current = current.getParent();
438 return null;
442 * isNodeRelated
444 * @param node TODO
446 * @return boolean
448 public boolean isNodeRelated(DefaultMutableTreeNode node)
450 if (node == null)
451 return false;
453 return node.getRoot() == getRoot();
457 * getDepth
459 * @return int
461 public int getDepth()
463 if ((! allowsChildren)
464 || children.size() == 0)
465 return 0;
467 Stack stack = new Stack();
468 stack.push(new Integer(0));
469 TreeNode node = getChildAt(0);
470 int depth = 0;
471 int current = 1;
473 while (! stack.empty())
475 if (node.getChildCount() != 0)
477 node = node.getChildAt(0);
478 stack.push(new Integer(0));
479 current++;
481 else
483 if (current > depth)
484 depth = current;
486 int size;
487 int index;
491 node = node.getParent();
492 size = node.getChildCount();
493 index = ((Integer) stack.pop()).intValue() + 1;
494 current--;
496 while (index >= size
497 && node != this);
499 if (index < size)
501 node = node.getChildAt(index);
502 stack.push(new Integer(index));
503 current++;
508 return depth;
512 * getLevel
514 * @return int
516 public int getLevel()
518 int count = -1;
519 TreeNode current = this;
523 current = current.getParent();
524 count++;
526 while (current != null);
528 return count;
532 * getPathToRoot
534 * @param node TODO
535 * @param depth TODO
537 * @return TreeNode[]
539 protected TreeNode[] getPathToRoot(TreeNode node, int depth)
541 if (node == null)
543 if (depth == 0)
544 return null;
546 return new TreeNode[depth];
549 TreeNode[] path = getPathToRoot(node.getParent(), depth + 1);
550 path[path.length - depth - 1] = node;
551 return path;
555 * getUserObjectPath
557 * @return Object[]
559 public Object[] getUserObjectPath()
561 TreeNode[] path = getPathToRoot(this, 0);
562 Object[] object = new Object[path.length];
564 for (int index = 0; index < path.length; ++index)
565 object[index] = ((DefaultMutableTreeNode) path[index]).getUserObject();
567 return object;
571 * Returns the root node by iterating the parents of this node.
573 * @return the root node
575 public TreeNode getRoot()
577 TreeNode current = this;
578 TreeNode check = current.getParent();
580 while (check != null)
582 current = check;
583 check = current.getParent();
586 return current;
590 * Tells whether this node is the root node or not.
592 * @return <code>true</code> if this is the root node,
593 * <code>false</code>otherwise
595 public boolean isRoot()
597 return parent == null;
601 * getNextNode
603 * @return DefaultMutableTreeNode
605 public DefaultMutableTreeNode getNextNode()
607 // Return first child.
608 if (getChildCount() != 0)
609 return (DefaultMutableTreeNode) getChildAt(0);
611 // Return next sibling (if needed the sibling of some parent).
612 DefaultMutableTreeNode node = this;
613 DefaultMutableTreeNode sibling;
617 sibling = node.getNextSibling();
618 node = (DefaultMutableTreeNode) node.getParent();
620 while (sibling == null &&
621 node != null);
623 // Return sibling.
624 return sibling;
628 * getPreviousNode
630 * @return DefaultMutableTreeNode
632 public DefaultMutableTreeNode getPreviousNode()
634 // Return null if no parent.
635 if (parent == null)
636 return null;
638 DefaultMutableTreeNode sibling = getPreviousSibling();
640 // Return parent if no sibling.
641 if (sibling == null)
642 return (DefaultMutableTreeNode) parent;
644 // Return last leaf of sibling.
645 if (sibling.getChildCount() != 0)
646 return sibling.getLastLeaf();
648 // Return sibling.
649 return sibling;
653 * preorderEnumeration
655 * @return Enumeration
657 public Enumeration preorderEnumeration()
659 return null; // TODO: Implement me.
663 * postorderEnumeration
665 * @return Enumeration
667 public Enumeration postorderEnumeration()
669 return null; // TODO: Implement me.
673 * breadthFirstEnumeration
675 * @return Enumeration
677 public Enumeration breadthFirstEnumeration()
679 return null; // TODO: Implement me.
683 * depthFirstEnumeration
685 * @return Enumeration
687 public Enumeration depthFirstEnumeration()
689 return postorderEnumeration();
693 * pathFromAncestorEnumeration
695 * @param node TODO
697 * @return Enumeration
699 public Enumeration pathFromAncestorEnumeration(TreeNode node)
701 if (node == null)
702 throw new IllegalArgumentException();
704 TreeNode parent = this;
705 Vector nodes = new Vector();
706 nodes.add(this);
708 while (parent != node && parent != null)
710 parent = parent.getParent();
711 nodes.add(0, parent);
714 if (parent != node)
715 throw new IllegalArgumentException();
717 return nodes.elements();
721 * isNodeChild
723 * @param node TODO
725 * @return boolean
727 public boolean isNodeChild(TreeNode node)
729 if (node == null)
730 return false;
732 return node.getParent() == this;
736 * getFirstChild
738 * @return TreeNode
740 public TreeNode getFirstChild()
742 return (TreeNode) children.firstElement();
746 * getLastChild
748 * @return TreeNode
750 public TreeNode getLastChild()
752 return (TreeNode) children.lastElement();
756 * getChildAfter
758 * @param node TODO
760 * @return TreeNode
762 public TreeNode getChildAfter(TreeNode node)
764 if (node == null
765 || node.getParent() != this)
766 throw new IllegalArgumentException();
768 int index = getIndex(node) + 1;
770 if (index == getChildCount())
771 return null;
773 return getChildAt(index);
777 * getChildBefore
779 * @param node TODO
781 * @return TreeNode
783 public TreeNode getChildBefore(TreeNode node)
785 if (node == null
786 || node.getParent() != this)
787 throw new IllegalArgumentException();
789 int index = getIndex(node) - 1;
791 if (index < 0)
792 return null;
794 return getChildAt(index);
798 * isNodeSibling
800 * @param node TODO
802 * @return boolean
804 public boolean isNodeSibling(TreeNode node)
806 if (node == null)
807 return false;
809 return (node.getParent() == getParent()
810 && getParent() != null);
814 * getSiblingCount
816 * @return int
818 public int getSiblingCount()
820 if (parent == null)
821 return 1;
823 return parent.getChildCount();
827 * getNextSibling
829 * @return DefaultMutableTreeNode
831 public DefaultMutableTreeNode getNextSibling()
833 if (parent == null)
834 return null;
836 int index = parent.getIndex(this) + 1;
838 if (index == parent.getChildCount())
839 return null;
841 return (DefaultMutableTreeNode) parent.getChildAt(index);
845 * getPreviousSibling
847 * @return DefaultMutableTreeNode
849 public DefaultMutableTreeNode getPreviousSibling()
851 if (parent == null)
852 return null;
854 int index = parent.getIndex(this) - 1;
856 if (index < 0)
857 return null;
859 return (DefaultMutableTreeNode) parent.getChildAt(index);
863 * isLeaf
865 * @return boolean
867 public boolean isLeaf()
869 return children.size() == 0;
873 * getFirstLeaf
875 * @return DefaultMutableTreeNode
877 public DefaultMutableTreeNode getFirstLeaf()
879 TreeNode current = this;
881 while (current.getChildCount() > 0)
882 current = current.getChildAt(0);
884 return (DefaultMutableTreeNode) current;
888 * getLastLeaf
890 * @return DefaultMutableTreeNode
892 public DefaultMutableTreeNode getLastLeaf()
894 TreeNode current = this;
895 int size = current.getChildCount();
897 while (size > 0)
899 current = current.getChildAt(size - 1);
900 size = current.getChildCount();
903 return (DefaultMutableTreeNode) current;
907 * getNextLeaf
909 * @return DefaultMutableTreeNode
911 public DefaultMutableTreeNode getNextLeaf()
913 if (parent == null)
914 return null;
916 return null;
917 //return parent.getChildAfter(this);
921 * getPreviousLeaf
923 * @return DefaultMutableTreeNode
925 public DefaultMutableTreeNode getPreviousLeaf()
927 if (parent == null)
928 return null;
930 return null;
931 //return parent.getChildBefore(this);
935 * getLeafCount
937 * @return int
939 public int getLeafCount()
941 int count = 0;
942 Enumeration e = depthFirstEnumeration();
944 while (e.hasMoreElements())
946 TreeNode current = (TreeNode) e.nextElement();
948 if (current.isLeaf())
949 count++;
952 return count;