From c31b9895e5242ed80d97db141602f1f651ba7c5f Mon Sep 17 00:00:00 2001 From: Forrest Date: Wed, 7 Feb 2024 11:49:26 -0500 Subject: [PATCH 01/11] refactor: split out imaging configs useSliceConfig and useWindowingConfig encapsulate the values, ranges, and config objects for each respective imaging property. SliceSlider now supports the v-model protocol. fix: asdf --- src/components/SliceSlider.vue | 12 +- src/components/VtkObliqueView.vue | 32 ++--- src/components/VtkTwoView.vue | 161 ++++++++++++++------------ src/composables/useSliceConfig.ts | 32 +++++ src/composables/useWindowingConfig.ts | 36 ++++++ 5 files changed, 174 insertions(+), 99 deletions(-) create mode 100644 src/composables/useSliceConfig.ts create mode 100644 src/composables/useWindowingConfig.ts diff --git a/src/components/SliceSlider.vue b/src/components/SliceSlider.vue index 74737e17c..d87f131c6 100644 --- a/src/components/SliceSlider.vue +++ b/src/components/SliceSlider.vue @@ -35,7 +35,7 @@ function getYOffsetFromTransform(matStr) { export default { props: { - slice: { + modelValue: { type: Number, default: 0, }, @@ -57,6 +57,8 @@ export default { }, }, + emits: ['update:modelValue'], + data() { return { maxHandlePos: 0, @@ -70,7 +72,7 @@ export default { computed: { handlePosition() { const range = this.max - this.min <= 0 ? 1 : this.max - this.min; - const pos = this.maxHandlePos * ((this.slice - this.min) / range); + const pos = this.maxHandlePos * ((this.modelValue - this.min) / range); return this.dragging ? this.draggingHandlePos : pos; }, draggingHandlePos() { @@ -118,7 +120,7 @@ export default { Math.min(this.maxHandlePos, ev.pageY - y - this.handleHeight / 2) ); const newSlice = this.getNearestSlice(this.initialHandlePos); - this.$emit('input', newSlice); + this.$emit('modelValue', newSlice); } this.yOffset = 0; @@ -132,7 +134,7 @@ export default { this.yOffset = ev.pageY - this.initialMousePosY; const slice = this.getNearestSlice(this.handlePosition); - this.$emit('input', slice); + this.$emit('modelValue', slice); }, onDragEnd(ev) { @@ -142,7 +144,7 @@ export default { this.dragging = false; const slice = this.getNearestSlice(this.handlePosition); - this.$emit('input', slice); + this.$emit('modelValue', slice); }, getNearestSlice(pos) { diff --git a/src/components/VtkObliqueView.vue b/src/components/VtkObliqueView.vue index 57fdd9f81..4cc95d818 100644 --- a/src/components/VtkObliqueView.vue +++ b/src/components/VtkObliqueView.vue @@ -130,6 +130,8 @@ import { ResliceCursorWidgetState } from '@kitware/vtk.js/Widgets/Widgets3D/Resl import { onVTKEvent } from '@/src/composables/onVTKEvent'; import { manageVTKSubscription } from '@/src/composables/manageVTKSubscription'; import ViewOverlayGrid from '@/src/components/ViewOverlayGrid.vue'; +import { useSliceConfig } from '@/src/composables/useSliceConfig'; +import { useWindowingConfig } from '@/src/composables/useWindowingConfig'; import { useResizeObserver } from '../composables/useResizeObserver'; import { getLPSAxisFromDir } from '../utils/lps'; import { useCurrentImage } from '../composables/useCurrentImage'; @@ -146,9 +148,7 @@ import { LPSAxisDir } from '../types/lps'; import { ViewProxyType } from '../core/proxies'; import { useViewProxy } from '../composables/useViewProxy'; import { useWidgetManager } from '../composables/useWidgetManager'; -import useViewSliceStore, { - defaultSliceConfig, -} from '../store/view-configs/slicing'; +import useViewSliceStore from '../store/view-configs/slicing'; import { OBLIQUE_OUTLINE_COLORS, ToolContainer, @@ -207,26 +207,16 @@ export default defineComponent({ const dicomStore = useDICOMStore(); - const sliceConfigDefaults = defaultSliceConfig(); - const sliceConfig = computed(() => - viewSliceStore.getConfig(viewID.value, curImageID.value) - ); - const currentSlice = computed( - () => sliceConfig.value?.slice ?? sliceConfigDefaults.slice + const { slice: currentSlice, config: sliceConfig } = useSliceConfig( + viewID, + curImageID ); + const { + width: windowWidth, + level: windowLevel, + config: wlConfig, + } = useWindowingConfig(viewID, curImageID); - const wlConfig = computed({ - get: () => windowingStore.getConfig(viewID.value, curImageID.value), - set: (newValue) => { - const imageID = curImageID.value; - if (imageID != null && newValue != null) { - windowingStore.updateConfig(viewID.value, imageID, newValue); - } - }, - }); - - const windowWidth = computed(() => wlConfig.value?.width); - const windowLevel = computed(() => wlConfig.value?.level); const dicomInfo = computed(() => { if ( curImageID.value != null && diff --git a/src/components/VtkTwoView.vue b/src/components/VtkTwoView.vue index 94ee61c43..4785e74d8 100644 --- a/src/components/VtkTwoView.vue +++ b/src/components/VtkTwoView.vue @@ -19,13 +19,12 @@
@@ -135,6 +83,7 @@ import { useSliceConfigInitializer } from '@/src/composables/useSliceConfigIniti import { useWindowingConfig } from '@/src/composables/useWindowingConfig'; import { useWindowingConfigInitializer } from '@/src/composables/useWindowingConfigInitializer'; import { useProxyRepresentation } from '@/src/composables/useProxyRepresentations'; +import DicomQuickInfoButton from '@/src/components/DicomQuickInfoButton.vue'; import { useResizeObserver } from '../composables/useResizeObserver'; import { getLPSAxisFromDir } from '../utils/lps'; import { useCurrentImage } from '../composables/useCurrentImage'; @@ -144,7 +93,6 @@ import PanTool from './tools/PanTool.vue'; import ZoomTool from './tools/ZoomTool.vue'; import ResliceCursorTool from './tools/ResliceCursorTool.vue'; import { useResetViewsEvents } from './tools/ResetViews.vue'; -import { useDICOMStore } from '../store/datasets-dicom'; import { LPSAxisDir } from '../types/lps'; import { ViewProxyType } from '../core/proxies'; import { useViewProxy } from '../composables/useViewProxy'; @@ -186,6 +134,7 @@ export default defineComponent({ PanTool, ZoomTool, ResliceCursorTool, + DicomQuickInfoButton, }, setup(props) { const viewSliceStore = useViewSliceStore(); @@ -205,8 +154,6 @@ export default defineComponent({ isImageLoading, } = useCurrentImage(); - const dicomStore = useDICOMStore(); - const { slice: currentSlice, config: sliceConfig } = useSliceConfig( viewID, curImageID @@ -217,36 +164,6 @@ export default defineComponent({ config: wlConfig, } = useWindowingConfig(viewID, curImageID); - const dicomInfo = computed(() => { - if ( - curImageID.value != null && - curImageID.value in dicomStore.imageIDToVolumeKey - ) { - const volumeKey = dicomStore.imageIDToVolumeKey[curImageID.value]; - const volumeInfo = dicomStore.volumeInfo[volumeKey]; - const studyKey = dicomStore.volumeStudy[volumeKey]; - const studyInfo = dicomStore.studyInfo[studyKey]; - const patientKey = dicomStore.studyPatient[studyKey]; - const patientInfo = dicomStore.patientInfo[patientKey]; - - const patientID = patientInfo.PatientID; - const studyID = studyInfo.StudyID; - const studyDescription = studyInfo.StudyDescription; - const seriesNumber = volumeInfo.SeriesNumber; - const seriesDescription = volumeInfo.SeriesDescription; - - return { - patientID, - studyID, - studyDescription, - seriesNumber, - seriesDescription, - }; - } - - return null; - }); - // --- view proxy setup --- // const { viewProxy, setContainer: setViewProxyContainer } = @@ -631,12 +548,12 @@ export default defineComponent({ viewProxy, viewAxis, active: true, + curImageID, currentSlice, windowWidth, windowLevel, isImageLoading, widgetManager, - dicomInfo, enableResizeToFit, hover, }; diff --git a/src/components/VtkTwoView.vue b/src/components/VtkTwoView.vue index 4bfce5dd5..06b05e10c 100644 --- a/src/components/VtkTwoView.vue +++ b/src/components/VtkTwoView.vue @@ -106,61 +106,9 @@ @@ -212,6 +160,7 @@ import { useWindowingConfigInitializer } from '@/src/composables/useWindowingCon import { useBaseSliceRepresentation } from '@/src/composables/useBaseSliceRepresentation'; import { useLabelMapRepresentations } from '@/src/composables/useLabelMapRepresentations'; import { useLayerRepresentations } from '@/src/composables/useLayerRepresentations'; +import DicomQuickInfoButton from '@/src/components/DicomQuickInfoButton.vue'; import { useResizeObserver } from '../composables/useResizeObserver'; import { useOrientationLabels } from '../composables/useOrientationLabels'; import { getLPSAxisFromDir } from '../utils/lps'; @@ -225,7 +174,6 @@ import RulerTool from './tools/ruler/RulerTool.vue'; import RectangleTool from './tools/rectangle/RectangleTool.vue'; import PolygonTool from './tools/polygon/PolygonTool.vue'; import PaintTool from './tools/paint/PaintTool.vue'; -import { useDICOMStore } from '../store/datasets-dicom'; import { useSegmentGroupStore } from '../store/segmentGroups'; import { usePaintToolStore } from '../store/tools/paint'; import { usePersistCameraConfig } from '../composables/usePersistCameraConfig'; @@ -282,6 +230,7 @@ export default defineComponent({ CrosshairsTool, CropTool, SelectTool, + DicomQuickInfoButton, }, setup(props) { const viewSliceStore = useViewSliceStore(); @@ -304,8 +253,6 @@ export default defineComponent({ currentLayers, } = useCurrentImage(); - const dicomStore = useDICOMStore(); - const { config: sliceConfig, slice: currentSlice, @@ -317,36 +264,6 @@ export default defineComponent({ level: windowLevel, } = useWindowingConfig(viewID, curImageID); - const dicomInfo = computed(() => { - if ( - curImageID.value != null && - curImageID.value in dicomStore.imageIDToVolumeKey - ) { - const volumeKey = dicomStore.imageIDToVolumeKey[curImageID.value]; - const volumeInfo = dicomStore.volumeInfo[volumeKey]; - const studyKey = dicomStore.volumeStudy[volumeKey]; - const studyInfo = dicomStore.studyInfo[studyKey]; - const patientKey = dicomStore.studyPatient[studyKey]; - const patientInfo = dicomStore.patientInfo[patientKey]; - - const patientID = patientInfo.PatientID; - const studyID = studyInfo.StudyID; - const studyDescription = studyInfo.StudyDescription; - const seriesNumber = volumeInfo.SeriesNumber; - const seriesDescription = volumeInfo.SeriesDescription; - - return { - patientID, - studyID, - studyDescription, - seriesNumber, - seriesDescription, - }; - } - - return null; - }); - // --- initializers --- // const sliceDomain = computed(() => { @@ -735,6 +652,7 @@ export default defineComponent({ viewProxy, viewAxis, active: true, + curImageID, currentSlice, sliceRange, windowWidth, @@ -743,7 +661,6 @@ export default defineComponent({ leftLabel, isImageLoading, widgetManager, - dicomInfo, enableResizeToFit() { resizeToFit.value = true; }, @@ -756,10 +673,3 @@ export default defineComponent({ - From 3585904684c37b172eda49319831da23a9a49c47 Mon Sep 17 00:00:00 2001 From: Forrest Date: Wed, 7 Feb 2024 22:16:46 -0500 Subject: [PATCH 05/11] refactor: simplify view setContainer call --- src/components/VtkObliqueThreeView.vue | 9 +++++---- src/components/VtkObliqueView.vue | 10 ++++++---- src/components/VtkThreeView.vue | 9 +++++---- src/components/VtkTwoView.vue | 10 ++++++---- src/composables/useViewProxy.ts | 24 +++--------------------- 5 files changed, 25 insertions(+), 37 deletions(-) diff --git a/src/components/VtkObliqueThreeView.vue b/src/components/VtkObliqueThreeView.vue index 4560e56e2..a0fea0e60 100644 --- a/src/components/VtkObliqueThreeView.vue +++ b/src/components/VtkObliqueThreeView.vue @@ -106,8 +106,10 @@ export default defineComponent({ // --- view proxy setup --- // - const { viewProxy, setContainer: setViewProxyContainer } = - useViewProxy(viewID, ViewProxyType.Oblique3D); + const { viewProxy } = useViewProxy( + viewID, + ViewProxyType.Oblique3D + ); const { representation: baseImageRep } = useProxyRepresentation( @@ -134,7 +136,6 @@ export default defineComponent({ }; onBeforeUnmount(() => { - setViewProxyContainer(null); viewProxy.value.setContainer(null); }); @@ -143,7 +144,7 @@ export default defineComponent({ viewProxy.value.setOrientationAxesType('cube'); viewProxy.value.setBackground([0, 0, 0, 0]); viewProxy.value.getCamera().setParallelProjection(true); - setViewProxyContainer(vtkContainerRef.value); + viewProxy.value.setContainer(vtkContainerRef.value ?? null); }); const resliceCursor = inject(VTKResliceCursor); diff --git a/src/components/VtkObliqueView.vue b/src/components/VtkObliqueView.vue index d9ad09401..9694d6ab0 100644 --- a/src/components/VtkObliqueView.vue +++ b/src/components/VtkObliqueView.vue @@ -166,8 +166,10 @@ export default defineComponent({ // --- view proxy setup --- // - const { viewProxy, setContainer: setViewProxyContainer } = - useViewProxy(viewID, ViewProxyType.Oblique); + const { viewProxy } = useViewProxy( + viewID, + ViewProxyType.Oblique + ); const resliceCursor = inject(VTKResliceCursor); if (!resliceCursor) { @@ -224,7 +226,7 @@ export default defineComponent({ ); onMounted(() => { - setViewProxyContainer(vtkContainerRef.value); + viewProxy.value.setContainer(vtkContainerRef.value ?? null); viewProxy.value.setOrientationAxesVisibility(false); // Initialize camera points during construction @@ -240,7 +242,7 @@ export default defineComponent({ }); onBeforeUnmount(() => { - setViewProxyContainer(null); + viewProxy.value.setContainer(null); }); // Function to compute float range of slicing for oblique slicing. diff --git a/src/components/VtkThreeView.vue b/src/components/VtkThreeView.vue index 613ef5b1a..862d25187 100644 --- a/src/components/VtkThreeView.vue +++ b/src/components/VtkThreeView.vue @@ -425,18 +425,19 @@ export default defineComponent({ // --- view proxy setup --- // - const { viewProxy, setContainer: setViewProxyContainer } = - useViewProxy(viewID, ViewProxyType.Volume); + const { viewProxy } = useViewProxy( + viewID, + ViewProxyType.Volume + ); onMounted(() => { viewProxy.value.setOrientationAxesVisibility(true); viewProxy.value.setOrientationAxesType('cube'); viewProxy.value.setBackground([0, 0, 0, 0]); - setViewProxyContainer(vtkContainerRef.value); + viewProxy.value.setContainer(vtkContainerRef.value ?? null); }); onBeforeUnmount(() => { - setViewProxyContainer(null); viewProxy.value.setContainer(null); }); diff --git a/src/components/VtkTwoView.vue b/src/components/VtkTwoView.vue index 06b05e10c..86205e21a 100644 --- a/src/components/VtkTwoView.vue +++ b/src/components/VtkTwoView.vue @@ -282,8 +282,10 @@ export default defineComponent({ // --- view proxy setup --- // - const { viewProxy, setContainer: setViewProxyContainer } = - useViewProxy(viewID, ViewProxyType.Slice); + const { viewProxy } = useViewProxy( + viewID, + ViewProxyType.Slice + ); onBeforeMount(() => { // do this before mount, as the ManipulatorTools run onMounted @@ -292,12 +294,12 @@ export default defineComponent({ }); onMounted(() => { - setViewProxyContainer(vtkContainerRef.value); + viewProxy.value.setContainer(vtkContainerRef.value ?? null); viewProxy.value.setOrientationAxesVisibility(false); }); onBeforeUnmount(() => { - setViewProxyContainer(null); + viewProxy.value.setContainer(null); }); // --- Slicing setup --- // diff --git a/src/composables/useViewProxy.ts b/src/composables/useViewProxy.ts index e2a85ce5f..0b25af4f3 100644 --- a/src/composables/useViewProxy.ts +++ b/src/composables/useViewProxy.ts @@ -12,34 +12,16 @@ export function useViewProxy( ) { const viewStore = useViewStore(); - const container = ref(null); - - const setContainer = (el: HTMLElement | null | undefined) => { - container.value = el ?? null; - }; - const viewProxy = computed(() => viewStore.createOrGetViewProxy(unref(id), unref(type)) ); - watch(viewProxy, (curViewProxy, oldViewProxy) => { - oldViewProxy.setContainer(null); - curViewProxy.setContainer(container.value); - }); - - watch(container, (curContainer) => { - viewProxy.value.setContainer(curContainer); - // setContainer doesn't call modified - viewProxy.value.modified(); - }); - return { viewProxy, - setContainer, }; } -function useMountedViewProxy( +function isViewProxyMounted( viewProxy: MaybeRef> ) { const mounted = ref(false); @@ -65,7 +47,7 @@ export function onViewProxyMounted( viewProxy: MaybeRef>, callback: () => void ) { - const mounted = useMountedViewProxy(viewProxy); + const mounted = isViewProxyMounted(viewProxy); watch( mounted, @@ -80,7 +62,7 @@ export function onViewProxyUnmounted( viewProxy: MaybeRef>, callback: () => void ) { - const mounted = useMountedViewProxy(viewProxy); + const mounted = isViewProxyMounted(viewProxy); let invoked = false; const invokeCallback = () => { if (invoked) return; From 668585a677edae97521759aa30508bc09e032beb Mon Sep 17 00:00:00 2001 From: Forrest Date: Wed, 7 Feb 2024 23:44:24 -0500 Subject: [PATCH 06/11] fix(useProxyRepresentations): addRep in PostEffect --- src/composables/useProxyRepresentations.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/composables/useProxyRepresentations.ts b/src/composables/useProxyRepresentations.ts index d2f1fa5be..95ec64364 100644 --- a/src/composables/useProxyRepresentations.ts +++ b/src/composables/useProxyRepresentations.ts @@ -2,7 +2,7 @@ import { useViewStore } from '@/src/store/views'; import { Maybe } from '@/src/types'; import { vtkLPSViewProxy } from '@/src/types/vtk-types'; import vtkAbstractRepresentationProxy from '@kitware/vtk.js/Proxy/Core/AbstractRepresentationProxy'; -import { MaybeRef, computed, unref, watchEffect } from 'vue'; +import { MaybeRef, computed, unref, watchPostEffect } from 'vue'; export function useProxyRepresentations< T extends vtkAbstractRepresentationProxy = vtkAbstractRepresentationProxy @@ -22,11 +22,16 @@ export function useProxyRepresentations< .filter((rep): rep is T => !!rep); }); - watchEffect((onCleanup) => { - const reps = representations.value; + // Wait for the component to have mounted with PostEffect. + // When changing layouts, it's possible for the new component instance to + // execute effects prior to the old component running onCleanup callbacks. + watchPostEffect((onCleanup) => { const view = viewProxy.value; if (!view) return; + const reps = representations.value; + if (!reps.length) return; + reps.forEach((rep) => { view.addRepresentation(rep); }); From 2b943494386c7da1ca85484616384fb4fa0da1b1 Mon Sep 17 00:00:00 2001 From: Forrest Date: Thu, 8 Feb 2024 12:06:53 -0500 Subject: [PATCH 07/11] refactor: get widget manager from view proxy --- src/components/VtkObliqueView.vue | 8 -- src/components/VtkThreeView.vue | 8 -- src/components/VtkTwoView.vue | 17 +--- src/components/tools/ResliceCursorTool.vue | 13 +--- src/components/tools/SelectTool.vue | 11 ++- src/components/tools/crop/Crop3D.vue | 8 +- .../tools/crosshairs/CrosshairsTool.vue | 6 -- .../tools/crosshairs/CrosshairsWidget2D.vue | 26 +++---- src/components/tools/paint/PaintTool.vue | 6 -- src/components/tools/paint/PaintWidget2D.vue | 21 +++-- src/components/tools/polygon/PolygonTool.vue | 6 -- .../tools/polygon/PolygonWidget2D.vue | 27 +++---- .../tools/rectangle/RectangleTool.vue | 6 -- .../tools/rectangle/RectangleWidget2D.vue | 27 +++---- src/components/tools/ruler/RulerTool.vue | 6 -- src/components/tools/ruler/RulerWidget2D.vue | 25 +++--- src/composables/annotationTool.ts | 4 +- src/constants.ts | 15 ---- src/vtk/LPSView2DProxy/index.d.ts | 17 ++-- src/vtk/LPSView2DProxy/index.js | 6 +- src/vtk/LPSView3DProxy/index.d.ts | 17 ++-- src/vtk/LPSView3DProxy/index.js | 65 +--------------- src/vtk/LPSViewProxyBase/index.d.ts | 14 ++++ src/vtk/LPSViewProxyBase/index.js | 78 +++++++++++++++++++ 24 files changed, 178 insertions(+), 259 deletions(-) create mode 100644 src/vtk/LPSViewProxyBase/index.d.ts create mode 100644 src/vtk/LPSViewProxyBase/index.js diff --git a/src/components/VtkObliqueView.vue b/src/components/VtkObliqueView.vue index 9694d6ab0..cf07da675 100644 --- a/src/components/VtkObliqueView.vue +++ b/src/components/VtkObliqueView.vue @@ -96,12 +96,10 @@ import { useResetViewsEvents } from './tools/ResetViews.vue'; import { LPSAxisDir } from '../types/lps'; import { ViewProxyType } from '../core/proxies'; import { useViewProxy } from '../composables/useViewProxy'; -import { useWidgetManager } from '../composables/useWidgetManager'; import useViewSliceStore from '../store/view-configs/slicing'; import { OBLIQUE_OUTLINE_COLORS, ToolContainer, - VTKTwoViewWidgetManager, VTKResliceCursor, } from '../constants'; @@ -303,11 +301,6 @@ export default defineComponent({ const toolContainer = ref(); provide(ToolContainer, toolContainer); - // --- widget manager --- // - - const { widgetManager } = useWidgetManager(viewProxy); - provide(VTKTwoViewWidgetManager, widgetManager); - // --- window/level setup --- // watch( @@ -555,7 +548,6 @@ export default defineComponent({ windowWidth, windowLevel, isImageLoading, - widgetManager, enableResizeToFit, hover, }; diff --git a/src/components/VtkThreeView.vue b/src/components/VtkThreeView.vue index 862d25187..decc538da 100644 --- a/src/components/VtkThreeView.vue +++ b/src/components/VtkThreeView.vue @@ -57,7 +57,6 @@ import { onBeforeUnmount, onMounted, PropType, - provide, ref, toRefs, watch, @@ -94,8 +93,6 @@ import useVolumeColoringStore, { import { getShiftedOpacityFromPreset } from '../utils/vtk-helpers'; import CropTool from './tools/crop/CropTool.vue'; import PanTool from './tools/PanTool.vue'; -import { useWidgetManager } from '../composables/useWidgetManager'; -import { VTKThreeViewWidgetManager } from '../constants'; import { useCropStore, croppingPlanesEqual } from '../store/tools/crop'; import { isViewAnimating } from '../composables/isViewAnimating'; import { ColoringConfig } from '../types/views'; @@ -461,11 +458,6 @@ export default defineComponent({ { immediate: true } ); - // --- widget manager --- // - - const { widgetManager } = useWidgetManager(viewProxy); - provide(VTKThreeViewWidgetManager, widgetManager); - // --- camera setup --- // const { cameraUpVec, cameraDirVec } = useCameraOrientation( diff --git a/src/components/VtkTwoView.vue b/src/components/VtkTwoView.vue index 86205e21a..4751de986 100644 --- a/src/components/VtkTwoView.vue +++ b/src/components/VtkTwoView.vue @@ -47,35 +47,30 @@ - + @@ -181,10 +176,9 @@ import CrosshairsTool from './tools/crosshairs/CrosshairsTool.vue'; import { LPSAxisDir } from '../types/lps'; import { ViewProxyType } from '../core/proxies'; import { useViewProxy } from '../composables/useViewProxy'; -import { useWidgetManager } from '../composables/useWidgetManager'; import useViewSliceStore from '../store/view-configs/slicing'; import CropTool from './tools/crop/CropTool.vue'; -import { ToolContainer, VTKTwoViewWidgetManager } from '../constants'; +import { ToolContainer } from '../constants'; import { useProxyManager } from '../composables/useProxyManager'; import { getShiftedOpacityFromPreset } from '../utils/vtk-helpers'; import { useLayersStore } from '../store/datasets-layers'; @@ -334,12 +328,6 @@ export default defineComponent({ const toolContainer = ref(); provide(ToolContainer, toolContainer); - // --- widget manager --- // - - // TODO Attach to ViewProxy - const { widgetManager } = useWidgetManager(viewProxy); - provide(VTKTwoViewWidgetManager, widgetManager); - // --- scene setup --- // const segmentGroupStore = useSegmentGroupStore(); @@ -662,7 +650,6 @@ export default defineComponent({ topLabel, leftLabel, isImageLoading, - widgetManager, enableResizeToFit() { resizeToFit.value = true; }, diff --git a/src/components/tools/ResliceCursorTool.vue b/src/components/tools/ResliceCursorTool.vue index 5739b66ec..a8ad12f51 100644 --- a/src/components/tools/ResliceCursorTool.vue +++ b/src/components/tools/ResliceCursorTool.vue @@ -15,11 +15,7 @@ import { vtkResliceCursorViewWidget, ResliceCursorWidgetState, } from '@kitware/vtk.js/Widgets/Widgets3D/ResliceCursorWidget'; -import { - OBLIQUE_OUTLINE_COLORS, - VTKTwoViewWidgetManager, - VTKResliceCursor, -} from '@/src/constants'; +import { OBLIQUE_OUTLINE_COLORS, VTKResliceCursor } from '@/src/constants'; import { onViewProxyMounted } from '@/src/composables/useViewProxy'; import { getLPSAxisFromDir, getVTKViewTypeFromLPSAxis } from '@/src/utils/lps'; import { LPSAxisDir } from '@/src/types/lps'; @@ -39,12 +35,6 @@ export default defineComponent({ setup(props) { const active = true; const { viewId: viewID, viewDirection } = toRefs(props); - const widgetManager = inject(VTKTwoViewWidgetManager); - if (!widgetManager) { - throw new Error( - 'ResliceCursorTool component cannot access the 2D widget manager.' - ); - } const { currentImageMetadata: curImageMetadata, currentImageData } = useCurrentImage(); @@ -53,6 +43,7 @@ export default defineComponent({ const viewProxy = computed( () => viewStore.getViewProxy(viewID.value)! ); + const widgetManager = computed(() => viewProxy.value.getWidgetManager()); const viewType = computed(() => { return viewStore.viewSpecs[viewID.value].viewType; diff --git a/src/components/tools/SelectTool.vue b/src/components/tools/SelectTool.vue index 22b55c18b..5f8bc3809 100644 --- a/src/components/tools/SelectTool.vue +++ b/src/components/tools/SelectTool.vue @@ -3,18 +3,20 @@ import { onVTKEvent } from '@/src/composables/onVTKEvent'; import { useViewStore } from '@/src/store/views'; import { computed, toRefs } from 'vue'; import { WIDGET_PRIORITY } from '@kitware/vtk.js/Widgets/Core/AbstractWidget/Constants'; -import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager'; import { useToolSelectionStore } from '@/src/store/tools/toolSelection'; import { vtkAnnotationToolWidget } from '@/src/vtk/ToolWidgetUtils/types'; +import type { vtkLPSViewProxy } from '@/src/types/vtk-types'; const props = defineProps<{ viewId: string; - widgetManager: vtkWidgetManager; }>(); -const { viewId, widgetManager } = toRefs(props); +const { viewId } = toRefs(props); -const viewProxy = computed(() => useViewStore().getViewProxy(viewId.value)); +const viewProxy = computed(() => + useViewStore().getViewProxy(viewId.value) +); +const widgetManager = computed(() => viewProxy.value?.getWidgetManager()); const interactor = computed(() => viewProxy.value?.getInteractor()); const selectionStore = useToolSelectionStore(); @@ -22,6 +24,7 @@ onVTKEvent( interactor, 'onLeftButtonPress', (event: any) => { + if (!widgetManager.value) return; const withModifiers = !!(event.shiftKey || event.controlKey); const selectedData = widgetManager.value.getSelectedData(); if ('widget' in selectedData) { diff --git a/src/components/tools/crop/Crop3D.vue b/src/components/tools/crop/Crop3D.vue index ad3455e2b..3f6390d4c 100644 --- a/src/components/tools/crop/Crop3D.vue +++ b/src/components/tools/crop/Crop3D.vue @@ -1,7 +1,6 @@