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:
abakkk 2020-09-11 04:06:21 +02:00
parent a06d318646
commit 771bad2d59
10 changed files with 225 additions and 97 deletions

View File

@ -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
View File

@ -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();
}, },

View File

@ -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),

111
files.js
View File

@ -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,
_clipboardImagesContains: function(file) {
return this._clipboardImages.some(image => image.file.equal(file));
},
_getImages: function() {
if (this._upToDate)
return this._images;
getImages: function() {
let images = []; let images = [];
let userLocation = Me.drawingSettings.get_string('image-location') || DEFAULT_USER_IMAGE_LOCATION;
let userDirectory = Gio.File.new_for_commandline_arg(userLocation);
[EXAMPLE_IMAGES, USER_IMAGES].forEach(directory => { [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,19 +255,20 @@ 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]);
} }
}); });
} }

View File

@ -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
View File

@ -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) => {

View File

@ -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.

View File

@ -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>["&lt;Primary&gt;v"]</default> <default>["&lt;Primary&gt;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>["&lt;Primary&gt;&lt;Shift&gt;z"]</default> <default>["&lt;Primary&gt;&lt;Shift&gt;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>["&lt;Primary&gt;&lt;Shift&gt;i"]</default> <default>["&lt;Primary&gt;&lt;Alt&gt;i"]</default>
<summary>Change image file</summary> <summary>Change image</summary>
</key>
<key type="as" name="switch-image-file-reverse">
<default>["&lt;Primary&gt;&lt;Alt&gt;&lt;Shift&gt;i"]</default>
<summary>Change image (reverse)</summary>
</key> </key>
<key type="as" name="switch-linecap"> <key type="as" name="switch-linecap">
<default>["&lt;Primary&gt;k"]</default> <default>["&lt;Primary&gt;k"]</default>

View File

@ -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'],
]; ];