[gtk+] cssnode: Add node-added and node-removed signal



commit 6988f9b818c398511378de5a28cd68b53745110b
Author: Benjamin Otte <otte redhat com>
Date:   Sun Mar 1 21:33:54 2015 +0100

    cssnode: Add node-added and node-removed signal
    
    This allows monitoring the CSS tree. For now, moving a child to a
    different position relative to its siblings while keeping the same
    parent will cause a child-added + child-removed emission.

 gtk/gtkcssnode.c        |  156 ++++++++++++++++++++++++++++++-----------------
 gtk/gtkcssnodeprivate.h |    7 ++
 2 files changed, 107 insertions(+), 56 deletions(-)
---
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 462d550..e31690a 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -21,6 +21,8 @@
 
 #include "gtkcssanimatedstyleprivate.h"
 #include "gtkdebug.h"
+#include "gtkintl.h"
+#include "gtkmarshalers.h"
 #include "gtksettingsprivate.h"
 
 /* When these change we do a full restyling. Otherwise we try to figure out
@@ -29,6 +31,14 @@
 
 G_DEFINE_TYPE (GtkCssNode, gtk_css_node, G_TYPE_OBJECT)
 
+enum {
+  NODE_ADDED,
+  NODE_REMOVED,
+  LAST_SIGNAL
+};
+
+static guint cssnode_signals[LAST_SIGNAL] = { 0 };
+
 static GtkStyleProviderPrivate *
 gtk_css_node_get_style_provider_or_null (GtkCssNode *cssnode)
 {
@@ -333,6 +343,51 @@ gtk_css_node_real_get_frame_clock (GtkCssNode *cssnode)
 }
 
 static void
+gtk_css_node_real_node_removed (GtkCssNode *parent,
+                                GtkCssNode *node,
+                                GtkCssNode *previous)
+{
+  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;
+  node->parent = NULL;
+}
+
+static void
+gtk_css_node_real_node_added (GtkCssNode *parent,
+                              GtkCssNode *node,
+                              GtkCssNode *new_previous)
+{
+  if (new_previous)
+    {
+      node->previous_sibling = new_previous;
+      node->next_sibling = new_previous->next_sibling;
+      new_previous->next_sibling = node;
+    }
+  else
+    {
+      node->next_sibling = parent->first_child;
+      parent->first_child = node;
+    }
+
+  if (node->next_sibling)
+    node->next_sibling->previous_sibling = node;
+  else
+    parent->last_child = node;
+
+  node->parent = parent;
+}
+
+static void
 gtk_css_node_class_init (GtkCssNodeClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -350,6 +405,28 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
   klass->get_widget_path = gtk_css_node_real_get_widget_path;
   klass->get_style_provider = gtk_css_node_real_get_style_provider;
   klass->get_frame_clock = gtk_css_node_real_get_frame_clock;
+
+  klass->node_added = gtk_css_node_real_node_added;
+  klass->node_removed = gtk_css_node_real_node_removed;
+
+  cssnode_signals[NODE_ADDED] =
+    g_signal_new (I_("node-added"),
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkCssNodeClass, node_added),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__OBJECT_OBJECT,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_CSS_NODE, GTK_TYPE_CSS_NODE);
+  cssnode_signals[NODE_REMOVED] =
+    g_signal_new (I_("node-removed"),
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkCssNodeClass, node_removed),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__OBJECT_OBJECT,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_CSS_NODE, GTK_TYPE_CSS_NODE);
 }
 
 static void
@@ -397,44 +474,6 @@ 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 (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 (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)
@@ -464,23 +503,28 @@ gtk_css_node_invalidate_style (GtkCssNode *cssnode)
 
 static void
 gtk_css_node_reposition (GtkCssNode *node,
-                         GtkCssNode *parent,
+                         GtkCssNode *new_parent,
                          GtkCssNode *previous)
 {
-  g_assert (! (parent == NULL && previous != NULL));
+  GtkCssNode *old_parent;
 
+  g_assert (! (new_parent == NULL && previous != NULL));
+
+  old_parent = node->parent;
   /* Take a reference here so the whole function has a reference */
   g_object_ref (node);
 
   if (node->next_sibling)
     gtk_css_node_invalidate_style (node->next_sibling);
 
-  if (node->parent != NULL)
-    gtk_css_node_unlink_from_siblings (node);
+  if (old_parent != NULL)
+    {
+      g_signal_emit (old_parent, cssnode_signals[NODE_REMOVED], 0, node, node->previous_sibling);
+    }
 
-  if (node->parent != parent)
+  if (old_parent != new_parent)
     {
-      if (node->parent == NULL)
+      if (old_parent == NULL)
         {
           gtk_css_node_parent_will_be_set (node);
         }
@@ -488,34 +532,34 @@ gtk_css_node_reposition (GtkCssNode *node,
         {
           g_object_unref (node);
           if (node->visible)
-            gtk_css_node_set_children_changed (node->parent);
+            gtk_css_node_set_children_changed (old_parent);
         }
 
-      node->parent = parent;
+      if (gtk_css_node_get_style_provider_or_null (node) == NULL)
+        gtk_css_node_invalidate_style_provider (node);
+      gtk_css_node_invalidate (node, GTK_CSS_CHANGE_TIMESTAMP | GTK_CSS_CHANGE_ANIMATIONS);
 
-      if (parent)
+      if (new_parent)
         {
           if (node->visible)
-            gtk_css_node_set_children_changed (parent);
+            gtk_css_node_set_children_changed (new_parent);
           g_object_ref (node);
 
           if (node->pending_changes)
-            parent->needs_propagation = TRUE;
+            new_parent->needs_propagation = TRUE;
           if (node->invalid && node->visible)
-            gtk_css_node_set_invalid (parent, TRUE);
+            gtk_css_node_set_invalid (new_parent, TRUE);
         }
       else
         {
           gtk_css_node_parent_was_unset (node);
         }
-
-      if (gtk_css_node_get_style_provider_or_null (node) == NULL)
-        gtk_css_node_invalidate_style_provider (node);
-      gtk_css_node_invalidate (node, GTK_CSS_CHANGE_TIMESTAMP | GTK_CSS_CHANGE_ANIMATIONS);
     }
 
-  if (parent)
-    gtk_css_node_link_to_siblings (node, previous);
+  if (new_parent)
+    {
+      g_signal_emit (new_parent, cssnode_signals[NODE_ADDED], 0, node, previous);
+    }
 
   if (node->next_sibling)
     gtk_css_node_invalidate_style (node->next_sibling);
diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h
index 611bc71..6cc9f72 100644
--- a/gtk/gtkcssnodeprivate.h
+++ b/gtk/gtkcssnodeprivate.h
@@ -65,6 +65,13 @@ struct _GtkCssNodeClass
 {
   GObjectClass object_class;
 
+  void                  (* node_added)                  (GtkCssNode            *cssnode,
+                                                         GtkCssNode            *child,
+                                                         GtkCssNode            *previous);
+  void                  (* node_removed)                (GtkCssNode            *cssnode,
+                                                         GtkCssNode            *child,
+                                                         GtkCssNode            *previous);
+
   gboolean              (* init_matcher)                (GtkCssNode            *cssnode,
                                                          GtkCssMatcher         *matcher);
   GtkWidgetPath *       (* create_widget_path)          (GtkCssNode            *cssnode);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]