[gnumeric] css: implement #ifdef for built-in css.



commit afbae66f9dd43a121b8f2b52e58143786332a78f
Author: Morten Welinder <terra gnome org>
Date:   Wed Feb 17 20:57:12 2021 -0500

    css: implement #ifdef for built-in css.
    
    This is a poor man's preprocessor.  A very poor man's.  It understands
    basically two things at the moment:
    
    |   #ifdef DARK
    |     ...
    |   #else
    |     ...
    |   #endif
    
    and
    
    |   #if GTK_CHECK_VERSION(...)
    |     ...
    |   #else
    |     ...
    |   #endif
    
    Note, that "DARK" is set iff running under a dark theme.  The gtk version
    check is a run-time check.
    
    Note: this code is not in play when ~/.config/gtk-3.0/gtk.css is being read.

 NEWS             |  1 +
 src/gnumeric.css | 72 ++++++++++++++++++++++++++++++++------------------------
 src/gui-util.c   | 18 ++++++++++++++
 src/gui-util.h   |  1 +
 src/gutils.c     | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gutils.h     |  2 ++
 src/wbc-gtk.c    | 14 ++++++++---
 7 files changed, 146 insertions(+), 34 deletions(-)
---
diff --git a/NEWS b/NEWS
index c85b68ffe..c3029d7de 100644
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,7 @@ Morten:
        * Check for yelp in autogen.  [#558]
        * Fix ssconvert problem with conditional styles.
        * Move from style regions to style classes in css.
+       * Implement #ifdef for built-in css.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.48
diff --git a/src/gnumeric.css b/src/gnumeric.css
index 48bca6a38..be12d703b 100644
--- a/src/gnumeric.css
+++ b/src/gnumeric.css
@@ -189,17 +189,6 @@ GocItem.object-size.rubber-band {
   color: black;
 }
 
-/* ------------------------------------------------------------------------- */
-/* Auto filter in two versions: the first one for "all", second for others.  */
-
-GtkArrow.auto-filter {
-  color: black;
-}
-
-GtkArrow.auto-filter:active {
-  color: yellow;
-}
-
 /* ------------------------------------------------------------------------- */
 /* GnmNotebookButton is the sheet name buttons used to select sheets.  */
 
@@ -219,24 +208,7 @@ GtkDialog GtkTextView.function-help {
   -GtkWidget-link-color: #4040ff;
 }
 
-/* ------------------------------------------------------------------------- */
-/* This is the vertical line used in the fixed-width part of the stf */
-/* import dialog to show where a new column division will be placed */
-
-GtkDialog.fixed-format-ruler {
-  color: red;
-}
-
-/* ------------------------------------------------------------------------- */
-/* Extra space around multiple toolbars adds up quickly so avoid it. */
-
-GtkBox.toolbarzone GtkToolbar {
-  padding: 0px;
-}
-GtkBox.toolbarzone GtkToolbar * {
-  padding: 1px;
-}
-
+#if GTK_CHECK_VERSION(3,20,0)
 /* ------------------------------------------------------------------------- */
 /* Styles for Gtk+ 3.20 and later */
 /* ------------------------------------------------------------------------- */
@@ -256,8 +228,8 @@ button.itembar, button.itembar * {
 
 /* The whole column/row selected. */
 button:active.itembar, button:active.itembar * {
-  color: red;
-  font-weight: bold;
+    color: red;
+    font-weight: bold;
 }
 
 /* Some, but not all, of a column/row selected. */
@@ -278,8 +250,46 @@ box > box:last-child > toolbar {
     padding-bottom: 1pt;
 }
 
+/* This is the vertical line used in the fixed-width part of the stf */
+/* import dialog to show where a new column division will be placed */
 dialog.fixed-format-ruler {
   color: red;
 }
 
+/* Auto filter in two versions: the first one for "all", second for others.  */
+/* Not working: */
+arrow.auto-filter {
+  color: black;
+}
+arrow.auto-filter:active {
+  color: yellow;
+}
+
+#else
+
+/* Extra space around multiple toolbars adds up quickly so avoid it. */
+GtkBox.toolbarzone GtkToolbar {
+  padding: 0px;
+}
+GtkBox.toolbarzone GtkToolbar * {
+  padding: 1px;
+}
+
+/* This is the vertical line used in the fixed-width part of the stf */
+/* import dialog to show where a new column division will be placed */
+GtkDialog.fixed-format-ruler {
+  color: red;
+}
+
+/* Auto filter in two versions: the first one for "all", second for others.  */
+GtkArrow.auto-filter {
+  color: black;
+}
+
+GtkArrow.auto-filter:active {
+  color: yellow;
+}
+
+#endif
+
 /* ------------------------------------------------------------------------- */
diff --git a/src/gui-util.c b/src/gui-util.c
index c00b15d22..84c0b19a0 100644
--- a/src/gui-util.c
+++ b/src/gui-util.c
@@ -1404,4 +1404,22 @@ gnm_get_link_color (G_GNUC_UNUSED GtkWidget *widget, GdkRGBA *res)
 }
 #endif /* GTK_STATE_FLAG_LINK */
 
+gboolean
+gnm_theme_is_dark (GtkWidget *widget)
+{
+       GtkStyleContext *context;
+       GdkRGBA fg_color;
+       double lum;
+
+       context = gtk_widget_get_style_context (widget);
+       gnm_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &fg_color);
+
+       // One of many possible versions.
+       lum = 0.299 * fg_color.red + 0.587 * fg_color.green + 0.114 * fg_color.blue;
+
+       // Theme is dark if fg is light.
+       return lum > 0.5;
+}
+
+
 // ----------------------------------------------------------------------------
diff --git a/src/gui-util.h b/src/gui-util.h
index 785879810..8dd6dd65e 100644
--- a/src/gui-util.h
+++ b/src/gui-util.h
@@ -187,6 +187,7 @@ void gnm_style_context_get_color (GtkStyleContext *context,
                                  GdkRGBA *color);
 
 void gnm_get_link_color (GtkWidget *widget, GdkRGBA *res);
+gboolean gnm_theme_is_dark (GtkWidget *widget);
 
 G_END_DECLS
 
diff --git a/src/gutils.c b/src/gutils.c
index a2a5696a8..10a2a3010 100644
--- a/src/gutils.c
+++ b/src/gutils.c
@@ -1014,3 +1014,75 @@ gnm_file_saver_common_export_option (GOFileSaver const *fs,
 
        return TRUE;
 }
+
+
+static int
+gnm_cpp_expr (const char *expr, G_GNUC_UNUSED GHashTable *vars)
+{
+       int vmajor, vminor, vmicro;
+
+       while (g_ascii_isspace (*expr))
+               expr++;
+
+       if (sscanf (expr, "GTK_CHECK_VERSION (%d,%d,%d) ", &vmajor, &vminor, &vmicro) == 3) {
+               return gtk_check_version (vmajor, vminor, vmicro) ? 0 : 1;
+       }
+
+       g_warning ("Unhandled cpp expression %s", expr);
+       return 0;
+}
+
+
+char *
+gnm_cpp (const char *src, GHashTable *vars)
+{
+       GString *res = g_string_new (NULL);
+       GString *ifdefs = g_string_new ("1");
+
+       while (*src) {
+               const char *end;
+
+               end = strchr (src, '\n');
+               if (end)
+                       end++;
+               else
+                       end = src + strlen (src);
+
+               if (*src == '#') {
+                       if (strncmp (src, "#ifdef ", 7) == 0 || strncmp (src, "#ifndef ", 8) == 0) {
+                               int is_not = (src[3] == 'n');
+                               const char *var = src + 7 + is_not;
+                               char *w;
+                               gboolean res;
+
+                               while (g_ascii_isspace (*var))
+                                       var++;
+                               src = var;
+                               while (g_ascii_isalnum (*src))
+                                       src++;
+                               w = g_strndup (var, src - var);
+                               res = is_not ^ !!g_hash_table_lookup (vars, w);
+                               g_string_append_c (ifdefs, ifdefs->str[ifdefs->len - 1] && res);
+                               g_free (w);
+                       } else if (strncmp (src, "#if ", 4) == 0) {
+                               gboolean res = gnm_cpp_expr (src + 4, vars) > 0;
+                               g_string_append_c (ifdefs, ifdefs->str[ifdefs->len - 1] && res);
+                       } else if (strncmp (src, "#else", 5) == 0) {
+                               ifdefs->str[ifdefs->len - 1] =
+                                       !ifdefs->str[ifdefs->len - 1] &&
+                                       ifdefs->str[ifdefs->len - 2];
+                       } else if (strncmp (src, "#endif", 6) == 0 && ifdefs->len > 1) {
+                               g_string_set_size (ifdefs, ifdefs->len - 1);
+                       } else {
+                               g_warning ("cpp failure");
+                       }
+               } else {
+                       if (ifdefs->str[ifdefs->len - 1])
+                               g_string_append_len (res, src, end - src);
+               }
+               src = end;
+       }
+
+       g_string_free (ifdefs, TRUE);
+       return g_string_free (res, FALSE);
+}
diff --git a/src/gutils.h b/src/gutils.h
index 945b5a425..42d96844a 100644
--- a/src/gutils.h
+++ b/src/gutils.h
@@ -74,6 +74,8 @@ gboolean gnm_file_saver_common_export_option (GOFileSaver const *fs,
                                              const char *value,
                                              GError **err);
 
+char *gnm_cpp (const char *src, GHashTable *vars);
+
 G_END_DECLS
 
 #endif /* _GNM_GUTILS_H_ */
diff --git a/src/wbc-gtk.c b/src/wbc-gtk.c
index e330105f4..93544d94b 100644
--- a/src/wbc-gtk.c
+++ b/src/wbc-gtk.c
@@ -2367,10 +2367,17 @@ cb_screen_changed (GtkWidget *widget)
 
        data = g_object_get_data (app, app_key);
        if (!data) {
-               const char *resource = "/org/gnumeric/gnumeric/ui/gnumeric.css";
-               GBytes *cssbytes = g_resources_lookup_data (resource, 0, NULL);
-               const char *csstext = g_bytes_get_data (cssbytes, NULL);
                gboolean debug = gnm_debug_flag ("css");
+               gboolean q_dark = gnm_theme_is_dark (widget);
+               const char *resource = "/org/gnumeric/gnumeric/ui/gnumeric.css";
+               GBytes *cssbytes;
+               char *csstext;
+               GHashTable *vars = g_hash_table_new (g_str_hash, g_str_equal);
+
+               cssbytes = g_resources_lookup_data (resource, 0, NULL);
+               if (q_dark)
+                       g_hash_table_insert (vars, "DARK", "1");
+               csstext = gnm_cpp (g_bytes_get_data (cssbytes, NULL), vars);
 
                data = g_new (struct css_provider_data, 1);
                data->css = gtk_css_provider_new ();
@@ -2386,6 +2393,7 @@ cb_screen_changed (GtkWidget *widget)
                gtk_css_provider_load_from_data (data->css, csstext, -1, NULL);
                g_object_set_data_full (app, app_key, data, cb_unload_providers);
                g_bytes_unref (cssbytes);
+               g_free (csstext);
        }
 
        if (screen && !g_slist_find (data->screens, screen)) {


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