UNPKG

@aurigma/design-atoms

Version:

Design Atoms is a part of Customer's Canvas SDK which allows for manipulating individual design elements through your code.

330 lines 14.8 kB
import { InputType, NativeEventType, Button, InputState, isNativeMouseEvent } from "./IInputManager"; import { EventObject } from "@aurigma/design-atoms-model/EventObject"; import { PointF, RectangleF } from "@aurigma/design-atoms-model/Math"; import { FrontEndLogger, LogSource, LogClr } from "../../Services/FrontEndLogger"; import { PointerInputHelper } from "./PointerInputHelper"; export class InputManager { constructor(_convertor = null, settings = null) { this._convertor = _convertor; this._touchEndCancel = false; this._keyMap = new Map(); this._onMouseDown = (event) => { if (this._currentAction != null) return; this._pointerInputHelper.onButtonDown(event.coordinates); this._pointerEventNotify(event, InputType.PointerDown); }; this._onMouseMove = (event) => { this._pointerEventNotify(event, InputType.Hover); if ((event.button !== Button.Primary) && (event.button !== Button.Tertiary)) return; if (this._currentAction === InputType.Move) return this._dragEventNotify(event, this._currentAction == null ? InputState.Started : InputState.InProgress); if (this._currentAction == null && this._pointerInputHelper.isButtonDown() == false || this._pointerInputHelper.isInDownUpThresholdArea(event.coordinates, false)) return; this._dragEventNotify(event, this._currentAction == null ? InputState.Started : InputState.InProgress); }; this._onMouseUp = (event) => { if (this._pointerInputHelper.isButtonDown() == false) return; const clickCount = this._pointerInputHelper.onButtonUp(event.coordinates, false, event.button); if (this._currentAction !== InputType.Move) { if (clickCount > 0) this._pointerEventNotify(event, InputType.Click, clickCount); } else { if (event.button !== Button.Primary && event.button !== Button.Secondary && event.button !== Button.Tertiary) return; this._dragEventNotify(event, InputState.Finished); } this._resetState(); }; this._onTouchStart = (event) => { this._touchEndCancel = false; this._pointerInputHelper.onButtonDown(event.touches[0]); this._clearLongTapTimeout(); if (event.touches.length === 2) { this._transformPoints = event.touches; } else { this._longTapTimeout = window.setTimeout(this._onLongTap, this._settings.longTapTime, event); this._pointerEventNotify(event, InputType.PointerDown); } }; this._onTouchMove = (event) => { if (this._pointerInputHelper.isButtonDown() == false) return; if (event.touches.length === 2 && this._currentAction !== InputType.Move) { let state; if (this._currentAction == null) { state = InputState.Started; this._currentAction = InputType.Transform; } else { state = InputState.InProgress; } this._transformEventNotify(event, state); this._transformPoints = event.touches; } else { if (this._currentAction !== InputType.Move && this._pointerInputHelper.isInDownUpThresholdArea(event.touches[0], true)) return; this._clearLongTapTimeout(); this._dragEventNotify(event, this._currentAction == null ? InputState.Started : InputState.InProgress); } }; this._onTouchEnd = (event) => { if (this._pointerInputHelper.isButtonDown() == false || this._touchEndCancel) return; const time = Date.now(); const clickCount = this._pointerInputHelper.onButtonUp(event.changedTouches[0], true, Button.Primary); if (this._currentAction === InputType.Transform) { this._transformEventNotify(event, InputState.Finished); } else if (this._currentAction !== InputType.Move) { if (clickCount > 0) this._pointerEventNotify(event, InputType.Click, clickCount); } else { if (event.touches.length > 0) return; this._dragEventNotify(event, InputState.Finished); } this._resetState(); }; this._resetState = () => { this._currentAction = null; this._transformPoints = null; this._clearLongTapTimeout(); }; this._clearLongTapTimeout = () => { if (this._longTapTimeout != null) clearTimeout(this._longTapTimeout); }; this._onLongTap = (e) => { this._pointerEventNotify(e, InputType.LongTap); this._clearLongTapTimeout(); this._touchEndCancel = true; }; this._pointerEventNotify = (e, type, clickCount = 0) => { const data = this._getPointerArgs(e, type, clickCount); this._emitEvent(data); }; this._transformEventNotify = (e, state) => { try { const args = { preventDefault: e.preventDefault, scale: this._calculateScale(this._transformPoints[0], this._transformPoints[1], e.touches[0], e.touches[1]), translate: this._calculateTransform(this._transformPoints[0], this._transformPoints[1], e.touches[0], e.touches[1]), type: InputType.Transform, state: state, altKey: e.altKey, ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, metaKey: e.metaKey }; this._emitEvent(args); this._transformPoints = e.touches; if (state !== InputState.Finished) this._currentAction = InputType.Transform; } catch (ex) { console.error(ex); } }; this._calculateScale = (oldPoint1, oldPoint2, newPoint1, newPoint2) => { if (oldPoint1 == null || oldPoint2 == null || newPoint1 == null || newPoint2 == null) return 1; const oldDistance = oldPoint1.distance(oldPoint2); const newDistance = newPoint1.distance(newPoint2); if (newDistance <= this._settings.minimalScaleDistance) return 1; const scale = newDistance / oldDistance; return isNaN(scale) ? 1 : scale; }; this._calculateTransform = (oldPoint1, oldPoint2, newPoint1, newPoint2) => { if (oldPoint1 == null || oldPoint2 == null || newPoint1 == null || newPoint2 == null) return new PointF(); const oldRect = RectangleF.fromPoints(oldPoint1, oldPoint2); const newRect = RectangleF.fromPoints(newPoint1, newPoint2); const oldCenter = oldRect.center; const newCenter = newRect.center; return new PointF(newCenter.x - oldCenter.x, newCenter.y - oldCenter.y); }; this._getPointerArgs = (e, type, clickCount = 0) => { const firstPoint = this._getFirstCoordinate(e); const workspaceCoords = this._convertor.pageToWorkspacePoint(firstPoint); const buttonType = isNativeMouseEvent(e) ? e.button : Button.Primary; const data = { page: firstPoint, workspace: workspaceCoords, preventDefault: e.preventDefault, type: type, button: buttonType, isMobile: !isNativeMouseEvent(e), altKey: e.altKey, ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, metaKey: e.metaKey, clickCount: clickCount }; return data; }; this._getFirstCoordinate = (e) => { var _a; return isNativeMouseEvent(e) ? e.coordinates : ((_a = e.touches[0]) !== null && _a !== void 0 ? _a : e.changedTouches[0]); }; this._dragEventNotify = (e, state) => { var _a, _b; const data = this._getPointerArgs(e, InputType.Move); const downPoint = new PointF((_a = this._pointerInputHelper.lastDownPoint) === null || _a === void 0 ? void 0 : _a.x, (_b = this._pointerInputHelper.lastDownPoint) === null || _b === void 0 ? void 0 : _b.y); data.startPage = downPoint.clone(); data.startWorkspace = this._convertor.pageToWorkspacePoint(downPoint); data.state = state; this._emitEvent(data); if (state !== InputState.Finished) this._currentAction = InputType.Move; }; this._onKeyDown = (e) => { const state = this._keyMap.get(e.code); if (this._pointerInputHelper.isButtonDown()) return; if (state == null || state === InputState.Finished) { this._keyMap.set(e.code, InputState.Started); } else { this._keyMap.set(e.code, InputState.InProgress); } this._emitKeyEvent(e); }; this._onKeyUp = (e) => { this._keyMap.set(e.code, InputState.Finished); this._emitKeyEvent(e); }; this._emitKeyEvent = (e) => { const params = { altKey: e.altKey, ctrlKey: e.ctrlKey, code: e.code, key: e.key, preventDefault: e.preventDefault, type: InputType.Key, shiftKey: e.shiftKey, metaKey: e.metaKey, state: this._keyMap.get(e.code) }; this._emitEvent(params); }; this._onWheel = (e) => { const args = { altKey: e.altKey, ctrlKey: e.ctrlKey, delta: e.delta, preventDefault: e.preventDefault, shiftKey: e.shiftKey, type: InputType.Wheel, metaKey: e.metaKey }; this._emitEvent(args); }; this._emitEvent = (data) => { InputManagerLogger.log(data); this._inputEvent.notify(data); }; this._inputEvent = new EventObject(); if (this._convertor == null) this._convertor = { pageToWorkspacePoint: x => x }; const defaultSettings = { clickThreshold: 4, tapThreshold: 10, doubleTapThreshold: 20, doubleTapTime: 500, longTapTime: 500, minimalScaleDistance: 120 }; this._settings = Object.assign(Object.assign({}, defaultSettings), (settings || {})); this._pointerInputHelper = new PointerInputHelper(this._settings); } raiseNativeEvent(event) { switch (event.eventType) { case NativeEventType.MouseDown: this._onMouseDown(event); break; case NativeEventType.MouseMove: this._onMouseMove(event); break; case NativeEventType.MouseUp: this._onMouseUp(event); break; case NativeEventType.TouchStart: const touchEvent = event; this._onTouchStart(touchEvent); break; case NativeEventType.TouchMove: this._onTouchMove(event); break; case NativeEventType.TouchEnd: this._onTouchEnd(event); break; case NativeEventType.KeyDown: this._onKeyDown(event); break; case NativeEventType.KeyUp: this._onKeyUp(event); break; case NativeEventType.Wheel: this._onWheel(event); break; } } addOnInput(handler) { this._inputEvent.add(handler); } removeOnInput(handler) { this._inputEvent.remove(handler); } dispose() { } } class InputManagerLogger { static log(data) { let message = `${LogClr.green(data.type.toString())} was performed!`; switch (data.type) { case InputType.Hover: return; case InputType.Click: case InputType.LongTap: case InputType.PointerDown: let clickData = data; message += ` ${LogClr.cyan(clickData.workspace.toString())}`; message += ` with ${LogClr.green(clickData.button.toString())} button`; message += ` clickCount: ${LogClr.cyan(clickData.clickCount.toString())}`; break; case InputType.Move: let dragData = data; message += ` From ${LogClr.cyan(dragData.startWorkspace.toString())}`; message += ` to ${LogClr.cyan(dragData.workspace.toString())}.`; message += ` State is ${dragData.state}.`; break; case InputType.Key: let keyData = data; message += ` Key code was ${keyData.code}`; if (keyData.altKey) message += ` with alt`; if (keyData.ctrlKey) message += ` with ctrl`; message += `. State is ${keyData.state}.`; break; case InputType.Transform: let transformParams = data; message += ` Scale: ${LogClr.cyan(transformParams.scale.toFixed(2))}, translate: ${LogClr.cyan(transformParams.translate.toString())}`; message += ` State is ${transformParams.state}.`; break; case InputType.Wheel: let wheelParams = data; message += ` Delta: ${wheelParams.delta.toString()}`; break; } FrontEndLogger.debugLog(message, LogSource.InputManager); } } //# sourceMappingURL=InputManager.js.map