From 01f9f385d7e0e71aa065097154274bcea33608b6 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Tue, 12 Sep 2023 21:29:20 +0200 Subject: [PATCH] [Editor] Change the style of the bounding box and the resizers (bug 1852897) --- src/display/editor/editor.js | 42 +++++++++++++- src/display/editor/freetext.js | 1 + src/display/editor/ink.js | 1 + web/annotation_editor_layer_builder.css | 77 ++++++++++++++++--------- 4 files changed, 91 insertions(+), 30 deletions(-) diff --git a/src/display/editor/editor.js b/src/display/editor/editor.js index 5f014f37890c5..0641248fe75d8 100644 --- a/src/display/editor/editor.js +++ b/src/display/editor/editor.js @@ -58,6 +58,8 @@ class AnnotationEditor { #zIndex = AnnotationEditor._zIndex++; + static _borderLineWidth = -1; + static _colorManager = new ColorManager(); static _zIndex = 1; @@ -124,7 +126,14 @@ class AnnotationEditor { * Initialize the l10n stuff for this type of editor. * @param {Object} _l10n */ - static initialize(_l10n) {} + static initialize(_l10n) { + if (AnnotationEditor._borderLineWidth !== -1) { + return; + } + const style = getComputedStyle(document.documentElement); + AnnotationEditor._borderLineWidth = + parseFloat(style.getPropertyValue("--outline-width")) || 0; + } /** * Update the default parameters for this type of editor. @@ -365,11 +374,34 @@ class AnnotationEditor { // The editor can be moved wherever the user wants, so we don't need to fix // the position: it'll be done when the user will release the mouse button. - this.div.style.left = `${(100 * this.x).toFixed(2)}%`; - this.div.style.top = `${(100 * this.y).toFixed(2)}%`; + + let { x, y } = this; + const [bx, by] = this.#getBaseTranslation(); + x += bx; + y += by; + + this.div.style.left = `${(100 * x).toFixed(2)}%`; + this.div.style.top = `${(100 * y).toFixed(2)}%`; this.div.scrollIntoView({ block: "nearest" }); } + #getBaseTranslation() { + const [parentWidth, parentHeight] = this.parentDimensions; + const { _borderLineWidth } = AnnotationEditor; + const x = _borderLineWidth / parentWidth; + const y = _borderLineWidth / parentHeight; + switch (this.rotation) { + case 90: + return [-x, y]; + case 180: + return [x, y]; + case 270: + return [x, -y]; + default: + return [-x, -y]; + } + } + fixAndSetPosition() { const [pageWidth, pageHeight] = this.pageDimensions; let { x, y, width, height } = this; @@ -400,6 +432,10 @@ class AnnotationEditor { this.x = x /= pageWidth; this.y = y /= pageHeight; + const [bx, by] = this.#getBaseTranslation(); + x += bx; + y += by; + const { style } = this.div; style.left = `${(100 * x).toFixed(2)}%`; style.top = `${(100 * y).toFixed(2)}%`; diff --git a/src/display/editor/freetext.js b/src/display/editor/freetext.js index 3c973ff8ec4f2..385492c0cc7e9 100644 --- a/src/display/editor/freetext.js +++ b/src/display/editor/freetext.js @@ -145,6 +145,7 @@ class FreeTextEditor extends AnnotationEditor { /** @inheritdoc */ static initialize(l10n) { + super.initialize(l10n); this._l10nPromise = new Map( ["free_text2_default_content", "editor_free_text2_aria_label"].map( str => [str, l10n.get(str)] diff --git a/src/display/editor/ink.js b/src/display/editor/ink.js index 811db67430092..7651b5451d978 100644 --- a/src/display/editor/ink.js +++ b/src/display/editor/ink.js @@ -84,6 +84,7 @@ class InkEditor extends AnnotationEditor { /** @inheritdoc */ static initialize(l10n) { + super.initialize(l10n); this._l10nPromise = new Map( ["editor_ink_canvas_aria_label", "editor_ink2_aria_label"].map(str => [ str, diff --git a/web/annotation_editor_layer_builder.css b/web/annotation_editor_layer_builder.css index c8f01ec988ae5..465dcc0e0c4ce 100644 --- a/web/annotation_editor_layer_builder.css +++ b/web/annotation_editor_layer_builder.css @@ -15,17 +15,21 @@ :root { --outline-width: 2px; - --outline-color: blue; + --outline-color: #0060df; + --outline-around-width: 1px; + --outline-around-color: #f0f0f4; --focus-outline: solid var(--outline-width) var(--outline-color); + --unfocus-outline: solid var(--outline-width) transparent; + --focus-outline-around: solid var(--outline-around-width) + var(--outline-around-color); --hover-outline: dashed var(--outline-width) var(--outline-color); --freetext-line-height: 1.35; --freetext-padding: 2px; - --resizer-size: 8px; + --resizer-size: 6px; --resizer-shift: calc( - 0px - var(--outline-width) - var(--resizer-size) / 2 - var(--outline-width) / - 2 + 0px - (var(--outline-width) + var(--resizer-size)) / 2 - + var(--outline-around-width) ); - --resizer-color: white; --editorFreeText-editing-cursor: text; /*#if COMPONENTS*/ --editorInk-editing-cursor: pointer; @@ -45,10 +49,8 @@ @media screen and (forced-colors: active) { :root { - --outline-width: 3px; --outline-color: ButtonText; - --resizer-size: 12px; - --resizer-color: ButtonFace; + --outline-around-color: ButtonFace; } } @@ -89,15 +91,6 @@ cursor: var(--editorInk-editing-cursor); } -.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor).draggable.selectedEditor { - cursor: move; -} - -.annotationEditorLayer .selectedEditor { - outline: var(--focus-outline); -} - .annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) { position: absolute; background: transparent; @@ -107,6 +100,44 @@ cursor: auto; max-width: 100%; max-height: 100%; + border: var(--unfocus-outline); + + &.draggable.selectedEditor { + cursor: move; + } + + &.selectedEditor { + border: var(--focus-outline); + outline: var(--focus-outline-around); + + &::before { + /* + This is a workaround for the lack of support for stripes(...) (see + https://drafts.csswg.org/css-images-4/#stripes). + The outline should be composed of 1px white, 2px blue and 1px white. + This could be achieved in different ways: + - using a linear-gradient; + - using a box-shadow; + - using an outline on the selected element and an outline+border on + the ::before pseudo-element. + All these options lead to incorrect rendering likely due to rounding + issues. + That said it doesn't mean that the current is ideal, but it's the best + we could come up with for the moment. + One drawback of this approach is that we use a border on the selected + element which means that we must take care of it when positioning the + div in js (see AnnotationEditor._borderLineWidth in editor.js). + */ + content: ""; + position: absolute; + inset: 0; + border: var(--focus-outline-around); + } + } + + &:hover:not(.selectedEditor) { + border: var(--hover-outline); + } } .annotationEditorLayer .freeTextEditor { @@ -150,11 +181,6 @@ user-select: auto; } -.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor):hover:not(.selectedEditor) { - outline: var(--hover-outline); -} - .annotationEditorLayer .inkEditor { width: 100%; height: 100%; @@ -185,8 +211,6 @@ .annotationEditorLayer { :is(.freeTextEditor, .inkEditor, .stampEditor) { & > .resizers { - width: 100%; - height: 100%; position: absolute; inset: 0; @@ -197,9 +221,8 @@ & > .resizer { width: var(--resizer-size); height: var(--resizer-size); - border-radius: 50%; - background: var(--resizer-color); - border: var(--focus-outline); + background: var(--outline-color); + border: var(--focus-outline-around); position: absolute; &.topLeft {