feat: Add inherit from basic/longitudinal modes (#5435)

Co-authored-by: Ibrahim <ibrahim.mdev@gmail.com>
This commit is contained in:
Bill WallaceandIbrahim authored and GitHub committed 2025-10-01 14:31:26 -04:00
1 parent 71d21ee184
commit 9ad0d7fc8c
28 files changed
+1153 -743

No files matched your search

@@ -1,7 +1,6 @@
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const pkg = require('./../package.json');
const webpackCommon = require('./../../../.webpack/webpack.base.js');
+47 -288
View File
@@ -1,315 +1,74 @@
import i18n from 'i18next';
import { id } from './id';
import initToolGroups from './initToolGroups';
import toolbarButtons from './toolbarButtons';
import { initToolGroups, toolbarButtons, cornerstone,
ohif,
dicomsr,
dicomvideo,
basicLayout,
basicRoute,
extensionDependencies as basicDependencies,
mode as basicMode,
modeInstance as basicModeInstance,
} from '@ohif/mode-basic';
// Allow this mode by excluding non-imaging modalities such as SR, SEG
// Also, SM is not a simple imaging modalities, so exclude it.
const NON_IMAGE_MODALITIES = ['ECG', 'SEG', 'RTSTRUCT', 'RTPLAN', 'PR'];
const ohif = {
layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout',
sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack',
thumbnailList: '@ohif/extension-default.panelModule.seriesList',
wsiSopClassHandler:
'@ohif/extension-cornerstone.sopClassHandlerModule.DicomMicroscopySopClassHandler',
};
const cornerstone = {
measurements: '@ohif/extension-cornerstone.panelModule.panelMeasurement',
segmentation: '@ohif/extension-cornerstone.panelModule.panelSegmentation',
};
const tracked = {
export const tracked = {
measurements: '@ohif/extension-measurement-tracking.panelModule.trackedMeasurements',
thumbnailList: '@ohif/extension-measurement-tracking.panelModule.seriesList',
viewport: '@ohif/extension-measurement-tracking.viewportModule.cornerstone-tracked',
};
const dicomsr = {
sopClassHandler: '@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr',
sopClassHandler3D: '@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr-3d',
viewport: '@ohif/extension-cornerstone-dicom-sr.viewportModule.dicom-sr',
};
const dicomvideo = {
sopClassHandler: '@ohif/extension-dicom-video.sopClassHandlerModule.dicom-video',
viewport: '@ohif/extension-dicom-video.viewportModule.dicom-video',
};
const dicompdf = {
sopClassHandler: '@ohif/extension-dicom-pdf.sopClassHandlerModule.dicom-pdf',
viewport: '@ohif/extension-dicom-pdf.viewportModule.dicom-pdf',
};
const dicomSeg = {
sopClassHandler: '@ohif/extension-cornerstone-dicom-seg.sopClassHandlerModule.dicom-seg',
viewport: '@ohif/extension-cornerstone-dicom-seg.viewportModule.dicom-seg',
};
const dicomPmap = {
sopClassHandler: '@ohif/extension-cornerstone-dicom-pmap.sopClassHandlerModule.dicom-pmap',
viewport: '@ohif/extension-cornerstone-dicom-pmap.viewportModule.dicom-pmap',
};
const dicomRT = {
viewport: '@ohif/extension-cornerstone-dicom-rt.viewportModule.dicom-rt',
sopClassHandler: '@ohif/extension-cornerstone-dicom-rt.sopClassHandlerModule.dicom-rt',
};
const extensionDependencies = {
export const extensionDependencies = {
// Can derive the versions at least process.env.from npm_package_version
'@ohif/extension-default': '^3.0.0',
'@ohif/extension-cornerstone': '^3.0.0',
...basicDependencies,
'@ohif/extension-measurement-tracking': '^3.0.0',
'@ohif/extension-cornerstone-dicom-sr': '^3.0.0',
'@ohif/extension-cornerstone-dicom-seg': '^3.0.0',
'@ohif/extension-cornerstone-dicom-pmap': '^3.0.0',
'@ohif/extension-cornerstone-dicom-rt': '^3.0.0',
'@ohif/extension-dicom-pdf': '^3.0.1',
'@ohif/extension-dicom-video': '^3.0.1',
};
function modeFactory({ modeConfiguration }) {
let _activatePanelTriggersSubscriptions = [];
return {
export const longitudinalInstance = {
...basicLayout,
id: ohif.layout,
props: {
...basicLayout.props,
leftPanels: [tracked.thumbnailList],
rightPanels: [cornerstone.segmentation, tracked.measurements],
viewports: [
{
namespace: tracked.viewport,
// Re-use the display sets from basic
displaySetsToDisplay: basicLayout.props.viewports[0].displaySetsToDisplay,
},
...basicLayout.props.viewports,
],
}
};
export const longitudinalRoute =
{
...basicRoute,
path: 'longitudinal',
/*init: ({ servicesManager, extensionManager }) => {
//defaultViewerRouteInit
},*/
layoutInstance: longitudinalInstance,
};
export const modeInstance = {
...basicModeInstance,
// TODO: We're using this as a route segment
// We should not be.
id,
routeName: 'viewer',
displayName: i18n.t('Modes:Basic Viewer'),
/**
* Lifecycle hooks
*/
onModeEnter: function ({ servicesManager, extensionManager, commandsManager }: withAppTypes) {
const { measurementService, toolbarService, toolGroupService, customizationService } =
servicesManager.services;
measurementService.clearMeasurements();
// Init Default and SR ToolGroups
initToolGroups(extensionManager, toolGroupService, commandsManager);
toolbarService.register(toolbarButtons);
toolbarService.updateSection(toolbarService.sections.primary, [
'MeasurementTools',
'Zoom',
'Pan',
'TrackballRotate',
'WindowLevel',
'Capture',
'Layout',
'Crosshairs',
'MoreTools',
]);
toolbarService.updateSection(toolbarService.sections.viewportActionMenu.topLeft, [
'orientationMenu',
'dataOverlayMenu',
]);
toolbarService.updateSection(toolbarService.sections.viewportActionMenu.bottomMiddle, [
'AdvancedRenderingControls',
]);
toolbarService.updateSection('AdvancedRenderingControls', [
'windowLevelMenuEmbedded',
'voiManualControlMenu',
'Colorbar',
'opacityMenu',
'thresholdMenu',
]);
toolbarService.updateSection(toolbarService.sections.viewportActionMenu.topRight, [
'modalityLoadBadge',
'trackingStatus',
'navigationComponent',
]);
toolbarService.updateSection(toolbarService.sections.viewportActionMenu.bottomLeft, [
'windowLevelMenu',
]);
toolbarService.updateSection('MeasurementTools', [
'Length',
'Bidirectional',
'ArrowAnnotate',
'EllipticalROI',
'RectangleROI',
'CircleROI',
'PlanarFreehandROI',
'SplineROI',
'LivewireContour',
]);
toolbarService.updateSection('MoreTools', [
'Reset',
'rotate-right',
'flipHorizontal',
'ImageSliceSync',
'ReferenceLines',
'ImageOverlayViewer',
'StackScroll',
'invert',
'Probe',
'Cine',
'Angle',
'CobbAngle',
'Magnify',
'CalibrationLine',
'TagBrowser',
'AdvancedMagnify',
'UltrasoundDirectionalTool',
'WindowLevelRegion',
'SegmentLabelTool',
]);
customizationService.setCustomizations({
'panelSegmentation.disableEditing': {
$set: true,
},
});
// // 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 = [
// ...panelService.addActivatePanelTriggers(
// cornerstone.segmentation,
// [
// {
// sourcePubSubService: segmentationService,
// sourceEvents: [segmentationService.EVENTS.SEGMENTATION_ADDED],
// },
// ],
// true
// ),
// ...panelService.addActivatePanelTriggers(
// tracked.measurements,
// [
// {
// sourcePubSubService: measurementService,
// sourceEvents: [
// measurementService.EVENTS.MEASUREMENT_ADDED,
// measurementService.EVENTS.RAW_MEASUREMENT_ADDED,
// ],
// },
// ],
// true
// ),
// true,
// ];
},
onModeExit: ({ servicesManager }: withAppTypes) => {
const {
toolGroupService,
syncGroupService,
segmentationService,
cornerstoneViewportService,
uiDialogService,
uiModalService,
} = servicesManager.services;
_activatePanelTriggersSubscriptions.forEach(sub => sub.unsubscribe());
_activatePanelTriggersSubscriptions = [];
uiDialogService.hideAll();
uiModalService.hide();
toolGroupService.destroy();
syncGroupService.destroy();
segmentationService.destroy();
cornerstoneViewportService.destroy();
},
validationTags: {
study: [],
series: [],
},
isValidMode: function ({ modalities }) {
const modalities_list = modalities.split('\\');
// Exclude non-image modalities
return {
valid: !!modalities_list.filter(modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1)
.length,
description:
'The mode does not support studies that ONLY include the following modalities: SM, ECG, SEG, RTSTRUCT',
};
},
routes: [
{
path: 'longitudinal',
/*init: ({ servicesManager, extensionManager }) => {
//defaultViewerRouteInit
},*/
layoutTemplate: () => {
return {
id: ohif.layout,
props: {
leftPanels: [tracked.thumbnailList],
leftPanelResizable: true,
rightPanels: [cornerstone.segmentation, tracked.measurements],
rightPanelClosed: true,
rightPanelResizable: true,
viewports: [
{
namespace: tracked.viewport,
displaySetsToDisplay: [
ohif.sopClassHandler,
dicomvideo.sopClassHandler,
ohif.wsiSopClassHandler,
],
},
{
namespace: dicomsr.viewport,
displaySetsToDisplay: [dicomsr.sopClassHandler, dicomsr.sopClassHandler3D],
},
{
namespace: dicompdf.viewport,
displaySetsToDisplay: [dicompdf.sopClassHandler],
},
{
namespace: dicomSeg.viewport,
displaySetsToDisplay: [dicomSeg.sopClassHandler],
},
{
namespace: dicomPmap.viewport,
displaySetsToDisplay: [dicomPmap.sopClassHandler],
},
{
namespace: dicomRT.viewport,
displaySetsToDisplay: [dicomRT.sopClassHandler],
},
],
},
};
},
},
longitudinalRoute
],
extensions: extensionDependencies,
// Default protocol gets self-registered by default in the init
hangingProtocol: 'default',
// Order is important in sop class handlers when two handlers both use
// the same sop class under different situations. In that case, the more
// general handler needs to come last. For this case, the dicomvideo must
// come first to remove video transfer syntax before ohif uses images
sopClassHandlers: [
dicomvideo.sopClassHandler,
dicomSeg.sopClassHandler,
dicomPmap.sopClassHandler,
ohif.sopClassHandler,
ohif.wsiSopClassHandler,
dicompdf.sopClassHandler,
dicomsr.sopClassHandler3D,
dicomsr.sopClassHandler,
dicomRT.sopClassHandler,
],
...modeConfiguration,
};
}
const mode = {
...basicMode,
id,
modeFactory,
modeInstance,
extensionDependencies,
};
-315
View File
@@ -1,315 +0,0 @@
import { toolNames as SRToolNames } from '@ohif/extension-cornerstone-dicom-sr';
const colours = {
'viewport-0': 'rgb(200, 0, 0)',
'viewport-1': 'rgb(200, 200, 0)',
'viewport-2': 'rgb(0, 200, 0)',
};
const colorsByOrientation = {
axial: 'rgb(200, 0, 0)',
sagittal: 'rgb(200, 200, 0)',
coronal: 'rgb(0, 200, 0)',
};
function initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, toolGroupId) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames, Enums } = utilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }, { numTouchPoints: 2 }],
},
{
toolName: toolNames.StackScroll,
bindings: [{ mouseButton: Enums.MouseBindings.Wheel }, { numTouchPoints: 3 }],
},
],
passive: [
{ toolName: toolNames.Length },
{
toolName: toolNames.ArrowAnnotate,
configuration: {
getTextCallback: (callback, eventDetails) => {
commandsManager.runCommand('arrowTextCallback', {
callback,
eventDetails,
});
},
changeTextCallback: (data, eventDetails, callback) => {
commandsManager.runCommand('arrowTextCallback', {
callback,
data,
eventDetails,
});
},
},
},
{
toolName: toolNames.SegmentBidirectional,
},
{ toolName: toolNames.Bidirectional },
{ toolName: toolNames.DragProbe },
{ toolName: toolNames.Probe },
{ toolName: toolNames.EllipticalROI },
{ toolName: toolNames.CircleROI },
{ toolName: toolNames.RectangleROI },
{ toolName: toolNames.StackScroll },
{ toolName: toolNames.Angle },
{ toolName: toolNames.CobbAngle },
{ toolName: toolNames.Magnify },
{ toolName: toolNames.CalibrationLine },
{
toolName: toolNames.PlanarFreehandContourSegmentation,
configuration: {
displayOnePointAsCrosshairs: true,
},
},
{ toolName: toolNames.UltrasoundDirectional },
{ toolName: toolNames.PlanarFreehandROI },
{ toolName: toolNames.SplineROI },
{ toolName: toolNames.LivewireContour },
{ toolName: toolNames.WindowLevelRegion },
],
enabled: [
{ toolName: toolNames.ImageOverlayViewer },
{ toolName: toolNames.ReferenceLines },
],
disabled: [
{
toolName: toolNames.AdvancedMagnify,
},
],
};
const updatedTools = commandsManager.run('initializeSegmentLabelTool', { tools });
toolGroupService.createToolGroupAndAddTools(toolGroupId, updatedTools);
}
function initSRToolGroup(extensionManager, toolGroupService) {
const SRUtilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone-dicom-sr.utilityModule.tools'
);
if (!SRUtilityModule) {
return;
}
const CS3DUtilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames: SRToolNames } = SRUtilityModule.exports;
const { toolNames, Enums } = CS3DUtilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [
{
mouseButton: Enums.MouseBindings.Primary,
},
],
},
{
toolName: toolNames.Pan,
bindings: [
{
mouseButton: Enums.MouseBindings.Auxiliary,
},
],
},
{
toolName: toolNames.Zoom,
bindings: [
{
mouseButton: Enums.MouseBindings.Secondary,
},
{ numTouchPoints: 2 },
],
},
{
toolName: toolNames.StackScroll,
bindings: [{ mouseButton: Enums.MouseBindings.Wheel }, { numTouchPoints: 3 }],
},
],
passive: [
{ toolName: SRToolNames.SRLength },
{ toolName: SRToolNames.SRArrowAnnotate },
{ toolName: SRToolNames.SRBidirectional },
{ toolName: SRToolNames.SREllipticalROI },
{ toolName: SRToolNames.SRCircleROI },
{ toolName: SRToolNames.SRPlanarFreehandROI },
{ toolName: SRToolNames.SRRectangleROI },
{ toolName: toolNames.WindowLevelRegion },
],
enabled: [
{
toolName: SRToolNames.DICOMSRDisplay,
},
],
// disabled
};
const toolGroupId = 'SRToolGroup';
toolGroupService.createToolGroupAndAddTools(toolGroupId, tools);
}
function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const serviceManager = extensionManager._servicesManager;
const { cornerstoneViewportService } = serviceManager.services;
const { toolNames, Enums } = utilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }, { numTouchPoints: 2 }],
},
{
toolName: toolNames.StackScroll,
bindings: [{ mouseButton: Enums.MouseBindings.Wheel }, { numTouchPoints: 3 }],
},
],
passive: [
{ toolName: toolNames.Length },
{
toolName: toolNames.ArrowAnnotate,
configuration: {
getTextCallback: (callback, eventDetails) => {
commandsManager.runCommand('arrowTextCallback', {
callback,
eventDetails,
});
},
changeTextCallback: (data, eventDetails, callback) => {
commandsManager.runCommand('arrowTextCallback', {
callback,
data,
eventDetails,
});
},
},
},
{ toolName: toolNames.Bidirectional },
{ toolName: toolNames.DragProbe },
{ toolName: toolNames.Probe },
{ toolName: toolNames.EllipticalROI },
{ toolName: toolNames.CircleROI },
{ toolName: toolNames.RectangleROI },
{ toolName: toolNames.StackScroll },
{ toolName: toolNames.Angle },
{ toolName: toolNames.CobbAngle },
{ toolName: toolNames.PlanarFreehandROI },
{ toolName: toolNames.SplineROI },
{ toolName: toolNames.LivewireContour },
{ toolName: toolNames.WindowLevelRegion },
{
toolName: toolNames.PlanarFreehandContourSegmentation,
configuration: {
displayOnePointAsCrosshairs: true,
},
},
],
disabled: [
{
toolName: toolNames.Crosshairs,
configuration: {
viewportIndicators: true,
viewportIndicatorsConfig: {
circleRadius: 5,
xOffset: 0.95,
yOffset: 0.05,
},
disableOnPassive: true,
autoPan: {
enabled: false,
panSize: 10,
},
getReferenceLineColor: viewportId => {
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
const viewportOptions = viewportInfo?.viewportOptions;
if (viewportOptions) {
return (
colours[viewportOptions.id] ||
colorsByOrientation[viewportOptions.orientation] ||
'#0c0'
);
} else {
console.warn('missing viewport?', viewportId);
return '#0c0';
}
},
},
},
{
toolName: toolNames.AdvancedMagnify,
},
{ toolName: toolNames.ReferenceLines },
],
};
toolGroupService.createToolGroupAndAddTools('mpr', tools);
}
function initVolume3DToolGroup(extensionManager, toolGroupService) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames, Enums } = utilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.TrackballRotateTool,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }, { numTouchPoints: 2 }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }, { numTouchPoints: 3 }],
},
],
};
toolGroupService.createToolGroupAndAddTools('volume3d', tools);
}
function initToolGroups(extensionManager, toolGroupService, commandsManager) {
initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, 'default');
initSRToolGroup(extensionManager, toolGroupService);
initMPRToolGroup(extensionManager, toolGroupService, commandsManager);
initVolume3DToolGroup(extensionManager, toolGroupService);
}
export default initToolGroups;
-716
View File
@@ -1,716 +0,0 @@
import type { Button } from '@ohif/core/types';
import { EVENTS } from '@cornerstonejs/core';
import { ViewportGridService } from '@ohif/core';
import i18n from 'i18next';
const callbacks = (toolName: string) => [
{
commandName: 'setViewportForToolConfiguration',
commandOptions: {
toolName,
},
},
];
export const setToolActiveToolbar = {
commandName: 'setToolActiveToolbar',
commandOptions: {
toolGroupIds: ['default', 'mpr', 'SRToolGroup', 'volume3d'],
},
};
const toolbarButtons: Button[] = [
// sections
{
id: 'MeasurementTools',
uiType: 'ohif.toolButtonList',
props: {
buttonSection: true,
},
},
{
id: 'MoreTools',
uiType: 'ohif.toolButtonList',
props: {
buttonSection: true,
},
},
{
id: 'AdvancedRenderingControls',
uiType: 'ohif.advancedRenderingControls',
props: {
buttonSection: true,
},
},
// tool defs
{
id: 'modalityLoadBadge',
uiType: 'ohif.modalityLoadBadge',
props: {
icon: 'Status',
label: i18n.t('Buttons:Status'),
tooltip: i18n.t('Buttons:Status'),
evaluate: {
name: 'evaluate.modalityLoadBadge',
hideWhenDisabled: true,
},
},
},
{
id: 'navigationComponent',
uiType: 'ohif.navigationComponent',
props: {
icon: 'Navigation',
label: i18n.t('Buttons:Navigation'),
tooltip: i18n.t('Buttons:Navigate between segments/measurements and manage their visibility'),
evaluate: {
name: 'evaluate.navigationComponent',
hideWhenDisabled: true,
},
},
},
{
id: 'trackingStatus',
uiType: 'ohif.trackingStatus',
props: {
icon: 'TrackingStatus',
label: i18n.t('Buttons:Tracking Status'),
tooltip: i18n.t('Buttons:View and manage tracking status of measurements and annotations'),
evaluate: {
name: 'evaluate.trackingStatus',
hideWhenDisabled: true,
},
},
},
{
id: 'dataOverlayMenu',
uiType: 'ohif.dataOverlayMenu',
props: {
icon: 'ViewportViews',
label: i18n.t('Buttons:Data Overlay'),
tooltip: i18n.t(
'Buttons:Configure data overlay options and manage foreground/background display sets'
),
evaluate: 'evaluate.dataOverlayMenu',
},
},
{
id: 'orientationMenu',
uiType: 'ohif.orientationMenu',
props: {
icon: 'OrientationSwitch',
label: i18n.t('Buttons:Orientation'),
tooltip: i18n.t(
'Buttons:Change viewport orientation between axial, sagittal, coronal and reformat planes'
),
evaluate: {
name: 'evaluate.orientationMenu',
// hideWhenDisabled: true,
},
},
},
{
id: 'windowLevelMenuEmbedded',
uiType: 'ohif.windowLevelMenuEmbedded',
props: {
icon: 'WindowLevel',
label: i18n.t('Buttons:Window Level'),
tooltip: i18n.t('Buttons:Adjust window/level presets and customize image contrast settings'),
evaluate: {
name: 'evaluate.windowLevelMenuEmbedded',
hideWhenDisabled: true,
},
},
},
{
id: 'windowLevelMenu',
uiType: 'ohif.windowLevelMenu',
props: {
icon: 'WindowLevel',
label: i18n.t('Buttons:Window Level'),
tooltip: i18n.t('Buttons:Adjust window/level presets and customize image contrast settings'),
evaluate: {
name: 'evaluate.windowLevelMenu',
},
},
},
{
id: 'voiManualControlMenu',
uiType: 'ohif.voiManualControlMenu',
props: {
icon: 'WindowLevelAdvanced',
label: i18n.t('Buttons:Advanced Window Level'),
tooltip: i18n.t('Buttons:Advanced window/level settings with manual controls and presets'),
evaluate: 'evaluate.voiManualControlMenu',
},
},
{
id: 'thresholdMenu',
uiType: 'ohif.thresholdMenu',
props: {
icon: 'Threshold',
label: i18n.t('Buttons:Threshold'),
tooltip: i18n.t('Buttons:Image threshold settings'),
evaluate: {
name: 'evaluate.thresholdMenu',
hideWhenDisabled: true,
},
},
},
{
id: 'opacityMenu',
uiType: 'ohif.opacityMenu',
props: {
icon: 'Opacity',
label: i18n.t('Buttons:Opacity'),
tooltip: i18n.t('Buttons:Image opacity settings'),
evaluate: {
name: 'evaluate.opacityMenu',
hideWhenDisabled: true,
},
},
},
{
id: 'Colorbar',
uiType: 'ohif.colorbar',
props: {
type: 'tool',
label: i18n.t('Buttons:Colorbar'),
},
},
{
id: 'Reset',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-reset',
label: i18n.t('Buttons:Reset View'),
tooltip: i18n.t('Buttons:Reset View'),
commands: 'resetViewport',
evaluate: 'evaluate.action',
},
},
{
id: 'rotate-right',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-rotate-right',
label: i18n.t('Buttons:Rotate Right'),
tooltip: i18n.t('Buttons:Rotate +90'),
commands: 'rotateViewportCW',
evaluate: [
'evaluate.action',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'flipHorizontal',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-flip-horizontal',
label: i18n.t('Buttons:Flip Horizontal'),
tooltip: i18n.t('Buttons:Flip Horizontally'),
commands: 'flipViewportHorizontal',
evaluate: [
'evaluate.viewportProperties.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video', 'volume3d'],
},
],
},
},
{
id: 'ImageSliceSync',
uiType: 'ohif.toolButton',
props: {
icon: 'link',
label: i18n.t('Buttons:Image Slice Sync'),
tooltip: i18n.t('Buttons: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: i18n.t('Buttons:Reference Lines'),
tooltip: i18n.t('Buttons:Show Reference Lines'),
commands: 'toggleEnabledDisabledToolbar',
listeners: {
[ViewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED]: callbacks('ReferenceLines'),
[ViewportGridService.EVENTS.VIEWPORTS_READY]: callbacks('ReferenceLines'),
},
evaluate: [
'evaluate.cornerstoneTool.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'ImageOverlayViewer',
uiType: 'ohif.toolButton',
props: {
icon: 'toggle-dicom-overlay',
label: i18n.t('Buttons:Image Overlay'),
tooltip: i18n.t('Buttons: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: i18n.t('Buttons:Stack Scroll'),
tooltip: i18n.t('Buttons:Stack Scroll'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'invert',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-invert',
label: i18n.t('Buttons:Invert'),
tooltip: i18n.t('Buttons:Invert Colors'),
commands: 'invertViewport',
evaluate: [
'evaluate.viewportProperties.toggle',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'Probe',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-probe',
label: i18n.t('Buttons:Probe'),
tooltip: i18n.t('Buttons:Probe'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Cine',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-cine',
label: i18n.t('Buttons:Cine'),
tooltip: i18n.t('Buttons:Cine'),
commands: 'toggleCine',
evaluate: [
'evaluate.cine',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['volume3d'],
},
],
},
},
{
id: 'Angle',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-angle',
label: i18n.t('Buttons:Angle'),
tooltip: i18n.t('Buttons:Angle'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'CobbAngle',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-cobb-angle',
label: i18n.t('Buttons:Cobb Angle'),
tooltip: i18n.t('Buttons:Cobb Angle'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Magnify',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-magnify',
label: i18n.t('Buttons:Zoom-in'),
tooltip: i18n.t('Buttons:Zoom-in'),
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'CalibrationLine',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-calibration',
label: i18n.t('Buttons:Calibration'),
tooltip: i18n.t('Buttons:Calibration Line'),
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'TagBrowser',
uiType: 'ohif.toolButton',
props: {
icon: 'dicom-tag-browser',
label: i18n.t('Buttons:Dicom Tag Browser'),
tooltip: i18n.t('Buttons:Dicom Tag Browser'),
commands: 'openDICOMTagViewer',
},
},
{
id: 'AdvancedMagnify',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-loupe',
label: i18n.t('Buttons:Magnify Probe'),
tooltip: i18n.t('Buttons: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: i18n.t('Buttons:Ultrasound Directional'),
tooltip: i18n.t('Buttons: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: i18n.t('Buttons:Window Level Region'),
tooltip: i18n.t('Buttons:Window Level Region'),
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video'],
},
],
},
},
{
id: 'Length',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-length',
label: i18n.t('Buttons:Length'),
tooltip: i18n.t('Buttons:Length Tool'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Bidirectional',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-bidirectional',
label: i18n.t('Buttons:Bidirectional'),
tooltip: i18n.t('Buttons:Bidirectional Tool'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'ArrowAnnotate',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-annotate',
label: i18n.t('Buttons:Annotation'),
tooltip: i18n.t('Buttons:Arrow Annotate'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'EllipticalROI',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-ellipse',
label: i18n.t('Buttons:Ellipse'),
tooltip: i18n.t('Buttons:Ellipse ROI'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'RectangleROI',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-rectangle',
label: i18n.t('Buttons:Rectangle'),
tooltip: i18n.t('Buttons:Rectangle ROI'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'CircleROI',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-circle',
label: i18n.t('Buttons:Circle'),
tooltip: i18n.t('Buttons:Circle Tool'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'PlanarFreehandROI',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-freehand-roi',
label: i18n.t('Buttons:Freehand ROI'),
tooltip: i18n.t('Buttons:Freehand ROI'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'SplineROI',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-spline-roi',
label: i18n.t('Buttons:Spline ROI'),
tooltip: i18n.t('Buttons:Spline ROI'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'LivewireContour',
uiType: 'ohif.toolButton',
props: {
icon: 'icon-tool-livewire',
label: i18n.t('Buttons:Livewire tool'),
tooltip: i18n.t('Buttons:Livewire tool'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
// Window Level
{
id: 'WindowLevel',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-window-level',
label: i18n.t('Buttons:Window Level'),
commands: setToolActiveToolbar,
evaluate: [
'evaluate.cornerstoneTool',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['wholeSlide'],
},
],
},
},
{
id: 'Pan',
uiType: 'ohif.toolButton',
props: {
type: 'tool',
icon: 'tool-move',
label: i18n.t('Buttons:Pan'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Zoom',
uiType: 'ohif.toolButton',
props: {
type: 'tool',
icon: 'tool-zoom',
label: i18n.t('Buttons:Zoom'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'TrackballRotate',
uiType: 'ohif.toolButton',
props: {
type: 'tool',
icon: 'tool-3d-rotate',
label: i18n.t('Buttons:3D Rotate'),
commands: setToolActiveToolbar,
evaluate: {
name: 'evaluate.cornerstoneTool',
disabledText: 'Select a 3D viewport to enable this tool',
},
},
},
{
id: 'Capture',
uiType: 'ohif.toolButton',
props: {
icon: 'tool-capture',
label: i18n.t('Buttons:Capture'),
commands: 'showDownloadViewportModal',
evaluate: [
'evaluate.action',
{
name: 'evaluate.viewport.supported',
unsupportedViewportTypes: ['video', 'wholeSlide'],
},
],
},
},
{
id: 'Layout',
uiType: 'ohif.layoutSelector',
props: {
rows: 3,
columns: 4,
evaluate: 'evaluate.action',
},
},
{
id: 'Crosshairs',
uiType: 'ohif.toolButton',
props: {
type: 'tool',
icon: 'tool-crosshair',
label: i18n.t('Buttons:Crosshairs'),
commands: {
commandName: 'setToolActiveToolbar',
commandOptions: {
toolGroupIds: ['mpr'],
},
},
evaluate: {
name: 'evaluate.cornerstoneTool',
disabledText: 'Select an MPR viewport to enable this tool',
},
},
},
// 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: i18n.t('Buttons:Segment Label Display'),
tooltip: i18n.t(
'Buttons: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',
// props: {
// type: 'tool',
// icon: 'prev-arrow',
// label: 'Undo',
// commands: {
// commandName: 'undo',
// },
// evaluate: 'evaluate.action',
// },
// },
// {
// id: 'Redo',
// uiType: 'ohif.toolButton',
// props: {
// type: 'tool',
// icon: 'next-arrow',
// label: 'Redo',
// commands: {
// commandName: 'redo',
// },
// evaluate: 'evaluate.action',
// },
// },
];
export default toolbarButtons;