Commit 507016ca authored by Benjamin Otte's avatar Benjamin Otte

cssnode: Refactor node tree modification code

This allows adding more API for it.

It also includes code that tracks modifications and invalidates siblings
and their positions whenever nodes get added or removed.
parent 310f9f40
......@@ -359,73 +359,118 @@ gtk_css_node_parent_will_be_set (GtkCssNode *node)
GTK_CSS_NODE_GET_CLASS (node)->dequeue_validate (node);
}
void
gtk_css_node_set_parent (GtkCssNode *node,
GtkCssNode *parent)
static void
gtk_css_node_unlink_from_siblings (GtkCssNode *node)
{
if (node->parent == parent)
if (GTK_IS_CSS_TRANSIENT_NODE (node))
return;
/* Take a reference here so the whole function has a reference */
g_object_ref (node);
if (node->previous_sibling)
node->previous_sibling->next_sibling = node->next_sibling;
else
node->parent->first_child = node->next_sibling;
if (node->parent != NULL)
if (node->next_sibling)
node->next_sibling->previous_sibling = node->previous_sibling;
else
node->parent->last_child = node->previous_sibling;
node->previous_sibling = NULL;
node->next_sibling = NULL;
}
static void
gtk_css_node_link_to_siblings (GtkCssNode *node,
GtkCssNode *new_previous)
{
if (GTK_IS_CSS_TRANSIENT_NODE (node))
return;
if (new_previous)
{
if (!GTK_IS_CSS_TRANSIENT_NODE (node))
{
if (node->previous_sibling)
node->previous_sibling->next_sibling = node->next_sibling;
else
node->parent->first_child = node->next_sibling;
node->previous_sibling = new_previous;
node->next_sibling = new_previous->next_sibling;
new_previous->next_sibling = node;
}
else
{
node->next_sibling = node->parent->first_child;
node->parent->first_child = node;
}
if (node->next_sibling)
node->next_sibling->previous_sibling = node;
else
node->parent->last_child = node;
}
if (node->next_sibling)
node->next_sibling->previous_sibling = node->previous_sibling;
else
node->parent->last_child = node->previous_sibling;
static void
gtk_css_node_set_children_changed (GtkCssNode *node)
{
if (node->children_changed)
return;
node->parent->n_children--;
}
node->children_changed = TRUE;
gtk_css_node_set_invalid (node, TRUE);
}
node->parent = NULL;
node->next_sibling = NULL;
node->previous_sibling = NULL;
static void
gtk_css_node_reposition (GtkCssNode *node,
GtkCssNode *parent,
GtkCssNode *previous)
{
g_assert (! (parent == NULL && previous != NULL));
g_object_unref (node);
/* Take a reference here so the whole function has a reference */
g_object_ref (node);
if (parent == NULL)
gtk_css_node_parent_was_unset (node);
}
if (node->parent != NULL)
gtk_css_node_unlink_from_siblings (node);
if (parent)
if (node->parent != parent)
{
if (node->parent == NULL)
gtk_css_node_parent_will_be_set (node);
{
gtk_css_node_parent_will_be_set (node);
}
else
{
g_object_unref (node);
gtk_css_node_set_children_changed (node->parent);
}
node->parent = parent;
if (!GTK_IS_CSS_TRANSIENT_NODE (node))
if (parent)
{
parent->n_children++;
gtk_css_node_set_children_changed (parent);
g_object_ref (node);
if (parent->last_child)
{
parent->last_child->next_sibling = node;
node->previous_sibling = parent->last_child;
}
parent->last_child = node;
if (parent->first_child == NULL)
parent->first_child = node;
if (node->invalid)
gtk_css_node_set_invalid (parent, TRUE);
}
else
{
gtk_css_node_parent_was_unset (node);
}
if (node->invalid)
gtk_css_node_set_invalid (parent, TRUE);
}
if (parent)
gtk_css_node_link_to_siblings (node, previous);
gtk_css_node_invalidate (node, GTK_CSS_CHANGE_ANY_PARENT | GTK_CSS_CHANGE_ANY_SIBLING);
if (node->parent == NULL)
g_object_unref (node);
g_object_unref (node);
}
void
gtk_css_node_set_parent (GtkCssNode *node,
GtkCssNode *parent)
{
if (node->parent == parent)
return;
gtk_css_node_reposition (node, parent, parent ? parent->last_child : NULL);
}
GtkCssNode *
......@@ -638,6 +683,11 @@ gtk_css_node_propagate_pending_changes (GtkCssNode *cssnode)
return;
change = _gtk_css_change_for_child (cssnode->pending_changes);
if (cssnode->children_changed)
{
change |= GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_ANY_SIBLING;
cssnode->children_changed = FALSE;
}
for (child = gtk_css_node_get_first_child (cssnode);
child;
......@@ -671,11 +721,11 @@ gtk_css_node_validate (GtkCssNode *cssnode,
if (G_UNLIKELY (gtk_get_debug_flags () & GTK_DEBUG_NO_CSS_CACHE))
change = GTK_CSS_CHANGE_ANY;
gtk_css_node_propagate_pending_changes (cssnode);
if (!cssnode->invalid && change == 0 && _gtk_bitmask_is_empty (parent_changes))
return;
gtk_css_node_propagate_pending_changes (cssnode);
gtk_css_node_set_invalid (cssnode, FALSE);
change = cssnode->pending_changes;
......
......@@ -43,7 +43,6 @@ struct _GtkCssNode
GtkCssNode *next_sibling;
GtkCssNode *first_child;
GtkCssNode *last_child;
guint n_children;
GtkCssNodeDeclaration *decl;
GtkCssStyle *style;
......@@ -51,6 +50,7 @@ struct _GtkCssNode
GtkCssChange pending_changes; /* changes that accumulated since the style was last computed */
guint invalid :1; /* node or a child needs to be validated (even if just for animation) */
guint children_changed :1; /* the children changed since last validation */
};
struct _GtkCssNodeClass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment