diff --git a/extensions/cornerstone-dicom-sr/src/commandsModule.ts b/extensions/cornerstone-dicom-sr/src/commandsModule.ts index d65278d6c..43a6efb3c 100644 --- a/extensions/cornerstone-dicom-sr/src/commandsModule.ts +++ b/extensions/cornerstone-dicom-sr/src/commandsModule.ts @@ -41,7 +41,7 @@ const _generateReport = (measurementData, additionalFindingTypes, options = {}) }; const commandsModule = (props: withAppTypes) => { - const { servicesManager, extensionManager } = props; + const { servicesManager, extensionManager, commandsManager } = props; const { customizationService, viewportGridService, displaySetService } = servicesManager.services; const actions = { @@ -156,12 +156,14 @@ const commandsModule = (props: withAppTypes) => { const displaySets = displaySetService.getDisplaySetsForSeries(SeriesInstanceUIDs[0]); if (displaySets.length) { - viewportGridService.setDisplaySetsForViewports([ - { - viewportId: viewportGridService.getActiveViewportId(), - displaySetInstanceUIDs: [displaySets[0].displaySetInstanceUID], - }, - ]); + commandsManager.run('setDisplaySetsForViewports', { + viewportsToUpdate: [ + { + viewportId: viewportGridService.getActiveViewportId(), + displaySetInstanceUIDs: [displaySets[0].displaySetInstanceUID], + }, + ], + }); } }, }; diff --git a/extensions/cornerstone-dynamic-volume/src/commandsModule.ts b/extensions/cornerstone-dynamic-volume/src/commandsModule.ts index 34422bebb..b50589056 100644 --- a/extensions/cornerstone-dynamic-volume/src/commandsModule.ts +++ b/extensions/cornerstone-dynamic-volume/src/commandsModule.ts @@ -263,7 +263,7 @@ const commandsModule = ({ commandsManager, servicesManager }: withAppTypes) => { } } - viewportGridService.setDisplaySetsForViewports(viewportsToUpdate); + commandsManager.run('setDisplaySetsForViewports', { viewportsToUpdate }); }, swapComputedWithDynamicDisplaySet: () => { // Todo: this assumes there is only one dynamic display set in the viewer @@ -313,7 +313,7 @@ const commandsModule = ({ commandsManager, servicesManager }: withAppTypes) => { } } - viewportGridService.setDisplaySetsForViewports(viewportsToUpdate); + commandsManager.run('setDisplaySetsForViewports', { viewportsToUpdate }); }, createNewLabelMapForDynamicVolume: async ({ label }) => { const { viewports, activeViewportId } = viewportGridService.getState(); diff --git a/extensions/cornerstone/src/commandsModule.ts b/extensions/cornerstone/src/commandsModule.ts index b3bff6094..237e78df0 100644 --- a/extensions/cornerstone/src/commandsModule.ts +++ b/extensions/cornerstone/src/commandsModule.ts @@ -581,7 +581,6 @@ function commandsModule({ }); viewport.render(); }, - toggleViewportColorbar: ({ viewportId, displaySetInstanceUIDs, options = {} }) => { const hasColorbar = colorbarService.hasColorbar(viewportId); if (hasColorbar) { @@ -590,7 +589,6 @@ function commandsModule({ } colorbarService.addColorbar(viewportId, displaySetInstanceUIDs, options); }, - setWindowLevel(props) { const { toolGroupId } = props; const { viewportId } = _getActiveViewportEnabledElement(); @@ -1536,6 +1534,22 @@ function commandsModule({ measurementService.remove(activeAnnotationUID); }); }, + setDisplaySetsForViewports: ({ viewportsToUpdate }) => { + const { cineService, viewportGridService } = servicesManager.services; + // Stopping the cine of modified viewports before changing the viewports to + // avoid inconsistent state and lost references + viewportsToUpdate.forEach(viewport => { + const state = cineService.getState(); + const currentCineState = state.cines?.[viewport.viewportId]; + cineService.setCine({ + id: viewport.viewportId, + frameRate: currentCineState?.frameRate ?? state.default?.frameRate ?? 24, + isPlaying: false, + }); + }); + + viewportGridService.setDisplaySetsForViewports(viewportsToUpdate); + }, undo: () => { DefaultHistoryMemo.undo(); }, @@ -1987,6 +2001,7 @@ function commandsModule({ deleteActiveAnnotation: { commandFn: actions.deleteActiveAnnotation, }, + setDisplaySetsForViewports: actions.setDisplaySetsForViewports, undo: actions.undo, redo: actions.redo, interpolateLabelmap: actions.interpolateLabelmap, diff --git a/extensions/default/src/commandsModule.ts b/extensions/default/src/commandsModule.ts index 0cb05c7fa..c32c8cb9a 100644 --- a/extensions/default/src/commandsModule.ts +++ b/extensions/default/src/commandsModule.ts @@ -622,7 +622,7 @@ const commandsModule = ({ }); } - viewportGridService.setDisplaySetsForViewports(updatedViewports); + commandsManager.run('setDisplaySetsForViewports', { viewportsToUpdate: updatedViewports }); setTimeout(() => actions.scrollActiveThumbnailIntoView(), 0); }, diff --git a/extensions/default/src/customizations/studyBrowserCustomization.ts b/extensions/default/src/customizations/studyBrowserCustomization.ts index d171b79ad..000fdb9c5 100644 --- a/extensions/default/src/customizations/studyBrowserCustomization.ts +++ b/extensions/default/src/customizations/studyBrowserCustomization.ts @@ -46,10 +46,9 @@ export default { 'studyBrowser.studyMode': 'all', 'studyBrowser.thumbnailDoubleClickCallback': { callbacks: [ - ({ activeViewportId, servicesManager, isHangingProtocolLayout }) => + ({ activeViewportId, servicesManager, commandsManager, isHangingProtocolLayout }) => async displaySetInstanceUID => { - const { hangingProtocolService, viewportGridService, uiNotificationService } = - servicesManager.services; + const { hangingProtocolService, uiNotificationService } = servicesManager.services; let updatedViewports = []; const viewportId = activeViewportId; @@ -69,7 +68,9 @@ export default { }); } - viewportGridService.setDisplaySetsForViewports(updatedViewports); + commandsManager.run('setDisplaySetsForViewports', { + viewportsToUpdate: updatedViewports, + }); }, ], }, diff --git a/platform/app/src/components/ViewportGrid.tsx b/platform/app/src/components/ViewportGrid.tsx index 0c4561af0..6cd48f796 100644 --- a/platform/app/src/components/ViewportGrid.tsx +++ b/platform/app/src/components/ViewportGrid.tsx @@ -247,7 +247,8 @@ function ViewerViewportGrid(props: withAppTypes) { }); event.consume(); - viewportGridService.setDisplaySetsForViewports(updatedViewports); + + commandsManager.run('setDisplaySetsForViewports', { viewportsToUpdate: updatedViewports }); } ); @@ -268,7 +269,8 @@ function ViewerViewportGrid(props: withAppTypes) { dropHandlerPromise.then(({ handled }) => { if (!handled) { const updatedViewports = _getUpdatedViewports(viewportId, displaySetInstanceUID); - viewportGridService.setDisplaySetsForViewports(updatedViewports); + + commandsManager.run('setDisplaySetsForViewports', { viewportsToUpdate: updatedViewports }); } }); viewportGridService.publishViewportOnDropHandled({ displaySetInstanceUID }); diff --git a/platform/core/src/services/ViewportGridService/ViewportGridService.ts b/platform/core/src/services/ViewportGridService/ViewportGridService.ts index f39fec02b..1eb8bb6b2 100644 --- a/platform/core/src/services/ViewportGridService/ViewportGridService.ts +++ b/platform/core/src/services/ViewportGridService/ViewportGridService.ts @@ -189,14 +189,14 @@ class ViewportGridService extends PubSubService { this.setDisplaySetsForViewports([props]); } - public async setDisplaySetsForViewports(props) { - await this.serviceImplementation._setDisplaySetsForViewports(props); + public async setDisplaySetsForViewports(viewportsToUpdate) { + await this.serviceImplementation._setDisplaySetsForViewports(viewportsToUpdate); const state = this.getState(); const updatedViewports = []; const removedViewportIds = []; - for (const viewport of props) { + for (const viewport of viewportsToUpdate) { const updatedViewport = state.viewports.get(viewport.viewportId); if (updatedViewport) { diff --git a/platform/docs/docs/platform/services/customization-service/sampleCustomizations.tsx b/platform/docs/docs/platform/services/customization-service/sampleCustomizations.tsx index a7dd8c8a5..6ab5b84ee 100644 --- a/platform/docs/docs/platform/services/customization-service/sampleCustomizations.tsx +++ b/platform/docs/docs/platform/services/customization-service/sampleCustomizations.tsx @@ -1814,7 +1814,10 @@ window.config = { }); } - viewportGridService.setDisplaySetsForViewports(updatedViewports); + commandsManager.run({ + commandName: 'setDisplaySetsForViewports', + commandOptions: { viewportsToUpdate: updatedViewports }, + }); }, }`, configuration: ` @@ -1859,7 +1862,10 @@ window.config = { duration: 3000, }); } - viewportGridService.setDisplaySetsForViewports(updatedViewports); + commandsManager.run({ + commandName: 'setDisplaySetsForViewports', + commandOptions: { viewportsToUpdate: updatedViewports }, + }); }; }, }],