Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/display/editor/annotation_editor_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,15 @@ class AnnotationEditorLayer {
this.addCommands({ cmd, undo, mustExec: false });
}

getEditorByUID(uid) {
for (const editor of this.#editors.values()) {
if (editor.uid === uid) {
return editor;
}
}
return null;
}

/**
* Get an id for an editor.
* @returns {string}
Expand Down
61 changes: 44 additions & 17 deletions src/display/editor/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import { noContextMenu } from "../display_utils.js";

class Comment {
#commentButton = null;
#commentStandaloneButton = null;

#commentToolbarButton = null;

#commentWasFromKeyBoard = false;

Expand All @@ -32,16 +34,40 @@ class Comment {

constructor(editor) {
this.#editor = editor;
this.toolbar = null;
}

render() {
renderForToolbar() {
const button = (this.#commentToolbarButton =
document.createElement("button"));
button.className = "comment";
return this.#render(button);
}

renderForStandalone() {
const button = (this.#commentStandaloneButton =
document.createElement("button"));
button.className = "annotationCommentButton";

const position = this.#editor.commentButtonPosition;
if (position) {
const { style } = button;
style.insetInlineEnd = `calc(${
100 *
(this.#editor._uiManager.direction === "ltr"
? 1 - position[0]
: position[0])
}% - var(--comment-button-dim))`;
style.top = `calc(${100 * position[1]}% - var(--comment-button-dim))`;
}

return this.#render(button);
}

#render(comment) {
if (!this.#editor._uiManager.hasCommentManager()) {
return null;
}

const comment = (this.#commentButton = document.createElement("button"));
comment.className = "comment";
comment.tabIndex = "0";
comment.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-button");

Expand All @@ -57,7 +83,11 @@ class Comment {

const onClick = event => {
event.preventDefault();
this.edit();
if (comment === this.#commentToolbarButton) {
this.edit();
} else {
this.#editor._uiManager.toggleComment(this.#editor);
}
};
comment.addEventListener("click", onClick, { capture: true, signal });
comment.addEventListener(
Expand Down Expand Up @@ -86,10 +116,12 @@ class Comment {
}

finish() {
if (!this.#commentButton) {
if (!this.#commentToolbarButton) {
return;
}
this.#commentButton.focus({ focusVisible: this.#commentWasFromKeyBoard });
this.#commentToolbarButton.focus({
focusVisible: this.#commentWasFromKeyBoard,
});
this.#commentWasFromKeyBoard = false;
}

Expand Down Expand Up @@ -132,18 +164,13 @@ class Comment {
this.data = text;
}

toggle(enabled = false) {
if (!this.#commentButton) {
return;
}
this.#commentButton.disabled = !enabled;
}

shown() {}

destroy() {
this.#commentButton?.remove();
this.#commentButton = null;
this.#commentToolbarButton?.remove();
this.#commentToolbarButton = null;
this.#commentStandaloneButton?.remove();
this.#commentStandaloneButton = null;
this.#text = "";
this.#date = null;
this.#editor = null;
Expand Down
45 changes: 37 additions & 8 deletions src/display/editor/drawers/freedraw.js
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ class FreeDrawOutline extends Outline {
this.#scaleFactor = scaleFactor;
this.#innerMargin = innerMargin;
this.#isLTR = isLTR;
this.firstPoint = [NaN, NaN];
this.lastPoint = [NaN, NaN];
this.#computeMinMax(isLTR);

Expand Down Expand Up @@ -560,9 +561,12 @@ class FreeDrawOutline extends Outline {
let lastX = outline[4];
let lastY = outline[5];
const minMax = [lastX, lastY, lastX, lastY];
let firstPointX = lastX;
let firstPointY = lastY;
let lastPointX = lastX;
let lastPointY = lastY;
const ltrCallback = isLTR ? Math.max : Math.min;
const bezierBbox = new Float32Array(4);

for (let i = 6, ii = outline.length; i < ii; i += 6) {
const x = outline[i + 4],
Expand All @@ -571,23 +575,47 @@ class FreeDrawOutline extends Outline {
if (isNaN(outline[i])) {
Util.pointBoundingBox(x, y, minMax);

if (firstPointY > y) {
firstPointX = x;
firstPointY = y;
} else if (firstPointY === y) {
firstPointX = ltrCallback(firstPointX, x);
}
if (lastPointY < y) {
lastPointX = x;
lastPointY = y;
} else if (lastPointY === y) {
lastPointX = ltrCallback(lastPointX, x);
}
} else {
const bbox = [Infinity, Infinity, -Infinity, -Infinity];
Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6), bbox);
bezierBbox[0] = bezierBbox[1] = Infinity;
bezierBbox[2] = bezierBbox[3] = -Infinity;
Util.bezierBoundingBox(
lastX,
lastY,
...outline.slice(i, i + 6),
bezierBbox
);

Util.rectBoundingBox(...bbox, minMax);
Util.rectBoundingBox(
bezierBbox[0],
bezierBbox[1],
bezierBbox[2],
bezierBbox[3],
minMax
);

if (lastPointY < bbox[3]) {
lastPointX = bbox[2];
lastPointY = bbox[3];
} else if (lastPointY === bbox[3]) {
lastPointX = ltrCallback(lastPointX, bbox[2]);
if (firstPointY > bezierBbox[1]) {
firstPointX = bezierBbox[0];
firstPointY = bezierBbox[1];
} else if (firstPointY === bezierBbox[1]) {
firstPointX = ltrCallback(firstPointX, bezierBbox[0]);
}
if (lastPointY < bezierBbox[3]) {
lastPointX = bezierBbox[2];
lastPointY = bezierBbox[3];
} else if (lastPointY === bezierBbox[3]) {
lastPointX = ltrCallback(lastPointX, bezierBbox[2]);
}
}
lastX = x;
Expand All @@ -599,6 +627,7 @@ class FreeDrawOutline extends Outline {
bbox[1] = minMax[1] - this.#innerMargin;
bbox[2] = minMax[2] - minMax[0] + 2 * this.#innerMargin;
bbox[3] = minMax[3] - minMax[1] + 2 * this.#innerMargin;
this.firstPoint = [firstPointX, firstPointY];
this.lastPoint = [lastPointX, lastPointY];
}

Expand Down
33 changes: 30 additions & 3 deletions src/display/editor/drawers/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { Util } from "../../../shared/util.js";
class HighlightOutliner {
#box;

#firstPoint;

#lastPoint;

#verticalEdges = [];
Expand Down Expand Up @@ -63,12 +65,30 @@ class HighlightOutliner {
const bboxHeight = minMax[3] - minMax[1] + 2 * innerMargin;
const shiftedMinX = minMax[0] - innerMargin;
const shiftedMinY = minMax[1] - innerMargin;
let firstPointX = isLTR ? -Infinity : Infinity;
let firstPointY = Infinity;
const lastEdge = this.#verticalEdges.at(isLTR ? -1 : -2);
const lastPoint = [lastEdge[0], lastEdge[2]];

// Convert the coordinates of the edges into box coordinates.
for (const edge of this.#verticalEdges) {
const [x, y1, y2] = edge;
const [x, y1, y2, left] = edge;
if (!left && isLTR) {
if (y1 < firstPointY) {
firstPointY = y1;
firstPointX = x;
} else if (y1 === firstPointY) {
firstPointX = Math.max(firstPointX, x);
}
} else if (left && !isLTR) {
if (y1 < firstPointY) {
firstPointY = y1;
firstPointX = x;
} else if (y1 === firstPointY) {
firstPointX = Math.min(firstPointX, x);
}
}

edge[0] = (x - shiftedMinX) / bboxWidth;
edge[1] = (y1 - shiftedMinY) / bboxHeight;
edge[2] = (y2 - shiftedMinY) / bboxHeight;
Expand All @@ -80,6 +100,7 @@ class HighlightOutliner {
bboxWidth,
bboxHeight,
]);
this.#firstPoint = [firstPointX, firstPointY];
this.#lastPoint = lastPoint;
}

Expand Down Expand Up @@ -170,7 +191,12 @@ class HighlightOutliner {
}
outline.push(lastPointX, lastPointY);
}
return new HighlightOutline(outlines, this.#box, this.#lastPoint);
return new HighlightOutline(
outlines,
this.#box,
this.#firstPoint,
this.#lastPoint
);
}

#binarySearch(y) {
Expand Down Expand Up @@ -264,10 +290,11 @@ class HighlightOutline extends Outline {

#outlines;

constructor(outlines, box, lastPoint) {
constructor(outlines, box, firstPoint, lastPoint) {
super();
this.#outlines = outlines;
this.#box = box;
this.firstPoint = firstPoint;
this.lastPoint = lastPoint;
}

Expand Down
49 changes: 46 additions & 3 deletions src/display/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class AnnotationEditor {

#comment = null;

#commentStandaloneButton = null;

#disabled = false;

#dragPointerId = null;
Expand Down Expand Up @@ -184,6 +186,7 @@ class AnnotationEditor {
this._initialOptions.isCentered = parameters.isCentered;
this._structTreeParentId = null;
this.annotationElementId = parameters.annotationElementId || null;
this.creationDate = new Date();

const {
rotation,
Expand Down Expand Up @@ -313,6 +316,10 @@ class AnnotationEditor {
this.div?.classList.toggle("draggable", value);
}

get uid() {
return this.annotationElementId || this.id;
}

/**
* @returns {boolean} true if the editor handles the Enter key itself.
*/
Expand Down Expand Up @@ -1166,10 +1173,21 @@ class AnnotationEditor {
}

addCommentButton() {
if (this.#comment) {
return this.#comment;
return (this.#comment ||= new Comment(this));
}

addStandaloneCommentButton() {
this.#comment ||= new Comment(this);
if (this.#commentStandaloneButton) {
return;
}
return (this.#comment = new Comment(this));
this.#commentStandaloneButton = this.#comment.renderForStandalone();
this.div.append(this.#commentStandaloneButton);
}

removeStandaloneCommentButton() {
this.#commentStandaloneButton?.remove();
this.#commentStandaloneButton = null;
}

get commentColor() {
Expand Down Expand Up @@ -1204,13 +1222,19 @@ class AnnotationEditor {
return this.#comment?.hasBeenEdited();
}

get hasComment() {
return !!this.#comment && !this.#comment.isDeleted();
}

async editComment() {
if (!this.#comment) {
this.#comment = new Comment(this);
}
this.#comment.edit();
}

showComment() {}

addComment(serialized) {
if (this.hasEditedComment) {
const DEFAULT_POPUP_WIDTH = 180;
Expand Down Expand Up @@ -1581,6 +1605,17 @@ class AnnotationEditor {
return this.getRect(0, 0);
}

getData() {
return {
id: this.uid,
pageIndex: this.pageIndex,
rect: this.getPDFRect(),
contentsObj: { str: this.comment.text },
creationDate: this.creationDate,
popupRef: !this.#comment.isDeleted(),
};
}

/**
* Executed once this editor has been rendered.
* @param {boolean} focus - true if the editor should be focused.
Expand Down Expand Up @@ -1814,6 +1849,14 @@ class AnnotationEditor {
return null;
}

/**
* Get the position of the comment button.
* @returns {Array<number>|null}
*/
get commentButtonPosition() {
return this._uiManager.direction === "ltr" ? [1, 0] : [0, 0];
}

/**
* onkeydown callback.
* @param {KeyboardEvent} event
Expand Down
Loading
Loading