[goffice] Gtk: import css helper function from Gnumeric.



commit 3b9e40bb1eeebeb5e781c506ca609e15e27e92b5
Author: Morten Welinder <terra gnome org>
Date:   Sun Dec 10 14:36:30 2017 -0500

    Gtk: import css helper function from Gnumeric.

 ChangeLog                 |    5 ++
 goffice/gtk/goffice-gtk.c |  151 +++++++++++++++++++++++++++++++++++++++++++++
 goffice/gtk/goffice-gtk.h |    3 +
 3 files changed, 159 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c799891..9ab1c8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2017-12-10  Morten Welinder  <terra gnome org>
+
+       * goffice/gtk/goffice-gtk.c (go_style_context_from_selector):
+       Import from Gnumeric (in turn from gtk+).
+
 2017-12-05  Morten Welinder  <terra gnome org>
 
        * tests/constants.c (main): Improve checking if double math
diff --git a/goffice/gtk/goffice-gtk.c b/goffice/gtk/goffice-gtk.c
index 7866aac..c058c76 100644
--- a/goffice/gtk/goffice-gtk.c
+++ b/goffice/gtk/goffice-gtk.c
@@ -1686,6 +1686,157 @@ _go_gtk_new_theming (void)
 #endif
 }
 
+// ---------------------------------------------------------------------------
+// Foreign drawing style code copied from foreigndrawing.c
+
+#if GTK_CHECK_VERSION(3,20,0)
+static void
+append_element (GtkWidgetPath *path,
+                const char    *selector)
+{
+       static const struct {
+               const char    *name;
+               GtkStateFlags  state_flag;
+       } pseudo_classes[] = {
+               { "active",        GTK_STATE_FLAG_ACTIVE },
+               { "hover",         GTK_STATE_FLAG_PRELIGHT },
+               { "selected",      GTK_STATE_FLAG_SELECTED },
+               { "disabled",      GTK_STATE_FLAG_INSENSITIVE },
+               { "indeterminate", GTK_STATE_FLAG_INCONSISTENT },
+               { "focus",         GTK_STATE_FLAG_FOCUSED },
+               { "backdrop",      GTK_STATE_FLAG_BACKDROP },
+               { "dir(ltr)",      GTK_STATE_FLAG_DIR_LTR },
+               { "dir(rtl)",      GTK_STATE_FLAG_DIR_RTL },
+               { "link",          GTK_STATE_FLAG_LINK },
+               { "visited",       GTK_STATE_FLAG_VISITED },
+               { "checked",       GTK_STATE_FLAG_CHECKED },
+               { "drop(active)",  GTK_STATE_FLAG_DROP_ACTIVE }
+       };
+       const char *next;
+       char *name;
+       char type;
+       guint i;
+
+       next = strpbrk (selector, "#.:");
+       if (next == NULL)
+               next = selector + strlen (selector);
+
+       name = g_strndup (selector, next - selector);
+       if (g_ascii_isupper (selector[0]))
+       {
+               GType gtype;
+               gtype = g_type_from_name (name);
+               if (gtype == G_TYPE_INVALID)
+               {
+                       g_critical ("Unknown type name `%s'", name);
+                       g_free (name);
+                       return;
+               }
+               gtk_widget_path_append_type (path, gtype);
+       }
+       else
+       {
+               /* Omit type, we're using name */
+               gtk_widget_path_append_type (path, G_TYPE_NONE);
+               gtk_widget_path_iter_set_object_name (path, -1, name);
+       }
+       g_free (name);
+
+       while (*next != '\0')
+       {
+               type = *next;
+               selector = next + 1;
+               next = strpbrk (selector, "#.:");
+               if (next == NULL)
+                       next = selector + strlen (selector);
+               name = g_strndup (selector, next - selector);
+
+               switch (type)
+               {
+               case '#':
+                       gtk_widget_path_iter_set_name (path, -1, name);
+                       break;
+
+               case '.':
+                       gtk_widget_path_iter_add_class (path, -1, name);
+                       break;
+
+               case ':':
+                       for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
+                       {
+                               if (g_str_equal (pseudo_classes[i].name, name))
+                               {
+                                       gtk_widget_path_iter_set_state (path,
+                                                                       -1,
+                                                                       gtk_widget_path_iter_get_state (path, 
-1)
+                                                                       | pseudo_classes[i].state_flag);
+                                       break;
+                               }
+                       }
+                       if (i == G_N_ELEMENTS (pseudo_classes))
+                               g_critical ("Unknown pseudo-class :%s", name);
+                       break;
+
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+
+               g_free (name);
+       }
+}
+
+static GtkStyleContext *
+create_context_for_path (GtkWidgetPath   *path,
+                         GtkStyleContext *parent)
+{
+       GtkStyleContext *context;
+
+       context = gtk_style_context_new ();
+       gtk_style_context_set_path (context, path);
+       gtk_style_context_set_parent (context, parent);
+       /* Unfortunately, we have to explicitly set the state again here
+        * for it to take effect
+        */
+       gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1));
+       gtk_widget_path_unref (path);
+
+       return context;
+}
+#endif
+
+/**
+ * go_style_context_from_selector:
+ * @parent: (allow-none): style context for container
+ * @selector: a css selector
+ *
+ * Returns: (transfer full): a new style context.
+ */
+GtkStyleContext *
+go_style_context_from_selector (GtkStyleContext *parent,
+                               const char      *selector)
+{
+#if GTK_CHECK_VERSION(3,20,0)
+       GtkWidgetPath *path;
+
+       g_return_val_if_fail (selector != NULL, NULL);
+
+       path = parent
+               ? gtk_widget_path_copy (gtk_style_context_get_path (parent))
+               : gtk_widget_path_new ();
+
+       append_element (path, selector);
+
+       return create_context_for_path (path, parent);
+#else
+       (void)parent;
+       g_return_val_if_fail (selector != NULL, NULL);
+       g_assert_not_reached ();
+       return NULL;
+#endif
+}
+
+// ---------------------------------------------------------------------------
 
 void
 _go_gtk_shutdown (void)
diff --git a/goffice/gtk/goffice-gtk.h b/goffice/gtk/goffice-gtk.h
index 829ab7d..4c2beb1 100644
--- a/goffice/gtk/goffice-gtk.h
+++ b/goffice/gtk/goffice-gtk.h
@@ -61,6 +61,9 @@ void       _go_gtk_shutdown (void);
 // Add goffice-specific css provider
 void       _go_gtk_widget_add_css_provider (GtkWidget *w);
 
+GtkStyleContext *go_style_context_from_selector (GtkStyleContext *parent,
+                                                const char      *selector);
+
 gboolean _go_gtk_new_theming (void);
 
 void      go_gtk_editable_enters (GtkWindow *window, GtkWidget *w);


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