diff --git a/extensions/cornerstone-dicom-seg/src/utils/initSEGToolGroup.ts b/extensions/cornerstone-dicom-seg/src/utils/initSEGToolGroup.ts index 9db899b0b..a26f17f84 100644 --- a/extensions/cornerstone-dicom-seg/src/utils/initSEGToolGroup.ts +++ b/extensions/cornerstone-dicom-seg/src/utils/initSEGToolGroup.ts @@ -1,7 +1,14 @@ -function createSEGToolGroupAndAddTools(ToolGroupService, customizationService, toolGroupId) { +function createSEGToolGroupAndAddTools({ + commandsManager, + toolGroupService, + customizationService, + toolGroupId, +}) { const tools = customizationService.getCustomization('cornerstone.overlayViewportTools'); - return ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools); + const updatedTools = commandsManager.run('initializeSegmentLabelTool', { tools }); + + return toolGroupService.createToolGroupAndAddTools(toolGroupId, updatedTools); } export default createSEGToolGroupAndAddTools; diff --git a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx index b6d8e5259..81e42d2d4 100644 --- a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx +++ b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx @@ -214,7 +214,12 @@ function OHIFCornerstoneSEGViewport(props: withAppTypes) { // This creates a custom tool group which has the lifetime of this view // only, and does NOT interfere with currently displayed segmentations. - toolGroup = createSEGToolGroupAndAddTools(toolGroupService, customizationService, toolGroupId); + toolGroup = createSEGToolGroupAndAddTools({ + commandsManager, + toolGroupService, + customizationService, + toolGroupId, + }); return () => { // remove the segmentation representations if seg displayset changed diff --git a/extensions/cornerstone/src/commandsModule.ts b/extensions/cornerstone/src/commandsModule.ts index a0791411c..337e386c0 100644 --- a/extensions/cornerstone/src/commandsModule.ts +++ b/extensions/cornerstone/src/commandsModule.ts @@ -102,6 +102,7 @@ let segmentAIEnabled = false; function commandsModule({ servicesManager, commandsManager, + extensionManager, }: OhifTypes.Extensions.ExtensionParams): OhifTypes.Extensions.CommandsModule { const { viewportGridService, @@ -1743,17 +1744,62 @@ function commandsModule({ } }); }, - toggleSegmentLabel: ({ toggle }) => { + toggleSegmentLabel: () => { + const toolName = cornerstoneTools.SegmentLabelTool.toolName; const toolGroupIds = toolGroupService.getToolGroupIds(); + + const isOn = toolGroupIds.some(toolGroupId => { + const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId); + const mode = toolGroup.getToolInstance(toolName)?.mode; + return mode === 'Active'; + }); + toolGroupIds.forEach(toolGroupId => { const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId); - if (toggle) { - toolGroup.setToolActive(cornerstoneTools.SegmentLabelTool.toolName); + if (isOn) { + toolGroup.setToolDisabled(toolName); } else { - toolGroup.setToolDisabled(cornerstoneTools.SegmentLabelTool.toolName); + toolGroup.setToolActive(toolName); } }); }, + /** + * Used to sync the apps initial state with the config file settings. + * + * Will mutate the tools object of the given tool group and add the segmentLabelTool to the proper place. + * + * Use it before initializing the toolGroup with the tools. + */ + initializeSegmentLabelTool: ({ tools }) => { + const appConfig = extensionManager.appConfig; + const segmentLabelConfig = appConfig.segmentation?.segmentLabel; + + if (segmentLabelConfig?.enabledByDefault) { + const activeTools = tools?.active ?? []; + activeTools.push({ + toolName: toolNames.SegmentLabel, + configuration: { + hoverTimeout: segmentLabelConfig?.hoverTimeout ?? 1, + color: segmentLabelConfig?.labelColor, + background: segmentLabelConfig?.background, + }, + }); + + tools.active = activeTools; + return tools; + } + + const disabledTools = tools?.disabled ?? []; + disabledTools.push({ + toolName: toolNames.SegmentLabel, + configuration: { + hoverTimeout: segmentLabelConfig?.hoverTimeout ?? 1, + color: segmentLabelConfig?.labelColor, + }, + }); + tools.disabled = disabledTools; + return tools; + }, toggleUseCenterSegmentIndex: ({ toggle }) => { let labelmapTools = getLabelmapTools({ toolGroupService }); labelmapTools = labelmapTools.filter(tool => !tool.toolName.includes('Eraser')); @@ -2369,6 +2415,7 @@ function commandsModule({ startRecordingForAnnotationGroup: actions.startRecordingForAnnotationGroup, endRecordingForAnnotationGroup: actions.endRecordingForAnnotationGroup, toggleSegmentLabel: actions.toggleSegmentLabel, + initializeSegmentLabelTool: actions.initializeSegmentLabelTool, }; return { diff --git a/extensions/cornerstone/src/customizations/segmentationPanelCustomization.tsx b/extensions/cornerstone/src/customizations/segmentationPanelCustomization.tsx index 8da3c5723..82280b270 100644 --- a/extensions/cornerstone/src/customizations/segmentationPanelCustomization.tsx +++ b/extensions/cornerstone/src/customizations/segmentationPanelCustomization.tsx @@ -38,7 +38,6 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser const [previewEdits, setPreviewEdits] = useState(false); const [toggleSegmentEnabled, setToggleSegmentEnabled] = useState(false); const [useCenterAsSegmentIndex, setUseCenterAsSegmentIndex] = useState(false); - const [shouldShowLabelOnHover, setShouldShowLabelOnHover] = useState(false); const handlePreviewEditsChange = checked => { setPreviewEdits(checked); commandsManager.run('toggleSegmentPreviewEdit', { toggle: checked }); @@ -54,11 +53,6 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser commandsManager.run('toggleUseCenterSegmentIndex', { toggle: checked }); }; - const handleToggleShowLabelOnHover = checked => { - setShouldShowLabelOnHover(checked); - commandsManager.run('toggleSegmentLabel', { toggle: checked }); - }; - return (
@@ -84,14 +78,6 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser /> Hover on segment border to activate
- -
- - Show segment label on mouse hover -
); }, diff --git a/extensions/cornerstone/src/getCustomizationModule.tsx b/extensions/cornerstone/src/getCustomizationModule.tsx index b37931289..16f0dc825 100644 --- a/extensions/cornerstone/src/getCustomizationModule.tsx +++ b/extensions/cornerstone/src/getCustomizationModule.tsx @@ -12,13 +12,17 @@ import miscCustomization from './customizations/miscCustomization'; import captureViewportModalCustomization from './customizations/captureViewportModalCustomization'; import viewportDownloadWarningCustomization from './customizations/viewportDownloadWarningCustomization'; -function getCustomizationModule({ commandsManager, servicesManager }) { +function getCustomizationModule({ commandsManager, servicesManager, extensionManager }) { return [ { name: 'default', value: { ...viewportOverlayCustomization, - ...getSegmentationPanelCustomization({ commandsManager, servicesManager }), + ...getSegmentationPanelCustomization({ + commandsManager, + servicesManager, + extensionManager, + }), ...layoutSelectorCustomization, ...viewportToolsCustomization, ...viewportClickCommandsCustomization, diff --git a/modes/longitudinal/src/index.ts b/modes/longitudinal/src/index.ts index 60f9d0a7f..8e8d911ce 100644 --- a/modes/longitudinal/src/index.ts +++ b/modes/longitudinal/src/index.ts @@ -161,6 +161,7 @@ function modeFactory({ modeConfiguration }) { 'AdvancedMagnify', 'UltrasoundDirectionalTool', 'WindowLevelRegion', + 'SegmentLabelTool', ]); customizationService.setCustomizations({ diff --git a/modes/longitudinal/src/initToolGroups.js b/modes/longitudinal/src/initToolGroups.js index 6b608c52b..110f5bdd0 100644 --- a/modes/longitudinal/src/initToolGroups.js +++ b/modes/longitudinal/src/initToolGroups.js @@ -95,16 +95,12 @@ function initDefaultToolGroup(extensionManager, toolGroupService, commandsManage { toolName: toolNames.AdvancedMagnify, }, - { - toolName: toolNames.SegmentLabel, - configuration: { - hoverTimeout: 1, - }, - }, ], }; - toolGroupService.createToolGroupAndAddTools(toolGroupId, tools); + const updatedTools = commandsManager.run('initializeSegmentLabelTool', { tools }); + + toolGroupService.createToolGroupAndAddTools(toolGroupId, updatedTools); } function initSRToolGroup(extensionManager, toolGroupService) { diff --git a/modes/longitudinal/src/toolbarButtons.ts b/modes/longitudinal/src/toolbarButtons.ts index 4129b7248..c9db3f257 100644 --- a/modes/longitudinal/src/toolbarButtons.ts +++ b/modes/longitudinal/src/toolbarButtons.ts @@ -654,6 +654,30 @@ const toolbarButtons: Button[] = [ }, }, }, + // Section containers for the nested toolbox + { + id: 'SegmentationUtilities', + uiType: 'ohif.toolBoxButton', + props: { + buttonSection: true, + }, + }, + { + id: 'SegmentLabelTool', + uiType: 'ohif.toolBoxButton', + props: { + icon: 'tool-segment-label', + label: 'Segment Label Display', + tooltip: 'Click to show or hide segment labels when hovering with your mouse.', + commands: { commandName: 'toggleSegmentLabel' }, + evaluate: [ + 'evaluate.cornerstoneTool.toggle', + { + name: 'evaluate.cornerstone.hasSegmentation', + }, + ], + }, + }, // { // id: 'Undo', // uiType: 'ohif.toolButton', diff --git a/modes/segmentation/src/index.tsx b/modes/segmentation/src/index.tsx index 3e0de17a7..5962f56df 100644 --- a/modes/segmentation/src/index.tsx +++ b/modes/segmentation/src/index.tsx @@ -122,6 +122,7 @@ function modeFactory({ modeConfiguration }) { 'LabelmapSlicePropagation', 'InterpolateLabelmap', 'SegmentBidirectional', + 'SegmentLabelTool', ]); toolbarService.updateSection('SegmentationTools', [ 'BrushTools', diff --git a/modes/segmentation/src/initToolGroups.ts b/modes/segmentation/src/initToolGroups.ts index f0998bf52..48a153032 100644 --- a/modes/segmentation/src/initToolGroups.ts +++ b/modes/segmentation/src/initToolGroups.ts @@ -10,9 +10,10 @@ const colorsByOrientation = { coronal: 'rgb(0, 200, 0)', }; -function createTools(utilityModule) { +function createTools({ utilityModule, commandsManager }) { const { toolNames, Enums } = utilityModule.exports; - return { + + const tools = { active: [ { toolName: toolNames.WindowLevel, bindings: [{ mouseButton: Enums.MouseBindings.Primary }] }, { toolName: toolNames.Pan, bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }] }, @@ -114,24 +115,19 @@ function createTools(utilityModule) { { toolName: toolNames.UltrasoundDirectional }, ], - disabled: [ - { toolName: toolNames.ReferenceLines }, - { toolName: toolNames.AdvancedMagnify }, - { - toolName: toolNames.SegmentLabel, - configuration: { - hoverTimeout: 1, - }, - }, - ], + disabled: [{ toolName: toolNames.ReferenceLines }, { toolName: toolNames.AdvancedMagnify }], }; + + const updatedTools = commandsManager.run('initializeSegmentLabelTool', { tools }); + + return updatedTools; } function initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, toolGroupId) { const utilityModule = extensionManager.getModuleEntry( '@ohif/extension-cornerstone.utilityModule.tools' ); - const tools = createTools(utilityModule); + const tools = createTools({ commandsManager, utilityModule }); toolGroupService.createToolGroupAndAddTools(toolGroupId, tools); } @@ -141,7 +137,7 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { ); const servicesManager = extensionManager._servicesManager; const { cornerstoneViewportService } = servicesManager.services; - const tools = createTools(utilityModule); + const tools = createTools({ commandsManager, utilityModule }); tools.disabled.push( { toolName: utilityModule.exports.toolNames.Crosshairs, diff --git a/modes/segmentation/src/toolbarButtons.ts b/modes/segmentation/src/toolbarButtons.ts index 1263429d2..72c17b34c 100644 --- a/modes/segmentation/src/toolbarButtons.ts +++ b/modes/segmentation/src/toolbarButtons.ts @@ -739,6 +739,22 @@ const toolbarButtons: Button[] = [ ], }, }, + { + id: 'SegmentLabelTool', + uiType: 'ohif.toolBoxButton', + props: { + icon: 'tool-segment-label', + label: 'Segment Label Display', + tooltip: 'Click to show or hide segment labels when hovering with your mouse.', + commands: { commandName: 'toggleSegmentLabel' }, + evaluate: [ + 'evaluate.cornerstoneTool.toggle', + { + name: 'evaluate.cornerstone.hasSegmentation', + }, + ], + }, + }, ]; export default toolbarButtons; diff --git a/platform/app/public/config/default.js b/platform/app/public/config/default.js index eb9dc2b24..327de4fd2 100644 --- a/platform/app/public/config/default.js +++ b/platform/app/public/config/default.js @@ -275,6 +275,14 @@ window.config = { // Could use services manager here to bring up a dialog/modal if needed. console.warn('test, navigate to https://ohif.org/'); }, + // segmentation: { + // segmentLabel: { + // enabledByDefault: true, + // labelColor: [255, 255, 0, 1], // must be an array + // hoverTimeout: 1, + // background: 'rgba(100, 100, 100, 0.5)', // can be any valid css color + // }, + // }, // whiteLabeling: { // createLogoComponentFn: function (React) { // return React.createElement( diff --git a/platform/ui-next/src/components/Icons/Icons.tsx b/platform/ui-next/src/components/Icons/Icons.tsx index ef2bbdd71..4d3deb742 100644 --- a/platform/ui-next/src/components/Icons/Icons.tsx +++ b/platform/ui-next/src/components/Icons/Icons.tsx @@ -145,6 +145,7 @@ import { ToolContract, ToolExpand, ToolClickSegment, + ToolSegmentLabel, } from './Sources/Tools'; import ActionNewDialog from './Sources/ActionNewDialog'; import NotificationInfo from './Sources/NotificationInfo'; @@ -730,6 +731,7 @@ export const Icons = { 'tool-ultrasound-bidirectional': (props: IconProps) => ToolUltrasoundBidirectional(props), 'tool-window-level': (props: IconProps) => ToolWindowLevel(props), 'tool-window-region': (props: IconProps) => ToolWindowRegion(props), + 'tool-segment-label': (props: IconProps) => ToolSegmentLabel(props), 'icon-tool-window-region': (props: IconProps) => ToolWindowRegion(props), 'icon-tool-ultrasound-bidirectional': (props: IconProps) => ToolUltrasoundBidirectional(props), 'icon-tool-cobb-angle': (props: IconProps) => ToolCobbAngle(props), diff --git a/platform/ui-next/src/components/Icons/Sources/Tools.tsx b/platform/ui-next/src/components/Icons/Sources/Tools.tsx index d4fbc8f23..2a612dabf 100644 --- a/platform/ui-next/src/components/Icons/Sources/Tools.tsx +++ b/platform/ui-next/src/components/Icons/Sources/Tools.tsx @@ -2983,6 +2983,32 @@ export const ToolUltrasoundBidirectional = (props: IconProps) => ( ); +export const ToolSegmentLabel = (props: IconProps) => ( + + + + +); + export const ToolWindowLevel = (props: IconProps) => (