From 6e873cc92a16bea9ebbbd39318bcac5435b27af3 Mon Sep 17 00:00:00 2001 From: dannyrb Date: Thu, 25 Jun 2020 17:00:42 -0400 Subject: [PATCH] Expose ViewportGridService API methods to extensions --- platform/core/src/index.js | 7 +- .../ViewportGridService.js | 54 +++++++ .../src/services/ViewportGridService/index.js | 3 + platform/core/src/services/index.js | 2 + .../contextProviders/ViewportGridProvider.jsx | 141 ++++++++++++++++-- platform/viewer/src/App.jsx | 50 +------ platform/viewer/src/appInit.js | 2 + 7 files changed, 199 insertions(+), 60 deletions(-) create mode 100644 platform/core/src/services/ViewportGridService/ViewportGridService.js diff --git a/platform/core/src/index.js b/platform/core/src/index.js index 9ffa1c70a..acfdd3fbf 100644 --- a/platform/core/src/index.js +++ b/platform/core/src/index.js @@ -30,8 +30,9 @@ import { // DicomMetadataStore, DisplaySetService, - ToolBarSerivce, + ToolBarSerivce, // TODO: Typo MeasurementService, + ViewportGridService, } from './services'; import IWebApiDataSource from './DataSources/IWebApiDataSource'; @@ -70,7 +71,8 @@ const OHIF = { UIViewportDialogService, DisplaySetService, MeasurementService, - ToolBarSerivce, + ToolBarSerivce, // TODO: TYPO + ViewportGridService, IWebApiDataSource, DicomMetadataStore, // @@ -112,6 +114,7 @@ export { DisplaySetService, MeasurementService, ToolBarSerivce, + ViewportGridService, IWebApiDataSource, DicomMetadataStore, ViewModelProvider, diff --git a/platform/core/src/services/ViewportGridService/ViewportGridService.js b/platform/core/src/services/ViewportGridService/ViewportGridService.js new file mode 100644 index 000000000..b4b213969 --- /dev/null +++ b/platform/core/src/services/ViewportGridService/ViewportGridService.js @@ -0,0 +1,54 @@ +const name = 'ViewportGridService'; + +const publicAPI = { + name, + hide: _hide, + show: _show, + setServiceImplementation, +}; + +const serviceImplementation = { + _hide: () => console.warn('hide() NOT IMPLEMENTED'), + _show: () => console.warn('show() NOT IMPLEMENTED'), +}; + +function _show({ viewportIndex, type, message, actions, onSubmit }) { + return serviceImplementation._show({ + viewportIndex, + type, + message, + actions, + onSubmit, + }); +} + +function _hide() { + return serviceImplementation._hide(); +} + +function setServiceImplementation({ + hide: hideImplementation, + show: showImplementation, +}) { + if (hideImplementation) { + serviceImplementation._hide = hideImplementation; + } + if (showImplementation) { + serviceImplementation._show = showImplementation; + } +} + +export default { + name, + create: ({ configuration = {} }) => { + return publicAPI; + }, +}; + +// initialState={{ +// numRows: 1, +// numCols: 1, +// viewports: [], +// activeViewportIndex: 0, +// }} +// reducer={viewportGridReducer} diff --git a/platform/core/src/services/ViewportGridService/index.js b/platform/core/src/services/ViewportGridService/index.js index e69de29bb..47d083531 100644 --- a/platform/core/src/services/ViewportGridService/index.js +++ b/platform/core/src/services/ViewportGridService/index.js @@ -0,0 +1,3 @@ +import ViewportGridService from './ViewportGridService'; + +export default ViewportGridService; diff --git a/platform/core/src/services/index.js b/platform/core/src/services/index.js index 96ecfb4d5..3862a2554 100644 --- a/platform/core/src/services/index.js +++ b/platform/core/src/services/index.js @@ -7,6 +7,7 @@ import UIViewportDialogService from './UIViewportDialogService'; import DicomMetadataStore from './DicomMetadataStore'; import DisplaySetService from './DisplaySetService'; import ToolBarSerivce from './ToolBarService'; +import ViewportGridService from './ViewportGridService'; export { MeasurementService, @@ -18,4 +19,5 @@ export { DicomMetadataStore, DisplaySetService, ToolBarSerivce, + ViewportGridService, }; diff --git a/platform/ui/src/contextProviders/ViewportGridProvider.jsx b/platform/ui/src/contextProviders/ViewportGridProvider.jsx index c56268cc4..b718d5145 100644 --- a/platform/ui/src/contextProviders/ViewportGridProvider.jsx +++ b/platform/ui/src/contextProviders/ViewportGridProvider.jsx @@ -1,20 +1,141 @@ -import React, { createContext, useContext, useReducer } from 'react'; - -// export const VIEWPORT_GRID_DEFAULT_VALUE = { -// numCols: 1, -// numRows: 1, -// activeViewportIndex: 0, -// viewports: [], -// }; +import React, { + createContext, + useCallback, + useContext, + useEffect, + useReducer, +} from 'react'; +import PropTypes from 'prop-types'; export const ViewportGridContext = createContext(); -export function ViewportGridProvider({ reducer, initialState, children }) { +// export function ViewportGridProvider({ reducer, initialState, children }) { +// return ( +// +// {children} +// +// ); +// } + +export function ViewportGridProvider({ children, service }) { + const DEFAULT_STATE = { + numRows: 1, + numCols: 1, + viewports: [], + activeViewportIndex: 0, + }; + + const viewportGridReducer = (state, action) => { + switch (action.type) { + case 'SET_ACTIVE_VIEWPORT_INDEX': + return { ...state, ...{ activeViewportIndex: action.payload } }; + case 'SET_DISPLAYSET_FOR_VIEWPORT': { + const { viewportIndex, displaySetInstanceUID } = action.payload; + const viewports = state.viewports.slice(); + + viewports[viewportIndex] = { displaySetInstanceUID }; + + return { ...state, ...{ viewports } }; + } + case 'SET_LAYOUT': { + const { numCols, numRows } = action.payload; + const numPanes = numCols * numRows; + const viewports = state.viewports.slice(); + const activeViewportIndex = + state.activeViewportIndex >= numPanes ? 0 : state.activeViewportIndex; + + while (viewports.length < numPanes) { + viewports.push({}); + } + while (viewports.length > numPanes) { + viewports.pop(); + } + + return { + ...state, + ...{ activeViewportIndex, numCols, numRows, viewports }, + }; + } + default: + return action.payload; + } + }; + + const [viewportGridState, dispatch] = useReducer( + DEFAULT_STATE, + viewportGridReducer + ); + + const getState = useCallback(() => viewportGridState, [viewportGridState]); + const setActiveViewportIndex = useCallback( + index => dispatch({ type: 'SET_ACTIVE_VIEWPORT_INDEX', payload: index }), + [dispatch] + ); + const setDisplaysetForViewport = useCallback( + ({ viewportIndex, displaySetInstanceUID }) => + dispatch({ + type: 'SET_DISPLAYSET_FOR_VIEWPORT', + payload: { + viewportIndex, + displaySetInstanceUID, + }, + }), + [dispatch] + ); + + const setLayout = useCallback( + ({ numCols, numRows }) => + dispatch({ + type: 'SET_LAYOUT', + payload: { + numCols, + numRows, + }, + }), + [dispatch] + ); + + /** + * Sets the implementation of a modal service that can be used by extensions. + * + * @returns void + */ + useEffect(() => { + if (service) { + service.setServiceImplementation({ + getState, + setActiveViewportIndex, + setDisplaysetForViewport, + setLayout, + }); + } + }, [ + getState, + service, + setActiveViewportIndex, + setDisplaysetForViewport, + setLayout, + ]); + + const api = { + // getState, + setActiveViewportIndex, + setDisplaysetForViewport, + setLayout, + }; + return ( - + {children} ); } +ViewportGridProvider.propTypes = { + children: PropTypes.any, + service: PropTypes.shape({ + setServiceImplementation: PropTypes.func, + }).isRequired, +}; + export const useViewportGrid = () => useContext(ViewportGridContext); diff --git a/platform/viewer/src/App.jsx b/platform/viewer/src/App.jsx index 969977107..01f1e3a3d 100644 --- a/platform/viewer/src/App.jsx +++ b/platform/viewer/src/App.jsx @@ -54,60 +54,14 @@ function App({ config, defaultExtensions }) { UIModalService, UINotificationService, UIViewportDialogService, + ViewportGridService, // TODO: Should this be a "UI" Service? } = servicesManager.services; - // A UI Service may need to use the ViewportGrid context - const viewportGridReducer = (state, action) => { - console.log(state, action); - - switch (action.type) { - case 'SET_ACTIVE_VIEWPORT_INDEX': - return { ...state, ...{ activeViewportIndex: action.payload } }; - case 'SET_DISPLAYSET_FOR_VIEWPORT': { - const { viewportIndex, displaySetInstanceUID } = action.payload; - const viewports = state.viewports.slice(); - - viewports[viewportIndex] = { displaySetInstanceUID }; - - return { ...state, ...{ viewports } }; - } - case 'SET_LAYOUT': { - const { numCols, numRows } = action.payload; - const numPanes = numCols * numRows; - const viewports = state.viewports.slice(); - const activeViewportIndex = - state.activeViewportIndex >= numPanes ? 0 : state.activeViewportIndex; - - while (viewports.length < numPanes) { - viewports.push({}); - } - while (viewports.length > numPanes) { - viewports.pop(); - } - - return { - ...state, - ...{ activeViewportIndex, numCols, numRows, viewports }, - }; - } - default: - return action.payload; - } - }; - return ( - + diff --git a/platform/viewer/src/appInit.js b/platform/viewer/src/appInit.js index ef8c16641..2f5433f54 100644 --- a/platform/viewer/src/appInit.js +++ b/platform/viewer/src/appInit.js @@ -10,6 +10,7 @@ import { MeasurementService, DisplaySetService, ToolBarSerivce, + ViewportGridService, // utils, // redux as reduxOHIF, } from '@ohif/core'; @@ -51,6 +52,7 @@ function appInit(appConfigOrFunc, defaultExtensions) { MeasurementService, DisplaySetService, ToolBarSerivce, + ViewportGridService, ]); /**