fix: backward compatibility with toolbar service (#5052)

This commit is contained in:
Alireza 2025-05-16 13:42:35 -04:00 committed by GitHub
parent c6b28654b5
commit 9b1b501d83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 198 additions and 144 deletions

View File

@ -5,6 +5,8 @@ import { PanelSegmentation } from '@ohif/extension-cornerstone';
import DynamicExport from './panels/DynamicExport'; import DynamicExport from './panels/DynamicExport';
function getPanelModule({ commandsManager, extensionManager, servicesManager, configuration }) { function getPanelModule({ commandsManager, extensionManager, servicesManager, configuration }) {
const { toolbarService } = servicesManager.services;
const wrappedDynamicDataPanel = () => { const wrappedDynamicDataPanel = () => {
return ( return (
<DynamicDataPanel <DynamicDataPanel
@ -19,7 +21,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager, co
return ( return (
<> <>
<Toolbox <Toolbox
buttonSectionId="dynamic-toolbox" buttonSectionId={toolbarService.sections.dynamicToolbox}
title="Threshold Tools" title="Threshold Tools"
/> />
<PanelSegmentation <PanelSegmentation

View File

@ -172,7 +172,7 @@ function ViewportDataOverlayMenu({ viewportId }: withAppTypes<{ viewportId: stri
}; };
// Check if the advanced window level components exist in toolbar // Check if the advanced window level components exist in toolbar
const hasAdvancedRenderingControls = !!toolbarService.getButton('advancedRenderingControls'); const hasAdvancedRenderingControls = !!toolbarService.getButton('AdvancedRenderingControls');
const hasOpacityMenu = !!toolbarService.getButton('opacityMenu'); const hasOpacityMenu = !!toolbarService.getButton('opacityMenu');
const handleThresholdOpacityToggle = () => { const handleThresholdOpacityToggle = () => {

View File

@ -33,10 +33,12 @@ const getPanelModule = ({ commandsManager, servicesManager, extensionManager }:
}; };
const wrappedPanelSegmentationWithTools = ({ configuration }) => { const wrappedPanelSegmentationWithTools = ({ configuration }) => {
const { toolbarService } = servicesManager.services;
return ( return (
<> <>
<Toolbox <Toolbox
buttonSectionId="segmentationToolbox" buttonSectionId={toolbarService.sections.segmentationToolbox}
title="Segmentation Tools" title="Segmentation Tools"
/> />
<PanelSegmentation <PanelSegmentation

View File

@ -56,7 +56,7 @@ function mapMeasurementToDisplay(measurement, displaySetService) {
* @param {Object} options.valueTypes - The value types for mapping measurements. * @param {Object} options.valueTypes - The value types for mapping measurements.
* @returns {Array} An array of mapped and filtered measurements. * @returns {Array} An array of mapped and filtered measurements.
*/ */
export function useMeasurements({ measurementFilter }) { export function useMeasurements({ measurementFilter } = { measurementFilter: () => true }) {
const { servicesManager } = useSystem(); const { servicesManager } = useSystem();
const { measurementService, displaySetService } = servicesManager.services; const { measurementService, displaySetService } = servicesManager.services;
const [displayMeasurements, setDisplayMeasurements] = useState([]); const [displayMeasurements, setDisplayMeasurements] = useState([]);

View File

@ -138,27 +138,29 @@ export function useViewportDisplaySets(
}); });
}, [includeOverlay, segmentationRepresentations, displaySetService]); }, [includeOverlay, segmentationRepresentations, displaySetService]);
const overlayDisplaySetUIDs = useMemo( const overlayDisplaySetUIDs = useMemo(() => {
() => overlayDisplaySets.map(ds => ds.displaySetInstanceUID), return overlayDisplaySets.map(ds => ds.displaySetInstanceUID);
[overlayDisplaySets] }, [overlayDisplaySets]);
);
// Get enhanced display sets (only if needed) // Get enhanced display sets (only if needed)
const needsEnhancedDisplaySets = const needsEnhancedDisplaySets =
includeBackground || includeForeground || includePotentialOverlay || includePotentialForeground; includeBackground || includeForeground || includePotentialOverlay || includePotentialForeground;
const { viewportDisplaySets, enhancedDisplaySets } = useMemo(() => { const { viewportDisplaySets = [], enhancedDisplaySets = [] } = useMemo(() => {
if (!needsEnhancedDisplaySets) { if (!needsEnhancedDisplaySets) {
return { viewportDisplaySets: [], enhancedDisplaySets: [] }; return { viewportDisplaySets: [], enhancedDisplaySets: [] };
} }
return getEnhancedDisplaySets({ return (
viewportId: viewportIdToUse, getEnhancedDisplaySets({
services: { displaySetService, viewportGridService }, viewportId: viewportIdToUse,
}); services: { displaySetService, viewportGridService },
}) || { viewportDisplaySets: [], enhancedDisplaySets: [] }
);
}, [viewportIdToUse, displaySetService, viewportGridService, needsEnhancedDisplaySets]); }, [viewportIdToUse, displaySetService, viewportGridService, needsEnhancedDisplaySets]);
const backgroundDisplaySet = useMemo( const backgroundDisplaySet = useMemo(
() => (includeBackground ? viewportDisplaySets[0] : undefined), () =>
includeBackground && viewportDisplaySets.length > 0 ? viewportDisplaySets[0] : undefined,
[includeBackground, viewportDisplaySets] [includeBackground, viewportDisplaySets]
); );
@ -227,7 +229,10 @@ export function useViewportDisplaySets(
foregroundDisplaySetUIDs, foregroundDisplaySetUIDs,
]); ]);
const result: ViewportDisplaySets = { allDisplaySets, viewportDisplaySets }; const result: ViewportDisplaySets = {
allDisplaySets: allDisplaySets || [],
viewportDisplaySets: viewportDisplaySets || [],
};
if (includeBackground) { if (includeBackground) {
result.backgroundDisplaySet = backgroundDisplaySet; result.backgroundDisplaySet = backgroundDisplaySet;

View File

@ -4,6 +4,8 @@ import { Toolbox } from '@ohif/extension-default';
import PanelTMTV from './Panels/PanelTMTV'; import PanelTMTV from './Panels/PanelTMTV';
function getPanelModule({ commandsManager, extensionManager, servicesManager }) { function getPanelModule({ commandsManager, extensionManager, servicesManager }) {
const { toolbarService } = servicesManager.services;
const wrappedPanelPetSuv = () => { const wrappedPanelPetSuv = () => {
return <PanelPetSUV />; return <PanelPetSUV />;
}; };
@ -11,7 +13,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
const wrappedROIThresholdToolbox = () => { const wrappedROIThresholdToolbox = () => {
return ( return (
<Toolbox <Toolbox
buttonSectionId="ROIThresholdToolbox" buttonSectionId={toolbarService.sections.roiThresholdToolbox}
title="Threshold Tools" title="Threshold Tools"
/> />
); );
@ -25,7 +27,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
return ( return (
<> <>
<Toolbox <Toolbox
buttonSectionId="ROIThresholdToolbox" buttonSectionId={toolbarService.sections.roiThresholdToolbox}
title="Threshold Tools" title="Threshold Tools"
/> />
<PanelTMTV <PanelTMTV

View File

@ -96,7 +96,7 @@ function modeFactory({ modeConfiguration }) {
toolbarService.register(toolbarButtons); toolbarService.register(toolbarButtons);
toolbarService.updateSection('primary', [ toolbarService.updateSection('primary', [
'measurementSection', 'MeasurementTools',
'Zoom', 'Zoom',
'WindowLevel', 'WindowLevel',
'Pan', 'Pan',

View File

@ -11,17 +11,17 @@ export const setToolActiveToolbar = {
const toolbarButtons: Button[] = [ const toolbarButtons: Button[] = [
// sections // sections
{ {
id: 'measurementSection', id: 'MeasurementTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'measurementSection', buttonSection: true,
}, },
}, },
{ {
id: 'MoreTools', id: 'MoreTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'moreToolsSection', buttonSection: true,
}, },
}, },

View File

@ -103,7 +103,7 @@ function modeFactory() {
'MoreTools', 'MoreTools',
]); ]);
toolbarService.updateSection('windowLevelSection', [ toolbarService.updateSection('WindowLevelGroup', [
'WindowLevel', 'WindowLevel',
'Soft tissue', 'Soft tissue',
'Lung', 'Lung',
@ -118,10 +118,10 @@ function modeFactory() {
]); ]);
toolbarService.updateSection(toolbarService.sections.viewportActionMenu.bottomMiddle, [ toolbarService.updateSection(toolbarService.sections.viewportActionMenu.bottomMiddle, [
'advancedRenderingControls', 'AdvancedRenderingControls',
]); ]);
toolbarService.updateSection('advancedRenderingControls', [ toolbarService.updateSection('AdvancedRenderingControls', [
'voiManualControlMenu', 'voiManualControlMenu',
'Colorbar', 'Colorbar',
'opacityMenu', 'opacityMenu',
@ -138,7 +138,7 @@ function modeFactory() {
'windowLevelMenu', 'windowLevelMenu',
]); ]);
toolbarService.updateSection('windowLevelSection', [ toolbarService.updateSection('WindowLevelGroup', [
'WindowLevel', 'WindowLevel',
'Soft tissue', 'Soft tissue',
'Lung', 'Lung',
@ -147,7 +147,7 @@ function modeFactory() {
'Brain', 'Brain',
]); ]);
toolbarService.updateSection(toolbarService.sections.measurementSection, [ toolbarService.updateSection('MeasurementTools', [
'Length', 'Length',
'Bidirectional', 'Bidirectional',
'ArrowAnnotate', 'ArrowAnnotate',
@ -158,7 +158,7 @@ function modeFactory() {
'LivewireContour', 'LivewireContour',
]); ]);
toolbarService.updateSection(toolbarService.sections.moreToolsSection, [ toolbarService.updateSection('MoreTools', [
'Reset', 'Reset',
'rotate-right', 'rotate-right',
'flipHorizontal', 'flipHorizontal',

View File

@ -40,35 +40,26 @@ export const setToolActiveToolbar = {
}, },
}; };
const callbacks = (toolName: string) => [
{
commandName: 'setViewportForToolConfiguration',
commandOptions: {
toolName,
},
},
];
const toolbarButtons: Button[] = [ const toolbarButtons: Button[] = [
{ {
id: 'MeasurementTools', id: 'MeasurementTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'measurementSection', buttonSection: true,
}, },
}, },
{ {
id: 'MoreTools', id: 'MoreTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'moreToolsSection', buttonSection: true,
}, },
}, },
{ {
id: 'WindowLevelGroup', id: 'WindowLevelGroup',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'windowLevelSection', buttonSection: true,
}, },
}, },

View File

@ -112,7 +112,7 @@ function modeFactory({ modeConfiguration }) {
'AdvancedRenderingControls', 'AdvancedRenderingControls',
]); ]);
toolbarService.updateSection(toolbarService.sections.advancedRenderingControlsSection, [ toolbarService.updateSection('AdvancedRenderingControls', [
'windowLevelMenuEmbedded', 'windowLevelMenuEmbedded',
'voiManualControlMenu', 'voiManualControlMenu',
'Colorbar', 'Colorbar',
@ -130,7 +130,7 @@ function modeFactory({ modeConfiguration }) {
'windowLevelMenu', 'windowLevelMenu',
]); ]);
toolbarService.updateSection(toolbarService.sections.measurementSection, [ toolbarService.updateSection('MeasurementTools', [
'Length', 'Length',
'Bidirectional', 'Bidirectional',
'ArrowAnnotate', 'ArrowAnnotate',
@ -142,7 +142,7 @@ function modeFactory({ modeConfiguration }) {
'LivewireContour', 'LivewireContour',
]); ]);
toolbarService.updateSection(toolbarService.sections.moreToolsSection, [ toolbarService.updateSection('MoreTools', [
'Reset', 'Reset',
'rotate-right', 'rotate-right',
'flipHorizontal', 'flipHorizontal',

View File

@ -25,21 +25,21 @@ const toolbarButtons: Button[] = [
id: 'MeasurementTools', id: 'MeasurementTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'measurementSection', buttonSection: true,
}, },
}, },
{ {
id: 'MoreTools', id: 'MoreTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'moreToolsSection', buttonSection: true,
}, },
}, },
{ {
id: 'AdvancedRenderingControls', id: 'AdvancedRenderingControls',
uiType: 'ohif.advancedRenderingControls', uiType: 'ohif.advancedRenderingControls',
props: { props: {
buttonSection: 'advancedRenderingControlsSection', buttonSection: true,
}, },
}, },
// tool defs // tool defs

View File

@ -50,7 +50,7 @@ function modeFactory({ modeConfiguration }) {
toolbarService.register(toolbarButtons); toolbarService.register(toolbarButtons);
toolbarService.updateSection('primary', ['MeasurementTools', 'dragPan', 'TagBrowser']); toolbarService.updateSection('primary', ['MeasurementTools', 'dragPan', 'TagBrowser']);
toolbarService.updateSection('measurementSection', [ toolbarService.updateSection('MeasurementTools', [
'line', 'line',
'point', 'point',
'polygon', 'polygon',

View File

@ -13,7 +13,7 @@ const toolbarButtons: Button[] = [
id: 'MeasurementTools', id: 'MeasurementTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'measurementSection', buttonSection: true,
}, },
}, },
{ {

View File

@ -10,31 +10,35 @@ const cornerstone = {
activeViewportWindowLevel: '@ohif/extension-cornerstone.panelModule.activeViewportWindowLevel', activeViewportWindowLevel: '@ohif/extension-cornerstone.panelModule.activeViewportWindowLevel',
}; };
const defaultButtons = [ function getDefaultButtons({ toolbarService }) {
{ return [
buttonSection: 'primary', {
buttons: ['MeasurementTools', 'Zoom', 'WindowLevel', 'Crosshairs', 'Pan'], buttonSection: toolbarService.sections.primary,
}, buttons: ['MeasurementTools', 'Zoom', 'WindowLevel', 'Crosshairs', 'Pan'],
{ },
buttonSection: 'measurementSection', {
buttons: ['Length', 'Bidirectional', 'ArrowAnnotate', 'EllipticalROI'], buttonSection: 'MeasurementTools',
}, buttons: ['Length', 'Bidirectional', 'ArrowAnnotate', 'EllipticalROI'],
]; },
];
}
const ROIThresholdToolbox = [ function getROIThresholdToolbox({ toolbarService }) {
{ return [
buttonSection: 'dynamic-toolbox', {
buttons: ['SegmentationTools'], buttonSection: toolbarService.sections.dynamicToolbox,
}, buttons: ['SegmentationTools'],
{ },
buttonSection: 'segmentationToolboxToolsSection', {
buttons: ['BrushTools', 'RectangleROIStartEndThreshold'], buttonSection: 'SegmentationTools',
}, buttons: ['BrushTools', 'RectangleROIStartEndThreshold'],
{ },
buttonSection: 'brushToolsSection', {
buttons: ['Brush', 'Eraser', 'Threshold'], buttonSection: 'BrushTools',
}, buttons: ['Brush', 'Eraser', 'Threshold'],
]; },
];
}
const defaultLeftPanel = [[dynamicVolume.leftPanel, cornerstone.activeViewportWindowLevel]]; const defaultLeftPanel = [[dynamicVolume.leftPanel, cornerstone.activeViewportWindowLevel]];
@ -46,6 +50,10 @@ const defaultLayout = {
}; };
function getWorkflowSettings({ servicesManager }) { function getWorkflowSettings({ servicesManager }) {
const { toolbarService } = servicesManager.services;
const defaultButtons = getDefaultButtons({ toolbarService });
const ROIThresholdToolbox = getROIThresholdToolbox({ toolbarService });
return { return {
steps: [ steps: [
{ {

View File

@ -56,7 +56,7 @@ function modeFactory({ modeConfiguration }) {
toolbarService.register(toolbarButtons); toolbarService.register(toolbarButtons);
toolbarService.updateSection('secondary', ['ProgressDropdown']); toolbarService.updateSection(toolbarService.sections.secondary, ['ProgressDropdown']);
toolbarService.updateSection(toolbarService.sections.viewportActionMenu.topLeft, [ toolbarService.updateSection(toolbarService.sections.viewportActionMenu.topLeft, [
'orientationMenu', 'orientationMenu',
@ -72,7 +72,7 @@ function modeFactory({ modeConfiguration }) {
'AdvancedRenderingControls', 'AdvancedRenderingControls',
]); ]);
toolbarService.updateSection(toolbarService.sections.advancedRenderingControlsSection, [ toolbarService.updateSection('AdvancedRenderingControls', [
'windowLevelMenuEmbedded', 'windowLevelMenuEmbedded',
'voiManualControlMenu', 'voiManualControlMenu',
'Colorbar', 'Colorbar',

View File

@ -22,28 +22,28 @@ const toolbarButtons = [
id: 'MeasurementTools', id: 'MeasurementTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'measurementSection', buttonSection: true,
}, },
}, },
{ {
id: 'BrushTools', id: 'BrushTools',
uiType: 'ohif.toolBoxButtonGroup', uiType: 'ohif.toolBoxButtonGroup',
props: { props: {
buttonSection: 'brushToolsSection', buttonSection: true,
}, },
}, },
{ {
id: 'SegmentationTools', id: 'SegmentationTools',
uiType: 'ohif.toolBoxButton', uiType: 'ohif.toolBoxButton',
props: { props: {
buttonSection: 'segmentationToolboxToolsSection', buttonSection: true,
}, },
}, },
{ {
id: 'AdvancedRenderingControls', id: 'AdvancedRenderingControls',
uiType: 'ohif.advancedRenderingControls', uiType: 'ohif.advancedRenderingControls',
props: { props: {
buttonSection: 'advancedRenderingControlsSection', buttonSection: true,
}, },
}, },
{ {

View File

@ -83,7 +83,7 @@ function modeFactory({ modeConfiguration }) {
'AdvancedRenderingControls', 'AdvancedRenderingControls',
]); ]);
toolbarService.updateSection(toolbarService.sections.advancedRenderingControlsSection, [ toolbarService.updateSection('AdvancedRenderingControls', [
'windowLevelMenuEmbedded', 'windowLevelMenuEmbedded',
'voiManualControlMenu', 'voiManualControlMenu',
'Colorbar', 'Colorbar',
@ -101,7 +101,7 @@ function modeFactory({ modeConfiguration }) {
'windowLevelMenu', 'windowLevelMenu',
]); ]);
toolbarService.updateSection('moreToolsSection', [ toolbarService.updateSection('MoreTools', [
'Reset', 'Reset',
'rotate-right', 'rotate-right',
'flipHorizontal', 'flipHorizontal',
@ -114,22 +114,22 @@ function modeFactory({ modeConfiguration }) {
'TagBrowser', 'TagBrowser',
]); ]);
toolbarService.updateSection('segmentationToolbox', [ toolbarService.updateSection(toolbarService.sections.segmentationToolbox, [
'SegmentationUtilities', 'SegmentationUtilities',
'SegmentationTools', 'SegmentationTools',
]); ]);
toolbarService.updateSection('segmentationToolboxUtilitySection', [ toolbarService.updateSection('SegmentationUtilities', [
'LabelmapSlicePropagation', 'LabelmapSlicePropagation',
'InterpolateLabelmap', 'InterpolateLabelmap',
'SegmentBidirectional', 'SegmentBidirectional',
]); ]);
toolbarService.updateSection('segmentationToolboxToolsSection', [ toolbarService.updateSection('SegmentationTools', [
'BrushTools', 'BrushTools',
'MarkerLabelmap', 'MarkerLabelmap',
'RegionSegmentPlus', 'RegionSegmentPlus',
'Shapes', 'Shapes',
]); ]);
toolbarService.updateSection('brushToolsSection', ['Brush', 'Eraser', 'Threshold']); toolbarService.updateSection('BrushTools', ['Brush', 'Eraser', 'Threshold']);
}, },
onModeExit: ({ servicesManager }: withAppTypes) => { onModeExit: ({ servicesManager }: withAppTypes) => {
const { const {

View File

@ -22,7 +22,7 @@ const toolbarButtons: Button[] = [
id: 'AdvancedRenderingControls', id: 'AdvancedRenderingControls',
uiType: 'ohif.advancedRenderingControls', uiType: 'ohif.advancedRenderingControls',
props: { props: {
buttonSection: 'advancedRenderingControlsSection', buttonSection: true,
}, },
}, },
{ {
@ -160,14 +160,14 @@ const toolbarButtons: Button[] = [
id: 'MoreTools', id: 'MoreTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'moreToolsSection', buttonSection: true,
}, },
}, },
{ {
id: 'BrushTools', id: 'BrushTools',
uiType: 'ohif.toolBoxButtonGroup', uiType: 'ohif.toolBoxButtonGroup',
props: { props: {
buttonSection: 'brushToolsSection', buttonSection: true,
}, },
}, },
// Section containers for the nested toolbox // Section containers for the nested toolbox
@ -175,14 +175,14 @@ const toolbarButtons: Button[] = [
id: 'SegmentationUtilities', id: 'SegmentationUtilities',
uiType: 'ohif.toolBoxButton', uiType: 'ohif.toolBoxButton',
props: { props: {
buttonSection: 'segmentationToolboxUtilitySection', buttonSection: true,
}, },
}, },
{ {
id: 'SegmentationTools', id: 'SegmentationTools',
uiType: 'ohif.toolBoxButton', uiType: 'ohif.toolBoxButton',
props: { props: {
buttonSection: 'segmentationToolboxToolsSection', buttonSection: true,
}, },
}, },
// tool defs // tool defs

View File

@ -106,7 +106,7 @@ function modeFactory({ modeConfiguration }) {
'AdvancedRenderingControls', 'AdvancedRenderingControls',
]); ]);
toolbarService.updateSection(toolbarService.sections.advancedRenderingControlsSection, [ toolbarService.updateSection('AdvancedRenderingControls', [
'windowLevelMenuEmbedded', 'windowLevelMenuEmbedded',
'voiManualControlMenu', 'voiManualControlMenu',
'Colorbar', 'Colorbar',
@ -124,7 +124,7 @@ function modeFactory({ modeConfiguration }) {
'windowLevelMenu', 'windowLevelMenu',
]); ]);
toolbarService.updateSection('measurementSection', [ toolbarService.updateSection('MeasurementTools', [
'Length', 'Length',
'Bidirectional', 'Bidirectional',
'ArrowAnnotate', 'ArrowAnnotate',

View File

@ -12,28 +12,28 @@ const toolbarButtons = [
id: 'MeasurementTools', id: 'MeasurementTools',
uiType: 'ohif.toolButtonList', uiType: 'ohif.toolButtonList',
props: { props: {
buttonSection: 'measurementSection', buttonSection: true,
}, },
}, },
{ {
id: 'SegmentationTools', id: 'SegmentationTools',
uiType: 'ohif.toolBoxButton', uiType: 'ohif.toolBoxButton',
props: { props: {
buttonSection: 'segmentationToolboxToolsSection', buttonSection: true,
}, },
}, },
{ {
id: 'BrushTools', id: 'BrushTools',
uiType: 'ohif.toolBoxButtonGroup', uiType: 'ohif.toolBoxButtonGroup',
props: { props: {
buttonSection: 'brushToolsSection', buttonSection: true,
}, },
}, },
{ {
id: 'AdvancedRenderingControls', id: 'AdvancedRenderingControls',
uiType: 'ohif.advancedRenderingControls', uiType: 'ohif.advancedRenderingControls',
props: { props: {
buttonSection: 'advancedRenderingControlsSection', buttonSection: true,
}, },
}, },
{ {

View File

@ -56,7 +56,7 @@ describe('CS3D Image Consistency and Quality', () => {
'2.16.124.113543.6004.101.103.20021117.061159.1.004' '2.16.124.113543.6004.101.103.20021117.061159.1.004'
); );
cy.wait(2000); cy.wait(3000);
testPixel(1018, 1028, 255); testPixel(1018, 1028, 255);
// Horizontal and vertical delta from this should not be contaminated // Horizontal and vertical delta from this should not be contaminated
// by values from center // by values from center

View File

@ -50,7 +50,7 @@ function modeFactory({ modeConfiguration }) {
toolbarService.register([...toolbarButtons, ...moreTools]); toolbarService.register([...toolbarButtons, ...moreTools]);
toolbarService.updateSection('primary', [ toolbarService.updateSection('primary', [
'measurementSection', 'MeasurementTools',
'Zoom', 'Zoom',
'Pan', 'Pan',
'TrackballRotate', 'TrackballRotate',
@ -58,10 +58,10 @@ function modeFactory({ modeConfiguration }) {
'Capture', 'Capture',
'Layout', 'Layout',
'Crosshairs', 'Crosshairs',
'moreToolsSection', 'MoreTools',
]); ]);
toolbarService.updateSection('measurementSection', [ toolbarService.updateSection('MeasurementTools', [
'Length', 'Length',
'Bidirectional', 'Bidirectional',
'ArrowAnnotate', 'ArrowAnnotate',
@ -73,7 +73,7 @@ function modeFactory({ modeConfiguration }) {
'LivewireContour', 'LivewireContour',
]); ]);
toolbarService.updateSection('moreToolsSection', [ toolbarService.updateSection('MoreTools', [
'Reset', 'Reset',
'rotate-right', 'rotate-right',
'flipHorizontal', 'flipHorizontal',

View File

@ -37,20 +37,10 @@ export const TOOLBAR_SECTIONS = {
rightMiddle: 'viewportActionMenu.rightMiddle', rightMiddle: 'viewportActionMenu.rightMiddle',
}, },
/** // mode specific
* Measurement tools section segmentationToolbox: 'segmentationToolbox',
*/ dynamicToolbox: 'dynamic-toolbox',
measurementSection: 'measurementSection', roiThresholdToolbox: 'ROIThresholdToolbox',
/**
* More tools section
*/
moreToolsSection: 'moreToolsSection',
/**
* Advanced rendering controls section
*/
advancedRenderingControlsSection: 'advancedRenderingControlsSection',
}; };
export enum ButtonLocation { export enum ButtonLocation {
@ -199,6 +189,11 @@ export default class ToolbarService extends PubSubService {
button.props = {} as ButtonProps; button.props = {} as ButtonProps;
} }
// if button section is true as boolean, we assign the id of the button to the buttonSection
if (button.props.buttonSection === true) {
button.props.buttonSection = button.id;
}
this.state.buttons[button.id] = button; this.state.buttons[button.id] = button;
} }
}); });
@ -410,6 +405,19 @@ export default class ToolbarService extends PubSubService {
return this.state.buttons[id]; return this.state.buttons[id];
} }
/**
* @deprecated Use register() instead. This method will be removed in a future version.
* Adds buttons to the toolbar.
* @param buttons - The buttons to be added.
* @param replace - Flag indicating if any existing button with the same id as one being added should be replaced
*/
public addButtons(buttons: Button[], replace: boolean = false): void {
console.warn(
'ToolbarService.addButtons() is deprecated. Use ToolbarService.register() instead.'
);
this.register(buttons, replace);
}
/** /**
* Retrieves the buttons from the toolbar service. * Retrieves the buttons from the toolbar service.
* @returns An array of buttons. * @returns An array of buttons.
@ -470,6 +478,19 @@ export default class ToolbarService extends PubSubService {
this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, { ...this.state }); this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, { ...this.state });
} }
/**
* @deprecated Use updateSection() instead. This method will be removed in a future version.
* Creates a button section with the specified key and buttons.
* @param {string} key - The key of the button section.
* @param {Array} buttons - The buttons to be added to the section.
*/
createButtonSection(key, buttons) {
console.warn(
'ToolbarService.createButtonSection() is deprecated. Use ToolbarService.updateSection() instead.'
);
this.updateSection(key, buttons);
}
/** /**
* Retrieves the button section with the specified sectionId. * Retrieves the button section with the specified sectionId.
* *

View File

@ -13,8 +13,6 @@ export type ToolbarSections = {
bottomLeft: string; bottomLeft: string;
bottomRight: string; bottomRight: string;
}; };
measurementSection: string;
moreToolsSection: string;
}; };
export type EvaluatePublic = export type EvaluatePublic =
@ -59,7 +57,7 @@ export type ButtonProps = {
evaluate?: EvaluatePublic; evaluate?: EvaluatePublic;
listeners?: Record<string, RunCommand>; listeners?: Record<string, RunCommand>;
options?: ButtonOptions[]; options?: ButtonOptions[];
buttonSection?: string; buttonSection?: string | boolean;
}; };
export type Button = { export type Button = {

View File

@ -27,7 +27,7 @@ export const EVENTS = {
sections: [ sections: [
{ {
key: 'primary', key: 'primary',
buttons: [ 'measurementSection', 'Zoom', ... ], buttons: [ 'MeasurementTools', 'Zoom', ... ],
}, },
], ],
}, },

View File

@ -31,6 +31,7 @@ summary: Migration guide for OHIF 3.11's toolbar service changes, including the
**Migration Steps:** **Migration Steps:**
1. **Update `ToolbarService` Method Calls:** 1. **Update `ToolbarService` Method Calls:**
* Although the previous method also works but gives warning in the console when used.
* Replace all instances of `toolbarService.addButtons(...)` with `toolbarService.register(...)`. * Replace all instances of `toolbarService.addButtons(...)` with `toolbarService.register(...)`.
* Replace all instances of `toolbarService.createButtonSection(...)` with `toolbarService.updateSection(...)`. * Replace all instances of `toolbarService.createButtonSection(...)` with `toolbarService.updateSection(...)`.
@ -96,36 +97,60 @@ summary: Migration guide for OHIF 3.11's toolbar service changes, including the
``` ```
3. **Adapt Toolbar Button and Component Configurations:** 3. **Adapt Toolbar Button and Component Configurations:**
* For `ohif.toolButtonList` or `ohif.toolBoxButtonGroup` (and their wrappers), the `groupId` prop is no longer the primary way to define the set of buttons. Instead, ensure the `buttonSection` prop correctly points to the section name containing the desired buttons. The `id` prop on these wrapper components should be unique for the component instance.
```diff The configuration of toolbar buttons, especially how they relate to sections
// Before
- {
- id: 'MeasurementTools',
- uiType: 'ohif.toolButtonList',
- props: {
- buttonSection: 'measurementSection',
- groupId: 'MeasurementTools', // groupId often matched buttonSection
- },
- },
// After * **Button Section Association via `props.buttonSection`:**
+ {
+ id: 'MeasurementTools', // This is the ID of the ToolButtonList/ToolBox component itself The toolbar service now offers two ways to define this association:
+ uiType: 'ohif.toolButtonList',
+ props: { * **A. Simple Approach: `buttonSection: true` (Implicitly Uses Button's Own ID)**
+ // This section contains the actual tool buttons (e.g., Length, Bidirectional)
+ buttonSection: 'measurementSection', If a button definition includes `props: { buttonSection: true }`, the `ToolbarService` automatically sets the effective `buttonSection` ID to be the same as the button's own `id`.
+ },
+ }, ```javascript
``` // Example: A ToolButtonList component's definition in toolbarButtons.ts
* Update wrappers like `ToolBoxButtonGroupWrapper` and `ToolButtonListWrapper`: // {
* The `groupId` prop is replaced by `id` (which is the ID of the wrapper button itself). // id: 'MeasurementTools', // ID of this ToolButtonList component
* The `onInteraction` callback in these wrappers now provides `id` (the wrapper's ID) instead of `groupId`. // uiType: 'ohif.toolButtonList',
* If you have custom `evaluate` functions, you can now use `evaluateProps: { hideWhenDisabled: true }` in your button definition to automatically hide the button if it evaluates to disabled. // props: {
// buttonSection: true // This ToolButtonList will render the section named 'MeasurementTools'
// }
// }
```
later you can use it like
5. **Adopt `IconPresentationProvider` (Optional but Recommended):** ```javascript
toolbarService.updateSection('MeasurementTools', ['Length', 'Bidirectional', ...]);
```
* **B. Flexible Approach: `buttonSection: 'customSectionName'` (Explicit Section ID)**
You can explicitly provide a string for `props.buttonSection` if the button should be associated with a section ID that is different from its own `id`, or if you prefer explicit naming.
```javascript
// Example: A ToolButtonList component's definition
// {
// id: 'MySpecialToolList', // ID of this ToolButtonList component
// uiType: 'ohif.toolButtonList',
// props: {
// buttonSection: 'toolsForAdvancedUsers', // This list renders 'toolsForAdvancedUsers' section
// }
// }
```
* **`evaluate` Function Enhancement:**
* Button `evaluate` functions can now leverage `evaluateProps: { hideWhenDisabled: true }` in your button definition to automatically hide a button when it's disabled.
* **Wrapper Component `onInteraction` (e.g., `ToolButtonListWrapper`):**
* Update wrappers like `ToolBoxButtonGroupWrapper` and `ToolButtonListWrapper`:
* The `groupId` prop is replaced by `id` (which is the ID of the wrapper button component itself).
* The `onInteraction` callback in these wrappers now provides `id` (the wrapper's ID) instead of `groupId`.
4. **Adopt `IconPresentationProvider` (Optional but Recommended):**
* For consistent icon styling across your application's toolbars, wrap a high-level component (like your main `Header` or layout component) with `<IconPresentationProvider size="yourDefaultSize">`. * For consistent icon styling across your application's toolbars, wrap a high-level component (like your main `Header` or layout component) with `<IconPresentationProvider size="yourDefaultSize">`.
* Custom tool button components can then use the `useIconPresentation` hook to get appropriate class names for icons or a pre-styled `IconContainer`. * Custom tool button components can then use the `useIconPresentation` hook to get appropriate class names for icons or a pre-styled `IconContainer`.
@ -149,5 +174,5 @@ summary: Migration guide for OHIF 3.11's toolbar service changes, including the
+ } + }
``` ```
6. **Remove Legacy Component Usage:** 5. **Remove Legacy Component Usage:**
* Replace any usage of `ToolbarSplitButtonWithServicesLegacy` and `ToolbarButtonGroupWithServicesLegacy` with the newer patterns, typically by configuring individual buttons and using `ToolButtonList` or `ButtonGroup` from `@ohif/ui-next` directly, driven by `useToolbar`. * Replace any usage of `ToolbarSplitButtonWithServicesLegacy` and `ToolbarButtonGroupWithServicesLegacy` with the newer patterns, typically by configuring individual buttons and using `ToolButtonList` or `ButtonGroup` from `@ohif/ui-next` directly, driven by `useToolbar`.