1
0
Fork 0
gnome-shell-extensions-extra/extensions/vertical-workspaces/optionsFactory.js
Daniel Baumann 4f2ad4e96b
Merging upstream version 20230205.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-09 23:09:13 +01:00

552 lines
16 KiB
JavaScript

/**
* Vertical Workspaces
* 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();
const Settings = Me.imports.settings;
const shellVersion = Settings.shellVersion;
// gettext
const _ = Settings._;
// libadwaita is available starting with GNOME Shell 42.
let Adw = null;
try { Adw = imports.gi.Adw; } catch (e) {}
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,
/*width_chars: 80,*/
xalign: 0
})
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) {
if (widget._is_switch) {
this._connectSwitch(widget, key, variable);
} else if (widget._is_spinbutton || widget._is_scale) {
this._connectSpinButton(widget, key, variable);
} else if (widget._is_combo_box) {
this._connectComboBox(widget, key, variable, options);
} else if (widget._is_drop_down) {
this._connectDropDown(widget, key, variable, options);
}
}
return item;
}
_connectSwitch(widget, key, variable) {
this._settings.bind(key, widget, 'active', Gio.SettingsBindFlags.DEFAULT);
}
_connectSpinButton(widget, key, variable) {
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]);
if (value === currentValue) {
widget.set_active_iter(iter);
}
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();
if (!success) return;
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 }));
if (id === currentValue) {
widget.set_selected(i);
}
}
const factory = new Gtk.SignalListItemFactory();
factory.connect("setup", (factory, list_item) => {
const label = new Gtk.Label({xalign: 0});
list_item.set_child(label);
});
factory.connect("bind", (factory, list_item) => {
const label = list_item.get_child();
const item = list_item.get_item();
label.set_text(item.text);
});
widget.connect("notify::selected-item", (dropDown) => {
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];
if (id === newId) {
widget.set_selected(i);
}
}
});
widget.set_factory(factory);
}
newSwitch() {
let sw = new Gtk.Switch({
halign: Gtk.Align.END,
valign: Gtk.Align.CENTER,
hexpand: true,
});
sw._is_switch = true;
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);
spinButton._is_spinbutton = true;
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);
comboBox._is_combo_box = true;
return comboBox;
}
newDropDown() {
const dropDown = new Gtk.DropDown({
model: new Gio.ListStore({
item_type: DropDownItem
}),
halign: Gtk.Align.END,
valign: Gtk.Align.CENTER,
hexpand: true,
});
dropDown._is_drop_down = true;
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);
scale._is_scale = true;
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;
}
newResetButton(callback) {
const btn = new Gtk.Button({
halign: Gtk.Align.END,
valign: Gtk.Align.CENTER,
hexpand: true,
css_classes: ['destructive-action'],
icon_name: 'view-refresh-symbolic'
});
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'],
icon_name: 'view-refresh-symbolic'
});
btn.connect('clicked', () => {
const settings = this._settings;
settings.list_keys().forEach(
key => settings.reset(key)
);
});
btn._activatable = false;
return btn;
}
}
var AdwPrefs = class {
constructor(gOptions) {
this._gOptions = gOptions;
}
getFilledWindow(window, pages) {
for (let page of pages) {
const title = page.title;
const icon_name = page.iconName;
const optionList = page.optionList;
window.add(
this._getAdwPage(optionList, {
title,
icon_name
})
);
}
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) {
if (group) {
page.add(group);
}
group = new Adw.PreferencesGroup({
title: option,
hexpand: true,
width_request: 700
});
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,
})
/*for (let i of item) {
box.append(i);*/
grid.attach(option, 0, 0, 1, 1);
if (widget) {
grid.attach(widget, 1, 0, 1, 1);
}
row.set_child(grid);
if (widget._activatable === false) {
row.activatable = false;
} else {
row.activatable_widget = widget;
}
group.add(row);
}
page.add(group);
return page;
}
}
var LegacyPrefs = class {
constructor(gOptions) {
this._gOptions = gOptions;
}
getPrefsWidget(pages) {
const prefsWidget = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL
});
const stack = new Gtk.Stack({
hexpand: true
});
const stackSwitcher = new Gtk.StackSwitcher({
halign: Gtk.Align.CENTER,
hexpand: true
});
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,
visible: true
};
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(
[new Gtk.Label({ label: title}), _newImageFromIconName(iconName, Gtk.IconSize.BUTTON)]
);
}
let stBtn = stackSwitcher.get_first_child ? stackSwitcher.get_first_child() : null;
for (let i = 0; i < pagesBtns.length; i++) {
const box = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL, spacing: 6, visible: true});
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();
}
}
stack.show_all && stack.show_all();
stackSwitcher.show_all && stackSwitcher.show_all();
prefsWidget.append(stack);
prefsWidget.show_all && prefsWidget.show_all();
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,
});
const context = page.get_style_context();
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,
margin_bottom: 4
});
const context = lbl.get_style_context();
context.add_class('heading');
mainBox.append(lbl);
frame = new Gtk.Frame({
margin_bottom: 16
});
frameBox = new Gtk.ListBox({
selection_mode: null
});
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,
hexpand: true
})
grid.attach(option, 0, 0, 5, 1);
if (widget) {
grid.attach(widget, 5, 0, 2, 1);
}
frameBox.append(grid);
}
page.set_child(mainBox);
return page;
}
}
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;
}
set text(text) {
this._text = text;
}
get id() {
return this._id;
}
set id(id) {
this._id = id;
}
}
);