From cf53b1e883604da5645d5cc616f9634267ec8442 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Fri, 22 Jul 2022 15:49:42 +0200 Subject: [PATCH] [Editor] Fix multi-selection on touch screens --- src/display/editor/annotation_editor_layer.js | 20 ++--- src/display/editor/editor.js | 58 ++++---------- src/display/editor/tools.js | 78 +++++++++++-------- 3 files changed, 67 insertions(+), 89 deletions(-) diff --git a/src/display/editor/annotation_editor_layer.js b/src/display/editor/annotation_editor_layer.js index 9c459628f72501..1f1f188950f73e 100644 --- a/src/display/editor/annotation_editor_layer.js +++ b/src/display/editor/annotation_editor_layer.js @@ -548,6 +548,14 @@ class AnnotationEditorLayer { this.#uiManager.setSelected(editor); } + /** + * Add an editor the current selection. + * @param {AnnotationEditor} editor + */ + addToSelection(editor) { + this.#uiManager.addToSelection(editor); + } + /** * Check if the editor is selected. * @param {AnnotationEditor} editor @@ -564,18 +572,6 @@ class AnnotationEditorLayer { this.#uiManager.unselect(editor); } - get isMultipleSelection() { - return this.#uiManager.isMultipleSelection; - } - - /** - * An editor just got a mousedown with ctrl key pressed. - * @param {boolean}} isMultiple - */ - set isMultipleSelection(isMultiple) { - this.#uiManager.isMultipleSelection = isMultiple; - } - /** * Pointerup callback. * @param {PointerEvent} event diff --git a/src/display/editor/editor.js b/src/display/editor/editor.js index b60ef582654332..9907d036ff3534 100644 --- a/src/display/editor/editor.js +++ b/src/display/editor/editor.js @@ -35,16 +35,12 @@ class AnnotationEditor { #boundFocusout = this.focusout.bind(this); - #isEditing = false; + #hasBeenSelected = false; - #isFocused = false; + #isEditing = false; #isInEditMode = false; - #wasSelected = false; - - #wasFocused = false; - #zIndex = AnnotationEditor._zIndex++; static _colorManager = new ColorManager(); @@ -96,26 +92,14 @@ class AnnotationEditor { this.div.style.zIndex = this.#zIndex; } - #select() { - if (this.#wasSelected) { - this.parent.unselect(this); - this.unselect(); - this.#wasSelected = true; - } else { - this.parent.setSelected(this); - this.select(); - } - } - /** * onfocus callback. */ focusin(event) { - this.#isFocused = - event.target === this.div || - !!event.relatedTarget?.closest(`#${this.id}`); - if (event.target === this.div) { - this.#select(); + if (!this.#hasBeenSelected) { + this.parent.setSelected(this); + } else { + this.#hasBeenSelected = false; } } @@ -139,14 +123,8 @@ class AnnotationEditor { event.preventDefault(); - this.#isFocused = false; if (!this.parent.isMultipleSelection) { this.commitOrRemove(); - if (target?.closest(".annotationEditorLayer")) { - // We only unselect the element when another editor (or its parent) - // is grabbing the focus. - this.parent.unselect(this); - } } } @@ -261,7 +239,7 @@ class AnnotationEditor { const [tx, ty] = this.getInitialTranslation(); this.translate(tx, ty); - bindEvents(this, this.div, ["dragstart", "pointerdown", "pointerup"]); + bindEvents(this, this.div, ["dragstart", "pointerdown"]); return this.div; } @@ -276,22 +254,13 @@ class AnnotationEditor { event.preventDefault(); } - const isMultipleSelection = (this.parent.isMultipleSelection = - event.ctrlKey || event.shiftKey); - this.#wasSelected = isMultipleSelection && this.parent.isSelected(this); - this.#wasFocused = this.#isFocused; - } - - /** - * Onmouseup callback. - * @param {PointerEvent} event - */ - pointerup(event) { - if (this.#wasFocused) { - this.#select(); + if (event.ctrlKey || event.shiftKey) { + this.parent.addToSelection(this); + } else { + this.parent.setSelected(this); } - this.parent.isMultipleSelection = false; - this.#wasFocused = false; + + this.#hasBeenSelected = true; } getRect(tx, ty) { @@ -545,7 +514,6 @@ class AnnotationEditor { set isEditing(value) { this.#isEditing = value; if (value) { - this.select(); this.parent.setSelected(this); this.parent.setActiveEditor(this); } else { diff --git a/src/display/editor/tools.js b/src/display/editor/tools.js index 8d67cc0b1cc73a..cb1e051ee29b97 100644 --- a/src/display/editor/tools.js +++ b/src/display/editor/tools.js @@ -377,8 +377,6 @@ class AnnotationEditorUIManager { #currentPageIndex = 0; - #isMultipleSelection = false; - #editorTypes = null; #eventBus = null; @@ -740,32 +738,41 @@ class AnnotationEditorUIManager { } } + /** + * Add an editor the current selection. + * @param {AnnotationEditor} editor + */ + addToSelection(editor) { + if (this.#selectedEditors.has(editor)) { + this.#selectedEditors.delete(editor); + editor.unselect(); + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection, + }); + return; + } + this.#selectedEditors.add(editor); + editor.select(); + this.#dispatchUpdateUI(editor.propertiesToUpdate); + this.#dispatchUpdateStates({ + hasSelectedEditor: true, + }); + } + /** * Set the last selected editor. * @param {AnnotationEditor} editor */ setSelected(editor) { - if (!this.#isMultipleSelection) { - if (this.#selectedEditors.has(editor)) { - if (this.#selectedEditors.size > 1) { - for (const ed of this.#selectedEditors) { - if (ed !== editor) { - ed.unselect(); - } - } - this.#selectedEditors.clear(); - this.#selectedEditors.add(editor); - this.#dispatchUpdateUI(editor.propertiesToUpdate); - } - return; - } - - for (const ed of this.#selectedEditors) { + for (const ed of this.#selectedEditors) { + if (ed !== editor) { ed.unselect(); } - this.#selectedEditors.clear(); } + this.#selectedEditors.clear(); + this.#selectedEditors.add(editor); + editor.select(); this.#dispatchUpdateUI(editor.propertiesToUpdate); this.#dispatchUpdateStates({ hasSelectedEditor: this.hasSelection, @@ -796,18 +803,6 @@ class AnnotationEditorUIManager { return this.#selectedEditors.size !== 0; } - get isMultipleSelection() { - return this.#isMultipleSelection; - } - - /** - * An editor just got a mousedown with ctrl key pressed. - * @param {boolean} isMultiple - */ - set isMultipleSelection(isMultiple) { - this.#isMultipleSelection = isMultiple; - } - /** * Undo the last command. */ @@ -863,6 +858,11 @@ class AnnotationEditorUIManager { * Delete the current editor or all. */ delete() { + if (this.#activeEditor) { + // An editor is being edited so just commit it. + this.#activeEditor.commitOrRemove(); + } + if (!this.hasSelection) { return; } @@ -886,8 +886,22 @@ class AnnotationEditorUIManager { * Copy the selected editor. */ copy() { + if (this.#activeEditor) { + // An editor is being edited so just commit it. + this.#activeEditor.commitOrRemove(); + } if (this.hasSelection) { - this.#clipboardManager.copy([...this.#selectedEditors]); + const editors = []; + for (const editor of this.#selectedEditors) { + if (!editor.isEmpty()) { + editors.push(editor); + } + } + if (editors.length === 0) { + return; + } + + this.#clipboardManager.copy(editors); this.#dispatchUpdateStates({ hasEmptyClipboard: false }); } }