[gtk+/wip/cssnode3: 42/46] cssnode: Refactor node tree modification code
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/cssnode3: 42/46] cssnode: Refactor node tree modification code
- Date: Tue, 10 Feb 2015 01:58:38 +0000 (UTC)
commit 022a60946065934ca0d3cbc9d2f8a6e575870dff
Author: Benjamin Otte <otte redhat com>
Date: Mon Feb 9 22:03:13 2015 +0100
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.
gtk/gtkcssnode.c | 142 +++++++++++++++++++++++++++++++---------------
gtk/gtkcssnodeprivate.h | 2 +-
2 files changed, 97 insertions(+), 47 deletions(-)
---
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 8a9027c..83ba092 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -206,73 +206,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 *
@@ -637,6 +682,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;
@@ -670,11 +720,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 4207d2f..b1339b0 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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]