Merge pull request #20213 from lab-core/pointer-type
[Editor] A new CurrentPointers class to store current pointers used by the editor
This commit is contained in:
commit
2cc809ade2
@ -16,6 +16,7 @@
|
|||||||
import { AnnotationEditorParamsType, unreachable } from "../../shared/util.js";
|
import { AnnotationEditorParamsType, unreachable } from "../../shared/util.js";
|
||||||
import { noContextMenu, stopEvent } from "../display_utils.js";
|
import { noContextMenu, stopEvent } from "../display_utils.js";
|
||||||
import { AnnotationEditor } from "./editor.js";
|
import { AnnotationEditor } from "./editor.js";
|
||||||
|
import { CurrentPointers } from "./tools.js";
|
||||||
|
|
||||||
class DrawingOptions {
|
class DrawingOptions {
|
||||||
#svgProperties = Object.create(null);
|
#svgProperties = Object.create(null);
|
||||||
@ -81,14 +82,6 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
|
|
||||||
static #currentDrawingOptions = null;
|
static #currentDrawingOptions = null;
|
||||||
|
|
||||||
static #currentPointerId = NaN;
|
|
||||||
|
|
||||||
static #currentPointerType = null;
|
|
||||||
|
|
||||||
static #currentPointerIds = null;
|
|
||||||
|
|
||||||
static #currentMoveTimestamp = NaN;
|
|
||||||
|
|
||||||
static _INNER_MARGIN = 3;
|
static _INNER_MARGIN = 3;
|
||||||
|
|
||||||
constructor(params) {
|
constructor(params) {
|
||||||
@ -678,20 +671,15 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static startDrawing(parent, uiManager, _isLTR, event) {
|
static startDrawing(parent, uiManager, _isLTR, event) {
|
||||||
// The _currentPointerType is set when the user starts an empty drawing
|
// The pointerType of CurrentPointer is set when the user starts an empty
|
||||||
// session. If, in the same drawing session, the user starts using a
|
// drawing session. If, in the same drawing session, the user starts using a
|
||||||
// different type of pointer (e.g. a pen and then a finger), we just return.
|
// different type of pointer (e.g. a pen and then a finger), we just return.
|
||||||
//
|
//
|
||||||
// The _currentPointerId and _currentPointerIds are used to keep track of
|
// If the user starts to draw with a finger and then uses a second finger,
|
||||||
// the pointers with a same type (e.g. two fingers). If the user starts to
|
// we just stop the current drawing and let the user zoom the document.
|
||||||
// draw with a finger and then uses a second finger, we just stop the
|
|
||||||
// current drawing and let the user zoom the document.
|
|
||||||
|
|
||||||
const { target, offsetX: x, offsetY: y, pointerId, pointerType } = event;
|
const { target, offsetX: x, offsetY: y, pointerId, pointerType } = event;
|
||||||
if (
|
if (CurrentPointers.isInitializedAndDifferentPointerType(pointerType)) {
|
||||||
DrawingEditor.#currentPointerType &&
|
|
||||||
DrawingEditor.#currentPointerType !== pointerType
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,16 +692,13 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
const ac = (DrawingEditor.#currentDrawingAC = new AbortController());
|
const ac = (DrawingEditor.#currentDrawingAC = new AbortController());
|
||||||
const signal = parent.combinedSignal(ac);
|
const signal = parent.combinedSignal(ac);
|
||||||
|
|
||||||
DrawingEditor.#currentPointerId ||= pointerId;
|
CurrentPointers.setPointer(pointerType, pointerId);
|
||||||
DrawingEditor.#currentPointerType ??= pointerType;
|
|
||||||
|
|
||||||
window.addEventListener(
|
window.addEventListener(
|
||||||
"pointerup",
|
"pointerup",
|
||||||
e => {
|
e => {
|
||||||
if (DrawingEditor.#currentPointerId === e.pointerId) {
|
if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) {
|
||||||
this._endDraw(e);
|
this._endDraw(e);
|
||||||
} else {
|
|
||||||
DrawingEditor.#currentPointerIds?.delete(e.pointerId);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ signal }
|
{ signal }
|
||||||
@ -721,10 +706,8 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
window.addEventListener(
|
window.addEventListener(
|
||||||
"pointercancel",
|
"pointercancel",
|
||||||
e => {
|
e => {
|
||||||
if (DrawingEditor.#currentPointerId === e.pointerId) {
|
if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) {
|
||||||
this._currentParent.endDrawingSession();
|
this._currentParent.endDrawingSession();
|
||||||
} else {
|
|
||||||
DrawingEditor.#currentPointerIds?.delete(e.pointerId);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ signal }
|
{ signal }
|
||||||
@ -732,14 +715,14 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
window.addEventListener(
|
window.addEventListener(
|
||||||
"pointerdown",
|
"pointerdown",
|
||||||
e => {
|
e => {
|
||||||
if (DrawingEditor.#currentPointerType !== e.pointerType) {
|
if (!CurrentPointers.isSamePointerType(e.pointerType)) {
|
||||||
// For example, we started with a pen and the user
|
// For example, we started with a pen and the user
|
||||||
// is now using a finger.
|
// is now using a finger.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For example, the user is using a second finger.
|
// For example, the user is using a second finger.
|
||||||
(DrawingEditor.#currentPointerIds ||= new Set()).add(e.pointerId);
|
CurrentPointers.initializeAndAddPointerId(e.pointerId);
|
||||||
|
|
||||||
// The first finger created a first point and a second finger just
|
// The first finger created a first point and a second finger just
|
||||||
// started, so we stop the drawing and remove this only point.
|
// started, so we stop the drawing and remove this only point.
|
||||||
@ -765,7 +748,7 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
target.addEventListener(
|
target.addEventListener(
|
||||||
"touchmove",
|
"touchmove",
|
||||||
e => {
|
e => {
|
||||||
if (e.timeStamp === DrawingEditor.#currentMoveTimestamp) {
|
if (CurrentPointers.isSameTimeStamp(e.timeStamp)) {
|
||||||
// This move event is used to draw so we don't want to scroll.
|
// This move event is used to draw so we don't want to scroll.
|
||||||
stopEvent(e);
|
stopEvent(e);
|
||||||
}
|
}
|
||||||
@ -812,16 +795,16 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static _drawMove(event) {
|
static _drawMove(event) {
|
||||||
DrawingEditor.#currentMoveTimestamp = -1;
|
CurrentPointers.isSameTimeStamp(event.timeStamp);
|
||||||
if (!DrawingEditor.#currentDraw) {
|
if (!DrawingEditor.#currentDraw) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { offsetX, offsetY, pointerId } = event;
|
const { offsetX, offsetY, pointerId } = event;
|
||||||
|
|
||||||
if (DrawingEditor.#currentPointerId !== pointerId) {
|
if (!CurrentPointers.isSamePointerId(pointerId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (DrawingEditor.#currentPointerIds?.size >= 1) {
|
if (CurrentPointers.isUsingMultiplePointers()) {
|
||||||
// The user is using multiple fingers and the first one is moving.
|
// The user is using multiple fingers and the first one is moving.
|
||||||
this._endDraw(event);
|
this._endDraw(event);
|
||||||
return;
|
return;
|
||||||
@ -831,7 +814,7 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
DrawingEditor.#currentDraw.add(offsetX, offsetY)
|
DrawingEditor.#currentDraw.add(offsetX, offsetY)
|
||||||
);
|
);
|
||||||
// We track the timestamp to know if the touchmove event is used to draw.
|
// We track the timestamp to know if the touchmove event is used to draw.
|
||||||
DrawingEditor.#currentMoveTimestamp = event.timeStamp;
|
CurrentPointers.setTimeStamp(event.timeStamp);
|
||||||
stopEvent(event);
|
stopEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -841,15 +824,14 @@ class DrawingEditor extends AnnotationEditor {
|
|||||||
this._currentParent = null;
|
this._currentParent = null;
|
||||||
DrawingEditor.#currentDraw = null;
|
DrawingEditor.#currentDraw = null;
|
||||||
DrawingEditor.#currentDrawingOptions = null;
|
DrawingEditor.#currentDrawingOptions = null;
|
||||||
DrawingEditor.#currentPointerType = null;
|
CurrentPointers.clearPointerType();
|
||||||
DrawingEditor.#currentMoveTimestamp = NaN;
|
CurrentPointers.clearTimeStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DrawingEditor.#currentDrawingAC) {
|
if (DrawingEditor.#currentDrawingAC) {
|
||||||
DrawingEditor.#currentDrawingAC.abort();
|
DrawingEditor.#currentDrawingAC.abort();
|
||||||
DrawingEditor.#currentDrawingAC = null;
|
DrawingEditor.#currentDrawingAC = null;
|
||||||
DrawingEditor.#currentPointerId = NaN;
|
CurrentPointers.clearPointerIds();
|
||||||
DrawingEditor.#currentPointerIds = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,87 @@ function bindEvents(obj, element, names) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to store current pointers used by the editor to be able to handle
|
||||||
|
* multiple pointers (e.g. two fingers, a pen, a mouse, ...).
|
||||||
|
*/
|
||||||
|
class CurrentPointers {
|
||||||
|
// To manage the pointer events.
|
||||||
|
|
||||||
|
// The pointerId and pointerIds are used to keep track of
|
||||||
|
// the pointers with a same type (e.g. two fingers).
|
||||||
|
static #pointerId = NaN;
|
||||||
|
|
||||||
|
static #pointerIds = null;
|
||||||
|
|
||||||
|
// Track the timestamp to know if the touchmove event is used.
|
||||||
|
static #moveTimestamp = NaN;
|
||||||
|
|
||||||
|
// The pointerType is used to know if we are using a mouse, a pen or a touch.
|
||||||
|
static #pointerType = null;
|
||||||
|
|
||||||
|
static initializeAndAddPointerId(pointerId) {
|
||||||
|
// Store pointer ids. For example, the user is using a second finger.
|
||||||
|
(CurrentPointers.#pointerIds ||= new Set()).add(pointerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static setPointer(pointerType, pointerId) {
|
||||||
|
CurrentPointers.#pointerId ||= pointerId;
|
||||||
|
CurrentPointers.#pointerType ??= pointerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static setTimeStamp(timeStamp) {
|
||||||
|
CurrentPointers.#moveTimestamp = timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isSamePointerId(pointerId) {
|
||||||
|
return CurrentPointers.#pointerId === pointerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's the same pointer id, otherwise remove it from the set.
|
||||||
|
static isSamePointerIdOrRemove(pointerId) {
|
||||||
|
if (CurrentPointers.#pointerId === pointerId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentPointers.#pointerIds?.delete(pointerId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isSamePointerType(pointerType) {
|
||||||
|
return CurrentPointers.#pointerType === pointerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isInitializedAndDifferentPointerType(pointerType) {
|
||||||
|
return (
|
||||||
|
CurrentPointers.#pointerType !== null &&
|
||||||
|
!CurrentPointers.isSamePointerType(pointerType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isSameTimeStamp(timeStamp) {
|
||||||
|
return CurrentPointers.#moveTimestamp === timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isUsingMultiplePointers() {
|
||||||
|
// Check if the user is using multiple fingers
|
||||||
|
return CurrentPointers.#pointerIds?.size >= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clearPointerType() {
|
||||||
|
CurrentPointers.#pointerType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clearPointerIds() {
|
||||||
|
CurrentPointers.#pointerId = NaN;
|
||||||
|
CurrentPointers.#pointerIds = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clearTimeStamp() {
|
||||||
|
CurrentPointers.#moveTimestamp = NaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to create some unique ids for the different editors.
|
* Class to create some unique ids for the different editors.
|
||||||
*/
|
*/
|
||||||
@ -2801,5 +2882,6 @@ export {
|
|||||||
bindEvents,
|
bindEvents,
|
||||||
ColorManager,
|
ColorManager,
|
||||||
CommandManager,
|
CommandManager,
|
||||||
|
CurrentPointers,
|
||||||
KeyboardManager,
|
KeyboardManager,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user