[gtk+/gtk-style-context: 70/490] Refurbish GtkWidgetPath API.



commit 12a5252fb6469e3a3fc07a4d95100025d52210e0
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Apr 21 01:27:46 2010 +0200

    Refurbish GtkWidgetPath API.
    
    The foreach() function is now gone, there's now API to get
    GTypes and names from the position in the path.

 gtk/gtkcssprovider.c |  115 ++++++++++++++++--------------
 gtk/gtkwidget.c      |    4 +-
 gtk/gtkwidgetpath.c  |  191 +++++++++++++++++++++++++++-----------------------
 gtk/gtkwidgetpath.h  |   32 +++++----
 4 files changed, 185 insertions(+), 157 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 8fbddc2..039f4a0 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -271,15 +271,12 @@ struct ComparePathData
 };
 
 static gboolean
-compare_path_foreach (GType        type,
-                      const gchar *name,
-                      gpointer     user_data)
+compare_selector_element (GtkWidgetPath   *path,
+                          guint            index,
+                          SelectorElement *elem,
+                          guint8          *score)
 {
-  ComparePathData *data;
-  SelectorElement *elem;
-
-  data = user_data;
-  elem = data->iter->data;
+  *score = 0;
 
   if (elem->elem_type == SELECTOR_TYPE_NAME)
     {
@@ -295,8 +292,7 @@ compare_path_foreach (GType        type,
           /* Type couldn't be resolved, so the selector
            * clearly doesn't affect the given widget path
            */
-          data->score = 0;
-          return TRUE;
+          return FALSE;
         }
 
       elem->elem_type = SELECTOR_GTYPE;
@@ -305,84 +301,95 @@ compare_path_foreach (GType        type,
 
   if (elem->elem_type == SELECTOR_GTYPE)
     {
+      GType type;
+
+      type = gtk_widget_path_get_element_type (path, index);
+
       if (!g_type_is_a (type, elem->type))
-        {
-          /* Selector definitely doesn't match */
-          if (elem->combinator == COMBINATOR_CHILD)
-            {
-              data->score = 0;
-              return TRUE;
-            }
-          else
-            {
-              /* Keep checking descendants for a match */
-              return FALSE;
-            }
-        }
-      else if (type == elem->type)
-        data->score |= 0xF;
+        return FALSE;
+
+      if (type == elem->type)
+        *score |= 0xF;
       else
         {
           GType parent = type;
-          guint8 score = 0xE;
+
+          *score = 0xE;
 
           while ((parent = g_type_parent (parent)) != G_TYPE_INVALID)
             {
               if (parent == elem->type)
                 break;
 
-              score--;
+              *score -= 1;
 
-              if (score == 1)
+              if (*score == 1)
                 {
                   g_warning ("Hierarchy is higher than expected.");
                   break;
                 }
             }
-
-          data->score |= score;
         }
+
+      return TRUE;
     }
   else if (elem->elem_type == SELECTOR_GLOB)
     {
       /* Treat as lowest matching type */
-      data->score++;
-    }
-
-  data->iter = data->iter->next;
-
-  if (data->iter)
-    {
-      data->score <<= 4;
-      return FALSE;
+      *score = 1;
+      return TRUE;
     }
 
-  return TRUE;
+  return FALSE;
 }
 
 static guint64
 compare_selector (GtkWidgetPath *path,
                   SelectorPath  *selector)
 {
-  ComparePathData data;
+  GSList *elements = selector->elements;
+  gboolean match = TRUE;
+  guint64 score = 0;
+  guint i = 0;
+
+  while (elements && match &&
+         i < gtk_widget_path_length (path))
+    {
+      SelectorElement *elem;
+      guint8 elem_score;
 
-  data.score = 0;
-  data.path = selector;
-  data.iter = selector->elements;
+      elem = elements->data;
+      elements = elements->next;
 
-  gtk_widget_path_foreach (path,
-                           compare_path_foreach,
-                           &data);
+      match = compare_selector_element (path, i, elem, &elem_score);
+      i++;
 
-  if (data.iter)
-    {
-      /* There is remaining data to compare,
-       * so don't take it as a match.
-       */
-      data.score = 0;
+      if (!match && elem->combinator == COMBINATOR_DESCENDANT)
+        {
+          /* With descendant combinators there may
+           * be intermediate chidren in the hierarchy
+           */
+          match = TRUE;
+        }
+
+      if (match)
+        {
+          score <<= 4;
+          score |= elem_score;
+        }
     }
 
-  return data.score;
+  /* If there are pending selector
+   * elements to compare, it's not
+   * a match.
+   */
+  if (elements)
+    match = FALSE;
+
+  if (!match)
+    score = 0;
+
+  return score;
 }
 
 typedef struct StylePriorityInfo StylePriorityInfo;
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index cdfcdfd..155b607 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -13221,9 +13221,7 @@ gtk_widget_get_path (GtkWidget *widget)
 
   while (widget)
     {
-      gtk_widget_path_prepend_widget_desc (path,
-                                           G_OBJECT_TYPE (widget),
-                                           widget->name);
+      gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (widget));
       widget = widget->parent;
     }
 
diff --git a/gtk/gtkwidgetpath.c b/gtk/gtkwidgetpath.c
index 2af624f..a6cfccc 100644
--- a/gtk/gtkwidgetpath.c
+++ b/gtk/gtkwidgetpath.c
@@ -34,8 +34,7 @@ struct GtkPathElement
 
 struct GtkWidgetPath
 {
-  GSList *elems;
-  GSList *last; /* Last element contains the described widget */
+  GArray *elems; /* First element contains the described widget */
 };
 
 GtkWidgetPath *
@@ -44,139 +43,157 @@ gtk_widget_path_new (void)
   GtkWidgetPath *path;
 
   path = g_slice_new0 (GtkWidgetPath);
+  path->elems = g_array_new (FALSE, TRUE, sizeof (GtkPathElement));
 
   return path;
 }
 
-static GtkPathElement *
-path_element_new (GType        type,
-                  const gchar *name)
+GtkWidgetPath *
+gtk_widget_path_copy (const GtkWidgetPath *path)
 {
-  GtkPathElement *elem;
+  GtkWidgetPath *new_path;
+  guint i;
 
-  elem = g_slice_new (GtkPathElement);
-  elem->type = type;
-  elem->name = g_strdup (name);
+  g_return_val_if_fail (path != NULL, NULL);
 
-  return elem;
-}
+  new_path = gtk_widget_path_new ();
 
-static void
-path_element_free (GtkPathElement *elem)
-{
-  g_free (elem->name);
-  g_slice_free (GtkPathElement, elem);
+  for (i = 0; i < path->elems->len; i++)
+    {
+      GtkPathElement *elem, new = { 0 };
+
+      elem = &g_array_index (path->elems, GtkPathElement, i);
+
+      new.type = elem->type;
+      new.name = g_strdup (elem->name);
+
+      g_array_append_val (new_path->elems, new);
+    }
+
+  return new_path;
 }
 
 void
-gtk_widget_path_prepend_widget_desc (GtkWidgetPath *path,
-                                     GType          type,
-                                     const gchar   *name)
+gtk_widget_path_free (GtkWidgetPath *path)
 {
+  guint i;
+
   g_return_if_fail (path != NULL);
-  g_return_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET));
 
-  if (!path->elems)
+  for (i = 0; i < path->elems->len; i++)
     {
-      path->elems = g_slist_prepend (NULL, path_element_new (type, name));
-      path->last = path->elems;
-    }
-  else
-    {
-      path->last->next = g_slist_alloc ();
-      path->last->next->data = path_element_new (type, name);
-      path->last = path->last->next;
+      GtkPathElement *elem;
+
+      elem = &g_array_index (path->elems, GtkPathElement, i);
+      g_free (elem->name);
     }
+
+  g_array_free (path->elems, TRUE);
+  g_slice_free (GtkWidgetPath, path);
 }
 
-GtkWidgetPath *
-gtk_widget_path_copy (GtkWidgetPath *path)
+guint
+gtk_widget_path_length (GtkWidgetPath *path)
 {
-  GtkWidgetPath *new_path;
-  GSList *elems;
-
-  new_path = gtk_widget_path_new ();
-  elems = path->elems;
+  g_return_val_if_fail (path != NULL, 0);
 
-  while (elems)
-    {
-      GtkPathElement *elem;
-      GSList *link;
+  return path->elems->len;
+}
 
-      elem = elems->data;
-      link = g_slist_alloc ();
-      link->data = path_element_new (elem->type, elem->name);
+guint
+gtk_widget_path_prepend_type (GtkWidgetPath *path,
+                              GType          type)
+{
+  GtkPathElement new = { 0 };
 
-      if (!new_path->elems)
-        new_path->last = new_path->elems = link;
-      else
-        {
-          new_path->last->next = link;
-          new_path->last = link;
-        }
+  g_return_val_if_fail (path != NULL, 0);
+  g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0);
 
-      elems = elems->next;
-    }
+  new.type = type;
+  g_array_append_val (path->elems, new);
 
-  return new_path;
+  return path->elems->len - 1;
 }
 
-void
-gtk_widget_path_free (GtkWidgetPath *path)
+GType
+gtk_widget_path_get_element_type (GtkWidgetPath *path,
+                                  guint          pos)
 {
-  g_return_if_fail (path != NULL);
+  GtkPathElement *elem;
 
-  g_slist_foreach (path->elems, (GFunc) path_element_free, NULL);
-  g_slist_free (path->elems);
+  g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
+  g_return_val_if_fail (pos < path->elems->len, G_TYPE_INVALID);
 
-  g_slice_free (GtkWidgetPath, path);
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  return elem->type;
 }
 
-gboolean
-gtk_widget_path_has_parent (GtkWidgetPath *path,
-                            GType          type)
+void
+gtk_widget_path_set_element_type (GtkWidgetPath *path,
+                                  guint          pos,
+                                  GType          type)
 {
-  g_return_val_if_fail (path != NULL, FALSE);
-  g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE);
+  GtkPathElement *elem;
 
-  GSList *elems = path->elems;
+  g_return_if_fail (path != NULL);
+  g_return_if_fail (pos < path->elems->len);
+  g_return_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET));
 
-  while (elems)
-    {
-      GtkPathElement *elem;
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  elem->type = type;
+}
 
-      elem = elems->data;
+G_CONST_RETURN gchar *
+gtk_widget_path_get_element_name (GtkWidgetPath *path,
+                                  guint          pos)
+{
+  GtkPathElement *elem;
 
-      if (elem->type == type ||
-          g_type_is_a (elem->type, type))
-        return TRUE;
+  g_return_val_if_fail (path != NULL, NULL);
+  g_return_val_if_fail (pos < path->elems->len, NULL);
 
-      elems = elems->next;
-    }
-
-  return FALSE;
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
+  return elem->name;
 }
 
 void
-gtk_widget_path_foreach (GtkWidgetPath            *path,
-                         GtkWidgetPathForeachFunc  func,
-                         gpointer                  user_data)
+gtk_widget_path_set_element_name (GtkWidgetPath *path,
+                                  guint          pos,
+                                  const gchar   *name)
 {
-  GSList *elems;
+  GtkPathElement *elem;
 
   g_return_if_fail (path != NULL);
-  g_return_if_fail (func != NULL);
+  g_return_if_fail (pos < path->elems->len);
+  g_return_if_fail (name != NULL);
+
+  elem = &g_array_index (path->elems, GtkPathElement, pos);
+
+  if (elem->name)
+    g_free (elem->name);
+
+  elem->name = g_strdup (name);
+}
+
+gboolean
+gtk_widget_path_has_parent (const GtkWidgetPath *path,
+                            GType                type)
+{
+  guint i;
 
-  elems = path->elems;
+  g_return_val_if_fail (path != NULL, FALSE);
+  g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE);
 
-  while (elems)
+  for (i = 1; i < path->elems->len; i++)
     {
       GtkPathElement *elem;
 
-      elem = elems->data;
-      elems = elems->next;
+      elem = &g_array_index (path->elems, GtkPathElement, i);
 
-      if ((func) (elem->type, elem->name, user_data))
-        return;
+      if (elem->type == type ||
+          g_type_is_a (elem->type, type))
+        return TRUE;
     }
+
+  return FALSE;
 }
diff --git a/gtk/gtkwidgetpath.h b/gtk/gtkwidgetpath.h
index 664562c..3846988 100644
--- a/gtk/gtkwidgetpath.h
+++ b/gtk/gtkwidgetpath.h
@@ -21,31 +21,37 @@
 #define __GTK_WIDGET_PATH_H__
 
 #include <glib-object.h>
+#include "gtkenums.h"
 
 G_BEGIN_DECLS
 
 typedef struct GtkWidgetPath GtkWidgetPath;
 
-typedef gboolean (* GtkWidgetPathForeachFunc) (GType        type,
-                                               const gchar *name,
-                                               gpointer     user_data);
 
 GtkWidgetPath * gtk_widget_path_new (void);
 
-void            gtk_widget_path_prepend_widget_desc (GtkWidgetPath *path,
-                                                     GType          type,
-                                                     const gchar   *name);
+GtkWidgetPath * gtk_widget_path_copy                (const GtkWidgetPath *path);
+void            gtk_widget_path_free                (GtkWidgetPath       *path);
 
-GtkWidgetPath * gtk_widget_path_copy                (GtkWidgetPath *path);
-void            gtk_widget_path_free                (GtkWidgetPath *path);
+guint           gtk_widget_path_length              (GtkWidgetPath       *path);
 
-gboolean        gtk_widget_path_has_parent          (GtkWidgetPath *path,
-                                                     GType          type);
+guint           gtk_widget_path_prepend_type        (GtkWidgetPath       *path,
+                                                     GType                type);
 
-void            gtk_widget_path_foreach             (GtkWidgetPath            *path,
-                                                     GtkWidgetPathForeachFunc  func,
-                                                     gpointer                  user_data);
+GType               gtk_widget_path_get_element_type (GtkWidgetPath      *path,
+                                                      guint               pos);
+void                gtk_widget_path_set_element_type (GtkWidgetPath      *path,
+                                                      guint               pos,
+                                                      GType               type);
 
+G_CONST_RETURN gchar * gtk_widget_path_get_element_name (GtkWidgetPath   *path,
+                                                         guint            pos);
+void                   gtk_widget_path_set_element_name (GtkWidgetPath   *path,
+                                                         guint            pos,
+                                                         const gchar     *name);
+
+gboolean        gtk_widget_path_has_parent          (const GtkWidgetPath *path,
+                                                     GType                type);
 
 G_END_DECLS
 



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