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.
This commit is contained in:
174
gtk/gtkcssnode.c
174
gtk/gtkcssnode.c
@@ -359,6 +359,110 @@ gtk_css_node_parent_will_be_set (GtkCssNode *node)
|
||||
GTK_CSS_NODE_GET_CLASS (node)->dequeue_validate (node);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_node_unlink_from_siblings (GtkCssNode *node)
|
||||
{
|
||||
if (GTK_IS_CSS_TRANSIENT_NODE (node))
|
||||
return;
|
||||
|
||||
if (node->previous_sibling)
|
||||
node->previous_sibling->next_sibling = node->next_sibling;
|
||||
else
|
||||
node->parent->first_child = node->next_sibling;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_node_set_children_changed (GtkCssNode *node)
|
||||
{
|
||||
if (node->children_changed)
|
||||
return;
|
||||
|
||||
node->children_changed = TRUE;
|
||||
gtk_css_node_set_invalid (node, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_node_reposition (GtkCssNode *node,
|
||||
GtkCssNode *parent,
|
||||
GtkCssNode *previous)
|
||||
{
|
||||
g_assert (! (parent == NULL && previous != NULL));
|
||||
|
||||
/* Take a reference here so the whole function has a reference */
|
||||
g_object_ref (node);
|
||||
|
||||
if (node->parent != NULL)
|
||||
gtk_css_node_unlink_from_siblings (node);
|
||||
|
||||
if (node->parent != parent)
|
||||
{
|
||||
if (node->parent == NULL)
|
||||
{
|
||||
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 (parent)
|
||||
{
|
||||
gtk_css_node_set_children_changed (parent);
|
||||
g_object_ref (node);
|
||||
|
||||
if (node->invalid)
|
||||
gtk_css_node_set_invalid (parent, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_node_parent_was_unset (node);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
g_object_unref (node);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_node_set_parent (GtkCssNode *node,
|
||||
GtkCssNode *parent)
|
||||
@@ -366,66 +470,7 @@ gtk_css_node_set_parent (GtkCssNode *node,
|
||||
if (node->parent == parent)
|
||||
return;
|
||||
|
||||
/* Take a reference here so the whole function has a reference */
|
||||
g_object_ref (node);
|
||||
|
||||
if (node->parent != NULL)
|
||||
{
|
||||
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;
|
||||
|
||||
if (node->next_sibling)
|
||||
node->next_sibling->previous_sibling = node->previous_sibling;
|
||||
else
|
||||
node->parent->last_child = node->previous_sibling;
|
||||
|
||||
node->parent->n_children--;
|
||||
}
|
||||
|
||||
node->parent = NULL;
|
||||
node->next_sibling = NULL;
|
||||
node->previous_sibling = NULL;
|
||||
|
||||
g_object_unref (node);
|
||||
|
||||
if (parent == NULL)
|
||||
gtk_css_node_parent_was_unset (node);
|
||||
}
|
||||
|
||||
if (parent)
|
||||
{
|
||||
if (node->parent == NULL)
|
||||
gtk_css_node_parent_will_be_set (node);
|
||||
|
||||
node->parent = parent;
|
||||
|
||||
if (!GTK_IS_CSS_TRANSIENT_NODE (node))
|
||||
{
|
||||
parent->n_children++;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
gtk_css_node_invalidate (node, GTK_CSS_CHANGE_ANY_PARENT | GTK_CSS_CHANGE_ANY_SIBLING);
|
||||
|
||||
if (node->parent == NULL)
|
||||
g_object_unref (node);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user