[gtk+] widgetpath: Implement using GtkCssNodeDeclaration



commit c6a5a12922e99daff27b751d0ad6a0dfe13b8025
Author: Benjamin Otte <otte redhat com>
Date:   Sat Sep 12 02:59:38 2015 +0200

    widgetpath: Implement using GtkCssNodeDeclaration
    
    This removes a bunch of code but more importantly allows providing the
    declaration in CSS matchers.

 gtk/gtkcssnodedeclaration.c        |   15 ++
 gtk/gtkcssnodedeclarationprivate.h |    1 +
 gtk/gtkwidgetpath.c                |  309 ++++++++++--------------------------
 3 files changed, 103 insertions(+), 222 deletions(-)
---
diff --git a/gtk/gtkcssnodedeclaration.c b/gtk/gtkcssnodedeclaration.c
index 8e425a4..83bbb3d 100644
--- a/gtk/gtkcssnodedeclaration.c
+++ b/gtk/gtkcssnodedeclaration.c
@@ -450,6 +450,21 @@ gtk_css_node_declaration_remove_region (GtkCssNodeDeclaration **decl,
 }
 
 gboolean
+gtk_css_node_declaration_clear_regions (GtkCssNodeDeclaration **decl)
+{
+  if ((*decl)->n_regions == 0)
+    return FALSE;
+
+  gtk_css_node_declaration_make_writable_resize (decl,
+                                                 (char *) get_regions (*decl) - (char *) *decl,
+                                                 0,
+                                                 sizeof (GtkRegion) * (*decl)->n_regions);
+  (*decl)->n_regions = 0;
+
+  return TRUE;
+}
+
+gboolean
 gtk_css_node_declaration_has_region (const GtkCssNodeDeclaration  *decl,
                                      GQuark                        region_quark,
                                      GtkRegionFlags               *flags_return)
diff --git a/gtk/gtkcssnodedeclarationprivate.h b/gtk/gtkcssnodedeclarationprivate.h
index f1499b2..066b8e2 100644
--- a/gtk/gtkcssnodedeclarationprivate.h
+++ b/gtk/gtkcssnodedeclarationprivate.h
@@ -56,6 +56,7 @@ gboolean                gtk_css_node_declaration_add_region             (GtkCssN
                                                                          GtkRegionFlags                 
flags);
 gboolean                gtk_css_node_declaration_remove_region          (GtkCssNodeDeclaration        **decl,
                                                                          GQuark                         
region_quark);
+gboolean                gtk_css_node_declaration_clear_regions          (GtkCssNodeDeclaration        
**decl);
 gboolean                gtk_css_node_declaration_has_region             (const GtkCssNodeDeclaration   *decl,
                                                                          GQuark                         
region_quark,
                                                                          GtkRegionFlags                
*flags_return);
diff --git a/gtk/gtkwidgetpath.c b/gtk/gtkwidgetpath.c
index f83af29..a8504c0 100644
--- a/gtk/gtkwidgetpath.c
+++ b/gtk/gtkwidgetpath.c
@@ -17,13 +17,15 @@
 
 #include "config.h"
 
+#include "gtkwidgetpath.h"
+
 #include <string.h>
 
-#include "gtkwidget.h"
-#include "gtkwidgetpath.h"
+#include "gtkcssnodedeclarationprivate.h"
+#include "gtkprivate.h"
 #include "gtkstylecontextprivate.h"
 #include "gtktypebuiltins.h"
-#include "gtkprivate.h"
+#include "gtkwidget.h"
 
 /**
  * SECTION:gtkwidgetpath
@@ -88,12 +90,8 @@ typedef struct GtkPathElement GtkPathElement;
 
 struct GtkPathElement
 {
-  GType type;
-  GQuark name;
-  GtkStateFlags state;
+  GtkCssNodeDeclaration *decl;
   guint sibling_index;
-  GHashTable *regions;
-  GArray *classes;
   GtkWidgetPath *siblings;
 };
 
@@ -131,30 +129,10 @@ gtk_path_element_copy (GtkPathElement       *dest,
 {
   memset (dest, 0, sizeof (GtkPathElement));
 
-  dest->type = src->type;
-  dest->name = src->name;
-  dest->state = src->state;
+  dest->decl = gtk_css_node_declaration_ref (src->decl);
   if (src->siblings)
     dest->siblings = gtk_widget_path_ref (src->siblings);
   dest->sibling_index = src->sibling_index;
-
-  if (src->regions)
-    {
-      GHashTableIter iter;
-      gpointer key, value;
-
-      g_hash_table_iter_init (&iter, src->regions);
-      dest->regions = g_hash_table_new (NULL, NULL);
-
-      while (g_hash_table_iter_next (&iter, &key, &value))
-        g_hash_table_insert (dest->regions, key, value);
-    }
-
-  if (src->classes)
-    {
-      dest->classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
-      g_array_append_vals (dest->classes, src->classes->data, src->classes->len);
-    }
 }
 
 /**
@@ -237,14 +215,7 @@ gtk_widget_path_unref (GtkWidgetPath *path)
 
       elem = &g_array_index (path->elems, GtkPathElement, i);
 
-      if (elem->regions)
-        g_hash_table_destroy (elem->regions);
-
-      if (elem->classes)
-        g_array_free (elem->classes, TRUE);
-
-      if (elem->siblings)
-        gtk_widget_path_unref (elem->siblings);
+      gtk_css_node_declaration_unref (elem->decl);
     }
 
   g_array_free (path->elems, TRUE);
@@ -306,7 +277,7 @@ char *
 gtk_widget_path_to_string (const GtkWidgetPath *path)
 {
   GString *string;
-  guint i, j;
+  guint i, j, n;
 
   gtk_internal_return_val_if_fail (path != NULL, NULL);
 
@@ -315,29 +286,33 @@ gtk_widget_path_to_string (const GtkWidgetPath *path)
   for (i = 0; i < path->elems->len; i++)
     {
       GtkPathElement *elem;
+      GtkStateFlags state;
+      const GQuark *classes;
+      GList *list, *regions;
 
       elem = &g_array_index (path->elems, GtkPathElement, i);
 
       if (i > 0)
         g_string_append_c (string, ' ');
 
-      g_string_append (string, g_type_name (elem->type));
+      g_string_append (string, g_type_name (gtk_css_node_declaration_get_type (elem->decl)));
 
-      if (elem->name)
+      if (gtk_css_node_declaration_get_id (elem->decl))
         {
           g_string_append_c (string, '(');
-          g_string_append (string, g_quark_to_string (elem->name));
+          g_string_append (string, gtk_css_node_declaration_get_id (elem->decl));
           g_string_append_c (string, ')');
         }
 
-      if (elem->state)
+      state = gtk_css_node_declaration_get_state (elem->decl);
+      if (state)
         {
           GFlagsClass *fclass;
 
           fclass = g_type_class_ref (GTK_TYPE_STATE_FLAGS);
           for (j = 0; j < fclass->n_values; j++)
             {
-              if (elem->state & fclass->values[j].value)
+              if (state & fclass->values[j].value)
                 {
                   g_string_append_c (string, ':');
                   g_string_append (string, fclass->values[j].value_nick);
@@ -351,45 +326,40 @@ gtk_widget_path_to_string (const GtkWidgetPath *path)
                                 elem->sibling_index + 1,
                                 gtk_widget_path_length (elem->siblings));
 
-      if (elem->classes)
+      classes = gtk_css_node_declaration_get_classes (elem->decl, &n);
+      for (j = 0; j < n; j++)
         {
-          for (j = 0; j < elem->classes->len; j++)
-            {
-              g_string_append_c (string, '.');
-              g_string_append (string, g_quark_to_string (g_array_index (elem->classes, GQuark, j)));
-            }
+          g_string_append_c (string, '.');
+          g_string_append (string, g_quark_to_string (classes[j]));
         }
 
-      if (elem->regions)
+      regions = gtk_css_node_declaration_list_regions (elem->decl);
+      for (list = regions; list; list = list->next)
         {
-          GHashTableIter iter;
-          gpointer key, value;
-
-          g_hash_table_iter_init (&iter, elem->regions);
-          while (g_hash_table_iter_next (&iter, &key, &value))
+          static const char *flag_names[] = {
+            "even",
+            "odd",
+            "first",
+            "last",
+            "only",
+            "sorted"
+          };
+          GtkRegionFlags flags;
+          GQuark region = GPOINTER_TO_UINT (regions->data);
+
+          gtk_css_node_declaration_has_region (elem->decl, region, &flags);
+          g_string_append_c (string, ' ');
+          g_string_append (string, g_quark_to_string (region));
+          for (j = 0; j < G_N_ELEMENTS(flag_names); j++)
             {
-              GtkRegionFlags flags = GPOINTER_TO_UINT (value);
-              static const char *flag_names[] = {
-                "even",
-                "odd",
-                "first",
-                "last",
-                "only",
-                "sorted"
-              };
-
-              g_string_append_c (string, ' ');
-              g_string_append (string, g_quark_to_string (GPOINTER_TO_UINT (key)));
-              for (j = 0; j < G_N_ELEMENTS(flag_names); j++)
+              if (flags & (1 << j))
                 {
-                  if (flags & (1 << j))
-                    {
-                      g_string_append_c (string, ':');
-                      g_string_append (string, flag_names[j]);
-                    }
+                  g_string_append_c (string, ':');
+                  g_string_append (string, flag_names[j]);
                 }
             }
         }
+      g_list_free (regions);
     }
 
   return g_string_free (string, FALSE);
@@ -408,11 +378,13 @@ void
 gtk_widget_path_prepend_type (GtkWidgetPath *path,
                               GType          type)
 {
-  GtkPathElement new = { 0 };
+  GtkPathElement new = { NULL };
 
   gtk_internal_return_if_fail (path != NULL);
 
-  new.type = type;
+  new.decl = gtk_css_node_declaration_new ();
+  gtk_css_node_declaration_set_type (&new.decl, type);
+
   g_array_prepend_val (path->elems, new);
 }
 
@@ -431,11 +403,12 @@ gint
 gtk_widget_path_append_type (GtkWidgetPath *path,
                              GType          type)
 {
-  GtkPathElement new = { 0 };
+  GtkPathElement new = { NULL };
 
   gtk_internal_return_val_if_fail (path != NULL, 0);
 
-  new.type = type;
+  new.decl = gtk_css_node_declaration_new ();
+  gtk_css_node_declaration_set_type (&new.decl, type);
   g_array_append_val (path->elems, new);
 
   return path->elems->len - 1;
@@ -560,7 +533,7 @@ gtk_widget_path_iter_get_object_type (const GtkWidgetPath *path,
     pos = path->elems->len - 1;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
-  return elem->type;
+  return gtk_css_node_declaration_get_type (elem->decl);
 }
 
 /**
@@ -588,7 +561,7 @@ gtk_widget_path_iter_set_object_type (GtkWidgetPath *path,
     pos = path->elems->len - 1;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
-  elem->type = type;
+  gtk_css_node_declaration_set_type (&elem->decl, type);
 }
 
 /**
@@ -617,7 +590,7 @@ gtk_widget_path_iter_get_state (const GtkWidgetPath *path,
     pos = path->elems->len - 1;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
-  return elem->state;
+  return gtk_css_node_declaration_get_state (elem->decl);
 }
 
 /**
@@ -662,7 +635,7 @@ gtk_widget_path_iter_set_state (GtkWidgetPath *path,
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  elem->state = state;
+  gtk_css_node_declaration_set_state (&elem->decl, state);
 }
 
 /**
@@ -689,7 +662,7 @@ gtk_widget_path_iter_get_name (const GtkWidgetPath *path,
     pos = path->elems->len - 1;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
-  return g_quark_to_string (elem->name);
+  return gtk_css_node_declaration_get_id (elem->decl);
 }
 
 /**
@@ -719,7 +692,7 @@ gtk_widget_path_iter_set_name (GtkWidgetPath *path,
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  elem->name = g_quark_from_string (name);
+  gtk_css_node_declaration_set_id (&elem->decl, g_intern_string (name));
 }
 
 /**
@@ -740,18 +713,11 @@ gtk_widget_path_iter_has_qname (const GtkWidgetPath *path,
                                 gint                 pos,
                                 GQuark               qname)
 {
-  GtkPathElement *elem;
-
   gtk_internal_return_val_if_fail (path != NULL, FALSE);
   gtk_internal_return_val_if_fail (path->elems->len != 0, FALSE);
   gtk_internal_return_val_if_fail (qname != 0, FALSE);
 
-  if (pos < 0 || pos >= path->elems->len)
-    pos = path->elems->len - 1;
-
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
-
-  return (elem->name == qname);
+  return gtk_widget_path_iter_has_name (path, pos, g_quark_to_string (qname));
 }
 
 /**
@@ -772,7 +738,7 @@ gtk_widget_path_iter_has_name (const GtkWidgetPath *path,
                                gint                 pos,
                                const gchar         *name)
 {
-  GQuark qname;
+  GtkPathElement *elem;
 
   gtk_internal_return_val_if_fail (path != NULL, FALSE);
   gtk_internal_return_val_if_fail (path->elems->len != 0, FALSE);
@@ -780,12 +746,10 @@ gtk_widget_path_iter_has_name (const GtkWidgetPath *path,
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
-  qname = g_quark_try_string (name);
-
-  if (qname == 0)
-    return FALSE;
+  name = g_intern_string (name);
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  return gtk_widget_path_iter_has_qname (path, pos, qname);
+  return gtk_css_node_declaration_get_id (elem->decl) == name;
 }
 
 /**
@@ -809,6 +773,9 @@ gtk_widget_path_iter_add_class (GtkWidgetPath *path,
   gtk_internal_return_if_fail (path->elems->len != 0);
   gtk_internal_return_if_fail (name != NULL);
 
+  if (pos < 0 || pos >= path->elems->len)
+    pos = path->elems->len - 1;
+
   gtk_widget_path_iter_add_qclass (path, pos, g_quark_from_string (name));
 }
 
@@ -818,36 +785,10 @@ gtk_widget_path_iter_add_qclass (GtkWidgetPath *path,
                                  GQuark         qname)
 {
   GtkPathElement *elem;
-  gboolean added = FALSE;
-  guint i;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (!elem->classes)
-    elem->classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
-
-  for (i = 0; i < elem->classes->len; i++)
-    {
-      GQuark quark;
-
-      quark = g_array_index (elem->classes, GQuark, i);
-
-      if (qname == quark)
-        {
-          /* Already there */
-          added = TRUE;
-          break;
-        }
-      if (qname < quark)
-        {
-          g_array_insert_val (elem->classes, i, qname);
-          added = TRUE;
-          break;
-        }
-    }
-
-  if (!added)
-    g_array_append_val (elem->classes, qname);
+  gtk_css_node_declaration_add_class (&elem->decl, qname);
 }
 
 /**
@@ -868,7 +809,6 @@ gtk_widget_path_iter_remove_class (GtkWidgetPath *path,
 {
   GtkPathElement *elem;
   GQuark qname;
-  guint i;
 
   gtk_internal_return_if_fail (path != NULL);
   gtk_internal_return_if_fail (path->elems->len != 0);
@@ -877,30 +817,12 @@ gtk_widget_path_iter_remove_class (GtkWidgetPath *path,
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
   qname = g_quark_try_string (name);
-
   if (qname == 0)
     return;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
-
-  if (!elem->classes)
-    return;
-
-  for (i = 0; i < elem->classes->len; i++)
-    {
-      GQuark quark;
-
-      quark = g_array_index (elem->classes, GQuark, i);
-
-      if (quark > qname)
-        break;
-      else if (quark == qname)
-        {
-          g_array_remove_index (elem->classes, i);
-          break;
-        }
-    }
+  gtk_css_node_declaration_remove_class (&elem->decl, qname);
 }
 
 /**
@@ -927,11 +849,7 @@ gtk_widget_path_iter_clear_classes (GtkWidgetPath *path,
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (!elem->classes)
-    return;
-
-  if (elem->classes->len > 0)
-    g_array_remove_range (elem->classes, 0, elem->classes->len);
+  gtk_css_node_declaration_clear_classes (&elem->decl);
 }
 
 /**
@@ -955,7 +873,8 @@ gtk_widget_path_iter_list_classes (const GtkWidgetPath *path,
 {
   GtkPathElement *elem;
   GSList *list = NULL;
-  guint i;
+  const GQuark *classes;
+  guint i, n;
 
   gtk_internal_return_val_if_fail (path != NULL, NULL);
   gtk_internal_return_val_if_fail (path->elems->len != 0, NULL);
@@ -964,16 +883,11 @@ gtk_widget_path_iter_list_classes (const GtkWidgetPath *path,
     pos = path->elems->len - 1;
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
+  classes = gtk_css_node_declaration_get_classes (elem->decl, &n);
 
-  if (!elem->classes)
-    return NULL;
-
-  for (i = 0; i < elem->classes->len; i++)
+  for (i = 0; i < n; i++)
     {
-      GQuark quark;
-
-      quark = g_array_index (elem->classes, GQuark, i);
-      list = g_slist_prepend (list, (gchar *) g_quark_to_string (quark));
+      list = g_slist_prepend (list, (gchar *) g_quark_to_string (classes[i]));
     }
 
   return g_slist_reverse (list);
@@ -998,7 +912,6 @@ gtk_widget_path_iter_has_qclass (const GtkWidgetPath *path,
                                  GQuark               qname)
 {
   GtkPathElement *elem;
-  guint i;
 
   gtk_internal_return_val_if_fail (path != NULL, FALSE);
   gtk_internal_return_val_if_fail (path->elems->len != 0, FALSE);
@@ -1009,22 +922,7 @@ gtk_widget_path_iter_has_qclass (const GtkWidgetPath *path,
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (!elem->classes)
-    return FALSE;
-
-  for (i = 0; i < elem->classes->len; i++)
-    {
-      GQuark quark;
-
-      quark = g_array_index (elem->classes, GQuark, i);
-
-      if (quark == qname)
-        return TRUE;
-      else if (quark > qname)
-        break;
-    }
-
-  return FALSE;
+  return gtk_css_node_declaration_has_class (elem->decl, qname);
 }
 
 /**
@@ -1100,12 +998,7 @@ gtk_widget_path_iter_add_region (GtkWidgetPath  *path,
   elem = &g_array_index (path->elems, GtkPathElement, pos);
   qname = g_quark_from_string (name);
 
-  if (!elem->regions)
-    elem->regions = g_hash_table_new (NULL, NULL);
-
-  g_hash_table_insert (elem->regions,
-                       GUINT_TO_POINTER (qname),
-                       GUINT_TO_POINTER (flags));
+  gtk_css_node_declaration_add_region (&elem->decl, qname, flags);
 }
 
 /**
@@ -1136,15 +1029,12 @@ gtk_widget_path_iter_remove_region (GtkWidgetPath *path,
   if (pos < 0 || pos >= path->elems->len)
     pos = path->elems->len - 1;
 
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
   qname = g_quark_try_string (name);
-
   if (qname == 0)
     return;
 
-  elem = &g_array_index (path->elems, GtkPathElement, pos);
-
-  if (elem->regions)
-    g_hash_table_remove (elem->regions, GUINT_TO_POINTER (qname));
+  gtk_css_node_declaration_remove_region (&elem->decl, qname);
 }
 
 /**
@@ -1173,8 +1063,7 @@ gtk_widget_path_iter_clear_regions (GtkWidgetPath *path,
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (elem->regions)
-    g_hash_table_remove_all (elem->regions);
+  gtk_css_node_declaration_clear_regions (&elem->decl);
 }
 
 /**
@@ -1199,9 +1088,8 @@ gtk_widget_path_iter_list_regions (const GtkWidgetPath *path,
                                    gint                 pos)
 {
   GtkPathElement *elem;
-  GHashTableIter iter;
   GSList *list = NULL;
-  gpointer key;
+  GList *l, *wrong_list;
 
   gtk_internal_return_val_if_fail (path != NULL, NULL);
   gtk_internal_return_val_if_fail (path->elems->len != 0, NULL);
@@ -1211,18 +1099,12 @@ gtk_widget_path_iter_list_regions (const GtkWidgetPath *path,
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (!elem->regions)
-    return NULL;
-
-  g_hash_table_iter_init (&iter, elem->regions);
-
-  while (g_hash_table_iter_next (&iter, &key, NULL))
+  wrong_list = gtk_css_node_declaration_list_regions (elem->decl);
+  for (l = wrong_list; l; l = l->next)
     {
-      GQuark qname;
-
-      qname = GPOINTER_TO_UINT (key);
-      list = g_slist_prepend (list, (gchar *) g_quark_to_string (qname));
+      list = g_slist_prepend (list, (char *) g_quark_to_string (GPOINTER_TO_UINT (l->data)));
     }
+  g_list_free (wrong_list);
 
   return list;
 }
@@ -1250,7 +1132,6 @@ gtk_widget_path_iter_has_qregion (const GtkWidgetPath *path,
                                   GtkRegionFlags      *flags)
 {
   GtkPathElement *elem;
-  gpointer value;
 
   gtk_internal_return_val_if_fail (path != NULL, FALSE);
   gtk_internal_return_val_if_fail (path->elems->len != 0, FALSE);
@@ -1261,18 +1142,7 @@ gtk_widget_path_iter_has_qregion (const GtkWidgetPath *path,
 
   elem = &g_array_index (path->elems, GtkPathElement, pos);
 
-  if (!elem->regions)
-    return FALSE;
-
-  if (!g_hash_table_lookup_extended (elem->regions,
-                                     GUINT_TO_POINTER (qname),
-                                     NULL, &value))
-    return FALSE;
-
-  if (flags)
-    *flags = GPOINTER_TO_UINT (value);
-
-  return TRUE;
+  return gtk_css_node_declaration_has_region (elem->decl, qname, flags);
 }
 
 /**
@@ -1336,7 +1206,7 @@ gtk_widget_path_get_object_type (const GtkWidgetPath *path)
 
   elem = &g_array_index (path->elems, GtkPathElement,
                          path->elems->len - 1);
-  return elem->type;
+  return gtk_css_node_declaration_get_type (elem->decl);
 }
 
 /**
@@ -1362,11 +1232,7 @@ gtk_widget_path_is_type (const GtkWidgetPath *path,
   elem = &g_array_index (path->elems, GtkPathElement,
                          path->elems->len - 1);
 
-  if (elem->type == type ||
-      g_type_is_a (elem->type, type))
-    return TRUE;
-
-  return FALSE;
+  return g_type_is_a (gtk_css_node_declaration_get_type (elem->decl), type);
 }
 
 /**
@@ -1395,8 +1261,7 @@ gtk_widget_path_has_parent (const GtkWidgetPath *path,
 
       elem = &g_array_index (path->elems, GtkPathElement, i);
 
-      if (elem->type == type ||
-          g_type_is_a (elem->type, type))
+      if (g_type_is_a (gtk_css_node_declaration_get_type (elem->decl), type))
         return TRUE;
     }
 


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