[gnome-maps/wip/cdavis/dark-style-preference: 2/2] Use new color scheme API




commit fb933c07307e265a1643f0b2afb6362abfdcdfde
Author: Christopher Davis <christopherdavis gnome org>
Date:   Sun Sep 26 01:14:46 2021 -0700

    Use new color scheme API
    
    Global dark themes are going to be supported in GNOME 42.
    Maps already has a setting for "Night Mode", so we want
    to switch that to a color scheme selector.
    
    See https://gitlab.gnome.org/Teams/Design/os-mockups/-/blob/master/prefer-dark/prefer-dark.png for design 
reference.

 data/gnome-maps.css             | 41 +++++++++++++++++++++++++++++++++
 data/org.gnome.Maps.gschema.xml | 15 ++++++++-----
 data/ui/main-window.ui          | 50 +++++++++++++++++++++++++++++++++++++----
 src/application.js              | 50 +++++++++++++++++++++++++++++------------
 src/layersPopover.js            | 11 ++++-----
 src/mainWindow.js               | 19 +++++++++++++++-
 src/mapView.js                  | 11 ++++-----
 7 files changed, 163 insertions(+), 34 deletions(-)
---
diff --git a/data/gnome-maps.css b/data/gnome-maps.css
index 55e60fb9..aa9bb5dd 100644
--- a/data/gnome-maps.css
+++ b/data/gnome-maps.css
@@ -110,3 +110,44 @@
   -gtk-outline-radius: 14px;
 }
 
+
+/* Adapted from 
https://gitlab.gnome.org/GNOME/gnome-text-editor/-/blob/bf8c0c249f06a0be69e65aed3b786ba02a9f999e/src/TextEditor.css#L51
 */
+radiobutton.theme-selector radio {
+  -gtk-icon-source: none;
+  background: none;
+  box-shadow: none;
+  padding: 15px;
+  min-height: 24px;
+  min-width: 24px;
+  border-width: 1px;
+  border-style: solid;
+  border-color: @borders;
+}
+
+radiobutton.theme-selector radio:checked {
+  border-width: 3px;
+  border-color: @theme_selected_bg_color;
+  margin: -2px;
+  -gtk-icon-source: -gtk-icontheme("object-select-symbolic");
+}
+
+
+radiobutton.theme-selector.system radio {
+  color: #2e3436;
+  background: linear-gradient(135deg, #fff 50%, #2e3436 50%);
+}
+
+radiobutton.theme-selector.system radio:checked {
+  color: #2e3436;
+  background: linear-gradient(135deg, #f6f5f4 50%, #c0bfbc 50%);
+}
+
+radiobutton.theme-selector.light radio {
+  color: #2e3436;
+  background-color: #fff;
+}
+
+radiobutton.theme-selector.dark radio {
+  color: #fff;
+  background-color: #2e3436;
+}
diff --git a/data/org.gnome.Maps.gschema.xml b/data/org.gnome.Maps.gschema.xml
index cc32f780..8efb27bc 100644
--- a/data/org.gnome.Maps.gschema.xml
+++ b/data/org.gnome.Maps.gschema.xml
@@ -75,15 +75,20 @@
       <default>'pedestrian'</default>
       <summary>Last used transportation type for routing</summary>
     </key>
-    <key name="night-mode" type="b">
-      <default>false</default>
-      <summary>Night mode</summary>
-      <description>Whether the application is in night mode.</description>
-    </key>
     <key name="hybrid-aerial" type="b">
       <default>false</default>
       <summary>Use hybrid aerial tiles</summary>
       <description>Whether aerial tiles should use hybrid style (with labels).</description>
     </key>
+    <key name="color-scheme" type="s">
+      <choices>
+        <choice value="default"/>
+        <choice value="light"/>
+        <choice value="dark"/>
+      </choices>
+      <default>'default'</default>
+      <summary>Color Scheme</summary>
+      <description>The color scheme to use for windows.</description>
+    </key>
   </schema>
 </schemalist>
diff --git a/data/ui/main-window.ui b/data/ui/main-window.ui
index 99e17a11..4748909d 100644
--- a/data/ui/main-window.ui
+++ b/data/ui/main-window.ui
@@ -14,11 +14,53 @@
         <property name="margin-bottom">12</property>
         <property name="orientation">vertical</property>
         <child>
-          <object class="GtkModelButton">
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <property name="margin_bottom">12</property>
+            <property name="orientation">horizontal</property>
+            <property name="spacing">18</property>
+            <child>
+              <object class="GtkRadioButton" id="defaultSelector">
+                <property name="visible">True</property>
+                <property name="action-name">app.set-color-scheme</property>
+                <property name="action-target">'default'</property>
+                <style>
+                  <class name="theme-selector"/>
+                  <class name="system"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkRadioButton" id="lightSelector">
+                <property name="visible">True</property>
+                <property name="group">defaultSelector</property>
+                <property name="action-name">app.set-color-scheme</property>
+                <property name="action-target">'light'</property>
+                <style>
+                  <class name="theme-selector"/>
+                  <class name="light"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkRadioButton" id="darkSelector">
+                <property name="visible">True</property>
+                <property name="group">defaultSelector</property>
+                <property name="action-name">app.set-color-scheme</property>
+                <property name="action-target">'dark'</property>
+                <style>
+                  <class name="theme-selector"/>
+                  <class name="dark"/>
+                </style>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkSeparator">
             <property name="visible">True</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Night Mode</property>
-            <property name="action-name">app.night-mode</property>
           </object>
         </child>
         <child>
diff --git a/src/application.js b/src/application.js
index 573bceef..8575f6fc 100644
--- a/src/application.js
+++ b/src/application.js
@@ -172,6 +172,25 @@ var Application = GObject.registerClass({
         }
     }
 
+    _onColorSchemeChange(action, parameter) {
+        parameter.print(true);
+        let scheme = parameter.get_string()[0];
+
+        switch (scheme) {
+            case 'default':
+                this._styleManager.set_color_scheme(Hdy.ColorScheme.PREFER_LIGHT);
+                break;
+            case 'light':
+                this._styleManager.set_color_scheme(Hdy.ColorScheme.FORCE_LIGHT);
+                break;
+            case 'dark':
+                this._styleManager.set_color_scheme(Hdy.ColorScheme.FORCE_DARK);
+                break;
+        }
+
+        settings.set('color-scheme', scheme);
+    }
+
     _onOsmAccountSetupActivate() {
         let dialog = osmEdit.createAccountDialog(this._mainWindow, false);
 
@@ -227,12 +246,6 @@ var Application = GObject.registerClass({
         }
     }
 
-    _onNightModeChange(action) {
-        let state = action.get_state();
-        let gtkSettings = Gtk.Settings.get_default();
-        gtkSettings.gtk_application_prefer_dark_theme = state.get_boolean();
-    }
-
     vfunc_startup() {
         super.vfunc_startup();
 
@@ -252,10 +265,9 @@ var Application = GObject.registerClass({
             'osm-account-setup': {
                 onActivate: this._onOsmAccountSetupActivate.bind(this)
             },
-            'night-mode': {
-                paramType:     'b',
-                onChangeState: this._onNightModeChange.bind(this),
-                setting:       'night-mode'
+            'set-color-scheme': {
+                paramType:     's',
+                onActivate: this._onColorSchemeChange.bind(this)
             },
             'quit': {
                 onActivate: () => this.quit(),
@@ -263,11 +275,21 @@ var Application = GObject.registerClass({
             }
         }, settings);
 
-        // set dark theme when night-mode is enabled
-        let gtkSettings = Gtk.Settings.get_default();
 
-        gtkSettings.gtk_application_prefer_dark_theme =
-            settings.get('night-mode');
+        this._styleManager = Hdy.StyleManager.get_default();
+
+        // Set color scheme based on settings
+        switch (settings.get('color-scheme')) {
+            case 'default':
+                this._styleManager.set_color_scheme(Hdy.ColorScheme.PREFER_LIGHT);
+                break;
+            case 'light':
+                this._styleManager.set_color_scheme(Hdy.ColorScheme.FORCE_LIGHT);
+                break;
+            case 'dark':
+                this._styleManager.set_color_scheme(Hdy.ColorScheme.FORCE_DARK);
+                break;
+        }
 
         Gtk.IconTheme.get_default().append_search_path(GLib.build_filenamev([pkg.pkgdatadir,
                                                                              'icons']));
diff --git a/src/layersPopover.js b/src/layersPopover.js
index 70f25657..d421b71f 100644
--- a/src/layersPopover.js
+++ b/src/layersPopover.js
@@ -21,6 +21,7 @@ const Champlain = imports.gi.Champlain;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Gdk = imports.gi.Gdk;
+const Hdy = imports.gi.Handy;
 
 const Application = imports.application;
 const MapSource = imports.mapSource;
@@ -144,8 +145,8 @@ var LayersPopover = GObject.registerClass({
                                        this._setLayerPreviews.bind(this));
             this._mapView.view.connect("notify::longitude",
                                        this._setLayerPreviews.bind(this));
-            Application.settings.connect("changed::night-mode",
-                                         this._onNightModeChanged.bind(this));
+            Hdy.StyleManager.get_default().connect("notify::dark",
+                                                    this._onDarkChanged.bind(this));
             Application.settings.connect("changed::hybrid-aerial",
                                          this._onHybridAerialChanged.bind(this));
 
@@ -160,9 +161,9 @@ var LayersPopover = GObject.registerClass({
         });
     }
 
-    _onNightModeChanged() {
+    _onDarkChanged() {
         if (Service.getService().tiles.streetDark &&
-            Application.settings.get('night-mode')) {
+            Hdy.StyleManager.get_default().dark) {
             this._setLayerPreviewImage('streetDark', true);
         } else {
             this._setLayerPreviewImage('street', true);
@@ -180,7 +181,7 @@ var LayersPopover = GObject.registerClass({
 
     _setLayerPreviews() {
         if (Service.getService().tiles.streetDark &&
-            Application.settings.get('night-mode')) {
+            Hdy.StyleManager.get_default().dark) {
             this._setLayerPreviewImage('streetDark');
         } else {
             this._setLayerPreviewImage('street');
diff --git a/src/mainWindow.js b/src/mainWindow.js
index 9abceb46..4d9b7205 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -86,7 +86,10 @@ var MainWindow = GObject.registerClass({
                         'noNetworkView',
                         'actionBar',
                         'actionBarRevealer',
-                        'placeBarContainer' ]
+                        'placeBarContainer',
+                        'defaultSelector',
+                        'lightSelector',
+                        'darkSelector']
 }, class MainWindow extends Gtk.ApplicationWindow {
 
     get mapView() {
@@ -116,6 +119,7 @@ var MainWindow = GObject.registerClass({
         this._initHeaderbar();
         this._initSignals();
         this._restoreWindowGeometry();
+        this._restoreColorSchemeSelectors();
         this._initDND();
         this._initPlaceBar();
 
@@ -444,6 +448,19 @@ var MainWindow = GObject.registerClass({
             this.maximize();
     }
 
+    _restoreColorSchemeSelectors() {
+        switch (Application.settings.get('color-scheme')) {
+            case 'default':
+                this._defaultSelector.active = true;
+                break;
+            case 'light':
+                this._lightSelector.active = true;
+                break;
+            case 'dark':
+                this._darkSelector.active = true;
+                break;
+        }
+    }
     _onConfigureEvent(widget, event) {
         if (this._configureId !== 0) {
             Mainloop.source_remove(this._configureId);
diff --git a/src/mapView.js b/src/mapView.js
index 10e6d5a3..fef736c2 100644
--- a/src/mapView.js
+++ b/src/mapView.js
@@ -26,6 +26,7 @@ const Geocode = imports.gi.GeocodeGlib;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
 const GtkChamplain = imports.gi.GtkChamplain;
+const Hdy = imports.gi.Handy;
 const Mainloop = imports.mainloop;
 
 const Application = imports.application;
@@ -210,8 +211,8 @@ var MapView = GObject.registerClass({
 
         // if dark tiles is available, setup handler to switch style
         if (Service.getService().tiles.streetDark) {
-            Application.settings.connect('changed::night-mode',
-                                         this._onNightModeChanged.bind(this));
+            Hdy.StyleManager.get_default().connect('notify::dark',
+                                                    this._onDarkChanged.bind(this));
         }
 
         // if hybrid aerial tiles are available, setup handler to toggle
@@ -272,11 +273,11 @@ var MapView = GObject.registerClass({
         this._setBackgroundPatternIfNeeded();
     }
 
-    _onNightModeChanged() {
+    _onDarkChanged() {
         if (this._mapType === MapType.STREET) {
             let overlay_sources = this.view.get_overlay_sources();
 
-            if (Application.settings.get('night-mode'))
+            if (Hdy.StyleManager.get_default().dark)
                 this.view.map_source = MapSource.createStreetDarkSource();
             else
                 this.view.map_source = MapSource.createStreetSource();
@@ -428,7 +429,7 @@ var MapView = GObject.registerClass({
                 }
             } else {
                 if (tiles.streetDark &&
-                    Application.settings.get('night-mode')) {
+                    Hdy.StyleManager.get_default().dark) {
                     this.view.map_source = MapSource.createStreetDarkSource();
                 } else {
                     this.view.map_source = MapSource.createStreetSource();


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