// Copyright (C) 2007 Id Software, Inc. // #ifndef __HIERARCHY_H__ #define __HIERARCHY_H__ /* ============================================================================== idHierarchy ============================================================================== */ template< class type > class idHierarchy { public: idHierarchy(); ~idHierarchy(); void SetOwner( type *object ); type * Owner( void ) const; void ParentTo( idHierarchy &node ); void MakeSiblingAfter( idHierarchy &node ); bool ParentedBy( const idHierarchy &node ) const; void RemoveFromParent( void ); void RemoveFromHierarchy( void ); type * GetParent( void ) const; // parent of this node type * GetChild( void ) const; // first child of this node type * GetSibling( void ) const; // next node with the same parent type * GetPriorSibling( void ) const; // previous node with the same parent type * GetNext( void ) const; // goes through all nodes of the hierarchy type * GetNextLeaf( void ) const; // goes through all leaf nodes of the hierarchy private: idHierarchy * parent; idHierarchy * sibling; idHierarchy * child; type * owner; idHierarchy *GetPriorSiblingNode( void ) const; // previous node with the same parent }; /* ================ idHierarchy::idHierarchy ================ */ template< class type > idHierarchy::idHierarchy() { owner = NULL; parent = NULL; sibling = NULL; child = NULL; } /* ================ idHierarchy::~idHierarchy ================ */ template< class type > idHierarchy::~idHierarchy() { RemoveFromHierarchy(); } /* ================ idHierarchy::Owner Gets the object that is associated with this node. ================ */ template< class type > type *idHierarchy::Owner( void ) const { return owner; } /* ================ idHierarchy::SetOwner Sets the object that this node is associated with. ================ */ template< class type > void idHierarchy::SetOwner( type *object ) { owner = object; } /* ================ idHierarchy::ParentedBy ================ */ template< class type > bool idHierarchy::ParentedBy( const idHierarchy &node ) const { if ( parent == &node ) { return true; } else if ( parent ) { return parent->ParentedBy( node ); } return false; } /* ================ idHierarchy::ParentTo Makes the given node the parent. ================ */ template< class type > void idHierarchy::ParentTo( idHierarchy &node ) { RemoveFromParent(); parent = &node; sibling = node.child; node.child = this; } /* ================ idHierarchy::MakeSiblingAfter Makes the given node a sibling after the passed in node. ================ */ template< class type > void idHierarchy::MakeSiblingAfter( idHierarchy &node ) { RemoveFromParent(); parent = node.parent; sibling = node.sibling; node.sibling = this; } /* ================ idHierarchy::RemoveFromParent ================ */ template< class type > void idHierarchy::RemoveFromParent( void ) { idHierarchy *prev; if ( parent ) { prev = GetPriorSiblingNode(); if ( prev ) { prev->sibling = sibling; } else { parent->child = sibling; } } parent = NULL; sibling = NULL; } /* ================ idHierarchy::RemoveFromHierarchy Removes the node from the hierarchy and adds it's children to the parent. ================ */ template< class type > void idHierarchy::RemoveFromHierarchy( void ) { idHierarchy *parentNode; idHierarchy *node; parentNode = parent; RemoveFromParent(); if ( parentNode ) { while( child ) { node = child; node->RemoveFromParent(); node->ParentTo( *parentNode ); } } else { while( child ) { child->RemoveFromParent(); } } } /* ================ idHierarchy::GetParent ================ */ template< class type > type *idHierarchy::GetParent( void ) const { if ( parent ) { return parent->owner; } return NULL; } /* ================ idHierarchy::GetChild ================ */ template< class type > type *idHierarchy::GetChild( void ) const { if ( child ) { return child->owner; } return NULL; } /* ================ idHierarchy::GetSibling ================ */ template< class type > type *idHierarchy::GetSibling( void ) const { if ( sibling ) { return sibling->owner; } return NULL; } /* ================ idHierarchy::GetPriorSiblingNode Returns NULL if no parent, or if it is the first child. ================ */ template< class type > idHierarchy *idHierarchy::GetPriorSiblingNode( void ) const { if ( !parent || ( parent->child == this ) ) { return NULL; } idHierarchy *prev; idHierarchy *node; node = parent->child; prev = NULL; while( ( node != this ) && ( node != NULL ) ) { prev = node; node = node->sibling; } if ( node != this ) { idLib::Error( "idHierarchy::GetPriorSibling: could not find node in parent's list of children" ); } return prev; } /* ================ idHierarchy::GetPriorSibling Returns NULL if no parent, or if it is the first child. ================ */ template< class type > type *idHierarchy::GetPriorSibling( void ) const { idHierarchy *prior; prior = GetPriorSiblingNode(); if ( prior ) { return prior->owner; } return NULL; } /* ================ idHierarchy::GetNext Goes through all nodes of the hierarchy. ================ */ template< class type > type *idHierarchy::GetNext( void ) const { const idHierarchy *node; if ( child ) { return child->owner; } else { node = this; while( node && node->sibling == NULL ) { node = node->parent; } if ( node ) { return node->sibling->owner; } else { return NULL; } } } /* ================ idHierarchy::GetNextLeaf Goes through all leaf nodes of the hierarchy. ================ */ template< class type > type *idHierarchy::GetNextLeaf( void ) const { const idHierarchy *node; if ( child ) { node = child; while ( node->child ) { node = node->child; } return node->owner; } else { node = this; while( node && node->sibling == NULL ) { node = node->parent; } if ( node ) { node = node->sibling; while ( node->child ) { node = node->child; } return node->owner; } else { return NULL; } } } #endif /* !__HIERARCHY_H__ */