All files / core/src/utilities viewportCapabilities.ts

57.14% Statements 8/14
45.45% Branches 10/22
53.84% Functions 7/13
57.14% Lines 8/14

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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186                                                                                    15097x                 51x                                                         89x                 4330x                                                               4453x                                                                                     1568x                   89x 89x                    
import type {
  ActorEntry,
  IGenericViewport,
  IStackViewport,
  IViewport,
  IVolumeViewport,
  ViewportContentMode,
  VOIRange,
} from '../types';
 
export type ImageSliceViewport = IViewport &
  Pick<
    IStackViewport,
    | 'getCurrentImageId'
    | 'getCurrentImageIdIndex'
    | 'getImageIds'
    | 'hasImageURI'
  >;
 
export type StackCompatibilityViewport = ImageSliceViewport &
  Pick<IStackViewport, 'setStack'>;
 
export type StackCalibrationViewport = ImageSliceViewport & {
  calibrateSpacing(imageId: string): void;
};
 
export type VolumeCompatibilityViewport = IViewport &
  Pick<IVolumeViewport, 'addVolumes' | 'setVolumes'>;
 
export type VolumeIdViewport = IViewport & Pick<IVolumeViewport, 'hasVolumeId'>;
 
export type VolumeURIViewport = IViewport &
  Pick<IVolumeViewport, 'hasVolumeURI'>;
 
export type VolumeActorViewport = VolumeIdViewport & {
  getActors(): ActorEntry[];
};
 
function viewportHasMethod<TMethod extends string>(
  viewport: unknown,
  method: TMethod
): viewport is Record<TMethod, (...args: unknown[]) => unknown> {
  return (
    typeof (viewport as Record<TMethod, unknown> | undefined)?.[method] ===
    'function'
  );
}
 
export function viewportSupportsImageSlices(
  viewport: unknown
): viewport is ImageSliceViewport {
  return (
    viewportHasMethod(viewport, 'getCurrentImageId') &&
    viewportHasMethod(viewport, 'getCurrentImageIdIndex') &&
    viewportHasMethod(viewport, 'getImageIds') &&
    viewportHasMethod(viewport, 'hasImageURI')
  );
}
 
export function viewportSupportsStackCompatibility(
  viewport: unknown
): viewport is StackCompatibilityViewport {
  return (
    viewportSupportsImageSlices(viewport) &&
    viewportHasMethod(viewport, 'setStack')
  );
}
 
export function viewportSupportsStackCalibration(
  viewport: unknown
): viewport is StackCalibrationViewport {
  return (
    viewportSupportsImageSlices(viewport) &&
    viewportHasMethod(viewport, 'calibrateSpacing')
  );
}
 
export function viewportSupportsVolumeCompatibility(
  viewport: unknown
): viewport is VolumeCompatibilityViewport {
  return (
    viewportHasMethod(viewport, 'addVolumes') &&
    viewportHasMethod(viewport, 'setVolumes')
  );
}
 
export function viewportSupportsVolumeId(
  viewport: unknown
): viewport is VolumeIdViewport {
  return viewportHasMethod(viewport, 'hasVolumeId');
}
 
export function viewportSupportsVolumeURI(
  viewport: unknown
): viewport is VolumeURIViewport {
  return viewportHasMethod(viewport, 'hasVolumeURI');
}
 
export function viewportSupportsVolumeActors(
  viewport: unknown
): viewport is VolumeActorViewport {
  return (
    viewportSupportsVolumeId(viewport) &&
    viewportHasMethod(viewport, 'getActors')
  );
}
 
/**
 * Narrows a viewport to the direct Generic ("next") viewport surface
 * (`setDisplaySets` / `setDisplaySetPresentation` / `setViewState` and the
 * related data/view-state APIs).
 *
 * Use this instead of `instanceof PlanarViewport` (or a `viewport.type` check)
 * when code needs the native-next API rather than the legacy stack/volume
 * method surface. A viewport created with a legacy compatibility adapter is
 * intentionally NOT matched: it exposes the legacy methods, not the direct
 * Generic surface.
 */
export function isGenericViewport(
  viewport: unknown
): viewport is IGenericViewport {
  return (
    viewportHasMethod(viewport, 'setDisplaySets') &&
    viewportHasMethod(viewport, 'setDisplaySetPresentation') &&
    viewportHasMethod(viewport, 'setViewState')
  );
}
 
/**
 * A Generic ("next") viewport that also exposes the per-display-set source/VOI
 * accessors. These live only on the `PlanarViewport` family (not video / WSI /
 * ECG / 3D), so they are gated by a focused guard rather than declared on
 * `IGenericViewport` — narrowing to this lets the VOI-region / livewire tools
 * read the bound dataId and its default VOI without an inline cast.
 */
export type DisplaySetPresentationViewport = IGenericViewport & {
  getSourceDataId(): string | undefined;
  getDefaultVOIRange(dataId?: string): VOIRange | undefined;
};
 
export function viewportSupportsDisplaySetPresentation(
  viewport: unknown
): viewport is DisplaySetPresentationViewport {
  return (
    isGenericViewport(viewport) &&
    viewportHasMethod(viewport, 'getSourceDataId') &&
    viewportHasMethod(viewport, 'getDefaultVOIRange')
  );
}
 
/**
 * Returns the content-true mode of the viewport's bound source data when the
 * viewport can classify it (i.e. exposes `getCurrentMode`), otherwise
 * `undefined`.
 *
 * Unlike the capability guards above (which test method presence), this reports
 * what the viewport is actually showing — the question a `PLANAR_NEXT` viewport
 * cannot answer through `viewportSupportsImageSlices` /
 * `viewportSupportsVolumeId` alone, since it supports both regardless of
 * content. See {@link ViewportContentMode}.
 */
export function getViewportContentMode(
  viewport: unknown
): ViewportContentMode | undefined {
  return viewportHasMethod(viewport, 'getCurrentMode')
    ? (viewport as IGenericViewport).getCurrentMode()
    : undefined;
}
 
/**
 * Returns `true` when the viewport is currently rendering volume-backed content
 * (a volume slice or a 3D volume). Content-true; see {@link getViewportContentMode}.
 */
export function viewportIsInVolumeMode(viewport: unknown): boolean {
  const mode = getViewportContentMode(viewport);
  return mode === 'volume' || mode === 'volume3d';
}
 
/**
 * Returns `true` when the viewport is currently rendering image-id stack
 * content. Content-true; see {@link getViewportContentMode}.
 */
export function viewportIsInStackMode(viewport: unknown): boolean {
  return getViewportContentMode(viewport) === 'stack';
}