From dd6acb2d03310ed76821aa14294cc467db6def1d Mon Sep 17 00:00:00 2001 From: Evren Ozkan Date: Mon, 24 Jun 2019 18:04:26 -0400 Subject: [PATCH] feat(extension-cornerstone): Add additional tools: Magnify, ROI Window, Probe, Ellipse, Rectangle, Invert, Rotate Right, Flip H, Flip V, Clear --- .../ohif-cornerstone-extension/package.json | 2 +- .../src/commandsModule.js | 70 ++++++++++++-- .../src/toolbarModule.js | 96 ++++++++++++++++++- package.json | 2 +- src/connectedComponents/PluginSwitch.js | 2 +- src/connectedComponents/ToolbarRow.js | 9 +- src/setupTools.js | 3 + yarn.lock | 8 +- 8 files changed, 166 insertions(+), 26 deletions(-) diff --git a/extensions/ohif-cornerstone-extension/package.json b/extensions/ohif-cornerstone-extension/package.json index f47bab1bc..3043f2a11 100644 --- a/extensions/ohif-cornerstone-extension/package.json +++ b/extensions/ohif-cornerstone-extension/package.json @@ -1,6 +1,6 @@ { "name": "@ohif/extension-cornerstone", - "version": "0.0.38", + "version": "0.0.39", "description": "OHIF extension for Cornerstone", "author": "OHIF", "license": "MIT", diff --git a/extensions/ohif-cornerstone-extension/src/commandsModule.js b/extensions/ohif-cornerstone-extension/src/commandsModule.js index d87569456..89597c65a 100644 --- a/extensions/ohif-cornerstone-extension/src/commandsModule.js +++ b/extensions/ohif-cornerstone-extension/src/commandsModule.js @@ -1,5 +1,6 @@ import cornerstone from 'cornerstone-core'; import cornerstoneTools from 'cornerstone-tools'; +import OHIF from 'ohif-core'; const actions = { rotateViewport: ({ viewports, rotation }) => { @@ -89,15 +90,60 @@ const actions = { // TODO console.warn('updateDisplaySet: ', direction); }, - clearAnnotations: () => { - console.warn('clearAnnotations: not yet implemented'); - // const toolState = - // cornerstoneTools.globalImageIdSpecificToolStateManager.toolState; - // if (!toolState) return; - // Object.keys(toolState).forEach(imageId => { - // if (!cornerstoneImageId || cornerstoneImageId === imageId) - // delete toolState[imageId]; - // }); + clearAnnotations: ({ viewports }) => { + const element = _getActiveViewportEnabledElement( + viewports.viewportSpecificData, + viewports.activeViewportIndex + ); + if (!element) { + return; + } + + const enabledElement = cornerstone.getEnabledElement(element); + if (!enabledElement || !enabledElement.image) { + return; + } + + const { + toolState, + } = cornerstoneTools.globalImageIdSpecificToolStateManager; + if ( + !toolState || + toolState.hasOwnProperty(enabledElement.image.imageId) === false + ) { + return; + } + + const imageIdToolState = toolState[enabledElement.image.imageId]; + + const measurementsToRemove = []; + + Object.keys(imageIdToolState).forEach(toolType => { + const { data } = imageIdToolState[toolType]; + + data.forEach(measurementData => { + const { _id, lesionNamingNumber, measurementNumber } = measurementData; + if (!_id) { + return; + } + + measurementsToRemove.push({ + toolType, + _id, + lesionNamingNumber, + measurementNumber, + }); + }); + }); + + measurementsToRemove.forEach(measurementData => { + OHIF.measurements.MeasurementHandlers.onRemoved({ + detail: { + toolType: measurementData.toolType, + measurementData, + }, + }); + }); }, }; @@ -147,7 +193,11 @@ const definitions = { storeContexts: ['viewports'], options: {}, }, - // TODO: Clear Annotations + clearAnnotations: { + commandFn: actions.clearAnnotations, + storeContexts: ['viewports'], + options: {}, + }, // TODO: Next/Previous image // TODO: First/Last image // Next/Previous series/DisplaySet diff --git a/extensions/ohif-cornerstone-extension/src/toolbarModule.js b/extensions/ohif-cornerstone-extension/src/toolbarModule.js index 3fd206ade..3d2616359 100644 --- a/extensions/ohif-cornerstone-extension/src/toolbarModule.js +++ b/extensions/ohif-cornerstone-extension/src/toolbarModule.js @@ -17,12 +17,12 @@ // -- ACTIVE_ROUTE::VIEWER // -- ACTIVE_VIEWPORT::CORNERSTONE // setToolActive commands should receive the button event that triggered -// so we can do the "bind to this butyon" magic +// so we can do the "bind to this button" magic const TOOLBAR_BUTTON_TYPES = { COMMAND: 'command', SET_TOOL_ACTIVE: 'setToolActive', - BUILT_IN: 'builtIn', + BUILT_IN: 'builtIn' }; const definitions = [ @@ -98,6 +98,98 @@ const definitions = [ behavior: 'CINE', }, }, + { + id: 'More', + label: 'More', + icon: 'ellipse-circle', + buttons: [ + { + id: 'Magnify', + label: 'Magnify', + icon: 'circle', + // + type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE, + commandName: 'setToolActive', + commandOptions: { toolName: 'Magnify' }, + }, + { + id: 'WwwcRegion', + label: 'ROI Window', + icon: 'stop', + // + type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE, + commandName: 'setToolActive', + commandOptions: { toolName: 'WwwcRegion' }, + }, + { + id: 'DragProbe', + label: 'Probe', + icon: 'dot-circle', + // + type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE, + commandName: 'setToolActive', + commandOptions: { toolName: 'DragProbe' }, + }, + { + id: 'EllipticalRoi', + label: 'Ellipse', + icon: 'circle-o', + // + type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE, + commandName: 'setToolActive', + commandOptions: { toolName: 'EllipticalRoi' }, + }, + { + id: 'RectangleRoi', + label: 'Rectangle', + icon: 'square-o', + // + type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE, + commandName: 'setToolActive', + commandOptions: { toolName: 'RectangleRoi' }, + }, + { + id: 'Invert', + label: 'Invert', + icon: 'adjust', + // + type: TOOLBAR_BUTTON_TYPES.COMMAND, + commandName: 'invertViewport', + }, + { + id: 'RotateRight', + label: 'Rotate Right', + icon: 'rotate-right', + // + type: TOOLBAR_BUTTON_TYPES.COMMAND, + commandName: 'rotateViewportCW', + }, + { + id: 'FlipH', + label: 'Flip H', + icon: 'ellipse-h', + // + type: TOOLBAR_BUTTON_TYPES.COMMAND, + commandName: 'flipViewportHorizontal', + }, + { + id: 'FlipV', + label: 'Flip V', + icon: 'ellipse-v', + // + type: TOOLBAR_BUTTON_TYPES.COMMAND, + commandName: 'flipViewportVertical', + }, + { + id: 'Clear', + label: 'Clear', + icon: 'trash', + // + type: TOOLBAR_BUTTON_TYPES.COMMAND, + commandName: 'clearAnnotations', + }, + ], + }, ]; export default { diff --git a/package.json b/package.json index 45e9f3353..4abaa5865 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ }, "dependencies": { "@babel/runtime": "^7.4.5", - "@ohif/extension-cornerstone": "0.0.38", + "@ohif/extension-cornerstone": "0.0.39", "@ohif/extension-dicom-html": "0.0.3", "@ohif/extension-dicom-microscopy": "0.0.8", "@ohif/extension-dicom-pdf": "0.0.7", diff --git a/src/connectedComponents/PluginSwitch.js b/src/connectedComponents/PluginSwitch.js index 12debb48a..4e4e1d153 100644 --- a/src/connectedComponents/PluginSwitch.js +++ b/src/connectedComponents/PluginSwitch.js @@ -13,7 +13,7 @@ class PluginSwitch extends Component { render() { return (
- +
); } diff --git a/src/connectedComponents/ToolbarRow.js b/src/connectedComponents/ToolbarRow.js index a12dde0d4..c25db6a24 100644 --- a/src/connectedComponents/ToolbarRow.js +++ b/src/connectedComponents/ToolbarRow.js @@ -1,11 +1,7 @@ import './ToolbarRow.css'; import React, { Component } from 'react'; -import { - RoundedButtonGroup, - ToolbarButton, - ExpandableToolMenu, -} from 'react-viewerbase'; +import { ExpandableToolMenu, RoundedButtonGroup, ToolbarButton } from 'react-viewerbase'; import { commandsManager, extensionManager } from './../App.js'; import ConnectedCineDialog from './ConnectedCineDialog'; @@ -155,7 +151,7 @@ class ToolbarRow extends Component { */ function _getButtonComponents(toolbarButtons, activeButtons) { return toolbarButtons.map((button, index) => { - if (button.buttons) { + if (button.buttons && button.buttons.length) { // Iterate over button definitions and update `onClick` behavior const childButtons = button.buttons.map(childButton => { childButton.onClick = _handleToolbarButtonClick.bind(this, childButton); @@ -171,7 +167,6 @@ function _getButtonComponents(toolbarButtons, activeButtons) { /> ); } - return (