Files

229 lines
9.5 KiB
JavaScript

/*
* Copyright 2019 Abakkk
* Copyright 2024 Dave Prowse
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-FileCopyrightText: 2019 Abakkk
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileContributor: Modified by Dave Prowse
*/
/* jslint esversion: 6 (2019) */
/* eslint version: 9.16 (2024) */
/* exported DrawingHelper */
import Clutter from 'gi://Clutter';
import St from 'gi://St';
import GObject from 'gi://GObject';
import * as Shortcuts from './shortcuts.js';
import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js';
import { CURATED_UUID as UUID } from './utils.js';
import { SHELL_MAJOR_VERSION } from './utils.js';
import GLib from 'gi://GLib';
const HELPER_ANIMATION_TIME = 0.25;
// DrawingHelper provides the "help osd" (Ctrl + F1)
// It uses the same texts as in prefs
//TODO: Review this class later
export const DrawingHelper = GObject.registerClass({
GTypeName: `${UUID}-DrawingHelper`,
}, class DrawingHelper extends St.ScrollView {
_init(extension, params, monitor) {
params.style_class = 'osd-window draw-on-gnome-helper';
super._init(params);
this._extension = extension;
this.monitor = monitor;
this.hide();
this.settingsHandler = this._extension.settings.connect('changed', this._onSettingsChanged.bind(this));
this.internalShortcutsettingsHandler = this._extension.internalShortcutSettings.connect('changed', this._onSettingsChanged.bind(this));
this.connect('destroy', () => {
this._extension.settings.disconnect(this.settingsHandler);
this._extension.internalShortcutSettings.disconnect(this.internalShortcutsettingsHandler);
});
}
_onSettingsChanged(settings, key) {
if (key == 'toggle-help')
this._updateHelpKeyLabel();
if (this.vbox) {
this.vbox.destroy();
delete this.vbox;
}
}
_updateHelpKeyLabel() {
try {
this._helpKeyLabel = this._extension.internalShortcutSettings.get_strv('toggle-help')[0];
} catch(e) {
logError(e);
this._helpKeyLabel = " ";
}
}
get helpKeyLabel() {
if (!this._helpKeyLabel)
this._updateHelpKeyLabel();
return GLib.markup_escape_text(this._helpKeyLabel, -1);
}
_populate() {
this.vbox = new St.BoxLayout({ vertical: true });
this.add_child(this.vbox);
this.vbox.add_child(new St.Label({ text: _("Global") }));
Shortcuts.GLOBAL_KEYBINDINGS.forEach((settingKeys) => {
this.vbox.add_child(new St.BoxLayout({ vertical: false, style_class: 'draw-on-gnome-helper-separator' }));
if (!this._extension.settings.get_strv(settingKeys)[0])
return;
let hbox = new St.BoxLayout({ vertical: false });
let shortcut = this._extension.settings.get_strv(settingKeys)[0];
// Convert modifier keys
shortcut = shortcut.replace(/<Primary>/g, 'Ctrl+')
.replace(/<Shift>/g, 'Shift+')
.replace(/<Alt>/g, 'Alt+')
.replace(/<Super>/g, 'Super+')
// Remove KP_ prefix (numpad keys)
.replace(/KP_/g, '')
// Convert symbol names to actual symbols
.replace(/equal/g, '=')
.replace(/Multiply/g, '*')
.replace(/Divide/g, '/')
.replace(/Add/g, '+')
.replace(/Subtract/g, '-')
.replace(/period/g, '.')
.replace(/comma/g, ',')
.replace(/slash/g, '/')
.replace(/minus/g, '-')
.replace(/plus/g, '+')
.replace(/asterisk/g, '*')
// Uppercase single letters after + or at start
.replace(/\+([a-z])$/g, (match, letter) => '+' + letter.toUpperCase())
.replace(/^([a-z])$/g, (match, letter) => letter.toUpperCase());
shortcut = GLib.markup_escape_text(shortcut, -1);
hbox.add_child(new St.Label({ text: this._extension.settings.settings_schema.get_key(settingKeys).get_summary() }));
let label = new St.Label({ text: "<b><i>" + shortcut + "</i></b>", x_expand: true })
label.get_clutter_text().set_use_markup(true);
hbox.add_child(label);
this.vbox.add_child(hbox);
});
this.vbox.add_child(new St.BoxLayout({ vertical: false, style_class: 'draw-on-gnome-helper-separator' }));
this.vbox.add_child(new St.Label({ text: _("Internal") }));
// Shortcuts.OTHERS.forEach((pairs, index) => {
// if (index)
// this.vbox.add_child(new St.BoxLayout({ vertical: false, style_class: 'draw-on-gnome-helper-separator' }));
// pairs.forEach(pair => {
// let [action, shortcut] = pair;
// let hbox = new St.BoxLayout({ vertical: false });
// hbox.add_child(new St.Label({ text: action }));
// hbox.add_child(new St.Label({ text: shortcut, x_expand: true }).get_clutter_text().set_use_markup(true));
// hbox.get_children()[0]);
// this.vbox.add_child(hbox);
// });
// });
// this.vbox.add_child(new St.BoxLayout({ vertical: false, style_class: 'draw-on-gnome-helper-separator' }));
Shortcuts.INTERNAL_KEYBINDINGS.forEach((settingKeys) => {
this.vbox.add_child(new St.BoxLayout({ vertical: false, style_class: 'draw-on-gnome-helper-separator' }));
if (!this._extension.internalShortcutSettings.get_strv(settingKeys)[0])
return;
let hbox = new St.BoxLayout({ vertical: false });
let shortcut = this._extension.internalShortcutSettings.get_strv(settingKeys)[0];
// Convert modifier keys
shortcut = shortcut.replace(/<Primary>/g, 'Ctrl+')
.replace(/<Shift>/g, 'Shift+')
.replace(/<Alt>/g, 'Alt+')
.replace(/<Super>/g, 'Super+')
// Remove KP_ prefix (numpad keys)
.replace(/KP_/g, '')
// Convert symbol names to actual symbols
.replace(/equal/g, '=')
.replace(/Multiply/g, '*')
.replace(/Divide/g, '/')
.replace(/Add/g, '+')
.replace(/Subtract/g, '-')
.replace(/period/g, '.')
.replace(/comma/g, ',')
.replace(/slash/g, '/')
.replace(/minus/g, '-')
.replace(/plus/g, '+')
.replace(/asterisk/g, '*')
// Uppercase single letters after + or at start
.replace(/\+([a-z])$/g, (match, letter) => '+' + letter.toUpperCase())
.replace(/^([a-z])$/g, (match, letter) => letter.toUpperCase());
shortcut = GLib.markup_escape_text(shortcut, -1);
hbox.add_child(new St.Label({ text: this._extension.internalShortcutSettings.settings_schema.get_key(settingKeys).get_summary() }));
let label = new St.Label({ text: "<b><i>" + shortcut + "</i></b>", x_expand: true })
label.get_clutter_text().set_use_markup(true);
hbox.add_child(label);
this.vbox.add_child(hbox);
});
}
showHelp() {
if (!this.vbox)
this._populate();
this.opacity = 0;
this.show();
let maxHeight = this.monitor.height * 3 / 4;
this.set_height(Math.min(this.height, maxHeight));
this.set_position(Math.floor(this.monitor.width / 2 - this.width / 2),
Math.floor(this.monitor.height / 2 - this.height / 2));
// St.PolicyType: GS 3.32+
if (this.height == maxHeight)
this.vscrollbar_policy = St.PolicyType ? St.PolicyType.ALWAYS : 1;
else
this.vscrollbar_policy = St.PolicyType ? St.PolicyType.NEVER : 0;
this.remove_all_transitions();
this.ease({
opacity: 255,
duration: HELPER_ANIMATION_TIME * 1000,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
hideHelp() {
this.remove_all_transitions();
this.ease({
opacity: 0,
duration: HELPER_ANIMATION_TIME * 1000,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.hide()
});
}
});