mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 04:37:34 +00:00
LibHTML: Add a simple TreeNode<T> template for making trees.
We'll be making a lot of trees here, so let's share code during bootstrap. Eventually some of these classes are gonna want custom trees but for now we can just fit them all into the same clothes.
This commit is contained in:
parent
e9b619c4aa
commit
8adae51b35
8 changed files with 68 additions and 109 deletions
|
@ -21,8 +21,8 @@ static void create_layout_tree_for_node(Node& node)
|
|||
printf("created layout node for <%s>, parent is %p, parent ln is %p\n", static_cast<const Element&>(node).tag_name().characters(), node.parent_node(), node.parent_node()->layout_node());
|
||||
}
|
||||
#endif
|
||||
if (node.parent_node() && node.parent_node()->layout_node())
|
||||
node.parent_node()->layout_node()->append_child(*layout_node);
|
||||
if (node.parent() && node.parent()->layout_node())
|
||||
node.parent()->layout_node()->append_child(*layout_node);
|
||||
}
|
||||
if (node.is_parent_node()) {
|
||||
static_cast<ParentNode&>(node).for_each_child([&](auto& child) {
|
||||
|
|
|
@ -10,19 +10,6 @@ Node::~Node()
|
|||
{
|
||||
}
|
||||
|
||||
void Node::ref()
|
||||
{
|
||||
ASSERT(m_retain_count);
|
||||
++m_retain_count;
|
||||
}
|
||||
|
||||
void Node::deref()
|
||||
{
|
||||
ASSERT(m_retain_count);
|
||||
if (!--m_retain_count)
|
||||
delete this;
|
||||
}
|
||||
|
||||
RefPtr<LayoutNode> Node::create_layout_node()
|
||||
{
|
||||
return nullptr;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <AK/Badge.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibHTML/TreeNode.h>
|
||||
|
||||
enum class NodeType : unsigned {
|
||||
INVALID = 0,
|
||||
|
@ -14,33 +15,16 @@ enum class NodeType : unsigned {
|
|||
class LayoutNode;
|
||||
class ParentNode;
|
||||
|
||||
class Node {
|
||||
class Node : public TreeNode<Node> {
|
||||
public:
|
||||
virtual ~Node();
|
||||
|
||||
void ref();
|
||||
void deref();
|
||||
int ref_count() const { return m_retain_count; }
|
||||
|
||||
ParentNode* parent_node() { return m_parent_node; }
|
||||
const ParentNode* parent_node() const { return m_parent_node; }
|
||||
|
||||
void set_parent_node(Badge<ParentNode>, ParentNode* parent_node) { m_parent_node = parent_node; }
|
||||
|
||||
NodeType type() const { return m_type; }
|
||||
bool is_element() const { return type() == NodeType::ELEMENT_NODE; }
|
||||
bool is_text() const { return type() == NodeType::TEXT_NODE; }
|
||||
bool is_document() const { return type() == NodeType::DOCUMENT_NODE; }
|
||||
bool is_parent_node() const { return is_element() || is_document(); }
|
||||
|
||||
Node* next_sibling() { return m_next_sibling; }
|
||||
Node* previous_sibling() { return m_previous_sibling; }
|
||||
const Node* next_sibling() const { return m_next_sibling; }
|
||||
const Node* previous_sibling() const { return m_previous_sibling; }
|
||||
|
||||
void set_next_sibling(Node* node) { m_next_sibling = node; }
|
||||
void set_previous_sibling(Node* node) { m_previous_sibling = node; }
|
||||
|
||||
virtual RefPtr<LayoutNode> create_layout_node();
|
||||
|
||||
const LayoutNode* layout_node() const { return m_layout_node; }
|
||||
|
@ -51,10 +35,6 @@ public:
|
|||
protected:
|
||||
explicit Node(NodeType);
|
||||
|
||||
int m_retain_count { 1 };
|
||||
NodeType m_type { NodeType::INVALID };
|
||||
ParentNode* m_parent_node { nullptr };
|
||||
Node* m_next_sibling { nullptr };
|
||||
Node* m_previous_sibling { nullptr };
|
||||
RefPtr<LayoutNode> m_layout_node;
|
||||
};
|
||||
|
|
|
@ -1,11 +1,2 @@
|
|||
#include <LibHTML/DOM/ParentNode.h>
|
||||
|
||||
void ParentNode::append_child(NonnullRefPtr<Node> node)
|
||||
{
|
||||
if (m_last_child)
|
||||
m_last_child->set_next_sibling(node.ptr());
|
||||
node->set_parent_node({}, this);
|
||||
m_last_child = &node.leak_ref();
|
||||
if (!m_first_child)
|
||||
m_first_child = m_last_child;
|
||||
}
|
||||
|
|
|
@ -4,13 +4,6 @@
|
|||
|
||||
class ParentNode : public Node {
|
||||
public:
|
||||
void append_child(NonnullRefPtr<Node>);
|
||||
|
||||
Node* first_child() { return m_first_child; }
|
||||
Node* last_child() { return m_last_child; }
|
||||
const Node* first_child() const { return m_first_child; }
|
||||
const Node* last_child() const { return m_last_child; }
|
||||
|
||||
template<typename F> void for_each_child(F) const;
|
||||
template<typename F> void for_each_child(F);
|
||||
|
||||
|
@ -19,10 +12,6 @@ protected:
|
|||
: Node(type)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Node* m_first_child { nullptr };
|
||||
Node* m_last_child { nullptr };
|
||||
};
|
||||
|
||||
template<typename Callback>
|
||||
|
|
|
@ -9,29 +9,6 @@ LayoutNode::~LayoutNode()
|
|||
{
|
||||
}
|
||||
|
||||
void LayoutNode::ref()
|
||||
{
|
||||
ASSERT(m_retain_count);
|
||||
++m_retain_count;
|
||||
}
|
||||
|
||||
void LayoutNode::deref()
|
||||
{
|
||||
ASSERT(m_retain_count);
|
||||
if (!--m_retain_count)
|
||||
delete this;
|
||||
}
|
||||
|
||||
void LayoutNode::append_child(NonnullRefPtr<LayoutNode> node)
|
||||
{
|
||||
if (m_last_child)
|
||||
m_last_child->set_next_sibling(node.ptr());
|
||||
node->m_parent_node = this;
|
||||
m_last_child = &node.leak_ref();
|
||||
if (!m_first_child)
|
||||
m_first_child = m_last_child;
|
||||
}
|
||||
|
||||
void LayoutNode::layout()
|
||||
{
|
||||
for_each_child([](auto& child) {
|
||||
|
|
|
@ -3,18 +3,15 @@
|
|||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibHTML/Layout/LayoutStyle.h>
|
||||
#include <LibHTML/TreeNode.h>
|
||||
#include <SharedGraphics/Rect.h>
|
||||
|
||||
class Node;
|
||||
|
||||
class LayoutNode {
|
||||
class LayoutNode : public TreeNode<LayoutNode> {
|
||||
public:
|
||||
virtual ~LayoutNode();
|
||||
|
||||
void ref();
|
||||
void deref();
|
||||
int ref_count() const { return m_retain_count; }
|
||||
|
||||
const Rect& rect() const { return m_rect; }
|
||||
Rect& rect() { return m_rect; }
|
||||
void set_rect(const Rect& rect) { m_rect = rect; }
|
||||
|
@ -25,24 +22,6 @@ public:
|
|||
bool is_anonymous() const { return !m_node; }
|
||||
const Node* node() const { return m_node; }
|
||||
|
||||
const LayoutNode* parent_layout_node() const { return m_parent_node; }
|
||||
|
||||
LayoutNode* next_sibling() { return m_next_sibling; }
|
||||
LayoutNode* previous_sibling() { return m_previous_sibling; }
|
||||
LayoutNode* first_child() { return m_first_child; }
|
||||
LayoutNode* last_child() { return m_last_child; }
|
||||
const LayoutNode* next_sibling() const { return m_next_sibling; }
|
||||
const LayoutNode* previous_sibling() const { return m_previous_sibling; }
|
||||
const LayoutNode* first_child() const { return m_first_child; }
|
||||
const LayoutNode* last_child() const { return m_last_child; }
|
||||
|
||||
bool has_children() const { return m_first_child; }
|
||||
|
||||
void append_child(NonnullRefPtr<LayoutNode>);
|
||||
|
||||
void set_next_sibling(LayoutNode* node) { m_next_sibling = node; }
|
||||
void set_previous_sibling(LayoutNode* node) { m_previous_sibling = node; }
|
||||
|
||||
template<typename Callback>
|
||||
inline void for_each_child(Callback callback) const
|
||||
{
|
||||
|
@ -66,13 +45,8 @@ protected:
|
|||
explicit LayoutNode(const Node*);
|
||||
|
||||
private:
|
||||
int m_retain_count { 1 };
|
||||
const Node* m_node { nullptr };
|
||||
LayoutNode* m_parent_node { nullptr };
|
||||
LayoutNode* m_first_child { nullptr };
|
||||
LayoutNode* m_last_child { nullptr };
|
||||
LayoutNode* m_next_sibling { nullptr };
|
||||
LayoutNode* m_previous_sibling { nullptr };
|
||||
|
||||
LayoutStyle m_style;
|
||||
Rect m_rect;
|
||||
};
|
||||
|
|
61
LibHTML/TreeNode.h
Normal file
61
LibHTML/TreeNode.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
|
||||
template<typename T>
|
||||
class TreeNode {
|
||||
public:
|
||||
void ref()
|
||||
{
|
||||
ASSERT(m_ref_count);
|
||||
++m_ref_count;
|
||||
}
|
||||
|
||||
void deref()
|
||||
{
|
||||
ASSERT(m_ref_count);
|
||||
if (!--m_ref_count)
|
||||
delete static_cast<T*>(this);
|
||||
}
|
||||
int ref_count() const { return m_ref_count; }
|
||||
|
||||
T* parent() { return m_parent; }
|
||||
const T* parent() const { return m_parent; }
|
||||
|
||||
bool has_children() const { return m_first_child; }
|
||||
T* next_sibling() { return m_next_sibling; }
|
||||
T* previous_sibling() { return m_previous_sibling; }
|
||||
T* first_child() { return m_first_child; }
|
||||
T* last_child() { return m_last_child; }
|
||||
const T* next_sibling() const { return m_next_sibling; }
|
||||
const T* previous_sibling() const { return m_previous_sibling; }
|
||||
const T* first_child() const { return m_first_child; }
|
||||
const T* last_child() const { return m_last_child; }
|
||||
|
||||
void append_child(NonnullRefPtr<T> node);
|
||||
|
||||
protected:
|
||||
TreeNode() { }
|
||||
|
||||
private:
|
||||
int m_ref_count { 1 };
|
||||
T* m_parent { nullptr };
|
||||
T* m_first_child { nullptr };
|
||||
T* m_last_child { nullptr };
|
||||
T* m_next_sibling { nullptr };
|
||||
T* m_previous_sibling { nullptr };
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline void TreeNode<T>::append_child(NonnullRefPtr<T> node)
|
||||
{
|
||||
ASSERT(!node->m_parent);
|
||||
if (m_last_child)
|
||||
m_last_child->m_next_sibling = node.ptr();
|
||||
node->m_previous_sibling = m_last_child;
|
||||
node->m_parent = static_cast<T*>(this);
|
||||
m_last_child = &node.leak_ref();
|
||||
if (!m_first_child)
|
||||
m_first_child = m_last_child;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue