From 52cc9e6ce3bcd2e016b52c2a514978be71df0439 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Wed, 15 May 2019 20:51:02 -0700 Subject: [PATCH] added unbound InputObserver --- src/mol-canvas3d/canvas3d.ts | 4 +- src/mol-util/input/input-observer.ts | 114 +++++++++++++++------------ 2 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index 1caea985d..a4a5648a9 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -101,8 +101,8 @@ namespace Canvas3D { preserveDrawingBuffer: true }) if (gl === null) throw new Error('Could not create a WebGL rendering context') - const input = InputObserver.create(canvas) - return Canvas3D.create(gl, input) + const input = InputObserver.fromElement(canvas) + return Canvas3D.create(gl, input, props) } export function create(gl: GLRenderingContext, input: InputObserver, props: Partial<Canvas3DProps> = {}): Canvas3D { diff --git a/src/mol-util/input/input-observer.ts b/src/mol-util/input/input-observer.ts index 8b08cb2fb..d9b521298 100644 --- a/src/mol-util/input/input-observer.ts +++ b/src/mol-util/input/input-observer.ts @@ -8,7 +8,7 @@ import { Subject, Observable } from 'rxjs'; import { Vec2 } from 'mol-math/linear-algebra'; -import { BitFlags } from 'mol-util'; +import { BitFlags, noop } from 'mol-util'; function getButtons(event: MouseEvent | Touch) { if (typeof event === 'object') { @@ -144,23 +144,50 @@ interface InputObserver { noScroll: boolean noContextMenu: boolean - drag: Observable<DragInput>, + readonly drag: Observable<DragInput>, // Equivalent to mouseUp and touchEnd - interactionEnd: Observable<undefined>, - wheel: Observable<WheelInput>, - pinch: Observable<PinchInput>, - click: Observable<ClickInput>, - move: Observable<MoveInput>, - leave: Observable<undefined>, - enter: Observable<undefined>, - resize: Observable<ResizeInput>, - modifiers: Observable<ModifiersKeys> + readonly interactionEnd: Observable<undefined>, + readonly wheel: Observable<WheelInput>, + readonly pinch: Observable<PinchInput>, + readonly click: Observable<ClickInput>, + readonly move: Observable<MoveInput>, + readonly leave: Observable<undefined>, + readonly enter: Observable<undefined>, + readonly resize: Observable<ResizeInput>, + readonly modifiers: Observable<ModifiersKeys> dispose: () => void } +function createEvents() { + return { + drag: new Subject<DragInput>(), + interactionEnd: new Subject<undefined>(), + click: new Subject<ClickInput>(), + move: new Subject<MoveInput>(), + wheel: new Subject<WheelInput>(), + pinch: new Subject<PinchInput>(), + resize: new Subject<ResizeInput>(), + leave: new Subject<undefined>(), + enter: new Subject<undefined>(), + modifiers: new Subject<ModifiersKeys>(), + } +} + namespace InputObserver { - export function create (element: Element, props: InputObserverProps = {}): InputObserver { + export function create(props: InputObserverProps = {}): InputObserver { + const { noScroll, noContextMenu } = { ...DefaultInputObserverProps, ...props } + return { + noScroll, + noContextMenu, + + ...createEvents(), + + dispose: noop + } + } + + export function fromElement(element: Element, props: InputObserverProps = {}): InputObserver { let { noScroll, noContextMenu, noPinchZoom } = { ...DefaultInputObserverProps, ...props } let lastTouchDistance = 0 @@ -169,15 +196,15 @@ namespace InputObserver { const pointerEnd = Vec2.zero() const pointerDelta = Vec2.zero() const rectSize = Vec2.zero() - const modifiers: ModifiersKeys = { + const modifierKeys: ModifiersKeys = { shift: false, alt: false, control: false, meta: false } - function getModifiers(): ModifiersKeys { - return { ...modifiers }; + function getModifierKeys(): ModifiersKeys { + return { ...modifierKeys }; } let dragging: DraggingState = DraggingState.Stopped @@ -185,16 +212,8 @@ namespace InputObserver { let buttons = 0 as ButtonsType let isInside = false - const drag = new Subject<DragInput>() - const interactionEnd = new Subject<undefined>(); - const click = new Subject<ClickInput>() - const move = new Subject<MoveInput>() - const wheel = new Subject<WheelInput>() - const pinch = new Subject<PinchInput>() - const resize = new Subject<ResizeInput>() - const leave = new Subject<undefined>() - const enter = new Subject<undefined>() - const modifiersEvent = new Subject<ModifiersKeys>() + const events = createEvents() + const { drag, interactionEnd, wheel, pinch, click, move, leave, enter, resize, modifiers } = events attach() @@ -204,22 +223,13 @@ namespace InputObserver { get noContextMenu () { return noContextMenu }, set noContextMenu (value: boolean) { noContextMenu = value }, - drag, - interactionEnd, - wheel, - pinch, - click, - move, - leave, - enter, - resize, - modifiers: modifiersEvent, + ...events, dispose } function attach () { - element.addEventListener( 'contextmenu', onContextMenu, false ) + element.addEventListener('contextmenu', onContextMenu, false ) element.addEventListener('wheel', onMouseWheel as any, false) element.addEventListener('mousedown', onMouseDown as any, false) @@ -274,31 +284,31 @@ namespace InputObserver { } function handleBlur () { - if (buttons || modifiers.shift || modifiers.alt || modifiers.meta || modifiers.control) { + if (buttons || modifierKeys.shift || modifierKeys.alt || modifierKeys.meta || modifierKeys.control) { buttons = 0 as ButtonsType - modifiers.shift = modifiers.alt = modifiers.control = modifiers.meta = false + modifierKeys.shift = modifierKeys.alt = modifierKeys.control = modifierKeys.meta = false } } function handleKeyDown (event: KeyboardEvent) { let changed = false; - if (!modifiers.alt && event.altKey) { changed = true; modifiers.alt = true; } - if (!modifiers.shift && event.shiftKey) { changed = true; modifiers.shift = true; } - if (!modifiers.control && event.ctrlKey) { changed = true; modifiers.control = true; } - if (!modifiers.meta && event.metaKey) { changed = true; modifiers.meta = true; } + if (!modifierKeys.alt && event.altKey) { changed = true; modifierKeys.alt = true; } + if (!modifierKeys.shift && event.shiftKey) { changed = true; modifierKeys.shift = true; } + if (!modifierKeys.control && event.ctrlKey) { changed = true; modifierKeys.control = true; } + if (!modifierKeys.meta && event.metaKey) { changed = true; modifierKeys.meta = true; } - if (changed && isInside) modifiersEvent.next(getModifiers()); + if (changed && isInside) modifiers.next(getModifierKeys()); } function handleKeyUp (event: KeyboardEvent) { let changed = false; - if (modifiers.alt && !event.altKey) { changed = true; modifiers.alt = false; } - if (modifiers.shift && !event.shiftKey) { changed = true; modifiers.shift = false; } - if (modifiers.control && !event.ctrlKey) { changed = true; modifiers.control = false; } - if (modifiers.meta && !event.metaKey) { changed = true; modifiers.meta = false; } + if (modifierKeys.alt && !event.altKey) { changed = true; modifierKeys.alt = false; } + if (modifierKeys.shift && !event.shiftKey) { changed = true; modifierKeys.shift = false; } + if (modifierKeys.control && !event.ctrlKey) { changed = true; modifierKeys.control = false; } + if (modifierKeys.meta && !event.metaKey) { changed = true; modifierKeys.meta = false; } - if (changed && isInside) modifiersEvent.next(getModifiers()); + if (changed && isInside) modifiers.next(getModifierKeys()); } function getCenterTouch (ev: TouchEvent): PointerEvent { @@ -403,7 +413,7 @@ namespace InputObserver { const { pageX, pageY } = ev const [ x, y ] = pointerEnd - click.next({ x, y, pageX, pageY, buttons, modifiers: getModifiers() }) + click.next({ x, y, pageX, pageY, buttons, modifiers: getModifierKeys() }) } } @@ -412,7 +422,7 @@ namespace InputObserver { const { pageX, pageY } = ev const [ x, y ] = pointerEnd const inside = insideBounds(pointerEnd) - move.next({ x, y, pageX, pageY, buttons, modifiers: getModifiers(), inside }) + move.next({ x, y, pageX, pageY, buttons, modifiers: getModifierKeys(), inside }) if (dragging === DraggingState.Stopped) return @@ -420,7 +430,7 @@ namespace InputObserver { const isStart = dragging === DraggingState.Started const [ dx, dy ] = pointerDelta - drag.next({ x, y, dx, dy, pageX, pageY, buttons, modifiers: getModifiers(), isStart }) + drag.next({ x, y, dx, dy, pageX, pageY, buttons, modifiers: getModifierKeys(), isStart }) Vec2.copy(pointerStart, pointerEnd) dragging = DraggingState.Moving @@ -443,7 +453,7 @@ namespace InputObserver { const dz = (ev.deltaZ || 0) * scale if (dx || dy || dz) { - wheel.next({ dx, dy, dz, buttons, modifiers: getModifiers() }) + wheel.next({ dx, dy, dz, buttons, modifiers: getModifierKeys() }) } } -- GitLab