All files / packages/tools/src/eventListeners/keyboard keyDownListener.ts

95.45% Statements 21/22
100% Branches 0/0
75% Functions 3/4
95.23% Lines 20/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100                          1x                   1x                             9x   9x 9x   9x 9x 9x 9x   9x 9x                           9x   9x     9x       9x                   9x 9x     9x 9x       167x                
import _cloneDeep from 'lodash.clonedeep';
import { getEnabledElement, triggerEvent } from '@cornerstonejs/core';
import Events from '../../enums/Events';
import { KeyDownEventDetail, KeyUpEventDetail } from '../../types/EventTypes';
 
interface IKeyDownListenerState {
  renderingEngineId: string;
  viewportId: string;
  key: string | null;
  keyCode: number | null;
  element: HTMLDivElement;
}
 
const defaultState: IKeyDownListenerState = {
  //
  renderingEngineId: undefined,
  viewportId: undefined,
  //
  key: undefined,
  keyCode: undefined,
  element: null,
};
 
let state: IKeyDownListenerState = {
  //
  renderingEngineId: undefined,
  viewportId: undefined,
  //
  key: undefined,
  keyCode: undefined,
  element: null,
};
 
/**
 * Normalizes the keyboard event and triggers KEY_DOWN event from CornerstoneTools3D events
 * @param evt - DOM Keyboard event
 */
function keyListener(evt: KeyboardEvent): void {
  state.element = <HTMLDivElement>evt.currentTarget;
 
  const enabledElement = getEnabledElement(state.element);
  const { renderingEngineId, viewportId } = enabledElement;
 
  state.renderingEngineId = renderingEngineId;
  state.viewportId = viewportId;
  state.key = evt.key;
  state.keyCode = evt.keyCode;
 
  evt.preventDefault();
  const eventDetail: KeyDownEventDetail = {
    renderingEngineId: state.renderingEngineId,
    viewportId: state.viewportId,
    element: state.element,
    key: state.key,
    keyCode: state.keyCode,
 
    // detail: evt,
    // Todo: mouse event points can be used later for placing tools with a key
    // e.g., putting an arrow/probe/etc. on the mouse position. Another use case
    // hovering and deleting the tool
    // points: getMouseEventPoints(evt),
  };
 
  triggerEvent(eventDetail.element, Events.KEY_DOWN, eventDetail);
 
  document.addEventListener('keyup', _onKeyUp);
 
  // Todo: handle combination of keys
  state.element.removeEventListener('keydown', keyListener);
}
 
function _onKeyUp(evt: KeyboardEvent): void {
  const eventDetail: KeyUpEventDetail = {
    renderingEngineId: state.renderingEngineId,
    viewportId: state.viewportId,
    element: state.element,
    key: state.key,
    keyCode: state.keyCode,
    // detail: evt,
  };
 
  // Remove our temporary handlers
  document.removeEventListener('keyup', _onKeyUp);
  state.element.addEventListener('keydown', keyListener);
 
  // Restore `state` to `defaultState`
  state = _cloneDeep(defaultState);
  triggerEvent(eventDetail.element, Events.KEY_UP, eventDetail);
}
 
export function getModifierKey(): number | undefined {
  return state.keyCode;
}
 
export function resetModifierKey(): void {
  state.keyCode = undefined;
}
 
export default keyListener;