mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
[editor] Add some UI elements in order to set font size & color, and ink thickness & color
This commit is contained in:
parent
4e025e1f08
commit
1a3ef2a0aa
20 changed files with 624 additions and 65 deletions
|
@ -3767,7 +3767,7 @@ class InkAnnotation extends MarkupAnnotation {
|
|||
}
|
||||
|
||||
const appearanceBuffer = [
|
||||
`${thickness} w`,
|
||||
`${thickness} w 1 J 1 j`,
|
||||
`${getPdfColor(color, /* isFill */ false)}`,
|
||||
];
|
||||
const buffer = [];
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
Util,
|
||||
warn,
|
||||
} from "../shared/util.js";
|
||||
import { getRGB, PixelsPerInch } from "./display_utils.js";
|
||||
import {
|
||||
getShadingPattern,
|
||||
PathType,
|
||||
|
@ -33,7 +34,6 @@ import {
|
|||
} from "./pattern_helper.js";
|
||||
import { applyMaskImageData } from "../shared/image_utils.js";
|
||||
import { isNodeJS } from "../shared/is_node.js";
|
||||
import { PixelsPerInch } from "./display_utils.js";
|
||||
|
||||
// <canvas> contexts store most of the state we need natively.
|
||||
// However, PDF needs a bit more state, which we store here.
|
||||
|
@ -1326,10 +1326,7 @@ class CanvasGraphics {
|
|||
// Then for every color in the pdf, if its rounded luminance is the
|
||||
// same as the background one then it's replaced by the new
|
||||
// background color else by the foreground one.
|
||||
const cB = parseInt(defaultBg.slice(1), 16);
|
||||
const rB = (cB && 0xff0000) >> 16;
|
||||
const gB = (cB && 0x00ff00) >> 8;
|
||||
const bB = cB && 0x0000ff;
|
||||
const [rB, gB, bB] = getRGB(defaultBg);
|
||||
const newComp = x => {
|
||||
x /= 255;
|
||||
return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
|
||||
|
|
|
@ -567,6 +567,28 @@ function getXfaPageViewport(xfaPage, { scale = 1, rotation = 0 }) {
|
|||
});
|
||||
}
|
||||
|
||||
function getRGB(color) {
|
||||
if (color.startsWith("#")) {
|
||||
const colorRGB = parseInt(color.slice(1), 16);
|
||||
return [
|
||||
(colorRGB & 0xff0000) >> 16,
|
||||
(colorRGB & 0x00ff00) >> 8,
|
||||
colorRGB & 0x0000ff,
|
||||
];
|
||||
}
|
||||
|
||||
if (color.startsWith("rgb(")) {
|
||||
// getComputedStyle(...).color returns a `rgb(R, G, B)` color.
|
||||
return color
|
||||
.slice(/* "rgb(".length */ 4, -1) // Strip out "rgb(" and ")".
|
||||
.split(",")
|
||||
.map(x => parseInt(x));
|
||||
}
|
||||
|
||||
warn(`Not a valid color format: "${color}"`);
|
||||
return [0, 0, 0];
|
||||
}
|
||||
|
||||
export {
|
||||
deprecated,
|
||||
DOMCanvasFactory,
|
||||
|
@ -575,6 +597,7 @@ export {
|
|||
DOMSVGFactory,
|
||||
getFilenameFromUrl,
|
||||
getPdfFilenameFromUrl,
|
||||
getRGB,
|
||||
getXfaPageViewport,
|
||||
isDataScheme,
|
||||
isPdfFile,
|
||||
|
|
|
@ -78,6 +78,8 @@ class AnnotationEditorLayer {
|
|||
if (!AnnotationEditorLayer._initialized) {
|
||||
AnnotationEditorLayer._initialized = true;
|
||||
FreeTextEditor.initialize(options.l10n);
|
||||
|
||||
options.uiManager.registerEditorTypes([FreeTextEditor, InkEditor]);
|
||||
}
|
||||
this.#uiManager = options.uiManager;
|
||||
this.annotationStorage = options.annotationStorage;
|
||||
|
@ -98,14 +100,22 @@ class AnnotationEditorLayer {
|
|||
* @param {number} mode
|
||||
*/
|
||||
updateMode(mode) {
|
||||
if (mode === AnnotationEditorType.INK) {
|
||||
// We want to have the ink editor covering all of the page without having
|
||||
// to click to create it: it must be here when we start to draw.
|
||||
this.div.addEventListener("mouseover", this.#boundMouseover);
|
||||
this.div.removeEventListener("click", this.#boundClick);
|
||||
} else {
|
||||
this.div.removeEventListener("mouseover", this.#boundMouseover);
|
||||
switch (mode) {
|
||||
case AnnotationEditorType.INK:
|
||||
// We want to have the ink editor covering all of the page without
|
||||
// having to click to create it: it must be here when we start to draw.
|
||||
this.div.addEventListener("mouseover", this.#boundMouseover);
|
||||
this.div.removeEventListener("click", this.#boundClick);
|
||||
break;
|
||||
case AnnotationEditorType.FREETEXT:
|
||||
this.div.removeEventListener("mouseover", this.#boundMouseover);
|
||||
this.div.addEventListener("click", this.#boundClick);
|
||||
break;
|
||||
default:
|
||||
this.div.removeEventListener("mouseover", this.#boundMouseover);
|
||||
this.div.removeEventListener("click", this.#boundClick);
|
||||
}
|
||||
|
||||
this.setActiveEditor(null);
|
||||
}
|
||||
|
||||
|
@ -130,13 +140,10 @@ class AnnotationEditorLayer {
|
|||
|
||||
/**
|
||||
* Add some commands into the CommandManager (undo/redo stuff).
|
||||
* @param {function} cmd
|
||||
* @param {function} undo
|
||||
* @param {boolean} mustExec - If true the command is executed after having
|
||||
* been added.
|
||||
* @param {Object} params
|
||||
*/
|
||||
addCommands(cmd, undo, mustExec) {
|
||||
this.#uiManager.addCommands(cmd, undo, mustExec);
|
||||
addCommands(params) {
|
||||
this.#uiManager.addCommands(params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -232,7 +239,10 @@ class AnnotationEditorLayer {
|
|||
this.unselectAll();
|
||||
this.div.removeEventListener("click", this.#boundClick);
|
||||
} else {
|
||||
this.#uiManager.allowClick = false;
|
||||
// When in Ink mode, setting the editor to null allows the
|
||||
// user to have to make one click in order to start drawing.
|
||||
this.#uiManager.allowClick =
|
||||
this.#uiManager.getMode() === AnnotationEditorType.INK;
|
||||
this.div.addEventListener("click", this.#boundClick);
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +342,7 @@ class AnnotationEditorLayer {
|
|||
editor.remove();
|
||||
};
|
||||
|
||||
this.addCommands(cmd, undo, true);
|
||||
this.addCommands({ cmd, undo, mustExec: true });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,7 +357,7 @@ class AnnotationEditorLayer {
|
|||
editor.remove();
|
||||
};
|
||||
|
||||
this.addCommands(cmd, undo, false);
|
||||
this.addCommands({ cmd, undo, mustExec: false });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -372,6 +372,21 @@ class AnnotationEditor {
|
|||
this.div.classList.remove("selectedEditor");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update some parameters which have been changed through the UI.
|
||||
* @param {number} type
|
||||
* @param {*} value
|
||||
*/
|
||||
updateParams(type, value) {}
|
||||
|
||||
/**
|
||||
* Get some properties to update in the UI.
|
||||
* @returns {Object}
|
||||
*/
|
||||
get propertiesToUpdate() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export { AnnotationEditor };
|
||||
|
|
|
@ -14,12 +14,14 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
AnnotationEditorParamsType,
|
||||
AnnotationEditorType,
|
||||
assert,
|
||||
LINE_FACTOR,
|
||||
} from "../../shared/util.js";
|
||||
import { AnnotationEditor } from "./editor.js";
|
||||
import { bindEvents } from "./tools.js";
|
||||
import { getRGB } from "../display_utils.js";
|
||||
|
||||
/**
|
||||
* Basic text editor in order to create a FreeTex annotation.
|
||||
|
@ -41,10 +43,14 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
|
||||
static _internalPadding = 0;
|
||||
|
||||
static _defaultFontSize = 10;
|
||||
|
||||
static _defaultColor = "CanvasText";
|
||||
|
||||
constructor(params) {
|
||||
super({ ...params, name: "freeTextEditor" });
|
||||
this.#color = params.color || "CanvasText";
|
||||
this.#fontSize = params.fontSize || 10;
|
||||
this.#color = params.color || FreeTextEditor._defaultColor;
|
||||
this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
|
||||
}
|
||||
|
||||
static initialize(l10n) {
|
||||
|
@ -89,6 +95,94 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
return editor;
|
||||
}
|
||||
|
||||
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,
|
||||
],
|
||||
[AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor],
|
||||
];
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
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;
|
||||
};
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
getInitialTranslation() {
|
||||
// The start of the base line is where the user clicked.
|
||||
|
@ -116,6 +210,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
enableEditMode() {
|
||||
super.enableEditMode();
|
||||
this.overlayDiv.classList.remove("enabled");
|
||||
this.editorDiv.contentEditable = true;
|
||||
this.div.draggable = false;
|
||||
}
|
||||
|
||||
|
@ -123,6 +218,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
disableEditMode() {
|
||||
super.disableEditMode();
|
||||
this.overlayDiv.classList.add("enabled");
|
||||
this.editorDiv.contentEditable = false;
|
||||
this.div.draggable = true;
|
||||
}
|
||||
|
||||
|
@ -223,7 +319,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
this.editorDiv.contentEditable = true;
|
||||
|
||||
const { style } = this.editorDiv;
|
||||
style.fontSize = `${this.#fontSize}%`;
|
||||
style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;
|
||||
style.color = this.#color;
|
||||
|
||||
this.div.append(this.editorDiv);
|
||||
|
@ -248,6 +344,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
);
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
this.editorDiv.innerHTML = this.#contentHTML;
|
||||
this.div.draggable = true;
|
||||
}
|
||||
|
||||
return this.div;
|
||||
|
@ -258,9 +355,12 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
const padding = FreeTextEditor._internalPadding * this.parent.scaleFactor;
|
||||
const rect = this.getRect(padding, padding);
|
||||
|
||||
// We don't use this.#color directly because it can be CanvasText.
|
||||
const color = getRGB(getComputedStyle(this.editorDiv).color);
|
||||
|
||||
return {
|
||||
annotationType: AnnotationEditorType.FREETEXT,
|
||||
color: [0, 0, 0],
|
||||
color,
|
||||
fontSize: this.#fontSize,
|
||||
value: this.#content,
|
||||
pageIndex: this.parent.pageIndex,
|
||||
|
|
|
@ -13,9 +13,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AnnotationEditorType, Util } from "../../shared/util.js";
|
||||
import {
|
||||
AnnotationEditorParamsType,
|
||||
AnnotationEditorType,
|
||||
Util,
|
||||
} from "../../shared/util.js";
|
||||
import { AnnotationEditor } from "./editor.js";
|
||||
import { fitCurve } from "./fit_curve/fit_curve.js";
|
||||
import { getRGB } from "../display_utils.js";
|
||||
|
||||
/**
|
||||
* Basic draw editor in order to generate an Ink annotation.
|
||||
|
@ -43,10 +48,14 @@ class InkEditor extends AnnotationEditor {
|
|||
|
||||
#realHeight = 0;
|
||||
|
||||
static _defaultThickness = 1;
|
||||
|
||||
static _defaultColor = "CanvasText";
|
||||
|
||||
constructor(params) {
|
||||
super({ ...params, name: "inkEditor" });
|
||||
this.color = params.color || "CanvasText";
|
||||
this.thickness = params.thickness || 1;
|
||||
this.color = params.color || InkEditor._defaultColor;
|
||||
this.thickness = params.thickness || InkEditor._defaultThickness;
|
||||
this.paths = [];
|
||||
this.bezierPath2D = [];
|
||||
this.currentPath = [];
|
||||
|
@ -89,6 +98,88 @@ class InkEditor extends AnnotationEditor {
|
|||
return editor;
|
||||
}
|
||||
|
||||
static updateDefaultParams(type, value) {
|
||||
switch (type) {
|
||||
case AnnotationEditorParamsType.INK_THICKNESS:
|
||||
InkEditor._defaultThickness = value;
|
||||
break;
|
||||
case AnnotationEditorParamsType.INK_COLOR:
|
||||
InkEditor._defaultColor = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
updateParams(type, value) {
|
||||
switch (type) {
|
||||
case AnnotationEditorParamsType.INK_THICKNESS:
|
||||
this.#updateThickness(value);
|
||||
break;
|
||||
case AnnotationEditorParamsType.INK_COLOR:
|
||||
this.#updateColor(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static get defaultPropertiesToUpdate() {
|
||||
return [
|
||||
[AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness],
|
||||
[AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor],
|
||||
];
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
get propertiesToUpdate() {
|
||||
return [
|
||||
[AnnotationEditorParamsType.INK_THICKNESS, this.thickness],
|
||||
[AnnotationEditorParamsType.INK_COLOR, this.color],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the thickness and make this action undoable.
|
||||
* @param {number} thickness
|
||||
*/
|
||||
#updateThickness(thickness) {
|
||||
const savedThickness = this.thickness;
|
||||
this.parent.addCommands({
|
||||
cmd: () => {
|
||||
this.thickness = thickness;
|
||||
this.#fitToContent();
|
||||
},
|
||||
undo: () => {
|
||||
this.thickness = savedThickness;
|
||||
this.#fitToContent();
|
||||
},
|
||||
mustExec: true,
|
||||
type: AnnotationEditorParamsType.INK_THICKNESS,
|
||||
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.#redraw();
|
||||
},
|
||||
undo: () => {
|
||||
this.color = savedColor;
|
||||
this.#redraw();
|
||||
},
|
||||
mustExec: true,
|
||||
type: AnnotationEditorParamsType.INK_COLOR,
|
||||
overwriteIfSameType: true,
|
||||
keepUndo: true,
|
||||
});
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
rebuild() {
|
||||
if (this.div === null) {
|
||||
|
@ -186,7 +277,7 @@ class InkEditor extends AnnotationEditor {
|
|||
this.ctx.lineWidth =
|
||||
(this.thickness * this.parent.scaleFactor) / this.scaleFactor;
|
||||
this.ctx.lineCap = "round";
|
||||
this.ctx.lineJoin = "miter";
|
||||
this.ctx.lineJoin = "round";
|
||||
this.ctx.miterLimit = 10;
|
||||
this.ctx.strokeStyle = this.color;
|
||||
}
|
||||
|
@ -263,7 +354,7 @@ class InkEditor extends AnnotationEditor {
|
|||
}
|
||||
};
|
||||
|
||||
this.parent.addCommands(cmd, undo, true);
|
||||
this.parent.addCommands({ cmd, undo, mustExec: true });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -755,9 +846,12 @@ class InkEditor extends AnnotationEditor {
|
|||
const height =
|
||||
this.rotation % 180 === 0 ? rect[3] - rect[1] : rect[2] - rect[0];
|
||||
|
||||
// We don't use this.color directly because it can be CanvasText.
|
||||
const color = getRGB(this.ctx.strokeStyle);
|
||||
|
||||
return {
|
||||
annotationType: AnnotationEditorType.INK,
|
||||
color: [0, 0, 0],
|
||||
color,
|
||||
thickness: this.thickness,
|
||||
paths: this.#serializePaths(
|
||||
this.scaleFactor / this.parent.scaleFactor,
|
||||
|
|
|
@ -64,9 +64,36 @@ class CommandManager {
|
|||
* @param {function} cmd
|
||||
* @param {function} undo
|
||||
* @param {boolean} mustExec
|
||||
* @param {number} type
|
||||
* @param {boolean} overwriteIfSameType
|
||||
* @param {boolean} keepUndo
|
||||
*/
|
||||
add(cmd, undo, mustExec) {
|
||||
const save = [cmd, undo];
|
||||
add({
|
||||
cmd,
|
||||
undo,
|
||||
mustExec,
|
||||
type = NaN,
|
||||
overwriteIfSameType = false,
|
||||
keepUndo = false,
|
||||
}) {
|
||||
const save = { cmd, undo, type };
|
||||
if (
|
||||
overwriteIfSameType &&
|
||||
!isNaN(this.#position) &&
|
||||
this.#commands[this.#position].type === type
|
||||
) {
|
||||
// For example when we change a color we don't want to
|
||||
// be able to undo all the steps, hence we only want to
|
||||
// keep the last undoable action in this sequence of actions.
|
||||
if (keepUndo) {
|
||||
save.undo = this.#commands[this.#position].undo;
|
||||
}
|
||||
this.#commands[this.#position] = save;
|
||||
if (mustExec) {
|
||||
cmd();
|
||||
}
|
||||
return;
|
||||
}
|
||||
const next = (this.#position + 1) % this.#maxSize;
|
||||
if (next !== this.#start) {
|
||||
if (this.#start < next) {
|
||||
|
@ -94,7 +121,7 @@ class CommandManager {
|
|||
// Nothing to undo.
|
||||
return;
|
||||
}
|
||||
this.#commands[this.#position][1]();
|
||||
this.#commands[this.#position].undo();
|
||||
if (this.#position === this.#start) {
|
||||
this.#position = NaN;
|
||||
} else {
|
||||
|
@ -108,7 +135,7 @@ class CommandManager {
|
|||
redo() {
|
||||
if (isNaN(this.#position)) {
|
||||
if (this.#start < this.#commands.length) {
|
||||
this.#commands[this.#start][0]();
|
||||
this.#commands[this.#start].cmd();
|
||||
this.#position = this.#start;
|
||||
}
|
||||
return;
|
||||
|
@ -116,7 +143,7 @@ class CommandManager {
|
|||
|
||||
const next = (this.#position + 1) % this.#maxSize;
|
||||
if (next !== this.#start && next < this.#commands.length) {
|
||||
this.#commands[next][0]();
|
||||
this.#commands[next].cmd();
|
||||
this.#position = next;
|
||||
}
|
||||
}
|
||||
|
@ -273,6 +300,10 @@ class AnnotationEditorUIManager {
|
|||
|
||||
#commandManager = new CommandManager();
|
||||
|
||||
#editorTypes = null;
|
||||
|
||||
#eventBus = null;
|
||||
|
||||
#idManager = new IdManager();
|
||||
|
||||
#isAllSelected = false;
|
||||
|
@ -281,6 +312,26 @@ class AnnotationEditorUIManager {
|
|||
|
||||
#mode = AnnotationEditorType.NONE;
|
||||
|
||||
#previousActiveEditor = null;
|
||||
|
||||
constructor(eventBus) {
|
||||
this.#eventBus = eventBus;
|
||||
}
|
||||
|
||||
#dispatchUpdateUI(details) {
|
||||
this.#eventBus?.dispatch("annotationeditorparamschanged", {
|
||||
source: this,
|
||||
details,
|
||||
});
|
||||
}
|
||||
|
||||
registerEditorTypes(types) {
|
||||
this.#editorTypes = types;
|
||||
for (const editorType of this.#editorTypes) {
|
||||
this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an id.
|
||||
* @returns {string}
|
||||
|
@ -326,6 +377,21 @@ class AnnotationEditorUIManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a parameter in the current editor or globally.
|
||||
* @param {number} type
|
||||
* @param {*} value
|
||||
*/
|
||||
updateParams(type, value) {
|
||||
(this.#activeEditor || this.#previousActiveEditor)?.updateParams(
|
||||
type,
|
||||
value
|
||||
);
|
||||
for (const editorType of this.#editorTypes) {
|
||||
editorType.updateDefaultParams(type, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable all the layers.
|
||||
*/
|
||||
|
@ -395,7 +461,24 @@ class AnnotationEditorUIManager {
|
|||
* @param {AnnotationEditor} editor
|
||||
*/
|
||||
setActiveEditor(editor) {
|
||||
if (this.#activeEditor === editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#previousActiveEditor = this.#activeEditor;
|
||||
|
||||
this.#activeEditor = editor;
|
||||
if (editor) {
|
||||
this.#dispatchUpdateUI(editor.propertiesToUpdate);
|
||||
} else {
|
||||
if (this.#previousActiveEditor) {
|
||||
this.#dispatchUpdateUI(this.#previousActiveEditor.propertiesToUpdate);
|
||||
} else {
|
||||
for (const editorType of this.#editorTypes) {
|
||||
this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -414,12 +497,10 @@ class AnnotationEditorUIManager {
|
|||
|
||||
/**
|
||||
* Add a command to execute (cmd) and another one to undo it.
|
||||
* @param {function} cmd
|
||||
* @param {function} undo
|
||||
* @param {boolean} mustExec
|
||||
* @param {Object} params
|
||||
*/
|
||||
addCommands(cmd, undo, mustExec) {
|
||||
this.#commandManager.add(cmd, undo, mustExec);
|
||||
addCommands(params) {
|
||||
this.#commandManager.add(params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -468,7 +549,7 @@ class AnnotationEditorUIManager {
|
|||
}
|
||||
};
|
||||
|
||||
this.addCommands(cmd, undo, true);
|
||||
this.addCommands({ cmd, undo, mustExec: true });
|
||||
} else {
|
||||
if (!this.#activeEditor) {
|
||||
return;
|
||||
|
@ -482,7 +563,7 @@ class AnnotationEditorUIManager {
|
|||
};
|
||||
}
|
||||
|
||||
this.addCommands(cmd, undo, true);
|
||||
this.addCommands({ cmd, undo, mustExec: true });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -509,7 +590,7 @@ class AnnotationEditorUIManager {
|
|||
layer.addOrRebuild(editor);
|
||||
};
|
||||
|
||||
this.addCommands(cmd, undo, true);
|
||||
this.addCommands({ cmd, undo, mustExec: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,7 +611,7 @@ class AnnotationEditorUIManager {
|
|||
editor.remove();
|
||||
};
|
||||
|
||||
this.addCommands(cmd, undo, true);
|
||||
this.addCommands({ cmd, undo, mustExec: true });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
/** @typedef {import("./display/text_layer").TextLayerRenderTask} TextLayerRenderTask */
|
||||
|
||||
import {
|
||||
AnnotationEditorParamsType,
|
||||
AnnotationEditorType,
|
||||
AnnotationMode,
|
||||
CMapCompressionType,
|
||||
|
@ -110,6 +111,7 @@ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) {
|
|||
|
||||
export {
|
||||
AnnotationEditorLayer,
|
||||
AnnotationEditorParamsType,
|
||||
AnnotationEditorType,
|
||||
AnnotationEditorUIManager,
|
||||
AnnotationLayer,
|
||||
|
|
|
@ -60,6 +60,13 @@ const AnnotationEditorType = {
|
|||
INK: 15,
|
||||
};
|
||||
|
||||
const AnnotationEditorParamsType = {
|
||||
FREETEXT_SIZE: 0,
|
||||
FREETEXT_COLOR: 1,
|
||||
INK_COLOR: 2,
|
||||
INK_THICKNESS: 3,
|
||||
};
|
||||
|
||||
// Permission flags from Table 22, Section 7.6.3.2 of the PDF specification.
|
||||
const PermissionFlag = {
|
||||
PRINT: 0x04,
|
||||
|
@ -1146,6 +1153,7 @@ export {
|
|||
AbortException,
|
||||
AnnotationActionEventType,
|
||||
AnnotationBorderStyleType,
|
||||
AnnotationEditorParamsType,
|
||||
AnnotationEditorPrefix,
|
||||
AnnotationEditorType,
|
||||
AnnotationFieldFlag,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue