Issue #645: Support clipboard to paste images

This commit is contained in:
juliandescottes 2017-08-07 00:51:58 +02:00 committed by Julian Descottes
parent 5e6280301d
commit b9423bc831
2 changed files with 92 additions and 19 deletions

View File

@ -5,9 +5,23 @@
this.reset();
};
ns.BaseSelection.prototype.stringify = function () {
return JSON.stringify({
pixels: this.pixels,
time: this.time
});
};
ns.BaseSelection.prototype.parse = function (str) {
var selectionData = JSON.parse(str);
this.pixels = selectionData.pixels;
this.time = selectionData.time;
};
ns.BaseSelection.prototype.reset = function () {
this.pixels = [];
this.hasPastedContent = false;
this.time = -1;
};
ns.BaseSelection.prototype.move = function (colDiff, rowDiff) {
@ -30,5 +44,8 @@
});
this.hasPastedContent = true;
// Keep track of the selection time to compare between local selection and
// paste event selections.
this.time = Date.now();
};
})();

View File

@ -22,12 +22,14 @@
$.subscribe(Events.SELECTION_PASTE, this.paste.bind(this));
var shortcuts = pskl.service.keyboard.Shortcuts;
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.PASTE, this.paste.bind(this));
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.CUT, this.cut.bind(this));
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.COPY, this.copy.bind(this));
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.DELETE, this.onDeleteShortcut_.bind(this));
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.COMMIT, this.commit.bind(this));
// These 3 events should be handled by a new separated service
window.addEventListener('cut', this.cut.bind(this), true);
window.addEventListener('copy', this.copy.bind(this), true);
window.addEventListener('paste', this.paste.bind(this), true);
$.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this));
};
@ -78,29 +80,90 @@
scope : this,
replay : {
type : SELECTION_REPLAY.ERASE,
pixels : JSON.parse(JSON.stringify(pixels.slice(0)))
pixels : JSON.parse(JSON.stringify(pixels))
}
});
};
ns.SelectionManager.prototype.cut = function() {
if (this.currentSelection) {
ns.SelectionManager.prototype.copy = function(event) {
if (this.currentSelection && this.piskelController.getCurrentFrame()) {
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
event.clipboardData.setData('text/plain', this.currentSelection.stringify());
event.preventDefault();
}
};
ns.SelectionManager.prototype.cut = function(event) {
if (this.currentSelection && this.piskelController.getCurrentFrame()) {
// Put cut target into the selection:
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
event.clipboardData.setData('text/plain', JSON.stringify(this.currentSelection));
event.preventDefault();
this.erase();
}
};
ns.SelectionManager.prototype.paste = function() {
if (!this.currentSelection || !this.currentSelection.hasPastedContent) {
if (window.localStorage.getItem('piskel.clipboard')) {
this.currentSelection = JSON.parse(window.localStorage.getItem('piskel.clipboard'));
} else {
var items = event.clipboardData.items;
try {
for (var i = 0 ; i < items.length ; i++) {
var item = items[i];
if (/^image/i.test(item.type)) {
this.pasteImage_(item);
event.stopPropagation();
return;
}
if (/^text\/plain/i.test(item.type)) {
this.pasteText_(item);
event.stopPropagation();
return;
}
}
} catch (e) {
// Some of the clipboard APIs are not available on Safari/IE
// Allow Piskel to fallback on local currentSelection pasting.
}
var pixels = this.currentSelection.pixels;
// temporarily keeping this code path for tests and fallbacks.
if (this.currentSelection && this.currentSelection.hasPastedContent) {
this.pastePixelsOnCurrentFrame_(this.currentSelection.pixels);
}
};
ns.SelectionManager.prototype.pasteImage_ = function(clipboardItem) {
var blob = clipboardItem.getAsFile();
pskl.utils.FileUtils.readImageFile(blob, function (image) {
pskl.app.fileDropperService.dropPosition_ = {x: 0, y: 0};
pskl.app.fileDropperService.onImageLoaded_(image, blob);
}.bind(this));
};
ns.SelectionManager.prototype.pasteText_ = function(clipboardItem) {
var blob = clipboardItem.getAsString(function (selectionString) {
var selectionData = JSON.parse(selectionString);
var time = selectionData.time;
var pixels = selectionData.pixels;
if (this.currentSelection && this.currentSelection.time >= time) {
// If the local selection is newer or equal to the one coming from the clipboard event
// use the local one. The reason is that the "move" information is only updated locally
// without synchronizing it to the clipboard.
// TODO: the selection should store the origin of the selection and the selection itself
// separately.
pixels = this.currentSelection.pixels;
}
if (pixels) {
// If the current clipboard data is some random text, pixels will not be defined.
this.pastePixelsOnCurrentFrame_(pixels);
}
}.bind(this));
};
ns.SelectionManager.prototype.pastePixelsOnCurrentFrame_ = function (pixels) {
var frame = this.piskelController.getCurrentFrame();
this.pastePixels_(frame, pixels);
@ -146,13 +209,6 @@
});
};
ns.SelectionManager.prototype.copy = function() {
if (this.currentSelection && this.piskelController.getCurrentFrame()) {
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
window.localStorage.setItem('piskel.clipboard', JSON.stringify(this.currentSelection));
}
};
/**
* @private
*/