/*----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is Fever Framework code. The Initial Developer of the Original Code is Romain Ecarnot. Portions created by Initial Developer are Copyright (C) 2006 the Initial Developer. All Rights Reserved. Contributor(s): Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -----------------------------------------------------------------------------*/ import fvaswing.components.tree.FvAbstractTreeNode; import fvaswing.components.tree.FvTreeItem; /** * Tree node for {@link fvaswing.components.FvTree} componant. * * @author Romain Ecarnot */ class fvaswing.components.tree.FvTreeNode extends FvAbstractTreeNode { //------------------------------------------------------------------------- // Public API //------------------------------------------------------------------------- /** * Creates a tree node with no parent, no children, initialized with * the specified user object, and that allows children only if * specified. * * @param userObject an Object provided by the user that constitutes * the node's data * @param allowsChildren (optional)if true, the node is allowed to have child * nodes -- otherwise, it is always a leaf node. Default is true. * @param draggable Node is draggable or not ( override tree behaviour for this specific node ) * @param editable Node is editable or not ( override tree behaviour for this specific node ) */ public function FvTreeNode( userObject : FvTreeItem, allowsChildren : Boolean, draggable : Boolean, editable : Boolean, deletable : Boolean ) { super( userObject, allowsChildren, draggable, editable, deletable ); } /** * Sets the user object for this node to userObject. * * @param userObject the Object that constitutes this node's * user-specified data */ public function setUserObject( userObject : FvTreeItem ) : Void { _userObject = userObject; } /** * Returns this node's user object. */ public function getUserObject() : FvTreeItem { return FvTreeItem( _userObject ); } /** * Removes newChild from its present parent (if it has a * parent), sets the child's parent to this node, and then adds the child * to this node's child array at index childIndex. * newChild must not be null and must not be an ancestor of * this node. * * @param newChild the FvTreeNode to insert under this node * @param childIndex the index in this node's child array * where this node is to be inserted * @exception Error if * newChild is null or is an ancestor of this node, * or if childIndex is out of bounds, or if this * node does not allow children * @see #isNodeDescendant */ public function insert( newChild : FvTreeNode, childIndex : Number ) : Void { super.insert( newChild, childIndex ); } /** * Sets this node's parent to newParent but does not * change the parent's child array. This method is called from * insert() and remove() to * reassign a child's parent, it should not be messaged from anywhere * else. * * @param newParent this node's new parent */ public function setParent( newParent : FvTreeNode ) : Void { super.setParent( newParent ); } /** * Returns this node's parent or null if this node has no parent. * * @return this node's parent TreeNode, or null if this node has no parent */ public function getParent() : FvTreeNode { return FvTreeNode( _parent ); } /** * Returns the child at the specified index in this node's child array. * * @param index an index into this node's child array * @exception ArrayIndexOutOfBoundsException if index * is out of bounds * @return the TreeNode in this node's child array at the specified index */ public function getChildAt( index : Number ) : FvTreeNode { return FvTreeNode( super.getChildAt( index ) ); } /** * Returns the index of the specified child in this node's child array. * If the specified node is not a child of this node, returns * -1. This method performs a linear search and is O(n) * where n is the number of children. * * @param aChild the FvTreeNode to search for among this node's children * @return an int giving the index of the node in this node's child * array, or -1 if the specified node is a not * a child of this node */ public function getIndex( aChild : FvTreeNode ) : Number { return super.getIndex( aChild ); } /** * Removes aChild from this node's child array, giving it a * null parent. * * @param aChild a child of this node to remove */ public function remove( aChild : FvTreeNode ) : Void { super.remove( aChild ); } /** * Removes newChild from its parent and makes it a child of * this node by adding it to the end of this node's child array. * * @param newChild node to add as a child of this node */ public function append( newChild : FvTreeNode ) : Void { super.append( newChild ); } /** * Returns true if anotherNode is an ancestor of this node * -- if it is this node, this node's parent, or an ancestor of this * node's parent. (Note that a node is considered an ancestor of itself.) * If anotherNode is null, this method returns false. This * operation is at worst O(h) where h is the distance from the root to * this node. * * @param anotherNode node to test as an ancestor of this node * @return true if this node is a descendant of anotherNode */ public function isNodeAncestor( anotherNode : FvTreeNode ) : Boolean { return super.isNodeAncestor( anotherNode ); } /** * Returns true if anotherNode is a descendant of this node * -- if it is this node, one of this node's children, or a descendant of * one of this node's children. Note that a node is considered a * descendant of itself. If anotherNode is null, returns * false. This operation is at worst O(h) where h is the distance from the * root to anotherNode. * * @param anotherNode node to test as descendant of this node * @return true if this node is an ancestor of anotherNode */ public function isNodeDescendant( anotherNode : FvTreeNode ) : Boolean { return super.isNodeDescendant( anotherNode ); } /** * Returns the nearest common ancestor to this node and aNode. * Returns null, if no such ancestor exists -- if this node and * aNode are in different trees or if aNode is * null. A node is considered an ancestor of itself. * * @param aNode node to find common ancestor with * @return nearest ancestor common to this node and aNode, * or null if none */ public function getSharedAncestor( aNode : FvTreeNode ) : FvTreeNode { return FvTreeNode( super.getSharedAncestor( aNode ) ); } /** * Returns true if and only if aNode is in the same tree * as this node. Returns false if aNode is null. * * @see #getSharedAncestor * @see #getRoot * @return true if aNode is in the same tree as this node; * false if aNode is null */ public function isNodeRelated( aNode : FvTreeNode ) : Boolean { return super.isNodeRelated( aNode ); } /** * Returns the root of the tree that contains this node. The root is * the ancestor with a null parent. * * @return the root of the tree that contains this node */ public function getRoot() : FvTreeNode { return FvTreeNode( super.getRoot() ); } /** * Returns the node that follows this node in a preorder traversal of this * node's tree. Returns null if this node is the last node of the * traversal. This is an inefficient way to traverse the entire tree; use * an enumeration, instead. * * @see #preorderEnumeration * @return the node that follows this node in a preorder traversal, or * null if this node is last */ public function getNextNode() : FvTreeNode { return FvTreeNode( super.getNextNode() ); } /** * Returns the node that precedes this node in a preorder traversal of * this node's tree. Returns null if this node is the * first node of the traversal -- the root of the tree. * This is an inefficient way to * traverse the entire tree; use an enumeration, instead. * * @see #preorderEnumeration * @return the node that precedes this node in a preorder traversal, or * null if this node is the first */ public function getPreviousNode() : FvTreeNode { return FvTreeNode( super.getPreviousNode() ); } /** * Creates and returns an enumeration that follows the path from * ancestor to this node. The enumeration's * nextElement() method first returns ancestor, * then the child of ancestor that is an ancestor of this * node, and so on, and finally returns this node. Creation of the * enumeration is O(m) where m is the number of nodes between this node * and ancestor, inclusive. Each nextElement() * message is O(1).

* * Modifying the tree by inserting, removing, or moving a node invalidates * any enumerations created before the modification. * * @see #isNodeAncestor() * @see #isNodeDescendant() * @exception IllegalArgumentException if ancestor is * not an ancestor of this node * @return an enumeration for following the path from an ancestor of * this node to this one */ public function pathFromAncestorEnumeration( ancestor : FvTreeNode ) : Array { return pathFromAncestorEnumeration( ancestor ); } /** * Returns true if aNode is a child of this node. If * aNode is null, this method returns false. * * @return true if aNode is a child of this node; false if * aNode is null */ public function isNodeChild( aNode : FvTreeNode ) : Boolean { return super.isNodeChild( aNode ); } /** * Returns this node's first child. * * @return the first child of this node, null if this node has no children */ public function getFirstChild() : FvTreeNode { return FvTreeNode( super.getFirstChild() ); } /** * Returns this node's last child. * * @return the last child of this node, null if this node has no children */ public function getLastChild() : FvTreeNode { return FvTreeNode( super.getLastChild() ); } /** * Returns the child in this node's child array that immediately * follows aChild, which must be a child of this node. If * aChild is the last child, returns null. This method * performs a linear search of this node's children for * aChild and is O(n) where n is the number of children; to * traverse the entire array of children, use an enumeration instead. * * @see #children() * @exception Error if aChild is * null or is not a child of this node * @return the child of this node that immediately follows * aChild */ public function getChildAfter( aChild : FvTreeNode ) : FvTreeNode { return FvTreeNode( super.getChildAfter( aChild ) ); } /** * Returns the child in this node's child array that immediately * precedes aChild, which must be a child of this node. If * aChild is the first child, returns null. This method * performs a linear search of this node's children for aChild * and is O(n) where n is the number of children. * * @exception IllegalArgumentException if aChild is null * or is not a child of this node * @return the child of this node that immediately precedes * aChild */ public function getChildBefore( aChild : FvTreeNode ) : FvTreeNode { return FvTreeNode( super.getChildBefore( aChild ) ); } /** * Returns true if anotherNode is a sibling of (has the * same parent as) this node. A node is its own sibling. If * anotherNode is null, returns false. * * @param anotherNode node to test as sibling of this node * @return true if anotherNode is a sibling of this node */ public function isNodeSibling( anotherNode : FvTreeNode ) : Boolean { return super.isNodeSibling( anotherNode ); } /** * Returns the next sibling of this node in the parent's children array. * Returns null if this node has no parent or is the parent's last child. * This method performs a linear search that is O(n) where n is the number * of children; to traverse the entire array, use the parent's child * enumeration instead. * * @see #children * @return the sibling of this node that immediately follows this node */ public function getNextSibling() : FvTreeNode { return FvTreeNode( super.getNextSibling() ); } /** * Returns the previous sibling of this node in the parent's children * array. Returns null if this node has no parent or is the parent's * first child. This method performs a linear search that is O(n) where n * is the number of children. * * @return the sibling of this node that immediately precedes this node */ public function getPreviousSibling() : FvTreeNode { return FvTreeNode( super.getPreviousSibling() ); } /** * Finds and returns the first leaf that is a descendant of this node -- * either this node or its first child's first leaf. * Returns this node if it is a leaf. * * @return the first leaf in the subtree rooted at this node */ public function getFirstLeaf() : FvTreeNode { return FvTreeNode( super.getFirstLeaf() ); } /** * Finds and returns the last leaf that is a descendant of this node -- * either this node or its last child's last leaf. * Returns this node if it is a leaf. * * @see #isLeaf() * @see #isNodeDescendant() * @return the last leaf in the subtree rooted at this node */ public function getLastLeaf() : FvTreeNode { return FvTreeNode( super.getLastLeaf() ); } /** * Returns the leaf after this node or null if this node is the * last leaf in the tree. *

* In this implementation of the MutableNode interface, * this operation is very inefficient. In order to determine the * next node, this method first performs a linear search in the * parent's child-list in order to find the current node. *

* That implementation makes the operation suitable for short * traversals from a known position. But to traverse all of the * leaves in the tree, you should use depthFirstEnumeration * to enumerate the nodes in the tree and use isLeaf * on each node to determine which are leaves. * * @return returns the next leaf past this node */ public function getNextLeaf() : FvTreeNode { return FvTreeNode( super.getNextLeaf() ); } /** * Returns the leaf before this node or null if this node is the * first leaf in the tree. *

* In this implementation of the MutableNode interface, * this operation is very inefficient. In order to determine the * previous node, this method first performs a linear search in the * parent's child-list in order to find the current node. *

* That implementation makes the operation suitable for short * traversals from a known position. But to traverse all of the * leaves in the tree, you should use depthFirstEnumeration * to enumerate the nodes in the tree and use isLeaf * on each node to determine which are leaves. * * @return returns the leaf before this node */ public function getPreviousLeaf() : FvTreeNode { return FvTreeNode( super.getPreviousLeaf() ); } /** * Returns a duplicated node. */ public function duplicate() : FvTreeNode { return new FvTreeNode( null, _allowsChildren, _isDraggable, _isEditable, _isDeletable ); } }