diff --git a/fuses/appearance/AppearanceView.vala b/fuses/appearance/AppearanceView.vala index bcfd4de..00da59f 100644 --- a/fuses/appearance/AppearanceView.vala +++ b/fuses/appearance/AppearanceView.vala @@ -1,68 +1,40 @@ public class AppearanceView : Gtk.Box { + private static GLib.Settings bg_settings; + private static GLib.Settings fusebox_appearance_settings; private static GLib.Settings interface_settings; private static GLib.Settings tau_appearance_settings; - private static GLib.Settings fusebox_appearance_settings; - private static GLib.Settings bg_settings; public Fusebox.Fuse fuse { get; construct set; } - private He.SegmentedButton color_type_button; - private Gtk.ToggleButton basic_type_button; - private Gtk.Stack color_stack; private Bis.Carousel color_carousel; - private PrefersAccentColorButton red; - private PrefersAccentColorButton yellow; - private PrefersAccentColorButton green; - private PrefersAccentColorButton blue; - private PrefersAccentColorButton purple; - private PrefersAccentColorButton pink; - private PrefersAccentColorButton multi; - private Gtk.FlowBoxChild defavlt; // default is a Vala keyword, deal with it - private Gtk.FlowBoxChild muted; - private Gtk.FlowBoxChild vibrant; - private Gtk.FlowBoxChild salad; - private Gtk.CheckButton prefer_light_radio; - private Gtk.CheckButton prefer_default_radio; - private Gtk.CheckButton prefer_dark_radio; private Gtk.Box accent_box; - private Gtk.FlowBox ensor_flowbox; + private Gtk.CheckButton prefer_dark_radio; + private Gtk.CheckButton prefer_default_radio; + private Gtk.CheckButton prefer_light_radio; private Gtk.FlowBoxChild current_emb; + private Gtk.Stack color_stack; + private Gtk.ToggleButton basic_type_button; + private He.SegmentedButton color_type_button; + + private PrefersAccentColorButton blue; + private PrefersAccentColorButton green; + private PrefersAccentColorButton multi; + private PrefersAccentColorButton pink; + private PrefersAccentColorButton purple; + private PrefersAccentColorButton red; + private PrefersAccentColorButton yellow; - public He.ContentBlockImage wallpaper_preview; - public He.ContentBlockImage wallpaper_lock_preview; - public Appearance.WallpaperGrid wallpaper_view; - public Gtk.ToggleButton wallpaper_type_button; public Gtk.ScrolledWindow sw; public Gtk.Stack contrast_stack; - public Gtk.Stack wallpaper_stack; public Gtk.Stack main_stack; + public Gtk.Stack wallpaper_stack; + public Gtk.ToggleButton wallpaper_type_button; + public He.ContentBlockImage wallpaper_lock_preview; + public He.ContentBlockImage wallpaper_preview; - private uint rscale_timeout; - - private string _ensor; - public string ensor { - get { return _ensor; } - set { - if (value == "default") { - select_ensor (defavlt); - return; - } - - if (value == "muted") { - select_ensor (muted); - return; - } - - if (value == "vibrant") { - select_ensor (vibrant); - return; - } - - _ensor = value; - critical ("Unknown palette ID: %s", value); - } - } + public Appearance.WallpaperGrid wallpaper_view; + private uint rscale_timeout; public AppearanceView (Fusebox.Fuse _fuse) { Object (fuse: _fuse); @@ -238,40 +210,6 @@ public class AppearanceView : Gtk.Box { accent_box.append (green); accent_box.append (blue); - defavlt = new Gtk.FlowBoxChild (); - defavlt.child = new EnsorModeButton ("default"); - defavlt.tooltip_text = _("Default Scheme"); - muted = new Gtk.FlowBoxChild (); - muted.child = new EnsorModeButton ("muted"); - muted.tooltip_text = _("Muted Scheme"); - vibrant = new Gtk.FlowBoxChild (); - vibrant.child = new EnsorModeButton ("vibrant"); - vibrant.tooltip_text = _("Vibrant Scheme"); - salad = new Gtk.FlowBoxChild (); - salad.child = new EnsorModeButton ("salad"); - salad.tooltip_text = _("Fruit Salad Scheme"); - - ensor_flowbox = new Gtk.FlowBox () { - hexpand = true, - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER, - column_spacing = 12, - homogeneous = true, - min_children_per_line = 4, - max_children_per_line = 4 - }; - ensor_flowbox.add_css_class ("ensor-box"); - ensor_flowbox.append (defavlt); - ensor_flowbox.append (muted); - ensor_flowbox.append (vibrant); - ensor_flowbox.append (salad); - ensor_flowbox.child_activated.connect (child_activated_cb); - - ensor_refresh (); - tau_appearance_settings.notify["changed::ensor-scheme"].connect (() => { - ensor_refresh (); - }); - wallpaper_type_button = new Gtk.ToggleButton () { active = fusebox_appearance_settings.get_boolean ("wallpaper-accent") == true }; @@ -289,11 +227,16 @@ public class AppearanceView : Gtk.Box { color_type_button.append (basic_type_button); color_carousel = new Bis.Carousel (); - color_carousel.append (ensor_flowbox); + var color_carousel_dots = new Bis.CarouselIndicatorDots (); + color_carousel_dots.set_carousel (color_carousel); + + var carousel_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 4); + carousel_box.append (color_carousel); + carousel_box.append (color_carousel_dots); color_stack = new Gtk.Stack (); color_stack.add_titled (accent_box, "basic", "Basic Colors"); - color_stack.add_titled (color_carousel, "wallpaper", "Wallpaper Colors"); + color_stack.add_titled (carousel_box, "wallpaper", "Wallpaper Colors"); if (wallpaper_type_button.active) { color_stack.set_visible_child_name ("wallpaper"); @@ -309,14 +252,12 @@ public class AppearanceView : Gtk.Box { pink.set_active (false); } else { color_stack.set_visible_child_name ("basic"); - select_ensor (defavlt); accent_box.sensitive = true; } basic_type_button.toggled.connect (() => { color_stack.set_visible_child_name ("basic"); fusebox_appearance_settings.set_boolean ("wallpaper-accent", false); - select_ensor (defavlt); accent_box.sensitive = true; }); wallpaper_type_button.toggled.connect (() => { @@ -510,55 +451,51 @@ public class AppearanceView : Gtk.Box { He.Ensor.accent_from_pixels_async.begin (pixbuf.get_pixels_with_length (), pixbuf.get_has_alpha (), (obj, res) => { GLib.Array result = He.Ensor.accent_from_pixels_async.end (res); - if (result.index (0) != null) { - int[] argb_ints = { result.index (0) }; - ColorGenerator color_gen = new ColorGenerator (argb_ints); - Gee.ArrayList resd = color_gen.get_generated_colors (He.SchemeVariant.DEFAULT); - ((EnsorModeButton)defavlt.get_first_child ()).colors = resd; - Gee.ArrayList resm = color_gen.get_generated_colors (He.SchemeVariant.MUTED); - ((EnsorModeButton)muted.get_first_child ()).colors = resm; - Gee.ArrayList resv = color_gen.get_generated_colors (He.SchemeVariant.VIBRANT); - ((EnsorModeButton)vibrant.get_first_child ()).colors = resv; - Gee.ArrayList ress = color_gen.get_generated_colors (He.SchemeVariant.SALAD); - ((EnsorModeButton)salad.get_first_child ()).colors = ress; - - tau_appearance_settings.set_string ("accent-color", He.hexcode_argb (result.index (0))); - } - if (result.index (1) != null) { - int[] argb_ints = { result.index (0), result.index (1) }; - ColorGenerator color_gen = new ColorGenerator (argb_ints); - Gee.ArrayList resd = color_gen.get_generated_colors (He.SchemeVariant.DEFAULT); - ((EnsorModeButton)defavlt.get_first_child ()).colors = resd; - Gee.ArrayList resm = color_gen.get_generated_colors (He.SchemeVariant.MUTED); - ((EnsorModeButton)muted.get_first_child ()).colors = resm; - Gee.ArrayList resv = color_gen.get_generated_colors (He.SchemeVariant.VIBRANT); - ((EnsorModeButton)vibrant.get_first_child ()).colors = resv; - Gee.ArrayList ress = color_gen.get_generated_colors (He.SchemeVariant.SALAD); - ((EnsorModeButton)salad.get_first_child ()).colors = ress; - } - if (result.index (1) != null && result.index (2) != null) { - int[] argb_ints = { result.index (0), result.index (1), result.index (2) }; - ColorGenerator color_gen = new ColorGenerator (argb_ints); - Gee.ArrayList resd = color_gen.get_generated_colors (He.SchemeVariant.DEFAULT); - ((EnsorModeButton)defavlt.get_first_child ()).colors = resd; - Gee.ArrayList resm = color_gen.get_generated_colors (He.SchemeVariant.MUTED); - ((EnsorModeButton)muted.get_first_child ()).colors = resm; - Gee.ArrayList resv = color_gen.get_generated_colors (He.SchemeVariant.VIBRANT); - ((EnsorModeButton)vibrant.get_first_child ()).colors = resv; - Gee.ArrayList ress = color_gen.get_generated_colors (He.SchemeVariant.SALAD); - ((EnsorModeButton)salad.get_first_child ()).colors = ress; + int[] argb_ints = new int[3]; // We're only interested in 4 colors. + + for (int i = 0; i == color_carousel.get_n_pages(); i++) { + color_carousel.remove (color_carousel.get_nth_page(i)); } - if (result.index (1) != null && result.index (2) != null && result.index (3) != null) { - int[] argb_ints = { result.index (0), result.index (1), result.index (2), result.index (3) }; - ColorGenerator color_gen = new ColorGenerator (argb_ints); - Gee.ArrayList resd = color_gen.get_generated_colors (He.SchemeVariant.DEFAULT); - ((EnsorModeButton)defavlt.get_first_child ()).colors = resd; - Gee.ArrayList resm = color_gen.get_generated_colors (He.SchemeVariant.MUTED); - ((EnsorModeButton)muted.get_first_child ()).colors = resm; - Gee.ArrayList resv = color_gen.get_generated_colors (He.SchemeVariant.VIBRANT); - ((EnsorModeButton)vibrant.get_first_child ()).colors = resv; - Gee.ArrayList ress = color_gen.get_generated_colors (He.SchemeVariant.SALAD); - ((EnsorModeButton)salad.get_first_child ()).colors = ress; + + for (int i = 0; i < result.length; i++) { + var value = result.index(i); + if (value != null) { + argb_ints[i] = value; + } + + var defavlt = new Gtk.FlowBoxChild (); + defavlt.child = new EnsorModeButton (argb_ints[i], "default"); + defavlt.tooltip_text = _("Default Scheme"); + var muted = new Gtk.FlowBoxChild (); + muted.child = new EnsorModeButton (argb_ints[i], "muted"); + muted.tooltip_text = _("Muted Scheme"); + var vibrant = new Gtk.FlowBoxChild (); + vibrant.child = new EnsorModeButton (argb_ints[i], "vibrant"); + vibrant.tooltip_text = _("Vibrant Scheme"); + var salad = new Gtk.FlowBoxChild (); + salad.child = new EnsorModeButton (argb_ints[i], "salad"); + salad.tooltip_text = _("Fruit Salad Scheme"); + + var ensor_flowbox = new Gtk.FlowBox () { + hexpand = true, + halign = Gtk.Align.CENTER, + valign = Gtk.Align.CENTER, + column_spacing = 12, + homogeneous = true, + min_children_per_line = 4, + max_children_per_line = 4 + }; + ensor_flowbox.add_css_class ("ensor-box"); + ensor_flowbox.append (defavlt); + ensor_flowbox.append (muted); + ensor_flowbox.append (vibrant); + ensor_flowbox.append (salad); + ensor_flowbox.child_activated.connect ((c) => { + var ensor = ((EnsorModeButton)c.get_first_child ()).mode; + tau_appearance_settings.set_string ("ensor-scheme", ensor); + }); + + color_carousel.append (ensor_flowbox); } loop.quit (); @@ -569,72 +506,6 @@ public class AppearanceView : Gtk.Box { } } - private void child_activated_cb (Gtk.FlowBoxChild child) { - select_ensor (child); - } - - private void select_ensor (Gtk.FlowBoxChild emb) { - current_emb = emb; - _ensor = ((EnsorModeButton)emb.get_first_child ()).mode; - tau_appearance_settings.set_string ("ensor-scheme", _ensor); - ensor_flowbox.select_child (current_emb); - } - - private void ensor_refresh () { - string value = tau_appearance_settings.get_string ("ensor-scheme"); - - if (value == "default") { - select_ensor (defavlt); - } else if (value == "muted") { - select_ensor (muted); - } else if (value == "vibrant") { - select_ensor (vibrant); - } else if (value == "salad") { - select_ensor (salad); - } - } - - private class EnsorModeButton : Gtk.Box { - public string mode { get; construct; } - public Gee.ArrayList colors; - - public EnsorModeButton (string mode) { - Object ( - mode: mode - ); - overflow = HIDDEN; - add_css_class ("circle-radius"); - } - - public override void snapshot (Gtk.Snapshot snapshot) { - int w = get_width (); - int h = get_height (); - - float r = 999; - - snapshot.translate ({ w / 2, h / 2 }); - - Gsk.RoundedRect rect = {}; - rect.init_from_rect ({ { -r, -r }, { r* 2, r* 2 } }, r); - snapshot.push_rounded_clip (rect); - snapshot.append_color (color_to_rgba (0), { { -r, -r }, { r, r } }); - snapshot.append_color (color_to_rgba (1), { { -r, 0 }, { r, r } }); - snapshot.append_color (color_to_rgba (2), { { 0, 0 }, { r, r } }); - snapshot.append_color (color_to_rgba (3), { { 0, -r }, { r, r } }); - snapshot.pop (); - snapshot.append_inset_shadow (rect, { 0, 0, 0 }, 0, 0, 1, 0); - } - - private Gdk.RGBA color_to_rgba (int index) { - int rgb = colors.get (index); - float r = ((rgb >> 16) & 0xFF) / 255.0f; - float g = ((rgb >> 8) & 0xFF) / 255.0f; - float b = (rgb & 0xFF) / 255.0f; - - return { r, g, b, 1.0f }; - } - } - private class PrefersAccentColorButton : Gtk.CheckButton { public string color { get; construct; } public string hex { get; construct set; } diff --git a/fuses/appearance/ColorGenerator.vala b/fuses/appearance/Utils/ColorGenerator.vala similarity index 92% rename from fuses/appearance/ColorGenerator.vala rename to fuses/appearance/Utils/ColorGenerator.vala index 49ef955..29b5349 100644 --- a/fuses/appearance/ColorGenerator.vala +++ b/fuses/appearance/Utils/ColorGenerator.vala @@ -1,16 +1,14 @@ -using Gee; - public class ColorGenerator { private const int SCHEME_COUNT = 6; // 6 entries on the He.SchemeVariant enum private const int COLORS_PER_SCHEME = 4; private const int DEFAULT_COLOR = 0x8C56BF; // Tau Purple as fallback private int[] argb_ints; - private ArrayList generated_colors; + private Gee.ArrayList generated_colors; public ColorGenerator(int[] argb_ints) { this.argb_ints = argb_ints; - this.generated_colors = new ArrayList(); + this.generated_colors = new Gee.ArrayList(); generate_colors(); } @@ -72,14 +70,14 @@ public class ColorGenerator { } // Retrieves the generated colors for a specified scheme - public ArrayList get_generated_colors(He.SchemeVariant scheme_variant) { + public Gee.ArrayList get_generated_colors(He.SchemeVariant scheme_variant) { int scheme_index = (int) scheme_variant; if (scheme_index < 0 || scheme_index >= SCHEME_COUNT) { warning("Scheme index %d is out of range. Returning default colors.", scheme_index); return get_default_colors(); } - var colors = new ArrayList(); + var colors = new Gee.ArrayList(); int base_index = scheme_index * COLORS_PER_SCHEME; for (int i = 0; i < argb_ints.length; i++) { @@ -102,7 +100,7 @@ public class ColorGenerator { } // Retrieves the colors for a specific ARGB int and scheme - public ArrayList get_colors_for_argb(int index, He.SchemeVariant scheme_variant) { + public Gee.ArrayList get_colors_for_argb(int index, He.SchemeVariant scheme_variant) { if (index < 0 || index >= argb_ints.length) { warning("Index %d out of range for ARGB values. Returning default colors.", index); return get_default_colors(); @@ -114,7 +112,7 @@ public class ColorGenerator { return get_default_colors(); } - var colors = new ArrayList(); + var colors = new Gee.ArrayList(); int base_index = index * SCHEME_COUNT * COLORS_PER_SCHEME + scheme_index * COLORS_PER_SCHEME; for (int i = 0; i < COLORS_PER_SCHEME; i++) { @@ -125,8 +123,8 @@ public class ColorGenerator { } // Provides a default set of colors - private ArrayList get_default_colors() { - var default_colors = new ArrayList(); + private Gee.ArrayList get_default_colors() { + var default_colors = new Gee.ArrayList(); for (int i = 0; i <= COLORS_PER_SCHEME; i++) { default_colors.add(DEFAULT_COLOR); } diff --git a/fuses/appearance/Utils/EnsorModeButton.vala b/fuses/appearance/Utils/EnsorModeButton.vala new file mode 100644 index 0000000..986853d --- /dev/null +++ b/fuses/appearance/Utils/EnsorModeButton.vala @@ -0,0 +1,99 @@ +public class EnsorModeButton : Gtk.Box { + public Gee.ArrayList colors; + ColorGenerator generator; + + private static GLib.Settings tau_appearance_settings; + + private string _mode; + public string mode { + get { return _mode; } + set { + if (_mode != value) { + _mode = value; + update_colors(); + queue_draw(); + } + } + } + + static construct { + tau_appearance_settings = new GLib.Settings ("com.fyralabs.desktop.appearance"); + } + + public EnsorModeButton(int color, string initial_mode) { + this.mode = initial_mode; + generator = new ColorGenerator ({color}); + set_colors(generator.get_generated_colors(get_scheme_variant(mode))); + + overflow = HIDDEN; + add_css_class ("circle-radius"); + + tau_appearance_settings.set_string ("accent-color", He.hexcode_argb (color)); + } + + private void update_colors() { + if (!is_valid_mode(mode)) { + warning("Invalid mode '%s'. Using default colors.", mode); + mode = "default"; + } + + set_colors(generator.get_generated_colors(get_scheme_variant(mode))); + queue_draw(); + } + + public void set_colors(Gee.ArrayList colors) { + if (colors.size == 0) { + warning("EnsorModeButton requires # of colors"); + return; + } + + this.colors = colors; + queue_draw(); + } + + private He.SchemeVariant get_scheme_variant(string mode) { + switch (mode) { + default: + case "default": + return He.SchemeVariant.DEFAULT; + case "muted": + return He.SchemeVariant.MUTED; + case "vibrant": + return He.SchemeVariant.VIBRANT; + case "salad": + return He.SchemeVariant.SALAD; + } + } + + private bool is_valid_mode(string mode) { + return mode == "default" || mode == "muted" || mode == "vibrant" || mode == "salad"; + } + + public override void snapshot (Gtk.Snapshot snapshot) { + int w = get_width (); + int h = get_height (); + + float r = 999; + + snapshot.translate ({ w / 2, h / 2 }); + + Gsk.RoundedRect rect = {}; + rect.init_from_rect ({ { -r, -r }, { r* 2, r* 2 } }, r); + snapshot.push_rounded_clip (rect); + snapshot.append_color (color_to_rgba (0), { { -r, -r }, { r, r } }); + snapshot.append_color (color_to_rgba (1), { { -r, 0 }, { r, r } }); + snapshot.append_color (color_to_rgba (2), { { 0, 0 }, { r, r } }); + snapshot.append_color (color_to_rgba (3), { { 0, -r }, { r, r } }); + snapshot.pop (); + snapshot.append_inset_shadow (rect, { 0, 0, 0 }, 0, 0, 1, 0); + } + + private Gdk.RGBA color_to_rgba (int index) { + int rgb = colors.get (index); + float r = ((rgb >> 16) & 0xFF) / 255.0f; + float g = ((rgb >> 8) & 0xFF) / 255.0f; + float b = (rgb & 0xFF) / 255.0f; + + return { r, g, b, 1.0f }; + } +} \ No newline at end of file diff --git a/fuses/appearance/meson.build b/fuses/appearance/meson.build index 95c0514..157dd9d 100644 --- a/fuses/appearance/meson.build +++ b/fuses/appearance/meson.build @@ -5,7 +5,8 @@ fuse_files = files( 'WallpaperGrid.vala', 'TextView.vala', 'WindowView.vala', - 'ColorGenerator.vala', + 'Utils/ColorGenerator.vala', + 'Utils/EnsorModeButton.vala', # 'DockView.vala', )