2025-02-09 23:09:13 +01:00
|
|
|
/**
|
2025-02-09 23:13:53 +01:00
|
|
|
* V-Shell (Vertical Workspaces)
|
2025-02-09 23:09:13 +01:00
|
|
|
* optionsFactory.js
|
|
|
|
*
|
|
|
|
* @author GdH <G-dH@github.com>
|
|
|
|
* @copyright 2022 - 2023
|
|
|
|
* @license GPL-3.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const { Gtk, Gio, GObject } = imports.gi;
|
|
|
|
|
|
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
|
|
const Me = ExtensionUtils.getCurrentExtension();
|
2025-02-09 23:13:53 +01:00
|
|
|
const Settings = Me.imports.lib.settings;
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
const shellVersion = Settings.shellVersion;
|
|
|
|
|
|
|
|
// gettext
|
|
|
|
const _ = Settings._;
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
const ProfileNames = [
|
|
|
|
_('GNOME 3'),
|
|
|
|
_('GNOME 40+ - Bottom Hot Edge'),
|
|
|
|
_('Hot Corner Centric - Top Left Hot Corner'),
|
|
|
|
_('Dock Overview - Bottom Hot Edge'),
|
|
|
|
];
|
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
// libadwaita is available starting with GNOME Shell 42.
|
|
|
|
let Adw = null;
|
2025-02-09 23:13:53 +01:00
|
|
|
try {
|
|
|
|
Adw = imports.gi.Adw;
|
|
|
|
} catch (e) {}
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
function _newImageFromIconName(name) {
|
|
|
|
return Gtk.Image.new_from_icon_name(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
var ItemFactory = class ItemFactory {
|
|
|
|
constructor(gOptions) {
|
|
|
|
this._gOptions = gOptions;
|
|
|
|
this._settings = this._gOptions._gsettings;
|
|
|
|
}
|
|
|
|
|
|
|
|
getRowWidget(text, caption, widget, variable, options = []) {
|
|
|
|
let item = [];
|
|
|
|
let label;
|
|
|
|
if (widget) {
|
|
|
|
label = new Gtk.Box({
|
|
|
|
orientation: Gtk.Orientation.VERTICAL,
|
|
|
|
spacing: 4,
|
|
|
|
halign: Gtk.Align.START,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
});
|
|
|
|
const option = new Gtk.Label({
|
|
|
|
halign: Gtk.Align.START,
|
|
|
|
});
|
|
|
|
option.set_text(text);
|
|
|
|
label.append(option);
|
|
|
|
|
|
|
|
if (caption) {
|
|
|
|
const captionLabel = new Gtk.Label({
|
|
|
|
halign: Gtk.Align.START,
|
|
|
|
wrap: true,
|
2025-02-09 23:13:53 +01:00
|
|
|
/* width_chars: 80, */
|
|
|
|
xalign: 0,
|
|
|
|
});
|
2025-02-09 23:09:13 +01:00
|
|
|
const context = captionLabel.get_style_context();
|
|
|
|
context.add_class('dim-label');
|
|
|
|
context.add_class('caption');
|
|
|
|
captionLabel.set_text(caption);
|
|
|
|
label.append(captionLabel);
|
|
|
|
}
|
|
|
|
label._title = text;
|
|
|
|
} else {
|
|
|
|
label = text;
|
|
|
|
}
|
|
|
|
item.push(label);
|
|
|
|
item.push(widget);
|
|
|
|
|
|
|
|
let key;
|
|
|
|
|
|
|
|
if (variable && this._gOptions.options[variable]) {
|
|
|
|
const opt = this._gOptions.options[variable];
|
|
|
|
key = opt[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (widget) {
|
2025-02-09 23:13:53 +01:00
|
|
|
if (widget._isSwitch)
|
2025-02-09 23:09:13 +01:00
|
|
|
this._connectSwitch(widget, key, variable);
|
2025-02-09 23:13:53 +01:00
|
|
|
else if (widget._isSpinButton || widget._isScale)
|
2025-02-09 23:09:13 +01:00
|
|
|
this._connectSpinButton(widget, key, variable);
|
2025-02-09 23:13:53 +01:00
|
|
|
else if (widget._isComboBox)
|
2025-02-09 23:09:13 +01:00
|
|
|
this._connectComboBox(widget, key, variable, options);
|
2025-02-09 23:13:53 +01:00
|
|
|
else if (widget._isDropDown)
|
2025-02-09 23:09:13 +01:00
|
|
|
this._connectDropDown(widget, key, variable, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
_connectSwitch(widget, key /* , variable */) {
|
2025-02-09 23:09:13 +01:00
|
|
|
this._settings.bind(key, widget, 'active', Gio.SettingsBindFlags.DEFAULT);
|
|
|
|
}
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
_connectSpinButton(widget, key /* , variable */) {
|
2025-02-09 23:09:13 +01:00
|
|
|
this._settings.bind(key, widget.adjustment, 'value', Gio.SettingsBindFlags.DEFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
_connectComboBox(widget, key, variable, options) {
|
|
|
|
let model = widget.get_model();
|
|
|
|
widget._comboMap = {};
|
|
|
|
const currentValue = this._gOptions.get(variable);
|
|
|
|
for (const [label, value] of options) {
|
|
|
|
let iter;
|
|
|
|
model.set(iter = model.append(), [0, 1], [label, value]);
|
2025-02-09 23:13:53 +01:00
|
|
|
if (value === currentValue)
|
2025-02-09 23:09:13 +01:00
|
|
|
widget.set_active_iter(iter);
|
2025-02-09 23:13:53 +01:00
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
widget._comboMap[value] = iter;
|
|
|
|
}
|
|
|
|
this._gOptions.connect(`changed::${key}`, () => {
|
|
|
|
widget.set_active_iter(widget._comboMap[this._gOptions.get(variable, true)]);
|
|
|
|
});
|
|
|
|
widget.connect('changed', () => {
|
|
|
|
const [success, iter] = widget.get_active_iter();
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
if (!success)
|
|
|
|
return;
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
this._gOptions.set(variable, model.get_value(iter, 1));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_connectDropDown(widget, key, variable, options) {
|
|
|
|
const model = widget.get_model();
|
|
|
|
const currentValue = this._gOptions.get(variable);
|
|
|
|
for (let i = 0; i < options.length; i++) {
|
|
|
|
const text = options[i][0];
|
|
|
|
const id = options[i][1];
|
|
|
|
model.append(new DropDownItem({ text, id }));
|
2025-02-09 23:13:53 +01:00
|
|
|
if (id === currentValue)
|
2025-02-09 23:09:13 +01:00
|
|
|
widget.set_selected(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
const factory = new Gtk.SignalListItemFactory();
|
2025-02-09 23:13:53 +01:00
|
|
|
factory.connect('setup', (fact, listItem) => {
|
|
|
|
const label = new Gtk.Label({ xalign: 0 });
|
|
|
|
listItem.set_child(label);
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
2025-02-09 23:13:53 +01:00
|
|
|
factory.connect('bind', (fact, listItem) => {
|
|
|
|
const label = listItem.get_child();
|
|
|
|
const item = listItem.get_item();
|
2025-02-09 23:09:13 +01:00
|
|
|
label.set_text(item.text);
|
|
|
|
});
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
widget.connect('notify::selected-item', dropDown => {
|
2025-02-09 23:09:13 +01:00
|
|
|
const item = dropDown.get_selected_item();
|
|
|
|
this._gOptions.set(variable, item.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
this._gOptions.connect(`changed::${key}`, () => {
|
|
|
|
const newId = this._gOptions.get(variable, true);
|
|
|
|
for (let i = 0; i < options.length; i++) {
|
|
|
|
const id = options[i][1];
|
2025-02-09 23:13:53 +01:00
|
|
|
if (id === newId)
|
2025-02-09 23:09:13 +01:00
|
|
|
widget.set_selected(i);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
widget.set_factory(factory);
|
|
|
|
}
|
|
|
|
|
|
|
|
newSwitch() {
|
|
|
|
let sw = new Gtk.Switch({
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
});
|
2025-02-09 23:13:53 +01:00
|
|
|
sw._isSwitch = true;
|
2025-02-09 23:09:13 +01:00
|
|
|
return sw;
|
|
|
|
}
|
|
|
|
|
|
|
|
newSpinButton(adjustment) {
|
|
|
|
let spinButton = new Gtk.SpinButton({
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
vexpand: false,
|
|
|
|
xalign: 0.5,
|
|
|
|
});
|
|
|
|
spinButton.set_adjustment(adjustment);
|
2025-02-09 23:13:53 +01:00
|
|
|
spinButton._isSpinButton = true;
|
2025-02-09 23:09:13 +01:00
|
|
|
return spinButton;
|
|
|
|
}
|
|
|
|
|
|
|
|
newComboBox() {
|
|
|
|
const model = new Gtk.ListStore();
|
|
|
|
model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT]);
|
|
|
|
const comboBox = new Gtk.ComboBox({
|
|
|
|
model,
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
});
|
|
|
|
const renderer = new Gtk.CellRendererText();
|
|
|
|
comboBox.pack_start(renderer, true);
|
|
|
|
comboBox.add_attribute(renderer, 'text', 0);
|
2025-02-09 23:13:53 +01:00
|
|
|
comboBox._isComboBox = true;
|
2025-02-09 23:09:13 +01:00
|
|
|
return comboBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
newDropDown() {
|
|
|
|
const dropDown = new Gtk.DropDown({
|
|
|
|
model: new Gio.ListStore({
|
2025-02-09 23:13:53 +01:00
|
|
|
item_type: DropDownItem,
|
2025-02-09 23:09:13 +01:00
|
|
|
}),
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
});
|
2025-02-09 23:13:53 +01:00
|
|
|
dropDown._isDropDown = true;
|
2025-02-09 23:09:13 +01:00
|
|
|
return dropDown;
|
|
|
|
}
|
|
|
|
|
|
|
|
newScale(adjustment) {
|
|
|
|
const scale = new Gtk.Scale({
|
|
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
|
|
draw_value: true,
|
|
|
|
has_origin: false,
|
|
|
|
value_pos: Gtk.PositionType.LEFT,
|
|
|
|
digits: 0,
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
vexpand: false,
|
|
|
|
});
|
|
|
|
scale.set_size_request(300, -1);
|
|
|
|
scale.set_adjustment(adjustment);
|
2025-02-09 23:13:53 +01:00
|
|
|
scale._isScale = true;
|
2025-02-09 23:09:13 +01:00
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
newLabel(text = '') {
|
|
|
|
const label = new Gtk.Label({
|
|
|
|
label: text,
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
});
|
|
|
|
label._activatable = false;
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
|
|
|
|
newLinkButton(uri) {
|
|
|
|
const linkBtn = new Gtk.LinkButton({
|
|
|
|
label: shellVersion < 42 ? 'Click Me!' : '',
|
|
|
|
uri,
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
});
|
|
|
|
return linkBtn;
|
|
|
|
}
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
newButton() {
|
2025-02-09 23:09:13 +01:00
|
|
|
const btn = new Gtk.Button({
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
2025-02-09 23:13:53 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
btn._activatable = true;
|
|
|
|
return btn;
|
|
|
|
}
|
|
|
|
|
|
|
|
newPresetButton(opt, profileIndex) {
|
|
|
|
const load = opt.loadProfile.bind(opt);
|
|
|
|
const save = opt.storeProfile.bind(opt);
|
|
|
|
const reset = opt.resetProfile.bind(opt);
|
|
|
|
|
|
|
|
const box = new Gtk.Box({
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
spacing: 8,
|
|
|
|
});
|
|
|
|
box.is_profile_box = true;
|
|
|
|
|
|
|
|
const entry = new Gtk.Entry({
|
|
|
|
width_chars: 40,
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
xalign: 0,
|
|
|
|
});
|
|
|
|
entry.set_text(opt.get(`profileName${profileIndex}`));
|
|
|
|
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'edit-clear-symbolic');
|
|
|
|
entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, true);
|
|
|
|
entry.connect('icon-press', e => e.set_text(''));
|
|
|
|
entry.connect('changed', e => opt.set(`profileName${profileIndex}`, e.get_text()));
|
|
|
|
|
|
|
|
const resetProfile = this.newButton();
|
|
|
|
resetProfile.set({
|
|
|
|
tooltip_text: _('Reset profile to defaults'),
|
|
|
|
icon_name: 'edit-delete-symbolic',
|
|
|
|
hexpand: false,
|
2025-02-09 23:09:13 +01:00
|
|
|
css_classes: ['destructive-action'],
|
2025-02-09 23:13:53 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
function setName() {
|
|
|
|
let name = opt.get(`profileName${profileIndex}`, true);
|
|
|
|
if (!name)
|
|
|
|
name = ProfileNames[profileIndex - 1];
|
|
|
|
entry.set_text(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
setName();
|
|
|
|
resetProfile.connect('clicked', () => {
|
|
|
|
reset(profileIndex);
|
|
|
|
setName();
|
|
|
|
});
|
|
|
|
resetProfile._activatable = false;
|
|
|
|
|
|
|
|
const loadProfile = this.newButton();
|
|
|
|
loadProfile.set({
|
|
|
|
tooltip_text: _('Load profile'),
|
|
|
|
icon_name: 'view-refresh-symbolic',
|
|
|
|
hexpand: false,
|
|
|
|
});
|
|
|
|
loadProfile.connect('clicked', () => load(profileIndex));
|
|
|
|
loadProfile._activatable = false;
|
|
|
|
|
|
|
|
const saveProfile = this.newButton();
|
|
|
|
saveProfile.set({
|
|
|
|
tooltip_text: _('Save current settings into this profile'),
|
|
|
|
icon_name: 'document-save-symbolic',
|
|
|
|
hexpand: false,
|
|
|
|
});
|
|
|
|
saveProfile.connect('clicked', () => save(profileIndex));
|
|
|
|
saveProfile._activatable = false;
|
|
|
|
|
|
|
|
box.append(resetProfile);
|
|
|
|
box.append(entry);
|
|
|
|
box.append(saveProfile);
|
|
|
|
box.append(loadProfile);
|
|
|
|
return box;
|
|
|
|
}
|
|
|
|
|
|
|
|
newResetButton(callback) {
|
|
|
|
const btn = this.newButton();
|
|
|
|
btn.set({
|
|
|
|
css_classes: ['destructive-action'],
|
|
|
|
icon_name: 'edit-delete-symbolic',
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
btn.connect('clicked', callback);
|
|
|
|
btn._activatable = false;
|
|
|
|
return btn;
|
|
|
|
}
|
|
|
|
|
|
|
|
newOptionsResetButton() {
|
|
|
|
const btn = new Gtk.Button({
|
|
|
|
halign: Gtk.Align.END,
|
|
|
|
valign: Gtk.Align.CENTER,
|
|
|
|
hexpand: true,
|
|
|
|
css_classes: ['destructive-action'],
|
2025-02-09 23:13:53 +01:00
|
|
|
icon_name: 'edit-delete-symbolic',
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
btn.connect('clicked', () => {
|
|
|
|
const settings = this._settings;
|
|
|
|
settings.list_keys().forEach(
|
|
|
|
key => settings.reset(key)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
btn._activatable = false;
|
|
|
|
return btn;
|
|
|
|
}
|
2025-02-09 23:13:53 +01:00
|
|
|
};
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
var AdwPrefs = class {
|
|
|
|
constructor(gOptions) {
|
|
|
|
this._gOptions = gOptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
getFilledWindow(window, pages) {
|
|
|
|
for (let page of pages) {
|
|
|
|
const title = page.title;
|
2025-02-09 23:13:53 +01:00
|
|
|
const iconName = page.iconName;
|
2025-02-09 23:09:13 +01:00
|
|
|
const optionList = page.optionList;
|
|
|
|
|
|
|
|
window.add(
|
|
|
|
this._getAdwPage(optionList, {
|
|
|
|
title,
|
2025-02-09 23:13:53 +01:00
|
|
|
icon_name: iconName,
|
2025-02-09 23:09:13 +01:00
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
window.set_search_enabled(true);
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
|
|
|
_getAdwPage(optionList, pageProperties = {}) {
|
|
|
|
pageProperties.width_request = 840;
|
|
|
|
const page = new Adw.PreferencesPage(pageProperties);
|
|
|
|
let group;
|
|
|
|
for (let item of optionList) {
|
|
|
|
// label can be plain text for Section Title
|
|
|
|
// or GtkBox for Option
|
|
|
|
const option = item[0];
|
|
|
|
const widget = item[1];
|
|
|
|
if (!widget) {
|
2025-02-09 23:13:53 +01:00
|
|
|
if (group)
|
2025-02-09 23:09:13 +01:00
|
|
|
page.add(group);
|
2025-02-09 23:13:53 +01:00
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
group = new Adw.PreferencesGroup({
|
|
|
|
title: option,
|
|
|
|
hexpand: true,
|
2025-02-09 23:13:53 +01:00
|
|
|
width_request: 700,
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const row = new Adw.ActionRow({
|
|
|
|
title: option._title,
|
|
|
|
});
|
|
|
|
|
|
|
|
const grid = new Gtk.Grid({
|
|
|
|
column_homogeneous: false,
|
|
|
|
column_spacing: 20,
|
|
|
|
margin_start: 8,
|
|
|
|
margin_end: 8,
|
|
|
|
margin_top: 8,
|
|
|
|
margin_bottom: 8,
|
|
|
|
hexpand: true,
|
2025-02-09 23:13:53 +01:00
|
|
|
});
|
|
|
|
/* for (let i of item) {
|
2025-02-09 23:09:13 +01:00
|
|
|
box.append(i);*/
|
|
|
|
grid.attach(option, 0, 0, 1, 1);
|
2025-02-09 23:13:53 +01:00
|
|
|
if (widget)
|
2025-02-09 23:09:13 +01:00
|
|
|
grid.attach(widget, 1, 0, 1, 1);
|
2025-02-09 23:13:53 +01:00
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
row.set_child(grid);
|
2025-02-09 23:13:53 +01:00
|
|
|
if (widget._activatable === false)
|
2025-02-09 23:09:13 +01:00
|
|
|
row.activatable = false;
|
2025-02-09 23:13:53 +01:00
|
|
|
else
|
2025-02-09 23:09:13 +01:00
|
|
|
row.activatable_widget = widget;
|
2025-02-09 23:13:53 +01:00
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
group.add(row);
|
|
|
|
}
|
|
|
|
page.add(group);
|
|
|
|
return page;
|
|
|
|
}
|
2025-02-09 23:13:53 +01:00
|
|
|
};
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
var LegacyPrefs = class {
|
|
|
|
constructor(gOptions) {
|
|
|
|
this._gOptions = gOptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
getPrefsWidget(pages) {
|
|
|
|
const prefsWidget = new Gtk.Box({
|
2025-02-09 23:13:53 +01:00
|
|
|
orientation: Gtk.Orientation.VERTICAL,
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
const stack = new Gtk.Stack({
|
2025-02-09 23:13:53 +01:00
|
|
|
hexpand: true,
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
const stackSwitcher = new Gtk.StackSwitcher({
|
|
|
|
halign: Gtk.Align.CENTER,
|
2025-02-09 23:13:53 +01:00
|
|
|
hexpand: true,
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
const context = stackSwitcher.get_style_context();
|
|
|
|
context.add_class('caption');
|
|
|
|
|
|
|
|
stackSwitcher.set_stack(stack);
|
|
|
|
stack.set_transition_duration(300);
|
|
|
|
stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT);
|
|
|
|
|
|
|
|
const pageProperties = {
|
|
|
|
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
|
|
|
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
|
|
|
vexpand: true,
|
|
|
|
hexpand: true,
|
2025-02-09 23:13:53 +01:00
|
|
|
visible: true,
|
2025-02-09 23:09:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const pagesBtns = [];
|
|
|
|
|
|
|
|
for (let page of pages) {
|
|
|
|
const name = page.name;
|
|
|
|
const title = page.title;
|
|
|
|
const iconName = page.iconName;
|
|
|
|
const optionList = page.optionList;
|
|
|
|
|
|
|
|
stack.add_named(this._getLegacyPage(optionList, pageProperties), name);
|
|
|
|
pagesBtns.push(
|
2025-02-09 23:13:53 +01:00
|
|
|
[new Gtk.Label({ label: title }), _newImageFromIconName(iconName, Gtk.IconSize.BUTTON)]
|
2025-02-09 23:09:13 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let stBtn = stackSwitcher.get_first_child ? stackSwitcher.get_first_child() : null;
|
|
|
|
for (let i = 0; i < pagesBtns.length; i++) {
|
2025-02-09 23:13:53 +01:00
|
|
|
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 6, visible: true });
|
2025-02-09 23:09:13 +01:00
|
|
|
const icon = pagesBtns[i][1];
|
|
|
|
icon.margin_start = 30;
|
|
|
|
icon.margin_end = 30;
|
|
|
|
box.append(icon);
|
|
|
|
box.append(pagesBtns[i][0]);
|
|
|
|
if (stackSwitcher.get_children) {
|
|
|
|
stBtn = stackSwitcher.get_children()[i];
|
|
|
|
stBtn.add(box);
|
|
|
|
} else {
|
|
|
|
stBtn.set_child(box);
|
|
|
|
stBtn.visible = true;
|
|
|
|
stBtn = stBtn.get_next_sibling();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
if (stack.show_all)
|
|
|
|
stack.show_all();
|
|
|
|
if (stackSwitcher.show_all)
|
|
|
|
stackSwitcher.show_all();
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
prefsWidget.append(stack);
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
if (prefsWidget.show_all)
|
|
|
|
prefsWidget.show_all();
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
prefsWidget._stackSwitcher = stackSwitcher;
|
|
|
|
|
|
|
|
return prefsWidget;
|
|
|
|
}
|
|
|
|
|
|
|
|
_getLegacyPage(optionList, pageProperties) {
|
|
|
|
const page = new Gtk.ScrolledWindow(pageProperties);
|
|
|
|
const mainBox = new Gtk.Box({
|
|
|
|
orientation: Gtk.Orientation.VERTICAL,
|
|
|
|
spacing: 5,
|
|
|
|
homogeneous: false,
|
|
|
|
margin_start: 30,
|
|
|
|
margin_end: 30,
|
|
|
|
margin_top: 12,
|
|
|
|
margin_bottom: 12,
|
|
|
|
});
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
let context = page.get_style_context();
|
2025-02-09 23:09:13 +01:00
|
|
|
context.add_class('background');
|
|
|
|
|
|
|
|
let frame;
|
|
|
|
let frameBox;
|
|
|
|
for (let item of optionList) {
|
|
|
|
// label can be plain text for Section Title
|
|
|
|
// or GtkBox for Option
|
|
|
|
const option = item[0];
|
|
|
|
const widget = item[1];
|
|
|
|
|
|
|
|
if (!widget) {
|
|
|
|
const lbl = new Gtk.Label({
|
|
|
|
label: option,
|
|
|
|
xalign: 0,
|
2025-02-09 23:13:53 +01:00
|
|
|
margin_bottom: 4,
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
context = lbl.get_style_context();
|
2025-02-09 23:09:13 +01:00
|
|
|
context.add_class('heading');
|
|
|
|
|
|
|
|
mainBox.append(lbl);
|
|
|
|
|
|
|
|
frame = new Gtk.Frame({
|
2025-02-09 23:13:53 +01:00
|
|
|
margin_bottom: 16,
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
frameBox = new Gtk.ListBox({
|
2025-02-09 23:13:53 +01:00
|
|
|
selection_mode: null,
|
2025-02-09 23:09:13 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
mainBox.append(frame);
|
|
|
|
frame.set_child(frameBox);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const grid = new Gtk.Grid({
|
|
|
|
column_homogeneous: false,
|
|
|
|
column_spacing: 20,
|
|
|
|
margin_start: 8,
|
|
|
|
margin_end: 8,
|
|
|
|
margin_top: 8,
|
|
|
|
margin_bottom: 8,
|
2025-02-09 23:13:53 +01:00
|
|
|
hexpand: true,
|
|
|
|
});
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
grid.attach(option, 0, 0, 5, 1);
|
|
|
|
|
2025-02-09 23:13:53 +01:00
|
|
|
if (widget)
|
2025-02-09 23:09:13 +01:00
|
|
|
grid.attach(widget, 5, 0, 2, 1);
|
2025-02-09 23:13:53 +01:00
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
frameBox.append(grid);
|
|
|
|
}
|
|
|
|
page.set_child(mainBox);
|
|
|
|
|
|
|
|
return page;
|
|
|
|
}
|
2025-02-09 23:13:53 +01:00
|
|
|
};
|
2025-02-09 23:09:13 +01:00
|
|
|
|
|
|
|
const DropDownItem = GObject.registerClass({
|
|
|
|
GTypeName: 'DropdownItem',
|
|
|
|
Properties: {
|
|
|
|
'text': GObject.ParamSpec.string(
|
|
|
|
'text',
|
|
|
|
'Text',
|
|
|
|
'DropDown item text',
|
|
|
|
GObject.ParamFlags.READWRITE,
|
|
|
|
''
|
|
|
|
),
|
|
|
|
'id': GObject.ParamSpec.int(
|
|
|
|
'id',
|
|
|
|
'Id',
|
|
|
|
'Item id stored in settings',
|
|
|
|
GObject.ParamFlags.READWRITE,
|
|
|
|
0, 100, 0
|
|
|
|
),
|
|
|
|
},
|
|
|
|
}, class DropDownItem extends GObject.Object {
|
|
|
|
get text() {
|
|
|
|
return this._text;
|
|
|
|
}
|
2025-02-09 23:13:53 +01:00
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
set text(text) {
|
|
|
|
this._text = text;
|
|
|
|
}
|
|
|
|
|
|
|
|
get id() {
|
|
|
|
return this._id;
|
|
|
|
}
|
2025-02-09 23:13:53 +01:00
|
|
|
|
2025-02-09 23:09:13 +01:00
|
|
|
set id(id) {
|
|
|
|
this._id = id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|