DrawOnYourScreen/prefs.js

749 lines
36 KiB
JavaScript
Raw Normal View History

2019-03-05 08:36:59 -03:00
/* jslint esversion: 6 */
/* exported GLOBAL_KEYBINDINGS, INTERNAL_KEYBINDINGS, OTHER_SHORTCUTS, init, buildPrefsWidget */
2019-03-05 08:36:59 -03:00
/*
* Copyright 2019 Abakkk
*
* This file is part of DrawOnYourScreen, a drawing extension for GNOME Shell.
2019-03-05 08:36:59 -03:00
* https://framagit.org/abakkk/DrawOnYourScreen
*
* 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 2 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/>.
*/
const Gdk = imports.gi.Gdk;
2020-06-18 20:35:25 -03:00
const GLib = imports.gi.GLib;
2019-03-05 08:36:59 -03:00
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Config = imports.misc.config;
2019-03-05 08:36:59 -03:00
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = ExtensionUtils.getSettings && ExtensionUtils.initTranslations ? ExtensionUtils : Me.imports.convenience;
const gettext = imports.gettext.domain(Me.metadata['gettext-domain']).gettext;
const _ = function(string) {
if (!string)
return "";
return gettext(string);
};
2019-03-28 10:59:14 -03:00
const _GTK = imports.gettext.domain('gtk30').gettext;
2019-03-05 08:36:59 -03:00
const GS_VERSION = Config.PACKAGE_VERSION;
2019-03-05 08:36:59 -03:00
const MARGIN = 10;
var GLOBAL_KEYBINDINGS = {
'toggle-drawing': "Enter/leave drawing mode",
'toggle-modal': "Grab/ungrab keyboard and pointer",
'erase-drawing': "Erase all drawings"
2019-03-05 08:36:59 -03:00
};
var INTERNAL_KEYBINDINGS = {
'undo': "Undo last brushstroke",
'redo': "Redo last brushstroke",
'delete-last-element' : "Erase last brushstroke",
2019-03-05 17:08:43 -03:00
'smooth-last-element': "Smooth last brushstroke",
2019-03-05 08:36:59 -03:00
'-separator-1': '',
'select-none-shape': "Free drawing",
'select-line-shape': "Select line",
'select-ellipse-shape': "Select ellipse",
'select-rectangle-shape': "Select rectangle",
'select-polygon-shape': "Select polygon",
'select-polyline-shape': "Select polyline",
'select-text-shape': "Select text",
'select-image-shape': "Select image",
'select-move-tool': "Select move",
'select-resize-tool': "Select resize",
'select-mirror-tool': "Select mirror",
'-separator-2': '',
2020-08-05 19:04:12 -03:00
'switch-fill': "Toggle fill/outline",
'switch-fill-rule': "Toggle fill rule",
'switch-color-palette': "Change color palette",
'switch-color-palette-reverse': "Change color palette (reverse)",
2020-06-20 06:17:56 -03:00
'-separator-3': '',
2019-03-05 08:36:59 -03:00
'increment-line-width': "Increment line width",
'decrement-line-width': "Decrement line width",
'increment-line-width-more': "Increment line width even more",
'decrement-line-width-more': "Decrement line width even more",
2020-08-05 19:04:12 -03:00
'switch-linejoin': "Change linejoin",
'switch-linecap': "Change linecap",
'switch-dash': "Dashed line",
2020-06-20 06:17:56 -03:00
'-separator-4': '',
2020-08-05 19:26:10 -03:00
'switch-font-family': "Change font family",
'switch-font-family-reverse': "Change font family (reverse)",
2020-08-05 19:04:12 -03:00
'switch-font-weight': "Change font weight",
'switch-font-style': "Change font style",
'switch-text-alignment': "Toggle text alignment",
'switch-image-file': "Change image file",
2020-06-20 06:17:56 -03:00
'-separator-5': '',
2019-03-05 08:36:59 -03:00
'toggle-panel-and-dock-visibility': "Hide panel and dock",
'toggle-background': "Add a drawing background",
2020-06-05 10:58:58 -03:00
'toggle-grid': "Add a grid overlay",
2019-03-07 12:32:06 -03:00
'toggle-square-area': "Square drawing area",
2020-06-20 06:17:56 -03:00
'-separator-6': '',
'open-previous-json': "Open previous drawing",
'open-next-json': "Open next drawing",
'save-as-json': "Save drawing",
2019-03-05 08:36:59 -03:00
'save-as-svg': "Save drawing as a SVG file",
'open-preferences': "Open preferences",
2019-03-05 08:36:59 -03:00
'toggle-help': "Show help"
};
if (GS_VERSION < "3.36")
delete INTERNAL_KEYBINDINGS['open-preferences'];
const getKeyLabel = function(accel) {
let [keyval, mods] = Gtk.accelerator_parse(accel);
return Gtk.accelerator_get_label(keyval, mods);
};
2019-03-05 18:00:14 -03:00
var OTHER_SHORTCUTS = [
{ desc: "Draw", get shortcut() { return _("Left click"); } },
{ desc: "Menu", get shortcut() { return _("Right click"); } },
{ desc: "Toggle fill/outline", get shortcut() { return _("Center click"); } },
{ desc: "Increment/decrement line width", get shortcut() { return _("Scroll"); } },
{ desc: "Select color", get shortcut() { return _("%s … %s").format(getKeyLabel('<Primary>1'), getKeyLabel('<Primary>9')); } },
{ desc: "Ignore pointer movement", get shortcut() { return _("%s held").format(getKeyLabel('space')); } },
2020-06-20 06:17:56 -03:00
{ desc: "Leave", shortcut: getKeyLabel('Escape') },
{ desc: "-separator-1", shortcut: "" },
2020-06-27 11:55:26 -03:00
{ desc: "Select eraser <span alpha=\"50%\">(while starting drawing)</span>", shortcut: getKeyLabel('<Shift>') },
{ desc: "Duplicate <span alpha=\"50%\">(while starting handling)</span>", shortcut: getKeyLabel('<Shift>') },
{ desc: "Rotate rectangle, polygon, polyline", shortcut: getKeyLabel('<Primary>') },
2020-06-20 06:17:56 -03:00
{ desc: "Extend circle to ellipse", shortcut: getKeyLabel('<Primary>') },
{ desc: "Curve line", shortcut: getKeyLabel('<Primary>') },
{ desc: "Smooth free drawing outline", shortcut: getKeyLabel('<Primary>') },
2020-06-20 06:17:56 -03:00
{ desc: "Rotate <span alpha=\"50%\">(while moving)</span>", shortcut: getKeyLabel('<Primary>') },
{ desc: "Stretch <span alpha=\"50%\">(while resizing)</span>", shortcut: getKeyLabel('<Primary>') },
{ desc: "Inverse <span alpha=\"50%\">(while mirroring)</span>", shortcut: getKeyLabel('<Primary>') }
2019-03-05 18:00:14 -03:00
];
2019-03-05 08:36:59 -03:00
function init() {
Convenience.initTranslations();
}
2019-03-28 10:59:14 -03:00
function buildPrefsWidget() {
let topStack = new TopStack();
let switcher = new Gtk.StackSwitcher({halign: Gtk.Align.CENTER, visible: true, stack: topStack});
2020-06-22 07:16:17 -03:00
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
2019-03-28 10:59:14 -03:00
let window = topStack.get_toplevel();
let headerBar = window.get_titlebar();
headerBar.custom_title = switcher;
return false;
});
topStack.show_all();
return topStack;
}
2020-03-02 12:32:50 -03:00
const TopStack = new GObject.Class({
2019-03-28 10:59:14 -03:00
Name: 'DrawOnYourScreenTopStack',
GTypeName: 'DrawOnYourScreenTopStack',
Extends: Gtk.Stack,
_init: function(params) {
this.parent({ transition_type: 1, transition_duration: 500, expand: true });
this.prefsPage = new PrefsPage();
this.add_titled(this.prefsPage, 'prefs', _("Preferences"));
this.drawingPage = new DrawingPage();
this.add_titled(this.drawingPage, 'drawing', _("Drawing"));
2019-03-28 10:59:14 -03:00
this.aboutPage = new AboutPage();
this.add_titled(this.aboutPage, 'about', _("About"));
}
});
2020-03-02 12:32:50 -03:00
const AboutPage = new GObject.Class({
2019-03-28 10:59:14 -03:00
Name: 'DrawOnYourScreenAboutPage',
GTypeName: 'DrawOnYourScreenAboutPage',
Extends: Gtk.ScrolledWindow,
_init: function(params) {
this.parent({ hscrollbar_policy: Gtk.PolicyType.NEVER });
2019-03-28 10:59:14 -03:00
let vbox= new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, margin: MARGIN*3 });
this.add(vbox);
2020-01-06 11:29:01 -03:00
let name = "<b> " + _(Me.metadata.name) + "</b>";
let version = _("Version %d").format(Me.metadata.version);
let description = _(Me.metadata.description);
let link = "<span><a href=\"" + Me.metadata.url + "\">" + Me.metadata.url + "</a></span>";
2019-03-28 10:59:14 -03:00
let licenceName = _GTK("GNU General Public License, version 2 or later");
let licenceLink = "https://www.gnu.org/licenses/old-licenses/gpl-2.0.html";
let licence = "<small>" + _GTK("This program comes with absolutely no warranty.\nSee the <a href=\"%s\">%s</a> for details.").format(licenceLink, licenceName) + "</small>";
let aboutLabel = new Gtk.Label({ wrap: true, justify: 2, use_markup: true, label:
name + "\n\n" + version + "\n\n" + description + "\n\n" + link + "\n\n" + licence + "\n" });
vbox.add(aboutLabel);
let creditBox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin: 2*MARGIN });
let leftBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let rightBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let leftLabel = new Gtk.Label({ wrap: true, valign: 1, halign: 2, justify: 1, use_markup: true, label: "<small>" + _GTK("Created by") + "</small>" });
let rightLabel = new Gtk.Label({ wrap: true, valign: 1, halign: 1, justify: 0, use_markup: true, label: "<small><a href=\"https://framagit.org/abakkk\">Abakkk</a></small>" });
2019-04-01 16:05:18 -03:00
leftBox.pack_start(leftLabel, false, false, 0);
rightBox.pack_start(rightLabel, false, false, 0);
2019-03-28 10:59:14 -03:00
creditBox.pack_start(leftBox, true, true, 5);
creditBox.pack_start(rightBox, true, true, 5);
vbox.add(creditBox);
if (_("translator-credits") != "translator-credits" && _("translator-credits") != "") {
2019-04-01 16:05:18 -03:00
leftBox.pack_start(new Gtk.Label(), false, false, 0);
rightBox.pack_start(new Gtk.Label(), false, false, 0);
2019-03-28 10:59:14 -03:00
leftLabel = new Gtk.Label({ wrap: true, valign: 1, halign: 2, justify: 1, use_markup: true, label: "<small>" + _GTK("Translated by") + "</small>" });
rightLabel = new Gtk.Label({ wrap: true, valign: 1, halign: 1, justify: 0, use_markup: true, label: "<small>" + _("translator-credits") + "</small>" });
2019-04-01 16:05:18 -03:00
leftBox.pack_start(leftLabel, false, false, 0);
rightBox.pack_start(rightLabel, false, false, 0);
2019-03-28 10:59:14 -03:00
}
}
});
const DrawingPage = new GObject.Class({
Name: 'DrawOnYourScreenDrawingPage',
GTypeName: 'DrawOnYourScreenDrawingPage',
Extends: Gtk.ScrolledWindow,
_init: function(params) {
this.parent({ hscrollbar_policy: Gtk.PolicyType.NEVER });
this.settings = Convenience.getSettings(Me.metadata['settings-schema'] + '.drawing');
this.schema = this.settings.settings_schema;
let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, margin: MARGIN*3 });
this.add(box);
let palettesFrame = new Gtk.Frame({ label_yalign: 1.0 });
palettesFrame.set_label_widget(new Gtk.Label({ margin_bottom: MARGIN/2, use_markup: true, label: "<b><big>" + _("Palettes") + "</big></b>" }));
box.add(palettesFrame);
let palettesScrolledWindow = new Gtk.ScrolledWindow({ vscrollbar_policy: Gtk.PolicyType.NEVER, margin_top: MARGIN/2, margin_bottom: MARGIN/2 });
palettesFrame.add(palettesScrolledWindow);
this.palettesListBox = new Gtk.ListBox({ selection_mode: 0, hexpand: true });
this.palettesListBox.get_style_context().add_class('background');
palettesScrolledWindow.add(this.palettesListBox);
this.settings.connect('changed::palettes', this._updatePalettes.bind(this));
this._updatePalettes();
this.addBox = new Gtk.Box({ margin_top: MARGIN/2, margin_bottom: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN, tooltip_text: _("Add a new palette") });
let addButton = Gtk.Button.new_from_icon_name('list-add-symbolic', Gtk.IconSize.BUTTON);
this.addBox.pack_start(addButton, true, true, 4);
addButton.connect('clicked', this._addNewPalette.bind(this));
this.palettesListBox.add(this.addBox);
this.addBox.get_parent().set_activatable(false);
let areaFrame = new Gtk.Frame({ margin_top: 3*MARGIN, label_yalign: 1.0 });
areaFrame.set_label_widget(new Gtk.Label({ margin_bottom: MARGIN/2, use_markup: true, label: "<b><big>" + _("Area") + "</big></b>" }));
box.add(areaFrame);
let areaListBox = new Gtk.ListBox({ selection_mode: 0, hexpand: true, margin_top: MARGIN/2, margin_bottom: MARGIN/2 });
areaListBox.get_style_context().add_class('background');
areaFrame.add(areaListBox);
let squareAreaRow = new PrefRow({ label: _("Square area size") });
let squareAreaAutoButton = new Gtk.CheckButton({ label: _("Auto"), tooltip_text: _(this.schema.get_key('square-area-auto').get_description()) });
let squareAreaSizeButton = new PixelSpinButton({ width_chars: 5, digits: 0,
adjustment: Gtk.Adjustment.new(0, 64, 32768, 1, 10, 0),
tooltip_text: _(this.schema.get_key('square-area-size').get_description()) });
this.settings.bind('square-area-auto', squareAreaAutoButton, 'active', 0);
this.settings.bind('square-area-size', squareAreaSizeButton, 'value', 0);
squareAreaAutoButton.bind_property('active', squareAreaSizeButton, 'sensitive', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN);
squareAreaRow.addWidget(squareAreaAutoButton);
squareAreaRow.addWidget(squareAreaSizeButton);
areaListBox.add(squareAreaRow);
let backgroundColorRow = new PrefRow({ label: _("Background color") });
let backgroundColorButton = new ColorStringButton({ use_alpha: true, show_editor: true,
tooltip_text: _(this.schema.get_key('area-background-color').get_description()) });
this.settings.bind('area-background-color', backgroundColorButton, 'color-string', 0);
backgroundColorRow.addWidget(backgroundColorButton);
areaListBox.add(backgroundColorRow);
let gridLineRow = new PrefRow({ label: _("Grid overlay line") });
let gridLineAutoButton = new Gtk.CheckButton({ label: _("Auto"), tooltip_text: _(this.schema.get_key('grid-line-auto').get_description()) });
let gridLineWidthButton = new PixelSpinButton({ width_chars: 5, digits: 1,
adjustment: Gtk.Adjustment.new(0, 0.1, 10, 0.1, 1, 0),
tooltip_text: _(this.schema.get_key('grid-line-width').get_description()) });
let gridLineSpacingButton = new PixelSpinButton({ width_chars: 5, digits: 1,
adjustment: Gtk.Adjustment.new(0, 1, 16384, 1, 10, 0),
tooltip_text: _(this.schema.get_key('grid-line-spacing').get_description()) });
this.settings.bind('grid-line-auto', gridLineAutoButton, 'active', 0);
this.settings.bind('grid-line-width', gridLineWidthButton, 'value', 0);
this.settings.bind('grid-line-spacing', gridLineSpacingButton, 'value', 0);
gridLineAutoButton.bind_property('active', gridLineWidthButton, 'sensitive', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN);
gridLineAutoButton.bind_property('active', gridLineSpacingButton, 'sensitive', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN);
gridLineRow.addWidget(gridLineAutoButton);
gridLineRow.addWidget(gridLineWidthButton);
gridLineRow.addWidget(gridLineSpacingButton);
areaListBox.add(gridLineRow);
let gridColorRow = new PrefRow({ label: _("Grid overlay color") });
let gridColorButton = new ColorStringButton({ use_alpha: true, show_editor: true,
tooltip_text: _(this.schema.get_key('grid-color').get_description()) });
this.settings.bind('grid-color', gridColorButton, 'color-string', 0);
gridColorRow.addWidget(gridColorButton);
areaListBox.add(gridColorRow);
let toolsFrame = new Gtk.Frame({ margin_top: 3*MARGIN, label_yalign: 1.0 });
toolsFrame.set_label_widget(new Gtk.Label({ margin_bottom: MARGIN/2, use_markup: true, label: "<b><big>" + _("Tools") + "</big></b>" }));
box.add(toolsFrame);
let toolsListBox = new Gtk.ListBox({ selection_mode: 0, hexpand: true, margin_top: MARGIN/2, margin_bottom: MARGIN/2 });
toolsListBox.get_style_context().add_class('background');
toolsFrame.add(toolsListBox);
let dashArrayRow = new PrefRow({ label: _("Dash array") });
let dashArrayAutoButton = new Gtk.CheckButton({ label: _("Auto"), tooltip_text: _(this.schema.get_key('dash-array-auto').get_description()) });
let dashArrayOnButton = new PixelSpinButton({ width_chars: 5, digits: 1,
adjustment: Gtk.Adjustment.new(0, 0, 16384, 0.1, 1, 0),
tooltip_text: _(this.schema.get_key('dash-array-on').get_description()) });
let dashArrayOffButton = new PixelSpinButton({ width_chars: 5, digits: 1,
adjustment: Gtk.Adjustment.new(0, 0, 16384, 0.1, 1, 0),
tooltip_text: _(this.schema.get_key('dash-array-off').get_description()) });
this.settings.bind('dash-array-auto', dashArrayAutoButton, 'active', 0);
this.settings.bind('dash-array-on', dashArrayOnButton, 'value', 0);
this.settings.bind('dash-array-off', dashArrayOffButton, 'value', 0);
dashArrayAutoButton.bind_property('active', dashArrayOnButton, 'sensitive', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN);
dashArrayAutoButton.bind_property('active', dashArrayOffButton, 'sensitive', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN);
dashArrayRow.addWidget(dashArrayAutoButton);
dashArrayRow.addWidget(dashArrayOnButton);
dashArrayRow.addWidget(dashArrayOffButton);
toolsListBox.add(dashArrayRow);
let dashOffsetRow = new PrefRow({ label: _("Dash offset") });
let dashOffsetButton = new PixelSpinButton({ width_chars: 5, digits: 1,
adjustment: Gtk.Adjustment.new(0, -16384, 16384, 0.1, 1, 0),
tooltip_text: _(this.schema.get_key('dash-offset').get_description()) });
this.settings.bind('dash-offset', dashOffsetButton, 'value', 0);
dashOffsetRow.addWidget(dashOffsetButton);
toolsListBox.add(dashOffsetRow);
},
_updatePalettes: function() {
this.palettes = this.settings.get_value('palettes').deep_unpack();
this.palettesListBox.get_children().filter(row=> row.get_child() != this.addBox)
.slice(this.palettes.length)
.forEach(row => this.palettesListBox.remove(row));
let paletteBoxes = this.palettesListBox.get_children().map(row => row.get_child()).filter(child => child != this.addBox);
this.palettes.forEach((palette, paletteIndex) => {
let [name, colors] = palette;
let paletteBox;
if (paletteBoxes[paletteIndex]) {
paletteBox = paletteBoxes[paletteIndex];
let nameEntry = paletteBox.get_children()[0];
if (nameEntry.get_text() !== _(name)) {
GObject.signal_handler_block(nameEntry, nameEntry.paletteNameChangedHandler);
nameEntry.set_text(_(name));
GObject.signal_handler_unblock(nameEntry, nameEntry.paletteNameChangedHandler);
}
} else {
let nameEntry = new Gtk.Entry({ text: name, halign: Gtk.Align.START, tooltip_text: _("Rename the palette") });
nameEntry.paletteNameChangedHandler = nameEntry.connect('changed', this._onPaletteNameChanged.bind(this, paletteIndex));
let removeButton = Gtk.Button.new_from_icon_name('list-remove-symbolic', Gtk.IconSize.BUTTON);
removeButton.set_tooltip_text(_("Remove the palette"));
removeButton.connect('clicked', this._removePalette.bind(this, paletteIndex));
paletteBox = new Gtk.Box({ margin_top: MARGIN/2, margin_bottom: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN });
paletteBox.pack_start(nameEntry, true, true, 4);
paletteBox.pack_start(new Gtk.Box({ spacing: 4 }), false, false, 4);
paletteBox.pack_start(removeButton, false, false, 4);
this.palettesListBox.insert(paletteBox, paletteIndex);
paletteBox.get_parent().set_activatable(false);
}
colors.splice(9);
while (colors.length < 9)
colors.push('transparent');
let colorsBox = paletteBox.get_children()[1];
let colorButtons = colorsBox.get_children();
colors.forEach((color, colorIndex) => {
if (colorButtons[colorIndex]) {
colorButtons[colorIndex].color_string = color;
} else {
let colorButton = new ColorStringButton({ color_string: color, use_alpha: true, show_editor: true, halign: Gtk.Align.START, hexpand: false });
colorButton.connect('notify::color-string', this._onPaletteColorChanged.bind(this, paletteIndex, colorIndex));
colorsBox.add(colorButton);
}
});
paletteBox.show_all();
});
},
_savePalettes: function() {
this.settings.set_value('palettes', new GLib.Variant('a(sas)', this.palettes));
},
_onPaletteNameChanged: function(index, entry) {
this.palettes[index][0] = entry.get_text();
this._savePalettes();
},
_onPaletteColorChanged: function(paletteIndex, colorIndex, colorButton) {
this.palettes[paletteIndex][1][colorIndex] = colorButton.get_rgba().to_string();
this._savePalettes();
},
_addNewPalette: function() {
let colors = Array(9).fill('Black');
this.palettes.push([_("New palette"), colors]);
this._savePalettes();
},
_removePalette: function(paletteIndex) {
this.palettes.splice(paletteIndex, 1);
this._savePalettes();
}
});
2020-03-02 12:32:50 -03:00
const PrefsPage = new GObject.Class({
Name: 'DrawOnYourScreenPrefsPage',
GTypeName: 'DrawOnYourScreenPrefsPage',
2019-03-05 08:36:59 -03:00
Extends: Gtk.ScrolledWindow,
_init: function(params) {
this.parent({ hscrollbar_policy: Gtk.PolicyType.NEVER });
2019-03-05 08:36:59 -03:00
2020-08-23 06:49:26 -03:00
let settings = Convenience.getSettings();
let internalShortcutSettings = Convenience.getSettings(Me.metadata['settings-schema'] + '.internal-shortcuts');
2019-03-05 08:36:59 -03:00
2020-01-07 18:15:18 -03:00
let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, margin: MARGIN*3 });
2019-03-05 08:36:59 -03:00
this.add(box);
2020-01-07 18:15:18 -03:00
let globalFrame = new Gtk.Frame({ label_yalign: 1.0 });
globalFrame.set_label_widget(new Gtk.Label({ margin_bottom: MARGIN/2, use_markup: true, label: "<b><big>" + _("Global") + "</big></b>" }));
box.add(globalFrame);
let listBox = new Gtk.ListBox({ selection_mode: 0, hexpand: true, margin_top: MARGIN/2, margin_bottom: MARGIN/2 });
globalFrame.add(listBox);
2019-03-05 08:36:59 -03:00
let styleContext = listBox.get_style_context();
styleContext.add_class('background');
2020-08-23 06:49:26 -03:00
let globalKeybindingsWidget = new KeybindingsWidget(GLOBAL_KEYBINDINGS, settings);
2019-03-05 08:36:59 -03:00
globalKeybindingsWidget.margin = MARGIN;
listBox.add(globalKeybindingsWidget);
2019-03-10 18:16:11 -03:00
2020-01-07 18:15:18 -03:00
let persistentBox = new Gtk.Box({ margin_top: MARGIN/2, margin_bottom: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN });
2019-03-11 13:53:35 -03:00
let persistentLabelBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let persistentLabel1 = new Gtk.Label({label: _("Persistent")});
2020-01-07 18:15:18 -03:00
let persistentLabel2 = new Gtk.Label({ use_markup: true, halign: 1, wrap: true, xalign: 0, label: "<small>" + _("Persistent drawing through session restart") + "</small>" });
2019-03-11 13:53:35 -03:00
persistentLabel1.set_halign(1);
2020-01-07 18:15:18 -03:00
persistentLabel2.get_style_context().add_class('dim-label');
2019-03-11 13:53:35 -03:00
persistentLabelBox.pack_start(persistentLabel1, true, true, 0);
persistentLabelBox.pack_start(persistentLabel2, true, true, 0);
let persistentSwitch = new Gtk.Switch({valign: 3});
2020-08-23 06:49:26 -03:00
settings.bind('persistent-drawing', persistentSwitch, 'active', 0);
2019-03-11 13:53:35 -03:00
persistentBox.pack_start(persistentLabelBox, true, true, 4);
persistentBox.pack_start(persistentSwitch, false, false, 4);
listBox.add(persistentBox);
2020-01-07 18:15:18 -03:00
let desktopBox = new Gtk.Box({ margin_top: MARGIN/2, margin_bottom: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN });
2020-01-05 10:50:38 -03:00
let desktopLabelBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let desktopLabel1 = new Gtk.Label({label: _("Drawing on the desktop")});
2020-01-07 18:15:18 -03:00
let desktopLabel2 = new Gtk.Label({ use_markup: true, halign: 1, wrap: true, xalign: 0, label: "<small>" + _("<i>Draw On Your Screen</i> becomes <i>Draw On Your Desktop</i>") + "</small>" });
2020-01-05 10:50:38 -03:00
desktopLabel1.set_halign(1);
2020-01-07 18:15:18 -03:00
desktopLabel2.get_style_context().add_class('dim-label');
2020-01-05 10:50:38 -03:00
desktopLabelBox.pack_start(desktopLabel1, true, true, 0);
desktopLabelBox.pack_start(desktopLabel2, true, true, 0);
let desktopSwitch = new Gtk.Switch({valign: 3});
2020-08-23 06:49:26 -03:00
settings.bind('drawing-on-desktop', desktopSwitch, 'active', 0);
2020-01-05 10:50:38 -03:00
desktopBox.pack_start(desktopLabelBox, true, true, 4);
desktopBox.pack_start(desktopSwitch, false, false, 4);
listBox.add(desktopBox);
2020-01-07 18:15:18 -03:00
let osdBox = new Gtk.Box({ margin_top: MARGIN/2, margin_bottom: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN });
let osdLabelBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let osdLabel1 = new Gtk.Label({label: _("Disable on-screen notifications")});
osdLabel1.set_halign(1);
osdLabelBox.pack_start(osdLabel1, true, true, 0);
let osdSwitch = new Gtk.Switch({valign: 3});
2020-08-23 06:49:26 -03:00
settings.bind('osd-disabled', osdSwitch, 'active', 0);
osdBox.pack_start(osdLabelBox, true, true, 4);
osdBox.pack_start(osdSwitch, false, false, 4);
listBox.add(osdBox);
2020-01-07 18:15:18 -03:00
let indicatorBox = new Gtk.Box({ margin_top: MARGIN/2, margin_bottom: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN });
let indicatorLabelBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let indicatorLabel1 = new Gtk.Label({label: _("Disable panel indicator")});
indicatorLabel1.set_halign(1);
indicatorLabelBox.pack_start(indicatorLabel1, true, true, 0);
let indicatorSwitch = new Gtk.Switch({valign: 3});
2020-08-23 06:49:26 -03:00
settings.bind('indicator-disabled', indicatorSwitch, 'active', 0);
indicatorBox.pack_start(indicatorLabelBox, true, true, 4);
indicatorBox.pack_start(indicatorSwitch, false, false, 4);
listBox.add(indicatorBox);
2020-01-05 10:50:38 -03:00
2020-01-07 18:15:18 -03:00
let children = listBox.get_children();
for (let i = 0; i < children.length; i++) {
if (children[i].activatable)
children[i].set_activatable(false);
}
let internalFrame = new Gtk.Frame({ margin_top: 3*MARGIN, label_yalign: 1.0 });
internalFrame.set_label_widget(new Gtk.Label({ margin_bottom: MARGIN/2, use_markup: true, label: "<b><big>" + _("Internal") + " </big></b>" + _("(in drawing mode)") }));
box.add(internalFrame);
2019-03-05 08:36:59 -03:00
2020-01-07 18:15:18 -03:00
listBox = new Gtk.ListBox({ selection_mode: 0, hexpand: true, margin_top: MARGIN });
internalFrame.add(listBox);
2019-03-05 08:36:59 -03:00
2020-01-07 18:15:18 -03:00
styleContext = listBox.get_style_context();
styleContext.add_class('background');
2019-03-05 08:36:59 -03:00
2019-03-05 18:00:14 -03:00
for (let i = 0; i < OTHER_SHORTCUTS.length; i++) {
if (OTHER_SHORTCUTS[i].desc.indexOf('-separator-') != -1) {
2019-03-05 08:36:59 -03:00
listBox.add(new Gtk.Box({ margin_top: MARGIN, margin_left: MARGIN, margin_right: MARGIN }));
continue;
}
let otherBox = new Gtk.Box({ margin_left: MARGIN, margin_right: MARGIN });
2020-06-20 06:17:56 -03:00
let otherLabel = new Gtk.Label({ label: _(OTHER_SHORTCUTS[i].desc), use_markup: true });
2019-03-05 08:36:59 -03:00
otherLabel.set_halign(1);
let otherLabel2 = new Gtk.Label({ label: OTHER_SHORTCUTS[i].shortcut });
2019-03-05 08:36:59 -03:00
otherBox.pack_start(otherLabel, true, true, 4);
otherBox.pack_start(otherLabel2, false, false, 4);
listBox.add(otherBox);
}
2020-08-23 06:49:26 -03:00
let internalKeybindingsWidget = new KeybindingsWidget(INTERNAL_KEYBINDINGS, internalShortcutSettings);
2019-03-05 08:36:59 -03:00
internalKeybindingsWidget.margin = MARGIN;
listBox.add(internalKeybindingsWidget);
2020-01-07 18:15:18 -03:00
let noteBox = new Gtk.Box({ margin: MARGIN });
2019-03-05 08:36:59 -03:00
let noteLabel = new Gtk.Label({
2020-01-07 18:15:18 -03:00
wrap: true,
xalign: 0,
2019-03-05 08:36:59 -03:00
use_markup: true,
label: _("When you save elements made with <b>eraser</b> in a <b>SVG</b> file, " +
2020-01-07 18:15:18 -03:00
"they are colored with background color, transparent if it is disabled.\n" +
"See <i>“%s”</i> or edit the SVG file afterwards.").format(_("Add a drawing background"))
2019-03-05 08:36:59 -03:00
});
noteLabel.set_halign(1);
2020-01-07 18:15:18 -03:00
noteLabel.get_style_context().add_class('dim-label');
2019-03-05 08:36:59 -03:00
noteBox.pack_start(noteLabel, true, true, 4);
listBox.add(noteBox);
2020-01-07 18:15:18 -03:00
children = listBox.get_children();
2019-03-05 08:36:59 -03:00
for (let i = 0; i < children.length; i++) {
if (children[i].activatable)
children[i].set_activatable(false);
}
}
});
const PrefRow = new GObject.Class({
Name: 'DrawOnYourScreenPrefRow',
GTypeName: 'DrawOnYourScreenPrefRow',
Extends: Gtk.ListBoxRow,
_init: function(params) {
this.parent({ activatable: false });
let hbox = new Gtk.Box({ margin_top: MARGIN/2, margin_bottom: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN });
this.add(hbox);
let labelBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
hbox.pack_start(labelBox, true, true, 4);
this.widgetBox = new Gtk.Box({ spacing: 4 });
hbox.pack_start(this.widgetBox, false, false, 4);
labelBox.pack_start(new Gtk.Label({ use_markup: true, label: params.label, halign: Gtk.Align.START }), true, true, 0);
if (params.desc) {
let desc = new Gtk.Label({ use_markup: true, label: `<small>${params.desc}</small>`, halign: Gtk.Align.START, wrap: true, xalign: 0 });
desc.get_style_context().add_class('dim-label');
labelBox.pack_start(desc, true, true, 0);
this.widgetBox.set_valign(Gtk.Align.START);
}
},
addWidget: function(widget) {
this.widgetBox.add(widget);
}
});
const PixelSpinButton = new GObject.Class({
Name: 'DrawOnYourScreenPixelSpinButton',
GTypeName: 'DrawOnYourScreenPixelSpinButton',
Extends: Gtk.SpinButton,
// Add 'px' unit.
vfunc_output: function() {
this.text = `${Math.round(this.value * 100) / 100} px`;
return true;
},
// Prevent accidental scrolling.
vfunc_scroll_event: function(event) {
return this.has_focus ? this.parent(event) : Gdk.EVENT_PROPAGATE;
}
});
// A color button that can be easily bound with a color string setting.
const ColorStringButton = new GObject.Class({
Name: 'DrawOnYourScreenColorStringButton',
GTypeName: 'DrawOnYourScreenColorStringButton',
Extends: Gtk.ColorButton,
Properties: {
'color-string': GObject.ParamSpec.string('color-string', 'colorString', 'A string that describes the color',
GObject.ParamFlags.READWRITE,
'black')
},
get color_string() {
return this._color_string || 'black';
},
set color_string(colorString) {
this._color_string = colorString;
let newRgba = new Gdk.RGBA();
newRgba.parse(colorString);
this.set_rgba(newRgba);
},
// Do nothing if the new color is equivalent to the old color (e.g. "black" and "rgb(0,0,0)").
vfunc_color_set(args) {
let oldRgba = new Gdk.RGBA();
oldRgba.parse(this.color_string);
if (!this.rgba.equal(oldRgba)) {
this._color_string = this.rgba.to_string();
this.notify('color-string');
}
}
});
2019-03-05 08:36:59 -03:00
// this code comes from Sticky Notes View by Sam Bull, https://extensions.gnome.org/extension/568/notes/
2020-03-02 12:32:50 -03:00
const KeybindingsWidget = new GObject.Class({
Name: 'DrawOnYourScreenKeybindings.Widget',
GTypeName: 'DrawOnYourScreenKeybindingsWidget',
2019-03-05 08:36:59 -03:00
Extends: Gtk.Box,
_init: function(keybindings, settings) {
this.parent();
this.set_orientation(Gtk.Orientation.VERTICAL);
this._keybindings = keybindings;
this._settings = settings;
this._columns = {
NAME: 0,
ACCEL_NAME: 1,
MODS: 2,
KEY: 3
};
this._store = new Gtk.ListStore();
this._store.set_column_types([
GObject.TYPE_STRING,
GObject.TYPE_STRING,
GObject.TYPE_INT,
GObject.TYPE_INT
]);
this._tree_view = new Gtk.TreeView({
model: this._store,
hexpand: false,
vexpand: false
});
this._tree_view.set_activate_on_single_click(false);
this._tree_view.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
let action_renderer = new Gtk.CellRendererText();
let action_column = new Gtk.TreeViewColumn({
title: "",
expand: true,
});
action_column.pack_start(action_renderer, true);
action_column.add_attribute(action_renderer, 'text', 1);
this._tree_view.append_column(action_column);
let keybinding_renderer = new Gtk.CellRendererAccel({
editable: true,
accel_mode: Gtk.CellRendererAccelMode.GTK,
xalign: 1
});
2020-08-01 10:00:49 -03:00
keybinding_renderer.connect('accel-edited', (renderer, iter, key, mods) => {
let value = Gtk.accelerator_name(key, mods);
let [success, iterator ] =
this._store.get_iter_from_string(iter);
2019-03-05 08:36:59 -03:00
2020-08-01 10:00:49 -03:00
if(!success) {
printerr("Can't change keybinding");
}
2019-03-05 08:36:59 -03:00
2020-08-01 10:00:49 -03:00
let name = this._store.get_value(iterator, 0);
2019-03-05 08:36:59 -03:00
2020-08-01 10:00:49 -03:00
this._store.set(
iterator,
[this._columns.MODS, this._columns.KEY],
[mods, key]
);
this._settings.set_strv(name, [value]);
});
2019-03-05 08:36:59 -03:00
let keybinding_column = new Gtk.TreeViewColumn({
title: "",
});
keybinding_column.pack_end(keybinding_renderer, false);
keybinding_column.add_attribute(
keybinding_renderer,
'accel-mods',
this._columns.MODS
);
keybinding_column.add_attribute(
keybinding_renderer,
'accel-key',
this._columns.KEY
);
this._tree_view.append_column(keybinding_column);
this._tree_view.columns_autosize();
this._tree_view.set_headers_visible(false);
this.add(this._tree_view);
this.keybinding_column = keybinding_column;
this.action_column = action_column;
this._refresh();
},
_refresh: function() {
this._store.clear();
for(let settings_key in this._keybindings) {
if (settings_key.indexOf('-separator-') != -1)
continue;
let [key, mods] = Gtk.accelerator_parse(
this._settings.get_strv(settings_key)[0]
);
let iter = this._store.append();
this._store.set(iter,
[
this._columns.NAME,
this._columns.ACCEL_NAME,
this._columns.MODS,
this._columns.KEY
],
[
settings_key,
_(this._keybindings[settings_key]),
mods,
key
]
);
}
}
});