@cornerstonejs/tools 1.20.3 → 1.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/cjs/drawingSvg/getSvgDrawingHelper.js +1 -1
  2. package/dist/cjs/drawingSvg/getSvgDrawingHelper.js.map +1 -1
  3. package/dist/cjs/enums/Events.d.ts +1 -0
  4. package/dist/cjs/enums/Events.js +1 -0
  5. package/dist/cjs/enums/Events.js.map +1 -1
  6. package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDown.js +5 -0
  7. package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDown.js.map +1 -1
  8. package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.d.ts +2 -0
  9. package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js +41 -0
  10. package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js.map +1 -0
  11. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.d.ts +3 -0
  12. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js +39 -0
  13. package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -0
  14. package/dist/cjs/eventListeners/mouse/mouseDownListener.js +5 -1
  15. package/dist/cjs/eventListeners/mouse/mouseDownListener.js.map +1 -1
  16. package/dist/cjs/eventListeners/mouse/mouseMoveListener.js +5 -1
  17. package/dist/cjs/eventListeners/mouse/mouseMoveListener.js.map +1 -1
  18. package/dist/cjs/index.d.ts +2 -2
  19. package/dist/cjs/index.js +3 -2
  20. package/dist/cjs/index.js.map +1 -1
  21. package/dist/cjs/store/ToolGroupManager/ToolGroup.d.ts +2 -0
  22. package/dist/cjs/store/ToolGroupManager/ToolGroup.js +35 -0
  23. package/dist/cjs/store/ToolGroupManager/ToolGroup.js.map +1 -1
  24. package/dist/cjs/tools/AdvancedMagnifyTool.d.ts +36 -0
  25. package/dist/cjs/tools/AdvancedMagnifyTool.js +448 -0
  26. package/dist/cjs/tools/AdvancedMagnifyTool.js.map +1 -0
  27. package/dist/cjs/tools/AdvancedMagnifyViewport.d.ts +76 -0
  28. package/dist/cjs/tools/AdvancedMagnifyViewport.js +352 -0
  29. package/dist/cjs/tools/AdvancedMagnifyViewport.js.map +1 -0
  30. package/dist/cjs/tools/AdvancedMagnifyViewportManager.d.ts +36 -0
  31. package/dist/cjs/tools/AdvancedMagnifyViewportManager.js +133 -0
  32. package/dist/cjs/tools/AdvancedMagnifyViewportManager.js.map +1 -0
  33. package/dist/cjs/tools/annotation/EllipticalROITool.d.ts +1 -1
  34. package/dist/cjs/tools/annotation/EllipticalROITool.js +12 -8
  35. package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
  36. package/dist/cjs/tools/index.d.ts +2 -1
  37. package/dist/cjs/tools/index.js +3 -1
  38. package/dist/cjs/tools/index.js.map +1 -1
  39. package/dist/cjs/types/EventTypes.d.ts +9 -1
  40. package/dist/cjs/types/IToolGroup.d.ts +3 -0
  41. package/dist/cjs/types/ToolAction.d.ts +8 -0
  42. package/dist/cjs/types/ToolAction.js +3 -0
  43. package/dist/cjs/types/ToolAction.js.map +1 -0
  44. package/dist/cjs/types/ToolSpecificAnnotationTypes.d.ts +11 -0
  45. package/dist/cjs/types/index.d.ts +2 -1
  46. package/dist/esm/drawingSvg/getSvgDrawingHelper.js +1 -1
  47. package/dist/esm/drawingSvg/getSvgDrawingHelper.js.map +1 -1
  48. package/dist/esm/enums/Events.d.ts +1 -0
  49. package/dist/esm/enums/Events.js +1 -0
  50. package/dist/esm/enums/Events.js.map +1 -1
  51. package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDown.js +5 -0
  52. package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDown.js.map +1 -1
  53. package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.d.ts +2 -0
  54. package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js +35 -0
  55. package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js.map +1 -0
  56. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.d.ts +3 -0
  57. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js +32 -0
  58. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -0
  59. package/dist/esm/eventListeners/mouse/mouseDownListener.js +5 -1
  60. package/dist/esm/eventListeners/mouse/mouseDownListener.js.map +1 -1
  61. package/dist/esm/eventListeners/mouse/mouseMoveListener.js +5 -1
  62. package/dist/esm/eventListeners/mouse/mouseMoveListener.js.map +1 -1
  63. package/dist/esm/index.d.ts +2 -2
  64. package/dist/esm/index.js +2 -2
  65. package/dist/esm/index.js.map +1 -1
  66. package/dist/esm/store/ToolGroupManager/ToolGroup.d.ts +2 -0
  67. package/dist/esm/store/ToolGroupManager/ToolGroup.js +35 -1
  68. package/dist/esm/store/ToolGroupManager/ToolGroup.js.map +1 -1
  69. package/dist/esm/tools/AdvancedMagnifyTool.d.ts +36 -0
  70. package/dist/esm/tools/AdvancedMagnifyTool.js +440 -0
  71. package/dist/esm/tools/AdvancedMagnifyTool.js.map +1 -0
  72. package/dist/esm/tools/AdvancedMagnifyViewport.d.ts +76 -0
  73. package/dist/esm/tools/AdvancedMagnifyViewport.js +346 -0
  74. package/dist/esm/tools/AdvancedMagnifyViewport.js.map +1 -0
  75. package/dist/esm/tools/AdvancedMagnifyViewportManager.d.ts +36 -0
  76. package/dist/esm/tools/AdvancedMagnifyViewportManager.js +128 -0
  77. package/dist/esm/tools/AdvancedMagnifyViewportManager.js.map +1 -0
  78. package/dist/esm/tools/annotation/EllipticalROITool.d.ts +1 -1
  79. package/dist/esm/tools/annotation/EllipticalROITool.js +12 -8
  80. package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
  81. package/dist/esm/tools/index.d.ts +2 -1
  82. package/dist/esm/tools/index.js +2 -1
  83. package/dist/esm/tools/index.js.map +1 -1
  84. package/dist/esm/types/EventTypes.d.ts +9 -1
  85. package/dist/esm/types/IToolGroup.d.ts +3 -0
  86. package/dist/esm/types/ToolAction.d.ts +8 -0
  87. package/dist/esm/types/ToolAction.js +2 -0
  88. package/dist/esm/types/ToolAction.js.map +1 -0
  89. package/dist/esm/types/ToolSpecificAnnotationTypes.d.ts +11 -0
  90. package/dist/esm/types/index.d.ts +2 -1
  91. package/dist/umd/index.js +1 -1
  92. package/dist/umd/index.js.map +1 -1
  93. package/package.json +3 -3
  94. package/src/drawingSvg/getSvgDrawingHelper.ts +4 -1
  95. package/src/enums/Events.ts +9 -0
  96. package/src/eventDispatchers/mouseEventHandlers/mouseDown.ts +10 -1
  97. package/src/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.ts +72 -0
  98. package/src/eventDispatchers/shared/getToolsWithActionsForMouseEvent.ts +66 -0
  99. package/src/eventListeners/mouse/mouseDownListener.ts +7 -1
  100. package/src/eventListeners/mouse/mouseMoveListener.ts +7 -1
  101. package/src/index.ts +2 -0
  102. package/src/store/ToolGroupManager/ToolGroup.ts +79 -2
  103. package/src/tools/AdvancedMagnifyTool.ts +725 -0
  104. package/src/tools/AdvancedMagnifyViewport.ts +624 -0
  105. package/src/tools/AdvancedMagnifyViewportManager.ts +291 -0
  106. package/src/tools/annotation/EllipticalROITool.ts +14 -9
  107. package/src/tools/index.ts +2 -0
  108. package/src/types/EventTypes.ts +23 -0
  109. package/src/types/IToolGroup.ts +7 -0
  110. package/src/types/ToolAction.ts +54 -0
  111. package/src/types/ToolSpecificAnnotationTypes.ts +12 -0
  112. package/src/types/index.ts +2 -0
@@ -0,0 +1,291 @@
1
+ import { vec3 } from 'gl-matrix';
2
+ import {
3
+ eventTarget,
4
+ Enums,
5
+ getRenderingEngine,
6
+ CONSTANTS,
7
+ } from '@cornerstonejs/core';
8
+ import type { Types } from '@cornerstonejs/core';
9
+ import { AnnotationRemovedEventType } from '../types/EventTypes';
10
+ import { Events as cstEvents } from '../enums';
11
+ import {
12
+ AdvancedMagnifyViewport,
13
+ AutoPanCallback,
14
+ } from './AdvancedMagnifyViewport';
15
+ import { AdvancedMagnifyAnnotation } from '../types/ToolSpecificAnnotationTypes';
16
+
17
+ // Defined the tool name internally instead of importing
18
+ // AdvangedMagnifyTool due to cyclic dependency
19
+ const ADVANCED_MAGNIFY_TOOL_NAME = 'AdvancedMagnify';
20
+
21
+ const PARALLEL_THRESHOLD = 1 - CONSTANTS.EPSILON;
22
+ const { Events } = Enums;
23
+
24
+ export type MagnifyViewportInfo = {
25
+ // Viewport id to be used or new v4 compliant GUID is used instead
26
+ magnifyViewportId?: string;
27
+ // Enabled element where the magnifying glass shall be added to
28
+ sourceEnabledElement: Types.IEnabledElement;
29
+ // Magnifying glass position (center)
30
+ position: Types.Point2;
31
+ // Magnifying glass radius (pixels)
32
+ radius: number;
33
+ // Amount of magnification applied to the magnifying glass image compared to the source viewport.
34
+ zoomFactor: number;
35
+ // Allow panning the viewport when moving an annotation point close to the border of the magnifying glass
36
+ autoPan: {
37
+ // Enable or disable auto pan
38
+ enabled: boolean;
39
+ // Minimum distance to the border before start auto panning
40
+ padding: number;
41
+ // Callback function responsible for updating the annotation (circle)
42
+ // that contains the magnifying viewport
43
+ callback: AutoPanCallback;
44
+ };
45
+ };
46
+
47
+ type MagnifyViewportsMapEntry = {
48
+ annotation: AdvancedMagnifyAnnotation;
49
+ magnifyViewport: AdvancedMagnifyViewport;
50
+ };
51
+
52
+ /**
53
+ * Manager responsible for creating, storing and destroying magnifying glass
54
+ * viewports. There are no restrictions to create a new instance of it but it
55
+ * should be accessed through getInstance() method.
56
+ */
57
+ class AdvancedMagnifyViewportManager {
58
+ private static _singleton: AdvancedMagnifyViewportManager;
59
+ private _magnifyViewportsMap: Map<string, MagnifyViewportsMapEntry>;
60
+
61
+ constructor() {
62
+ this._magnifyViewportsMap = new Map();
63
+ this._initialize();
64
+ }
65
+
66
+ /**
67
+ * Creates a new magnifying glass viewport manager instance when this method is
68
+ * called for the first time or return the instance previously created for
69
+ * any subsequent call (singleton pattern).
70
+ * @returns A magnifying viewport manager instance
71
+ */
72
+ public static getInstance(): AdvancedMagnifyViewportManager {
73
+ AdvancedMagnifyViewportManager._singleton =
74
+ AdvancedMagnifyViewportManager._singleton ??
75
+ new AdvancedMagnifyViewportManager();
76
+
77
+ return AdvancedMagnifyViewportManager._singleton;
78
+ }
79
+
80
+ /**
81
+ * Creates a new magnifying glass viewport instance
82
+ * @param viewportInfo - Viewport data used when creating a new magnifying glass viewport
83
+ * @returns A magnifying glass viewport instance
84
+ */
85
+ public createViewport = (
86
+ annotation: AdvancedMagnifyAnnotation,
87
+ viewportInfo: MagnifyViewportInfo
88
+ ): AdvancedMagnifyViewport => {
89
+ const {
90
+ magnifyViewportId,
91
+ sourceEnabledElement,
92
+ position,
93
+ radius,
94
+ zoomFactor,
95
+ autoPan,
96
+ } = viewportInfo;
97
+ const { viewport: sourceViewport } = sourceEnabledElement;
98
+ const { element: sourceElement } = sourceViewport;
99
+
100
+ const magnifyViewport = new AdvancedMagnifyViewport({
101
+ magnifyViewportId,
102
+ sourceEnabledElement,
103
+ radius,
104
+ position,
105
+ zoomFactor,
106
+ autoPan,
107
+ });
108
+
109
+ this._addSourceElementEventListener(sourceElement);
110
+ this._magnifyViewportsMap.set(magnifyViewport.viewportId, {
111
+ annotation,
112
+ magnifyViewport,
113
+ });
114
+
115
+ return magnifyViewport;
116
+ };
117
+
118
+ /**
119
+ * Find and return a magnifying glass viewport based on its id
120
+ * @param magnifyViewportId - Magnifying glass viewport id
121
+ * @returns A magnifying glass viewport instance
122
+ */
123
+ public getViewport(magnifyViewportId: string): AdvancedMagnifyViewport {
124
+ return this._magnifyViewportsMap.get(magnifyViewportId)?.magnifyViewport;
125
+ }
126
+
127
+ /**
128
+ * Release all magnifying glass viewport instances and remove all event
129
+ * listeners making all objects available to be garbage collected.
130
+ */
131
+ public dispose() {
132
+ this._removeEventListeners();
133
+ this._destroyViewports();
134
+ }
135
+
136
+ private _destroyViewport(magnifyViewportId: string) {
137
+ const magnifyViewportMapEntry =
138
+ this._magnifyViewportsMap.get(magnifyViewportId);
139
+
140
+ if (magnifyViewportMapEntry) {
141
+ const { magnifyViewport } = magnifyViewportMapEntry;
142
+ const { viewport: sourceViewport } = magnifyViewport.sourceEnabledElement;
143
+ const { element: sourceElement } = sourceViewport;
144
+
145
+ this._removeSourceElementEventListener(sourceElement);
146
+
147
+ magnifyViewport.dispose();
148
+ this._magnifyViewportsMap.delete(magnifyViewportId);
149
+ }
150
+ }
151
+
152
+ private _destroyViewports() {
153
+ const magnifyViewportIds = Array.from(this._magnifyViewportsMap.keys());
154
+
155
+ magnifyViewportIds.forEach((magnifyViewportId) =>
156
+ this._destroyViewport(magnifyViewportId)
157
+ );
158
+ }
159
+
160
+ private _annotationRemovedCallback = (evt: AnnotationRemovedEventType) => {
161
+ const { annotation } = evt.detail;
162
+
163
+ if (annotation.metadata.toolName !== ADVANCED_MAGNIFY_TOOL_NAME) {
164
+ return;
165
+ }
166
+
167
+ this._destroyViewport(annotation.data.magnifyViewportId);
168
+ };
169
+
170
+ private _getMagnifyViewportsMapEntriesBySourceViewportId(sourceViewportId) {
171
+ const magnifyViewportsMapEntries = Array.from(
172
+ this._magnifyViewportsMap.values()
173
+ );
174
+
175
+ return magnifyViewportsMapEntries.filter(({ magnifyViewport }) => {
176
+ const { viewport } = magnifyViewport.sourceEnabledElement;
177
+ return viewport.id === sourceViewportId;
178
+ });
179
+ }
180
+
181
+ private _newStackImageCallback = (
182
+ evt: Types.EventTypes.StackNewImageEvent
183
+ ) => {
184
+ const { viewportId: sourceViewportId, imageId } = evt.detail;
185
+ const magnifyViewportsMapEntries =
186
+ this._getMagnifyViewportsMapEntriesBySourceViewportId(sourceViewportId);
187
+
188
+ magnifyViewportsMapEntries.forEach(({ annotation }) => {
189
+ annotation.metadata.referencedImageId = imageId;
190
+ annotation.invalidated = true;
191
+ });
192
+ };
193
+
194
+ private _newVolumeImageCallback = (
195
+ evt: Types.EventTypes.VolumeNewImageEvent
196
+ ) => {
197
+ const { renderingEngineId, viewportId: sourceViewportId } = evt.detail;
198
+ const renderingEngine = getRenderingEngine(renderingEngineId);
199
+ const sourceViewport = renderingEngine.getViewport(sourceViewportId);
200
+ const { viewPlaneNormal: currentViewPlaneNormal } =
201
+ sourceViewport.getCamera();
202
+
203
+ const magnifyViewportsMapEntries =
204
+ this._getMagnifyViewportsMapEntriesBySourceViewportId(sourceViewportId);
205
+
206
+ magnifyViewportsMapEntries.forEach(({ annotation }) => {
207
+ const { viewPlaneNormal } = annotation.metadata;
208
+
209
+ // Compare the normal to make sure the volume is not rotate in 3D space
210
+ const isParallel =
211
+ Math.abs(vec3.dot(viewPlaneNormal, currentViewPlaneNormal)) >
212
+ PARALLEL_THRESHOLD;
213
+
214
+ if (!isParallel) {
215
+ return;
216
+ }
217
+
218
+ const { handles } = annotation.data;
219
+ const worldImagePlanePoint = sourceViewport.canvasToWorld([0, 0]);
220
+ const vecHandleToImagePlane = vec3.sub(
221
+ vec3.create(),
222
+ worldImagePlanePoint,
223
+ handles.points[0]
224
+ );
225
+ const worldDist = vec3.dot(vecHandleToImagePlane, currentViewPlaneNormal);
226
+ const worldDelta = vec3.scale(
227
+ vec3.create(),
228
+ currentViewPlaneNormal,
229
+ worldDist
230
+ );
231
+
232
+ // Move all handle points to the image plane to make the annotation visible
233
+ for (let i = 0, len = handles.points.length; i < len; i++) {
234
+ const point = handles.points[i];
235
+
236
+ point[0] += worldDelta[0];
237
+ point[1] += worldDelta[1];
238
+ point[2] += worldDelta[2];
239
+ }
240
+
241
+ annotation.invalidated = true;
242
+ });
243
+ };
244
+
245
+ private _addEventListeners() {
246
+ eventTarget.addEventListener(
247
+ cstEvents.ANNOTATION_REMOVED,
248
+ this._annotationRemovedCallback
249
+ );
250
+ }
251
+
252
+ private _removeEventListeners() {
253
+ eventTarget.removeEventListener(
254
+ cstEvents.ANNOTATION_REMOVED,
255
+ this._annotationRemovedCallback
256
+ );
257
+ }
258
+
259
+ private _addSourceElementEventListener(element) {
260
+ element.addEventListener(
261
+ Events.STACK_NEW_IMAGE,
262
+ this._newStackImageCallback
263
+ );
264
+
265
+ element.addEventListener(
266
+ Events.VOLUME_NEW_IMAGE,
267
+ this._newVolumeImageCallback
268
+ );
269
+ }
270
+
271
+ private _removeSourceElementEventListener(element) {
272
+ element.removeEventListener(
273
+ Events.STACK_NEW_IMAGE,
274
+ this._newStackImageCallback
275
+ );
276
+
277
+ element.removeEventListener(
278
+ Events.VOLUME_NEW_IMAGE,
279
+ this._newVolumeImageCallback
280
+ );
281
+ }
282
+
283
+ private _initialize() {
284
+ this._addEventListeners();
285
+ }
286
+ }
287
+
288
+ export {
289
+ AdvancedMagnifyViewportManager as default,
290
+ AdvancedMagnifyViewportManager,
291
+ };
@@ -125,7 +125,7 @@ class EllipticalROITool extends AnnotationTool {
125
125
  viewportIdsToRender: Array<string>;
126
126
  handleIndex?: number;
127
127
  movingTextBox?: boolean;
128
- centerCanvas?: Array<number>;
128
+ centerWorld?: Array<number>;
129
129
  canvasWidth?: number;
130
130
  canvasHeight?: number;
131
131
  originalHandleCanvas?: Array<number>;
@@ -238,7 +238,7 @@ class EllipticalROITool extends AnnotationTool {
238
238
  this.editData = {
239
239
  annotation,
240
240
  viewportIdsToRender,
241
- centerCanvas: canvasPos,
241
+ centerWorld: worldPos,
242
242
  newAnnotation: true,
243
243
  hasMoved: false,
244
244
  };
@@ -365,6 +365,7 @@ class EllipticalROITool extends AnnotationTool {
365
365
  let handleIndex;
366
366
 
367
367
  let centerCanvas;
368
+ let centerWorld;
368
369
  let canvasWidth;
369
370
  let canvasHeight;
370
371
  let originalHandleCanvas;
@@ -373,8 +374,8 @@ class EllipticalROITool extends AnnotationTool {
373
374
  movingTextBox = true;
374
375
  } else {
375
376
  const { points } = data.handles;
376
- const enabledElement = getEnabledElement(element);
377
- const { worldToCanvas } = enabledElement.viewport;
377
+ const { viewport } = getEnabledElement(element);
378
+ const { worldToCanvas, canvasToWorld } = viewport;
378
379
 
379
380
  handleIndex = points.findIndex((p) => p === handle);
380
381
 
@@ -389,6 +390,8 @@ class EllipticalROITool extends AnnotationTool {
389
390
  (pointsCanvas[2][0] + pointsCanvas[3][0]) / 2,
390
391
  (pointsCanvas[0][1] + pointsCanvas[1][1]) / 2,
391
392
  ];
393
+
394
+ centerWorld = canvasToWorld(centerCanvas);
392
395
  }
393
396
 
394
397
  // Find viewports to render on drag.
@@ -403,7 +406,7 @@ class EllipticalROITool extends AnnotationTool {
403
406
  handleIndex,
404
407
  canvasWidth,
405
408
  canvasHeight,
406
- centerCanvas,
409
+ centerWorld,
407
410
  originalHandleCanvas,
408
411
  movingTextBox,
409
412
  };
@@ -480,7 +483,8 @@ class EllipticalROITool extends AnnotationTool {
480
483
  const { canvasToWorld } = viewport;
481
484
 
482
485
  //////
483
- const { annotation, viewportIdsToRender, centerCanvas } = this.editData;
486
+ const { annotation, viewportIdsToRender, centerWorld } = this.editData;
487
+ const centerCanvas = viewport.worldToCanvas(centerWorld as Types.Point3);
484
488
  const { data } = annotation;
485
489
 
486
490
  const dX = Math.abs(currentCanvasPoints[0] - centerCanvas[0]);
@@ -554,17 +558,18 @@ class EllipticalROITool extends AnnotationTool {
554
558
  _dragHandle = (evt: EventTypes.InteractionEventType): void => {
555
559
  const eventDetail = evt.detail;
556
560
  const { element } = eventDetail;
557
- const enabledElement = getEnabledElement(element);
558
- const { canvasToWorld } = enabledElement.viewport;
561
+ const { viewport } = getEnabledElement(element);
562
+ const { canvasToWorld, worldToCanvas } = viewport;
559
563
 
560
564
  const {
561
565
  annotation,
562
566
  canvasWidth,
563
567
  canvasHeight,
564
568
  handleIndex,
565
- centerCanvas,
569
+ centerWorld,
566
570
  originalHandleCanvas,
567
571
  } = this.editData;
572
+ const centerCanvas = viewport.worldToCanvas(centerWorld as Types.Point3);
568
573
  const { data } = annotation;
569
574
  const { points } = data.handles;
570
575
 
@@ -10,6 +10,7 @@ import VolumeRotateMouseWheelTool from './VolumeRotateMouseWheelTool';
10
10
  import MIPJumpToClickTool from './MIPJumpToClickTool';
11
11
  import CrosshairsTool from './CrosshairsTool';
12
12
  import MagnifyTool from './MagnifyTool';
13
+ import AdvancedMagnifyTool from './AdvancedMagnifyTool';
13
14
  import ReferenceLinesTool from './ReferenceLinesTool';
14
15
  import OverlayGridTool from './OverlayGridTool';
15
16
  //
@@ -82,6 +83,7 @@ export {
82
83
  RectangleROIStartEndThresholdTool,
83
84
  BrushTool,
84
85
  MagnifyTool,
86
+ AdvancedMagnifyTool,
85
87
  ReferenceLines,
86
88
  PaintFillTool,
87
89
  ScaleOverlayTool,
@@ -5,6 +5,7 @@ import ITouchPoints from './ITouchPoints';
5
5
  import IDistance from './IDistance';
6
6
  import { SetToolBindingsType } from './ISetToolModeOptions';
7
7
  import { Swipe } from '../enums/Touch';
8
+ import { ToolModes } from '../enums';
8
9
 
9
10
  /**
10
11
  * The normalized interaction event detail
@@ -71,6 +72,20 @@ type InteractionStartEventDetail = InteractionEventDetail;
71
72
 
72
73
  type InteractionEndEventDetail = InteractionEventDetail;
73
74
 
75
+ /**
76
+ * The data that is passed to the event handler when tool mode changes
77
+ */
78
+ type ToolModeChangedEventDetail = {
79
+ /** unique id of the toolGroup */
80
+ toolGroupId: string;
81
+ /** Tool name */
82
+ toolName: string;
83
+ /** Tool mode */
84
+ mode: ToolModes;
85
+ /** Tool binding options */
86
+ toolBindingsOptions?: SetToolBindingsType;
87
+ };
88
+
74
89
  /**
75
90
  * The data that is passed to the event handler when a tool is activated.
76
91
  */
@@ -424,6 +439,12 @@ type NormalizedMouseEventType = Types.CustomEventType<MouseCustomEventDetail>;
424
439
  */
425
440
  type NormalizedTouchEventType = Types.CustomEventType<TouchCustomEventDetail>;
426
441
 
442
+ /**
443
+ * The ToolModeChanged event type
444
+ */
445
+ type ToolModeChangedEventType =
446
+ Types.CustomEventType<ToolModeChangedEventDetail>;
447
+
427
448
  /**
428
449
  * The ToolActivated event type
429
450
  */
@@ -629,6 +650,8 @@ export {
629
650
  NormalizedInteractionEventDetail,
630
651
  NormalizedMouseEventType,
631
652
  NormalizedTouchEventType,
653
+ ToolModeChangedEventDetail,
654
+ ToolModeChangedEventType,
632
655
  ToolActivatedEventDetail,
633
656
  ToolActivatedEventType,
634
657
  AnnotationAddedEventDetail,
@@ -75,4 +75,11 @@ export default interface IToolGroup {
75
75
  getDefaultMousePrimary: {
76
76
  (): MouseBindings;
77
77
  };
78
+
79
+ clone: {
80
+ (
81
+ newToolGroupId: string,
82
+ fnToolFilter: (toolName: string) => boolean
83
+ ): IToolGroup;
84
+ };
78
85
  }
@@ -0,0 +1,54 @@
1
+ import type { Annotation } from './AnnotationTypes';
2
+ import type { InteractionEventType } from './EventTypes';
3
+ import type { SetToolBindingsType } from './ISetToolModeOptions';
4
+
5
+ /**
6
+ * An action that may be defined at the tool configuration level
7
+ *
8
+ * Annotations can have actions that run a specific task (ex: showing a dropdown
9
+ * containing a list of all predefined zoom levels - advanced magnifier glass).
10
+ * Each action must have at least one binding option (mouse button + [modifier(s)])
11
+ * and a action runs if and only if no other tool is using that same binding options
12
+ * to draw an annotation because action has lower priority.
13
+ *
14
+ * Actions are defined in the following way in a annotation tool constructor:
15
+ *
16
+ * class MyAnnotationTool extends AnnotationTool {
17
+ * constructor(
18
+ * toolProps: PublicToolProps = {},
19
+ * defaultToolProps: ToolProps = {
20
+ * configuration: {
21
+ * actions: [
22
+ * {
23
+ * method: 'myAction',
24
+ * bindings: [
25
+ * {
26
+ * mouseButton: MouseBindings.Secondary,
27
+ * modifierKey: KeyboardBindings.Shift,
28
+ * }
29
+ * ]
30
+ * }
31
+ * ]
32
+ * }
33
+ * }
34
+ * ) {
35
+ * super(toolProps, defaultToolProps);
36
+ * }
37
+ *
38
+ * public myAction(evt: EventTypes.InteractionEventType, annotation: MyAnnotation) {
39
+ * // action code
40
+ * }
41
+ * }
42
+ *
43
+ * The "method" property may be a string or a javascript function. In case it is
44
+ * a string a function with same name must exists in the tool class. In both ways
45
+ * (string or function) the function is called in the tool's context (`this`)
46
+ */
47
+ type ToolAction = {
48
+ method:
49
+ | string
50
+ | ((evt: InteractionEventType, annotation: Annotation) => void);
51
+ bindings: SetToolBindingsType[];
52
+ };
53
+
54
+ export default ToolAction;
@@ -78,6 +78,18 @@ export interface LengthAnnotation extends Annotation {
78
78
  };
79
79
  }
80
80
 
81
+ export interface AdvancedMagnifyAnnotation extends Annotation {
82
+ data: {
83
+ zoomFactor: number;
84
+ sourceViewportId: string;
85
+ magnifyViewportId: string;
86
+ handles: {
87
+ points: Types.Point3[]; // [top, right, bottom, left]
88
+ activeHandleIndex: number | null;
89
+ };
90
+ };
91
+ }
92
+
81
93
  export interface CircleROIAnnotation extends Annotation {
82
94
  data: {
83
95
  handles: {
@@ -21,6 +21,7 @@ import type * as AnnotationStyle from './AnnotationStyle';
21
21
  import type ToolHandle from './ToolHandle';
22
22
  import type { AnnotationHandle, TextBoxHandle } from './ToolHandle';
23
23
  import type InteractionTypes from './InteractionTypes';
24
+ import type ToolAction from './ToolAction';
24
25
  import type {
25
26
  ToolProps,
26
27
  PublicToolProps,
@@ -84,6 +85,7 @@ export type {
84
85
  SetToolBindingsType,
85
86
  ToolOptionsType,
86
87
  InteractionTypes,
88
+ ToolAction,
87
89
  //
88
90
  IToolGroup,
89
91
  IToolClassReference,