[Editor] Add the possibility to paste an image from the clipboard (bug 1848317)
This commit is contained in:
parent
4b2eebf32e
commit
2dd6f07b57
@ -464,6 +464,31 @@ class AnnotationEditorLayer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paste some content into a new editor.
|
||||
* @param {number} mode
|
||||
* @param {Object} params
|
||||
*/
|
||||
pasteEditor(mode, params) {
|
||||
this.#uiManager.updateToolbar(mode);
|
||||
this.#uiManager.updateMode(mode);
|
||||
|
||||
const { offsetX, offsetY } = this.#getCenterPoint();
|
||||
const id = this.getNextId();
|
||||
const editor = this.#createNewEditor({
|
||||
parent: this,
|
||||
id,
|
||||
x: offsetX,
|
||||
y: offsetY,
|
||||
uiManager: this.#uiManager,
|
||||
isCentered: true,
|
||||
...params,
|
||||
});
|
||||
if (editor) {
|
||||
this.add(editor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new editor
|
||||
* @param {Object} data
|
||||
@ -504,10 +529,7 @@ class AnnotationEditorLayer {
|
||||
return editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add a new editor.
|
||||
*/
|
||||
addNewEditor() {
|
||||
#getCenterPoint() {
|
||||
const { x, y, width, height } = this.div.getBoundingClientRect();
|
||||
const tlX = Math.max(0, x);
|
||||
const tlY = Math.max(0, y);
|
||||
@ -520,11 +542,15 @@ class AnnotationEditorLayer {
|
||||
? [centerX, centerY]
|
||||
: [centerY, centerX];
|
||||
|
||||
return { offsetX, offsetY };
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add a new editor.
|
||||
*/
|
||||
addNewEditor() {
|
||||
this.#createAndAddNewEditor(
|
||||
{
|
||||
offsetX,
|
||||
offsetY,
|
||||
},
|
||||
this.#getCenterPoint(),
|
||||
/* isCentered = */ true
|
||||
);
|
||||
}
|
||||
|
@ -140,6 +140,26 @@ class AnnotationEditor {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this kind of editor is able to handle the given mime type for
|
||||
* pasting.
|
||||
* @param {string} mime
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isHandlingMimeForPasting(_mime) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the data from the clipboard item and delegate the creation of the
|
||||
* editor to the parent.
|
||||
* @param {DataTransferItem} item
|
||||
* @param {AnnotationEditorLayer} parent
|
||||
*/
|
||||
static paste(item, parent) {
|
||||
unreachable("Not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the properties to update in the UI for this editor.
|
||||
* @returns {Array}
|
||||
|
@ -30,6 +30,8 @@ class StampEditor extends AnnotationEditor {
|
||||
|
||||
#bitmapUrl = null;
|
||||
|
||||
#bitmapFile = null;
|
||||
|
||||
#canvas = null;
|
||||
|
||||
#observer = null;
|
||||
@ -45,6 +47,7 @@ class StampEditor extends AnnotationEditor {
|
||||
constructor(params) {
|
||||
super({ ...params, name: "stampEditor" });
|
||||
this.#bitmapUrl = params.bitmapUrl;
|
||||
this.#bitmapFile = params.bitmapFile;
|
||||
}
|
||||
|
||||
static get supportedTypes() {
|
||||
@ -64,10 +67,26 @@ class StampEditor extends AnnotationEditor {
|
||||
return shadow(
|
||||
this,
|
||||
"supportedTypes",
|
||||
types.map(type => `image/${type}`).join(",")
|
||||
types.map(type => `image/${type}`)
|
||||
);
|
||||
}
|
||||
|
||||
static get supportedTypesStr() {
|
||||
return shadow(this, "supportedTypesStr", this.supportedTypes.join(","));
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
static isHandlingMimeForPasting(mime) {
|
||||
return this.supportedTypes.includes(mime);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
static paste(item, parent) {
|
||||
parent.pasteEditor(AnnotationEditorType.STAMP, {
|
||||
bitmapFile: item.getAsFile(),
|
||||
});
|
||||
}
|
||||
|
||||
#getBitmapDone() {
|
||||
this._uiManager.enableWaiting(false);
|
||||
if (this.#canvas) {
|
||||
@ -115,6 +134,29 @@ class StampEditor extends AnnotationEditor {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.#bitmapFile) {
|
||||
const file = this.#bitmapFile;
|
||||
this.#bitmapFile = null;
|
||||
this._uiManager.enableWaiting(true);
|
||||
this.#bitmapPromise = this._uiManager.imageManager
|
||||
.getFromFile(file)
|
||||
.then(data => {
|
||||
this.#bitmapPromise = null;
|
||||
if (!data) {
|
||||
this.remove();
|
||||
return;
|
||||
}
|
||||
({
|
||||
bitmap: this.#bitmap,
|
||||
id: this.#bitmapId,
|
||||
isSvg: this.#isSvg,
|
||||
} = data);
|
||||
this.#createCanvas();
|
||||
})
|
||||
.finally(() => this.#getBitmapDone());
|
||||
return;
|
||||
}
|
||||
|
||||
const input = document.createElement("input");
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
input.hidden = true;
|
||||
@ -122,7 +164,7 @@ class StampEditor extends AnnotationEditor {
|
||||
document.body.append(input);
|
||||
}
|
||||
input.type = "file";
|
||||
input.accept = StampEditor.supportedTypes;
|
||||
input.accept = StampEditor.supportedTypesStr;
|
||||
this.#bitmapPromise = new Promise(resolve => {
|
||||
input.addEventListener("change", async () => {
|
||||
this.#bitmapPromise = null;
|
||||
|
@ -919,8 +919,17 @@ class AnnotationEditorUIManager {
|
||||
*/
|
||||
paste(event) {
|
||||
event.preventDefault();
|
||||
const { clipboardData } = event;
|
||||
for (const item of clipboardData.items) {
|
||||
for (const editorType of this.#editorTypes) {
|
||||
if (editorType.isHandlingMimeForPasting(item.type)) {
|
||||
editorType.paste(item, this.currentLayer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let data = event.clipboardData.getData("application/pdfjs");
|
||||
let data = clipboardData.getData("application/pdfjs");
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
@ -1099,6 +1108,9 @@ class AnnotationEditorUIManager {
|
||||
* @param {string|null} editId
|
||||
*/
|
||||
updateMode(mode, editId = null) {
|
||||
if (this.#mode === mode) {
|
||||
return;
|
||||
}
|
||||
this.#mode = mode;
|
||||
if (mode === AnnotationEditorType.NONE) {
|
||||
this.setEditingState(false);
|
||||
|
Loading…
Reference in New Issue
Block a user