All files / utils/test testUtilsMouseEvents.ts

96.66% Statements 29/30
80% Branches 8/10
100% Functions 7/7
96.29% Lines 26/27

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 101 102 103 104        1x     146x 146x                                                 146x 146x 146x 292x 438x 146x   146x                                                           20x 20x 20x 20x   20x 16x     20x     20x   20x 20x 20x   20x     20x       20x 20x   20x          
import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
import { getOrCreateCanvas } from '@cornerstonejs/core';
import * as cornerstoneTools from '@cornerstonejs/tools';
 
const { Events } = cornerstoneTools.Enums;
 
function canvasPointsToPagePoints(DomCanvasElement, canvasPoint) {
  const rect = DomCanvasElement.getBoundingClientRect();
  return [
    canvasPoint[0] + rect.left + window.pageXOffset,
    canvasPoint[1] + rect.top + window.pageYOffset,
  ];
}
 
/**
 * This function uses the imageData being displayed on the viewport (the default image) and
 * an index (IJK) on the image to normalize the mouse event details.
 * It should be noted that the normalization is required since client and page XY
 * cannot accept a float. Therefore, for the requested index, canvas coordinate
 * will get calculated and normalized (rounded) to enable normalized client/page XY
 *
 * @param {vtkImageData} imageData
 * @param {[number, number,number]} index - IJK index of the point to click
 * @param {HTMLDivElement} element - the canvas to be clicked on
 * @param {IStackViewport|IVolumeViewport} viewport
 * @returns pageX, pageY, clientX, clientY, worldCoordinate
 */
function createNormalizedMouseEvent(
  imageData: vtkImageData,
  index,
  element,
  viewport
) {
  const canvas = getOrCreateCanvas(element);
  const tempWorld1 = imageData.indexToWorld(index);
  const tempCanvasPoint1 = viewport.worldToCanvas(tempWorld1);
  const canvasPoint1 = tempCanvasPoint1.map((p) => Math.round(p));
  const [pageX, pageY] = canvasPointsToPagePoints(canvas, canvasPoint1);
  const worldCoord = viewport.canvasToWorld(canvasPoint1);
 
  return {
    pageX,
    pageY,
    clientX: pageX,
    clientY: pageY,
    worldCoord,
  };
}
 
/**
 * Asynchronously dispatches a mouse down followed by a mouse up on the given element.
 * Since mouse down events are performed on a timeout to detect potential
 * double clicks, the mouse up event is not triggered until the mouse down
 * event has been processed. An optional callback is invoked after the mouse
 * down is triggered but before the mouse up. An optional callback is invoked
 * after the mouse up has fired.
 *
 * @param element the element to dispatch to
 * @param mouseDownEvent the mouse down event to dispatch
 * @param mouseUpEvent the mouse up event to dispatch
 * @param betweenDownAndUpCallback optional callback between the down and up
 * @param afterDownAndUpCallback optional callback after the up
 * @returns a Promise for the eventual completion of the mouse down and up
 */
function performMouseDownAndUp(
  element: HTMLElement,
  mouseDownEvent: MouseEvent,
  mouseUpEvent: MouseEvent,
  betweenDownAndUpCallback: () => unknown = null,
  afterDownAndUpCallback: () => unknown = null
): Promise<void> {
  return new Promise<void>((resolve) => {
    const mouseDownListener = function () {
      element.removeEventListener(Events.MOUSE_DOWN, mouseDownListener);
 
      if (betweenDownAndUpCallback) {
        betweenDownAndUpCallback();
      }
 
      document.dispatchEvent(mouseUpEvent);
    };
 
    element.addEventListener(Events.MOUSE_DOWN, mouseDownListener);
 
    const mouseUpListener = function () {
      element.removeEventListener(Events.MOUSE_UP, mouseUpListener);
      element.removeEventListener(Events.MOUSE_CLICK, mouseUpListener);
 
      Iif (afterDownAndUpCallback) {
        afterDownAndUpCallback();
      }
      resolve();
    };
 
    // It could be a click or an up.
    element.addEventListener(Events.MOUSE_UP, mouseUpListener);
    element.addEventListener(Events.MOUSE_CLICK, mouseUpListener);
 
    element.dispatchEvent(mouseDownEvent);
  });
}
 
export { createNormalizedMouseEvent, performMouseDownAndUp };