Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Editor] Add a toggle button to show/hide all the highlights (bug 1867740) #17778

Merged
merged 1 commit into from
Mar 7, 2024
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
7 changes: 7 additions & 0 deletions l10n/en-US/viewer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -405,3 +405,10 @@ pdfjs-editor-colorpicker-pink =
.title = Pink
pdfjs-editor-colorpicker-red =
.title = Red

## Show all highlights
## This is a toggle button to show/hide all the highlights.

pdfjs-editor-highlight-show-all-button-label = Show all
pdfjs-editor-highlight-show-all-button =
.title = Show all
4 changes: 4 additions & 0 deletions src/display/draw_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ class DrawLayer {
DrawLayer.#setBox(this.#mapping.get(id), box);
}

show(id, visible) {
this.#mapping.get(id).classList.toggle("hidden", !visible);
}

rotate(id, angle) {
this.#mapping.get(id).setAttribute("data-main-rotation", angle);
}
Expand Down
5 changes: 5 additions & 0 deletions src/display/editor/annotation_editor_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,11 @@ class AnnotationEditorLayer {
// Do nothing on right click.
return;
}
this.#uiManager.showAllEditors(
"highlight",
true,
/* updateButton = */ true
);
this.#textLayer.div.classList.add("free");
HighlightEditor.startHighlighting(
this,
Expand Down
15 changes: 15 additions & 0 deletions src/display/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class AnnotationEditor {

_initialOptions = Object.create(null);

_isVisible = true;

_uiManager = null;

_focusEventsAllowed = true;
Expand Down Expand Up @@ -1001,6 +1003,9 @@ class AnnotationEditor {
this.div.className = this.name;
this.div.setAttribute("id", this.id);
this.div.setAttribute("tabIndex", 0);
if (!this._isVisible) {
this.div.classList.add("hidden");
}

this.setInForeground();

Expand Down Expand Up @@ -1263,6 +1268,7 @@ class AnnotationEditor {
rebuild() {
this.div?.addEventListener("focusin", this.#boundFocusin);
this.div?.addEventListener("focusout", this.#boundFocusout);
this.show(this._isVisible);
}

/**
Expand Down Expand Up @@ -1665,6 +1671,15 @@ class AnnotationEditor {
},
});
}

/**
* Show or hide this editor.
* @param {boolean} visible
*/
show(visible) {
this.div.classList.toggle("hidden", !visible);
this._isVisible = visible;
}
}

// This class is used to fake an editor which has been deleted.
Expand Down
9 changes: 9 additions & 0 deletions src/display/editor/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ class HighlightEditor extends AnnotationEditor {
!this.parent && this.div?.classList.contains("selectedEditor");
}
super.setParent(parent);
this.show(this._isVisible);
if (mustBeSelected) {
// We select it after the parent has been set.
this.select();
Expand Down Expand Up @@ -634,6 +635,14 @@ class HighlightEditor extends AnnotationEditor {
return !this.#isFreeHighlight;
}

show(visible) {
super.show(visible);
if (this.parent) {
this.parent.drawLayer.show(this.#id, visible);
this.parent.drawLayer.show(this.#outlineId, visible);
}
}

#getRotation() {
// Highlight annotations are always drawn horizontally but if
// a free highlight annotation can be rotated.
Expand Down
35 changes: 35 additions & 0 deletions src/display/editor/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ class AnnotationEditorUIManager {

#pageColors = null;

#showAllStates = null;

#boundBlur = this.blur.bind(this);

#boundFocus = this.focus.bind(this);
Expand Down Expand Up @@ -1029,6 +1031,9 @@ class AnnotationEditorUIManager {
if (this.#mode !== AnnotationEditorType.HIGHLIGHT) {
return;
}

this.showAllEditors("highlight", true, /* updateButton = */ true);
calixteman marked this conversation as resolved.
Show resolved Hide resolved

this.#highlightWhenShiftUp = this.isShiftKeyDown;
if (!this.isShiftKeyDown) {
const pointerup = e => {
Expand Down Expand Up @@ -1477,6 +1482,20 @@ class AnnotationEditorUIManager {
case AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR:
this.#mainHighlightColorPicker?.updateColor(value);
break;
case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:
this._eventBus.dispatch("reporttelemetry", {
source: this,
details: {
type: "editing",
data: {
type: "highlight",
action: "toggle_visibility",
},
},
});
(this.#showAllStates ||= new Map()).set(type, value);
this.showAllEditors("highlight", value);
break;
}

for (const editor of this.#selectedEditors) {
Expand All @@ -1488,6 +1507,22 @@ class AnnotationEditorUIManager {
}
}

showAllEditors(type, visible, updateButton = false) {
for (const editor of this.#allEditors.values()) {
if (editor.editorType === type) {
editor.show(visible);
}
}
const state =
this.#showAllStates?.get(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ??
true;
if (state !== visible) {
this.#dispatchUpdateUI([
[AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible],
]);
}
}

enableWaiting(mustWait = false) {
if (this.#isWaiting === mustWait) {
return;
Expand Down
1 change: 1 addition & 0 deletions src/shared/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const AnnotationEditorParamsType = {
HIGHLIGHT_DEFAULT_COLOR: 32,
HIGHLIGHT_THICKNESS: 33,
HIGHLIGHT_FREE: 34,
HIGHLIGHT_SHOW_ALL: 35,
};

// Permission flags from Table 22, Section 7.6.3.2 of the PDF specification.
Expand Down
69 changes: 69 additions & 0 deletions test/integration/highlight_editor_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1441,4 +1441,73 @@ describe("Highlight Editor", () => {
);
});
});

describe("Show/hide all the highlights", () => {
let pages;

beforeAll(async () => {
pages = await loadAndWait("tracemonkey.pdf", ".annotationEditorLayer");
});

afterAll(async () => {
await closePages(pages);
});

it("must check that the highlights are correctly hidden/shown", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.click("#editorHighlight");
await page.waitForSelector(".annotationEditorLayer.highlightEditing");

let rect = await page.$eval(".annotationEditorLayer", el => {
const { x, y } = el.getBoundingClientRect();
return { x, y };
});
const clickHandle = await waitForPointerUp(page);
await page.mouse.move(rect.x + 20, rect.y + 20);
await page.mouse.down();
await page.mouse.move(rect.x + 20, rect.y + 120);
await page.mouse.up();
await awaitPromise(clickHandle);
await page.waitForSelector(getEditorSelector(0));

rect = await getSpanRectFromText(page, 1, "Languages");
await page.mouse.click(
rect.x + rect.width / 2,
rect.y + rect.height / 2,
{ count: 2, delay: 100 }
);
await page.waitForSelector(getEditorSelector(1));

await page.click("#editorHighlightShowAll");
await page.waitForSelector(`${getEditorSelector(0)}.hidden`);
await page.waitForSelector(`${getEditorSelector(1)}.hidden`);

await page.click("#editorHighlightShowAll");
await page.waitForSelector(`${getEditorSelector(0)}:not(.hidden)`);
await page.waitForSelector(`${getEditorSelector(1)}:not(.hidden)`);

await page.click("#editorHighlightShowAll");
await page.waitForSelector(`${getEditorSelector(0)}.hidden`);
await page.waitForSelector(`${getEditorSelector(1)}.hidden`);

const oneToOne = Array.from(new Array(13).keys(), n => n + 2).concat(
Array.from(new Array(13).keys(), n => 13 - n)
);
for (const pageNumber of oneToOne) {
await scrollIntoView(
page,
`.page[data-page-number = "${pageNumber}"]`
);
if (pageNumber === 14) {
await page.click("#editorHighlightShowAll");
}
}

await page.waitForSelector(`${getEditorSelector(0)}:not(.hidden)`);
await page.waitForSelector(`${getEditorSelector(1)}:not(.hidden)`);
})
);
});
});
});
8 changes: 8 additions & 0 deletions web/annotation_editor_layer_builder.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

@import url(draw_layer_builder.css);
@import url(toggle_button.css);

:root {
--outline-width: 2px;
Expand Down Expand Up @@ -1211,4 +1212,11 @@
}
}
}

#editorHighlightVisibility {
display: flex;
justify-content: space-between;
align-items: center;
align-self: stretch;
}
}
9 changes: 9 additions & 0 deletions web/annotation_editor_params.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class AnnotationEditorParams {
editorInkOpacity,
editorStampAddImage,
editorFreeHighlightThickness,
editorHighlightShowAll,
}) {
const dispatchEvent = (typeStr, value) => {
this.eventBus.dispatch("switchannotationeditorparams", {
Expand Down Expand Up @@ -62,6 +63,11 @@ class AnnotationEditorParams {
editorFreeHighlightThickness.addEventListener("input", function () {
dispatchEvent("HIGHLIGHT_THICKNESS", this.valueAsNumber);
});
editorHighlightShowAll.addEventListener("click", function () {
const checked = this.getAttribute("aria-pressed") === "true";
this.setAttribute("aria-pressed", !checked);
calixteman marked this conversation as resolved.
Show resolved Hide resolved
dispatchEvent("HIGHLIGHT_SHOW_ALL", !checked);
});

this.eventBus._on("annotationeditorparamschanged", evt => {
for (const [type, value] of evt.details) {
Expand All @@ -87,6 +93,9 @@ class AnnotationEditorParams {
case AnnotationEditorParamsType.HIGHLIGHT_FREE:
editorFreeHighlightThickness.disabled = !value;
break;
case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:
editorHighlightShowAll.setAttribute("aria-pressed", value);
break;
}
}
});
Expand Down
Loading