init
This commit is contained in:
parent
1f67bc15af
commit
7f9a3195b4
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2011-2012, Giovanni Campagna <scampa.giovanni@gmail.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the GNOME nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Gettext = imports.gettext;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
|
|
||||||
|
const Config = imports.misc.config;
|
||||||
|
const ExtensionUtils = imports.misc.extensionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initTranslations:
|
||||||
|
* @domain: (optional): the gettext domain to use
|
||||||
|
*
|
||||||
|
* Initialize Gettext to load translations from extensionsdir/locale.
|
||||||
|
* If @domain is not provided, it will be taken from metadata['gettext-domain']
|
||||||
|
*/
|
||||||
|
function initTranslations(domain) {
|
||||||
|
let extension = ExtensionUtils.getCurrentExtension();
|
||||||
|
|
||||||
|
domain = domain || extension.metadata['gettext-domain'];
|
||||||
|
|
||||||
|
// check if this extension was built with "make zip-file", and thus
|
||||||
|
// has the locale files in a subfolder
|
||||||
|
// otherwise assume that extension has been installed in the
|
||||||
|
// same prefix as gnome-shell
|
||||||
|
let localeDir = extension.dir.get_child('locale');
|
||||||
|
if (localeDir.query_exists(null))
|
||||||
|
Gettext.bindtextdomain(domain, localeDir.get_path());
|
||||||
|
else
|
||||||
|
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getSettings:
|
||||||
|
* @schema: (optional): the GSettings schema id
|
||||||
|
*
|
||||||
|
* Builds and return a GSettings schema for @schema, using schema files
|
||||||
|
* in extensionsdir/schemas. If @schema is not provided, it is taken from
|
||||||
|
* metadata['settings-schema'].
|
||||||
|
*/
|
||||||
|
function getSettings(schema) {
|
||||||
|
let extension = ExtensionUtils.getCurrentExtension();
|
||||||
|
|
||||||
|
schema = schema || extension.metadata['settings-schema'];
|
||||||
|
|
||||||
|
const GioSSS = Gio.SettingsSchemaSource;
|
||||||
|
|
||||||
|
// check if this extension was built with "make zip-file", and thus
|
||||||
|
// has the schema files in a subfolder
|
||||||
|
// otherwise assume that extension has been installed in the
|
||||||
|
// same prefix as gnome-shell (and therefore schemas are available
|
||||||
|
// in the standard folders)
|
||||||
|
let schemaDir = extension.dir.get_child('schemas');
|
||||||
|
let schemaSource;
|
||||||
|
if (schemaDir.query_exists(null))
|
||||||
|
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
|
||||||
|
GioSSS.get_default(),
|
||||||
|
false);
|
||||||
|
else
|
||||||
|
schemaSource = GioSSS.get_default();
|
||||||
|
|
||||||
|
let schemaObj = schemaSource.lookup(schema, true);
|
||||||
|
if (!schemaObj)
|
||||||
|
throw new Error('Schema ' + schema + ' could not be found for extension '
|
||||||
|
+ extension.metadata.uuid + '. Please check your installation.');
|
||||||
|
|
||||||
|
return new Gio.Settings({ settings_schema: schemaObj });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,690 @@
|
||||||
|
/* jslint esversion: 6 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Abakkk
|
||||||
|
*
|
||||||
|
* This file is part of DrowOnYourScreen, a drawing extension for GNOME Shell.
|
||||||
|
* 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 Cairo = imports.cairo;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Screenshot = imports.ui.screenshot;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
const ExtensionUtils = imports.misc.extensionUtils;
|
||||||
|
const Extension = ExtensionUtils.getCurrentExtension();
|
||||||
|
const Convenience = Extension.imports.convenience;
|
||||||
|
const Prefs = Extension.imports.prefs;
|
||||||
|
const _ = imports.gettext.domain(Extension.metadata["gettext-domain"]).gettext;
|
||||||
|
|
||||||
|
var Shapes = { NONE: 0, LINE: 1, ELLIPSE: 2, RECTANGLE: 3, TEXT: 4 };
|
||||||
|
var ShapeNames = { 0: "Free drawing", 1: "Line", 2: "Circle", 3: "Rectangle", 4: "Text" };
|
||||||
|
var LineCapNames = { 0: 'Butt', 1: 'Round', 2: 'Square' };
|
||||||
|
var LineJoinNames = { 0: 'Miter', 1: 'Round', 2: 'Bevel' };
|
||||||
|
var FontWeightNames = { 0: 'Normal', 1: 'Bold' };
|
||||||
|
var FontStyleNames = { 0: 'Normal', 1: 'Italic', 2: 'Oblique' };
|
||||||
|
var FontFamilyNames = { 0: 'Default', 1: 'Sans-Serif', 2: 'Serif', 3: 'Monospace', 4: 'Cursive', 5: 'Fantasy' };
|
||||||
|
|
||||||
|
// DrawingArea is the widget in which we draw, thanks to Cairo.
|
||||||
|
// It creates and manages a DrawingElement for each "brushstroke".
|
||||||
|
// It handles pointer/mouse/(touch?) events and some keyboard events.
|
||||||
|
var DrawingArea = new Lang.Class({
|
||||||
|
Name: 'DrawingArea',
|
||||||
|
Extends: St.DrawingArea,
|
||||||
|
|
||||||
|
_init: function(params, helper) {
|
||||||
|
this.parent({ style_class: 'draw-on-your-screen', name: params && params.name ? params.name : ""});
|
||||||
|
|
||||||
|
// 'style-changed' is emitted when 'this' is added to an actor
|
||||||
|
// ('this' needs to be in the stage to query theme_node)
|
||||||
|
this.connect('style-changed', this._onStyleChanged.bind(this));
|
||||||
|
this.connect('repaint', this._repaint.bind(this));
|
||||||
|
|
||||||
|
this.emitter = new DrawingAreaEmitter();
|
||||||
|
this.helper = helper;
|
||||||
|
|
||||||
|
this.elements = [];
|
||||||
|
this.undoneElements = [];
|
||||||
|
this.currentElement = null;
|
||||||
|
this.currentShape = Shapes.NONE;
|
||||||
|
this.hasBackground = false;
|
||||||
|
this.textHasCursor = false;
|
||||||
|
this.dashedLine = false;
|
||||||
|
this.colors = [Clutter.Color.new(0, 0, 0, 255)];
|
||||||
|
},
|
||||||
|
|
||||||
|
_redisplay: function() {
|
||||||
|
// force area to emit 'repaint'
|
||||||
|
this.queue_repaint();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onStyleChanged: function() {
|
||||||
|
try {
|
||||||
|
let themeNode = this.get_theme_node();
|
||||||
|
for (let i = 1; i < 10; i++) {
|
||||||
|
this.colors[i] = themeNode.get_color('-drawing-color' + i);
|
||||||
|
}
|
||||||
|
this.activeBackgroundColor = themeNode.get_color('-drawing-background-color');
|
||||||
|
this.currentLineWidth = themeNode.get_length('-drawing-line-width');
|
||||||
|
this.currentLineJoin = themeNode.get_double('-drawing-line-join');
|
||||||
|
this.currentLineCap = themeNode.get_double('-drawing-line-cap');
|
||||||
|
this.dashArray = [themeNode.get_length('-drawing-dash-array-on'), themeNode.get_length('-drawing-dash-array-off')];
|
||||||
|
this.dashOffset = themeNode.get_length('-drawing-dash-offset');
|
||||||
|
let font = themeNode.get_font();
|
||||||
|
this.fontFamily = font.get_family();
|
||||||
|
this.currentFontWeight = font.get_weight();
|
||||||
|
this.currentFontStyle = font.get_style();
|
||||||
|
} catch(e) {
|
||||||
|
logError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i < 10; i++) {
|
||||||
|
this.colors[i] = this.colors[i].alpha ? this.colors[i] : this.colors[0];
|
||||||
|
}
|
||||||
|
this.currentColor = this.colors[1];
|
||||||
|
|
||||||
|
this.currentLineWidth = (this.currentLineWidth > 0) ? this.currentLineWidth : 3;
|
||||||
|
this.currentLineJoin = ([0, 1, 2].indexOf(this.currentLineJoin) != -1) ? this.currentLineJoin : Cairo.LineJoin.ROUND;
|
||||||
|
this.currentLineCap = ([0, 1, 2].indexOf(this.currentLineCap) != -1) ? this.currentLineCap : Cairo.LineCap.ROUND;
|
||||||
|
this.currentFontFamilyId = 0;
|
||||||
|
this.currentFontWeight = this.currentFontWeight > 500 ? 1 : 0 ;
|
||||||
|
// font style enum order of Cairo and Pango are different
|
||||||
|
this.currentFontStyle = this.currentFontStyle == 2 ? 1 : ( this.currentFontStyle == 1 ? 2 : 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
_repaint: function(area) {
|
||||||
|
let cr = area.get_context();
|
||||||
|
|
||||||
|
for (let i = 0; i < this.elements.length; i++) {
|
||||||
|
this.elements[i].buildCairo(cr, false);
|
||||||
|
|
||||||
|
if (this.elements[i].fill && this.elements[i].shape != Shapes.LINE)
|
||||||
|
cr.fill();
|
||||||
|
else
|
||||||
|
cr.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentElement) {
|
||||||
|
this.currentElement.buildCairo(cr, this.textHasCursor);
|
||||||
|
cr.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.$dispose();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onButtonPressed: function(actor, event) {
|
||||||
|
let button = event.get_button();
|
||||||
|
let [x, y] = event.get_coords();
|
||||||
|
let shiftPressed = event.has_shift_modifier();
|
||||||
|
|
||||||
|
// stop writing
|
||||||
|
if (this.currentElement && this.currentElement.shape == Shapes.TEXT) {
|
||||||
|
this._stopWriting();
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide helper
|
||||||
|
if (this.helper.visible && button != 2) {
|
||||||
|
this.helper.hideHelp();
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button == 1) {
|
||||||
|
this._startDrawing(x, y, false, shiftPressed);
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
} else if (button == 2) {
|
||||||
|
this.toggleShape();
|
||||||
|
} else if (button == 3) {
|
||||||
|
this._startDrawing(x, y, true, shiftPressed);
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onKeyPressed: function(actor, event) {
|
||||||
|
if (event.get_key_symbol() == Clutter.Escape) {
|
||||||
|
this.emitter.emit('stop-drawing');
|
||||||
|
this.erase();
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
} else if (this.currentElement && this.currentElement.shape == Shapes.TEXT) {
|
||||||
|
if (event.get_key_symbol() == Clutter.KEY_BackSpace) {
|
||||||
|
this.currentElement.text = this.currentElement.text.slice(0, -1);
|
||||||
|
this._updateCursorTimeout();
|
||||||
|
} else if (event.has_control_modifier() && event.get_key_symbol() == 118) {
|
||||||
|
// Ctrl + V
|
||||||
|
St.Clipboard.get_default().get_text(St.ClipboardType.CLIPBOARD, (clipBoard, clipText) => {
|
||||||
|
this.currentElement.text += clipText;
|
||||||
|
this._updateCursorTimeout();
|
||||||
|
this._redisplay();
|
||||||
|
});
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
} else if (event.get_key_symbol() == Clutter.KEY_Return || event.get_key_symbol() == 65421) {
|
||||||
|
// stop writing
|
||||||
|
// Clutter.KEY_Return is "Enter" and 65421 is KP_Enter
|
||||||
|
this._stopWriting();
|
||||||
|
} else {
|
||||||
|
let unicode = event.get_key_unicode();
|
||||||
|
this.currentElement.text += unicode;
|
||||||
|
this._updateCursorTimeout();
|
||||||
|
}
|
||||||
|
this._redisplay();
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
} else {
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onScroll: function(actor, event) {
|
||||||
|
if (this.helper.visible)
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
let direction = event.get_scroll_direction();
|
||||||
|
if (direction == Clutter.ScrollDirection.UP)
|
||||||
|
this.incrementLineWidth(1);
|
||||||
|
else if (direction == Clutter.ScrollDirection.DOWN)
|
||||||
|
this.incrementLineWidth(-1);
|
||||||
|
else
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
return Clutter.EVENT_STOP;
|
||||||
|
},
|
||||||
|
|
||||||
|
_startDrawing: function(stageX, stageY, fill, eraser) {
|
||||||
|
let [success, startX, startY] = this.transform_stage_point(stageX, stageY);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.buttonReleasedHandler = this.connect('button-release-event', (actor, event) => {
|
||||||
|
this._stopDrawing();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.currentElement = new DrawingElement ({
|
||||||
|
color: this.currentColor,
|
||||||
|
line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap },
|
||||||
|
dash: { array: this.dashedLine ? this.dashArray : [0, 0] , offset: this.dashedLine ? this.dashOffset : 0 },
|
||||||
|
fill: fill,
|
||||||
|
eraser: eraser,
|
||||||
|
shape: this.currentShape == Shapes.TEXT ? Shapes.RECTANGLE : this.currentShape,
|
||||||
|
text: '',
|
||||||
|
font: { family: (this.currentFontFamilyId == 0 ? this.fontFamily : FontFamilyNames[this.currentFontFamilyId]), weight: this.currentFontWeight, style: this.currentFontStyle },
|
||||||
|
points: [[startX, startY]]
|
||||||
|
});
|
||||||
|
|
||||||
|
this.motionHandler = this.connect('motion-event', (actor, event) => {
|
||||||
|
let coords = event.get_coords();
|
||||||
|
let [s, x, y] = this.transform_stage_point(coords[0], coords[1]);
|
||||||
|
if (!s)
|
||||||
|
return;
|
||||||
|
this._updateDrawing(x, y);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_stopDrawing: function() {
|
||||||
|
if (this.motionHandler) {
|
||||||
|
this.disconnect(this.motionHandler);
|
||||||
|
this.motionHandler = null;
|
||||||
|
}
|
||||||
|
if (this.buttonReleasedHandler) {
|
||||||
|
this.disconnect(this.buttonReleasedHandler);
|
||||||
|
this.buttonReleasedHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start writing
|
||||||
|
if (this.currentShape == Shapes.TEXT && this.currentElement) {
|
||||||
|
this.currentElement.shape = Shapes.TEXT;
|
||||||
|
this.currentElement.text = '';
|
||||||
|
this.emitter.emit('show-osd', _("Type your text\nand press Enter"), null);
|
||||||
|
this._updateCursorTimeout();
|
||||||
|
this._redisplay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentElement) {
|
||||||
|
this.elements.push(this.currentElement);
|
||||||
|
}
|
||||||
|
this.currentElement = null;
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateDrawing: function(x, y) {
|
||||||
|
if (!this.currentElement)
|
||||||
|
return;
|
||||||
|
if (this.currentElement.shape == Shapes.NONE)
|
||||||
|
this.currentElement.points.push([x, y]);
|
||||||
|
else
|
||||||
|
this.currentElement.points[1] = [x, y];
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
_stopWriting: function() {
|
||||||
|
this.elements.push(this.currentElement);
|
||||||
|
this.currentElement = null;
|
||||||
|
this._stopCursorTimeout();
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
_stopCursorTimeout: function() {
|
||||||
|
if (this.cursorTimeoutId) {
|
||||||
|
Mainloop.source_remove(this.cursorTimeoutId);
|
||||||
|
this.cursorTimeoutId = null;
|
||||||
|
}
|
||||||
|
this.textHasCursor = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateCursorTimeout: function() {
|
||||||
|
this._stopCursorTimeout();
|
||||||
|
this.cursorTimeoutId = Mainloop.timeout_add(600, () => {
|
||||||
|
this.textHasCursor = !this.textHasCursor;
|
||||||
|
this._redisplay();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
erase: function() {
|
||||||
|
this.elements = [];
|
||||||
|
this.undoneElements = [];
|
||||||
|
this.currentElement = null;
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteLastElement: function() {
|
||||||
|
if (this.currentElement) {
|
||||||
|
if (this.motionHandler) {
|
||||||
|
this.disconnect(this.motionHandler);
|
||||||
|
this.motionHandler = null;
|
||||||
|
}
|
||||||
|
if (this.buttonReleasedHandler) {
|
||||||
|
this.disconnect(this.buttonReleasedHandler);
|
||||||
|
this.buttonReleasedHandler = null;
|
||||||
|
}
|
||||||
|
this.currentElement = null;
|
||||||
|
this._stopCursorTimeout();
|
||||||
|
} else {
|
||||||
|
this.elements.pop();
|
||||||
|
}
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
undo: function() {
|
||||||
|
if (this.elements.length > 0)
|
||||||
|
this.undoneElements.push(this.elements.pop());
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
redo: function() {
|
||||||
|
if (this.undoneElements.length > 0)
|
||||||
|
this.elements.push(this.undoneElements.pop());
|
||||||
|
this._redisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleBackground: function() {
|
||||||
|
this.hasBackground = !this.hasBackground;
|
||||||
|
this.get_parent().set_background_color(this.hasBackground ? this.activeBackgroundColor : null);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleColor: function() {
|
||||||
|
this.selectColor((this.currentColor == this.colors[1]) ? 2 : 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectColor: function(index) {
|
||||||
|
this.currentColor = this.colors[index];
|
||||||
|
if (this.currentElement) {
|
||||||
|
this.currentElement.color = this.currentColor;
|
||||||
|
this._redisplay();
|
||||||
|
}
|
||||||
|
this.emitter.emit('show-osd', this.currentColor.to_string(), null);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectShape: function(shape) {
|
||||||
|
this.currentShape = shape;
|
||||||
|
this.emitter.emit('show-osd', _(ShapeNames[shape]), null);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleShape: function() {
|
||||||
|
this.selectShape((this.currentShape == Object.keys(Shapes).length - 1) ? 0 : this.currentShape + 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleDash: function() {
|
||||||
|
this.dashedLine = !this.dashedLine;
|
||||||
|
this.emitter.emit('show-osd', this.dashedLine ? _("Dashed line") : _("Full line"), null);
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementLineWidth: function(increment) {
|
||||||
|
this.currentLineWidth = Math.max(this.currentLineWidth + increment, 1);
|
||||||
|
this.emitter.emit('show-osd', this.currentLineWidth + "px", this.currentLineWidth);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleLineJoin: function() {
|
||||||
|
this.currentLineJoin = this.currentLineJoin == 2 ? 0 : this.currentLineJoin + 1;
|
||||||
|
this.emitter.emit('show-osd', LineJoinNames[this.currentLineJoin], null);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleLineCap: function() {
|
||||||
|
this.currentLineCap = this.currentLineCap == 2 ? 0 : this.currentLineCap + 1;
|
||||||
|
this.emitter.emit('show-osd', LineCapNames[this.currentLineCap], null);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleFontWeight: function() {
|
||||||
|
this.currentFontWeight = this.currentFontWeight == 1 ? 0 : this.currentFontWeight + 1;
|
||||||
|
if (this.currentElement) {
|
||||||
|
this.currentElement.font.weight = this.currentFontWeight;
|
||||||
|
this._redisplay();
|
||||||
|
}
|
||||||
|
this.emitter.emit('show-osd', FontWeightNames[this.currentFontWeight], null);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleFontStyle: function() {
|
||||||
|
this.currentFontStyle = this.currentFontStyle == 2 ? 0 : this.currentFontStyle + 1;
|
||||||
|
if (this.currentElement) {
|
||||||
|
this.currentElement.font.style = this.currentFontStyle;
|
||||||
|
this._redisplay();
|
||||||
|
}
|
||||||
|
this.emitter.emit('show-osd', FontStyleNames[this.currentFontStyle], null);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleFontFamily: function() {
|
||||||
|
this.currentFontFamilyId = this.currentFontFamilyId == 5 ? 0 : this.currentFontFamilyId + 1;
|
||||||
|
let currentFontFamily = this.currentFontFamilyId == 0 ? this.fontFamily : FontFamilyNames[this.currentFontFamilyId];
|
||||||
|
if (this.currentElement) {
|
||||||
|
this.currentElement.font.family = currentFontFamily;
|
||||||
|
this._redisplay();
|
||||||
|
}
|
||||||
|
this.emitter.emit('show-osd',currentFontFamily , null);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleHelp: function() {
|
||||||
|
if (this.helper.visible)
|
||||||
|
this.helper.hideHelp();
|
||||||
|
else
|
||||||
|
this.helper.showHelp();
|
||||||
|
},
|
||||||
|
|
||||||
|
enterDrawingMode: function() {
|
||||||
|
this.keyPressedHandler = this.connect('key-press-event', this._onKeyPressed.bind(this));
|
||||||
|
this.buttonPressedHandler = this.connect('button-press-event', this._onButtonPressed.bind(this));
|
||||||
|
this.scrollHandler = this.connect('scroll-event', this._onScroll.bind(this));
|
||||||
|
this.selectShape(Shapes.NONE);
|
||||||
|
this.get_parent().set_background_color(this.hasBackground ? this.activeBackgroundColor : null);
|
||||||
|
},
|
||||||
|
|
||||||
|
leaveDrawingMode: function() {
|
||||||
|
if (this.keyPressedHandler) {
|
||||||
|
this.disconnect(this.keyPressedHandler);
|
||||||
|
this.keyPressedHandler = null;
|
||||||
|
}
|
||||||
|
if (this.buttonPressedHandler) {
|
||||||
|
this.disconnect(this.buttonPressedHandler);
|
||||||
|
this.buttonPressedHandler = null;
|
||||||
|
}
|
||||||
|
if (this.motionHandler) {
|
||||||
|
this.disconnect(this.motionHandler);
|
||||||
|
this.motionHandler = null;
|
||||||
|
}
|
||||||
|
if (this.buttonReleasedHandler) {
|
||||||
|
this.disconnect(this.buttonReleasedHandler);
|
||||||
|
this.buttonReleasedHandler = null;
|
||||||
|
}
|
||||||
|
if (this.scrollHandler) {
|
||||||
|
this.disconnect(this.scrollHandler);
|
||||||
|
this.scrollHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.helper.visible)
|
||||||
|
this.helper.hideHelp();
|
||||||
|
|
||||||
|
this.currentElement = null;
|
||||||
|
this._stopCursorTimeout();
|
||||||
|
this.dashedLine = false;
|
||||||
|
this._redisplay();
|
||||||
|
this.get_parent().set_background_color(null);
|
||||||
|
},
|
||||||
|
|
||||||
|
save: function() {
|
||||||
|
// stop drawing or writing
|
||||||
|
if (this.currentElement && this.currentElement.shape == Shapes.TEXT) {
|
||||||
|
this._stopWriting();
|
||||||
|
} else if (this.currentElement && this.currentShape != Shapes.TEXT) {
|
||||||
|
this._stopDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = `<svg viewBox="0 0 ${this.width} ${this.height}" xmlns="http://www.w3.org/2000/svg">`;
|
||||||
|
let backgroundColorString = this.hasBackground ? this.activeBackgroundColor.to_string() : 'transparent';
|
||||||
|
if (backgroundColorString != 'transparent') {
|
||||||
|
content += `\n <rect id="background" width="100%" height="100%" fill="${backgroundColorString}"/>`;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < this.elements.length; i++) {
|
||||||
|
content += this.elements[i].buildSVG(backgroundColorString);
|
||||||
|
}
|
||||||
|
content += "\n</svg>";
|
||||||
|
|
||||||
|
let date = GLib.DateTime.new_now_local();
|
||||||
|
let filename = `DrawOnYourScreen ${date.format("%F")} ${date.format("%X")}.svg`;
|
||||||
|
let dir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES);
|
||||||
|
let path = GLib.build_filenamev([dir, filename]);
|
||||||
|
if (GLib.file_test(path, GLib.FileTest.EXISTS))
|
||||||
|
return false;
|
||||||
|
let success = GLib.file_set_contents(path, content);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
// pass the parent (bgContainer) to Flashspot because coords of this are relative
|
||||||
|
let flashspot = new Screenshot.Flashspot(this.get_parent());
|
||||||
|
flashspot.fire();
|
||||||
|
global.play_theme_sound(0, 'screen-capture', "Save as SVG", null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
disable: function() {
|
||||||
|
if (this.theme && this.customStylesheetsChangedHandler) {
|
||||||
|
this.theme.disconnect(this.customStylesheetsChangedHandler);
|
||||||
|
this.customStylesheetsChangedHandler = null;
|
||||||
|
}
|
||||||
|
this.erase();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var DrawingAreaEmitter = new Lang.Class({
|
||||||
|
Name: 'DrawingAreaEmitter',
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Signals.addSignalMethods(DrawingAreaEmitter.prototype);
|
||||||
|
|
||||||
|
|
||||||
|
// DrawingElement represents a "brushstroke".
|
||||||
|
// It can be converted into a cairo path as well as a svg element.
|
||||||
|
// See DrawingArea._startDrawing() to know its params.
|
||||||
|
var DrawingElement = new Lang.Class({
|
||||||
|
Name: 'DrawingElement',
|
||||||
|
|
||||||
|
_init: function(params) {
|
||||||
|
for (let key in params)
|
||||||
|
this[key] = params[key];
|
||||||
|
},
|
||||||
|
|
||||||
|
buildCairo: function(cr, showTextCursor) {
|
||||||
|
cr.setLineCap(this.line.lineCap);
|
||||||
|
cr.setLineJoin(this.line.lineJoin);
|
||||||
|
cr.setLineWidth(this.line.lineWidth);
|
||||||
|
|
||||||
|
if (this.dash.array[0] > 0 && this.dash.array[1] > 0)
|
||||||
|
cr.setDash(this.dash.array, this.dash.offset);
|
||||||
|
else
|
||||||
|
cr.setDash([1000000], 0);
|
||||||
|
|
||||||
|
if (this.eraser)
|
||||||
|
cr.setOperator(Cairo.Operator.CLEAR);
|
||||||
|
else
|
||||||
|
cr.setOperator(Cairo.Operator.OVER);
|
||||||
|
|
||||||
|
Clutter.cairo_set_source_color(cr, this.color);
|
||||||
|
|
||||||
|
let [points, shape] = [this.points, this.shape];
|
||||||
|
|
||||||
|
if (shape == Shapes.NONE || shape == Shapes.LINE) {
|
||||||
|
cr.moveTo(points[0][0], points[0][1]);
|
||||||
|
for (let j = 1; j < points.length; j++) {
|
||||||
|
cr.lineTo(points[j][0], points[j][1]);
|
||||||
|
}
|
||||||
|
} else if (shape == Shapes.ELLIPSE && points.length == 2) {
|
||||||
|
let r = Math.hypot(points[1][0] - points[0][0], points[1][1] - points[0][1]);
|
||||||
|
cr.arc(points[0][0], points[0][1], r, 0, 2 * Math.PI);
|
||||||
|
|
||||||
|
} else if (shape == Shapes.RECTANGLE && points.length == 2) {
|
||||||
|
cr.rectangle(points[0][0], points[0][1], points[1][0] - points[0][0], points[1][1] - points[0][1]);
|
||||||
|
} else if (shape == Shapes.TEXT && points.length == 2) {
|
||||||
|
cr.selectFontFace(this.font.family, this.font.style, this.font.weight);
|
||||||
|
cr.setFontSize(Math.abs(points[1][1] - points[0][1]));
|
||||||
|
cr.moveTo(Math.min(points[0][0], points[1][0]), Math.max(points[0][1], points[1][1]));
|
||||||
|
cr.showText((showTextCursor) ? (this.text + "_") : this.text);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
buildSVG: function(bgColor) {
|
||||||
|
let row = "\n ";
|
||||||
|
let points = this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100]);
|
||||||
|
let color = this.eraser ? bgColor : this.color.to_string();
|
||||||
|
let attributes = `fill="${this.fill ? color : 'transparent'}" ` +
|
||||||
|
`stroke="${this.fill ? 'transparent' : color}" ` +
|
||||||
|
`stroke-width="${this.line.lineWidth}" ` +
|
||||||
|
`stroke-linecap="${LineCapNames[this.line.lineCap].toLowerCase()}" ` +
|
||||||
|
`stroke-linejoin="${LineJoinNames[this.line.lineJoin].toLowerCase()}"`;
|
||||||
|
|
||||||
|
if (this.dash.array[0] > 0 && this.dash.array[1] > 0)
|
||||||
|
attributes += ` stroke-dasharray="${this.dash.array[0]} ${this.dash.array[1]}" stroke-dashoffset="${this.dash.offset}"`;
|
||||||
|
|
||||||
|
if (this.shape == Shapes.NONE || this.shape == Shapes.LINE) {
|
||||||
|
row += `<path ${attributes} d="M${points[0][0]} ${points[0][1]}`;
|
||||||
|
|
||||||
|
for (let i = 1; i < points.length; i++) {
|
||||||
|
row += ` L ${points[i][0]} ${points[i][1]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
row += `${this.fill ? 'z' : ''}"/>`;
|
||||||
|
} else if (this.shape == Shapes.ELLIPSE && points.length == 2) {
|
||||||
|
let r = Math.hypot(points[1][0] - points[0][0], points[1][1] - points[0][1]);
|
||||||
|
row += `<circle ${attributes} cx="${points[0][0]}" cy="${points[0][1]}" r="${r}"/>`;
|
||||||
|
} else if (this.shape == Shapes.RECTANGLE && points.length == 2) {
|
||||||
|
row += `<rect ${attributes} x="${Math.min(points[0][0], points[1][0])}" y="${Math.min(points[0][1], points[1][1])}" ` +
|
||||||
|
`width="${Math.abs(points[1][0] - points[0][0])}" height="${Math.abs(points[1][1] - points[0][1])}"/>`;
|
||||||
|
} else if (this.shape == Shapes.TEXT && points.length == 2) {
|
||||||
|
attributes = `fill="${color}" ` +
|
||||||
|
`stroke="transparent" ` +
|
||||||
|
`font-family="${this.font.family}" ` +
|
||||||
|
`font-size="${Math.abs(points[1][1] - points[0][1])}" ` +
|
||||||
|
`font-weight="${FontWeightNames[this.font.weight].toLowerCase()}" ` +
|
||||||
|
`font-style="${FontStyleNames[this.font.style].toLowerCase()}"`;
|
||||||
|
|
||||||
|
row += `<text ${attributes} x="${Math.min(points[0][0], points[1][0])}" y="${Math.max(points[0][1], points[1][1])}">${this.text}</text>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var HELPER_ANIMATION_TIME = 0.25;
|
||||||
|
|
||||||
|
// DrawingHelper provides the "help osd" (Ctrl + F1)
|
||||||
|
// It uses the same texts as in prefs
|
||||||
|
var DrawingHelper = new Lang.Class({
|
||||||
|
Name: 'DrawingHelper',
|
||||||
|
Extends: St.ScrollView,
|
||||||
|
|
||||||
|
_init: function(params, monitor) {
|
||||||
|
this.parent(params);
|
||||||
|
this.monitor = monitor;
|
||||||
|
this.hide();
|
||||||
|
this.vbox = new St.BoxLayout({ style_class: 'osd-window draw-on-your-screen-helper', vertical: true });
|
||||||
|
this.add_actor(this.vbox);
|
||||||
|
this.vbox.add(new St.Label({ text: _("Global") }));
|
||||||
|
|
||||||
|
let settings = Convenience.getSettings();
|
||||||
|
|
||||||
|
for (let settingKey in Prefs.GLOBAL_KEYBINDINGS) {
|
||||||
|
let hbox = new St.BoxLayout({ vertical: false });
|
||||||
|
if (settingKey.indexOf('-separator-') != -1) {
|
||||||
|
this.vbox.add(hbox);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let [keyval, mods] = Gtk.accelerator_parse(settings.get_strv(settingKey)[0]);
|
||||||
|
hbox.add(new St.Label({ text: _(Prefs.GLOBAL_KEYBINDINGS[settingKey]) }));
|
||||||
|
hbox.add(new St.Label({ text: Gtk.accelerator_get_label(keyval, mods) }), { expand: true });
|
||||||
|
this.vbox.add(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.vbox.add(new St.Label({ text: _("Internal") }));
|
||||||
|
|
||||||
|
for (let desc in Prefs.OTHER_SHORTCUTS) {
|
||||||
|
if (desc.indexOf('-separator-') != -1) {
|
||||||
|
this.vbox.add(new St.BoxLayout({ vertical: false, style_class: 'draw-on-your-screen-separator' }));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let hbox = new St.BoxLayout({ vertical: false });
|
||||||
|
hbox.add(new St.Label({ text: _(desc) }));
|
||||||
|
hbox.add(new St.Label({ text: _(Prefs.OTHER_SHORTCUTS[desc]) }), { expand: true });
|
||||||
|
this.vbox.add(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.vbox.add(new St.BoxLayout({ vertical: false, style_class: 'draw-on-your-screen-separator' }));
|
||||||
|
|
||||||
|
for (let settingKey in Prefs.INTERNAL_KEYBINDINGS) {
|
||||||
|
if (settingKey.indexOf('-separator-') != -1) {
|
||||||
|
this.vbox.add(new St.BoxLayout({ vertical: false, style_class: 'draw-on-your-screen-separator' }));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let hbox = new St.BoxLayout({ vertical: false });
|
||||||
|
let [keyval, mods] = Gtk.accelerator_parse(settings.get_strv(settingKey)[0]);
|
||||||
|
hbox.add(new St.Label({ text: _(Prefs.INTERNAL_KEYBINDINGS[settingKey]) }));
|
||||||
|
hbox.add(new St.Label({ text: Gtk.accelerator_get_label(keyval, mods) }), { expand: true });
|
||||||
|
this.vbox.add(hbox);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showHelp: function() {
|
||||||
|
this.opacity = 0;
|
||||||
|
this.show();
|
||||||
|
|
||||||
|
let maxHeight = this.monitor.height*(3/4);
|
||||||
|
if (this.height > maxHeight)
|
||||||
|
this.vscrollbar_policy = Gtk.PolicyType.ALWAYS;
|
||||||
|
else
|
||||||
|
this.vscrollbar_policy = Gtk.PolicyType.NEVER;
|
||||||
|
this.set_height(Math.min(this.height, maxHeight));
|
||||||
|
this.set_position(this.monitor.x + Math.floor(this.monitor.width / 2 - this.width / 2),
|
||||||
|
this.monitor.y + Math.floor(this.monitor.height / 2 - this.height / 2));
|
||||||
|
|
||||||
|
Tweener.removeTweens(this);
|
||||||
|
Tweener.addTween(this, { opacity: 255,
|
||||||
|
time: HELPER_ANIMATION_TIME,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onComplete: null });
|
||||||
|
},
|
||||||
|
|
||||||
|
hideHelp: function() {
|
||||||
|
Tweener.removeTweens(this);
|
||||||
|
Tweener.addTween(this, { opacity: 0,
|
||||||
|
time: HELPER_ANIMATION_TIME,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onComplete: this.hide.bind(this) });
|
||||||
|
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,278 @@
|
||||||
|
/* jslint esversion: 6 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Abakkk
|
||||||
|
*
|
||||||
|
* This file is part of DrowOnYourScreen, a drawing extension for GNOME Shell.
|
||||||
|
* 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 Gio = imports.gi.Gio;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const OsdWindow = imports.ui.osdWindow;
|
||||||
|
const Extension = imports.misc.extensionUtils.getCurrentExtension();
|
||||||
|
const Convenience = Extension.imports.convenience;
|
||||||
|
const Draw = Extension.imports.draw;
|
||||||
|
const _ = imports.gettext.domain(Extension.metadata["gettext-domain"]).gettext;
|
||||||
|
|
||||||
|
let manager;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
Convenience.initTranslations();
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable() {
|
||||||
|
manager = new AreaManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable() {
|
||||||
|
manager.disable();
|
||||||
|
manager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AreaManager assigns one DrawingArea per monitor (updateAreas()),
|
||||||
|
// distributes keybinding callbacks to the active area
|
||||||
|
// and handles stylesheet and monitor changes.
|
||||||
|
var AreaManager = new Lang.Class({
|
||||||
|
Name: 'AreaManager',
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
this.areas = [];
|
||||||
|
this.drawingHandlers = [];
|
||||||
|
this.activeArea = null;
|
||||||
|
this.enterGicon = new Gio.ThemedIcon({ name: 'applications-graphics-symbolic' });
|
||||||
|
this.leaveGicon = new Gio.ThemedIcon({ name: 'application-exit-symbolic' });
|
||||||
|
|
||||||
|
Main.wm.addKeybinding('toggle-drawing',
|
||||||
|
Convenience.getSettings(),
|
||||||
|
Meta.KeyBindingFlags.NONE,
|
||||||
|
Shell.ActionMode.ALL,
|
||||||
|
this.toggleDrawing.bind(this));
|
||||||
|
|
||||||
|
Main.wm.addKeybinding('erase-drawing',
|
||||||
|
Convenience.getSettings(),
|
||||||
|
Meta.KeyBindingFlags.NONE,
|
||||||
|
Shell.ActionMode.ALL,
|
||||||
|
this.eraseDrawing.bind(this));
|
||||||
|
|
||||||
|
this.updateAreas();
|
||||||
|
this.monitorChangedHandler = Main.layoutManager.connect('monitors-changed', this.updateAreas.bind(this));
|
||||||
|
|
||||||
|
if (Extension.stylesheet) {
|
||||||
|
this.stylesheetMonitor = Extension.stylesheet.monitor(Gio.FileMonitorFlags.NONE, null);
|
||||||
|
this.stylesheetChangedHandler = this.stylesheetMonitor.connect('changed', (monitor, file, otherFile, eventType) => {
|
||||||
|
if ((eventType != 0 && eventType != 3) || !Extension.stylesheet.query_exists(null))
|
||||||
|
return;
|
||||||
|
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
||||||
|
theme.unload_stylesheet(Extension.stylesheet);
|
||||||
|
theme.load_stylesheet(Extension.stylesheet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateAreas: function() {
|
||||||
|
if (this.activeArea)
|
||||||
|
this.toggleDrawing();
|
||||||
|
this.removeAreas();
|
||||||
|
|
||||||
|
this.monitors = Main.layoutManager.monitors;
|
||||||
|
|
||||||
|
for (let i = 0; i < this.monitors.length; i++) {
|
||||||
|
let monitor = this.monitors[i];
|
||||||
|
let helper = new Draw.DrawingHelper({ name: 'drawOnYourSreenHelper' + i }, monitor);
|
||||||
|
let bgContainer = new St.Bin({ name: 'drawOnYourSreenContainer' + i });
|
||||||
|
let area = new Draw.DrawingArea({ name: 'drawOnYourSreenArea' + i }, helper);
|
||||||
|
bgContainer.set_child(area);
|
||||||
|
Main.uiGroup.add_actor(bgContainer);
|
||||||
|
Main.uiGroup.add_actor(helper);
|
||||||
|
bgContainer.set_position(monitor.x, monitor.y);
|
||||||
|
bgContainer.set_size(monitor.width, monitor.height);
|
||||||
|
area.set_position(monitor.x, monitor.y);
|
||||||
|
area.set_size(monitor.width, monitor.height);
|
||||||
|
this.drawingHandlers.push(area.emitter.connect('stop-drawing', this.toggleDrawing.bind(this)));
|
||||||
|
this.drawingHandlers.push(area.emitter.connect('show-osd', this.showOsd.bind(this)));
|
||||||
|
this.areas.push(area);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addInternalKeybindings: function() {
|
||||||
|
this.internalKeybindings = {
|
||||||
|
'undo': this.activeArea.undo.bind(this.activeArea),
|
||||||
|
'redo': this.activeArea.redo.bind(this.activeArea),
|
||||||
|
'delete-last-element': this.activeArea.deleteLastElement.bind(this.activeArea),
|
||||||
|
'save-as-svg': this.activeArea.save.bind(this.activeArea),
|
||||||
|
'toggle-background': this.activeArea.toggleBackground.bind(this.activeArea),
|
||||||
|
'increment-line-width': () => this.activeArea.incrementLineWidth(1),
|
||||||
|
'decrement-line-width': () => this.activeArea.incrementLineWidth(-1),
|
||||||
|
'increment-line-width-more': () => this.activeArea.incrementLineWidth(5),
|
||||||
|
'decrement-line-width-more': () => this.activeArea.incrementLineWidth(-5),
|
||||||
|
'toggle-linejoin': this.activeArea.toggleLineJoin.bind(this.activeArea),
|
||||||
|
'toggle-linecap': this.activeArea.toggleLineCap.bind(this.activeArea),
|
||||||
|
'toggle-dash' : this.activeArea.toggleDash.bind(this.activeArea),
|
||||||
|
'select-none-shape': () => this.activeArea.selectShape(Draw.Shapes.NONE),
|
||||||
|
'select-line-shape': () => this.activeArea.selectShape(Draw.Shapes.LINE),
|
||||||
|
'select-ellipse-shape': () => this.activeArea.selectShape(Draw.Shapes.ELLIPSE),
|
||||||
|
'select-rectangle-shape': () => this.activeArea.selectShape(Draw.Shapes.RECTANGLE),
|
||||||
|
'select-text-shape': () => this.activeArea.selectShape(Draw.Shapes.TEXT),
|
||||||
|
'toggle-font-family': this.activeArea.toggleFontFamily.bind(this.activeArea),
|
||||||
|
'toggle-font-weight': this.activeArea.toggleFontWeight.bind(this.activeArea),
|
||||||
|
'toggle-font-style': this.activeArea.toggleFontStyle.bind(this.activeArea),
|
||||||
|
'toggle-panel-and-dock-visibility': this.togglePanelAndDockOpacity.bind(this),
|
||||||
|
'toggle-help': this.activeArea.toggleHelp.bind(this.activeArea),
|
||||||
|
'open-stylesheet': this.openStylesheetFile.bind(this)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let key in this.internalKeybindings) {
|
||||||
|
Main.wm.addKeybinding(key,
|
||||||
|
Convenience.getSettings(),
|
||||||
|
Meta.KeyBindingFlags.NONE,
|
||||||
|
256,
|
||||||
|
this.internalKeybindings[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i < 10; i++) {
|
||||||
|
Main.wm.addKeybinding('select-color' + i,
|
||||||
|
Convenience.getSettings(),
|
||||||
|
Meta.KeyBindingFlags.NONE,
|
||||||
|
256,
|
||||||
|
() => this.activeArea.selectColor(i));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
removeInternalKeybindings: function() {
|
||||||
|
for (let key in this.internalKeybindings) {
|
||||||
|
Main.wm.removeKeybinding(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i < 10; i++) {
|
||||||
|
Main.wm.removeKeybinding('select-color' + i);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
openStylesheetFile: function() {
|
||||||
|
if (Extension.stylesheet && Extension.stylesheet.query_exists(null))
|
||||||
|
Gio.AppInfo.launch_default_for_uri(Extension.stylesheet.get_uri(), global.create_app_launch_context(0, -1));
|
||||||
|
if (this.activeArea)
|
||||||
|
this.toggleDrawing();
|
||||||
|
},
|
||||||
|
|
||||||
|
eraseDrawing: function() {
|
||||||
|
for (let i = 0; i < this.areas.length; i++) {
|
||||||
|
this.areas[i].erase();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
togglePanelAndDockOpacity: function() {
|
||||||
|
if (this.hiddenList) {
|
||||||
|
for (let i = 0; i < this.hiddenList.length; i++) {
|
||||||
|
this.hiddenList[i].actor.set_opacity(this.hiddenList[i].oldOpacity);
|
||||||
|
}
|
||||||
|
this.hiddenList = null;
|
||||||
|
} else {
|
||||||
|
let activeIndex = this.areas.indexOf(this.activeArea);
|
||||||
|
|
||||||
|
// dash-to-dock
|
||||||
|
let dtdContainers = Main.uiGroup.get_children().filter((actor) => {
|
||||||
|
return actor.name && actor.name == 'dashtodockContainer' &&
|
||||||
|
actor._delegate &&
|
||||||
|
actor._delegate._monitorIndex !== undefined &&
|
||||||
|
actor._delegate._monitorIndex == activeIndex;
|
||||||
|
});
|
||||||
|
|
||||||
|
// for simplicity, we assume that main dash-to-panel panel is displayed on primary monitor
|
||||||
|
// and we hide all secondary panels together if the active area is not on the primary
|
||||||
|
let name = activeIndex == Main.layoutManager.primaryIndex ? 'panelBox' : 'dashtopanelSecondaryPanelBox';
|
||||||
|
let panelBoxes = Main.uiGroup.get_children().filter((actor) => {
|
||||||
|
return actor.name && actor.name == name;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let actorToHide = dtdContainers.concat(panelBoxes);
|
||||||
|
this.hiddenList = [];
|
||||||
|
for (let i = 0; i < actorToHide.length; i++) {
|
||||||
|
this.hiddenList.push({ actor: actorToHide[i], oldOpacity: actorToHide[i].get_opacity() });
|
||||||
|
actorToHide[i].set_opacity(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleDrawing: function() {
|
||||||
|
if (this.activeArea) {
|
||||||
|
if (this.hiddenList)
|
||||||
|
this.togglePanelAndDockOpacity();
|
||||||
|
Main.popModal(this.activeArea);
|
||||||
|
let activeIndex = this.areas.indexOf(this.activeArea);
|
||||||
|
this.removeInternalKeybindings();
|
||||||
|
this.activeArea.reactive = false;
|
||||||
|
this.activeArea.leaveDrawingMode();
|
||||||
|
this.activeArea = null;
|
||||||
|
global.display.set_cursor(Meta.Cursor.DEFAULT);
|
||||||
|
Main.osdWindowManager.show(activeIndex, this.leaveGicon, _("Leaving drawing mode"), null);
|
||||||
|
} else {
|
||||||
|
// avoid to deal with Meta changes (global.display/global.screen)
|
||||||
|
let currentIndex = Main.layoutManager.monitors.indexOf(Main.layoutManager.currentMonitor);
|
||||||
|
// 256 is a custom Shell.ActionMode
|
||||||
|
if (!Main.pushModal(this.areas[currentIndex], { actionMode: 256 | 1 }))
|
||||||
|
return;
|
||||||
|
this.activeArea = this.areas[currentIndex];
|
||||||
|
this.addInternalKeybindings();
|
||||||
|
this.activeArea.reactive = true;
|
||||||
|
this.activeArea.enterDrawingMode();
|
||||||
|
global.display.set_cursor(Meta.Cursor.POINTING_HAND);
|
||||||
|
// increase OSD display time
|
||||||
|
let hideTimeoutSave = OsdWindow.HIDE_TIMEOUT;
|
||||||
|
OsdWindow.HIDE_TIMEOUT = 2000;
|
||||||
|
Main.osdWindowManager.show(currentIndex, this.enterGicon, _("Press Ctrl + F1 for help") + "\n\n" + _("Entering drawing mode"), null);
|
||||||
|
OsdWindow.HIDE_TIMEOUT = hideTimeoutSave;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showOsd: function(emitter, label, level, maxLevel) {
|
||||||
|
let activeIndex = this.areas.indexOf(this.activeArea);
|
||||||
|
if (activeIndex != -1)
|
||||||
|
Main.osdWindowManager.show(activeIndex, this.enterGicon, label, level, maxLevel);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeAreas: function() {
|
||||||
|
for (let i = 0; i < this.areas.length; i++) {
|
||||||
|
let area = this.areas[i];
|
||||||
|
Main.uiGroup.remove_actor(area.get_parent());
|
||||||
|
area.emitter.disconnect(this.drawingHandlers[i]);
|
||||||
|
area.disable();
|
||||||
|
area.get_parent().destroy();
|
||||||
|
}
|
||||||
|
this.areas = [];
|
||||||
|
this.drawingHandlers = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
disable: function() {
|
||||||
|
if (this.stylesheetChangedHandler) {
|
||||||
|
this.stylesheetMonitor.disconnect(this.stylesheetChangedHandler);
|
||||||
|
this.stylesheetChangedHandler = null;
|
||||||
|
}
|
||||||
|
if (this.activeArea)
|
||||||
|
this.toggleDrawing();
|
||||||
|
Main.wm.removeKeybinding('toggle-drawing');
|
||||||
|
Main.wm.removeKeybinding('erase-drawing');
|
||||||
|
this.removeAreas();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,208 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2019-03-04 16:40+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: extension.js
|
||||||
|
msgid "Leaving drawing mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Press Ctrl + F1 for help"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Entering drawing mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: draw.js
|
||||||
|
msgid "Free drawing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Circle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Rectangle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Text"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Dashed line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Full line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Type your text\n"
|
||||||
|
"and press Enter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: prefs.js
|
||||||
|
msgid "Enter/leave drawing mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Erase all drawings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Undo last brushstroke"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Redo last brushstroke"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Erase last brushstroke"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Increment line width"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Decrement line width"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Increment line width even more"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Decrement line width even more"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Change linejoin"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Change linecap"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Dashed line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select circle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select rectangle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select text"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unselect shape (free drawing)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Change font family (generic name)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Change font weight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Change font style"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Hide panel and dock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Add a drawing background"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Save drawing as a SVG file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Open stylesheet.css"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Show help"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Draw"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Left click"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Draw by filling in"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Right click"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Toggle shape"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Center click"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Increment/decrement line width"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Scroll"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select color"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Ctrl+1...9"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select eraser"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Shift key held"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Leave and erase all drawings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Escape key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Start drawing with Super+Alt+D\n"
|
||||||
|
"Then save your beautiful work by taking a screenshot"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Global"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Internal"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "(in drawing mode)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Change the style"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "See stylesheet.css"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"<u>Note</u>: When you save elements made with eraser in a SVG file,\n"
|
||||||
|
"they are colored with background color, transparent if it is disabled.\n"
|
||||||
|
"(See \"Add a drawing background\" or edit the SVG file afterwards)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"<span size=\"small\">This program comes with ABSOLUTELY NO WARRANTY.\n"
|
||||||
|
"See the <a href=\"https://www.gnu.org/licenses/old-licenses/gpl-2.0.html"
|
||||||
|
"\">GNU General Public License, version 2 or later</a> for details.</span>"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Credits"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"name": "Draw On You Screen",
|
||||||
|
"description": "Start drawing with Super+Alt+D and save your beautiful work by taking a screenshot",
|
||||||
|
"version": 1,
|
||||||
|
"uuid": "drawOnYourScreen@abakkk.framagit.org",
|
||||||
|
"url": "https://framagit.org/abakkk/DrawOnYourScreen",
|
||||||
|
"settings-schema": "org.gnome.shell.extensions.draw-on-your-screen",
|
||||||
|
"gettext-domain": "draw-on-your-screen",
|
||||||
|
"shell-version": [
|
||||||
|
"3.26",
|
||||||
|
"3.28",
|
||||||
|
"3.30"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,333 @@
|
||||||
|
/* jslint esversion: 6 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Abakkk
|
||||||
|
*
|
||||||
|
* This file is part of DrowOnYourScreen, a drawing extension for GNOME Shell.
|
||||||
|
* 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 GObject = imports.gi.GObject;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
|
||||||
|
const ExtensionUtils = imports.misc.extensionUtils;
|
||||||
|
const Extension = ExtensionUtils.getCurrentExtension();
|
||||||
|
const Convenience = Extension.imports.convenience;
|
||||||
|
const Metadata = Extension.metadata;
|
||||||
|
const _ = imports.gettext.domain(Extension.metadata["gettext-domain"]).gettext;
|
||||||
|
|
||||||
|
const MARGIN = 10;
|
||||||
|
|
||||||
|
var GLOBAL_KEYBINDINGS = {
|
||||||
|
'toggle-drawing': "Enter/leave drawing mode",
|
||||||
|
'erase-drawing': "Erase all drawings"
|
||||||
|
};
|
||||||
|
|
||||||
|
var INTERNAL_KEYBINDINGS = {
|
||||||
|
'undo': "Undo last brushstroke",
|
||||||
|
'redo': "Redo last brushstroke",
|
||||||
|
'delete-last-element' : "Erase last brushstroke",
|
||||||
|
'-separator-1': '',
|
||||||
|
'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",
|
||||||
|
'toggle-linejoin': "Change linejoin",
|
||||||
|
'toggle-linecap': "Change linecap",
|
||||||
|
'toggle-dash': "Dashed line",
|
||||||
|
'-separator-2': '',
|
||||||
|
'select-line-shape': "Select line",
|
||||||
|
'select-ellipse-shape': "Select circle",
|
||||||
|
'select-rectangle-shape': "Select rectangle",
|
||||||
|
'select-text-shape': "Select text",
|
||||||
|
'select-none-shape': "Unselect shape (free drawing)",
|
||||||
|
'-separator-3': '',
|
||||||
|
'toggle-font-family': "Change font family (generic name)",
|
||||||
|
'toggle-font-weight': "Change font weight",
|
||||||
|
'toggle-font-style': "Change font style",
|
||||||
|
'-separator-4': '',
|
||||||
|
'toggle-panel-and-dock-visibility': "Hide panel and dock",
|
||||||
|
'toggle-background': "Add a drawing background",
|
||||||
|
'-separator-5': '',
|
||||||
|
'save-as-svg': "Save drawing as a SVG file",
|
||||||
|
'open-stylesheet': "Open stylesheet.css",
|
||||||
|
'toggle-help': "Show help"
|
||||||
|
};
|
||||||
|
|
||||||
|
var OTHER_SHORTCUTS = {
|
||||||
|
"Draw": "Left click",
|
||||||
|
"Draw by filling in": "Right click",
|
||||||
|
"Toggle shape": "Center click",
|
||||||
|
"Increment/decrement line width": "Scroll",
|
||||||
|
"Select color": "Ctrl+1...9",
|
||||||
|
"Select eraser": "Shift key held",
|
||||||
|
"Leave and erase all drawings": "Escape key"
|
||||||
|
};
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
Convenience.initTranslations();
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPrefsWidget() {
|
||||||
|
let prefsPage = new PrefsPage();
|
||||||
|
prefsPage.show_all();
|
||||||
|
return prefsPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PrefsPage = new GObject.Class({
|
||||||
|
Name: 'PrefsPage',
|
||||||
|
GTypeName: 'PrefsPage',
|
||||||
|
Extends: Gtk.ScrolledWindow,
|
||||||
|
|
||||||
|
_init: function(params) {
|
||||||
|
this.parent();
|
||||||
|
|
||||||
|
this.settings = Convenience.getSettings();
|
||||||
|
|
||||||
|
let box = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL, margin: MARGIN*3 });
|
||||||
|
this.add(box);
|
||||||
|
|
||||||
|
let textBox1 = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, margin: MARGIN });
|
||||||
|
let text1 = new Gtk.Label({ wrap: true, justify: 2, use_markup: true,
|
||||||
|
label: _("Start drawing with Super+Alt+D\nThen save your beautiful work by taking a screenshot") });
|
||||||
|
textBox1.pack_start(text1, false, false, 0);
|
||||||
|
box.add(textBox1);
|
||||||
|
|
||||||
|
let listBox = new Gtk.ListBox({ selection_mode: 0, hexpand: true, margin_top: 2*MARGIN, margin_bottom: 2*MARGIN });
|
||||||
|
box.add(listBox);
|
||||||
|
|
||||||
|
let styleContext = listBox.get_style_context();
|
||||||
|
styleContext.add_class('background');
|
||||||
|
|
||||||
|
let globalTitleBox = new Gtk.Box({ margin: MARGIN });
|
||||||
|
let globalTitleLabel = new Gtk.Label({ use_markup: true, label: "<b><big>" + _("Global") + " :</big></b>" });
|
||||||
|
globalTitleLabel.set_halign(1);
|
||||||
|
globalTitleBox.pack_start(globalTitleLabel, true, true, 4);
|
||||||
|
listBox.add(globalTitleBox);
|
||||||
|
|
||||||
|
let globalKeybindingsWidget = new KeybindingsWidget(GLOBAL_KEYBINDINGS, this.settings);
|
||||||
|
globalKeybindingsWidget.margin = MARGIN;
|
||||||
|
listBox.add(globalKeybindingsWidget);
|
||||||
|
this.addSeparator(listBox);
|
||||||
|
|
||||||
|
let internalTitleBox = new Gtk.Box({ margin: MARGIN });
|
||||||
|
let internalTitleLabel = new Gtk.Label({ use_markup: true, label: "<b><big>" + _("Internal") + " </big></b>" + _("(in drawing mode)") + " <b><big>:</big></b>" });
|
||||||
|
internalTitleLabel.set_halign(1);
|
||||||
|
internalTitleBox.pack_start(internalTitleLabel, true, true, 4);
|
||||||
|
listBox.add(internalTitleBox);
|
||||||
|
|
||||||
|
listBox.add(new Gtk.Box({ margin_top: MARGIN/2, margin_left: MARGIN, margin_right: MARGIN }));
|
||||||
|
|
||||||
|
for (let desc in OTHER_SHORTCUTS) {
|
||||||
|
if (desc.indexOf('-separator-') != -1) {
|
||||||
|
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 });
|
||||||
|
let otherLabel = new Gtk.Label({ label: _(desc) });
|
||||||
|
otherLabel.set_halign(1);
|
||||||
|
let otherLabel2 = new Gtk.Label({ label: _(OTHER_SHORTCUTS[desc]) });
|
||||||
|
otherBox.pack_start(otherLabel, true, true, 4);
|
||||||
|
otherBox.pack_start(otherLabel2, false, false, 4);
|
||||||
|
listBox.add(otherBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
listBox.add(new Gtk.Box({ margin_top: MARGIN, margin_left: MARGIN, margin_right: MARGIN }));
|
||||||
|
|
||||||
|
let internalKeybindingsWidget = new KeybindingsWidget(INTERNAL_KEYBINDINGS, this.settings);
|
||||||
|
internalKeybindingsWidget.margin = MARGIN;
|
||||||
|
listBox.add(internalKeybindingsWidget);
|
||||||
|
|
||||||
|
let styleBox = new Gtk.Box({ margin_top: MARGIN, margin_left: MARGIN, margin_right: MARGIN, margin_bottom:MARGIN });
|
||||||
|
let styleLabel = new Gtk.Label({ label: _("Change the style") });
|
||||||
|
styleLabel.set_halign(1);
|
||||||
|
let styleLabel2 = new Gtk.Label({ label: _("See stylesheet.css") });
|
||||||
|
styleBox.pack_start(styleLabel, true, true, 4);
|
||||||
|
styleBox.pack_start(styleLabel2, false, false, 4);
|
||||||
|
listBox.add(styleBox);
|
||||||
|
|
||||||
|
let noteBox = new Gtk.Box({ margin_top: MARGIN, margin_left: MARGIN, margin_right: MARGIN, margin_bottom:MARGIN });
|
||||||
|
let noteLabel = new Gtk.Label({
|
||||||
|
use_markup: true,
|
||||||
|
label: _("<u>Note</u>: When you save elements made with eraser in a SVG file,\nthey are colored with background color, transparent if it is disabled.\n(See \"Add a drawing background\" or edit the SVG file afterwards)")
|
||||||
|
});
|
||||||
|
noteLabel.set_halign(1);
|
||||||
|
//let noteLabel2 = new Gtk.Label({ label: _("See notesheet.css") });
|
||||||
|
noteBox.pack_start(noteLabel, true, true, 4);
|
||||||
|
//noteBox.pack_start(noteLabel2, false, false, 4);
|
||||||
|
listBox.add(noteBox);
|
||||||
|
|
||||||
|
this.addSeparator(listBox);
|
||||||
|
|
||||||
|
let licence = _("<span size=\"small\">This program comes with ABSOLUTELY NO WARRANTY.\nSee the <a href=\"https://www.gnu.org/licenses/old-licenses/gpl-2.0.html\">GNU General Public License, version 2 or later</a> for details.</span>");
|
||||||
|
|
||||||
|
let textBox2 = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
|
||||||
|
let text2 = new Gtk.Label({ wrap: true, justify: 2, use_markup: true,
|
||||||
|
label: "<small>Version" + " " + Metadata.version +"</small>\n\n" + "<span><a href=\"" + Metadata.url + "\">" + Metadata.url + "</a></span>" + "\n\n" + licence + "\n" });
|
||||||
|
textBox2.pack_start(text2, false, false, 0);
|
||||||
|
|
||||||
|
let creditBox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });
|
||||||
|
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><u>" + _("Credits") + ":</u></small>" });
|
||||||
|
let rightLabel = new Gtk.Label({ wrap: true, valign: 1, halign: 1, justify: 0, use_markup: true, label: "<small>Abakkk</small>" });
|
||||||
|
leftBox.pack_start(leftLabel, true, true, 0);
|
||||||
|
rightBox.pack_start(rightLabel, true, true, 0);
|
||||||
|
creditBox.pack_start(leftBox, true, true, 5);
|
||||||
|
creditBox.pack_start(rightBox, true, true, 5);
|
||||||
|
textBox2.pack_start(creditBox, false, false, 0);
|
||||||
|
|
||||||
|
box.add(textBox2);
|
||||||
|
|
||||||
|
let children = listBox.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
if (children[i].activatable)
|
||||||
|
children[i].set_activatable(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addSeparator: function(container) {
|
||||||
|
let separatorRow = new Gtk.ListBoxRow({sensitive: false});
|
||||||
|
separatorRow.add(new Gtk.Separator({ margin: MARGIN }));
|
||||||
|
container.add(separatorRow);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// this code comes from Sticky Notes View by Sam Bull, https://extensions.gnome.org/extension/568/notes/
|
||||||
|
const KeybindingsWidget = new GObject.Class({
|
||||||
|
Name: 'Keybindings.Widget',
|
||||||
|
GTypeName: 'KeybindingsWidget',
|
||||||
|
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
|
||||||
|
});
|
||||||
|
keybinding_renderer.connect('accel-edited',
|
||||||
|
Lang.bind(this, function(renderer, iter, key, mods) {
|
||||||
|
let value = Gtk.accelerator_name(key, mods);
|
||||||
|
let [success, iterator ] =
|
||||||
|
this._store.get_iter_from_string(iter);
|
||||||
|
|
||||||
|
if(!success) {
|
||||||
|
printerr("Can't change keybinding");
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = this._store.get_value(iterator, 0);
|
||||||
|
|
||||||
|
this._store.set(
|
||||||
|
iterator,
|
||||||
|
[this._columns.MODS, this._columns.KEY],
|
||||||
|
[mods, key]
|
||||||
|
);
|
||||||
|
this._settings.set_strv(name, [value]);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
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
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,175 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<schemalist gettext-domain="gnome-shell-extensions">
|
||||||
|
<schema path="/org/gnome/shell/extensions/draw-on-your-screen/" id="org.gnome.shell.extensions.draw-on-your-screen">
|
||||||
|
<key type="as" name="toggle-drawing">
|
||||||
|
<default>["<Alt><Super>d"]</default>
|
||||||
|
<summary>toggle drawing</summary>
|
||||||
|
<description>enter or leave drawing mode</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="erase-drawing">
|
||||||
|
<default>["<Alt><Super>e"]</default>
|
||||||
|
<summary>erase drawing</summary>
|
||||||
|
<description>erase drawing</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="undo">
|
||||||
|
<default>["<Primary>z"]</default>
|
||||||
|
<summary>undo</summary>
|
||||||
|
<description>undo</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="redo">
|
||||||
|
<default>["<Primary><Shift>z"]</default>
|
||||||
|
<summary>redo</summary>
|
||||||
|
<description>redo</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="delete-last-element">
|
||||||
|
<default>["Delete"]</default>
|
||||||
|
<summary>delete last element</summary>
|
||||||
|
<description>delete last element</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-background">
|
||||||
|
<default>["<Primary>b"]</default>
|
||||||
|
<summary>toggle background</summary>
|
||||||
|
<description>toggle background</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-panel-and-dock-visibility">
|
||||||
|
<default>["<Primary>h"]</default>
|
||||||
|
<summary>hide or show panel and dock</summary>
|
||||||
|
<description>hide or show panel and dock</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-ellipse-shape">
|
||||||
|
<default>["<Primary>e"]</default>
|
||||||
|
<summary>select cercle</summary>
|
||||||
|
<description>select a cercle</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-rectangle-shape">
|
||||||
|
<default>["<Primary>r"]</default>
|
||||||
|
<summary>select rectangle</summary>
|
||||||
|
<description>select rectangle</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-line-shape">
|
||||||
|
<default>["<Primary>l"]</default>
|
||||||
|
<summary>select line</summary>
|
||||||
|
<description>select a line</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-text-shape">
|
||||||
|
<default>["<Primary>t"]</default>
|
||||||
|
<summary>select text</summary>
|
||||||
|
<description>select text</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-none-shape">
|
||||||
|
<default>["<Primary>u"]</default>
|
||||||
|
<summary>unselect shape (free drawing)</summary>
|
||||||
|
<description>unselect shape (free drawing)</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="increment-line-width">
|
||||||
|
<default>["<Primary>KP_Add"]</default>
|
||||||
|
<summary>increment the line width</summary>
|
||||||
|
<description>increment the line width</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="decrement-line-width">
|
||||||
|
<default>["<Primary>KP_Subtract"]</default>
|
||||||
|
<summary>decrement the line width</summary>
|
||||||
|
<description>decrement the line width</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="increment-line-width-more">
|
||||||
|
<default>["<Primary>Page_Up"]</default>
|
||||||
|
<summary>increment the line width even more</summary>
|
||||||
|
<description>increment the line width even more</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="decrement-line-width-more">
|
||||||
|
<default>["<Primary>Page_Down"]</default>
|
||||||
|
<summary>decrement the line width even more</summary>
|
||||||
|
<description>decrement the line width even more</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-linejoin">
|
||||||
|
<default>["<Primary>j"]</default>
|
||||||
|
<summary>toggle linejoin</summary>
|
||||||
|
<description>toggle linejoin</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-linecap">
|
||||||
|
<default>["<Primary>k"]</default>
|
||||||
|
<summary>toggle linecap</summary>
|
||||||
|
<description>toggle linecap</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-dash">
|
||||||
|
<default>["<Primary>a"]</default>
|
||||||
|
<summary>toggle dash</summary>
|
||||||
|
<description>toggle dash</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color1">
|
||||||
|
<default><![CDATA[['<Primary>KP_1','<Primary>1']]]></default>
|
||||||
|
<summary>select color1</summary>
|
||||||
|
<description>select color1</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color2">
|
||||||
|
<default><![CDATA[['<Primary>KP_2','<Primary>2']]]></default>
|
||||||
|
<summary>select color2</summary>
|
||||||
|
<description>select color2</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color3">
|
||||||
|
<default><![CDATA[['<Primary>KP_3','<Primary>3']]]></default>
|
||||||
|
<summary>select color3</summary>
|
||||||
|
<description>select color3</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color4">
|
||||||
|
<default><![CDATA[['<Primary>KP_4','<Primary>4']]]></default>
|
||||||
|
<summary>select color4</summary>
|
||||||
|
<description>select color4</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color5">
|
||||||
|
<default><![CDATA[['<Primary>KP_5','<Primary>5']]]></default>
|
||||||
|
<summary>select color5</summary>
|
||||||
|
<description>select color5</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color6">
|
||||||
|
<default><![CDATA[['<Primary>KP_6','<Primary>6']]]></default>
|
||||||
|
<summary>select color6</summary>
|
||||||
|
<description>select color6</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color7">
|
||||||
|
<default><![CDATA[['<Primary>KP_7','<Primary>7']]]></default>
|
||||||
|
<summary>select color7</summary>
|
||||||
|
<description>select color7</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color8">
|
||||||
|
<default><![CDATA[['<Primary>KP_8','<Primary>8']]]></default>
|
||||||
|
<summary>select color8</summary>
|
||||||
|
<description>select color8</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="select-color9">
|
||||||
|
<default><![CDATA[['<Primary>KP_9','<Primary>9']]]></default>
|
||||||
|
<summary>select color9</summary>
|
||||||
|
<description>select color9</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-font-family">
|
||||||
|
<default>["<Primary>f"]</default>
|
||||||
|
<summary>toggle font family</summary>
|
||||||
|
<description>toggle font family</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-font-weight">
|
||||||
|
<default>["<Primary>w"]</default>
|
||||||
|
<summary>toggle font weight</summary>
|
||||||
|
<description>toggle font weight</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-font-style">
|
||||||
|
<default>["<Primary>i"]</default>
|
||||||
|
<summary>toggle font style</summary>
|
||||||
|
<description>toggle font style</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="open-stylesheet">
|
||||||
|
<default>["<Primary>o"]</default>
|
||||||
|
<summary>open stylesheet</summary>
|
||||||
|
<description>open stylesheet</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="save-as-svg">
|
||||||
|
<default>["<Primary>s"]</default>
|
||||||
|
<summary>Save drawing as a svg file</summary>
|
||||||
|
<description>Save drawing as a svg file</description>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="toggle-help">
|
||||||
|
<default>["<Primary>F1"]</default>
|
||||||
|
<summary>toggle help</summary>
|
||||||
|
<description>toggle help</description>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Except for the font,
|
||||||
|
* you don't need to restart the extension.
|
||||||
|
* Just save this file and the changes will be applied for your next brushstroke.
|
||||||
|
*
|
||||||
|
* line-join (no string):
|
||||||
|
* 0 : miter, 1 : round, 2 : bevel
|
||||||
|
* line-cap (no string):
|
||||||
|
* 0 : butt, 1 : round, 2 : square
|
||||||
|
*
|
||||||
|
* dash:
|
||||||
|
* dash-array-on is the length of dashes (no dashes if 0, you can put 0.1 to get dots or square according to line-cap)
|
||||||
|
* dash-array-off is the length of gaps (no dashes if 0)
|
||||||
|
*
|
||||||
|
* font:
|
||||||
|
* only one family : no comma separated list of families like "font1, font2, ..., Sans-Serif"
|
||||||
|
* font family can be any font installed, or a generic family name (Serif, Sans-Serif, Monospace, Cursive, Fantasy)
|
||||||
|
* font weight and font style : no upper case when string
|
||||||
|
* weight <= 500 (or lighter, normal, medium) is rendered as normal
|
||||||
|
* weight > 500 (or bolder, bold) is rendered as bold
|
||||||
|
* oblique and italic style support depends on the font family and seem to be rendered identically
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.draw-on-your-screen {
|
||||||
|
-drawing-line-width: 5px;
|
||||||
|
-drawing-line-join: 1;
|
||||||
|
-drawing-line-cap: 1;
|
||||||
|
-drawing-dash-array-on: 5px;
|
||||||
|
-drawing-dash-array-off: 15px;
|
||||||
|
-drawing-dash-offset: 0px;
|
||||||
|
-drawing-color1: HotPink;
|
||||||
|
-drawing-color2: Cyan;
|
||||||
|
-drawing-color3: yellow;
|
||||||
|
-drawing-color4: Orangered;
|
||||||
|
-drawing-color5: Chartreuse;
|
||||||
|
-drawing-color6: DarkViolet;
|
||||||
|
-drawing-color7: #ffffff;
|
||||||
|
-drawing-color8: rgba(130, 130, 130, 0.3);
|
||||||
|
-drawing-color9: rgb(0, 0, 0);
|
||||||
|
-drawing-background-color: #2e3436; /* GS osd_bg_color: #2e3436, GTK Adwaita-dark theme_base_color: #2d2c2e */
|
||||||
|
font-family: Cantarell;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following styles don't affect the drawing,
|
||||||
|
* but the "Ctrl + F1" on-screen-display
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.draw-on-your-screen-helper {
|
||||||
|
margin: 0;
|
||||||
|
spacing: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draw-on-your-screen-helper StBoxLayout {
|
||||||
|
spacing: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draw-on-your-screen-helper StBoxLayout StLabel {
|
||||||
|
text-align: right;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draw-on-your-screen-separator {
|
||||||
|
min-height: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue