feat(extensions): Toolbar module depends on plugin in active viewport
This commit is contained in:
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;
|
||||
+2
-1
@@ -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"
|
||||
|
||||
Reference in new issue
Block a user