[gtk+] Return an appropriate GtkStyle from gtk_rc_get_style_by_paths()



commit a2dddb1da06aacef356cd7f0982b98ed3d5bb639
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Mon Dec 20 13:48:44 2010 -0500

    Return an appropriate GtkStyle from gtk_rc_get_style_by_paths()
    
    Always returning NULL (no match) from gtk_rc_get_style_by_paths()
    means that looking up colors and style properties based on the
    GtkStyle will give default values instead of themed values. We can
    do better by returning a GtkStyle based on a GtkWidgetPath that we
    figure out from the values passed in to get_style_by_paths().
    
    https://bugzilla.gnome.org/show_bug.cgi?id=637520

 gtk/gtkrc.c    |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkstyle.c |   31 ++++++++++++++++------
 gtk/gtkstyle.h |    4 +++
 3 files changed, 103 insertions(+), 10 deletions(-)
---
diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c
index 44b0371..b0d99c8 100644
--- a/gtk/gtkrc.c
+++ b/gtk/gtkrc.c
@@ -807,7 +807,83 @@ gtk_rc_get_style_by_paths (GtkSettings *settings,
 			   const char  *class_path,
 			   GType        type)
 {
-  return NULL;
+  GtkWidgetPath *path;
+  GtkStyle *style;
+
+  path = gtk_widget_path_new ();
+
+  /* For compatibility, we return a GtkStyle based on a GtkStyleContext
+   * with a GtkWidgetPath appropriate for the supplied information.
+   *
+   * GtkWidgetPath is composed of a list of GTypes with optional names;
+   * In GTK+-2.0, widget_path consisted of the widget names, or
+   * the class names for unnamed widgets, while class_path had the
+   * class names always. So, use class_path to determine the GTypes
+   * and extract widget names from widget_path as applicable.
+   */
+  if (class_path == NULL)
+    {
+      gtk_widget_path_append_type (path, type == G_TYPE_NONE ? GTK_TYPE_WIDGET : type);
+    }
+  else
+    {
+      const gchar *widget_p, *widget_next;
+      const gchar *class_p, *class_next;
+
+      widget_next = widget_path;
+      class_next = class_path;
+
+      while (*class_next)
+	{
+	  GType component_type;
+	  gchar *component_class;
+	  gchar *component_name;
+	  gint pos;
+
+	  class_p = class_next;
+	  if (*class_p == '.')
+	    class_p++;
+
+	  widget_p = widget_next; /* Might be NULL */
+	  if (widget_p && *widget_p == '.')
+	    widget_p++;
+
+	  class_next = strchr (class_p, '.');
+	  if (class_next == NULL)
+	    class_next = class_p + strlen (class_p);
+
+	  if (widget_p)
+	    {
+	      widget_next = strchr (widget_p, '.');
+	      if (widget_next == NULL)
+		widget_next = widget_p + strlen (widget_p);
+	    }
+
+	  component_class = g_strndup (class_p, class_next - class_p);
+	  if (widget_p && *widget_p)
+	    component_name = g_strndup (widget_p, widget_next - widget_p);
+	  else
+	    component_name = NULL;
+
+	  component_type = g_type_from_name (component_class);
+	  if (component_type == G_TYPE_INVALID)
+	    component_type = GTK_TYPE_WIDGET;
+
+	  pos = gtk_widget_path_append_type (path, component_type);
+	  if (component_name != NULL && strcmp (component_name, component_name) != 0)
+	    gtk_widget_path_iter_set_name (path, pos, component_name);
+
+	  g_free (component_class);
+	  g_free (component_name);
+	}
+    }
+
+  style = _gtk_style_new_for_path (_gtk_settings_get_screen (settings),
+				   path);
+
+  gtk_widget_path_free (path);
+
+  return style;
 }
 
 /**
diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c
index e02beb5..3bfc664 100644
--- a/gtk/gtkstyle.c
+++ b/gtk/gtkstyle.c
@@ -798,6 +798,26 @@ gtk_style_copy (GtkStyle *style)
   return new_style;
 }
 
+GtkStyle*
+_gtk_style_new_for_path (GdkScreen     *screen,
+			 GtkWidgetPath *path)
+{
+  GtkStyleContext *context;
+  GtkStyle *style;
+
+  context = gtk_style_context_new ();
+  gtk_style_context_set_screen (context, screen);
+  gtk_style_context_set_path (context, path);
+
+  style = g_object_new (GTK_TYPE_STYLE,
+                        "context", context,
+                        NULL);
+
+  g_object_unref (context);
+
+  return style;
+}
+
 /**
  * gtk_style_new:
  * @returns: a new #GtkStyle.
@@ -809,22 +829,15 @@ gtk_style_copy (GtkStyle *style)
 GtkStyle*
 gtk_style_new (void)
 {
-  GtkStyleContext *context;
   GtkWidgetPath *path;
   GtkStyle *style;
 
-  context = gtk_style_context_new ();
-  gtk_style_context_set_screen (context, gdk_screen_get_default ());
-
   path = gtk_widget_path_new ();
   gtk_widget_path_append_type (path, GTK_TYPE_WIDGET);
-  gtk_style_context_set_path (context, path);
 
-  style = g_object_new (GTK_TYPE_STYLE,
-                        "context", context,
-                        NULL);
+  style = _gtk_style_new_for_path (gdk_screen_get_default (),
+				   path);
 
-  g_object_unref (context);
   gtk_widget_path_free (path);
 
   return style;
diff --git a/gtk/gtkstyle.h b/gtk/gtkstyle.h
index efd78a7..7aec22d 100644
--- a/gtk/gtkstyle.h
+++ b/gtk/gtkstyle.h
@@ -34,6 +34,7 @@
 
 #include <gdk/gdk.h>
 #include <gtk/gtkenums.h>
+#include <gtk/gtkwidgetpath.h>
 
 
 G_BEGIN_DECLS
@@ -634,10 +635,13 @@ void gtk_style_get                (GtkStyle    *style,
 #endif
 
 /* --- private API --- */
+GtkStyle*     _gtk_style_new_for_path        (GdkScreen          *screen,
+					      GtkWidgetPath      *path);
 void          _gtk_style_shade               (const GdkColor     *a,
                                               GdkColor           *b,
                                               gdouble             k);
 
+
 void   gtk_draw_insertion_cursor    (GtkWidget          *widget,
                                      cairo_t            *cr,
                                      const GdkRectangle *location,



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