improve images
* Let the user choose the directory. * Rework of Files.Images. * area.currentImage is now an ... image, not an index. * Add 'switch-image-file-reverse' keybinding. * Add image gicons (from thumbnails) in the submenu. * Images are reset on drawing mode left or on images added from the clipboard.
This commit is contained in:
parent
a06d318646
commit
771bad2d59
|
|
@ -42,7 +42,7 @@ Then save your beautiful work by taking a screenshot.
|
||||||
|
|
||||||
* Insertable images:
|
* Insertable images:
|
||||||
|
|
||||||
Add your images (jpeg, png, svg) to `~/.local/share/drawOnYourScreen/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.
|
||||||
|
|
||||||
* Eraser and SVG:
|
* Eraser and SVG:
|
||||||
|
|
||||||
|
|
|
||||||
43
area.js
43
area.js
|
|
@ -86,7 +86,7 @@ var DrawingArea = new Lang.Class({
|
||||||
this.undoneElements = [];
|
this.undoneElements = [];
|
||||||
this.currentElement = null;
|
this.currentElement = null;
|
||||||
this.currentTool = Shapes.NONE;
|
this.currentTool = Shapes.NONE;
|
||||||
this.currentImage = 0;
|
this.currentImage = null;
|
||||||
this.currentTextRightAligned = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
|
this.currentTextRightAligned = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
|
||||||
let fontName = St.Settings && St.Settings.get().font_name || Convenience.getSettings('org.gnome.desktop.interface').get_string('font-name');
|
let fontName = St.Settings && St.Settings.get().font_name || Convenience.getSettings('org.gnome.desktop.interface').get_string('font-name');
|
||||||
this.currentFont = Pango.FontDescription.from_string(fontName);
|
this.currentFont = Pango.FontDescription.from_string(fontName);
|
||||||
|
|
@ -150,6 +150,17 @@ var DrawingArea = new Lang.Class({
|
||||||
this.colors.push(Clutter.Color.get_static(Clutter.StaticColor.WHITE));
|
this.colors.push(Clutter.Color.get_static(Clutter.StaticColor.WHITE));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get currentImage() {
|
||||||
|
if (!this._currentImage)
|
||||||
|
this._currentImage = Files.Images.getNext(this._currentImage);
|
||||||
|
|
||||||
|
return this._currentImage;
|
||||||
|
},
|
||||||
|
|
||||||
|
set currentImage(image) {
|
||||||
|
this._currentImage = image;
|
||||||
|
},
|
||||||
|
|
||||||
get currentFontFamily() {
|
get currentFontFamily() {
|
||||||
return this.currentFont.get_family();
|
return this.currentFont.get_family();
|
||||||
},
|
},
|
||||||
|
|
@ -188,13 +199,6 @@ var DrawingArea = new Lang.Class({
|
||||||
this.currentFillRule = evenodd ? Cairo.FillRule.EVEN_ODD : Cairo.FillRule.WINDING;
|
this.currentFillRule = evenodd ? Cairo.FillRule.EVEN_ODD : Cairo.FillRule.WINDING;
|
||||||
},
|
},
|
||||||
|
|
||||||
getImages() {
|
|
||||||
let images = Files.Images.getImages();
|
|
||||||
if (!images[this.currentImage])
|
|
||||||
this.currentImage = Math.max(images.length - 1, 0);
|
|
||||||
return images;
|
|
||||||
},
|
|
||||||
|
|
||||||
get fontFamilies() {
|
get fontFamilies() {
|
||||||
if (!this._fontFamilies) {
|
if (!this._fontFamilies) {
|
||||||
let otherFontFamilies = Elements.getAllFontFamilies().filter(family => {
|
let otherFontFamilies = Elements.getAllFontFamilies().filter(family => {
|
||||||
|
|
@ -601,14 +605,11 @@ var DrawingArea = new Lang.Class({
|
||||||
points: []
|
points: []
|
||||||
});
|
});
|
||||||
} else if (this.currentTool == Shapes.IMAGE) {
|
} else if (this.currentTool == Shapes.IMAGE) {
|
||||||
let images = this.getImages();
|
|
||||||
if (!images.length)
|
|
||||||
return;
|
|
||||||
this.currentElement = new Elements.DrawingElement({
|
this.currentElement = new Elements.DrawingElement({
|
||||||
shape: this.currentTool,
|
shape: this.currentTool,
|
||||||
color: this.currentColor.to_string(),
|
color: this.currentColor.to_string(),
|
||||||
eraser: eraser,
|
eraser: eraser,
|
||||||
image: images[this.currentImage],
|
image: this.currentImage,
|
||||||
operator: this.currentOperator,
|
operator: this.currentOperator,
|
||||||
points: []
|
points: []
|
||||||
});
|
});
|
||||||
|
|
@ -988,21 +989,18 @@ var DrawingArea = new Lang.Class({
|
||||||
this.emit('show-osd', null, DisplayStrings.getTextAlignment(this.currentTextRightAligned), "", -1, false);
|
this.emit('show-osd', null, DisplayStrings.getTextAlignment(this.currentTextRightAligned), "", -1, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
switchImageFile: function() {
|
switchImageFile: function(reverse) {
|
||||||
let images = this.getImages();
|
this.currentImage = Files.Images[reverse ? 'getPrevious' : 'getNext'](this.currentImage);
|
||||||
if (!images.length)
|
if (this.currentImage)
|
||||||
return;
|
this.emit('show-osd', this.currentImage.gicon, this.currentImage.toString(), "", -1, false);
|
||||||
if (images.length > 1)
|
|
||||||
this.currentImage = this.currentImage == images.length - 1 ? 0 : this.currentImage + 1;
|
|
||||||
this.emit('show-osd', images[this.currentImage].gicon, images[this.currentImage].toString(), "", -1, false);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
pasteImageFiles: function() {
|
pasteImageFiles: function() {
|
||||||
Files.Images.addImagesFromClipboard((images, index) => {
|
Files.Images.addImagesFromClipboard(lastImage => {
|
||||||
this.currentImage = index;
|
this.currentImage = lastImage;
|
||||||
this.currentTool = Shapes.IMAGE;
|
this.currentTool = Shapes.IMAGE;
|
||||||
this.updatePointerCursor();
|
this.updatePointerCursor();
|
||||||
this.emit('show-osd', images[this.currentImage].gicon, images[this.currentImage].toString(), "", -1, false);
|
this.emit('show-osd', this.currentImage.gicon, this.currentImage.toString(), "", -1, false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1088,6 +1086,7 @@ var DrawingArea = new Lang.Class({
|
||||||
this._redisplay();
|
this._redisplay();
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
this.get_parent().set_background_color(null);
|
this.get_parent().set_background_color(null);
|
||||||
|
Files.Images.reset();
|
||||||
if (save)
|
if (save)
|
||||||
this.savePersistent();
|
this.savePersistent();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,8 @@ const AreaManager = new Lang.Class({
|
||||||
'switch-fill-rule': this.activeArea.switchFillRule.bind(this.activeArea),
|
'switch-fill-rule': this.activeArea.switchFillRule.bind(this.activeArea),
|
||||||
'switch-dash' : this.activeArea.switchDash.bind(this.activeArea),
|
'switch-dash' : this.activeArea.switchDash.bind(this.activeArea),
|
||||||
'switch-fill' : this.activeArea.switchFill.bind(this.activeArea),
|
'switch-fill' : this.activeArea.switchFill.bind(this.activeArea),
|
||||||
'switch-image-file' : this.activeArea.switchImageFile.bind(this.activeArea),
|
'switch-image-file' : this.activeArea.switchImageFile.bind(this.activeArea, false),
|
||||||
|
'switch-image-file-reverse' : this.activeArea.switchImageFile.bind(this.activeArea, true),
|
||||||
'select-none-shape': () => this.activeArea.selectTool(Area.Tools.NONE),
|
'select-none-shape': () => this.activeArea.selectTool(Area.Tools.NONE),
|
||||||
'select-line-shape': () => this.activeArea.selectTool(Area.Tools.LINE),
|
'select-line-shape': () => this.activeArea.selectTool(Area.Tools.LINE),
|
||||||
'select-ellipse-shape': () => this.activeArea.selectTool(Area.Tools.ELLIPSE),
|
'select-ellipse-shape': () => this.activeArea.selectTool(Area.Tools.ELLIPSE),
|
||||||
|
|
|
||||||
117
files.js
117
files.js
|
|
@ -31,8 +31,8 @@ const St = imports.gi.St;
|
||||||
|
|
||||||
const ExtensionUtils = imports.misc.extensionUtils;
|
const ExtensionUtils = imports.misc.extensionUtils;
|
||||||
const Me = ExtensionUtils.getCurrentExtension();
|
const Me = ExtensionUtils.getCurrentExtension();
|
||||||
const EXAMPLE_IMAGES = Me.dir.get_child('data').get_child('images');
|
const EXAMPLE_IMAGE_DIRECTORY = Me.dir.get_child('data').get_child('images');
|
||||||
const USER_IMAGES = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir'], 'images']));
|
const DEFAULT_USER_IMAGE_LOCATION = GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir'], 'images']);
|
||||||
const Clipboard = St.Clipboard.get_default();
|
const Clipboard = St.Clipboard.get_default();
|
||||||
const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD;
|
const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD;
|
||||||
const ICON_DIR = Me.dir.get_child('data').get_child('icons');
|
const ICON_DIR = Me.dir.get_child('data').get_child('icons');
|
||||||
|
|
@ -66,6 +66,11 @@ var Image = new Lang.Class({
|
||||||
_init: function(params) {
|
_init: function(params) {
|
||||||
for (let key in params)
|
for (let key in params)
|
||||||
this[key] = params[key];
|
this[key] = params[key];
|
||||||
|
|
||||||
|
if (this.info) {
|
||||||
|
this.displayName = this.info.get_display_name();
|
||||||
|
this.contentType = this.info.get_content_type();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
toString: function() {
|
toString: function() {
|
||||||
|
|
@ -81,13 +86,31 @@ var Image = new Lang.Class({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
// only called from menu so file exists
|
get thumbnailFile() {
|
||||||
|
if (!this._thumbnailFile) {
|
||||||
|
if (this.info.has_attribute('thumbnail::path') && this.info.get_attribute_boolean('thumbnail::is-valid')) {
|
||||||
|
let thumbnailPath = this.info.get_attribute_as_string('thumbnail::path');
|
||||||
|
this._thumbnailFile = Gio.File.new_for_path(thumbnailPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._thumbnailFile || null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// only called from menu or area so this.file exists
|
||||||
get gicon() {
|
get gicon() {
|
||||||
if (!this._gicon)
|
if (!this._gicon)
|
||||||
this._gicon = new Gio.FileIcon({ file: this.file });
|
this._gicon = new Gio.FileIcon({ file: this.thumbnailFile || this.file });
|
||||||
return this._gicon;
|
return this._gicon;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// use only thumbnails in menu (memory)
|
||||||
|
get thumbnailGicon() {
|
||||||
|
if (this.contentType != 'image/svg+xml' && !this.thumbnailFile)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this.gicon;
|
||||||
|
},
|
||||||
|
|
||||||
get bytes() {
|
get bytes() {
|
||||||
if (!this._bytes) {
|
if (!this._bytes) {
|
||||||
if (this.file)
|
if (this.file)
|
||||||
|
|
@ -95,7 +118,7 @@ var Image = new Lang.Class({
|
||||||
// load_bytes available in GLib 2.56+
|
// load_bytes available in GLib 2.56+
|
||||||
this._bytes = this.file.load_bytes(null)[0];
|
this._bytes = this.file.load_bytes(null)[0];
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
let [success_, contents] = this.file.load_contents(null);
|
let [, contents] = this.file.load_contents(null);
|
||||||
if (contents instanceof Uint8Array)
|
if (contents instanceof Uint8Array)
|
||||||
this._bytes = ByteArray.toGBytes(contents);
|
this._bytes = ByteArray.toGBytes(contents);
|
||||||
else
|
else
|
||||||
|
|
@ -151,34 +174,73 @@ var Image = new Lang.Class({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get images with getPrevious, getNext, or by iterating over it.
|
||||||
var Images = {
|
var Images = {
|
||||||
clipboardImages: [],
|
_images: [],
|
||||||
|
_clipboardImages: [],
|
||||||
|
_upToDate: false,
|
||||||
|
|
||||||
getImages: function() {
|
_clipboardImagesContains: function(file) {
|
||||||
let images = [];
|
return this._clipboardImages.some(image => image.file.equal(file));
|
||||||
|
},
|
||||||
|
|
||||||
|
_getImages: function() {
|
||||||
|
if (this._upToDate)
|
||||||
|
return this._images;
|
||||||
|
|
||||||
[EXAMPLE_IMAGES, USER_IMAGES].forEach(directory => {
|
let images = [];
|
||||||
|
let userLocation = Me.drawingSettings.get_string('image-location') || DEFAULT_USER_IMAGE_LOCATION;
|
||||||
|
let userDirectory = Gio.File.new_for_commandline_arg(userLocation);
|
||||||
|
|
||||||
|
[EXAMPLE_IMAGE_DIRECTORY, userDirectory].forEach(directory => {
|
||||||
let enumerator;
|
let enumerator;
|
||||||
try {
|
try {
|
||||||
enumerator = directory.enumerate_children('standard::display-name,standard::content-type', Gio.FileQueryInfoFlags.NONE, null);
|
enumerator = directory.enumerate_children('standard::,thumbnail::', Gio.FileQueryInfoFlags.NONE, null);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileInfo = enumerator.next_file(null);
|
let info = enumerator.next_file(null);
|
||||||
while (fileInfo) {
|
while (info) {
|
||||||
if (fileInfo.get_content_type().indexOf('image') == 0)
|
let file = enumerator.get_child(info);
|
||||||
images.push(new Image({ file: enumerator.get_child(fileInfo), contentType: fileInfo.get_content_type(), displayName: fileInfo.get_display_name() }));
|
|
||||||
fileInfo = enumerator.next_file(null);
|
if (info.get_content_type().indexOf('image') == 0 && !this._clipboardImagesContains(file)) {
|
||||||
|
let index = this._images.findIndex(image => image.file.equal(file));
|
||||||
|
if (index != -1)
|
||||||
|
images.push(this._images[index]);
|
||||||
|
else
|
||||||
|
images.push(new Image({ file, info }));
|
||||||
|
}
|
||||||
|
|
||||||
|
info = enumerator.next_file(null);
|
||||||
}
|
}
|
||||||
enumerator.close(null);
|
enumerator.close(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
images.sort((a, b) => {
|
this._images = images.concat(this._clipboardImages)
|
||||||
return a.displayName.localeCompare(b.displayName);
|
.sort((a, b) => a.toString().localeCompare(b.toString()));
|
||||||
});
|
this._upToDate = true;
|
||||||
|
return this._images;
|
||||||
return images.concat(this.clipboardImages);
|
},
|
||||||
|
|
||||||
|
[Symbol.iterator]: function() {
|
||||||
|
return this._getImages()[Symbol.iterator]();
|
||||||
|
},
|
||||||
|
|
||||||
|
getNext: function(currentImage) {
|
||||||
|
let images = this._getImages();
|
||||||
|
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0;
|
||||||
|
return images[index == images.length - 1 ? 0 : index + 1] || null;
|
||||||
|
},
|
||||||
|
|
||||||
|
getPrevious: function(currentImage) {
|
||||||
|
let images = this._getImages();
|
||||||
|
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0;
|
||||||
|
return images[index <= 0 ? images.length - 1 : index - 1] || null;
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function() {
|
||||||
|
this._upToDate = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
addImagesFromClipboard: function(callback) {
|
addImagesFromClipboard: function(callback) {
|
||||||
|
|
@ -193,20 +255,21 @@ var Images = {
|
||||||
let images = lines.filter(line => !!line)
|
let images = lines.filter(line => !!line)
|
||||||
.map(line => Gio.File.new_for_commandline_arg(line))
|
.map(line => Gio.File.new_for_commandline_arg(line))
|
||||||
.filter(file => file.query_exists(null))
|
.filter(file => file.query_exists(null))
|
||||||
.map(file => [file, file.query_info('standard::display-name,standard::content-type', Gio.FileQueryInfoFlags.NONE, null)])
|
.map(file => [file, file.query_info('standard::,thumbnail::', Gio.FileQueryInfoFlags.NONE, null)])
|
||||||
.filter(pair => pair[1].get_content_type().indexOf('image') == 0)
|
.filter(pair => pair[1].get_content_type().indexOf('image') == 0)
|
||||||
.map(pair => new Image({ file: pair[0], contentType: pair[1].get_content_type(), displayName: pair[1].get_display_name() }));
|
.map(pair => new Image({ file: pair[0], info: pair[1] }));
|
||||||
|
|
||||||
// Prevent duplicated
|
// Prevent duplicated
|
||||||
images.filter(image => !this.clipboardImages.map(clipboardImage => clipboardImage.file).some(clipboardFile => clipboardFile.equal(image.file)))
|
images.filter(image => !this._clipboardImagesContains(image.file))
|
||||||
.forEach(image => this.clipboardImages.push(image));
|
.forEach(image => this._clipboardImages.push(image));
|
||||||
|
|
||||||
if (images.length) {
|
if (images.length) {
|
||||||
|
this.reset();
|
||||||
|
let allImages = this._getImages();
|
||||||
let lastFile = images[images.length - 1].file;
|
let lastFile = images[images.length - 1].file;
|
||||||
let allImages = this.getImages();
|
|
||||||
let index = allImages.findIndex(image => image.file.equal(lastFile));
|
let index = allImages.findIndex(image => image.file.equal(lastFile));
|
||||||
callback(allImages, index);
|
callback(allImages[index]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Draw On Your Screen\n"
|
"Project-Id-Version: Draw On Your Screen\n"
|
||||||
"Report-Msgid-Bugs-To: https://framagit.org/abakkk/DrawOnYourScreen/issues\n"
|
"Report-Msgid-Bugs-To: https://framagit.org/abakkk/DrawOnYourScreen/issues\n"
|
||||||
"POT-Creation-Date: 2020-09-09 08:40+0200\n"
|
"POT-Creation-Date: 2020-09-11 03:43+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -502,6 +502,12 @@ msgstr ""
|
||||||
msgid "The line width in pixels"
|
msgid "The line width in pixels"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Image location"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "The location of the directory in which the image tool picks"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Color palettes"
|
msgid "Color palettes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -544,6 +550,9 @@ msgstr ""
|
||||||
msgid "Open previous drawing"
|
msgid "Open previous drawing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Paste images from the clipboard"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Redo last brushstroke"
|
msgid "Redo last brushstroke"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -640,7 +649,10 @@ msgstr ""
|
||||||
msgid "Change font weight"
|
msgid "Change font weight"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Change image file"
|
msgid "Change image"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Change image (reverse)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Change linecap"
|
msgid "Change linecap"
|
||||||
|
|
|
||||||
80
menu.js
80
menu.js
|
|
@ -262,12 +262,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
this.fontSection = fontSection;
|
this.fontSection = fontSection;
|
||||||
|
|
||||||
let imageSection = new PopupMenu.PopupMenuSection();
|
let imageSection = new PopupMenu.PopupMenuSection();
|
||||||
let images = this.area.getImages();
|
this._addImageSubMenuItem(imageSection);
|
||||||
if (images.length) {
|
|
||||||
if (this.area.currentImage > images.length - 1)
|
|
||||||
this.area.currentImage = images.length - 1;
|
|
||||||
this._addSubMenuItem(imageSection, null, images, this.area, 'currentImage');
|
|
||||||
}
|
|
||||||
this._addSeparator(imageSection);
|
this._addSeparator(imageSection);
|
||||||
this.menu.addMenuItem(imageSection);
|
this.menu.addMenuItem(imageSection);
|
||||||
imageSection.itemActivated = () => {};
|
imageSection.itemActivated = () => {};
|
||||||
|
|
@ -398,34 +393,27 @@ var DrawingMenu = new Lang.Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
_addSubMenuItem: function(menu, icon, obj, target, targetProperty, callback) {
|
_addSubMenuItem: function(menu, icon, obj, target, targetProperty, callback) {
|
||||||
if (targetProperty == 'currentImage')
|
|
||||||
icon = obj[target[targetProperty]].gicon;
|
|
||||||
let item = new PopupMenu.PopupSubMenuMenuItem(String(obj[target[targetProperty]]), icon ? true : false);
|
let item = new PopupMenu.PopupSubMenuMenuItem(String(obj[target[targetProperty]]), icon ? true : false);
|
||||||
if (icon && icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon))
|
if (icon && icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon))
|
||||||
item.icon.set_gicon(icon);
|
item.icon.set_gicon(icon);
|
||||||
else if (icon)
|
else if (icon)
|
||||||
item.icon.set_icon_name(icon);
|
item.icon.set_icon_name(icon);
|
||||||
|
|
||||||
item.menu.itemActivated = () => {
|
item.menu.itemActivated = item.menu.close;
|
||||||
item.menu.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
|
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
|
||||||
for (let i in obj) {
|
Object.keys(obj).forEach(key => {
|
||||||
let text;
|
let text;
|
||||||
if (targetProperty == 'currentFontWeight')
|
if (targetProperty == 'currentFontWeight')
|
||||||
text = `<span font_weight="${i}">${obj[i]}</span>`;
|
text = `<span font_weight="${key}">${obj[key]}</span>`;
|
||||||
else if (targetProperty == 'currentFontStyle')
|
else if (targetProperty == 'currentFontStyle')
|
||||||
text = `<span font_style="${DisplayStrings.FontStyleMarkup[i]}">${obj[i]}</span>`;
|
text = `<span font_style="${DisplayStrings.FontStyleMarkup[key]}">${obj[key]}</span>`;
|
||||||
else
|
else
|
||||||
text = String(obj[i]);
|
text = String(obj[key]);
|
||||||
|
|
||||||
let iCaptured = Number(i);
|
|
||||||
let subItem = item.menu.addAction(text, () => {
|
let subItem = item.menu.addAction(text, () => {
|
||||||
item.label.set_text(String(obj[iCaptured]));
|
item.label.set_text(String(obj[key]));
|
||||||
target[targetProperty] = iCaptured;
|
target[targetProperty] = Number(key);
|
||||||
if (targetProperty == 'currentImage')
|
|
||||||
item.icon.set_gicon(obj[iCaptured].gicon);
|
|
||||||
if (callback)
|
if (callback)
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
|
@ -434,13 +422,14 @@ var DrawingMenu = new Lang.Class({
|
||||||
getActor(subItem).connect('key-focus-in', updateSubMenuAdjustment);
|
getActor(subItem).connect('key-focus-in', updateSubMenuAdjustment);
|
||||||
|
|
||||||
// change the display order of tools
|
// change the display order of tools
|
||||||
if (obj == DisplayStrings.Tool && i == this.drawingTools.POLYGON)
|
if (obj == DisplayStrings.Tool && Number(key) == this.drawingTools.POLYGON)
|
||||||
item.menu.moveMenuItem(subItem, 4);
|
item.menu.moveMenuItem(subItem, 4);
|
||||||
else if (obj == DisplayStrings.Tool && i == this.drawingTools.POLYLINE)
|
else if (obj == DisplayStrings.Tool && Number(key) == this.drawingTools.POLYLINE)
|
||||||
item.menu.moveMenuItem(subItem, 5);
|
item.menu.moveMenuItem(subItem, 5);
|
||||||
}
|
});
|
||||||
return GLib.SOURCE_REMOVE;
|
return GLib.SOURCE_REMOVE;
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.addMenuItem(item);
|
menu.addMenuItem(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -449,9 +438,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
let item = new PopupMenu.PopupSubMenuMenuItem(text, true);
|
let item = new PopupMenu.PopupSubMenuMenuItem(text, true);
|
||||||
item.icon.set_gicon(Files.Icons.PALETTE);
|
item.icon.set_gicon(Files.Icons.PALETTE);
|
||||||
|
|
||||||
item.menu.itemActivated = () => {
|
item.menu.itemActivated = item.menu.close;
|
||||||
item.menu.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
|
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
|
||||||
this.area.palettes.forEach(palette => {
|
this.area.palettes.forEach(palette => {
|
||||||
|
|
@ -468,6 +455,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
});
|
});
|
||||||
return GLib.SOURCE_REMOVE;
|
return GLib.SOURCE_REMOVE;
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.addMenuItem(item);
|
menu.addMenuItem(item);
|
||||||
return item;
|
return item;
|
||||||
},
|
},
|
||||||
|
|
@ -478,9 +466,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
item.icon.set_gicon(Files.Icons.COLOR);
|
item.icon.set_gicon(Files.Icons.COLOR);
|
||||||
item.icon.set_style(`color:${this.area.currentColor.to_string().slice(0, 7)};`);
|
item.icon.set_style(`color:${this.area.currentColor.to_string().slice(0, 7)};`);
|
||||||
|
|
||||||
item.menu.itemActivated = () => {
|
item.menu.itemActivated = item.menu.close;
|
||||||
item.menu.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
this._populateColorSubMenu();
|
this._populateColorSubMenu();
|
||||||
menu.addMenuItem(item);
|
menu.addMenuItem(item);
|
||||||
|
|
@ -508,9 +494,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
let item = new PopupMenu.PopupSubMenuMenuItem(DisplayStrings.getFontFamily(this.area.currentFontFamily), true);
|
let item = new PopupMenu.PopupSubMenuMenuItem(DisplayStrings.getFontFamily(this.area.currentFontFamily), true);
|
||||||
item.icon.set_icon_name(icon);
|
item.icon.set_icon_name(icon);
|
||||||
|
|
||||||
item.menu.itemActivated = () => {
|
item.menu.itemActivated = item.menu.close;
|
||||||
item.menu.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
item.menu.openOld = item.menu.open;
|
item.menu.openOld = item.menu.open;
|
||||||
item.menu.open = (animate) => {
|
item.menu.open = (animate) => {
|
||||||
|
|
@ -531,6 +515,30 @@ var DrawingMenu = new Lang.Class({
|
||||||
menu.addMenuItem(item);
|
menu.addMenuItem(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_addImageSubMenuItem: function(menu, images) {
|
||||||
|
let item = new PopupMenu.PopupSubMenuMenuItem(this.area.currentImage.toString(), true);
|
||||||
|
item.icon.set_gicon(this.area.currentImage.gicon);
|
||||||
|
|
||||||
|
item.menu.itemActivated = item.menu.close;
|
||||||
|
|
||||||
|
item.menu.openOld = item.menu.open;
|
||||||
|
item.menu.open = (animate) => {
|
||||||
|
if (!item.menu.isOpen && item.menu.isEmpty()) {
|
||||||
|
[...Files.Images].forEach(image => {
|
||||||
|
let subItem = item.menu.addAction(image.toString(), () => {
|
||||||
|
item.label.set_text(image.toString());
|
||||||
|
this.area.currentImage = image;
|
||||||
|
item.icon.set_gicon(image.gicon);
|
||||||
|
}, image.thumbnailGicon || undefined);
|
||||||
|
getActor(subItem).connect('key-focus-in', updateSubMenuAdjustment);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
item.menu.openOld();
|
||||||
|
};
|
||||||
|
|
||||||
|
menu.addMenuItem(item);
|
||||||
|
},
|
||||||
|
|
||||||
_addDrawingNameItem: function(menu) {
|
_addDrawingNameItem: function(menu) {
|
||||||
this.drawingNameMenuItem = new PopupMenu.PopupMenuItem('', { reactive: false, activate: false });
|
this.drawingNameMenuItem = new PopupMenu.PopupMenuItem('', { reactive: false, activate: false });
|
||||||
this.drawingNameMenuItem.setSensitive(false);
|
this.drawingNameMenuItem.setSensitive(false);
|
||||||
|
|
@ -554,9 +562,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
item.setSensitive(Boolean(Files.getJsons().length));
|
item.setSensitive(Boolean(Files.getJsons().length));
|
||||||
item.icon.set_icon_name('document-open-symbolic');
|
item.icon.set_icon_name('document-open-symbolic');
|
||||||
|
|
||||||
item.menu.itemActivated = () => {
|
item.menu.itemActivated = item.menu.close;
|
||||||
item.menu.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
item.menu.openOld = item.menu.open;
|
item.menu.openOld = item.menu.open;
|
||||||
item.menu.open = (animate) => {
|
item.menu.open = (animate) => {
|
||||||
|
|
@ -609,9 +615,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
this.saveDrawingSubMenu = item.menu;
|
this.saveDrawingSubMenu = item.menu;
|
||||||
item.icon.set_icon_name('document-save-symbolic');
|
item.icon.set_icon_name('document-save-symbolic');
|
||||||
|
|
||||||
item.menu.itemActivated = () => {
|
item.menu.itemActivated = item.menu.close;
|
||||||
item.menu.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
item.menu.openOld = item.menu.open;
|
item.menu.openOld = item.menu.open;
|
||||||
item.menu.open = (animate) => {
|
item.menu.open = (animate) => {
|
||||||
|
|
|
||||||
43
prefs.js
43
prefs.js
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
const Atk = imports.gi.Atk;
|
const Atk = imports.gi.Atk;
|
||||||
const Gdk = imports.gi.Gdk;
|
const Gdk = imports.gi.Gdk;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const GObject = imports.gi.GObject;
|
const GObject = imports.gi.GObject;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
|
|
@ -268,6 +269,14 @@ const DrawingPage = new GObject.Class({
|
||||||
dashOffsetRow.addWidget(dashOffsetButton);
|
dashOffsetRow.addWidget(dashOffsetButton);
|
||||||
toolsListBox.add(dashOffsetRow);
|
toolsListBox.add(dashOffsetRow);
|
||||||
|
|
||||||
|
let imageLocationRow = new PrefRow({ label: this.schema.get_key('image-location').get_summary() });
|
||||||
|
let imageLocationButton = new FileChooserButton({ action: Gtk.FileChooserAction.SELECT_FOLDER,
|
||||||
|
name: this.schema.get_key('image-location').get_summary(),
|
||||||
|
tooltip_text: this.schema.get_key('image-location').get_description() });
|
||||||
|
this.settings.bind('image-location', imageLocationButton, 'location', 0);
|
||||||
|
imageLocationRow.addWidget(imageLocationButton);
|
||||||
|
toolsListBox.add(imageLocationRow);
|
||||||
|
|
||||||
let resetButton = new Gtk.Button({ label: _("Reset settings"), halign: Gtk.Align.CENTER });
|
let resetButton = new Gtk.Button({ label: _("Reset settings"), halign: Gtk.Align.CENTER });
|
||||||
resetButton.get_style_context().add_class('destructive-action');
|
resetButton.get_style_context().add_class('destructive-action');
|
||||||
resetButton.connect('clicked', () => this.schema.list_keys().forEach(key => this.settings.reset(key)));
|
resetButton.connect('clicked', () => this.schema.list_keys().forEach(key => this.settings.reset(key)));
|
||||||
|
|
@ -565,8 +574,7 @@ const ColorStringButton = new GObject.Class({
|
||||||
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',
|
||||||
GObject.ParamFlags.READWRITE,
|
GObject.ParamFlags.READWRITE, 'black')
|
||||||
'black')
|
|
||||||
},
|
},
|
||||||
|
|
||||||
get color_string() {
|
get color_string() {
|
||||||
|
|
@ -593,6 +601,37 @@ const ColorStringButton = new GObject.Class({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const FileChooserButton = new GObject.Class({
|
||||||
|
Name: 'DrawOnYourScreenFileChooserButton',
|
||||||
|
GTypeName: 'DrawOnYourScreenFileChooserButton',
|
||||||
|
Extends: Gtk.FileChooserButton,
|
||||||
|
Properties: {
|
||||||
|
'location': GObject.ParamSpec.string('location', 'location', 'location',
|
||||||
|
GObject.ParamFlags.READWRITE, '')
|
||||||
|
},
|
||||||
|
|
||||||
|
get location() {
|
||||||
|
return this.get_file().get_path();
|
||||||
|
},
|
||||||
|
|
||||||
|
set location(location) {
|
||||||
|
if (!location) {
|
||||||
|
this.unselect_all();
|
||||||
|
if (this.get_file())
|
||||||
|
this.set_file(Gio.File.new_for_path('aFileThatDoesNotExist'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = Gio.File.new_for_commandline_arg(location);
|
||||||
|
if (file.query_exists(null))
|
||||||
|
this.set_file(file);
|
||||||
|
},
|
||||||
|
|
||||||
|
vfunc_file_set: function(args) {
|
||||||
|
this.notify('location');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 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: 'DrawOnYourScreenKeybindings.Widget',
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -87,6 +87,11 @@
|
||||||
<summary>Grid overlay line width</summary>
|
<summary>Grid overlay line width</summary>
|
||||||
<description>The line width in pixels</description>
|
<description>The line width in pixels</description>
|
||||||
</key>
|
</key>
|
||||||
|
<key type="s" name="image-location">
|
||||||
|
<default>""</default>
|
||||||
|
<summary>Image location</summary>
|
||||||
|
<description>The location of the directory in which the image tool picks</description>
|
||||||
|
</key>
|
||||||
<key type="a(sas)" name="palettes">
|
<key type="a(sas)" name="palettes">
|
||||||
<default>
|
<default>
|
||||||
[
|
[
|
||||||
|
|
@ -148,7 +153,7 @@
|
||||||
</key>
|
</key>
|
||||||
<key type="as" name="paste-image-files">
|
<key type="as" name="paste-image-files">
|
||||||
<default>["<Primary>v"]</default>
|
<default>["<Primary>v"]</default>
|
||||||
<summary>Paste image files from the clipboard</summary>
|
<summary>Paste images from the clipboard</summary>
|
||||||
</key>
|
</key>
|
||||||
<key type="as" name="redo">
|
<key type="as" name="redo">
|
||||||
<default>["<Primary><Shift>z"]</default>
|
<default>["<Primary><Shift>z"]</default>
|
||||||
|
|
@ -284,8 +289,12 @@
|
||||||
<summary>Change font weight</summary>
|
<summary>Change font weight</summary>
|
||||||
</key>
|
</key>
|
||||||
<key type="as" name="switch-image-file">
|
<key type="as" name="switch-image-file">
|
||||||
<default>["<Primary><Shift>i"]</default>
|
<default>["<Primary><Alt>i"]</default>
|
||||||
<summary>Change image file</summary>
|
<summary>Change image</summary>
|
||||||
|
</key>
|
||||||
|
<key type="as" name="switch-image-file-reverse">
|
||||||
|
<default>["<Primary><Alt><Shift>i"]</default>
|
||||||
|
<summary>Change image (reverse)</summary>
|
||||||
</key>
|
</key>
|
||||||
<key type="as" name="switch-linecap">
|
<key type="as" name="switch-linecap">
|
||||||
<default>["<Primary>k"]</default>
|
<default>["<Primary>k"]</default>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,8 @@ var INTERNAL_KEYBINDINGS = [
|
||||||
['switch-fill', 'switch-fill-rule', 'switch-color-palette', 'switch-color-palette-reverse'],
|
['switch-fill', 'switch-fill-rule', 'switch-color-palette', 'switch-color-palette-reverse'],
|
||||||
['increment-line-width', 'increment-line-width-more', 'decrement-line-width', 'decrement-line-width-more',
|
['increment-line-width', 'increment-line-width-more', 'decrement-line-width', 'decrement-line-width-more',
|
||||||
'switch-linejoin', 'switch-linecap', 'switch-dash'],
|
'switch-linejoin', 'switch-linecap', 'switch-dash'],
|
||||||
['switch-font-family', 'switch-font-family-reverse', 'switch-font-weight', 'switch-font-style', 'switch-text-alignment', 'switch-image-file'],
|
['switch-font-family', 'switch-font-family-reverse', 'switch-font-weight', 'switch-font-style', 'switch-text-alignment'],
|
||||||
|
['switch-image-file', 'switch-image-file-reverse', 'paste-image-files'],
|
||||||
['toggle-panel-and-dock-visibility', 'toggle-background', 'toggle-grid', 'toggle-square-area'],
|
['toggle-panel-and-dock-visibility', 'toggle-background', 'toggle-grid', 'toggle-square-area'],
|
||||||
['open-next-json', 'open-previous-json', 'save-as-json', 'save-as-svg', 'open-preferences', 'toggle-help'],
|
['open-next-json', 'open-previous-json', 'save-as-json', 'save-as-svg', 'open-preferences', 'toggle-help'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue