diff options
author | Benjamin Otte <otte@redhat.com> | 2015-02-09 22:03:13 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2015-03-18 15:23:31 +0100 |
commit | 507016cafc407b2c47aea3fd1483df75e9757f29 (patch) | |
tree | ccc744f661a37d0c21cf75e3b402ab1ffa6a40be /gtk | |
parent | 310f9f40dac12471197e33d745ae46dd0d8aeb22 (diff) | |
download | gtk+-507016cafc407b2c47aea3fd1483df75e9757f29.tar.gz |
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.
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkcssnode.c | 142 | ||||
-rw-r--r-- | gtk/gtkcssnodeprivate.h | 2 |
2 files changed, 97 insertions, 47 deletions
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c index 816c667d3d..92b165dfa3 100644 --- a/gtk/gtkcssnode.c +++ b/gtk/gtkcssnode.c @@ -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; diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h index 4207d2ff56..b1339b0b9c 100644 --- a/gtk/gtkcssnodeprivate.h +++ b/gtk/gtkcssnodeprivate.h @@ -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 |