2022-06-01 10:38:08 +02:00
|
|
|
/* Copyright 2022 Mozilla Foundation
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2022-07-18 14:47:09 +02:00
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
/** @typedef {import("./annotation_editor_layer.js").AnnotationEditorLayer} AnnotationEditorLayer */
|
|
|
|
|
2022-06-01 15:42:46 +02:00
|
|
|
import {
|
2022-06-13 18:23:10 +02:00
|
|
|
AnnotationEditorParamsType,
|
2022-06-01 15:42:46 +02:00
|
|
|
AnnotationEditorType,
|
|
|
|
assert,
|
|
|
|
LINE_FACTOR,
|
2022-07-18 14:47:09 +02:00
|
|
|
Util,
|
2022-06-01 15:42:46 +02:00
|
|
|
} from "../../shared/util.js";
|
2022-07-19 20:54:17 +02:00
|
|
|
import { bindEvents, KeyboardManager } from "./tools.js";
|
2022-06-01 10:38:08 +02:00
|
|
|
import { AnnotationEditor } from "./editor.js";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Basic text editor in order to create a FreeTex annotation.
|
|
|
|
*/
|
|
|
|
class FreeTextEditor extends AnnotationEditor {
|
2022-07-21 10:42:15 +02:00
|
|
|
#boundEditorDivBlur = this.editorDivBlur.bind(this);
|
|
|
|
|
|
|
|
#boundEditorDivFocus = this.editorDivFocus.bind(this);
|
|
|
|
|
2022-07-19 20:54:17 +02:00
|
|
|
#boundEditorDivKeydown = this.editorDivKeydown.bind(this);
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
#color;
|
|
|
|
|
|
|
|
#content = "";
|
|
|
|
|
|
|
|
#contentHTML = "";
|
|
|
|
|
2022-06-16 18:16:49 +02:00
|
|
|
#hasAlreadyBeenCommitted = false;
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
#fontSize;
|
|
|
|
|
|
|
|
static _freeTextDefaultContent = "";
|
|
|
|
|
|
|
|
static _l10nPromise;
|
|
|
|
|
2022-06-01 15:42:46 +02:00
|
|
|
static _internalPadding = 0;
|
|
|
|
|
2022-06-29 15:39:02 +02:00
|
|
|
static _defaultColor = null;
|
2022-06-13 18:23:10 +02:00
|
|
|
|
2022-06-29 15:39:02 +02:00
|
|
|
static _defaultFontSize = 10;
|
2022-06-13 18:23:10 +02:00
|
|
|
|
2022-07-19 20:54:17 +02:00
|
|
|
static _keyboardManager = new KeyboardManager([
|
|
|
|
[
|
|
|
|
["ctrl+Enter", "mac+meta+Enter", "Escape", "mac+Escape"],
|
|
|
|
FreeTextEditor.prototype.commitOrRemove,
|
|
|
|
],
|
|
|
|
]);
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
constructor(params) {
|
|
|
|
super({ ...params, name: "freeTextEditor" });
|
2022-06-29 15:39:02 +02:00
|
|
|
this.#color =
|
|
|
|
params.color ||
|
|
|
|
FreeTextEditor._defaultColor ||
|
|
|
|
AnnotationEditor._defaultLineColor;
|
2022-06-13 18:23:10 +02:00
|
|
|
this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
|
|
|
|
2022-06-01 15:42:46 +02:00
|
|
|
static initialize(l10n) {
|
2022-06-28 18:21:32 +02:00
|
|
|
this._l10nPromise = new Map(
|
|
|
|
["free_text_default_content", "editor_free_text_aria_label"].map(str => [
|
|
|
|
str,
|
|
|
|
l10n.get(str),
|
|
|
|
])
|
|
|
|
);
|
|
|
|
|
2022-06-01 15:42:46 +02:00
|
|
|
const style = getComputedStyle(document.documentElement);
|
|
|
|
|
|
|
|
if (
|
|
|
|
typeof PDFJSDev === "undefined" ||
|
|
|
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
|
|
|
) {
|
|
|
|
const lineHeight = parseFloat(
|
2022-06-11 15:08:12 +02:00
|
|
|
style.getPropertyValue("--freetext-line-height")
|
2022-06-01 15:42:46 +02:00
|
|
|
);
|
|
|
|
assert(
|
|
|
|
lineHeight === LINE_FACTOR,
|
|
|
|
"Update the CSS variable to agree with the constant."
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._internalPadding = parseFloat(
|
2022-06-11 15:08:12 +02:00
|
|
|
style.getPropertyValue("--freetext-padding")
|
2022-06-01 15:42:46 +02:00
|
|
|
);
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
|
|
|
|
2022-06-13 18:23:10 +02:00
|
|
|
static updateDefaultParams(type, value) {
|
|
|
|
switch (type) {
|
|
|
|
case AnnotationEditorParamsType.FREETEXT_SIZE:
|
|
|
|
FreeTextEditor._defaultFontSize = value;
|
|
|
|
break;
|
|
|
|
case AnnotationEditorParamsType.FREETEXT_COLOR:
|
|
|
|
FreeTextEditor._defaultColor = value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
updateParams(type, value) {
|
|
|
|
switch (type) {
|
|
|
|
case AnnotationEditorParamsType.FREETEXT_SIZE:
|
|
|
|
this.#updateFontSize(value);
|
|
|
|
break;
|
|
|
|
case AnnotationEditorParamsType.FREETEXT_COLOR:
|
|
|
|
this.#updateColor(value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static get defaultPropertiesToUpdate() {
|
|
|
|
return [
|
|
|
|
[
|
|
|
|
AnnotationEditorParamsType.FREETEXT_SIZE,
|
|
|
|
FreeTextEditor._defaultFontSize,
|
|
|
|
],
|
2022-06-29 15:39:02 +02:00
|
|
|
[
|
|
|
|
AnnotationEditorParamsType.FREETEXT_COLOR,
|
|
|
|
FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor,
|
|
|
|
],
|
2022-06-13 18:23:10 +02:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
get propertiesToUpdate() {
|
|
|
|
return [
|
|
|
|
[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize],
|
|
|
|
[AnnotationEditorParamsType.FREETEXT_COLOR, this.#color],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the font size and make this action as undoable.
|
|
|
|
* @param {number} fontSize
|
|
|
|
*/
|
|
|
|
#updateFontSize(fontSize) {
|
|
|
|
const setFontsize = size => {
|
|
|
|
this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`;
|
|
|
|
this.translate(0, -(size - this.#fontSize) * this.parent.scaleFactor);
|
|
|
|
this.#fontSize = size;
|
2022-06-29 16:11:11 +02:00
|
|
|
this.#setEditorDimensions();
|
2022-06-13 18:23:10 +02:00
|
|
|
};
|
|
|
|
const savedFontsize = this.#fontSize;
|
|
|
|
this.parent.addCommands({
|
|
|
|
cmd: () => {
|
|
|
|
setFontsize(fontSize);
|
|
|
|
},
|
|
|
|
undo: () => {
|
|
|
|
setFontsize(savedFontsize);
|
|
|
|
},
|
|
|
|
mustExec: true,
|
|
|
|
type: AnnotationEditorParamsType.FREETEXT_SIZE,
|
|
|
|
overwriteIfSameType: true,
|
|
|
|
keepUndo: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the color and make this action undoable.
|
|
|
|
* @param {string} color
|
|
|
|
*/
|
|
|
|
#updateColor(color) {
|
|
|
|
const savedColor = this.#color;
|
|
|
|
this.parent.addCommands({
|
|
|
|
cmd: () => {
|
|
|
|
this.#color = color;
|
|
|
|
this.editorDiv.style.color = color;
|
|
|
|
},
|
|
|
|
undo: () => {
|
|
|
|
this.#color = savedColor;
|
|
|
|
this.editorDiv.style.color = savedColor;
|
|
|
|
},
|
|
|
|
mustExec: true,
|
|
|
|
type: AnnotationEditorParamsType.FREETEXT_COLOR,
|
|
|
|
overwriteIfSameType: true,
|
|
|
|
keepUndo: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-06-01 15:42:46 +02:00
|
|
|
/** @inheritdoc */
|
|
|
|
getInitialTranslation() {
|
|
|
|
// The start of the base line is where the user clicked.
|
|
|
|
return [
|
2022-06-13 11:01:55 +02:00
|
|
|
-FreeTextEditor._internalPadding * this.parent.scaleFactor,
|
2022-06-01 15:42:46 +02:00
|
|
|
-(FreeTextEditor._internalPadding + this.#fontSize) *
|
2022-06-13 11:01:55 +02:00
|
|
|
this.parent.scaleFactor,
|
2022-06-01 15:42:46 +02:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
/** @inheritdoc */
|
|
|
|
rebuild() {
|
2022-07-21 10:42:15 +02:00
|
|
|
super.rebuild();
|
2022-06-01 10:38:08 +02:00
|
|
|
if (this.div === null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.isAttachedToDOM) {
|
2022-06-04 23:28:19 +02:00
|
|
|
// At some point this editor was removed and we're rebuilting it,
|
|
|
|
// hence we must add it to its parent.
|
2022-06-01 10:38:08 +02:00
|
|
|
this.parent.add(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
enableEditMode() {
|
2022-07-27 14:11:29 +02:00
|
|
|
if (this.isInEditMode()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-04 18:04:32 +02:00
|
|
|
this.parent.setEditingState(false);
|
2022-06-29 18:09:32 +02:00
|
|
|
this.parent.updateToolbar(AnnotationEditorType.FREETEXT);
|
2022-06-01 10:38:08 +02:00
|
|
|
super.enableEditMode();
|
|
|
|
this.overlayDiv.classList.remove("enabled");
|
2022-06-13 18:23:10 +02:00
|
|
|
this.editorDiv.contentEditable = true;
|
2022-06-01 10:38:08 +02:00
|
|
|
this.div.draggable = false;
|
2022-07-19 20:54:17 +02:00
|
|
|
this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown);
|
2022-07-21 10:42:15 +02:00
|
|
|
this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus);
|
|
|
|
this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur);
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
disableEditMode() {
|
2022-07-27 14:11:29 +02:00
|
|
|
if (!this.isInEditMode()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-04 18:04:32 +02:00
|
|
|
this.parent.setEditingState(true);
|
2022-06-01 10:38:08 +02:00
|
|
|
super.disableEditMode();
|
|
|
|
this.overlayDiv.classList.add("enabled");
|
2022-06-13 18:23:10 +02:00
|
|
|
this.editorDiv.contentEditable = false;
|
2022-06-01 10:38:08 +02:00
|
|
|
this.div.draggable = true;
|
2022-07-19 20:54:17 +02:00
|
|
|
this.editorDiv.removeEventListener("keydown", this.#boundEditorDivKeydown);
|
2022-07-21 10:42:15 +02:00
|
|
|
this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus);
|
|
|
|
this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur);
|
2022-07-19 18:20:56 +02:00
|
|
|
|
2022-07-27 14:11:29 +02:00
|
|
|
// On Chrome, the focus is given to <body> when contentEditable is set to
|
|
|
|
// false, hence we focus the div.
|
|
|
|
this.div.focus();
|
|
|
|
|
2022-07-19 18:20:56 +02:00
|
|
|
// In case the blur callback hasn't been called.
|
|
|
|
this.isEditing = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
focusin(event) {
|
|
|
|
super.focusin(event);
|
|
|
|
if (event.target !== this.editorDiv) {
|
|
|
|
this.editorDiv.focus();
|
|
|
|
}
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
onceAdded() {
|
|
|
|
if (this.width) {
|
2022-06-04 23:28:19 +02:00
|
|
|
// The editor was created in using ctrl+c.
|
2022-06-01 10:38:08 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.enableEditMode();
|
|
|
|
this.editorDiv.focus();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
isEmpty() {
|
|
|
|
return this.editorDiv.innerText.trim() === "";
|
|
|
|
}
|
|
|
|
|
2022-07-04 18:04:32 +02:00
|
|
|
/** @inheritdoc */
|
|
|
|
remove() {
|
2022-07-21 10:42:15 +02:00
|
|
|
this.isEditing = false;
|
2022-07-04 18:04:32 +02:00
|
|
|
this.parent.setEditingState(true);
|
|
|
|
super.remove();
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
/**
|
|
|
|
* Extract the text from this editor.
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
#extractText() {
|
|
|
|
const divs = this.editorDiv.getElementsByTagName("div");
|
|
|
|
if (divs.length === 0) {
|
|
|
|
return this.editorDiv.innerText;
|
|
|
|
}
|
|
|
|
const buffer = [];
|
|
|
|
for (let i = 0, ii = divs.length; i < ii; i++) {
|
|
|
|
const div = divs[i];
|
|
|
|
const first = div.firstChild;
|
|
|
|
if (first?.nodeName === "#text") {
|
|
|
|
buffer.push(first.data);
|
|
|
|
} else {
|
|
|
|
buffer.push("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return buffer.join("\n");
|
|
|
|
}
|
|
|
|
|
2022-06-29 16:11:11 +02:00
|
|
|
#setEditorDimensions() {
|
|
|
|
const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
|
|
|
|
const rect = this.div.getBoundingClientRect();
|
|
|
|
|
|
|
|
this.width = rect.width / parentWidth;
|
|
|
|
this.height = rect.height / parentHeight;
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
/**
|
|
|
|
* Commit the content we have in this editor.
|
|
|
|
* @returns {undefined}
|
|
|
|
*/
|
|
|
|
commit() {
|
2022-06-16 18:16:49 +02:00
|
|
|
if (!this.#hasAlreadyBeenCommitted) {
|
|
|
|
// This editor has something and it's the first time
|
2022-07-04 18:04:32 +02:00
|
|
|
// it's commited so we can add it in the undo/redo stack.
|
2022-06-16 18:16:49 +02:00
|
|
|
this.#hasAlreadyBeenCommitted = true;
|
|
|
|
this.parent.addUndoableEditor(this);
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
this.disableEditMode();
|
|
|
|
this.#contentHTML = this.editorDiv.innerHTML;
|
|
|
|
this.#content = this.#extractText().trimEnd();
|
|
|
|
|
2022-06-29 16:11:11 +02:00
|
|
|
this.#setEditorDimensions();
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
shouldGetKeyboardEvents() {
|
|
|
|
return this.isInEditMode();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ondblclick callback.
|
|
|
|
* @param {MouseEvent} event
|
|
|
|
*/
|
|
|
|
dblclick(event) {
|
|
|
|
this.enableEditMode();
|
|
|
|
this.editorDiv.focus();
|
|
|
|
}
|
|
|
|
|
2022-06-28 18:21:32 +02:00
|
|
|
/**
|
|
|
|
* onkeydown callback.
|
2022-07-19 18:20:56 +02:00
|
|
|
* @param {KeyboardEvent} event
|
2022-06-28 18:21:32 +02:00
|
|
|
*/
|
2022-07-19 20:54:17 +02:00
|
|
|
keydown(event) {
|
|
|
|
if (event.target === this.div && event.key === "Enter") {
|
2022-06-28 18:21:32 +02:00
|
|
|
this.enableEditMode();
|
|
|
|
this.editorDiv.focus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-19 20:54:17 +02:00
|
|
|
editorDivKeydown(event) {
|
|
|
|
FreeTextEditor._keyboardManager.exec(this, event);
|
|
|
|
}
|
|
|
|
|
2022-07-21 10:42:15 +02:00
|
|
|
editorDivFocus(event) {
|
|
|
|
this.isEditing = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
editorDivBlur(event) {
|
|
|
|
this.isEditing = false;
|
|
|
|
}
|
|
|
|
|
2022-06-28 18:21:32 +02:00
|
|
|
/** @inheritdoc */
|
|
|
|
disableEditing() {
|
|
|
|
this.editorDiv.setAttribute("role", "comment");
|
|
|
|
this.editorDiv.removeAttribute("aria-multiline");
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
enableEditing() {
|
|
|
|
this.editorDiv.setAttribute("role", "textbox");
|
|
|
|
this.editorDiv.setAttribute("aria-multiline", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
getIdForTextLayer() {
|
|
|
|
return this.editorDiv.id;
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
/** @inheritdoc */
|
|
|
|
render() {
|
|
|
|
if (this.div) {
|
|
|
|
return this.div;
|
|
|
|
}
|
|
|
|
|
2022-06-23 15:47:45 +02:00
|
|
|
let baseX, baseY;
|
|
|
|
if (this.width) {
|
|
|
|
baseX = this.x;
|
|
|
|
baseY = this.y;
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
super.render();
|
|
|
|
this.editorDiv = document.createElement("div");
|
|
|
|
this.editorDiv.className = "internal";
|
|
|
|
|
2022-06-28 18:21:32 +02:00
|
|
|
this.editorDiv.setAttribute("id", `${this.id}-editor`);
|
|
|
|
this.enableEditing();
|
|
|
|
|
|
|
|
FreeTextEditor._l10nPromise
|
|
|
|
.get("editor_free_text_aria_label")
|
|
|
|
.then(msg => this.editorDiv?.setAttribute("aria-label", msg));
|
|
|
|
|
|
|
|
FreeTextEditor._l10nPromise
|
|
|
|
.get("free_text_default_content")
|
|
|
|
.then(msg => this.editorDiv?.setAttribute("default-content", msg));
|
2022-06-01 10:38:08 +02:00
|
|
|
this.editorDiv.contentEditable = true;
|
|
|
|
|
|
|
|
const { style } = this.editorDiv;
|
2022-06-13 18:23:10 +02:00
|
|
|
style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;
|
2022-06-01 10:38:08 +02:00
|
|
|
style.color = this.#color;
|
|
|
|
|
2022-06-12 12:20:25 +02:00
|
|
|
this.div.append(this.editorDiv);
|
2022-06-01 10:38:08 +02:00
|
|
|
|
|
|
|
this.overlayDiv = document.createElement("div");
|
|
|
|
this.overlayDiv.classList.add("overlay", "enabled");
|
2022-06-12 12:20:25 +02:00
|
|
|
this.div.append(this.overlayDiv);
|
2022-06-01 10:38:08 +02:00
|
|
|
|
|
|
|
// TODO: implement paste callback.
|
|
|
|
// The goal is to sanitize and have something suitable for this
|
|
|
|
// editor.
|
2022-07-19 20:54:17 +02:00
|
|
|
bindEvents(this, this.div, ["dblclick", "keydown"]);
|
2022-06-01 10:38:08 +02:00
|
|
|
|
|
|
|
if (this.width) {
|
2022-06-04 23:28:19 +02:00
|
|
|
// This editor was created in using copy (ctrl+c).
|
2022-06-23 15:47:45 +02:00
|
|
|
const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
|
|
|
|
this.setAt(
|
|
|
|
baseX * parentWidth,
|
|
|
|
baseY * parentHeight,
|
|
|
|
this.width * parentWidth,
|
|
|
|
this.height * parentHeight
|
|
|
|
);
|
2022-06-01 10:38:08 +02:00
|
|
|
// eslint-disable-next-line no-unsanitized/property
|
|
|
|
this.editorDiv.innerHTML = this.#contentHTML;
|
2022-06-13 18:23:10 +02:00
|
|
|
this.div.draggable = true;
|
2022-07-19 18:20:56 +02:00
|
|
|
this.editorDiv.contentEditable = false;
|
|
|
|
} else {
|
|
|
|
this.div.draggable = false;
|
|
|
|
this.editorDiv.contentEditable = true;
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return this.div;
|
|
|
|
}
|
|
|
|
|
2022-06-28 18:21:32 +02:00
|
|
|
get contentDiv() {
|
|
|
|
return this.editorDiv;
|
|
|
|
}
|
|
|
|
|
2022-07-18 14:47:09 +02:00
|
|
|
/** @inheritdoc */
|
|
|
|
static deserialize(data, parent) {
|
|
|
|
const editor = super.deserialize(data, parent);
|
|
|
|
|
|
|
|
editor.#fontSize = data.fontSize;
|
|
|
|
editor.#color = Util.makeHexColor(...data.color);
|
|
|
|
editor.#content = data.value;
|
|
|
|
editor.#contentHTML = data.value
|
|
|
|
.split("\n")
|
|
|
|
.map(line => `<div>${line}</div>`)
|
|
|
|
.join("");
|
|
|
|
|
|
|
|
return editor;
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
/** @inheritdoc */
|
|
|
|
serialize() {
|
2022-07-12 17:32:14 +02:00
|
|
|
if (this.isEmpty()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2022-06-13 11:01:55 +02:00
|
|
|
const padding = FreeTextEditor._internalPadding * this.parent.scaleFactor;
|
2022-06-23 15:47:45 +02:00
|
|
|
const rect = this.getRect(padding, padding);
|
2022-06-01 10:38:08 +02:00
|
|
|
|
2022-06-29 15:39:02 +02:00
|
|
|
const color = AnnotationEditor._colorManager.convert(
|
|
|
|
getComputedStyle(this.editorDiv).color
|
|
|
|
);
|
2022-06-13 18:23:10 +02:00
|
|
|
|
2022-06-01 10:38:08 +02:00
|
|
|
return {
|
|
|
|
annotationType: AnnotationEditorType.FREETEXT,
|
2022-06-13 18:23:10 +02:00
|
|
|
color,
|
2022-06-13 11:01:55 +02:00
|
|
|
fontSize: this.#fontSize,
|
2022-06-01 10:38:08 +02:00
|
|
|
value: this.#content,
|
|
|
|
pageIndex: this.parent.pageIndex,
|
2022-06-23 15:47:45 +02:00
|
|
|
rect,
|
|
|
|
rotation: this.rotation,
|
2022-06-01 10:38:08 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export { FreeTextEditor };
|