[gtk+/gtk-style-context: 248/540] GtkContainer: Add method to get the GtkWidgetPath for a child.



commit 087c10afd9f6876201278a519a00b64a5a782e81
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Oct 11 00:23:40 2010 +0200

    GtkContainer: Add method to get the GtkWidgetPath for a child.
    
    This is now used throughout in order to have the full path for a given widget,
    including intermediate named regions, the default implementation just returns
    the GtkContainer's path copy, no intermediate regions between.

 gtk/gtkcontainer.c    |   22 ++++++++++
 gtk/gtkcontainer.h    |    5 ++
 gtk/gtkstylecontext.c |   21 +++++-----
 gtk/gtkwidget.c       |  105 +++++++++++++++++++------------------------------
 gtk/gtkwidgetpath.c   |   15 +++++++
 gtk/gtkwidgetpath.h   |    2 +
 6 files changed, 95 insertions(+), 75 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index a37e361..8c09ba2 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -334,6 +334,9 @@ static void     gtk_container_adjust_size_allocation (GtkWidget       *widget,
 static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
 							  GtkWidget    *child);
 
+static GtkWidgetPath * gtk_container_real_get_path_for_child (GtkContainer *container,
+                                                              GtkWidget    *child);
+
 /* GtkBuildable */
 static void gtk_container_buildable_init           (GtkBuildableIface *iface);
 static void gtk_container_buildable_add_child      (GtkBuildable *buildable,
@@ -465,6 +468,7 @@ gtk_container_class_init (GtkContainerClass *class)
   class->set_focus_child = gtk_container_real_set_focus_child;
   class->child_type = NULL;
   class->composite_name = gtk_container_child_default_composite_name;
+  class->get_path_for_child = gtk_container_real_get_path_for_child;
 
   g_object_class_install_property (gobject_class,
                                    PROP_RESIZE_MODE,
@@ -2207,6 +2211,13 @@ gtk_container_get_all_children (GtkContainer *container)
   return children;
 }
 
+static GtkWidgetPath *
+gtk_container_real_get_path_for_child (GtkContainer *container,
+                                       GtkWidget    *child)
+{
+  return gtk_widget_path_copy (gtk_widget_get_path (GTK_WIDGET (container)));
+}
+
 static gboolean
 gtk_container_focus (GtkWidget        *widget,
                      GtkDirectionType  direction)
@@ -3220,3 +3231,14 @@ _gtk_container_get_reallocate_redraws (GtkContainer *container)
 {
   return container->priv->reallocate_redraws;
 }
+
+GtkWidgetPath *
+gtk_container_get_path_for_child (GtkContainer *container,
+                                  GtkWidget    *child)
+{
+  g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
+  g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
+  g_return_val_if_fail (container == (GtkContainer *) gtk_widget_get_parent (child), NULL);
+
+  return GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
+}
diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h
index f469d89..94a8502 100644
--- a/gtk/gtkcontainer.h
+++ b/gtk/gtkcontainer.h
@@ -88,6 +88,8 @@ struct _GtkContainerClass
 				 guint            property_id,
 				 GValue          *value,
 				 GParamSpec      *pspec);
+  GtkWidgetPath * (*get_path_for_child) (GtkContainer *container,
+                                         GtkWidget    *child);
 
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
@@ -228,6 +230,9 @@ void     _gtk_container_set_need_resize      (GtkContainer     *container,
                                               gboolean          need_resize);
 gboolean _gtk_container_get_reallocate_redraws (GtkContainer   *container);
 
+GtkWidgetPath * gtk_container_get_path_for_child (GtkContainer      *container,
+                                                  GtkWidget         *child);
+
 G_END_DECLS
 
 #endif /* __GTK_CONTAINER_H__ */
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 69e7797..13d15f9 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -524,11 +524,14 @@ rebuild_properties (GtkStyleContext *context)
   priv = context->priv;
   list = priv->providers;
 
+  gtk_style_set_clear (priv->store);
+
+  if (!priv->widget_path)
+    return;
+
   if (priv->screen)
     global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
 
-  gtk_style_set_clear (priv->store);
-
   while ((elem = find_next_candidate (list, global_list)) != NULL)
     {
       GtkStyleProviderData *data;
@@ -566,11 +569,13 @@ rebuild_icon_factories (GtkStyleContext *context)
   GList *elem, *list, *global_list = NULL;
 
   priv = context->priv;
-
   g_slist_foreach (priv->icon_factories, (GFunc) g_object_unref, NULL);
   g_slist_free (priv->icon_factories);
   priv->icon_factories = NULL;
 
+  if (!priv->widget_path)
+    return;
+
   list = priv->providers_last;
 
   if (priv->screen)
@@ -948,10 +953,9 @@ gtk_style_context_set_path (GtkStyleContext *context,
     }
 
   if (path)
-    {
-      priv->widget_path = gtk_widget_path_copy (path);
-      gtk_style_context_invalidate (context);
-    }
+    priv->widget_path = gtk_widget_path_copy (path);
+
+  gtk_style_context_invalidate (context);
 }
 
 G_CONST_RETURN GtkWidgetPath *
@@ -1953,9 +1957,6 @@ gtk_style_context_invalidate (GtkStyleContext *context)
   if (priv->invalidating_context)
     return;
 
-  if (!priv->widget_path)
-    return;
-
   priv->invalidating_context = TRUE;
 
   rebuild_properties (context);
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 3dfbc6c..4da12a1 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -374,6 +374,9 @@ struct _GtkWidgetPrivate
   /* The widget's parent.
    */
   GtkWidget *parent;
+
+  /* Widget's path for styling */
+  GtkWidgetPath *path;
 };
 
 enum {
@@ -7229,6 +7232,18 @@ gtk_widget_is_sensitive (GtkWidget *widget)
   return widget->priv->sensitive && widget->priv->parent_sensitive;
 }
 
+static void
+_gtk_widget_update_path (GtkWidget *widget)
+{
+  if (widget->priv->path)
+    {
+      gtk_widget_path_free (widget->priv->path);
+      widget->priv->path = NULL;
+    }
+
+  gtk_widget_get_path (widget);
+}
+
 /**
  * gtk_widget_set_parent:
  * @widget: a #GtkWidget
@@ -7326,11 +7341,8 @@ gtk_widget_set_parent (GtkWidget *widget,
                                 quark_style_context);
   if (context)
     {
-      GtkWidgetPath *path;
-
-      path = gtk_widget_get_path (widget);
-      gtk_style_context_set_path (context, path);
-      gtk_widget_path_free (path);
+      _gtk_widget_update_path (widget);
+      gtk_style_context_set_path (context, widget->priv->path);
 
       gtk_style_context_set_screen (context,
                                     gtk_widget_get_screen (widget));
@@ -8139,7 +8151,10 @@ reset_style_recurse (GtkWidget *widget, gpointer data)
   context = g_object_get_qdata (G_OBJECT (widget),
                                 quark_style_context);
   if (context)
-    gtk_style_context_invalidate (context);
+    {
+      _gtk_widget_update_path (widget);
+      gtk_style_context_set_path (context, widget->priv->path);
+    }
 
   if (GTK_IS_CONTAINER (widget))
     gtk_container_forall (GTK_CONTAINER (widget),
@@ -13267,71 +13282,34 @@ _gtk_widget_set_height_request_needed (GtkWidget *widget,
 GtkWidgetPath *
 gtk_widget_get_path (GtkWidget *widget)
 {
-  GtkStyleContext *context;
-  GtkWidgetPath *path;
-  GtkWidget *parent;
-
   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
-  parent = widget->priv->parent;
-
-  path = gtk_widget_path_new ();
-  gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (widget));
-
-  if (widget->priv->name)
-    gtk_widget_path_iter_set_name (path, 0, widget->priv->name);
-
-  context = g_object_get_qdata (G_OBJECT (widget),
-                                quark_style_context);
-
-  if (context)
+  if (!widget->priv->path)
     {
-      GList *list, *l;
-
-      list = l = gtk_style_context_list_regions (context);
-
-      while (l)
-        {
-          GtkRegionFlags flags;
-          const gchar *region_name;
-
-          region_name = l->data;
-          l = l->next;
-
-          gtk_style_context_has_region (context, region_name, &flags);
-          gtk_widget_path_iter_add_region (path, 0, region_name, flags);
-        }
-
-      g_list_free (list);
+      GtkWidget *parent;
+      guint pos;
 
-      list = l = gtk_style_context_list_classes (context);
+      parent = widget->priv->parent;
 
-      while (l)
+      if (parent)
+        widget->priv->path = gtk_container_get_path_for_child (GTK_CONTAINER (parent), widget);
+      else
         {
-          const gchar *class_name;
-
-          class_name = l->data;
-          l = l->next;
-
-          gtk_widget_path_iter_add_class (path, 0, class_name);
+          /* Widget is either toplevel or unparented, treat both
+           * as toplevels style wise, since there are situations
+           * where style properties might be retrieved on that
+           * situation.
+           */
+          widget->priv->path = gtk_widget_path_new ();
         }
 
-      g_list_free (list);
-    }
-
-  while (parent)
-    {
-      guint position;
-
-      position = gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (parent));
-
-      if (parent->priv->name)
-        gtk_widget_path_iter_set_name (path, position, parent->priv->name);
+      pos = gtk_widget_path_append_type (widget->priv->path, G_OBJECT_TYPE (widget));
 
-      parent = parent->priv->parent;
+      if (widget->priv->name)
+        gtk_widget_path_iter_set_name (widget->priv->path, pos, widget->priv->name);
     }
 
-  return path;
+  return widget->priv->path;
 }
 
 static void
@@ -13355,8 +13333,6 @@ gtk_widget_get_style_context (GtkWidget *widget)
 
   if (G_UNLIKELY (!context))
     {
-      GtkWidgetPath *path;
-
       context = g_object_new (GTK_TYPE_STYLE_CONTEXT,
                               "direction", gtk_widget_get_direction (widget),
                               NULL);
@@ -13371,9 +13347,8 @@ gtk_widget_get_style_context (GtkWidget *widget)
       gtk_style_context_set_screen (context,
                                     gtk_widget_get_screen (widget));
 
-      path = gtk_widget_get_path (widget);
-      gtk_style_context_set_path (context, path);
-      gtk_widget_path_free (path);
+      _gtk_widget_update_path (widget);
+      gtk_style_context_set_path (context, widget->priv->path);
     }
 
   return context;
diff --git a/gtk/gtkwidgetpath.c b/gtk/gtkwidgetpath.c
index 933a2dc..c6cfbb5 100644
--- a/gtk/gtkwidgetpath.c
+++ b/gtk/gtkwidgetpath.c
@@ -129,6 +129,21 @@ gtk_widget_path_prepend_type (GtkWidgetPath *path,
   g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0);
 
   new.type = type;
+  g_array_prepend_val (path->elems, new);
+
+  return 0;
+}
+
+guint
+gtk_widget_path_append_type (GtkWidgetPath *path,
+                             GType          type)
+{
+  GtkPathElement new = { 0 };
+
+  g_return_val_if_fail (path != NULL, 0);
+  g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0);
+
+  new.type = type;
   g_array_append_val (path->elems, new);
 
   return path->elems->len - 1;
diff --git a/gtk/gtkwidgetpath.h b/gtk/gtkwidgetpath.h
index 234f79b..4e5c476 100644
--- a/gtk/gtkwidgetpath.h
+++ b/gtk/gtkwidgetpath.h
@@ -35,6 +35,8 @@ void            gtk_widget_path_free                (GtkWidgetPath       *path);
 
 guint           gtk_widget_path_length              (const GtkWidgetPath *path);
 
+guint           gtk_widget_path_append_type         (GtkWidgetPath       *path,
+                                                     GType                type);
 guint           gtk_widget_path_prepend_type        (GtkWidgetPath       *path,
                                                      GType                type);
 



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