diff --git a/inc/hgl/type/Node.h b/inc/hgl/type/Node.h index d211f4a..5894dd7 100644 --- a/inc/hgl/type/Node.h +++ b/inc/hgl/type/Node.h @@ -61,13 +61,13 @@ namespace hgl };//class Node - template class DataNode:public Node + template class DataNode:public SuperNode { T node_data; public: - using Node::Node; + using SuperNode::SuperNode; virtual ~DataNode()override=default; public: diff --git a/inc/hgl/type/TreeBaseNode.h b/inc/hgl/type/TreeBaseNode.h new file mode 100644 index 0000000..97949a5 --- /dev/null +++ b/inc/hgl/type/TreeBaseNode.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +namespace hgl +{ + class TreeBaseNode:public Node + { + TreeBaseNode *parent_node; ///<父节点指针 + tsl::robin_map child_map; ///<子节点集合 + + protected: + + void DetachAll(); + + public: + + TreeBaseNode(NodeManager *nm,const size_t uid):Node(nm,uid) + { + parent_node=nullptr; + } + + virtual ~TreeBaseNode() + { + DetachAll(); + } + + public: + + virtual void OnAttachParentNode(TreeBaseNode *pn){parent_node=pn;} ///<被附加到父节点时调用(参见AttachChild) + virtual void OnDetachParentNode(){parent_node=nullptr;} ///<被从父节点中移除时调用(参见DetachChild) + + public: + + const TreeBaseNode * GetParent()const{return parent_node;} ///<获取父节点指针 + + const size_t GetChildCount()const{return child_map.size();} ///<获取子节点数量 + + const bool Contains(const size_t id)const{return child_map.contains(id);} ///<根据ID判断是否包含子节点 + const bool Contains(const TreeBaseNode *node)const; + + const bool AttachChild(TreeBaseNode *node); + void DetachChild(TreeBaseNode *node); + void DetachAllChild(); + + void DestoryAllChild(); + + void DetachParent(); + };//class TreeBaseNode +}//namespace hgl diff --git a/inc/hgl/type/TreeNode.h b/inc/hgl/type/TreeNode.h index 081d3c7..dec6981 100644 --- a/inc/hgl/type/TreeNode.h +++ b/inc/hgl/type/TreeNode.h @@ -1,97 +1,60 @@ #pragma once #include +#include namespace hgl { - template class TreeNode:public DataNode + template class TreeNode:public DataNode { - TreeNode *parent_node; ///<父节点指针 - tsl::robin_map *> child_map; ///<子节点集合 - private: + using SuperNode=DataNode; + friend class NodeManager; template friend class DataNodeManager; - TreeNode(NodeManager *nm,const size_t uid):DataNode(nm,uid) - { - parent_node=nullptr; - } + TreeNode(NodeManager *nm,const size_t uid):SuperNode(nm,uid){} public: virtual ~TreeNode() { - if(GetChildCount()) - DestoryAllChild(); - - if(parent_node) - parent_node->DetachChild(this); //从父节点中移除 + //这里必须处理DetachChild问题,不然各种OnDetach虚拟函数回调就失效了 + TreeBaseNode::DetachAll(); } - T *operator ->() {return DataNode::get_ptr();} - const T *operator ->()const {return DataNode::get_ptr();} + T *operator ->() {return SuperNode::get_ptr();} + const T *operator ->()const {return SuperNode::get_ptr();} - public: //子节点相关 + TreeNode *GetParent() + { + return (TreeNode *)SuperNode::GetParent(); + } - virtual void OnAttachParent(TreeNode *pn){parent_node=pn;} ///<被附加到父节点时调用(参见AttachChild) - virtual void OnDetachParent(TreeNode *pn){parent_node=nullptr;} ///<被从父节点中移除时调用(参见DetachChild) - const TreeNode * GetParent()const{return parent_node;} ///<获取父节点指针 + public: - const size_t GetChildCount()const{return child_map.size();} ///<获取子节点数量 + virtual void OnAttachParent(TreeNode *){} ///<被附加到父节点时调用 + virtual void OnDetachParent(){} ///<被从父节点中移除时调用 - const bool Contains(const size_t id)const{return child_map.contains(id);} ///<根据ID判断是否包含子节点 - const bool Contains(const TreeNode *node)const - { - if(!node)return(false); - if(node->Node::GetManager()!=Node::GetManager())return(false); + virtual void OnAttachParentNode(TreeBaseNode *pn)override ///<被附加到父节点时调用(参见AttachChild) + { + SuperNode::OnAttachParentNode(pn); + OnAttachParent((TreeNode *)pn); + } - return Contains(node->GetUniqueID()); - } + virtual void OnDetachParentNode()override ///<被从父节点中移除时调用(参见DetachChild) + { + OnDetachParent(); + SuperNode::OnDetachParentNode(); + } - const bool AttachChild(TreeNode *node) - { - if(!node)return(false); - if(Contains(node))return(false); - - child_map.emplace(node->GetUniqueID(),node); - node->OnAttachParent(this); - return(true); - } - - void DetachChild(TreeNode *node) - { - if(!node)return; - - if(node->Node::GetManager()!=Node::GetManager()) - return; - - const size_t child_id=node->GetUniqueID(); - - if(child_map.contains(child_id)) - child_map.erase(child_id); - - node->OnDetachParent(this); - } - - void DestoryAllChild() - { - for(auto &it:child_map) - { - TreeNode *node=it.second; - - if(!node) - continue; - - child_map.erase(node->GetUniqueID()); //从子节点集合中移除 - node->OnDetachParent(this); //从父节点中移除 - - node->Destory(); //销毁子节点 - } - - child_map.clear(); - } + virtual void OnDestory()override + { + TreeBaseNode::DetachParent(); + TreeBaseNode::DetachAllChild(); + SuperNode::OnDestory(); + } };//class TreeNode }//namespace hgl diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b97387a..5c49025 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,9 +44,11 @@ SOURCE_GROUP("DataType\\DataChain" FILES ${TYPE_DATA_CHAIN_SOURCE}) SET(TREE_NODE_FILES ${TYPE_INCLUDE_PATH}/Node.h ${TYPE_INCLUDE_PATH}/NodeManager.h + ${TYPE_INCLUDE_PATH}/TreeBaseNode.h ${TYPE_INCLUDE_PATH}/TreeNode.h Type/Node.cpp - Type/NodeManager.cpp) + Type/NodeManager.cpp + Type/TreeBaseNode.cpp) SOURCE_GROUP("DataType\\Node" FILES ${TREE_NODE_FILES}) diff --git a/src/Type/TreeBaseNode.cpp b/src/Type/TreeBaseNode.cpp new file mode 100644 index 0000000..ce78c82 --- /dev/null +++ b/src/Type/TreeBaseNode.cpp @@ -0,0 +1,89 @@ +#include + +namespace hgl +{ + void TreeBaseNode::DetachAll() + { + if(GetChildCount()) + DestoryAllChild(); + + if(parent_node) + parent_node->DetachChild(this); //从父节点中移除 + } + + const bool TreeBaseNode::Contains(const TreeBaseNode *node)const + { + if(!node)return(false); + if(node->GetManager()!=GetManager())return(false); + if(node->GetParent()!=this)return(false); + return Contains(node->GetUniqueID()); + } + + const bool TreeBaseNode::AttachChild(TreeBaseNode *node) + { + if(!node)return(false); + if(Contains(node))return(false); + + child_map.emplace(node->GetUniqueID(),node); + node->OnAttachParentNode(this); + return(true); + } + + void TreeBaseNode::DetachChild(TreeBaseNode *node) + { + if(!node)return; + + if(node->Node::GetManager()!=Node::GetManager()) + return; + + const size_t child_id=node->GetUniqueID(); + + if(!child_map.contains(child_id)) + return; + + child_map.erase(child_id); + node->OnDetachParentNode(); + } + + void TreeBaseNode::DetachAllChild() + { + for(auto &it:child_map) + { + TreeBaseNode *node=it.second; + + if(!node) + continue; + + node->OnDetachParentNode(); //从父节点中移除 + } + + child_map.clear(); + } + + void TreeBaseNode::DestoryAllChild() + { + for(auto &it:child_map) + { + TreeBaseNode *node=it.second; + + if(!node) + continue; + + child_map.erase(node->GetUniqueID()); //从子节点集合中移除 + node->OnDetachParentNode(); //从父节点中移除 + + node->Destory(); //销毁子节点 + } + + child_map.clear(); + } + + void TreeBaseNode::DetachParent() + { + if(!parent_node) + return; + + parent_node->DetachChild(this); //从父节点中移除 + parent_node=nullptr; + } +}//namespace hgl