import Adw from 'gi://Adw'; import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Gio from 'gi://Gio'; import Gtk from 'gi://Gtk'; /// Given a component (described by its preferences node), a gschema key and /// a Gtk.ColorButton, binds everything transparently. let bind_color = function (component, key, widget) { let property_name = key.replaceAll('-', '_').toUpperCase(); let parse_color = _ => { let [r, g, b, a] = component[property_name]; let w = widget.rgba; w.red = r; w.green = g; w.blue = b; w.alpha = a; widget.rgba = w; }; component.settings.connect('changed::' + key, parse_color); widget.connect('color-set', _ => { let c = widget.rgba; component[property_name] = [c.red, c.green, c.blue, c.alpha]; }); parse_color(); }; export const CustomizeRow = GObject.registerClass({ GTypeName: 'CustomizeRow', Template: GLib.uri_resolve_relative(import.meta.url, '../ui/customize-row.ui', GLib.UriFlags.NONE), InternalChildren: [ 'sigma', 'brightness', 'color', 'color_row', 'noise_amount', 'noise_amount_row', 'noise_lightness', 'noise_lightness_row', 'noise_color_notice' ], }, class CustomizeRow extends Adw.ExpanderRow { /// Makes the required connections between the widgets and the preferences. /// /// This function may be bound to another object than CustomizeRow, if we /// are using it for the General page; some things will then change (no /// expansion row, and no notice) /// /// The color_and_noise parameter is either a boolean (true by default) or /// a widget; and permits selecting weather or not we want to show the color /// and noise buttons to the user. If it is a widget, it means we need to /// dynamically update their visibility, according to the widget's state. connect_to(settings, component_settings, color_and_noise = true) { let s = component_settings.settings; // is not fired if in General page if (this instanceof CustomizeRow) // bind the customize button s.bind( 'customize', this, 'enable-expansion', Gio.SettingsBindFlags.DEFAULT ); // bind sigma and brightness s.bind( 'sigma', this._sigma, 'value', Gio.SettingsBindFlags.DEFAULT ); s.bind( 'brightness', this._brightness, 'value', Gio.SettingsBindFlags.DEFAULT ); // bind the color button bind_color(component_settings, 'color', this._color); // bind noise sliders s.bind( 'noise-amount', this._noise_amount, 'value', Gio.SettingsBindFlags.DEFAULT ); s.bind( 'noise-lightness', this._noise_lightness, 'value', Gio.SettingsBindFlags.DEFAULT ); // color_and_noise is either a boolean or a widget, if true, or it is a // widget, this will appropriately show the required preferences about // setting the color and noise if (color_and_noise) { // if we gave the static_blur widget, we are dealing with the panel, // and binding it to enable/disable the required components when // switching between static and dynamic blur if (color_and_noise instanceof Gtk.Switch) { // bind its state to dynamically toggle the notice and rows color_and_noise.bind_property( 'active', this._color_row, 'visible', GObject.BindingFlags.SYNC_CREATE ); color_and_noise.bind_property( 'active', this._noise_amount_row, 'visible', GObject.BindingFlags.SYNC_CREATE ); color_and_noise.bind_property( 'active', this._noise_lightness_row, 'visible', GObject.BindingFlags.SYNC_CREATE ); color_and_noise.bind_property( 'active', this._noise_color_notice, 'visible', GObject.BindingFlags.INVERT_BOOLEAN ); // only way to get the correct state when first opening the // window... setTimeout(_ => { let is_visible = color_and_noise.active; this._color_row.visible = is_visible; this._noise_amount_row.visible = is_visible; this._noise_lightness_row.visible = is_visible; this._noise_color_notice.visible = !is_visible; }, 10); } // if in General page, there is no notice at all if (this instanceof CustomizeRow) { // disable the notice this._noise_color_notice.visible = false; } } else { // enable the notice and disable color and noise preferences this._color_row.visible = false; this._noise_amount_row.visible = false; this._noise_lightness_row.visible = false; this._noise_color_notice.visible = true; } // now we bind the color-and-noise preference to the sensitivity of the // associated widgets, this will grey them out if the user choose not to // have color and noise enabled // note: I would love to bind to the visibility instead, but this part // is already dirty enough, it would look like I obfuscate my code // intentionally... (I am not) settings.settings.bind( 'color-and-noise', this._color_row, 'sensitive', Gio.SettingsBindFlags.DEFAULT ); settings.settings.bind( 'color-and-noise', this._noise_amount_row, 'sensitive', Gio.SettingsBindFlags.DEFAULT ); settings.settings.bind( 'color-and-noise', this._noise_lightness_row, 'sensitive', Gio.SettingsBindFlags.DEFAULT ); }; });