feat(extensions): Toolbar module depends on plugin in active viewport

This commit is contained in:
Erik Ziegler committed 2019-02-28 11:18:01 +01:00
1 parent 2fdc1687d0
commit f111411046
47 files changed
+10240 -72

No files matched your search

@@ -22,4 +22,5 @@ yarn-debug.log*
yarn-error.log*
.idea
yalc.lock
yalc.lock
.yalc
@@ -1,6 +1,6 @@
{
"name": "ohif-cornerstone-extension",
"version": "0.0.17",
"version": "0.0.20",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -26,12 +26,13 @@
"dcmjs": "^0.3.3",
"dicom-parser": "^1.8.3",
"hammerjs": "^2.0.8",
"ohif-core": "^0.3.0",
"ohif-core": "^0.3.3",
"prop-types": "^15.6.2",
"react": "^15.0.0 || ^16.0.0",
"react-dom": "^15.0.0 || ^16.0.0",
"react-redux": "^6.0.0",
"react-resize-detector": "^3.4.0",
"react-viewerbase": "^0.2.10",
"redux": "^4.0.1"
},
"devDependencies": {
@@ -51,6 +52,7 @@
"gh-pages": "^2.0.1",
"husky": "^1.3.1",
"lint-staged": "^8.1.0",
"lodash.clonedeep": "^4.5.0",
"prettier": "^1.15.3",
"react": "^16.6.3",
"react-dom": "^16.6.3",
@@ -90,6 +92,6 @@
"@babel/runtime": "^7.2.0",
"classnames": "^2.2.6",
"lodash.throttle": "^4.1.1",
"react-cornerstone-viewport": "^0.1.16"
"react-cornerstone-viewport": "^0.1.20"
}
}
@@ -0,0 +1,111 @@
import { connect } from 'react-redux';
import { CineDialog } from 'react-viewerbase';
import OHIF from 'ohif-core';
import cloneDeep from 'lodash.clonedeep';
const { setViewportSpecificData } = OHIF.redux.actions;
// TODO: I'm guessing this function will be used in other connect locations
// so we might want to put it somewhere shared
function getActiveViewportSpecificData(state) {
const { viewportSpecificData, activeViewportIndex } = state.viewports;
return viewportSpecificData[activeViewportIndex];
}
const mapStateToProps = state => {
// TODO:
// - Test if including CineDialog in the toolbarRow will prevent it
// from hovering over the rest of the UI when visible.
//
// - Create custom ToolbarButton which just shows Play state
// - Connect this ToolbarButton to Redux
const activeViewportSpecificData = getActiveViewportSpecificData(state);
let stack = {
imageIds: [],
currentImageIdIndex: 0
};
if (activeViewportSpecificData && activeViewportSpecificData.stack) {
stack = activeViewportSpecificData.stack
}
let cine = {
isPlaying: false,
cineFrameRate: 24
};
if (activeViewportSpecificData && activeViewportSpecificData.cine) {
cine = activeViewportSpecificData.cine
}
// TODO: activeViewportStackData won't currently change anything on
// CornerstoneViewport. The updates are too frequent and it's killing
// performance. Need to revisit how we can do this.
return {
activeViewportStackData: stack,
activeViewportCineData: cine,
activeViewportIndex: state.viewports.activeViewportIndex
};
};
const mapDispatchToProps = dispatch => {
return {
dispatchSetViewportSpecificData: (viewportIndex, data) => {
dispatch(setViewportSpecificData(viewportIndex, data));
},
};
};
const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
const { activeViewportStackData, activeViewportCineData, activeViewportIndex } = propsFromState;
return {
cineFrameRate: activeViewportCineData.cineFrameRate,
isPlaying: activeViewportCineData.isPlaying,
onPlayPauseChanged: isPlaying => {
const cine = cloneDeep(activeViewportCineData);
cine.isPlaying = !cine.isPlaying;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { cine });
},
onFrameRateChanged: frameRate => {
const cine = cloneDeep(activeViewportCineData);
cine.cineFrameRate = frameRate;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { cine });
},
onClickNextButton: () => {
const stack = cloneDeep(activeViewportStackData);
const largestPossibleIndex = stack.imageIds.length - 1;
stack.currentImageIdIndex = Math.min(stack.currentImageIdIndex + 1, largestPossibleIndex)
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
},
onClickBackButton: () => {
const stack = cloneDeep(activeViewportStackData);
stack.currentImageIdIndex = Math.max(stack.currentImageIdIndex - 1, 0);
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
},
onClickSkipToStart: () => {
const stack = cloneDeep(activeViewportStackData);
stack.currentImageIdIndex = 0;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
},
onClickSkipToEnd: () => {
const stack = cloneDeep(activeViewportStackData);
stack.currentImageIdIndex = stack.imageIds.length;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
}
};
};
const ConnectedCineDialog = connect(
mapStateToProps,
mapDispatchToProps,
mergeProps
)(CineDialog);
export default ConnectedCineDialog;
@@ -0,0 +1,29 @@
import { connect } from 'react-redux';
import { ToolbarSection } from 'react-viewerbase';
import OHIF from 'ohif-core'
const { setToolActive } = OHIF.redux.actions;
const mapStateToProps = state => {
const activeButton = state.tools.buttons.find(tool => tool.active === true);
return {
buttons: state.tools.buttons,
activeCommand: activeButton && activeButton.command
};
};
const mapDispatchToProps = dispatch => {
return {
setToolActive: tool => {
dispatch(setToolActive(tool.command))
}
};
};
const ConnectedToolbarSection = connect(
mapStateToProps,
mapDispatchToProps
)(ToolbarSection);
export default ConnectedToolbarSection;
@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import OHIFCornerstoneViewport from './OHIFCornerstoneViewport.js';
import ToolbarModule from './ToolbarModule.js';
/**
* Pass in 'children' to a React component. The purpose of this is to
@@ -48,6 +49,6 @@ export default class OHIFCornerstoneExtension {
}
getToolbarModule() {
return null;
return ToolbarModule;
}
}
@@ -0,0 +1,39 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ConnectedToolbarSection from './ConnectedToolbarSection';
import { ToolbarButton } from 'react-viewerbase';
import ConnectedCineDialog from './ConnectedCineDialog';
class ToolbarModule extends Component {
state = {
cineDialogOpen: false
}
onClickCineToolbarButton = () => {
this.setState({
cineDialogOpen: !this.state.cineDialogOpen
});
};
render() {
const cineDialogContainerStyle = {
display: this.state.cineDialogOpen ? 'inline-block' : 'none'
};
return (<div className="ToolbarModule">
<ConnectedToolbarSection />
<ToolbarButton
active={this.state.cineDialogOpen}
onClick={this.onClickCineToolbarButton}
text={'CINE'}
iconClasses={'fab fa-youtube'}
/>
<div className="CineDialogContainer" style={cineDialogContainerStyle}>
<ConnectedCineDialog />
</div>
</div>
);
}
}
export default ToolbarModule;
@@ -3248,6 +3248,11 @@ lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@@ -4413,10 +4418,10 @@ randomfill@^1.0.3:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
react-cornerstone-viewport@^0.1.16:
version "0.1.16"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.16.tgz#b1db13a3160ee10ffa9bfd91a6a0247f008170e2"
integrity sha512-hMEWoA3oDuurJ0AWZDH/hw1jPD7yY3EbaguE0CFusXdHsclCa7GjZXZb9EPqiAw8bF8vBIty7s96dwkqSFSLdw==
react-cornerstone-viewport@^0.1.20:
version "0.1.20"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.20.tgz#90e369a48e3f47dd5da69d42f0c8ee7e87e81543"
integrity sha512-SbaSjCAVFpQoUUXZ6d5F5QwKrP66zRJ4mN7JXPGyiL6+/m0jGkaBVci6pftkth66Lu5HRlCZUS8nh0plONPUtA==
dependencies:
lodash.debounce "^4.0.8"
moment "^2.23.0"