linux-presets/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blo.../prefs.js

642 lines
22 KiB
JavaScript
Executable File

/*
This file is part of CoverflowAltTab.
CoverflowAltTab 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.
CoverflowAltTab 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 CoverflowAltTab. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* CoverflowAltTab
*
* Preferences dialog for "gnome-extensions prefs" tool
*
* Based on preferences in the following extensions: JustPerfection, dash2doc-lite, night theme switcher, and desktop cube
*
*/
import Adw from 'gi://Adw';
import Gdk from 'gi://Gdk';
import GLib from 'gi://GLib';
import Gtk from 'gi://Gtk';
import Gio from 'gi://Gio';
import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'
const easing_options = [
{
id: 'ease-linear', name: 'easeLinear'
}, {
id: 'ease-in-quad', name: "easeInQuad"
}, {
id: 'ease-out-quad', name: "easeOutQuad"
}, {
id: 'ease-in-out-quad', name: "easeInOutQuad"
}, {
id: 'ease-in-cubic', name: "easeInCubic"
}, {
id: 'ease-out-cubic', name: "easeOutCubic"
}, {
id: 'ease-in-out-cubic', name: "easeInOutCubic"
}, {
id: 'ease-in-quart', name: "easeInQuart"
}, {
id: 'ease-out-quart', name: "easeOutQuart"
}, {
id: 'ease-in-out-quart', name: "easeInOutQuart"
}, {
id: 'ease-in-quint', name: "easeInQuint"
}, {
id: 'ease-out-quint', name: "easeOutQuint"
}, {
id: 'ease-in-out-quint', name: "easeInOutQuint"
}, {
id: 'ease-in-sine', name: "easeInSine"
}, {
id: 'ease-out-sine', name: "easeOutSine"
}, {
id: 'ease-in-out-sine', name: "easeInOutSine"
}, {
id: 'ease-in-expo', name: "easeInExpo"
}, {
id: 'ease-out-expo', name: "easeOutExpo"
}, {
id: 'ease-in-out-expo', name: "easeInOutExpo"
}, {
id: 'ease-in-circ', name: "easeInCirc"
}, {
id: 'ease-out-circ', name: "easeOutCirc"
}, {
id: 'ease-in-out-circ', name: "easeInOutCirc"
}, {
id: 'ease-in-back', name: "easeInBack"
}, {
id: 'ease-out-back', name: "easeOutBack"
}, {
id: 'ease-in-out-back', name: "easeInOutBack"
}, {
id: 'ease-in-elastic', name: "easeInElastic"
}, {
id: 'ease-out-elastic', name: "easeOutElastic"
}, {
id: 'ease-in-out-elastic', name: "easeInOutElastic"
}, {
id: 'ease-in-bounce', name: "easeInBounce"
}, {
id: 'ease-out-bounce', name: "easeOutBounce"
}, {
id: 'ease-in-out-bounce', name: "easeInOutBounce"
}, {
id: 'random', name: "Random"
}];
function getBaseString(translatedString) {
switch (translatedString) {
case _("Coverflow"): return "Coverflow";
case _("Timeline"): return "Timeline";
case _("Bottom"): return "Bottom";
case _("Top"): return "Top";
case _("Classic"): return "Classic";
case _("Overlay"): return "Overlay";
default: return translatedString;
}
}
function makeResetButton() {
return new Gtk.Button({
icon_name: "edit-clear-symbolic",
tooltip_text: _("Reset to default value"),
valign: Gtk.Align.CENTER,
});
}
export default class CoverflowAltTabPreferences extends ExtensionPreferences {
constructor(metadata) {
super(metadata);
let IconsPath = GLib.build_filenamev([this.path, 'ui', 'icons']);
let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default());
iconTheme.add_search_path(IconsPath);
}
getVersionString(_page) {
return _('Version %d').format(this.metadata.version);
}
fillPreferencesWindow(window) {
let settings = this.getSettings();
let general_page = new Adw.PreferencesPage({
title: _('General'),
icon_name: 'general-symbolic',
});
let switcher_pref_group = new Adw.PreferencesGroup({
title: _('Switcher'),
});
let switcher_looping_method_buttons = new Map([ [_("Flip Stack"), [[],[]]], [_("Carousel"), [[],[]]]]);
let switcher_looping_method_row = buildRadioAdw(settings, "switcher-looping-method", switcher_looping_method_buttons, _("Looping Method"), _("How to cycle through windows."));
switcher_pref_group.add(buildRadioAdw(settings, "switcher-style", new Map([ [_("Coverflow"), [[switcher_looping_method_row], []]], [_("Timeline"), [[],[switcher_looping_method_row]] ]]), _("Style"), _("Pick the type of switcher.")))
switcher_pref_group.add(buildSpinAdw(settings, "offset", [-500, 500, 1, 10], _("Vertical Offset"), _("Positive value moves everything down, negative up.")));
switcher_pref_group.add(buildRadioAdw(settings, "position", new Map([ [_("Bottom"), [[], []]], [_("Top"), [[],[]]]]), _("Window Title Position"), _("Place window title above or below the switcher.")));
switcher_pref_group.add(buildSwitcherAdw(settings, "enforce-primary-monitor", [], [], _("Enforce Primary Monitor"), _("Always show on the primary monitor, otherwise, show on the active monitor.")));
switcher_pref_group.add(switcher_looping_method_row);
switcher_pref_group.add(buildSwitcherAdw(settings, "hide-panel", [], [], _("Hide Panel"), _("Hide panel when switching windows.")));
switcher_pref_group.add(buildSwitcherAdw(settings, "invert-swipes", [], [], _("Invert Swipes"), _("Swipe content instead of view.")));
let animation_pref_group = new Adw.PreferencesGroup({
title: _('Animation'),
});
animation_pref_group.add(buildDropDownAdw(settings, "easing-function", easing_options, "Easing Function", "Determine how windows move."));
animation_pref_group.add(buildRangeAdw(settings, "animation-time", [0.01, 20, 0.001, [0.5, 1, 1.5]], _("Duration [s]"), "", true));
animation_pref_group.add(buildSwitcherAdw(settings, "randomize-animation-times", [], [], _("Randomize Durations"), _("Each animation duration assigned randomly between 0 and configured duration.")));
let windows_pref_group = new Adw.PreferencesGroup({
title: _('Switcher Windows'),
});
let options = [{
id: 'current', name: _("Current workspace only")
}, {
id: 'all', name: _("All workspaces")
}, {
id: 'all-currentfirst', name: _("All workspaces, current first")
}];
windows_pref_group.add(buildDropDownAdw(settings, "current-workspace-only", options, _("Workspaces"), _("Switch between windows on current or on all workspaces.")));
windows_pref_group.add(buildSwitcherAdw(settings, "switch-per-monitor", [], [], _("Current Monitor"), _("Switch between windows on current monitor.")));
let icon_pref_group = new Adw.PreferencesGroup({
title: _("Icons"),
});
let size_row = buildRangeAdw(settings, "overlay-icon-size", [16, 1024, 1, [32, 64, 128, 256, 512]], _("Overlay Icon Size"), _("Set the overlay icon size in pixels."), true);
let opacity_row = buildRangeAdw(settings, "overlay-icon-opacity", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Overlay Icon Opacity"), _("Set the overlay icon opacity."), true);
let buttons = new Map([[_("Classic"), [[],[size_row, opacity_row]]], [_("Overlay"), [[size_row, opacity_row], []]], [_("Attached"), [[size_row, opacity_row], []]]]);
let style_row = buildRadioAdw(settings, "icon-style", buttons, _("Application Icon Style"));
icon_pref_group.add(style_row);
icon_pref_group.add(size_row);
icon_pref_group.add(opacity_row);
icon_pref_group.add(buildSwitcherAdw(settings, "icon-has-shadow", [], [], _("Icon Shadow")));
let window_size_pref_group = new Adw.PreferencesGroup({
title: _("Window Properties")
});
window_size_pref_group.add(buildRangeAdw(settings, "preview-to-monitor-ratio", [0, 1, 0.001, [0.250, 0.500, 0.750]], _("Window Preview Size to Monitor Size Ratio"), _("Maximum ratio of window preview size to monitor size."), true));
window_size_pref_group.add(buildRangeAdw(settings, "preview-scaling-factor", [0, 1, 0.001, [0.250, 0.500, 0.800]], _("Off-center Size Factor"), _("Factor by which to successively shrink previews off to the side."), true));
let background_application_switcher_pref_group = new Adw.PreferencesGroup({
title: _('Application Switcher'),
});
background_application_switcher_pref_group.add(buildSwitcherAdw(settings, "switch-application-behaves-like-switch-windows", [], [], _("Make the Application Switcher Behave Like the Window Switcher"), _("Don't group windows of the same application in a subswitcher.")));
background_application_switcher_pref_group.add(buildRangeAdw(settings, "desaturate-factor", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Desaturate"), _("Larger means more desaturation."), true));
background_application_switcher_pref_group.add(buildSpinAdw(settings, "blur-radius", [0, 20, 1, 1], _("Blur"), _("Larger means blurrier.")));
let color_row = new Adw.ExpanderRow({
title: _("Tint"),
});
background_application_switcher_pref_group.add(color_row);
let use_tint_switch = new Gtk.Switch({
valign: Gtk.Align.CENTER,
active: settings.get_boolean("use-tint"),
});
settings.bind("use-tint", use_tint_switch, "active", Gio.SettingsBindFlags.DEFAULT);
color_row.add_suffix(use_tint_switch);
let tint_chooser_row = new Adw.ActionRow({
title: _("Color")
});
let choose_tint_box = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
spacing: 10,
valign: Gtk.Align.CENTER,
});
tint_chooser_row.add_suffix(choose_tint_box);
color_row.add_row(tint_chooser_row);
let color_dialog = new Gtk.ColorDialog({
with_alpha: false,
});
let color_button = new Gtk.ColorDialogButton({
valign: Gtk.Align.CENTER,
dialog: color_dialog,
});
let use_theme_color_button = new Gtk.Button({
label: _("Set to Theme Color"),
valign: Gtk.Align.CENTER,
});
use_theme_color_button.connect('clicked', () => {
let c = settings.get_value("switcher-background-color").deep_unpack();
let rgba = color_button.rgba;
rgba.red = c[0];
rgba.green = c[1];
rgba.blue = c[2];
rgba.alpha = 1
color_button.set_rgba(rgba);
});
choose_tint_box.append(use_theme_color_button);
choose_tint_box.append(color_button);
let c = settings.get_value("tint-color").deep_unpack();
let rgba = color_button.rgba;
rgba.red = c[0];
rgba.green = c[1];
rgba.blue = c[2];
rgba.alpha = 1
color_button.set_rgba(rgba);
color_button.connect('notify::rgba', _ => {
let c = color_button.rgba;
let val = new GLib.Variant("(ddd)", [c.red, c.green, c.blue]);
settings.set_value("tint-color", val);
});
use_tint_switch.connect('notify::active', function(widget) {
color_row.set_expanded(widget.get_active());
});
let reset_button = makeResetButton();
reset_button.connect("clicked", function (widget) {
settings.reset("use-tint");
});
color_row.add_suffix(reset_button);
color_row.add_row(buildRangeAdw(settings, "tint-blend", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Blend"), _("How much to blend the tint color; bigger means more tint color."), true));
background_application_switcher_pref_group.add(buildSwitcherAdw(settings, "use-glitch-effect", [], [], _("Glitch")));
let background_pref_group = new Adw.PreferencesGroup({
title: _('Background'),
});
background_pref_group.add(buildRangeAdw(settings, "dim-factor", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Dim-factor"), _("Bigger means darker."), true));
let keybinding_pref_group = new Adw.PreferencesGroup({
title: _("Keybindings"),
});
keybinding_pref_group.add(buildSwitcherAdw(settings, "bind-to-switch-windows", [], [], _("Bind to 'switch-windows'")));
keybinding_pref_group.add(buildSwitcherAdw(settings, "bind-to-switch-applications", [background_application_switcher_pref_group], [], _("Bind to 'switch-applications'")));
let pcorrection_pref_group = new Adw.PreferencesGroup({
title: _("Perspective Correction")
})
pcorrection_pref_group.add(buildDropDownAdw(settings, "perspective-correction-method", [
{ id: "None", name: _("None") },
{ id: "Move Camera", name: _("Move Camera") },
{ id: "Adjust Angles", name: _("Adjust Angles") }],
_("Perspective Correction"), ("Method to make off-center switcher look centered.")));
let highlight_mouse_over_pref_group = new Adw.PreferencesGroup({
title: _("Highlight Window Under Mouse"),
});
window_size_pref_group.add(buildSwitcherAdw(settings, "highlight-mouse-over", [], [], _("Highlight Window Under Mouse"), _("Draw embelishment on window under the mouse to know the effects of clicking.")));
window_size_pref_group.add(buildSwitcherAdw(settings, "raise-mouse-over", [], [], _("Raise Window Under Mouse"), _("Raise the window under the mouse above all others.")));
/*let tweaks_page = new Adw.PreferencesPage({
title: _('Tweaks'),
icon_name: 'applications-symbolic',
});
tweaks_page.add(pcorrection_pref_group);
tweaks_page.add(highlight_mouse_over_pref_group);*/
general_page.add(switcher_pref_group);
general_page.add(animation_pref_group);
general_page.add(icon_pref_group);
general_page.add(windows_pref_group);
general_page.add(window_size_pref_group);
general_page.add(background_pref_group);
general_page.add(background_application_switcher_pref_group);
general_page.add(pcorrection_pref_group);
general_page.add(keybinding_pref_group);
let contribution_page = new Adw.PreferencesPage({
title: _("Contribute"),
icon_name: 'contribute-symbolic',
});
let contribute_icon_pref_group = new Adw.PreferencesGroup();
let icon_box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
margin_top: 24,
margin_bottom: 24,
spacing: 18,
});
let icon_image = new Gtk.Image({
icon_name: "coverflow-symbolic",
pixel_size: 128,
});
let label_box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 6,
});
let label = new Gtk.Label({
label: "Coverflow Alt-Tab",
wrap: true,
});
let context = label.get_style_context();
context.add_class("title-1");
let another_label = new Gtk.Label({
label: this.getVersionString(),
});
let links_pref_group = new Adw.PreferencesGroup();
let code_row = new Adw.ActionRow({
icon_name: "code-symbolic",
title: _("Code (create pull requests, report issues, etc.)")
});
let github_link = new Gtk.LinkButton({
label: "Github",
uri: "https://github.com/dmo60/CoverflowAltTab",
});
let donate_row = new Adw.ActionRow({
title: _("Donate"),
icon_name: "support-symbolic",
})
let donate_link = new Gtk.LinkButton({
label: "Liberapay",
uri: "https://liberapay.com/dsheeler/donate",
});
let donate_link_paypal = new Gtk.LinkButton({
label: "PayPal",
uri: "https://paypal.me/DanielSheeler?country.x=US&locale.x=en_US",
});
let donate_link_github = new Gtk.LinkButton({
label: "Github",
uri: "https://github.com/sponsors/dsheeler",
});
let translate_row = new Adw.ActionRow({
title: _("Translate"),
icon_name: "translate-symbolic",
})
let translate_link = new Gtk.LinkButton({
label: "Weblate",
uri: "https://hosted.weblate.org/engage/coverflow-alt-tab/",
});
code_row.add_suffix(github_link);
code_row.set_activatable_widget(github_link);
translate_row.add_suffix(translate_link);
translate_row.set_activatable_widget(translate_link);
donate_row.add_suffix(donate_link);
donate_row.add_suffix(donate_link_paypal);
donate_row.add_suffix(donate_link_github);
links_pref_group.add(code_row);
links_pref_group.add(translate_row);
links_pref_group.add(donate_row);
label_box.append(label);
label_box.append(another_label);
icon_box.append(icon_image);
icon_box.append(label_box);
contribute_icon_pref_group.add(icon_box);
contribution_page.add(contribute_icon_pref_group);
contribution_page.add(links_pref_group)
window.add(general_page);
// window.add(appearance_page);
window.add(contribution_page);
window.set_search_enabled(true);
}
}
function buildSwitcherAdw(settings, key, dependant_widgets, inverse_dependant_widgets, title, subtitle=null) {
let pref = new Adw.ActionRow({
title: title,
});
if (subtitle != null) {
pref.set_subtitle(subtitle);
}
let switcher = new Gtk.Switch({
valign: Gtk.Align.CENTER,
active: settings.get_boolean(key)
});
switcher.expand = false;
switcher.connect('notify::active', function(widget) {
settings.set_boolean(key, widget.active);
});
pref.set_activatable_widget(switcher);
pref.add_suffix(switcher);
switcher.connect('notify::active', function(widget) {
for (let dep of dependant_widgets) {
dep.set_sensitive(widget.get_active());
}
});
for (let widget of dependant_widgets) {
widget.set_sensitive(switcher.get_active());
}
switcher.connect('notify::active', function(widget) {
for (let inv_dep of inverse_dependant_widgets) {
inv_dep.set_sensitive(!widget.get_active());
}
});
for (let widget of inverse_dependant_widgets) {
widget.set_sensitive(!switcher.get_active());
}
let reset_button = makeResetButton();
reset_button.connect("clicked", function(widget) {
settings.reset(key);
switcher.set_active(settings.get_boolean(key));
})
pref.add_suffix(reset_button);
return pref;
}
function buildRangeAdw(settings, key, values, title, subtitle="", draw_value=false) {
let [min, max, step, defvs] = values;
let pref = new Adw.ActionRow({
title: title, });
if (subtitle !== null && subtitle !== "") {
pref.set_subtitle(subtitle);
}
let range = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, min, max, step);
range.set_value(settings.get_double(key));
if (draw_value) {
range.set_draw_value(true);
range.set_value_pos(Gtk.PositionType.RIGHT)
}
for (let defv of defvs) {
range.add_mark(defv, Gtk.PositionType.BOTTOM, null);
}
range.set_size_request(200, -1);
range.connect('value-changed', function(slider) {
settings.set_double(key, slider.get_value());
});
pref.set_activatable_widget(range);
pref.add_suffix(range)
let reset_button = makeResetButton();
reset_button.connect("clicked", function(widget) {
settings.reset(key);
range.set_value(settings.get_double(key));
});
pref.add_suffix(reset_button);
return pref;
}
function buildRadioAdw(settings, key, buttons, title, subtitle=null) {
let pref = new Adw.ActionRow({
title: title,
});
if (subtitle != null) {
pref.set_subtitle(subtitle);
}
let hbox = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
spacing: 10,
valign: Gtk.Align.CENTER,
});
let radio = new Gtk.ToggleButton();
let radio_for_button = {};
for (let button_name of buttons.keys()) {
radio = new Gtk.ToggleButton({group: radio, label: button_name});
radio_for_button[button_name] = radio;
if (getBaseString(button_name) == settings.get_string(key)) {
radio.set_active(true);
for (let pref_row of buttons.get(button_name)[0]) {
pref_row.set_sensitive(radio_for_button[button_name].get_active());
}
for (let pref_row of buttons.get(button_name)[1]) {
pref_row.set_sensitive(!radio_for_button[button_name].get_active());
}
}
radio.connect('toggled', function(widget) {
if (widget.get_active()) {
settings.set_string(key, getBaseString(widget.get_label()));
}
for (let pref_row of buttons.get(button_name)[0]) {
pref_row.set_sensitive(widget.get_active());
}
for (let pref_row of buttons.get(button_name)[1]) {
pref_row.set_sensitive(!widget.get_active());
}
});
hbox.append(radio);
};
let reset_button = makeResetButton();
reset_button.connect("clicked", function(widget) {
settings.reset(key);
for (let button of buttons.keys()) {
if (getBaseString(button) == settings.get_string(key)) {
radio_for_button[button].set_active(true);
}
}
});
pref.set_activatable_widget(hbox);
pref.add_suffix(hbox);
pref.add_suffix(reset_button);
return pref;
};
function buildSpinAdw(settings, key, values, title, subtitle=null) {
let [min, max, step, page] = values;
let pref = new Adw.ActionRow({
title: title,
});
if (subtitle != null) {
pref.set_subtitle(subtitle);
}
let spin = new Gtk.SpinButton({ valign: Gtk.Align.CENTER });
spin.set_range(min, max);
spin.set_increments(step, page);
spin.set_value(settings.get_int(key));
spin.connect('value-changed', function(widget) {
settings.set_int(key, widget.get_value());
});
pref.set_activatable_widget(spin);
pref.add_suffix(spin);
let reset_button = makeResetButton();
reset_button.connect("clicked", function(widget) {
settings.reset(key);
spin.set_value(settings.get_int(key));
});
pref.add_suffix(reset_button);
return pref;
}
function buildDropDownAdw(settings, key, values, title, subtitle=null) {
let pref = new Adw.ActionRow({
title: title,
});
if (subtitle != null) {
pref.set_subtitle(subtitle);
}
let model = new Gtk.StringList();
let chosen_idx = 0;
for (let i = 0; i < values.length; i++) {
let item = values[i];
model.append(item.name);
if (item.id == settings.get_string(key)) {
chosen_idx = i;
}
}
let chooser = new Gtk.DropDown({
valign: Gtk.Align.CENTER,
model: model,
selected: chosen_idx,
});
chooser.connect('notify::selected-item', function(c) {
let idx = c.get_selected();
settings.set_string(key, values[idx].id);
});
pref.set_activatable_widget(chooser);
pref.add_suffix(chooser);
let reset_button = makeResetButton();
reset_button.connect("clicked", function(widget) {
settings.reset(key);
for (let i = 0; i < values.length; i++) {
let item = values[i];
if (item.id == settings.get_string(key)) {
chooser.set_selected(i);
break;
}
}
});
pref.add_suffix(reset_button);
return pref;
}