Merge branch 'dev' into 'master'

Dev

See merge request abakkk/DrawOnYourScreen!17
This commit is contained in:
abakkk 2020-09-27 19:35:29 +02:00
commit 6e99e380cb
10 changed files with 70 additions and 42 deletions

7
NEWS
View File

@ -1,5 +1,10 @@
v8 - September 2020
===================
Nothing.
v7 - September 2020 v7 - September 2020
===================== ===================
* Can import GIMP palettes. * Can import GIMP palettes.
* Can color SVG images. * Can color SVG images.

View File

@ -3,7 +3,7 @@
Start drawing with Super+Alt+D. Start drawing with Super+Alt+D.
Then save your beautiful work by taking a screenshot. Then save your beautiful work by taking a screenshot.
![](https://framagit.org/abakkk/DrawOnYourScreen/raw/ressources/screenshot.jpg) ![](https://framagit.org/abakkk/DrawOnYourScreen/raw/media/screenshot.jpg)
## Features ## Features
@ -28,6 +28,12 @@ Then save your beautiful work by taking a screenshot.
## Tips and tricks ## Tips and tricks
* Power is nothing without control:
The `Ctrl` key provides an extra functionality for each tool.
![Range of Ctrl key possibilities](https://framagit.org/abakkk/DrawOnYourScreen/-/raw/media/ctrl.webm)
* Draw arrows: * Draw arrows:
Intersect two lines and curve the second thanks to the `Ctrl` key. Intersect two lines and curve the second thanks to the `Ctrl` key.
@ -38,12 +44,14 @@ Then save your beautiful work by taking a screenshot.
Hold the `Shift` key while starting moving. Hold the `Shift` key while starting moving.
![How to duplicate an element](https://framagit.org/abakkk/DrawOnYourScreen/-/raw/ressources/duplicate.webm) ![How to duplicate an element](https://framagit.org/abakkk/DrawOnYourScreen/-/raw/media/duplicate.webm)
* Insertable images: * Insertable images:
You can insert images (jpeg, png, svg) in your drawings. By default images are sought in `~/.local/share/drawOnYourScreen/images/` but the location is configurable in the preferences. Another way is to copy-past the images from Nautilus or any clipboard source by using the usual `Ctrl + V` shortcut inside the drawing mode. You can insert images (jpeg, png, svg) in your drawings. By default images are sought in `~/.local/share/drawOnYourScreen/images/` but the location is configurable in the preferences. Another way is to copy-past the images from Nautilus or any clipboard source by using the usual `Ctrl + V` shortcut inside the drawing mode.
![How to add images from Nautilus](https://framagit.org/abakkk/DrawOnYourScreen/-/raw/media/ctrl-plus-v.webm)
* Eraser and SVG: * Eraser and SVG:
There is no eraser in SVG so when you export elements made with the eraser to a SVG file, they are colored with the background color, transparent if it is disabled. See `“Add a drawing background”` or edit the SVG file afterwards. There is no eraser in SVG so when you export elements made with the eraser to a SVG file, they are colored with the background color, transparent if it is disabled. See `“Add a drawing background”` or edit the SVG file afterwards.
@ -54,5 +62,7 @@ Then save your beautiful work by taking a screenshot.
* Color Picker extension: * Color Picker extension:
If the GNOME Shell built-in color picker is too basic for you, have a look at the [Color Picker extension](https://extensions.gnome.org/extension/3396/color-picker), which let's you select the pixel accurately, preview the color and adjust its values. Once installed and enabled, it will be transparently integrated into DrawOnYourScreen. If the GNOME Shell built-in color picker is too basic for you, have a look at the [Color Picker extension](https://extensions.gnome.org/extension/3396/color-picker), which let's you select the pixel accurately, preview the color and adjust its values. Once installed and enabled, it will be transparently integrated into DrawOnYourScreen.
![Color Picker extension in action](https://framagit.org/abakkk/DrawOnYourScreen/-/raw/media/color-picker-extension.jpg)

View File

@ -85,7 +85,7 @@ const getColorFromString = function(string, fallback) {
// It creates and manages a DrawingElement for each "brushstroke". // It creates and manages a DrawingElement for each "brushstroke".
// It handles pointer/mouse/(touch?) events and some keyboard events. // It handles pointer/mouse/(touch?) events and some keyboard events.
var DrawingArea = new Lang.Class({ var DrawingArea = new Lang.Class({
Name: 'DrawOnYourScreenDrawingArea', Name: `${Me.uuid}.DrawingArea`,
Extends: St.DrawingArea, Extends: St.DrawingArea,
Signals: { 'show-osd': { param_types: [Gio.Icon.$gtype, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_DOUBLE, GObject.TYPE_BOOLEAN] }, Signals: { 'show-osd': { param_types: [Gio.Icon.$gtype, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_DOUBLE, GObject.TYPE_BOOLEAN] },
'update-action-mode': {}, 'update-action-mode': {},

View File

@ -27,6 +27,8 @@ const Lang = imports.lang;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const PangoCairo = imports.gi.PangoCairo; const PangoCairo = imports.gi.PangoCairo;
const Me = imports.misc.extensionUtils.getCurrentExtension();
var Shapes = { NONE: 0, LINE: 1, ELLIPSE: 2, RECTANGLE: 3, TEXT: 4, POLYGON: 5, POLYLINE: 6, IMAGE: 7 }; var Shapes = { NONE: 0, LINE: 1, ELLIPSE: 2, RECTANGLE: 3, TEXT: 4, POLYGON: 5, POLYLINE: 6, IMAGE: 7 };
var Transformations = { TRANSLATION: 0, ROTATION: 1, SCALE_PRESERVE: 2, STRETCH: 3, REFLECTION: 4, INVERSION: 5 }; var Transformations = { TRANSLATION: 0, ROTATION: 1, SCALE_PRESERVE: 2, STRETCH: 3, REFLECTION: 4, INVERSION: 5 };
@ -70,7 +72,7 @@ var DrawingElement = function(params) {
// It can be converted into a cairo path as well as a svg element. // It can be converted into a cairo path as well as a svg element.
// See DrawingArea._startDrawing() to know its params. // See DrawingArea._startDrawing() to know its params.
const _DrawingElement = new Lang.Class({ const _DrawingElement = new Lang.Class({
Name: 'DrawOnYourScreenDrawingElement', Name: `${Me.uuid}.DrawingElement`,
_init: function(params) { _init: function(params) {
for (let key in params) for (let key in params)
@ -624,7 +626,7 @@ const _DrawingElement = new Lang.Class({
}); });
const TextElement = new Lang.Class({ const TextElement = new Lang.Class({
Name: 'DrawOnYourScreenTextElement', Name: `${Me.uuid}.TextElement`,
Extends: _DrawingElement, Extends: _DrawingElement,
toJSON: function() { toJSON: function() {
@ -764,7 +766,7 @@ const TextElement = new Lang.Class({
}); });
const ImageElement = new Lang.Class({ const ImageElement = new Lang.Class({
Name: 'DrawOnYourScreenImageElement', Name: `${Me.uuid}.ImageElement`,
Extends: _DrawingElement, Extends: _DrawingElement,
toJSON: function() { toJSON: function() {

View File

@ -53,7 +53,7 @@ function init() {
} }
const Extension = new Lang.Class({ const Extension = new Lang.Class({
Name: 'DrawOnYourScreenExtension', Name: `${Me.uuid}.Extension`,
_init: function() { _init: function() {
Convenience.initTranslations(); Convenience.initTranslations();
@ -81,7 +81,7 @@ const Extension = new Lang.Class({
// distributes keybinding callbacks to the active area // distributes keybinding callbacks to the active area
// and handles stylesheet and monitor changes. // and handles stylesheet and monitor changes.
const AreaManager = new Lang.Class({ const AreaManager = new Lang.Class({
Name: 'DrawOnYourScreenAreaManager', Name: `${Me.uuid}.AreaManager`,
_init: function() { _init: function() {
this.areas = []; this.areas = [];
@ -560,7 +560,7 @@ const AreaManager = new Lang.Class({
// The same as the original, without forcing a ratio of 1. // The same as the original, without forcing a ratio of 1.
const OsdWindowConstraint = new Lang.Class({ const OsdWindowConstraint = new Lang.Class({
Name: 'DrawOnYourScreenOsdWindowConstraint', Name: `${Me.uuid}.OsdWindowConstraint`,
Extends: OsdWindow.OsdWindowConstraint, Extends: OsdWindow.OsdWindowConstraint,
vfunc_update_allocation: function(actor, actorBox) { vfunc_update_allocation: function(actor, actorBox) {
@ -582,7 +582,7 @@ const OsdWindowConstraint = new Lang.Class({
}); });
const DrawingIndicator = new Lang.Class({ const DrawingIndicator = new Lang.Class({
Name: 'DrawOnYourScreenIndicator', Name: `${Me.uuid}.Indicator`,
_init: function() { _init: function() {
let [menuAlignment, dontCreateMenu] = [0, true]; let [menuAlignment, dontCreateMenu] = [0, true];

View File

@ -98,7 +98,7 @@ const replaceColor = function (contents, color) {
// Wrapper around image data. If not subclassed, it is used when loading in the area an image element for a drawing file (.json) // Wrapper around image data. If not subclassed, it is used when loading in the area an image element for a drawing file (.json)
// and it takes { displayName, contentType, base64, hash } as params. // and it takes { displayName, contentType, base64, hash } as params.
var Image = new Lang.Class({ var Image = new Lang.Class({
Name: 'DrawOnYourScreenImage', Name: `${Me.uuid}.Image`,
_init: function(params) { _init: function(params) {
for (let key in params) for (let key in params)
@ -193,7 +193,7 @@ var Image = new Lang.Class({
// Add a gicon generator to Image. It is used with image files and it takes { file, info } as params. // Add a gicon generator to Image. It is used with image files and it takes { file, info } as params.
const ImageWithGicon = new Lang.Class({ const ImageWithGicon = new Lang.Class({
Name: 'DrawOnYourScreenImageWithGicon', Name: `${Me.uuid}.ImageWithGicon`,
Extends: Image, Extends: Image,
get displayName() { get displayName() {
@ -247,7 +247,7 @@ const ImageWithGicon = new Lang.Class({
// It is directly generated from a Json object, without an image file. It takes { bytes, displayName, gicon } as params. // It is directly generated from a Json object, without an image file. It takes { bytes, displayName, gicon } as params.
const ImageFromJson = new Lang.Class({ const ImageFromJson = new Lang.Class({
Name: 'DrawOnYourScreenImageFromJson', Name: `${Me.uuid}.ImageFromJson`,
Extends: Image, Extends: Image,
contentType: 'image/svg+xml', contentType: 'image/svg+xml',
@ -394,7 +394,7 @@ var Images = {
// Wrapper around a json file (drawing saves). // Wrapper around a json file (drawing saves).
var Json = new Lang.Class({ var Json = new Lang.Class({
Name: 'DrawOnYourScreenJson', Name: `${Me.uuid}.Json`,
_init: function(params) { _init: function(params) {
for (let key in params) for (let key in params)

View File

@ -44,7 +44,7 @@ const MEDIA_KEYS_KEYS = ['screenshot', 'screenshot-clip', 'area-screenshot', 'ar
// DrawingHelper provides the "help osd" (Ctrl + F1) // DrawingHelper provides the "help osd" (Ctrl + F1)
// It uses the same texts as in prefs // It uses the same texts as in prefs
var DrawingHelper = new Lang.Class({ var DrawingHelper = new Lang.Class({
Name: 'DrawOnYourScreenDrawingHelper', Name: `${Me.uuid}.DrawingHelper`,
Extends: St.ScrollView, Extends: St.ScrollView,
_init: function(params, monitor) { _init: function(params, monitor) {

14
menu.js
View File

@ -139,10 +139,11 @@ var DisplayStrings = {
}; };
var DrawingMenu = new Lang.Class({ var DrawingMenu = new Lang.Class({
Name: 'DrawOnYourScreenDrawingMenu', Name: `${Me.uuid}.DrawingMenu`,
_init: function(area, monitor, drawingTools) { _init: function(area, monitor, drawingTools) {
this.area = area; this.area = area;
this.monitor = monitor;
this.drawingTools = drawingTools; this.drawingTools = drawingTools;
let side = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL ? St.Side.RIGHT : St.Side.LEFT; let side = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL ? St.Side.RIGHT : St.Side.LEFT;
@ -151,8 +152,8 @@ var DrawingMenu = new Lang.Class({
this.menuManager.addMenu(this.menu); this.menuManager.addMenu(this.menu);
Main.layoutManager.uiGroup.add_actor(this.menu.actor); Main.layoutManager.uiGroup.add_actor(this.menu.actor);
this.menu.actor.add_style_class_name('background-menu draw-on-your-screen-menu'); this.menu.actor.add_style_class_name('background-menu draw-on-your-screen-menu');
this.menu.actor.set_style('max-height:' + monitor.height + 'px;');
this.menu.actor.hide(); this.menu.actor.hide();
this.hasSeparators = monitor.height >= 750; this.hasSeparators = monitor.height >= 750;
@ -190,6 +191,11 @@ var DrawingMenu = new Lang.Class({
this.area.updateActionMode(); this.area.updateActionMode();
this.area.grab_key_focus(); this.area.grab_key_focus();
} }
let workArea = Main.layoutManager.getWorkAreaForMonitor(this.monitor.index);
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let maxHeight = Math.round(workArea.height / scaleFactor);
this.menu.actor.set_style(`max-height:${maxHeight}px;`);
}, },
popup: function() { popup: function() {
@ -736,7 +742,7 @@ const updateSubMenuAdjustment = function(itemActor) {
// An action button that uses upstream dash item tooltips. // An action button that uses upstream dash item tooltips.
const ActionButton = new Lang.Class({ const ActionButton = new Lang.Class({
Name: 'DrawOnYourScreenDrawingMenuActionButton', Name: `${Me.uuid}.DrawingMenuActionButton`,
Extends: St.Bin, Extends: St.Bin,
_labelShowing: false, _labelShowing: false,
_resetHoverTimeoutId: 0, _resetHoverTimeoutId: 0,
@ -781,7 +787,7 @@ const ActionButton = new Lang.Class({
// based on searchItem.js, https://github.com/leonardo-bartoli/gnome-shell-extension-Recents // based on searchItem.js, https://github.com/leonardo-bartoli/gnome-shell-extension-Recents
const Entry = new Lang.Class({ const Entry = new Lang.Class({
Name: 'DrawOnYourScreenDrawingMenuEntry', Name: `${Me.uuid}.DrawingMenuEntry`,
_init: function(params) { _init: function(params) {
this.params = params; this.params = params;

View File

@ -18,5 +18,5 @@
"3.36", "3.36",
"3.38" "3.38"
], ],
"version": 7 "version": 8
} }

View File

@ -44,6 +44,11 @@ const _GTK = imports.gettext.domain('gtk30').gettext;
const MARGIN = 10; const MARGIN = 10;
const ROWBOX_MARGIN_PARAMS = { margin_top: MARGIN / 2, margin_bottom: MARGIN / 2, margin_left: MARGIN, margin_right: MARGIN }; const ROWBOX_MARGIN_PARAMS = { margin_top: MARGIN / 2, margin_bottom: MARGIN / 2, margin_left: MARGIN, margin_right: MARGIN };
// GTypeName is not sanitized in GS 3.28-
const sanitizeGType = function(name) {
return `Gjs_${name.replace(/@/gi, '_at_').replace(/[^a-z0-9+_-]/gi, '_')}`;
}
function init() { function init() {
Convenience.initTranslations(); Convenience.initTranslations();
} }
@ -63,8 +68,8 @@ function buildPrefsWidget() {
} }
const TopStack = new GObject.Class({ const TopStack = new GObject.Class({
Name: 'DrawOnYourScreenTopStack', Name: `${Me.uuid}.TopStack`,
GTypeName: 'DrawOnYourScreenTopStack', GTypeName: sanitizeGType(`${Me.uuid}-TopStack`),
Extends: Gtk.Stack, Extends: Gtk.Stack,
_init: function(params) { _init: function(params) {
@ -82,8 +87,8 @@ const TopStack = new GObject.Class({
}); });
const AboutPage = new GObject.Class({ const AboutPage = new GObject.Class({
Name: 'DrawOnYourScreenAboutPage', Name: `${Me.uuid}.AboutPage`,
GTypeName: 'DrawOnYourScreenAboutPage', GTypeName: sanitizeGType(`${Me.uuid}-AboutPage`),
Extends: Gtk.ScrolledWindow, Extends: Gtk.ScrolledWindow,
_init: function(params) { _init: function(params) {
@ -136,8 +141,8 @@ const AboutPage = new GObject.Class({
}); });
const DrawingPage = new GObject.Class({ const DrawingPage = new GObject.Class({
Name: 'DrawOnYourScreenDrawingPage', Name: `${Me.uuid}.DrawingPage`,
GTypeName: 'DrawOnYourScreenDrawingPage', GTypeName: sanitizeGType(`${Me.uuid}-DrawingPage`),
Extends: Gtk.ScrolledWindow, Extends: Gtk.ScrolledWindow,
_init: function(params) { _init: function(params) {
@ -389,8 +394,8 @@ const DrawingPage = new GObject.Class({
}); });
const PrefsPage = new GObject.Class({ const PrefsPage = new GObject.Class({
Name: 'DrawOnYourScreenPrefsPage', Name: `${Me.uuid}.PrefsPage`,
GTypeName: 'DrawOnYourScreenPrefsPage', GTypeName: sanitizeGType(`${Me.uuid}-PrefsPage`),
Extends: Gtk.ScrolledWindow, Extends: Gtk.ScrolledWindow,
_init: function(params) { _init: function(params) {
@ -503,8 +508,8 @@ const PrefsPage = new GObject.Class({
}); });
const Frame = new GObject.Class({ const Frame = new GObject.Class({
Name: 'DrawOnYourScreenFrame', Name: `${Me.uuid}.Frame`,
GTypeName: 'DrawOnYourScreenFrame', GTypeName: sanitizeGType(`${Me.uuid}-Frame`),
Extends: Gtk.Frame, Extends: Gtk.Frame,
_init: function(params) { _init: function(params) {
@ -519,8 +524,8 @@ const Frame = new GObject.Class({
}); });
const PrefRow = new GObject.Class({ const PrefRow = new GObject.Class({
Name: 'DrawOnYourScreenPrefRow', Name: `${Me.uuid}.PrefRow`,
GTypeName: 'DrawOnYourScreenPrefRow', GTypeName: sanitizeGType(`${Me.uuid}-PrefRow`),
Extends: Gtk.ListBoxRow, Extends: Gtk.ListBoxRow,
_init: function(params) { _init: function(params) {
@ -564,8 +569,8 @@ const PrefRow = new GObject.Class({
}); });
const PixelSpinButton = new GObject.Class({ const PixelSpinButton = new GObject.Class({
Name: 'DrawOnYourScreenPixelSpinButton', Name: `${Me.uuid}.PixelSpinButton`,
GTypeName: 'DrawOnYourScreenPixelSpinButton', GTypeName: sanitizeGType(`${Me.uuid}-PixelSpinButton`),
Extends: Gtk.SpinButton, Extends: Gtk.SpinButton,
Properties: { Properties: {
'range': GObject.param_spec_variant('range', 'range', 'GSettings range', 'range': GObject.param_spec_variant('range', 'range', 'GSettings range',
@ -604,8 +609,8 @@ const PixelSpinButton = new GObject.Class({
// A color button that can be easily bound with a color string setting. // A color button that can be easily bound with a color string setting.
const ColorStringButton = new GObject.Class({ const ColorStringButton = new GObject.Class({
Name: 'DrawOnYourScreenColorStringButton', Name: `${Me.uuid}.ColorStringButton`,
GTypeName: 'DrawOnYourScreenColorStringButton', GTypeName: sanitizeGType(`${Me.uuid}-ColorStringButton`),
Extends: Gtk.ColorButton, Extends: Gtk.ColorButton,
Properties: { Properties: {
'color-string': GObject.ParamSpec.string('color-string', 'colorString', 'A string that describes the color', 'color-string': GObject.ParamSpec.string('color-string', 'colorString', 'A string that describes the color',
@ -637,8 +642,8 @@ const ColorStringButton = new GObject.Class({
}); });
const FileChooserButton = new GObject.Class({ const FileChooserButton = new GObject.Class({
Name: 'DrawOnYourScreenFileChooserButton', Name: `${Me.uuid}.FileChooserButton`,
GTypeName: 'DrawOnYourScreenFileChooserButton', GTypeName: sanitizeGType(`${Me.uuid}-FileChooserButton`),
Extends: Gtk.FileChooserButton, Extends: Gtk.FileChooserButton,
Properties: { Properties: {
'location': GObject.ParamSpec.string('location', 'location', 'location', 'location': GObject.ParamSpec.string('location', 'location', 'location',
@ -669,8 +674,8 @@ const FileChooserButton = new GObject.Class({
// this code comes from Sticky Notes View by Sam Bull, https://extensions.gnome.org/extension/568/notes/ // this code comes from Sticky Notes View by Sam Bull, https://extensions.gnome.org/extension/568/notes/
const KeybindingsWidget = new GObject.Class({ const KeybindingsWidget = new GObject.Class({
Name: 'DrawOnYourScreenKeybindings.Widget', Name: `${Me.uuid}.KeybindingsWidget`,
GTypeName: 'DrawOnYourScreenKeybindingsWidget', GTypeName: sanitizeGType(`${Me.uuid}-KeybindingsWidget`),
Extends: Gtk.Box, Extends: Gtk.Box,
_init: function(settingKeys, settings) { _init: function(settingKeys, settings) {