diff --git a/src/Plug.vala b/src/Plug.vala
index ce776b766..4456bf2bb 100644
--- a/src/Plug.vala
+++ b/src/Plug.vala
@@ -34,6 +34,7 @@ public class PantheonShell.Plug : Switchboard.Plug {
settings.set ("desktop/appearance", "appearance");
settings.set ("desktop/dock", "dock");
settings.set ("desktop/multitasking", "multitasking");
+ settings.set ("desktop/text", "text");
// DEPRECATED
settings.set ("desktop/wallpaper", "wallpaper");
@@ -60,6 +61,9 @@ public class PantheonShell.Plug : Switchboard.Plug {
var appearance = new Appearance ();
stack.add_titled (appearance, "appearance", _("Appearance"));
+
+ var text = new Text ();
+ stack.add_titled (text, "text", _("Text"));
if (GLib.Environment.find_program_in_path ("plank") != null) {
var dock = new Dock ();
diff --git a/src/Views/Appearance.vala b/src/Views/Appearance.vala
index adad65ad5..bc422e1af 100644
--- a/src/Views/Appearance.vala
+++ b/src/Views/Appearance.vala
@@ -22,20 +22,6 @@ public class PantheonShell.Appearance : Gtk.Grid {
private const string INTERFACE_SCHEMA = "org.gnome.desktop.interface";
private const string STYLESHEET_KEY = "gtk-theme";
private const string STYLESHEET_PREFIX = "io.elementary.stylesheet.";
- private const string TEXT_SIZE_KEY = "text-scaling-factor";
-
- private const string DYSLEXIA_KEY = "dyslexia-friendly-support";
- private const string FONT_KEY = "font-name";
- private const string DOCUMENT_FONT_KEY = "document-font-name";
- private const string MONOSPACE_FONT_KEY = "monospace-font-name";
-
- private const string OD_REG_FONT = "OpenDyslexic Regular 9";
- private const string OD_DOC_FONT = "OpenDyslexic Regular 10";
- private const string OD_MON_FONT = "OpenDyslexicMono Regular 10";
-
- private const double[] TEXT_SCALE = {0.75, 1, 1.25, 1.5};
-
- private Granite.Widgets.ModeButton text_size_modebutton;
private enum AccentColor {
NO_PREFERENCE,
@@ -178,48 +164,6 @@ public class PantheonShell.Appearance : Gtk.Grid {
schedule_grid.add (to_label);
schedule_grid.add (to_time);
- var text_size_label = new Gtk.Label (_("Text size:")) {
- halign = Gtk.Align.END,
- margin_top = 24
- };
-
- text_size_modebutton = new Granite.Widgets.ModeButton () {
- margin_top = 24
- };
- text_size_modebutton.append_text (_("Small"));
- text_size_modebutton.append_text (_("Default"));
- text_size_modebutton.append_text (_("Large"));
- text_size_modebutton.append_text (_("Larger"));
-
- var dyslexia_font_label = new Gtk.Label (_("Dyslexia-friendly text:")) {
- halign = Gtk.Align.END
- };
-
- var dyslexia_font_switch = new Gtk.Switch () {
- halign = Gtk.Align.START
- };
-
- var dyslexia_font_description_label = new Gtk.Label (
- _("Bottom-heavy shapes and increased character spacing can help improve legibility and reading speed.")
- ) {
- max_width_chars = 60,
- wrap = true,
- xalign = 0
- };
- dyslexia_font_description_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
-
- /* Rows 0 to 3 are for the dark style UI that gets attached only if we
- * can connect to the DBus API
- *
- * Row 4 and 5 are for accent color UI that gets constructed only if the
- * current stylesheet is supported (begins with the STYLESHEET_PREFIX)
- */
- attach (text_size_label, 0, 8);
- attach (text_size_modebutton, 1, 8, 2);
- attach (dyslexia_font_label, 0, 9);
- attach (dyslexia_font_switch, 1, 9);
- attach (dyslexia_font_description_label, 1, 10, 2);
-
Pantheon.AccountsService? pantheon_act = null;
string? user_path = null;
@@ -412,22 +356,6 @@ public class PantheonShell.Appearance : Gtk.Grid {
attach (accent_grid, 1, 4, 2);
attach (accent_info, 1, 5, 2);
}
-
- update_text_size_modebutton (interface_settings);
-
- interface_settings.changed.connect (() => {
- update_text_size_modebutton (interface_settings);
- });
-
- text_size_modebutton.mode_changed.connect (() => {
- set_text_scale (interface_settings, text_size_modebutton.selected);
- });
-
- dyslexia_font_switch.set_active (update_dyslexia_font_switch (interface_settings));
-
- dyslexia_font_switch.state_set.connect (() => {
- toggle_dyslexia_support (interface_settings, dyslexia_font_switch.get_active () );
- });
}
private class PrefersAccentColorButton : Gtk.RadioButton {
@@ -474,55 +402,6 @@ public class PantheonShell.Appearance : Gtk.Grid {
}
}
- private void toggle_dyslexia_support (GLib.Settings interface_settings, bool state) {
- if (state == true) {
- interface_settings.set_string (FONT_KEY, OD_REG_FONT);
- interface_settings.set_string (DOCUMENT_FONT_KEY, OD_DOC_FONT);
- interface_settings.set_string (MONOSPACE_FONT_KEY, OD_MON_FONT);
- }
- else {
- interface_settings.reset (FONT_KEY);
- interface_settings.reset (DOCUMENT_FONT_KEY);
- interface_settings.reset (MONOSPACE_FONT_KEY);
- }
- }
-
- private bool update_dyslexia_font_switch (GLib.Settings interface_settings) {
- var interface_font = interface_settings.get_string (FONT_KEY);
- var document_font = interface_settings.get_string (DOCUMENT_FONT_KEY);
- var monospace_font = interface_settings.get_string (MONOSPACE_FONT_KEY);
-
- if (interface_font == OD_REG_FONT || document_font == OD_DOC_FONT || monospace_font == OD_MON_FONT ) {
- return true;
- }
-
- else {
- return false;
- }
- }
-
- private int get_text_scale (GLib.Settings interface_settings) {
- double text_scaling_factor = interface_settings.get_double (TEXT_SIZE_KEY);
-
- if (text_scaling_factor <= TEXT_SCALE[0]) {
- return 0;
- } else if (text_scaling_factor <= TEXT_SCALE[1]) {
- return 1;
- } else if (text_scaling_factor <= TEXT_SCALE[2]) {
- return 2;
- } else {
- return 3;
- }
- }
-
- private void set_text_scale (GLib.Settings interface_settings, int option) {
- interface_settings.set_double (TEXT_SIZE_KEY, TEXT_SCALE[option]);
- }
-
- private void update_text_size_modebutton (GLib.Settings interface_settings) {
- text_size_modebutton.set_active (get_text_scale (interface_settings));
- }
-
private static DateTime double_date_time (double dbl) {
var hours = (int) dbl;
var minutes = (int) Math.round ((dbl - hours) * 60);
diff --git a/src/Views/Text.vala b/src/Views/Text.vala
new file mode 100644
index 000000000..ce4004ebb
--- /dev/null
+++ b/src/Views/Text.vala
@@ -0,0 +1,299 @@
+/*
+* Copyright 2018–2021 elementary, Inc. (https://elementary.io)
+* Copyright 2021 Justin Haygood (jhaygood86@gmail.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, write to the
+* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+* Boston, MA 02110-1301 USA
+*
+*/
+
+public class PantheonShell.Text : Gtk.Grid {
+
+ private const string INTERFACE_SCHEMA = "org.gnome.desktop.interface";
+ private const string XSETTINGS_SCHEMA = "org.gnome.settings-daemon.plugins.xsettings";
+ private const string TEXT_SIZE_KEY = "text-scaling-factor";
+ private const string ANTIALIAS_KEY = "antialiasing";
+ private const string SUBPIXELORDER_KEY = "rgba-order";
+
+ private const string DYSLEXIA_KEY = "dyslexia-friendly-support";
+ private const string FONT_KEY = "font-name";
+ private const string DOCUMENT_FONT_KEY = "document-font-name";
+ private const string MONOSPACE_FONT_KEY = "monospace-font-name";
+
+ private const string OD_REG_FONT = "OpenDyslexic Regular 9";
+ private const string OD_DOC_FONT = "OpenDyslexic Regular 10";
+ private const string OD_MON_FONT = "OpenDyslexicMono Regular 10";
+
+ private const double[] TEXT_SCALE = {0.75, 1, 1.25, 1.5};
+
+ private Granite.Widgets.ModeButton text_size_modebutton;
+ private TextFontOptionRadioGroup text_antialias_group;
+ private TextFontOptionRadioGroup text_subpixelorder_group;
+ private Gtk.Label text_subpixelorder_label;
+ private Gtk.Label text_subpixelorder_description_label;
+
+ construct {
+ column_spacing = 12;
+ halign = Gtk.Align.CENTER;
+ row_spacing = 6;
+ margin_start = margin_end = 12;
+ margin_bottom = 24;
+
+ var text_size_label = new Gtk.Label (_("Text size:")) {
+ halign = Gtk.Align.END,
+ margin_top = 24
+ };
+
+ text_size_modebutton = new Granite.Widgets.ModeButton () {
+ margin_top = 24
+ };
+ text_size_modebutton.append_text (_("Small"));
+ text_size_modebutton.append_text (_("Default"));
+ text_size_modebutton.append_text (_("Large"));
+ text_size_modebutton.append_text (_("Larger"));
+
+ var text_antialias_label = new Gtk.Label(_("Text anti-aliasing:")) {
+ halign = Gtk.Align.END,
+ margin_top = 18
+ };
+
+ text_antialias_group = new TextFontOptionRadioGroup () {
+ margin_top = 18
+ };
+
+ text_antialias_group.append_option(_("None"), (font_options) => {
+ font_options.set_antialias(Cairo.Antialias.NONE);
+ });
+
+ text_antialias_group.append_option(_("Grayscale"), (font_options) => {
+ font_options.set_antialias(Cairo.Antialias.GRAY);
+ });
+
+ text_antialias_group.append_option(_("Subpixel"), (font_options) => {
+ font_options.set_antialias(Cairo.Antialias.SUBPIXEL);
+ });
+
+
+ var text_antialias_description_label = new Gtk.Label (
+ _("Text anti-aliasing can improve text appearance and legibility, depending on display hardware. Choose the mode that looks best on your display. Apps have to be re-opened for changes to take effect")
+ ) {
+ max_width_chars = 60,
+ wrap = true,
+ xalign = 0
+ };
+
+ text_antialias_description_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+
+ text_subpixelorder_label = new Gtk.Label(_("Text subpixel order:")) {
+ halign = Gtk.Align.END,
+ margin_top = 18
+ };
+
+ text_subpixelorder_group = new TextFontOptionRadioGroup () {
+ margin_top = 18
+ };
+
+ text_subpixelorder_group.append_option(_("Red On Left (RGB)"), (font_options) => {
+ font_options.set_subpixel_order (Cairo.SubpixelOrder.RGB);
+ });
+
+ text_subpixelorder_group.append_option(_("Blue On Left (BGR)"), (font_options) => {
+ font_options.set_subpixel_order (Cairo.SubpixelOrder.BGR);
+ });
+
+ text_subpixelorder_group.append_option(_("Red On Top (VRGB)"), (font_options) => {
+ font_options.set_subpixel_order (Cairo.SubpixelOrder.VRGB);
+ });
+
+ text_subpixelorder_group.append_option(_("Blue On Top (VBGR)"), (font_options) => {
+ font_options.set_subpixel_order (Cairo.SubpixelOrder.VBGR);
+ });
+
+ text_subpixelorder_description_label = new Gtk.Label (
+ _("Different displays have different positions of the red, green, and blue subpixels. Select the mode that looks the best on your display. Apps have to be re-opened for changes to take effect")
+ ) {
+ max_width_chars = 60,
+ wrap = true,
+ xalign = 0
+ };
+
+ text_subpixelorder_description_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+
+
+ var dyslexia_font_label = new Gtk.Label (_("Dyslexia-friendly text:")) {
+ halign = Gtk.Align.END,
+ margin_top = 18
+ };
+
+ var dyslexia_font_switch = new Gtk.Switch () {
+ halign = Gtk.Align.START,
+ margin_top = 18
+ };
+
+ var dyslexia_font_description_label = new Gtk.Label (
+ _("Bottom-heavy shapes and increased character spacing can help improve legibility and reading speed.")
+ ) {
+ max_width_chars = 60,
+ wrap = true,
+ xalign = 0
+ };
+ dyslexia_font_description_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
+
+ /* Rows 0 to 3 are for the dark style UI that gets attached only if we
+ * can connect to the DBus API
+ *
+ * Row 4 and 5 are for accent color UI that gets constructed only if the
+ * current stylesheet is supported (begins with the STYLESHEET_PREFIX)
+ */
+ attach (text_size_label, 0, 8);
+ attach (text_size_modebutton, 1, 8, 2);
+
+ attach (text_antialias_label, 0, 9);
+ attach (text_antialias_group, 1, 9, 2);
+ attach (text_antialias_description_label, 1, 10, 2);
+
+ attach (text_subpixelorder_label, 0, 11);
+ attach (text_subpixelorder_group, 1, 11, 2);
+ attach (text_subpixelorder_description_label, 1, 12, 2);
+
+ attach (dyslexia_font_label, 0, 13);
+ attach (dyslexia_font_switch, 1, 13);
+ attach (dyslexia_font_description_label, 1, 14, 2);
+
+ var interface_settings = new GLib.Settings (INTERFACE_SCHEMA);
+
+ update_text_size_modebutton (interface_settings);
+
+ interface_settings.changed.connect (() => {
+ update_text_size_modebutton (interface_settings);
+ });
+
+ text_size_modebutton.mode_changed.connect (() => {
+ set_text_scale (interface_settings, text_size_modebutton.selected);
+ });
+
+ dyslexia_font_switch.set_active (update_dyslexia_font_switch (interface_settings));
+
+ dyslexia_font_switch.state_set.connect (() => {
+ toggle_dyslexia_support (interface_settings, dyslexia_font_switch.get_active () );
+ });
+
+ var xsettings_settings = new GLib.Settings (XSETTINGS_SCHEMA);
+
+ update_text_antialias_modebutton (xsettings_settings);
+
+ xsettings_settings.changed.connect (() => {
+ update_text_antialias_modebutton (xsettings_settings);
+ update_text_subpixelorder_modebutton (xsettings_settings);
+ });
+
+ text_antialias_group.changed.connect (() => {
+ set_text_antialias (xsettings_settings, text_antialias_group.selected);
+ });
+
+ update_text_subpixelorder_modebutton (xsettings_settings);
+
+ text_subpixelorder_group.changed.connect (() => {
+ set_text_subpixelorder (xsettings_settings, text_subpixelorder_group.selected);
+ });
+ }
+
+ private void toggle_dyslexia_support (GLib.Settings interface_settings, bool state) {
+ if (state == true) {
+ interface_settings.set_string (FONT_KEY, OD_REG_FONT);
+ interface_settings.set_string (DOCUMENT_FONT_KEY, OD_DOC_FONT);
+ interface_settings.set_string (MONOSPACE_FONT_KEY, OD_MON_FONT);
+ }
+ else {
+ interface_settings.reset (FONT_KEY);
+ interface_settings.reset (DOCUMENT_FONT_KEY);
+ interface_settings.reset (MONOSPACE_FONT_KEY);
+ }
+ }
+
+ private bool update_dyslexia_font_switch (GLib.Settings interface_settings) {
+ var interface_font = interface_settings.get_string (FONT_KEY);
+ var document_font = interface_settings.get_string (DOCUMENT_FONT_KEY);
+ var monospace_font = interface_settings.get_string (MONOSPACE_FONT_KEY);
+
+ if (interface_font == OD_REG_FONT || document_font == OD_DOC_FONT || monospace_font == OD_MON_FONT ) {
+ return true;
+ }
+
+ else {
+ return false;
+ }
+ }
+
+ private int get_text_scale (GLib.Settings interface_settings) {
+ double text_scaling_factor = interface_settings.get_double (TEXT_SIZE_KEY);
+
+ if (text_scaling_factor <= TEXT_SCALE[0]) {
+ return 0;
+ } else if (text_scaling_factor <= TEXT_SCALE[1]) {
+ return 1;
+ } else if (text_scaling_factor <= TEXT_SCALE[2]) {
+ return 2;
+ } else {
+ return 3;
+ }
+ }
+
+ private void set_text_scale (GLib.Settings interface_settings, int option) {
+ interface_settings.set_double (TEXT_SIZE_KEY, TEXT_SCALE[option]);
+ }
+
+ private void update_text_size_modebutton (GLib.Settings interface_settings) {
+ text_size_modebutton.set_active (get_text_scale (interface_settings));
+ }
+
+ private int get_text_antialias (GLib.Settings xsettings_settings) {
+ return xsettings_settings.get_enum (ANTIALIAS_KEY);
+ }
+
+ private void set_text_antialias (GLib.Settings xsettings_settings, int option) {
+ xsettings_settings.set_enum (ANTIALIAS_KEY, option);
+ }
+
+ private void update_text_antialias_modebutton (GLib.Settings xsettings_settings) {
+ text_antialias_group.set_active (get_text_antialias (xsettings_settings));
+ }
+
+ private int get_text_subpixelorder (GLib.Settings xsettings_settings) {
+ return xsettings_settings.get_enum (SUBPIXELORDER_KEY) - 1;
+ }
+
+ private void set_text_subpixelorder (GLib.Settings xsettings_settings, int option) {
+ xsettings_settings.set_enum (SUBPIXELORDER_KEY, option + 1);
+ }
+
+ private void update_text_subpixelorder_modebutton (GLib.Settings xsettings_settings) {
+
+ var antialias = get_text_antialias (xsettings_settings);
+
+ if (antialias != 2) {
+ text_subpixelorder_label.visible = false;
+ text_subpixelorder_group.visible = false;
+ text_subpixelorder_description_label.visible = false;
+ } else {
+ text_subpixelorder_label.visible = true;
+ text_subpixelorder_group.visible = true;
+ text_subpixelorder_description_label.visible = true;
+ }
+
+ text_subpixelorder_group.set_active (get_text_subpixelorder (xsettings_settings));
+ }
+
+}
diff --git a/src/Widgets/TextFontOptionRadioGroup.vala b/src/Widgets/TextFontOptionRadioGroup.vala
new file mode 100644
index 000000000..1a24f53ed
--- /dev/null
+++ b/src/Widgets/TextFontOptionRadioGroup.vala
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2021 Justin Haygood
+ *
+ * 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 .
+ *
+ */
+
+public class PantheonShell.TextFontOptionRadioGroup : Gtk.Box {
+
+ public delegate void FontOptionsCallback (Cairo.FontOptions font_options);
+ public signal void changed ();
+
+ private Gee.List radio_buttons;
+
+ public TextFontOptionRadioGroup () {
+ Object(orientation: Gtk.Orientation.VERTICAL, spacing: 5);
+
+ radio_buttons = new Gee.ArrayList ();
+ }
+
+ public void append_option(string label, FontOptionsCallback font_options_callback) {
+
+ Gtk.RadioButton radio_button;
+
+ if (radio_buttons.size == 0) {
+ radio_button = new Gtk.RadioButton (null) {
+ halign = Gtk.Align.START
+ };
+ } else {
+ radio_button = new Gtk.RadioButton.from_widget (radio_buttons.first ()) {
+ halign = Gtk.Align.START
+ };
+ }
+
+ radio_buttons.add (radio_button);
+
+ var radio_button_label = new Gtk.Label (label);
+ radio_button.add (radio_button_label);
+
+ var label_font_options = new Cairo.FontOptions ();
+
+ font_options_callback(label_font_options);
+
+ radio_button_label.set_font_options (label_font_options);
+
+ pack_start (radio_button);
+
+ radio_button.toggled.connect(() => {
+ changed ();
+ });
+ }
+
+ public int selected {
+ get {
+ for (var i = 0; i < radio_buttons.size; i++) {
+ if (radio_buttons[i].active) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ set {
+ set_active (value);
+ }
+ }
+
+ public void set_active (int new_active_index) {
+ radio_buttons[new_active_index].active = true;
+ }
+}
diff --git a/src/meson.build b/src/meson.build
index 259c0bf2c..ccfd55626 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -6,8 +6,10 @@ plug_files = files(
'Views/Appearance.vala',
'Views/Dock.vala',
'Views/Multitasking.vala',
+ 'Views/Text.vala',
'Views/Wallpaper.vala',
'Widgets/SolidColorContainer.vala',
+ 'Widgets/TextFontOptionRadioGroup.vala',
'Widgets/WallpaperContainer.vala',
)