[gnome-text-editor] recoloring: expiriment with recoloring



commit cb7bbfe50c7e8dc27f7bcc15f75f60049cd1ea38
Author: Christian Hergert <chergert redhat com>
Date:   Tue Nov 30 13:25:45 2021 -0800

    recoloring: expiriment with recoloring
    
    This can restyle the window based on colors from the GtkSourceStyleScheme.
    However, it just uses known styles to do this which is not exactly the
    best way to handle it. We need more control over styling from the style
    schemes in this case.
    
    My thoughts here are to add additional API to GtkSourceStyleScheme so you
    can get named colors. Then the style schemes themselves can export colors
    of a given name and if those are found, the scheme is capable for
    recoloring.
    
    Related #139

 data/org.gnome.TextEditor.gschema.xml |   5 ++
 src/editor-application-private.h      |   1 +
 src/editor-application.c              |  40 ++++++++-
 src/editor-recoloring-private.h       |  29 +++++++
 src/editor-recoloring.c               | 159 ++++++++++++++++++++++++++++++++++
 src/meson.build                       |   1 +
 6 files changed, 233 insertions(+), 2 deletions(-)
---
diff --git a/data/org.gnome.TextEditor.gschema.xml b/data/org.gnome.TextEditor.gschema.xml
index a15b3cd..2c7f2cd 100644
--- a/data/org.gnome.TextEditor.gschema.xml
+++ b/data/org.gnome.TextEditor.gschema.xml
@@ -109,6 +109,11 @@
       <summary>Restore session</summary>
       <description>When Text Editor is run, restore the previous session.</description>
     </key>
+    <key name="recolor-window" type="b">
+      <default>false</default>
+      <summary>Recolor Window</summary>
+      <description>Use the style-scheme to recolor the application window.</description>
+    </key>
     <key name="keybindings" type="s">
       <choices>
         <choice value="default"/>
diff --git a/src/editor-application-private.h b/src/editor-application-private.h
index eaf14cd..1d81593 100644
--- a/src/editor-application-private.h
+++ b/src/editor-application-private.h
@@ -29,6 +29,7 @@ struct _EditorApplication
   GtkApplication  parent_instance;
   EditorSession  *session;
   GSettings      *settings;
+  GtkCssProvider *recoloring;
 };
 
 EditorApplication *_editor_application_new          (void);
diff --git a/src/editor-application.c b/src/editor-application.c
index 5779ab0..5d63b9f 100644
--- a/src/editor-application.c
+++ b/src/editor-application.c
@@ -25,6 +25,7 @@
 #include <glib/gi18n.h>
 
 #include "editor-application-private.h"
+#include "editor-recoloring-private.h"
 #include "editor-session-private.h"
 #include "editor-utils-private.h"
 #include "editor-window.h"
@@ -168,6 +169,28 @@ update_dark (GtkWindow *window)
     gtk_widget_remove_css_class (GTK_WIDGET (window), "dark");
 }
 
+static void
+update_css (EditorApplication *self)
+{
+  g_autofree char *css = NULL;
+
+  g_assert (EDITOR_IS_APPLICATION (self));
+
+  if (g_settings_get_boolean (self->settings, "recolor-window"))
+    {
+      GtkSourceStyleSchemeManager *manager;
+      GtkSourceStyleScheme *style_scheme;
+      const char *id;
+
+      id = editor_application_get_style_scheme (self);
+      manager = gtk_source_style_scheme_manager_get_default ();
+      style_scheme = gtk_source_style_scheme_manager_get_scheme (manager, id);
+      css = _editor_recoloring_generate_css (style_scheme);
+    }
+
+  gtk_css_provider_load_from_data (self->recoloring, css ? css : "", -1);
+}
+
 static void
 on_style_manager_notify_dark (EditorApplication *self,
                               GParamSpec        *pspec,
@@ -186,6 +209,8 @@ on_style_manager_notify_dark (EditorApplication *self,
         update_dark (window);
     }
 
+  update_css (self);
+
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STYLE_SCHEME]);
 }
 
@@ -197,17 +222,21 @@ on_changed_style_scheme_cb (EditorApplication *self,
   g_assert (EDITOR_IS_APPLICATION (self));
   g_assert (G_IS_SETTINGS (settings));
 
+  update_css (self);
+
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STYLE_SCHEME]);
 }
 
 static void
 editor_application_startup (GApplication *application)
 {
+  static const gchar *quit_accels[] = { "<Primary>Q", NULL };
+  static const gchar *help_accels[] = { "F1", NULL };
+
   EditorApplication *self = (EditorApplication *)application;
   g_autoptr(GtkCssProvider) css_provider = NULL;
   AdwStyleManager *style_manager;
-  static const gchar *quit_accels[] = { "<Primary>Q", NULL };
-  static const gchar *help_accels[] = { "F1", NULL };
+  GdkDisplay *display;
 
   g_assert (EDITOR_IS_APPLICATION (self));
 
@@ -215,6 +244,12 @@ editor_application_startup (GApplication *application)
 
   adw_init ();
 
+  display = gdk_display_get_default ();
+  self->recoloring = gtk_css_provider_new ();
+  gtk_style_context_add_provider_for_display (display,
+                                              GTK_STYLE_PROVIDER (self->recoloring),
+                                              GTK_STYLE_PROVIDER_PRIORITY_THEME+1);
+
   gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.quit", quit_accels);
   gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.help", help_accels);
 
@@ -283,6 +318,7 @@ editor_application_shutdown (GApplication *application)
   EditorApplication *self = (EditorApplication *)application;
 
   g_clear_object (&self->session);
+  g_clear_object (&self->recoloring);
 
   G_APPLICATION_CLASS (editor_application_parent_class)->shutdown (application);
 }
diff --git a/src/editor-recoloring-private.h b/src/editor-recoloring-private.h
new file mode 100644
index 0000000..147611c
--- /dev/null
+++ b/src/editor-recoloring-private.h
@@ -0,0 +1,29 @@
+/* editor-recoloring-private.h
+ *
+ * Copyright 2020 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtksourceview/gtksource.h>
+
+G_BEGIN_DECLS
+
+char *_editor_recoloring_generate_css (GtkSourceStyleScheme *style_scheme);
+
+G_END_DECLS
diff --git a/src/editor-recoloring.c b/src/editor-recoloring.c
new file mode 100644
index 0000000..388f403
--- /dev/null
+++ b/src/editor-recoloring.c
@@ -0,0 +1,159 @@
+/* editor-recoloring.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include "editor-recoloring-private.h"
+
+#define SHARED_CSS \
+  "@define-color card_fg_color @window_fg_color;\n" \
+  "@define-color headerbar_fg_color @window_fg_color;\n" \
+  "@define-color headerbar_border_color @window_fg_color;\n" \
+  "@define-color popover_fg_color @window_fg_color;\n" \
+  "@define-color dark_fill_bg_color @headerbar_bg_color;\n" \
+  "@define-color view_bg_color @card_bg_color;\n" \
+  "@define-color view_fg_color @window_fg_color;\n"
+#define LIGHT_CSS_SUFFIX \
+  "@define-color popover_bg_color mix(@window_bg_color, white, .1);\n" \
+  "@define-color card_bg_color alpha(white, .65);\n"
+#define DARK_CSS_SUFFIX \
+  "@define-color popover_bg_color mix(@window_bg_color, black, .1);\n" \
+  "@define-color card_bg_color alpha(black, .65);\n"
+
+enum {
+  FOREGROUND,
+  BACKGROUND,
+};
+
+static gboolean
+get_color (GtkSourceStyleScheme *scheme,
+           const char           *style_name,
+           GdkRGBA              *color,
+           int                   kind)
+{
+  GtkSourceStyle *style;
+  g_autofree char *fg = NULL;
+  g_autofree char *bg = NULL;
+  gboolean fg_set = FALSE;
+  gboolean bg_set = FALSE;
+
+  g_assert (GTK_SOURCE_IS_STYLE_SCHEME (scheme));
+  g_assert (style_name != NULL);
+
+  if (!(style = gtk_source_style_scheme_get_style (scheme, style_name)))
+    return FALSE;
+
+  g_object_get (style,
+                "foreground", &fg,
+                "foreground-set", &fg_set,
+                "background", &bg,
+                "background-set", &bg_set,
+                NULL);
+
+  if (kind == FOREGROUND && fg_set)
+    return gdk_rgba_parse (color, fg);
+  else if (kind == BACKGROUND && bg_set)
+    return gdk_rgba_parse (color, bg);
+
+  return FALSE;
+}
+
+static inline gboolean
+get_foreground (GtkSourceStyleScheme *scheme,
+                const char           *style_name,
+                GdkRGBA              *fg)
+{
+  return get_color (scheme, style_name, fg, FOREGROUND);
+}
+
+static inline gboolean
+get_background (GtkSourceStyleScheme *scheme,
+                const char           *style_name,
+                GdkRGBA              *bg)
+{
+  return get_color (scheme, style_name, bg, BACKGROUND);
+}
+
+static void
+define_color (GString       *str,
+              const char    *name,
+              const GdkRGBA *color)
+{
+  g_autofree char *color_str = NULL;
+
+  g_assert (str != NULL);
+  g_assert (name != NULL);
+  g_assert (color != NULL);
+
+  color_str = gdk_rgba_to_string (color);
+  g_string_append_printf (str, "@define-color %s %s;\n", name, color_str);
+}
+
+static gboolean
+scheme_is_dark (GtkSourceStyleScheme *scheme)
+{
+  const char *id = gtk_source_style_scheme_get_id (scheme);
+  const char *variant = gtk_source_style_scheme_get_metadata (scheme, "variant");
+
+  if (strstr (id, "-dark") != NULL)
+    return TRUE;
+
+  if (g_strcmp0 (variant, "dark") == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+char *
+_editor_recoloring_generate_css (GtkSourceStyleScheme *style_scheme)
+{
+  const char *name;
+  GString *str;
+  GdkRGBA color;
+
+  g_return_val_if_fail (GTK_SOURCE_IS_STYLE_SCHEME (style_scheme), NULL);
+
+  name = gtk_source_style_scheme_get_name (style_scheme);
+
+  str = g_string_new (SHARED_CSS);
+  g_string_append_printf (str, "/* %s */\n", name);
+
+  if (get_background (style_scheme, "text", &color))
+    define_color (str, "window_bg_color", &color);
+
+  if (get_foreground (style_scheme, "text", &color))
+    define_color (str, "window_fg_color", &color);
+
+  if (get_background (style_scheme, "current-line", &color))
+    define_color (str, "headerbar_bg_color", &color);
+
+  if (get_foreground (style_scheme, "selection", &color))
+    define_color (str, "accent_color", &color);
+
+  if (get_background (style_scheme, "selection", &color))
+    define_color (str, "accent_bg_color", &color);
+
+  if (scheme_is_dark (style_scheme))
+    g_string_append (str, DARK_CSS_SUFFIX);
+  else
+    g_string_append (str, LIGHT_CSS_SUFFIX);
+
+  return g_string_free (str, FALSE);
+}
diff --git a/src/meson.build b/src/meson.build
index 0bcb463..c7e8181 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -26,6 +26,7 @@ editor_sources = [
   'editor-preferences-spin.c',
   'editor-preferences-switch.c',
   'editor-print-operation.c',
+  'editor-recoloring.c',
   'editor-save-changes-dialog.c',
   'editor-search-bar.c',
   'editor-search-entry.c',


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