improve images again
* Files.Images does the same thing, with just a new accessor (getSorted). * Files.Image is splited and the new subclass manage gicons.
This commit is contained in:
parent
24682db69c
commit
464aae77c6
206
files.js
206
files.js
|
|
@ -73,18 +73,13 @@ Object.keys(ThemedIconNames).forEach(key => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// wrapper around an image file
|
// wrapper around an image file. If not subclassed, it is used with drawing files (.json) and it takes { displayName, contentType, base64, hash } as params.
|
||||||
var Image = new Lang.Class({
|
var Image = new Lang.Class({
|
||||||
Name: 'DrawOnYourScreenImage',
|
Name: 'DrawOnYourScreenImage',
|
||||||
|
|
||||||
_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() {
|
||||||
|
|
@ -100,47 +95,9 @@ var Image = new Lang.Class({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
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() {
|
|
||||||
if (!this._gicon)
|
|
||||||
this._gicon = new Gio.FileIcon({ file: this.thumbnailFile || this.file });
|
|
||||||
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)
|
this._bytes = new GLib.Bytes(GLib.base64_decode(this.base64));
|
||||||
try {
|
|
||||||
// load_bytes available in GLib 2.56+
|
|
||||||
this._bytes = this.file.load_bytes(null)[0];
|
|
||||||
} catch(e) {
|
|
||||||
let [, contents] = this.file.load_contents(null);
|
|
||||||
if (contents instanceof Uint8Array)
|
|
||||||
this._bytes = ByteArray.toGBytes(contents);
|
|
||||||
else
|
|
||||||
this._bytes = contents.toGBytes();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this._bytes = new GLib.Bytes(GLib.base64_decode(this.base64));
|
|
||||||
}
|
|
||||||
return this._bytes;
|
return this._bytes;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -188,7 +145,61 @@ var Image = new Lang.Class({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get images with getPrevious, getNext, or by iterating over it.
|
// Add a gicon generator to Image. It is used with image files and it takes { file, info } as params.
|
||||||
|
const ImageWithGicon = new Lang.Class({
|
||||||
|
Name: 'DrawOnYourScreenImageWithGicon',
|
||||||
|
Extends: Image,
|
||||||
|
|
||||||
|
get displayName() {
|
||||||
|
return this.info.get_display_name();
|
||||||
|
},
|
||||||
|
|
||||||
|
get contentType() {
|
||||||
|
return this.info.get_content_type();
|
||||||
|
},
|
||||||
|
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
|
||||||
|
get gicon() {
|
||||||
|
if (!this._gicon)
|
||||||
|
this._gicon = new Gio.FileIcon({ file: this.thumbnailFile || this.file });
|
||||||
|
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() {
|
||||||
|
if (!this._bytes) {
|
||||||
|
try {
|
||||||
|
// load_bytes available in GLib 2.56+
|
||||||
|
this._bytes = this.file.load_bytes(null)[0];
|
||||||
|
} catch(e) {
|
||||||
|
let [, contents] = this.file.load_contents(null);
|
||||||
|
if (contents instanceof Uint8Array)
|
||||||
|
this._bytes = ByteArray.toGBytes(contents);
|
||||||
|
else
|
||||||
|
this._bytes = contents.toGBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._bytes;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Access images with getPrevious, getNext, getSorted or by iterating over it.
|
||||||
var Images = {
|
var Images = {
|
||||||
_images: [],
|
_images: [],
|
||||||
_clipboardImages: [],
|
_clipboardImages: [],
|
||||||
|
|
@ -198,57 +209,84 @@ var Images = {
|
||||||
return this._clipboardImages.some(image => image.file.equal(file));
|
return this._clipboardImages.some(image => image.file.equal(file));
|
||||||
},
|
},
|
||||||
|
|
||||||
_getImages: function() {
|
// Firstly iterate over the extension directory that contains Example.svg,
|
||||||
|
// secondly iterate over the directory that was configured by the user in prefs,
|
||||||
|
// finally iterate over the images pasted from the clipboard.
|
||||||
|
[Symbol.iterator]: function() {
|
||||||
if (this._upToDate)
|
if (this._upToDate)
|
||||||
return this._images;
|
return this._images.concat(this._clipboardImages)[Symbol.iterator]();
|
||||||
|
|
||||||
let images = [];
|
this._upToDate = true;
|
||||||
let userLocation = Me.drawingSettings.get_string('image-location') || DEFAULT_USER_IMAGE_LOCATION;
|
let oldImages = this._images;
|
||||||
let userDirectory = Gio.File.new_for_commandline_arg(userLocation);
|
let newImages = this._images = [];
|
||||||
|
let clipboardImagesContains = this._clipboardImagesContains.bind(this);
|
||||||
|
let clipboardIterator = this._clipboardImages[Symbol.iterator]();
|
||||||
|
|
||||||
[EXAMPLE_IMAGE_DIRECTORY, userDirectory].forEach(directory => {
|
return {
|
||||||
let enumerator;
|
getExampleEnumerator: function() {
|
||||||
try {
|
try {
|
||||||
enumerator = directory.enumerate_children('standard::,thumbnail::', Gio.FileQueryInfoFlags.NONE, null);
|
return EXAMPLE_IMAGE_DIRECTORY.enumerate_children('standard::,thumbnail::', Gio.FileQueryInfoFlags.NONE, null);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return;
|
return this.getUserEnumerator();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
let info = enumerator.next_file(null);
|
getUserEnumerator: function() {
|
||||||
while (info) {
|
try {
|
||||||
let file = enumerator.get_child(info);
|
let userLocation = Me.drawingSettings.get_string('image-location') || DEFAULT_USER_IMAGE_LOCATION;
|
||||||
|
let userDirectory = Gio.File.new_for_commandline_arg(userLocation);
|
||||||
|
return userDirectory.enumerate_children('standard::,thumbnail::', Gio.FileQueryInfoFlags.NONE, null);
|
||||||
|
} catch(e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get enumerator() {
|
||||||
|
if (this._enumerator === undefined)
|
||||||
|
this._enumerator = this.getExampleEnumerator();
|
||||||
|
else if (this._enumerator && this._enumerator.get_container().equal(EXAMPLE_IMAGE_DIRECTORY) && this._enumerator.is_closed())
|
||||||
|
this._enumerator = this.getUserEnumerator();
|
||||||
|
else if (this._enumerator && this._enumerator.is_closed())
|
||||||
|
this._enumerator = null;
|
||||||
|
|
||||||
if (info.get_content_type().indexOf('image') == 0 && !this._clipboardImagesContains(file)) {
|
return this._enumerator;
|
||||||
let index = this._images.findIndex(image => image.file.equal(file));
|
},
|
||||||
if (index != -1)
|
|
||||||
images.push(this._images[index]);
|
next: function() {
|
||||||
else
|
if (!this.enumerator)
|
||||||
images.push(new Image({ file, info }));
|
return clipboardIterator.next();
|
||||||
|
|
||||||
|
let info = this.enumerator.next_file(null);
|
||||||
|
if (!info) {
|
||||||
|
this.enumerator.close(null);
|
||||||
|
return this.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
info = enumerator.next_file(null);
|
let file = this.enumerator.get_child(info);
|
||||||
|
|
||||||
|
if (info.get_content_type().indexOf('image') == 0 && !clipboardImagesContains(file)) {
|
||||||
|
let image = oldImages.find(image => image.file.equal(file)) || new ImageWithGicon({ file, info });
|
||||||
|
newImages.push(image);
|
||||||
|
return { value: image, done: false };
|
||||||
|
} else {
|
||||||
|
return this.next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enumerator.close(null);
|
};
|
||||||
});
|
|
||||||
|
|
||||||
this._images = images.concat(this._clipboardImages)
|
|
||||||
.sort((a, b) => a.toString().localeCompare(b.toString()));
|
|
||||||
this._upToDate = true;
|
|
||||||
return this._images;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[Symbol.iterator]: function() {
|
getSorted: function() {
|
||||||
return this._getImages()[Symbol.iterator]();
|
return [...this].sort((a, b) => a.toString().localeCompare(b.toString()));
|
||||||
},
|
},
|
||||||
|
|
||||||
getNext: function(currentImage) {
|
getNext: function(currentImage) {
|
||||||
let images = this._getImages();
|
let images = this.getSorted();
|
||||||
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0;
|
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : -1;
|
||||||
return images[index == images.length - 1 ? 0 : index + 1] || null;
|
return images[index == images.length - 1 ? 0 : index + 1] || null;
|
||||||
},
|
},
|
||||||
|
|
||||||
getPrevious: function(currentImage) {
|
getPrevious: function(currentImage) {
|
||||||
let images = this._getImages();
|
let images = this.getSorted();
|
||||||
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0;
|
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0;
|
||||||
return images[index <= 0 ? images.length - 1 : index - 1] || null;
|
return images[index <= 0 ? images.length - 1 : index - 1] || null;
|
||||||
},
|
},
|
||||||
|
|
@ -271,7 +309,7 @@ var Images = {
|
||||||
.filter(file => file.query_exists(null))
|
.filter(file => file.query_exists(null))
|
||||||
.map(file => [file, file.query_info('standard::,thumbnail::', 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], info: pair[1] }));
|
.map(pair => new ImageWithGicon({ file: pair[0], info: pair[1] }));
|
||||||
|
|
||||||
// Prevent duplicated
|
// Prevent duplicated
|
||||||
images.filter(image => !this._clipboardImagesContains(image.file))
|
images.filter(image => !this._clipboardImagesContains(image.file))
|
||||||
|
|
@ -279,10 +317,8 @@ var Images = {
|
||||||
|
|
||||||
if (images.length) {
|
if (images.length) {
|
||||||
this.reset();
|
this.reset();
|
||||||
let allImages = this._getImages();
|
|
||||||
let lastFile = images[images.length - 1].file;
|
let lastFile = images[images.length - 1].file;
|
||||||
let index = allImages.findIndex(image => image.file.equal(lastFile));
|
callback(this._clipboardImages.find(image => image.file.equal(lastFile)));
|
||||||
callback(allImages[index]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
menu.js
2
menu.js
|
|
@ -539,7 +539,7 @@ var DrawingMenu = new Lang.Class({
|
||||||
item.menu.openOld = item.menu.open;
|
item.menu.openOld = item.menu.open;
|
||||||
item.menu.open = (animate) => {
|
item.menu.open = (animate) => {
|
||||||
if (!item.menu.isOpen && item.menu.isEmpty()) {
|
if (!item.menu.isOpen && item.menu.isEmpty()) {
|
||||||
[...Files.Images].forEach(image => {
|
Files.Images.getSorted().forEach(image => {
|
||||||
let subItem = item.menu.addAction(image.toString(), () => {
|
let subItem = item.menu.addAction(image.toString(), () => {
|
||||||
item.label.set_text(image.toString());
|
item.label.set_text(image.toString());
|
||||||
this.area.currentImage = image;
|
this.area.currentImage = image;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue