/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */ #pragma once #include "rbx/Declarations.h" #include "Util/IndexArray.h" #include "rbx/Debug.h" namespace RBX { class RBXBaseClass IndexedTree { private: IndexedTree* parent; int index; int& getIndex() {return index;} IndexArray children; bool circularReference(IndexedTree* newAncestor, IndexedTree* child); protected: virtual void onParentChanging() {} virtual void onParentChanged(IndexedTree* oldParent) {} virtual void onChildAdding(IndexedTree* child) {} virtual void onChildAdded(IndexedTree* child) {} virtual void onChildRemoving(IndexedTree* child) {} virtual void onChildRemoved(IndexedTree* child) {} virtual void onAncestorChanged() {} void setIndexedTreeParent(IndexedTree* newParent); public: IndexedTree(); virtual ~IndexedTree(); int numChildren() const {return children.size();} template Type* getTypedChild(int i) { return rbx_static_cast(children[i]); } template const Type* getConstTypedChild(int i) const { return rbx_static_cast(children[i]); } template Type* getTypedParent() { return rbx_static_cast(parent); } template const Type* getConstTypedParent() const { return rbx_static_cast(parent); } template Type* getRoot() { return (parent) ? parent->getRoot() : rbx_static_cast(this); } template const Type* getRoot() const { return (parent) ? parent->getRoot() : rbx_static_cast(this); } template Type* getOneBelowRoot() { IndexedTree* above = parent; RBXASSERT(above != NULL); IndexedTree* answer = this; while (above->parent) { answer = above; above = above->parent; } return rbx_static_cast(answer); } int getDepth() const { return parent ? (parent->getDepth() + 1) : 1; } template inline void visitMeAndChildren(Func func) { Type* t = rbx_static_cast(this); func(t); for (int i = 0; i < children.size(); ++i) { children[i]->visitMeAndChildren(func); } } template inline void visitConstMeAndChildren(Func func) { const Type* t = rbx_static_cast(this); func(t); for (int i = 0; i < children.size(); ++i) { children[i]->visitConstMeAndChildren(func); } } template inline void visitDescendents(Func func) { for (int i = 0; i < children.size(); ++i) { children[i]->visitMeAndChildren(func); } } template inline void visitConstDescendents(Func func) const { for (int i = 0; i < children.size(); ++i) { children[i]->visitConstMeAndChildren(func); } } }; } // namespace