Skip to content

Commit

Permalink
fix: Make livewire fire the right annotation completed event
Browse files Browse the repository at this point in the history
  • Loading branch information
wayfarer3130 committed Jan 17, 2024
1 parent 16a8e9d commit 7285fd6
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 120 deletions.
24 changes: 22 additions & 2 deletions common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ export abstract class BaseVolumeViewport extends Viewport implements IVolumeView
// (undocumented)
abstract getCurrentImageId(): string;
// (undocumented)
abstract getCurrentImageIdIndex(): number;
// (undocumented)
getDefaultProperties: (volumeId?: string) => VolumeViewportProperties;
// (undocumented)
getFrameOfReferenceUID: () => string;
Expand All @@ -125,6 +123,8 @@ export abstract class BaseVolumeViewport extends Viewport implements IVolumeView
// (undocumented)
getProperties: (volumeId?: string) => VolumeViewportProperties;
// (undocumented)
getReferencedImageId(specifier?: ReferencedImageSpecifier): string;
// (undocumented)
getRotation: () => number;
// (undocumented)
getSlabThickness(): number;
Expand Down Expand Up @@ -2102,6 +2102,8 @@ interface IViewport {
// (undocumented)
_getCorners(bounds: Array<number>): Array<number>[];
// (undocumented)
getCurrentImageIdIndex(): number;
// (undocumented)
getDefaultActor(): ActorEntry;
// (undocumented)
getDisplayArea(): DisplayArea | undefined;
Expand All @@ -2112,6 +2114,8 @@ interface IViewport {
// (undocumented)
getPan(): Point2;
// (undocumented)
getReferencedImageId(forImage?: ReferencedImageSpecifier): string;
// (undocumented)
getRenderer(): void;
// (undocumented)
getRenderingEngine(): any;
Expand Down Expand Up @@ -2539,6 +2543,13 @@ type RangeRetrieveOptions = BaseRetrieveOptions & {
chunkSize?: number | ((metadata: any) => number);
};

// @public (undocumented)
type ReferencedImageSpecifier = {
imageIdIndex?: number;
forFrameOfReference?: boolean;
points?: Point3[];
};

// @public (undocumented)
function registerColormap(colormap: ColormapRegistration): void;

Expand Down Expand Up @@ -2870,6 +2881,8 @@ export class StackViewport extends Viewport implements IStackViewport, IImagesLo
// (undocumented)
getProperties: () => StackViewportProperties;
// (undocumented)
getReferencedImageId(specifier?: ReferencedImageSpecifier): string;
// (undocumented)
getRenderer: () => any;
// (undocumented)
getRotation: () => number;
Expand Down Expand Up @@ -3051,6 +3064,7 @@ declare namespace Types {
IRegisterImageLoader,
IStreamingVolumeProperties,
IViewport,
ReferencedImageSpecifier,
StackViewportProperties,
VolumeViewportProperties,
ViewportProperties,
Expand Down Expand Up @@ -3276,6 +3290,8 @@ export class VideoViewport extends Viewport implements IVideoViewport {
// (undocumented)
getProperties: () => VideoViewportProperties;
// (undocumented)
getReferencedImageId(specifier?: ReferencedImageSpecifier): string;
// (undocumented)
getRotation: () => number;
// (undocumented)
protected getScalarData(): Uint8ClampedArray;
Expand Down Expand Up @@ -3416,6 +3432,8 @@ export class Viewport implements IViewport {
// (undocumented)
_getCorners(bounds: Array<number>): Array<number>[];
// (undocumented)
getCurrentImageIdIndex(): number;
// (undocumented)
getDefaultActor(): ActorEntry;
// (undocumented)
getDisplayArea(): DisplayArea | undefined;
Expand All @@ -3435,6 +3453,8 @@ export class Viewport implements IViewport {
// (undocumented)
getProperties: () => void;
// (undocumented)
getReferencedImageId(specifier?: ReferencedImageSpecifier): string;
// (undocumented)
getRenderer(): any;
// (undocumented)
getRenderingEngine(): IRenderingEngine;
Expand Down
52 changes: 0 additions & 52 deletions packages/tools/examples/interpolationContourSegmentation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
volumeLoader,
getRenderingEngine,
eventTarget,
getEnabledElement,
triggerEvent,
} from '@cornerstonejs/core';
import {
initDemo,
Expand All @@ -18,7 +16,6 @@ import {
} from '../../../../utils/demo/helpers';
import * as cornerstoneTools from '@cornerstonejs/tools';
import { Events } from '../../src/enums';
import { AnnotationLabelChangeEventDetail } from '../../src/types/EventTypes';

// This is for debugging purposes
console.warn(
Expand All @@ -35,7 +32,6 @@ const {
SegmentationDisplayTool,
ToolGroupManager,
Enums: csToolsEnums,
annotation,
segmentation,
} = cornerstoneTools;

Expand Down Expand Up @@ -184,27 +180,6 @@ function addToggleInterpolationButton(toolGroup) {
});
}

function addContourDeleteButton(toolGroup) {
addButtonToToolbar({
title: 'Delete Contour',
onClick: () => {
const annotationData =
annotation.state.getAnnotation(selectedAnnotationId);
if (!selectedAnnotationId || !annotationData) {
alert('Please select any Contour ROI');
return;
}
toolGroup.setToolConfiguration(interpolationToolName, {});
cornerstoneTools.annotation.state.removeAnnotation(
annotationData.annotationUID
);
const { viewport, element } =
getViewportDataBasedOnAnnotation(annotationData);
triggerLabelUpdateCallback({ viewport, element }, annotationData);
},
});
}

const toolGroupId = 'STACK_TOOL_GROUP_ID';
let selectedAnnotationId = '';

Expand Down Expand Up @@ -255,9 +230,6 @@ async function run() {
// set up toggle interpolation tool button.
addToggleInterpolationButton(toolGroup);

// delete button for contour ROI
addContourDeleteButton(toolGroup);

// Get Cornerstone imageIds and fetch metadata into RAM
const stackImageIds = await createImageIdsAndCacheMetaData({
StudyInstanceUID:
Expand All @@ -278,13 +250,6 @@ async function run() {
// Instantiate a rendering engine
const renderingEngine = new RenderingEngine(renderingEngineId);

eventTarget.addEventListener(Events.ANNOTATION_COMPLETED, (evt) => {
const { annotation } = evt.detail;
// annotation.data.label = 'Label';
const { viewport, element } = getViewportDataBasedOnAnnotation(annotation);
triggerLabelUpdateCallback({ viewport, element }, annotation);
});

eventTarget.addEventListener(Events.ANNOTATION_SELECTION_CHANGE, (evt) => {
const { selection } = evt.detail;
selectedAnnotationId = selection[0];
Expand Down Expand Up @@ -390,23 +355,6 @@ function getViewportDataBasedOnAnnotation(annotationData) {
return { viewport, element };
}

function triggerLabelUpdateCallback(eventData, annotation) {
const { element } = eventData;

if (!element) {
return;
}
const { viewportId, renderingEngineId } = getEnabledElement(element);

const eventDetail: AnnotationLabelChangeEventDetail = {
annotation,
renderingEngineId,
viewportId,
};

triggerEvent(eventTarget, Events.ANNOTATION_LABEL_CHANGE, eventDetail);
}

function updateActiveSegmentIndex(segmentIndex: number): void {
segmentation.segmentIndex.setActiveSegmentIndex(segmentationId, segmentIndex);
}
Expand Down
32 changes: 32 additions & 0 deletions packages/tools/src/enums/ChangeTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* ChangeTypes defines the types of changes occurring on annotation and
* segmentation data.
*/
enum ChangeTypes {
/**
* Interaction events are done when the user is actively interacting with
* an annotation, and probably means the event shouldn't be handled/used.
*/
Interaction = 'Interaction',
/**
* HandlesUpdated occurs when the handle data is added or removed, or moved around
*/
HandlesUpdated = 'HandlesUpdated',
/**
* StatsUpdated occurs when the stats are updated/calculated. This can be used
* to ignore stats calculations changes occurring on initial load, while still
* rendering other updates.
*/
StatsUpdated = 'StatsUpdated',
/**
* InitialSetup occurs when an annotation has been created initially and
* has the first render/data calculation being applied.
*/
InitialSetup = 'InitialSetup',
/**
* Completed occurs only for the annotation completed event, just to identify it
*/
Completed = 'Completed',
}

export default ChangeTypes;
2 changes: 2 additions & 0 deletions packages/tools/src/enums/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Events from './Events';
import SegmentationRepresentations from './SegmentationRepresentations';
import { Swipe } from './Touch';
import StrategyCallbacks from './StrategyCallbacks';
import ChangeTypes from './ChangeTypes';

export {
MouseBindings,
Expand All @@ -15,4 +16,5 @@ export {
SegmentationRepresentations,
Swipe,
StrategyCallbacks,
ChangeTypes,
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import InterpolationManager from '../utilities/segmentation/InterpolationManager

const enable = function (element: HTMLDivElement) {
eventTarget.addEventListener(
Events.ANNOTATION_LABEL_CHANGE,
InterpolationManager.handleAnnotationLabelChange as EventListener
Events.ANNOTATION_COMPLETED,
InterpolationManager.handleAnnotationCompleted as EventListener
);
eventTarget.addEventListener(
Events.ANNOTATION_MODIFIED,
Expand All @@ -19,8 +19,8 @@ const enable = function (element: HTMLDivElement) {

const disable = function (element: HTMLDivElement) {
eventTarget.removeEventListener(
Events.ANNOTATION_LABEL_CHANGE,
InterpolationManager.handleAnnotationLabelChange as EventListener
Events.ANNOTATION_COMPLETED,
InterpolationManager.handleAnnotationCompleted as EventListener
);
eventTarget.removeEventListener(
Events.ANNOTATION_MODIFIED,
Expand Down
14 changes: 6 additions & 8 deletions packages/tools/src/tools/annotation/LivewireContourTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import type { Types } from '@cornerstonejs/core';
import { removeAnnotation } from '../../stateManagement/annotation/annotationState';
import { drawHandles as drawHandlesSvg } from '../../drawingSvg';
import { state } from '../../store';
import { Events } from '../../enums';
import { Events, ChangeTypes } from '../../enums';
import { resetElementCursor } from '../../cursors/elementCursor';
import {
import type {
Annotation,
EventTypes,
ToolHandle,
Expand Down Expand Up @@ -89,12 +89,6 @@ class LivewireContourTool extends ContourSegmentationBaseTool {

this.isDrawing = true;

const defaultActor = viewport.getDefaultActor();

// if (!defaultActor || !csUtils.isImageActor(defaultActor)) {
// throw new Error('Default actor must be an image actor');
// }

const viewportImageData = viewport.getImageData();
const { imageData: vtkImageData } = viewportImageData;
let worldToSlice: (point: Types.Point3) => Types.Point2;
Expand Down Expand Up @@ -334,9 +328,13 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);

if (newAnnotation) {
const { viewportId, renderingEngineId } = enabledElement;
const eventType = Events.ANNOTATION_COMPLETED;
const eventDetail: AnnotationCompletedEventDetail = {
annotation,
viewportId,
renderingEngineId,
changeType: ChangeTypes.Completed,
};

triggerEvent(eventTarget, eventType, eventDetail);
Expand Down
6 changes: 5 additions & 1 deletion packages/tools/src/tools/annotation/PlanarFreehandROITool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,12 +420,16 @@ class PlanarFreehandROITool extends ContourSegmentationBaseTool {
* Triggers an annotation completed event.
*/
triggerAnnotationCompleted = (
annotation: PlanarFreehandROIAnnotation
annotation: PlanarFreehandROIAnnotation,
enabledElement?: Types.IEnabledElement
): void => {
const eventType = Events.ANNOTATION_COMPLETED;
const { viewportId, renderingEngineId } = enabledElement || {};

const eventDetail: AnnotationCompletedEventDetail = {
annotation,
viewportId,
renderingEngineId,
};

triggerEvent(eventTarget, eventType, eventDetail);
Expand Down
28 changes: 20 additions & 8 deletions packages/tools/src/tools/annotation/SplineROITool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import {
drawLinkedTextBox as drawLinkedTextBoxSvg,
} from '../../drawingSvg';
import { state } from '../../store';
import { Events, MouseBindings, KeyboardBindings } from '../../enums';
import {
Events,
MouseBindings,
KeyboardBindings,
ChangeTypes,
} from '../../enums';
import { resetElementCursor } from '../../cursors/elementCursor';
import {
Annotation,
Expand Down Expand Up @@ -46,7 +51,6 @@ import { LinearSpline } from './splines/LinearSpline';
import { CatmullRomSpline } from './splines/CatmullRomSpline';
import { BSpline } from './splines/BSpline';
import ContourSegmentationBaseTool from '../base/ContourSegmentationBaseTool';
import { inc } from 'semver';
import reverseIfAntiClockwise from '../../utilities/contours/reverseIfAntiClockwise';

const SPLINE_MIN_POINTS = 3;
Expand Down Expand Up @@ -323,6 +327,12 @@ class SplineROITool extends ContourSegmentationBaseTool {
};

triggerEvent(eventTarget, eventType, eventDetail);
} else {
this.triggerAnnotationModified(
annotation,
enabledElement,
ChangeTypes.HandlesUpdated
);
}

this.editData = null;
Expand Down Expand Up @@ -507,7 +517,8 @@ class SplineROITool extends ContourSegmentationBaseTool {
*/
triggerAnnotationModified = (
annotation: SplineROIAnnotation,
enabledElement: Types.IEnabledElement
enabledElement: Types.IEnabledElement,
changeType = ChangeTypes.StatsUpdated
): void => {
const { viewportId, renderingEngineId } = enabledElement;
const eventType = Events.ANNOTATION_MODIFIED;
Expand All @@ -516,6 +527,7 @@ class SplineROITool extends ContourSegmentationBaseTool {
annotation,
viewportId,
renderingEngineId,
changeType,
};

triggerEvent(eventTarget, eventType, eventDetail);
Expand Down Expand Up @@ -722,10 +734,6 @@ class SplineROITool extends ContourSegmentationBaseTool {
annotationStyle.textbox
);

if (annotation.invalidated) {
this.triggerAnnotationModified(annotation, enabledElement);
}

annotation.invalidated = false;
return true;
}
Expand Down Expand Up @@ -1054,7 +1062,11 @@ class SplineROITool extends ContourSegmentationBaseTool {
};
}

this.triggerAnnotationModified(annotation, enabledElement);
this.triggerAnnotationModified(
annotation,
enabledElement,
ChangeTypes.StatsUpdated
);

return cachedStats;
};
Expand Down
Loading

0 comments on commit 7285fd6

Please sign in to comment.