feat(toolbox): Refactor Toolbar and Toolbox to enable sections (#4825)

This commit is contained in:
Alireza authored and GitHub committed 2025-03-06 22:19:47 -05:00
1 parent 86c12246ac
commit cc5cdfb081
79 files changed
+3527 -2992

No files matched your search

+36 -6
View File
@@ -1,9 +1,7 @@
import { hotkeys } from '@ohif/core';
import i18n from 'i18next';
import { id } from './id';
import initToolGroups from './initToolGroups';
import toolbarButtons from './toolbarButtons';
import moreTools from './moreTools';
// Allow this mode by excluding non-imaging modalities such as SR, SEG
// Also, SM is not a simple imaging modalities, so exclude it.
@@ -84,15 +82,14 @@ function modeFactory({ modeConfiguration }) {
* Lifecycle hooks
*/
onModeEnter: function ({ servicesManager, extensionManager, commandsManager }: withAppTypes) {
const { measurementService, toolbarService, toolGroupService, customizationService } =
servicesManager.services;
const { measurementService, toolbarService, toolGroupService } = servicesManager.services;
measurementService.clearMeasurements();
// Init Default and SR ToolGroups
initToolGroups(extensionManager, toolGroupService, commandsManager);
toolbarService.addButtons([...toolbarButtons, ...moreTools]);
toolbarService.addButtons(toolbarButtons);
toolbarService.createButtonSection('primary', [
'MeasurementTools',
'Zoom',
@@ -105,6 +102,39 @@ function modeFactory({ modeConfiguration }) {
'MoreTools',
]);
toolbarService.createButtonSection('measurementSection', [
'Length',
'Bidirectional',
'ArrowAnnotate',
'EllipticalROI',
'RectangleROI',
'CircleROI',
'PlanarFreehandROI',
'SplineROI',
'LivewireContour',
]);
toolbarService.createButtonSection('moreToolsSection', [
'Reset',
'rotate-right',
'flipHorizontal',
'ImageSliceSync',
'ReferenceLines',
'ImageOverlayViewer',
'StackScroll',
'invert',
'Probe',
'Cine',
'Angle',
'CobbAngle',
'Magnify',
'CalibrationLine',
'TagBrowser',
'AdvancedMagnify',
'UltrasoundDirectionalTool',
'WindowLevelRegion',
]);
// // ActivatePanel event trigger for when a segmentation or measurement is added.
// // Do not force activation so as to respect the state the user may have left the UI in.
// _activatePanelTriggersSubscriptions = [
@@ -250,4 +280,4 @@ const mode = {
};
export default mode;
export { initToolGroups, moreTools, toolbarButtons };
export { initToolGroups, toolbarButtons };
-270
View File
@@ -1,270 +0,0 @@
import type { RunCommand } from '@ohif/core/types';
import { EVENTS } from '@cornerstonejs/core';
import { ToolbarService, ViewportGridService } from '@ohif/core';
import { setToolActiveToolbar } from './toolbarButtons';
const { createButton } = ToolbarService;
const ReferenceLinesListeners: RunCommand = [
{
commandName: 'setSourceViewportForReferenceLinesTool',
context: 'CORNERSTONE',
},
];
const moreTools = [
{
id: 'MoreTools',
uiType: 'ohif.toolButtonList',
props: {
groupId: 'MoreTools',
evaluate: 'evaluate.group.promoteToPrimaryIfCornerstoneToolNotActiveInTheList',
primary: createButton({
id: 'Reset',
icon: 'tool-reset',
tooltip: 'Reset View',
label: 'Reset',
commands: 'resetViewport',
evaluate: 'evaluate.action',
}),
secondary: {
icon: 'chevron-down',
label: '',
tooltip: 'More Tools',
},
items: [
createButton({
id: 'Reset',
icon: 'tool-reset',
label: 'Reset View',
tooltip: 'Reset View',
commands: 'resetViewport',
evaluate: 'evaluate.action',
}),
createButton({
id: 'rotate-right',
icon: 'tool-rotate-right',
label: 'Rotate Right',
tooltip: 'Rotate +90',
commands: 'rotateViewportCW',
evaluate: [
'evaluate.action',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
createButton({
id: 'flipHorizontal',
icon: 'tool-flip-horizontal',
label: 'Flip Horizontal',
tooltip: 'Flip Horizontally',
commands: 'flipViewportHorizontal',
evaluate: [
'evaluate.viewportProperties.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video', 'volume3d'],
},
],
}),
createButton({
id: 'ImageSliceSync',
icon: 'link',
label: 'Image Slice Sync',
tooltip: 'Enable position synchronization on stack viewports',
commands: {
commandName: 'toggleSynchronizer',
commandOptions: {
type: 'imageSlice',
},
},
listeners: {
[EVENTS.VIEWPORT_NEW_IMAGE_SET]: {
commandName: 'toggleImageSliceSync',
commandOptions: { toggledState: true },
},
},
evaluate: [
'evaluate.cornerstone.synchronizer',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video', 'volume3d'],
},
],
}),
createButton({
id: 'ReferenceLines',
icon: 'tool-referenceLines',
label: 'Reference Lines',
tooltip: 'Show Reference Lines',
commands: 'toggleEnabledDisabledToolbar',
listeners: {
[ViewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED]: ReferenceLinesListeners,
[ViewportGridService.EVENTS.VIEWPORTS_READY]: ReferenceLinesListeners,
},
evaluate: [
'evaluate.cornerstoneTool.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
createButton({
id: 'ImageOverlayViewer',
icon: 'toggle-dicom-overlay',
label: 'Image Overlay',
tooltip: 'Toggle Image Overlay',
commands: 'toggleEnabledDisabledToolbar',
evaluate: [
'evaluate.cornerstoneTool.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
createButton({
id: 'StackScroll',
icon: 'tool-stack-scroll',
label: 'Stack Scroll',
tooltip: 'Stack Scroll',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'invert',
icon: 'tool-invert',
label: 'Invert',
tooltip: 'Invert Colors',
commands: 'invertViewport',
evaluate: [
'evaluate.viewportProperties.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
createButton({
id: 'Probe',
icon: 'tool-probe',
label: 'Probe',
tooltip: 'Probe',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'Cine',
icon: 'tool-cine',
label: 'Cine',
tooltip: 'Cine',
commands: 'toggleCine',
evaluate: [
'evaluate.cine',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['volume3d'],
},
],
}),
createButton({
id: 'Angle',
icon: 'tool-angle',
label: 'Angle',
tooltip: 'Angle',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'CobbAngle',
icon: 'icon-tool-cobb-angle',
label: 'Cobb Angle',
tooltip: 'Cobb Angle',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'Magnify',
icon: 'tool-magnify',
label: 'Zoom-in',
tooltip: 'Zoom-in',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
createButton({
id: 'CalibrationLine',
icon: 'tool-calibration',
label: 'Calibration',
tooltip: 'Calibration Line',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
createButton({
id: 'TagBrowser',
icon: 'dicom-tag-browser',
label: 'Dicom Tag Browser',
tooltip: 'Dicom Tag Browser',
commands: 'openDICOMTagViewer',
}),
createButton({
id: 'AdvancedMagnify',
icon: 'icon-tool-loupe',
label: 'Magnify Probe',
tooltip: 'Magnify Probe',
commands: 'toggleActiveDisabledToolbar',
evaluate: [
'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
createButton({
id: 'UltrasoundDirectionalTool',
icon: 'icon-tool-ultrasound-bidirectional',
label: 'Ultrasound Directional',
tooltip: 'Ultrasound Directional',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.modality.supported',
supportedModalities: ['US'],
},
],
}),
createButton({
id: 'WindowLevelRegion',
icon: 'icon-tool-window-region',
label: 'Window Level Region',
tooltip: 'Window Level Region',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
}),
],
},
},
];
export default moreTools;
+406 -95
View File
@@ -1,9 +1,14 @@
// TODO: torn, can either bake this here; or have to create a whole new button type
// Only ways that you can pass in a custom React component for render :l
import { ToolbarService } from '@ohif/core';
import type { Button } from '@ohif/core/types';
const { createButton } = ToolbarService;
import { EVENTS } from '@cornerstonejs/core';
import { ViewportGridService } from '@ohif/core';
const ReferenceLinesListeners = [
{
commandName: 'setSourceViewportForReferenceLinesTool',
context: 'CORNERSTONE',
},
];
export const setToolActiveToolbar = {
commandName: 'setToolActiveToolbar',
@@ -13,107 +18,403 @@ export const setToolActiveToolbar = {
};
const toolbarButtons: Button[] = [
// sections
{
id: 'MeasurementTools',
uiType: 'ohif.toolButtonList',
props: {
buttonSection: 'measurementSection',
groupId: 'MeasurementTools',
// group evaluate to determine which item should move to the top
evaluate: 'evaluate.group.promoteToPrimaryIfCornerstoneToolNotActiveInTheList',
primary: createButton({
id: 'Length',
icon: 'tool-length',
label: 'Length',
tooltip: 'Length Tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
secondary: {
icon: 'chevron-down',
tooltip: 'More Measure Tools',
},
items: [
createButton({
id: 'Length',
icon: 'tool-length',
label: 'Length',
tooltip: 'Length Tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'Bidirectional',
icon: 'tool-bidirectional',
label: 'Bidirectional',
tooltip: 'Bidirectional Tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'ArrowAnnotate',
icon: 'tool-annotate',
label: 'Annotation',
tooltip: 'Arrow Annotate',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'EllipticalROI',
icon: 'tool-ellipse',
label: 'Ellipse',
tooltip: 'Ellipse ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'RectangleROI',
icon: 'tool-rectangle',
label: 'Rectangle',
tooltip: 'Rectangle ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'CircleROI',
icon: 'tool-circle',
label: 'Circle',
tooltip: 'Circle Tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'PlanarFreehandROI',
icon: 'icon-tool-freehand-roi',
label: 'Freehand ROI',
tooltip: 'Freehand ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'SplineROI',
icon: 'icon-tool-spline-roi',
label: 'Spline ROI',
tooltip: 'Spline ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'LivewireContour',
icon: 'icon-tool-livewire',
label: 'Livewire tool',
tooltip: 'Livewire tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
},
},
{
id: 'MoreTools',
uiType: 'ohif.toolButtonList',
props: {
buttonSection: 'moreToolsSection',
groupId: 'MoreTools',
},
},
// tool defs
{
id: 'Reset',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-reset',
label: 'Reset View',
tooltip: 'Reset View',
commands: 'resetViewport',
evaluate: 'evaluate.action',
},
},
{
id: 'rotate-right',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-rotate-right',
label: 'Rotate Right',
tooltip: 'Rotate +90',
commands: 'rotateViewportCW',
evaluate: [
'evaluate.action',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'Zoom',
id: 'flipHorizontal',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-zoom',
label: 'Zoom',
icon: 'tool-flip-horizontal',
label: 'Flip Horizontal',
tooltip: 'Flip Horizontally',
commands: 'flipViewportHorizontal',
evaluate: [
'evaluate.viewportProperties.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video', 'volume3d'],
},
],
},
},
{
id: 'ImageSliceSync',
uiType: 'ohif.toolButton',
props: {
icon: 'link',
label: 'Image Slice Sync',
tooltip: 'Enable position synchronization on stack viewports',
commands: {
commandName: 'toggleSynchronizer',
commandOptions: {
type: 'imageSlice',
},
},
listeners: {
[EVENTS.VIEWPORT_NEW_IMAGE_SET]: {
commandName: 'toggleImageSliceSync',
commandOptions: { toggledState: true },
},
},
evaluate: [
'evaluate.cornerstone.synchronizer',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video', 'volume3d'],
},
],
},
},
{
id: 'ReferenceLines',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-referenceLines',
label: 'Reference Lines',
tooltip: 'Show Reference Lines',
commands: 'toggleEnabledDisabledToolbar',
listeners: {
[ViewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED]: ReferenceLinesListeners,
[ViewportGridService.EVENTS.VIEWPORTS_READY]: ReferenceLinesListeners,
},
evaluate: [
'evaluate.cornerstoneTool.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'ImageOverlayViewer',
uiType: 'ohif.toolButton',
props: {
icon: 'toggle-dicom-overlay',
label: 'Image Overlay',
tooltip: 'Toggle Image Overlay',
commands: 'toggleEnabledDisabledToolbar',
evaluate: [
'evaluate.cornerstoneTool.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'StackScroll',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-stack-scroll',
label: 'Stack Scroll',
tooltip: 'Stack Scroll',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'invert',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-invert',
label: 'Invert',
tooltip: 'Invert Colors',
commands: 'invertViewport',
evaluate: [
'evaluate.viewportProperties.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'Probe',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-probe',
label: 'Probe',
tooltip: 'Probe',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Cine',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-cine',
label: 'Cine',
tooltip: 'Cine',
commands: 'toggleCine',
evaluate: [
'evaluate.cine',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['volume3d'],
},
],
},
},
{
id: 'Angle',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-angle',
label: 'Angle',
tooltip: 'Angle',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'CobbAngle',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-cobb-angle',
label: 'Cobb Angle',
tooltip: 'Cobb Angle',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Magnify',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-magnify',
label: 'Zoom-in',
tooltip: 'Zoom-in',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'CalibrationLine',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-calibration',
label: 'Calibration',
tooltip: 'Calibration Line',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'TagBrowser',
uiType: 'ohif.toolButton',
props: {
icon: 'dicom-tag-browser',
label: 'Dicom Tag Browser',
tooltip: 'Dicom Tag Browser',
commands: 'openDICOMTagViewer',
},
},
{
id: 'AdvancedMagnify',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-loupe',
label: 'Magnify Probe',
tooltip: 'Magnify Probe',
commands: 'toggleActiveDisabledToolbar',
evaluate: [
'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'UltrasoundDirectionalTool',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-ultrasound-bidirectional',
label: 'Ultrasound Directional',
tooltip: 'Ultrasound Directional',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.modality.supported',
supportedModalities: ['US'],
},
],
},
},
{
id: 'WindowLevelRegion',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-window-region',
label: 'Window Level Region',
tooltip: 'Window Level Region',
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'Length',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-length',
label: 'Length',
tooltip: 'Length Tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Bidirectional',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-bidirectional',
label: 'Bidirectional',
tooltip: 'Bidirectional Tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'ArrowAnnotate',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-annotate',
label: 'Annotation',
tooltip: 'Arrow Annotate',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'EllipticalROI',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-ellipse',
label: 'Ellipse',
tooltip: 'Ellipse ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'RectangleROI',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-rectangle',
label: 'Rectangle',
tooltip: 'Rectangle ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'CircleROI',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-circle',
label: 'Circle',
tooltip: 'Circle Tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'PlanarFreehandROI',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-freehand-roi',
label: 'Freehand ROI',
tooltip: 'Freehand ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'SplineROI',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-spline-roi',
label: 'Spline ROI',
tooltip: 'Spline ROI',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'LivewireContour',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-livewire',
label: 'Livewire tool',
tooltip: 'Livewire tool',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
@@ -135,7 +436,6 @@ const toolbarButtons: Button[] = [
],
},
},
// Pan...
{
id: 'Pan',
uiType: 'ohif.toolButton',
@@ -147,6 +447,17 @@ const toolbarButtons: Button[] = [
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Zoom',
uiType: 'ohif.toolButton',
props: {
type: 'tool',
icon: 'tool-zoom',
label: 'Zoom',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'TrackballRotate',
uiType: 'ohif.toolButton',