From 70ce476c3295bad401afc02ce8470429fc3001c2 Mon Sep 17 00:00:00 2001 From: dannyrb Date: Thu, 14 May 2020 15:58:06 -0400 Subject: [PATCH] Create and use ViewportGrid component --- .../viewer/src/components/ViewportGrid.jsx | 100 ++++++++++++++++++ .../viewer/src/components/ViewportPane.jsx | 47 ++++++++ .../src/components/getViewportsModule.js | 39 +++++++ platform/viewer/src/routes/ModeRoute.js | 5 + 4 files changed, 191 insertions(+) create mode 100644 platform/viewer/src/components/ViewportGrid.jsx create mode 100644 platform/viewer/src/components/ViewportPane.jsx create mode 100644 platform/viewer/src/components/getViewportsModule.js diff --git a/platform/viewer/src/components/ViewportGrid.jsx b/platform/viewer/src/components/ViewportGrid.jsx new file mode 100644 index 000000000..c14134bba --- /dev/null +++ b/platform/viewer/src/components/ViewportGrid.jsx @@ -0,0 +1,100 @@ +/** + * CSS Grid Reference: http://grid.malven.co/ + */ +import React, { useEffect } from 'react'; +import PropTypes from 'prop-types'; +// +import ViewportPane from './ViewportPane.jsx'; +// import DefaultViewport from './DefaultViewport.js'; +// import EmptyViewport from './EmptyViewport.js'; + +function ViewportGrid(props) { + const { + activeViewportIndex, + viewports, + displaySets, + numRows, + numColumns, + children, + } = props; + + const rowSize = 100 / numRows; + const colSize = 100 / numColumns; + + // viewportData --> displaySets + + const getViewportPanes = () => + viewports.map((viewport, viewportIndex) => { + const someId = viewport.displaySetId; + const displaySet = displaySets[someId]; + + if (!displaySet) { + // TODO: Empty Viewport + return null; + } + + // const pluginName = + // !layout.plugin && displaySet && displaySet.plugin + // ? displaySet.plugin + // : layout.plugin; + + // const ViewportComponent = _getViewportComponent( + // data, // Why do we pass this as `ViewportData`, when that's not really what it is? + // viewportIndex, + // children, + + // pluginName, + // defaultPluginName + // ); + + return ( + { /* setDisplaySet for Viewport */ }} + viewportIndex={viewportIndex} + isActive={activeViewportIndex === viewportIndex} + > + {/* {ViewportComponent} */} + + ); + }); + + // const ViewportPanes = React.useMemo(getViewportPanes, [ + // viewportData, + // children, + // setViewportData, + // activeViewportIndex, + // ]); + + return ( +
+ {/* {ViewportPanes} */} +
+ ); +}; + +ViewportGrid.propTypes = { + viewports: PropTypes.array.isRequired, + activeViewportIndex: PropTypes.number.isRequired, + children: PropTypes.node, + numRows: PropTypes.number.isRequired, + numColumns: PropTypes.number.isRequired, +}; + +ViewportGrid.defaultProps = { + viewports: [], + numRows: 1, + numColumns: 1, + activeViewportIndex: 0, +}; + +export default ViewportGrid; diff --git a/platform/viewer/src/components/ViewportPane.jsx b/platform/viewer/src/components/ViewportPane.jsx new file mode 100644 index 000000000..d3d4769d9 --- /dev/null +++ b/platform/viewer/src/components/ViewportPane.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { useDrop } from 'react-dnd'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +const ViewportPane = function(props) { + const { children, onDrop, viewportIndex } = props; + const [{ isHovered, isHighlighted }, drop] = useDrop({ + accept: 'displayset', + drop: (displaySet, monitor) => { + const canDrop = monitor.canDrop(); + const isOver = monitor.isOver(); + + if (canDrop && isOver && onDrop) { + const { StudyInstanceUID, displaySetInstanceUID } = displaySet; + + onDrop({ viewportIndex, StudyInstanceUID, displaySetInstanceUID }); + } + }, + // Monitor, and collect props; returned as values by `useDrop` + collect: monitor => ({ + isHighlighted: monitor.canDrop(), + isHovered: monitor.isOver(), + }), + }); + + return ( +
+ {children} +
+ ); +}; + +ViewportPane.propTypes = { + /** The ViewportComp */ + children: PropTypes.node.isRequired, + /** Function that handles drop events */ + onDrop: PropTypes.func.isRequired, + /** The "index" of the viewport in the current ViewportGrid */ + viewportIndex: PropTypes.number.isRequired, +}; + +export default ViewportPane; diff --git a/platform/viewer/src/components/getViewportsModule.js b/platform/viewer/src/components/getViewportsModule.js new file mode 100644 index 000000000..af58c0ecb --- /dev/null +++ b/platform/viewer/src/components/getViewportsModule.js @@ -0,0 +1,39 @@ +/** + * + * + * @param {*} plugin + * @param {*} viewportData + * @param {*} viewportIndex + * @param {*} children + * @returns + */ +function _getViewportComponent( + viewportData, + viewportIndex, + children, + availablePlugins, + pluginName, + defaultPluginName +) { + if (viewportData.displaySet) { + pluginName = pluginName || defaultPluginName; + const ViewportComponent = availablePlugins[pluginName]; + + if (!ViewportComponent) { + throw new Error( + `No Viewport Component available for name ${pluginName}. + Available plugins: ${JSON.stringify(availablePlugins)}` + ); + } + + return ( + + ); + } + + return ; +} diff --git a/platform/viewer/src/routes/ModeRoute.js b/platform/viewer/src/routes/ModeRoute.js index a4f691217..c4b5fdd6d 100644 --- a/platform/viewer/src/routes/ModeRoute.js +++ b/platform/viewer/src/routes/ModeRoute.js @@ -2,6 +2,7 @@ import React, { useContext, useEffect, useCallback } from 'react'; import { displaySetManager, ToolBarManager } from '@ohif/core'; import { useViewModel } from '@ohif/core'; import Compose from './Compose'; +import ViewportGrid from './../components/ViewportGrid.jsx'; export default function ModeRoute({ location, @@ -85,10 +86,14 @@ export default function ModeRoute({ return ( + {/* TODO: extensionManager is already provided to the extension module. + * Use it from there instead of passing as a prop here. + */}