[gtk+] cssnode: Refactor node tree modification code



commit 507016cafc407b2c47aea3fd1483df75e9757f29
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 816c667..92b165d 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 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]