[Annotation] Use the new popup in reading mode (bug 1987426)
This commit is contained in:
parent
3432c1933e
commit
38b86cb97a
@ -24,6 +24,8 @@
|
|||||||
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
/** @typedef {import("../../web/struct_tree_layer_builder.js").StructTreeLayerBuilder} StructTreeLayerBuilder */
|
/** @typedef {import("../../web/struct_tree_layer_builder.js").StructTreeLayerBuilder} StructTreeLayerBuilder */
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
/** @typedef {import("../../web/comment_manager.js").CommentManager} CommentManager */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AnnotationBorderStyleType,
|
AnnotationBorderStyleType,
|
||||||
@ -38,9 +40,6 @@ import {
|
|||||||
warn,
|
warn,
|
||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
import {
|
import {
|
||||||
applyOpacity,
|
|
||||||
CSSConstants,
|
|
||||||
findContrastColor,
|
|
||||||
PDFDateString,
|
PDFDateString,
|
||||||
renderRichText,
|
renderRichText,
|
||||||
setLayerDimensions,
|
setLayerDimensions,
|
||||||
@ -206,7 +205,7 @@ class AnnotationElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get hasCommentButton() {
|
get hasCommentButton() {
|
||||||
return this.enableComment && this._isEditable && this.hasPopupElement;
|
return this.enableComment && this.hasPopupElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
get commentButtonPosition() {
|
get commentButtonPosition() {
|
||||||
@ -230,16 +229,6 @@ class AnnotationElement {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get commentButtonColor() {
|
|
||||||
if (!this.data.color) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return findContrastColor(
|
|
||||||
applyOpacity(...this.data.color, this.data.opacity),
|
|
||||||
CSSConstants.commentForegroundColor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_normalizePoint(point) {
|
_normalizePoint(point) {
|
||||||
const {
|
const {
|
||||||
page: { view },
|
page: { view },
|
||||||
@ -253,6 +242,11 @@ class AnnotationElement {
|
|||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removePopup() {
|
||||||
|
(this.#popupElement?.popup || this.popup)?.remove();
|
||||||
|
this.#popupElement = this.popup = null;
|
||||||
|
}
|
||||||
|
|
||||||
updateEdited(params) {
|
updateEdited(params) {
|
||||||
if (!this.container) {
|
if (!this.container) {
|
||||||
return;
|
return;
|
||||||
@ -272,8 +266,10 @@ class AnnotationElement {
|
|||||||
|
|
||||||
let popup = this.#popupElement?.popup || this.popup;
|
let popup = this.#popupElement?.popup || this.popup;
|
||||||
if (!popup && newPopup?.text) {
|
if (!popup && newPopup?.text) {
|
||||||
this._createPopup(newPopup);
|
if (!this.parent._commentManager) {
|
||||||
popup = this.#popupElement.popup;
|
this._createPopup(newPopup);
|
||||||
|
popup = this.#popupElement.popup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!popup) {
|
if (!popup) {
|
||||||
return;
|
return;
|
||||||
@ -680,6 +676,9 @@ class AnnotationElement {
|
|||||||
* @memberof AnnotationElement
|
* @memberof AnnotationElement
|
||||||
*/
|
*/
|
||||||
_createPopup(popupData = null) {
|
_createPopup(popupData = null) {
|
||||||
|
if (this.parent._commentManager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const { data } = this;
|
const { data } = this;
|
||||||
|
|
||||||
let contentsObj, modificationDate;
|
let contentsObj, modificationDate;
|
||||||
@ -2228,18 +2227,24 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
|
|
||||||
class PopupAnnotationElement extends AnnotationElement {
|
class PopupAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const { data, elements } = parameters;
|
const { data, elements, parent } = parameters;
|
||||||
super(parameters, { isRenderable: AnnotationElement._hasPopupData(data) });
|
const hasCommentManager = !!parent._commentManager;
|
||||||
|
super(parameters, {
|
||||||
|
isRenderable: !hasCommentManager && AnnotationElement._hasPopupData(data),
|
||||||
|
});
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
this.popup = null;
|
if (hasCommentManager && AnnotationElement._hasPopupData(data)) {
|
||||||
|
const popup = (this.popup = this.#createPopup());
|
||||||
|
for (const element of elements) {
|
||||||
|
element.popup = popup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.popup = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
#createPopup() {
|
||||||
const { container } = this;
|
return new PopupElement({
|
||||||
container.classList.add("popupAnnotation");
|
|
||||||
container.role = "comment";
|
|
||||||
|
|
||||||
const popup = (this.popup = new PopupElement({
|
|
||||||
container: this.container,
|
container: this.container,
|
||||||
color: this.data.color,
|
color: this.data.color,
|
||||||
titleObj: this.data.titleObj,
|
titleObj: this.data.titleObj,
|
||||||
@ -2251,8 +2256,16 @@ class PopupAnnotationElement extends AnnotationElement {
|
|||||||
parent: this.parent,
|
parent: this.parent,
|
||||||
elements: this.elements,
|
elements: this.elements,
|
||||||
open: this.data.open,
|
open: this.data.open,
|
||||||
eventBus: this.linkService.eventBus,
|
commentManager: this.parent._commentManager,
|
||||||
}));
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { container } = this;
|
||||||
|
container.classList.add("popupAnnotation");
|
||||||
|
container.role = "comment";
|
||||||
|
|
||||||
|
const popup = (this.popup = this.#createPopup());
|
||||||
|
|
||||||
const elementIds = [];
|
const elementIds = [];
|
||||||
for (const element of this.elements) {
|
for (const element of this.elements) {
|
||||||
@ -2272,6 +2285,8 @@ class PopupAnnotationElement extends AnnotationElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PopupElement {
|
class PopupElement {
|
||||||
|
#commentManager = null;
|
||||||
|
|
||||||
#boundKeyDown = this.#keyDown.bind(this);
|
#boundKeyDown = this.#keyDown.bind(this);
|
||||||
|
|
||||||
#boundHide = this.#hide.bind(this);
|
#boundHide = this.#hide.bind(this);
|
||||||
@ -2290,8 +2305,6 @@ class PopupElement {
|
|||||||
|
|
||||||
#elements = null;
|
#elements = null;
|
||||||
|
|
||||||
#eventBus = null;
|
|
||||||
|
|
||||||
#parent = null;
|
#parent = null;
|
||||||
|
|
||||||
#parentRect = null;
|
#parentRect = null;
|
||||||
@ -2308,7 +2321,7 @@ class PopupElement {
|
|||||||
|
|
||||||
#commentButtonPosition = null;
|
#commentButtonPosition = null;
|
||||||
|
|
||||||
#commentButtonColor = null;
|
#popupPosition = null;
|
||||||
|
|
||||||
#rect = null;
|
#rect = null;
|
||||||
|
|
||||||
@ -2320,6 +2333,8 @@ class PopupElement {
|
|||||||
|
|
||||||
#wasVisible = false;
|
#wasVisible = false;
|
||||||
|
|
||||||
|
#firstElement = null;
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
container,
|
container,
|
||||||
color,
|
color,
|
||||||
@ -2332,7 +2347,7 @@ class PopupElement {
|
|||||||
rect,
|
rect,
|
||||||
parentRect,
|
parentRect,
|
||||||
open,
|
open,
|
||||||
eventBus = null,
|
commentManager = null,
|
||||||
}) {
|
}) {
|
||||||
this.#container = container;
|
this.#container = container;
|
||||||
this.#titleObj = titleObj;
|
this.#titleObj = titleObj;
|
||||||
@ -2343,29 +2358,35 @@ class PopupElement {
|
|||||||
this.#rect = rect;
|
this.#rect = rect;
|
||||||
this.#parentRect = parentRect;
|
this.#parentRect = parentRect;
|
||||||
this.#elements = elements;
|
this.#elements = elements;
|
||||||
this.#eventBus = eventBus;
|
this.#commentManager = commentManager;
|
||||||
|
this.#firstElement = elements[0];
|
||||||
|
|
||||||
// The modification date is shown in the popup instead of the creation
|
// The modification date is shown in the popup instead of the creation
|
||||||
// date if it is available and can be parsed correctly, which is
|
// date if it is available and can be parsed correctly, which is
|
||||||
// consistent with other viewers such as Adobe Acrobat.
|
// consistent with other viewers such as Adobe Acrobat.
|
||||||
this.#dateObj = PDFDateString.toDateObject(modificationDate);
|
this.#dateObj = PDFDateString.toDateObject(modificationDate);
|
||||||
|
|
||||||
this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
|
if (commentManager) {
|
||||||
this.#addEventListeners();
|
this.#popupAbortController = new AbortController();
|
||||||
|
this.#renderCommentButton();
|
||||||
|
} else {
|
||||||
|
this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
|
||||||
|
this.#addEventListeners();
|
||||||
|
|
||||||
this.#container.hidden = true;
|
this.#container.hidden = true;
|
||||||
if (open) {
|
if (open) {
|
||||||
this.#toggle();
|
this.#toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||||
// Since the popup is lazily created, we need to ensure that it'll be
|
// Since the popup is lazily created, we need to ensure that it'll be
|
||||||
// created and displayed during reference tests.
|
// created and displayed during reference tests.
|
||||||
this.#parent.popupShow.push(async () => {
|
this.#parent.popupShow.push(async () => {
|
||||||
if (this.#container.hidden) {
|
if (this.#container.hidden) {
|
||||||
this.#show();
|
this.#show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2390,8 +2411,6 @@ class PopupElement {
|
|||||||
signal,
|
signal,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#renderCommentButton();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#setCommentButtonPosition() {
|
#setCommentButtonPosition() {
|
||||||
@ -2402,7 +2421,6 @@ class PopupElement {
|
|||||||
this.#commentButtonPosition = element._normalizePoint(
|
this.#commentButtonPosition = element._normalizePoint(
|
||||||
element.commentButtonPosition
|
element.commentButtonPosition
|
||||||
);
|
);
|
||||||
this.#commentButtonColor = element.commentButtonColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#renderCommentButton() {
|
#renderCommentButton() {
|
||||||
@ -2420,40 +2438,153 @@ class PopupElement {
|
|||||||
|
|
||||||
const button = (this.#commentButton = document.createElement("button"));
|
const button = (this.#commentButton = document.createElement("button"));
|
||||||
button.className = "annotationCommentButton";
|
button.className = "annotationCommentButton";
|
||||||
const parentContainer = this.#elements[0].container;
|
const parentContainer = this.#firstElement.container;
|
||||||
button.style.zIndex = parentContainer.style.zIndex + 1;
|
button.style.zIndex = parentContainer.style.zIndex + 1;
|
||||||
button.tabIndex = 0;
|
button.tabIndex = 0;
|
||||||
|
button.ariaHasPopup = "dialog";
|
||||||
|
button.ariaControls = "commentPopup";
|
||||||
|
|
||||||
const { signal } = this.#popupAbortController;
|
const { signal } = this.#popupAbortController;
|
||||||
button.addEventListener("hover", this.#boundToggle, { signal });
|
|
||||||
button.addEventListener("keydown", this.#boundKeyDown, { signal });
|
button.addEventListener("keydown", this.#boundKeyDown, { signal });
|
||||||
button.addEventListener(
|
button.addEventListener(
|
||||||
"click",
|
"click",
|
||||||
() => {
|
() => {
|
||||||
const [
|
this.#commentManager.toggleCommentPopup(this, /* isSelected = */ true);
|
||||||
{
|
},
|
||||||
data: { id: editId },
|
{ signal }
|
||||||
annotationEditorType: mode,
|
);
|
||||||
},
|
button.addEventListener(
|
||||||
] = this.#elements;
|
"pointerenter",
|
||||||
this.#eventBus?.dispatch("switchannotationeditormode", {
|
() => {
|
||||||
source: this,
|
this.#commentManager.toggleCommentPopup(
|
||||||
editId,
|
this,
|
||||||
mode,
|
/* isSelected = */ false,
|
||||||
editComment: true,
|
/* visibility = */ true
|
||||||
});
|
);
|
||||||
|
},
|
||||||
|
{ signal }
|
||||||
|
);
|
||||||
|
button.addEventListener(
|
||||||
|
"pointerleave",
|
||||||
|
() => {
|
||||||
|
this.#commentManager.toggleCommentPopup(
|
||||||
|
this,
|
||||||
|
/* isSelected = */ false,
|
||||||
|
/* visibility = */ false
|
||||||
|
);
|
||||||
},
|
},
|
||||||
{ signal }
|
{ signal }
|
||||||
);
|
);
|
||||||
const { style } = button;
|
const { style } = button;
|
||||||
style.left = `calc(${this.#commentButtonPosition[0]}%)`;
|
style.left = `calc(${this.#commentButtonPosition[0]}%)`;
|
||||||
style.top = `calc(${this.#commentButtonPosition[1]}% - var(--comment-button-dim))`;
|
style.top = `calc(${this.#commentButtonPosition[1]}% - var(--comment-button-dim))`;
|
||||||
if (this.#commentButtonColor) {
|
if (this.commentButtonColor) {
|
||||||
style.backgroundColor = this.#commentButtonColor;
|
style.backgroundColor = this.commentButtonColor;
|
||||||
}
|
}
|
||||||
parentContainer.after(button);
|
parentContainer.after(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get commentButtonColor() {
|
||||||
|
const {
|
||||||
|
data: { color, opacity },
|
||||||
|
} = this.#firstElement;
|
||||||
|
if (!color) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.#parent._commentManager.makeCommentColor(color, opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
return this.#firstElement.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
get elementBeforePopup() {
|
||||||
|
return this.#commentButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
get comment() {
|
||||||
|
return this.#firstElement.data.contentsObj?.str || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
set comment(text) {
|
||||||
|
const element = this.#firstElement;
|
||||||
|
if (text) {
|
||||||
|
element.data.contentsObj = { str: text };
|
||||||
|
// TODO: Support saving the text.
|
||||||
|
// element.annotationStorage.setValue(element.data.id, {
|
||||||
|
// popup: { contents: text },
|
||||||
|
// });
|
||||||
|
} else {
|
||||||
|
element.data.contentsObj = null;
|
||||||
|
element.removePopup();
|
||||||
|
}
|
||||||
|
element.data.modificationDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
get parentBoundingClientRect() {
|
||||||
|
return this.#firstElement.layer.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommentButtonStates({ selected, hasPopup }) {
|
||||||
|
if (!this.#commentButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#commentButton.classList.toggle("selected", selected);
|
||||||
|
this.#commentButton.ariaExpanded = hasPopup;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedCommentButton(selected) {
|
||||||
|
this.#commentButton.classList.toggle("selected", selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
get commentPopupPosition() {
|
||||||
|
if (this.#popupPosition) {
|
||||||
|
return this.#popupPosition;
|
||||||
|
}
|
||||||
|
const { x, y, height } = this.#commentButton.getBoundingClientRect();
|
||||||
|
const {
|
||||||
|
x: parentX,
|
||||||
|
y: parentY,
|
||||||
|
width: parentWidth,
|
||||||
|
height: parentHeight,
|
||||||
|
} = this.#firstElement.layer.getBoundingClientRect();
|
||||||
|
return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight];
|
||||||
|
}
|
||||||
|
|
||||||
|
set commentPopupPosition(pos) {
|
||||||
|
this.#popupPosition = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
get commentButtonPosition() {
|
||||||
|
return this.#commentButtonPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
get commentButtonWidth() {
|
||||||
|
return (
|
||||||
|
this.#commentButton.getBoundingClientRect().width /
|
||||||
|
this.parentBoundingClientRect.width
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
editComment(options) {
|
||||||
|
const [posX, posY] =
|
||||||
|
this.#popupPosition || this.commentButtonPosition.map(x => x / 100);
|
||||||
|
const parentDimensions = this.parentBoundingClientRect;
|
||||||
|
const {
|
||||||
|
x: parentX,
|
||||||
|
y: parentY,
|
||||||
|
width: parentWidth,
|
||||||
|
height: parentHeight,
|
||||||
|
} = parentDimensions;
|
||||||
|
this.#commentManager.showDialog(
|
||||||
|
null,
|
||||||
|
this,
|
||||||
|
parentX + posX * parentWidth,
|
||||||
|
parentY + posY * parentHeight,
|
||||||
|
{ ...options, parentDimensions }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.#popup) {
|
if (this.#popup) {
|
||||||
return;
|
return;
|
||||||
@ -2612,8 +2743,12 @@ class PopupElement {
|
|||||||
this.#popup = null;
|
this.#popup = null;
|
||||||
this.#wasVisible = false;
|
this.#wasVisible = false;
|
||||||
this.#pinned = false;
|
this.#pinned = false;
|
||||||
for (const element of this.trigger) {
|
this.#commentButton?.remove();
|
||||||
element.classList.remove("popupTriggerArea");
|
this.#commentButton = null;
|
||||||
|
if (this.trigger) {
|
||||||
|
for (const element of this.trigger) {
|
||||||
|
element.classList.remove("popupTriggerArea");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2665,6 +2800,11 @@ class PopupElement {
|
|||||||
* Toggle the visibility of the popup.
|
* Toggle the visibility of the popup.
|
||||||
*/
|
*/
|
||||||
#toggle() {
|
#toggle() {
|
||||||
|
if (this.#commentManager) {
|
||||||
|
this.#commentManager.toggleCommentPopup(this, /* isSelected = */ false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.#pinned = !this.#pinned;
|
this.#pinned = !this.#pinned;
|
||||||
if (this.#pinned) {
|
if (this.#pinned) {
|
||||||
this.#show();
|
this.#show();
|
||||||
@ -2716,6 +2856,9 @@ class PopupElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maybeShow() {
|
maybeShow() {
|
||||||
|
if (this.#commentManager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.#addEventListeners();
|
this.#addEventListeners();
|
||||||
if (!this.#wasVisible) {
|
if (!this.#wasVisible) {
|
||||||
return;
|
return;
|
||||||
@ -2728,6 +2871,9 @@ class PopupElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isVisible() {
|
get isVisible() {
|
||||||
|
if (this.#commentManager) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return this.#container.hidden === false;
|
return this.#container.hidden === false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3425,6 +3571,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
|||||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||||
* @property {AnnotationEditorUIManager} [annotationEditorUIManager]
|
* @property {AnnotationEditorUIManager} [annotationEditorUIManager]
|
||||||
* @property {StructTreeLayerBuilder} [structTreeLayer]
|
* @property {StructTreeLayerBuilder} [structTreeLayer]
|
||||||
|
* @property {CommentManager} [commentManager] - The comment manager instance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3447,6 +3594,7 @@ class AnnotationLayer {
|
|||||||
page,
|
page,
|
||||||
viewport,
|
viewport,
|
||||||
structTreeLayer,
|
structTreeLayer,
|
||||||
|
commentManager,
|
||||||
}) {
|
}) {
|
||||||
this.div = div;
|
this.div = div;
|
||||||
this.#accessibilityManager = accessibilityManager;
|
this.#accessibilityManager = accessibilityManager;
|
||||||
@ -3456,6 +3604,7 @@ class AnnotationLayer {
|
|||||||
this.viewport = viewport;
|
this.viewport = viewport;
|
||||||
this.zIndex = 0;
|
this.zIndex = 0;
|
||||||
this._annotationEditorUIManager = annotationEditorUIManager;
|
this._annotationEditorUIManager = annotationEditorUIManager;
|
||||||
|
this._commentManager = commentManager || null;
|
||||||
|
|
||||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||||
// For testing purposes.
|
// For testing purposes.
|
||||||
|
|||||||
@ -104,11 +104,7 @@ class Comment {
|
|||||||
width: parentWidth,
|
width: parentWidth,
|
||||||
height: parentHeight,
|
height: parentHeight,
|
||||||
} = this.#editor.parent.boundingClientRect;
|
} = this.#editor.parent.boundingClientRect;
|
||||||
const OFFSET_UNDER_BUTTON = 2;
|
return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight];
|
||||||
return [
|
|
||||||
(x - parentX) / parentWidth,
|
|
||||||
(y + height + OFFSET_UNDER_BUTTON - parentY) / parentHeight,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set commentPopupPositionInLayer(pos) {
|
set commentPopupPositionInLayer(pos) {
|
||||||
|
|||||||
@ -1237,7 +1237,10 @@ class AnnotationEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommentData({ comment, richText }) {
|
setCommentData({ comment, popupRef, richText }) {
|
||||||
|
if (!popupRef) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.#comment ||= new Comment(this);
|
this.#comment ||= new Comment(this);
|
||||||
this.#comment.setInitialText(comment, richText);
|
this.#comment.setInitialText(comment, richText);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
|
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
||||||
|
/** @typedef {import("./comment_manager.js").CommentManager} CommentManager */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AnnotationLayer,
|
AnnotationLayer,
|
||||||
@ -53,6 +54,7 @@ import { PresentationModeState } from "./ui_utils.js";
|
|||||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||||
* @property {AnnotationEditorUIManager} [annotationEditorUIManager]
|
* @property {AnnotationEditorUIManager} [annotationEditorUIManager]
|
||||||
* @property {function} [onAppend]
|
* @property {function} [onAppend]
|
||||||
|
* @property {CommentManager} [commentManager]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,6 +74,8 @@ import { PresentationModeState } from "./ui_utils.js";
|
|||||||
class AnnotationLayerBuilder {
|
class AnnotationLayerBuilder {
|
||||||
#annotations = null;
|
#annotations = null;
|
||||||
|
|
||||||
|
#commentManager = null;
|
||||||
|
|
||||||
#externalHide = false;
|
#externalHide = false;
|
||||||
|
|
||||||
#onAppend = null;
|
#onAppend = null;
|
||||||
@ -91,6 +95,7 @@ class AnnotationLayerBuilder {
|
|||||||
imageResourcesPath = "",
|
imageResourcesPath = "",
|
||||||
renderForms = true,
|
renderForms = true,
|
||||||
enableComment = false,
|
enableComment = false,
|
||||||
|
commentManager = null,
|
||||||
enableScripting = false,
|
enableScripting = false,
|
||||||
hasJSActionsPromise = null,
|
hasJSActionsPromise = null,
|
||||||
fieldObjectsPromise = null,
|
fieldObjectsPromise = null,
|
||||||
@ -106,6 +111,7 @@ class AnnotationLayerBuilder {
|
|||||||
this.renderForms = renderForms;
|
this.renderForms = renderForms;
|
||||||
this.annotationStorage = annotationStorage;
|
this.annotationStorage = annotationStorage;
|
||||||
this.enableComment = enableComment;
|
this.enableComment = enableComment;
|
||||||
|
this.#commentManager = commentManager;
|
||||||
this.enableScripting = enableScripting;
|
this.enableScripting = enableScripting;
|
||||||
this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
|
this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
|
||||||
this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
|
this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
|
||||||
@ -204,6 +210,7 @@ class AnnotationLayerBuilder {
|
|||||||
page: this.pdfPage,
|
page: this.pdfPage,
|
||||||
viewport: viewport.clone({ dontFlip: true }),
|
viewport: viewport.clone({ dontFlip: true }),
|
||||||
structTreeLayer,
|
structTreeLayer,
|
||||||
|
commentManager: this.#commentManager,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -228,7 +228,7 @@ const defaultOptions = {
|
|||||||
},
|
},
|
||||||
enableComment: {
|
enableComment: {
|
||||||
/** @type {boolean} */
|
/** @type {boolean} */
|
||||||
value: typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING"),
|
value: typeof PDFJSDev === "undefined",
|
||||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||||
},
|
},
|
||||||
enableDetailCanvas: {
|
enableDetailCanvas: {
|
||||||
|
|||||||
@ -496,6 +496,7 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
z-index: 100001; /* above selected annotation editor */
|
z-index: 100001; /* above selected annotation editor */
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
margin-top: 2px;
|
||||||
|
|
||||||
border: 0.5px solid var(--comment-border-color);
|
border: 0.5px solid var(--comment-border-color);
|
||||||
background: var(--comment-bg-color);
|
background: var(--comment-bg-color);
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
|
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
/** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */
|
/** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */
|
||||||
|
/** @typedef {import("./comment_manager.js").CommentManager} CommentManager */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AbortException,
|
AbortException,
|
||||||
@ -102,6 +103,7 @@ import { XfaLayerBuilder } from "./xfa_layer_builder.js";
|
|||||||
* the necessary layer-properties.
|
* the necessary layer-properties.
|
||||||
* @property {boolean} [enableAutoLinking] - Enable creation of hyperlinks from
|
* @property {boolean} [enableAutoLinking] - Enable creation of hyperlinks from
|
||||||
* text that look like URLs. The default value is `true`.
|
* text that look like URLs. The default value is `true`.
|
||||||
|
* @property {CommentManager} [commentManager] - The comment manager instance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const DEFAULT_LAYER_PROPERTIES =
|
const DEFAULT_LAYER_PROPERTIES =
|
||||||
@ -136,6 +138,8 @@ class PDFPageView extends BasePDFPageView {
|
|||||||
|
|
||||||
#canvasWrapper = null;
|
#canvasWrapper = null;
|
||||||
|
|
||||||
|
#commentManager = null;
|
||||||
|
|
||||||
#enableAutoLinking = true;
|
#enableAutoLinking = true;
|
||||||
|
|
||||||
#hasRestrictedScaling = false;
|
#hasRestrictedScaling = false;
|
||||||
@ -197,6 +201,7 @@ class PDFPageView extends BasePDFPageView {
|
|||||||
this.capCanvasAreaFactor =
|
this.capCanvasAreaFactor =
|
||||||
options.capCanvasAreaFactor ?? AppOptions.get("capCanvasAreaFactor");
|
options.capCanvasAreaFactor ?? AppOptions.get("capCanvasAreaFactor");
|
||||||
this.#enableAutoLinking = options.enableAutoLinking !== false;
|
this.#enableAutoLinking = options.enableAutoLinking !== false;
|
||||||
|
this.#commentManager = options.commentManager || null;
|
||||||
|
|
||||||
this.l10n = options.l10n;
|
this.l10n = options.l10n;
|
||||||
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
||||||
@ -1011,6 +1016,7 @@ class PDFPageView extends BasePDFPageView {
|
|||||||
annotationCanvasMap: this._annotationCanvasMap,
|
annotationCanvasMap: this._annotationCanvasMap,
|
||||||
accessibilityManager: this._accessibilityManager,
|
accessibilityManager: this._accessibilityManager,
|
||||||
annotationEditorUIManager,
|
annotationEditorUIManager,
|
||||||
|
commentManager: this.#commentManager,
|
||||||
onAppend: annotationLayerDiv => {
|
onAppend: annotationLayerDiv => {
|
||||||
this.#addLayer(annotationLayerDiv, "annotationLayer");
|
this.#addLayer(annotationLayerDiv, "annotationLayer");
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user