Merge pull request #16732 from calixteman/editor_resize
[Editor] Add some resizers all around an editor (bug 1843302)
This commit is contained in:
commit
e00629966d
@ -21,11 +21,6 @@
|
|||||||
import { bindEvents, ColorManager } from "./tools.js";
|
import { bindEvents, ColorManager } from "./tools.js";
|
||||||
import { FeatureTest, shadow, unreachable } from "../../shared/util.js";
|
import { FeatureTest, shadow, unreachable } from "../../shared/util.js";
|
||||||
|
|
||||||
// The dimensions of the resizer is 15x15:
|
|
||||||
// https://searchfox.org/mozilla-central/rev/1ce190047b9556c3c10ab4de70a0e61d893e2954/toolkit/content/minimal-xul.css#136-137
|
|
||||||
// so each dimension must be greater than RESIZER_SIZE.
|
|
||||||
const RESIZER_SIZE = 16;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} AnnotationEditorParameters
|
* @typedef {Object} AnnotationEditorParameters
|
||||||
* @property {AnnotationEditorUIManager} uiManager - the global manager
|
* @property {AnnotationEditorUIManager} uiManager - the global manager
|
||||||
@ -41,6 +36,10 @@ const RESIZER_SIZE = 16;
|
|||||||
class AnnotationEditor {
|
class AnnotationEditor {
|
||||||
#keepAspectRatio = false;
|
#keepAspectRatio = false;
|
||||||
|
|
||||||
|
#resizersDiv = null;
|
||||||
|
|
||||||
|
#resizePosition = null;
|
||||||
|
|
||||||
#boundFocusin = this.focusin.bind(this);
|
#boundFocusin = this.focusin.bind(this);
|
||||||
|
|
||||||
#boundFocusout = this.focusout.bind(this);
|
#boundFocusout = this.focusout.bind(this);
|
||||||
@ -75,6 +74,7 @@ class AnnotationEditor {
|
|||||||
this.div = null;
|
this.div = null;
|
||||||
this._uiManager = parameters.uiManager;
|
this._uiManager = parameters.uiManager;
|
||||||
this.annotationElementId = null;
|
this.annotationElementId = null;
|
||||||
|
this._willKeepAspectRatio = false;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
rotation,
|
rotation,
|
||||||
@ -401,6 +401,274 @@ class AnnotationEditor {
|
|||||||
return [0, 0];
|
return [0, 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#createResizers() {
|
||||||
|
if (this.#resizersDiv) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#resizersDiv = document.createElement("div");
|
||||||
|
this.#resizersDiv.classList.add("resizers");
|
||||||
|
const classes = ["topLeft", "topRight", "bottomRight", "bottomLeft"];
|
||||||
|
if (!this._willKeepAspectRatio) {
|
||||||
|
classes.push("topMiddle", "middleRight", "bottomMiddle", "middleLeft");
|
||||||
|
}
|
||||||
|
for (const name of classes) {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
this.#resizersDiv.append(div);
|
||||||
|
div.classList.add("resizer", name);
|
||||||
|
div.addEventListener(
|
||||||
|
"pointerdown",
|
||||||
|
this.#resizerPointerdown.bind(this, name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.div.prepend(this.#resizersDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#resizerPointerdown(name, event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.#resizePosition = [event.clientX, event.clientY];
|
||||||
|
const boundResizerPointermove = this.#resizerPointermove.bind(this, name);
|
||||||
|
const savedDraggable = this.div.draggable;
|
||||||
|
this.div.draggable = false;
|
||||||
|
const resizingClassName = `resizing${name
|
||||||
|
.charAt(0)
|
||||||
|
.toUpperCase()}${name.slice(1)}`;
|
||||||
|
this.parent.div.classList.add(resizingClassName);
|
||||||
|
const pointerMoveOptions = { passive: true, capture: true };
|
||||||
|
window.addEventListener(
|
||||||
|
"pointermove",
|
||||||
|
boundResizerPointermove,
|
||||||
|
pointerMoveOptions
|
||||||
|
);
|
||||||
|
const pointerUpCallback = () => {
|
||||||
|
// Stop the undo accumulation in order to have an undo action for each
|
||||||
|
// resize session.
|
||||||
|
this._uiManager.stopUndoAccumulation();
|
||||||
|
this.div.draggable = savedDraggable;
|
||||||
|
this.parent.div.classList.remove(resizingClassName);
|
||||||
|
window.removeEventListener(
|
||||||
|
"pointermove",
|
||||||
|
boundResizerPointermove,
|
||||||
|
pointerMoveOptions
|
||||||
|
);
|
||||||
|
};
|
||||||
|
window.addEventListener("pointerup", pointerUpCallback, {
|
||||||
|
once: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#resizerPointermove(name, event) {
|
||||||
|
const { clientX, clientY } = event;
|
||||||
|
const deltaX = clientX - this.#resizePosition[0];
|
||||||
|
const deltaY = clientY - this.#resizePosition[1];
|
||||||
|
this.#resizePosition[0] = clientX;
|
||||||
|
this.#resizePosition[1] = clientY;
|
||||||
|
const [parentWidth, parentHeight] = this.parentDimensions;
|
||||||
|
const savedX = this.x;
|
||||||
|
const savedY = this.y;
|
||||||
|
const savedWidth = this.width;
|
||||||
|
const savedHeight = this.height;
|
||||||
|
const minWidth = AnnotationEditor.MIN_SIZE / parentWidth;
|
||||||
|
const minHeight = AnnotationEditor.MIN_SIZE / parentHeight;
|
||||||
|
let cmd;
|
||||||
|
|
||||||
|
// 10000 because we multiply by 100 and use toFixed(2) in fixAndSetPosition.
|
||||||
|
// Without rounding, the positions of the corners other than the top left
|
||||||
|
// one can be slightly wrong.
|
||||||
|
const round = x => Math.round(x * 10000) / 10000;
|
||||||
|
const updatePosition = (width, height) => {
|
||||||
|
// We must take the parent dimensions as they are when undo/redo.
|
||||||
|
const [pWidth, pHeight] = this.parentDimensions;
|
||||||
|
this.setDims(pWidth * width, pHeight * height);
|
||||||
|
this.fixAndSetPosition();
|
||||||
|
};
|
||||||
|
const undo = () => {
|
||||||
|
this.width = savedWidth;
|
||||||
|
this.height = savedHeight;
|
||||||
|
this.x = savedX;
|
||||||
|
this.y = savedY;
|
||||||
|
updatePosition(savedWidth, savedHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case "topLeft": {
|
||||||
|
if (Math.sign(deltaX) * Math.sign(deltaY) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dist = Math.hypot(deltaX, deltaY);
|
||||||
|
const oldDiag = Math.hypot(
|
||||||
|
savedWidth * parentWidth,
|
||||||
|
savedHeight * parentHeight
|
||||||
|
);
|
||||||
|
const brX = round(savedX + savedWidth);
|
||||||
|
const brY = round(savedY + savedHeight);
|
||||||
|
const ratio = Math.max(
|
||||||
|
Math.min(
|
||||||
|
1 - Math.sign(deltaX) * (dist / oldDiag),
|
||||||
|
// Avoid the editor to be larger than the page.
|
||||||
|
1 / savedWidth,
|
||||||
|
1 / savedHeight
|
||||||
|
),
|
||||||
|
// Avoid the editor to be smaller than the minimum size.
|
||||||
|
minWidth / savedWidth,
|
||||||
|
minHeight / savedHeight
|
||||||
|
);
|
||||||
|
const newWidth = round(savedWidth * ratio);
|
||||||
|
const newHeight = round(savedHeight * ratio);
|
||||||
|
const newX = brX - newWidth;
|
||||||
|
const newY = brY - newHeight;
|
||||||
|
cmd = () => {
|
||||||
|
this.width = newWidth;
|
||||||
|
this.height = newHeight;
|
||||||
|
this.x = newX;
|
||||||
|
this.y = newY;
|
||||||
|
updatePosition(newWidth, newHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "topMiddle": {
|
||||||
|
const bmY = round(this.y + savedHeight);
|
||||||
|
const newHeight = round(
|
||||||
|
Math.max(minHeight, Math.min(1, savedHeight - deltaY / parentHeight))
|
||||||
|
);
|
||||||
|
const newY = bmY - newHeight;
|
||||||
|
cmd = () => {
|
||||||
|
this.height = newHeight;
|
||||||
|
this.y = newY;
|
||||||
|
updatePosition(savedWidth, newHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "topRight": {
|
||||||
|
if (Math.sign(deltaX) * Math.sign(deltaY) > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dist = Math.hypot(deltaX, deltaY);
|
||||||
|
const oldDiag = Math.hypot(
|
||||||
|
this.width * parentWidth,
|
||||||
|
this.height * parentHeight
|
||||||
|
);
|
||||||
|
const blY = round(savedY + this.height);
|
||||||
|
const ratio = Math.max(
|
||||||
|
Math.min(
|
||||||
|
1 + Math.sign(deltaX) * (dist / oldDiag),
|
||||||
|
1 / savedWidth,
|
||||||
|
1 / savedHeight
|
||||||
|
),
|
||||||
|
minWidth / savedWidth,
|
||||||
|
minHeight / savedHeight
|
||||||
|
);
|
||||||
|
const newWidth = round(savedWidth * ratio);
|
||||||
|
const newHeight = round(savedHeight * ratio);
|
||||||
|
const newY = blY - newHeight;
|
||||||
|
cmd = () => {
|
||||||
|
this.width = newWidth;
|
||||||
|
this.height = newHeight;
|
||||||
|
this.y = newY;
|
||||||
|
updatePosition(newWidth, newHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "middleRight": {
|
||||||
|
const newWidth = round(
|
||||||
|
Math.max(minWidth, Math.min(1, savedWidth + deltaX / parentWidth))
|
||||||
|
);
|
||||||
|
cmd = () => {
|
||||||
|
this.width = newWidth;
|
||||||
|
updatePosition(newWidth, savedHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "bottomRight": {
|
||||||
|
if (Math.sign(deltaX) * Math.sign(deltaY) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dist = Math.hypot(deltaX, deltaY);
|
||||||
|
const oldDiag = Math.hypot(
|
||||||
|
this.width * parentWidth,
|
||||||
|
this.height * parentHeight
|
||||||
|
);
|
||||||
|
const ratio = Math.max(
|
||||||
|
Math.min(
|
||||||
|
1 + Math.sign(deltaX) * (dist / oldDiag),
|
||||||
|
1 / savedWidth,
|
||||||
|
1 / savedHeight
|
||||||
|
),
|
||||||
|
minWidth / savedWidth,
|
||||||
|
minHeight / savedHeight
|
||||||
|
);
|
||||||
|
const newWidth = round(savedWidth * ratio);
|
||||||
|
const newHeight = round(savedHeight * ratio);
|
||||||
|
cmd = () => {
|
||||||
|
this.width = newWidth;
|
||||||
|
this.height = newHeight;
|
||||||
|
updatePosition(newWidth, newHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "bottomMiddle": {
|
||||||
|
const newHeight = round(
|
||||||
|
Math.max(minHeight, Math.min(1, savedHeight + deltaY / parentHeight))
|
||||||
|
);
|
||||||
|
cmd = () => {
|
||||||
|
this.height = newHeight;
|
||||||
|
updatePosition(savedWidth, newHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "bottomLeft": {
|
||||||
|
if (Math.sign(deltaX) * Math.sign(deltaY) > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dist = Math.hypot(deltaX, deltaY);
|
||||||
|
const oldDiag = Math.hypot(
|
||||||
|
this.width * parentWidth,
|
||||||
|
this.height * parentHeight
|
||||||
|
);
|
||||||
|
const trX = round(savedX + this.width);
|
||||||
|
const ratio = Math.max(
|
||||||
|
Math.min(
|
||||||
|
1 - Math.sign(deltaX) * (dist / oldDiag),
|
||||||
|
1 / savedWidth,
|
||||||
|
1 / savedHeight
|
||||||
|
),
|
||||||
|
minWidth / savedWidth,
|
||||||
|
minHeight / savedHeight
|
||||||
|
);
|
||||||
|
const newWidth = round(savedWidth * ratio);
|
||||||
|
const newHeight = round(savedHeight * ratio);
|
||||||
|
const newX = trX - newWidth;
|
||||||
|
cmd = () => {
|
||||||
|
this.width = newWidth;
|
||||||
|
this.height = newHeight;
|
||||||
|
this.x = newX;
|
||||||
|
updatePosition(newWidth, newHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "middleLeft": {
|
||||||
|
const mrX = round(savedX + savedWidth);
|
||||||
|
const newWidth = round(
|
||||||
|
Math.max(minWidth, Math.min(1, savedWidth - deltaX / parentWidth))
|
||||||
|
);
|
||||||
|
const newX = mrX - newWidth;
|
||||||
|
cmd = () => {
|
||||||
|
this.width = newWidth;
|
||||||
|
this.x = newX;
|
||||||
|
updatePosition(newWidth, savedHeight);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.addCommands({
|
||||||
|
cmd,
|
||||||
|
undo,
|
||||||
|
mustExec: true,
|
||||||
|
type: this.resizeType,
|
||||||
|
overwriteIfSameType: true,
|
||||||
|
keepUndo: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render this editor in a div.
|
* Render this editor in a div.
|
||||||
* @returns {HTMLDivElement}
|
* @returns {HTMLDivElement}
|
||||||
@ -654,10 +922,35 @@ class AnnotationEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {number} the type to use in the undo/redo stack when resizing.
|
||||||
|
*/
|
||||||
|
get resizeType() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean} true if this editor can be resized.
|
||||||
|
*/
|
||||||
|
get isResizable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the resizers to this editor.
|
||||||
|
*/
|
||||||
|
makeResizable() {
|
||||||
|
if (this.isResizable) {
|
||||||
|
this.#createResizers();
|
||||||
|
this.#resizersDiv.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select this editor.
|
* Select this editor.
|
||||||
*/
|
*/
|
||||||
select() {
|
select() {
|
||||||
|
this.makeResizable();
|
||||||
this.div?.classList.add("selectedEditor");
|
this.div?.classList.add("selectedEditor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,6 +958,7 @@ class AnnotationEditor {
|
|||||||
* Unselect this editor.
|
* Unselect this editor.
|
||||||
*/
|
*/
|
||||||
unselect() {
|
unselect() {
|
||||||
|
this.#resizersDiv?.classList.add("hidden");
|
||||||
this.div?.classList.remove("selectedEditor");
|
this.div?.classList.remove("selectedEditor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,17 +1029,10 @@ class AnnotationEditor {
|
|||||||
const { style } = this.div;
|
const { style } = this.div;
|
||||||
style.aspectRatio = aspectRatio;
|
style.aspectRatio = aspectRatio;
|
||||||
style.height = "auto";
|
style.height = "auto";
|
||||||
if (aspectRatio >= 1) {
|
|
||||||
style.minHeight = `${RESIZER_SIZE}px`;
|
|
||||||
style.minWidth = `${Math.round(aspectRatio * RESIZER_SIZE)}px`;
|
|
||||||
} else {
|
|
||||||
style.minWidth = `${RESIZER_SIZE}px`;
|
|
||||||
style.minHeight = `${Math.round(RESIZER_SIZE / aspectRatio)}px`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get MIN_SIZE() {
|
static get MIN_SIZE() {
|
||||||
return RESIZER_SIZE;
|
return 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ class InkEditor extends AnnotationEditor {
|
|||||||
this.translationX = this.translationY = 0;
|
this.translationX = this.translationY = 0;
|
||||||
this.x = 0;
|
this.x = 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
|
this._willKeepAspectRatio = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
@ -156,6 +157,11 @@ class InkEditor extends AnnotationEditor {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
get resizeType() {
|
||||||
|
return AnnotationEditorParamsType.INK_DIMS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the thickness and make this action undoable.
|
* Update the thickness and make this action undoable.
|
||||||
* @param {number} thickness
|
* @param {number} thickness
|
||||||
@ -619,6 +625,7 @@ class InkEditor extends AnnotationEditor {
|
|||||||
this.div.classList.add("disabled");
|
this.div.classList.add("disabled");
|
||||||
|
|
||||||
this.#fitToContent(/* firstTime = */ true);
|
this.#fitToContent(/* firstTime = */ true);
|
||||||
|
this.makeResizable();
|
||||||
|
|
||||||
this.parent.addInkEditorIfNeeded(/* isCommitting = */ true);
|
this.parent.addInkEditorIfNeeded(/* isCommitting = */ true);
|
||||||
|
|
||||||
@ -754,6 +761,11 @@ class InkEditor extends AnnotationEditor {
|
|||||||
this.#observer.observe(this.div);
|
this.#observer.observe(this.div);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
get isResizable() {
|
||||||
|
return !this.isEmpty() && this.#disableEditing;
|
||||||
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
render() {
|
render() {
|
||||||
if (this.div) {
|
if (this.div) {
|
||||||
|
@ -13,8 +13,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
AnnotationEditorParamsType,
|
||||||
|
AnnotationEditorType,
|
||||||
|
} from "../../shared/util.js";
|
||||||
import { AnnotationEditor } from "./editor.js";
|
import { AnnotationEditor } from "./editor.js";
|
||||||
import { AnnotationEditorType } from "../../shared/util.js";
|
|
||||||
import { PixelsPerInch } from "../display_utils.js";
|
import { PixelsPerInch } from "../display_utils.js";
|
||||||
import { StampAnnotationElement } from "../annotation_layer.js";
|
import { StampAnnotationElement } from "../annotation_layer.js";
|
||||||
|
|
||||||
@ -123,6 +126,11 @@ class StampEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
get resizeType() {
|
||||||
|
return AnnotationEditorParamsType.STAMP_DIMS;
|
||||||
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
remove() {
|
remove() {
|
||||||
if (this.#bitmapId) {
|
if (this.#bitmapId) {
|
||||||
@ -170,6 +178,11 @@ class StampEditor extends AnnotationEditor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
get isResizable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
render() {
|
render() {
|
||||||
if (this.div) {
|
if (this.div) {
|
||||||
@ -194,7 +207,6 @@ class StampEditor extends AnnotationEditor {
|
|||||||
if (this.width) {
|
if (this.width) {
|
||||||
// This editor was created in using copy (ctrl+c).
|
// This editor was created in using copy (ctrl+c).
|
||||||
const [parentWidth, parentHeight] = this.parentDimensions;
|
const [parentWidth, parentHeight] = this.parentDimensions;
|
||||||
this.setAspectRatio(this.width * parentWidth, this.height * parentHeight);
|
|
||||||
this.setAt(
|
this.setAt(
|
||||||
baseX * parentWidth,
|
baseX * parentWidth,
|
||||||
baseY * parentHeight,
|
baseY * parentHeight,
|
||||||
@ -233,8 +245,6 @@ class StampEditor extends AnnotationEditor {
|
|||||||
(height * parentHeight) / pageHeight
|
(height * parentHeight) / pageHeight
|
||||||
);
|
);
|
||||||
|
|
||||||
this.setAspectRatio(width, height);
|
|
||||||
|
|
||||||
const canvas = (this.#canvas = document.createElement("canvas"));
|
const canvas = (this.#canvas = document.createElement("canvas"));
|
||||||
div.append(canvas);
|
div.append(canvas);
|
||||||
this.#drawBitmap(width, height);
|
this.#drawBitmap(width, height);
|
||||||
|
@ -280,6 +280,12 @@ class CommandManager {
|
|||||||
this.#commands.push(save);
|
this.#commands.push(save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopUndoAccumulation() {
|
||||||
|
if (this.#position !== -1) {
|
||||||
|
this.#commands[this.#position].type = NaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo the last command.
|
* Undo the last command.
|
||||||
*/
|
*/
|
||||||
@ -1168,6 +1174,10 @@ class AnnotationEditorUIManager {
|
|||||||
return this.#selectedEditors.size !== 0;
|
return this.#selectedEditors.size !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopUndoAccumulation() {
|
||||||
|
this.#commandManager.stopUndoAccumulation();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo the last command.
|
* Undo the last command.
|
||||||
*/
|
*/
|
||||||
|
@ -83,6 +83,8 @@ const AnnotationEditorParamsType = {
|
|||||||
INK_COLOR: 11,
|
INK_COLOR: 11,
|
||||||
INK_THICKNESS: 12,
|
INK_THICKNESS: 12,
|
||||||
INK_OPACITY: 13,
|
INK_OPACITY: 13,
|
||||||
|
INK_DIMS: 14,
|
||||||
|
STAMP_DIMS: 21,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Permission flags from Table 22, Section 7.6.3.2 of the PDF specification.
|
// Permission flags from Table 22, Section 7.6.3.2 of the PDF specification.
|
||||||
|
@ -14,10 +14,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--focus-outline: solid 2px blue;
|
--outline-width: 2px;
|
||||||
--hover-outline: dashed 2px blue;
|
--outline-color: blue;
|
||||||
|
--focus-outline: solid var(--outline-width) var(--outline-color);
|
||||||
|
--hover-outline: dashed var(--outline-width) var(--outline-color);
|
||||||
--freetext-line-height: 1.35;
|
--freetext-line-height: 1.35;
|
||||||
--freetext-padding: 2px;
|
--freetext-padding: 2px;
|
||||||
|
--resizer-size: 8px;
|
||||||
|
--resizer-shift: calc(
|
||||||
|
0px - var(--outline-width) - var(--resizer-size) / 2 - var(--outline-width) /
|
||||||
|
2
|
||||||
|
);
|
||||||
|
--resizer-color: white;
|
||||||
--editorFreeText-editing-cursor: text;
|
--editorFreeText-editing-cursor: text;
|
||||||
/*#if COMPONENTS*/
|
/*#if COMPONENTS*/
|
||||||
--editorInk-editing-cursor: pointer;
|
--editorInk-editing-cursor: pointer;
|
||||||
@ -37,8 +45,10 @@
|
|||||||
|
|
||||||
@media screen and (forced-colors: active) {
|
@media screen and (forced-colors: active) {
|
||||||
:root {
|
:root {
|
||||||
--focus-outline: solid 3px ButtonText;
|
--outline-width: 3px;
|
||||||
--hover-outline: dashed 3px ButtonText;
|
--outline-color: ButtonText;
|
||||||
|
--resizer-size: 12px;
|
||||||
|
--resizer-color: ButtonFace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +88,6 @@
|
|||||||
|
|
||||||
.annotationEditorLayer .selectedEditor {
|
.annotationEditorLayer .selectedEditor {
|
||||||
outline: var(--focus-outline);
|
outline: var(--focus-outline);
|
||||||
resize: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) {
|
.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) {
|
||||||
@ -92,13 +101,8 @@
|
|||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.annotationEditorLayer :is(.inkEditor, .stampEditor) {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.annotationEditorLayer .freeTextEditor {
|
.annotationEditorLayer .freeTextEditor {
|
||||||
padding: calc(var(--freetext-padding) * var(--scale-factor));
|
padding: calc(var(--freetext-padding) * var(--scale-factor));
|
||||||
resize: none;
|
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
@ -111,7 +115,6 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
resize: none;
|
|
||||||
font: 10px sans-serif;
|
font: 10px sans-serif;
|
||||||
line-height: var(--freetext-line-height);
|
line-height: var(--freetext-line-height);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -141,14 +144,6 @@
|
|||||||
user-select: auto;
|
user-select: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.annotationEditorLayer .inkEditor.disabled {
|
|
||||||
resize: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.annotationEditorLayer .inkEditor.disabled.selectedEditor {
|
|
||||||
resize: horizontal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.annotationEditorLayer
|
.annotationEditorLayer
|
||||||
:is(.freeTextEditor, .inkEditor, .stampEditor):hover:not(.selectedEditor) {
|
:is(.freeTextEditor, .inkEditor, .stampEditor):hover:not(.selectedEditor) {
|
||||||
outline: var(--hover-outline);
|
outline: var(--hover-outline);
|
||||||
@ -160,7 +155,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.annotationEditorLayer .inkEditor.editing {
|
.annotationEditorLayer .inkEditor.editing {
|
||||||
resize: none;
|
|
||||||
cursor: inherit;
|
cursor: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,11 +185,107 @@
|
|||||||
transition-delay: var(--loading-icon-delay);
|
transition-delay: var(--loading-icon-delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
.annotationEditorLayer .stampEditor.selectedEditor {
|
|
||||||
resize: horizontal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.annotationEditorLayer .stampEditor canvas {
|
.annotationEditorLayer .stampEditor canvas {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizers {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizers.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer {
|
||||||
|
width: var(--resizer-size);
|
||||||
|
height: var(--resizer-size);
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--resizer-color);
|
||||||
|
border: var(--focus-outline);
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.topLeft {
|
||||||
|
cursor: nw-resize;
|
||||||
|
top: var(--resizer-shift);
|
||||||
|
left: var(--resizer-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.topMiddle {
|
||||||
|
cursor: n-resize;
|
||||||
|
top: var(--resizer-shift);
|
||||||
|
left: calc(50% + var(--resizer-shift));
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.topRight {
|
||||||
|
cursor: ne-resize;
|
||||||
|
top: var(--resizer-shift);
|
||||||
|
right: var(--resizer-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.middleRight {
|
||||||
|
cursor: e-resize;
|
||||||
|
top: calc(50% + var(--resizer-shift));
|
||||||
|
right: var(--resizer-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.bottomRight {
|
||||||
|
cursor: se-resize;
|
||||||
|
bottom: var(--resizer-shift);
|
||||||
|
right: var(--resizer-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.bottomMiddle {
|
||||||
|
cursor: s-resize;
|
||||||
|
bottom: var(--resizer-shift);
|
||||||
|
left: calc(50% + var(--resizer-shift));
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.bottomLeft {
|
||||||
|
cursor: sw-resize;
|
||||||
|
bottom: var(--resizer-shift);
|
||||||
|
left: var(--resizer-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer .resizer.middleLeft {
|
||||||
|
cursor: w-resize;
|
||||||
|
top: calc(50% + var(--resizer-shift));
|
||||||
|
left: var(--resizer-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingTopLeft {
|
||||||
|
cursor: nw-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingTopMiddle {
|
||||||
|
cursor: n-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingTopRight {
|
||||||
|
cursor: ne-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingMiddleRight {
|
||||||
|
cursor: e-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingBottomRight {
|
||||||
|
cursor: se-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingBottomMiddle {
|
||||||
|
cursor: s-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingBottomLeft {
|
||||||
|
cursor: sw-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationEditorLayer.resizingMiddleLeft {
|
||||||
|
cursor: w-resize;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user