gnome-shell-extension-dash-.../gnome-shell-extension-just-perfection/usr/share/gnome-shell/extensions/just-perfection-desktop@just-perfection/lib/Prefs/Prefs.js

411 lines
10 KiB
JavaScript
Raw Normal View History

2024-08-27 20:32:05 +02:00
/**
* Prefs Library
*
* @author Javad Rahmatzadeh <j.rahmatzadeh@gmail.com>
* @copyright 2020-2024
* @license GPL-3.0-only
*/
/**
* prefs widget for showing prefs window
*/
export class Prefs
{
/**
* Current shell version
*
* @type {number|null}
*/
#shellVersion = null;
/**
* Instance of PrefsKeys
*
* @type {PrefsKeys|null}
*/
#prefsKeys = null;
/**
* Instance of Gtk.Builder
*
* @type {Gtk.Builder|null}
*/
#builder = null;
/**
* Instance of Gio.Settings
*
* @type {Settings|null}
*/
#settings = null;
/**
* Instance of Resource
*
* @type {Gio.Resource|null}
*/
#resource = null;
/**
* Instance of Gdk
*
* @type {Gdk|null}
*/
#gdk = null;
/**
* Instance of Gio
*
* @type {Gio|null}
*/
#gio = null;
/**
* All available profile names
*
* @type {Array}
*/
#profiles = [
'default',
'minimal',
'superminimal',
];
/**
* class constructor
*
* @param {Object} dependencies
* 'Builder' instance of Gtk::Builder
* 'Settings' instance of Gio::Settings
* 'Gdk' reference to Gdk
* 'Gio' reference to Gio
* @param {PrefsKeys.PrefsKeys} prefsKeys instance of PrefsKeys
* @param {number} shellVersion float in major.minor format
*/
constructor(dependencies, prefsKeys, shellVersion)
{
this.#settings = dependencies['Settings'] || null;
this.#builder = dependencies['Builder'] || null;
this.#gdk = dependencies['Gdk'] || null;
this.#gio = dependencies['Gio'] || null;
this.#prefsKeys = prefsKeys;
this.#shellVersion = shellVersion;
}
/**
* fill prefs window
*
* @param {Adw.PreferencesWindow} window prefs dialog
* @param {string} ResourcesFolderPath folder path to resources folder
* @param {string} gettextDomain gettext domain
*
* @returns {void}
*/
fillPrefsWindow(window, ResourcesFolderPath, gettextDomain)
{
// changing the order here can change the elements order in ui
let uiFilenames = [
'profile',
'visibility',
'icons',
'behavior',
'customize',
];
this.#loadResource(ResourcesFolderPath);
this.#builder.set_translation_domain(gettextDomain);
for (let uiFilename of uiFilenames) {
this.#builder.add_from_resource(
`/org/gnome/Shell/Extensions/justperfection/ui/${uiFilename}.ui`
);
}
for (let uiFilename of uiFilenames) {
let page = this.#builder.get_object(uiFilename);
window.add(page);
}
this.#setValues();
this.#guessProfile();
this.#onlyShowSupportedRows();
this.#registerAllSignals(window);
this.#setWindowSize(window);
window.search_enabled = true;
}
/**
* load resource
*
* @param {string} folder path to the resources folder
*
* @returns {void}
*/
#loadResource(path)
{
this.#resource = this.#gio.Resource.load(`${path}/resources.gresource`);
this.#gio.resources_register(this.#resource);
}
/**
* set window size
*
* @param {Adw.PreferencesWindow} window prefs window
*
* @returns {void}
*/
#setWindowSize(window)
{
let [pmWidth, pmHeight, pmScale] = this.#getPrimaryMonitorInfo();
let sizeTolerance = 50;
let width = 600;
let height = 730;
if (
(pmWidth / pmScale) - sizeTolerance >= width &&
(pmHeight / pmScale) - sizeTolerance >= height
) {
window.set_default_size(width, height);
}
}
/**
* get primary monitor info
*
* @returns {Array} [width, height, scale]
*/
#getPrimaryMonitorInfo()
{
let display = this.#gdk.Display.get_default();
let pm = display.get_monitors().get_item(0);
if (!pm) {
return [700, 500, 1];
}
let geo = pm.get_geometry();
let scale = pm.get_scale_factor();
return [geo.width, geo.height, scale];
}
/**
* register all signals
*
* @param {Adw.PreferencesWindow} window prefs dialog
*
* @returns {void}
*/
#registerAllSignals(window)
{
this.#registerKeySignals();
this.#registerProfileSignals();
this.#registerCloseSignal(window);
}
/**
* register close signal
*
* @param {Adw.PreferencesWindow} window prefs dialog
*
* @returns {void}
*/
#registerCloseSignal(window)
{
window.connect('close-request', () => {
if (this.#resource) {
this.#gio.resources_unregister(this.#resource);
}
});
}
/**
* register signals of all prefs keys
*
* @returns {void}
*/
#registerKeySignals()
{
// all available keys
for (let [, key] of Object.entries(this.#prefsKeys.keys)) {
switch (key.widgetType) {
case 'GtkSwitch':
this.#builder.get_object(key.widgetId).connect('state-set', (w) => {
this.#settings.set_boolean(key.name, w.get_active());
this.#guessProfile();
});
break;
case 'AdwActionRow':
this.#builder.get_object(key.widgetId).connect('notify::selected-item', (w) => {
let index = w.get_selected();
let value = (index in key.maps) ? key.maps[index] : index;
this.#settings.set_int(key.name, value);
this.#guessProfile();
});
break;
case 'AdwSpinRow':
this.#builder.get_object(key.widgetId).connect('notify::value', (w) => {
let value = w.get_value();
this.#settings.set_int(key.name, value);
this.#guessProfile();
});
break;
}
}
}
/**
* register profile signals
*
* @returns {void}
*/
#registerProfileSignals()
{
for (let profile of this.#profiles) {
let widget = this.#builder.get_object(`profile_${profile}`);
if (!widget) {
break;
}
widget.connect('clicked', (w) => {
this.#setValues(profile);
});
}
}
/**
* can check all current values and guess the profile based on the values
*
* @returns {void}
*/
#guessProfile()
{
let totalCount = 0;
let matchCount = {};
for (let profile of this.#profiles) {
matchCount[profile] = 0;
}
for (let [, key] of Object.entries(this.#prefsKeys.keys)) {
if (!key.supported) {
continue;
}
let value;
switch (key.widgetType) {
case 'GtkSwitch':
value = this.#builder.get_object(key.widgetId).get_active();
break;
case 'AdwActionRow':
value = this.#builder.get_object(key.widgetId).get_selected();
break;
case 'AdwSpinRow':
value = this.#builder.get_object(key.widgetId).get_value();
break;
default:
value = '';
continue;
}
for (let profile of this.#profiles) {
if (key.profiles[profile] === value) {
matchCount[profile]++;
}
}
totalCount++;
}
let currentProfile = 'custom';
for (let profile of this.#profiles) {
if (matchCount[profile] === totalCount) {
currentProfile = profile;
break;
}
}
let widget = this.#builder.get_object(`profile_${currentProfile}`);
if (widget) {
widget.set_active(true);
}
}
/**
* set values for all elements
*
* @param {string} profile profile name or null for get it from gsettings
*
* @returns {void}
*/
#setValues(profile)
{
for (let [, key] of Object.entries(this.#prefsKeys.keys)) {
let widget = this.#builder.get_object(key.widgetId);
let value;
switch (key.widgetType) {
case 'GtkSwitch':
value
= (profile)
? key.profiles[profile]
: this.#settings.get_boolean(key.name);
widget.set_active(value);
break;
case 'AdwActionRow':
let index
= (profile)
? key.profiles[profile]
: this.#settings.get_int(key.name);
for (let k in key.maps) {
if (key.maps[k] === index) {
index = k;
break;
}
}
widget.set_selected(index);
break;
case 'AdwSpinRow':
value
= (profile)
? key.profiles[profile]
: this.#settings.get_int(key.name);
widget.set_value(value);
break;
}
}
}
/**
* apply all supported keys to the elements
*
* @returns {void}
*/
#onlyShowSupportedRows()
{
for (let [, key] of Object.entries(this.#prefsKeys.keys)) {
let row = this.#builder.get_object(`${key.id}_row`);
let visible = key.supported;
row.visible = visible;
}
}
};