All files / core/src/RenderingEngine/GenericViewport/Planar planarImageEvents.ts

0% Statements 0/8
0% Branches 0/14
0% Functions 0/2
0% Lines 0/8

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                                                                                                                                                             
import { Events, OrientationAxis } from '../../../enums';
import triggerEvent from '../../../utilities/triggerEvent';
import type { IImage } from '../../../types';
import type { PlanarViewState } from './PlanarViewportTypes';
 
interface PlanarImageEventContext {
  viewportId: string;
  renderingEngineId: string;
  viewport: { element: HTMLDivElement };
}
 
interface PlanarNewImageArgs {
  image?: IImage;
  imageId?: string;
  imageIdIndex?: number;
}
 
export function triggerPlanarNewImage(
  ctx: PlanarImageEventContext,
  args: PlanarNewImageArgs = {}
): void {
  triggerEvent(ctx.viewport.element, Events.STACK_NEW_IMAGE, {
    image: args.image,
    imageId: args.imageId ?? args.image?.imageId,
    imageIdIndex: args.imageIdIndex,
    viewportId: ctx.viewportId,
    renderingEngineId: ctx.renderingEngineId,
  });
}
 
export function triggerPlanarVolumeNewImage(
  ctx: PlanarImageEventContext,
  params: {
    camera: PlanarViewState | undefined;
    acquisitionOrientation?: PlanarViewState['orientation'];
    imageIds: string[];
    imageIdIndex: number | undefined;
    maxImageIdIndex: number;
  }
): void {
  const orientation = params.camera?.orientation;
  const isAcquisitionAligned =
    !orientation ||
    orientation === OrientationAxis.ACQUISITION ||
    (params.acquisitionOrientation !== undefined &&
      orientation === params.acquisitionOrientation);
 
  if (
    isAcquisitionAligned &&
    typeof params.imageIdIndex === 'number' &&
    params.imageIds[params.imageIdIndex]
  ) {
    triggerPlanarNewImage(ctx, {
      imageId: params.imageIds[params.imageIdIndex],
      imageIdIndex: params.imageIdIndex,
    });
  } else {
    triggerPlanarNewImage(ctx);
  }
 
  // A volume-backed slice change must also emit VOLUME_NEW_IMAGE so that
  // volume-aware consumers (volume scroll indicators, MPR slice synchronizers,
  // segmentation slice tracking) react. The native volume-slice path previously
  // emitted only STACK_NEW_IMAGE, which those consumers do not listen for, so
  // every slice change on a PLANAR_NEXT volume viewport was missed.
  //
  // Only emit when the slice index is known: defaulting an unknown index to 0
  // would incorrectly snap volume-aware consumers to the first slice (this
  // happens on oblique/reformatted planes that do not map to a discrete index).
  if (typeof params.imageIdIndex === 'number') {
    triggerEvent(ctx.viewport.element, Events.VOLUME_NEW_IMAGE, {
      imageIndex: params.imageIdIndex,
      numberOfSlices: params.maxImageIdIndex + 1,
      viewportId: ctx.viewportId,
      renderingEngineId: ctx.renderingEngineId,
    });
  }
}