stylecontext: Handle parent in CssNode code
authorBenjamin Otte <otte@redhat.com>
Mon, 26 Jan 2015 01:18:06 +0000 (02:18 +0100)
committerBenjamin Otte <otte@redhat.com>
Wed, 18 Mar 2015 14:23:29 +0000 (15:23 +0100)
Make CssNode a real tree with a DOM-like API.

gtk/gtkcssnode.c
gtk/gtkcssnodeprivate.h
gtk/gtkstylecontext.c
gtk/gtkwidget.c

index 6e0b9627bd30ccbeb48aeef4868656e4ef233a2d..4e3301046001cd2802665ef57f17dafdf27c219c 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "gtkcssnodeprivate.h"
 
+#include "gtkcsstransientnodeprivate.h"
+
 G_DEFINE_TYPE (GtkCssNode, gtk_css_node, G_TYPE_OBJECT)
 
 static void
@@ -70,10 +72,55 @@ gtk_css_node_init (GtkCssNode *cssnode)
 }
 
 void
-gtk_css_node_set_parent (GtkCssNode *cssnode,
+gtk_css_node_set_parent (GtkCssNode *node,
                          GtkCssNode *parent)
 {
-  cssnode->parent = parent;
+  if (node->parent == parent)
+    return;
+
+  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;
+    }
+
+  if (parent)
+    {
+      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;
+        }
+    }
+
+  gtk_css_node_invalidate (node, GTK_CSS_CHANGE_ANY_PARENT | GTK_CSS_CHANGE_ANY_SIBLING);
 }
 
 GtkCssNode *
@@ -82,6 +129,30 @@ gtk_css_node_get_parent (GtkCssNode *cssnode)
   return cssnode->parent;
 }
 
+GtkCssNode *
+gtk_css_node_get_first_child (GtkCssNode *cssnode)
+{
+  return cssnode->first_child;
+}
+
+GtkCssNode *
+gtk_css_node_get_last_child (GtkCssNode *cssnode)
+{
+  return cssnode->last_child;
+}
+
+GtkCssNode *
+gtk_css_node_get_previous_sibling (GtkCssNode *cssnode)
+{
+  return cssnode->previous_sibling;
+}
+
+GtkCssNode *
+gtk_css_node_get_next_sibling (GtkCssNode *cssnode)
+{
+  return cssnode->next_sibling;
+}
+
 void
 gtk_css_node_set_style (GtkCssNode  *cssnode,
                         GtkCssStyle *style)
index 46aafb01a72db2fcd1fa6221ca750b9a7b3b5ff0..c00c8754da7fdb59a8ac248e65cb698b17c00f3c 100644 (file)
@@ -37,8 +37,14 @@ struct _GtkCssNode
 {
   GObject object;
 
+  GtkCssNode *parent;
+  GtkCssNode *previous_sibling;
+  GtkCssNode *next_sibling;
+  GtkCssNode *first_child;
+  GtkCssNode *last_child;
+  guint n_children;
+
   GtkCssNodeDeclaration *decl;
-  GtkCssNode            *parent;
   GtkCssStyle           *style;
 };
 
@@ -57,6 +63,10 @@ GType                   gtk_css_node_get_type           (void) G_GNUC_CONST;
 void                    gtk_css_node_set_parent         (GtkCssNode            *cssnode,
                                                          GtkCssNode            *parent);
 GtkCssNode *            gtk_css_node_get_parent         (GtkCssNode            *cssnode);
+GtkCssNode *            gtk_css_node_get_first_child    (GtkCssNode            *cssnode);
+GtkCssNode *            gtk_css_node_get_last_child     (GtkCssNode            *cssnode);
+GtkCssNode *            gtk_css_node_get_previous_sibling(GtkCssNode           *cssnode);
+GtkCssNode *            gtk_css_node_get_next_sibling   (GtkCssNode            *cssnode);
 
 void                    gtk_css_node_set_widget_type    (GtkCssNode            *cssnode,
                                                          GType                  widget_type);
index 3b5e4cd07c00c1b4212f6b1f444d116d7bd3833f..681d9e3f58a69e254327a72e07dd881fba01cb9e 100644 (file)
@@ -288,22 +288,14 @@ static GtkCssStyle *
 gtk_css_node_get_parent_style (GtkStyleContext *context,
                                GtkCssNode      *cssnode)
 {
-  GtkStyleContextPrivate *priv;
   GtkCssNode *parent;
 
   parent = gtk_css_node_get_parent (cssnode);
 
-  g_assert (parent == NULL || gtk_css_node_get_style (parent) != NULL);
-
-  if (parent)
-    return gtk_css_node_get_style (parent);
-
-  priv = context->priv;
-
-  if (priv->parent)
-    return gtk_style_context_lookup_style (priv->parent);
-
-  return NULL;
+  if (parent == NULL)
+    return NULL;
+  
+  return gtk_css_node_get_style (parent);
 }
 
 static void
@@ -1513,6 +1505,12 @@ gtk_style_context_set_parent (GtkStyleContext *context,
       g_object_ref (parent);
       if (priv->invalid)
         gtk_style_context_set_invalid (parent, TRUE);
+      gtk_css_node_set_parent (gtk_style_context_get_root (context),
+                               gtk_style_context_get_root (parent));
+    }
+  else
+    {
+      gtk_css_node_set_parent (gtk_style_context_get_root (context), NULL);
     }
 
   gtk_style_context_clear_parent (context);
index 25ba751bf6d2bac6be469cf14de2819da11b4d7e..00c8c4b6d6d5524680d60432bb125b1cb9bca49f 100644 (file)
@@ -16444,11 +16444,11 @@ gtk_widget_get_style_context (GtkWidget *widget)
       if (frame_clock)
         gtk_style_context_set_frame_clock (priv->context, frame_clock);
 
+      _gtk_style_context_set_widget (priv->context, widget);
+
       if (priv->parent)
         gtk_style_context_set_parent (priv->context,
                                       gtk_widget_get_style_context (priv->parent));
-
-      _gtk_style_context_set_widget (priv->context, widget);
     }
 
   return widget->priv->context;