2024-03-27 21:01:32 +01:00
|
|
|
import { Enums } from '@cornerstonejs/tools';
|
2025-01-29 19:36:52 +01:00
|
|
|
import { utils } from '@ohif/ui-next';
|
2025-05-15 18:08:12 +02:00
|
|
|
import { ViewportDataOverlayMenuWrapper } from './components/ViewportDataOverlaySettingMenu/ViewportDataOverlayMenuWrapper';
|
|
|
|
|
import { ViewportOrientationMenuWrapper } from './components/ViewportOrientationMenu/ViewportOrientationMenuWrapper';
|
|
|
|
|
import { WindowLevelActionMenuWrapper } from './components/WindowLevelActionMenu/WindowLevelActionMenuWrapper';
|
|
|
|
|
import { VOIManualControlMenuWrapper } from './components/VOIManualControlMenu';
|
|
|
|
|
import { ThresholdMenuWrapper } from './components/ThresholdMenu/ThresholdMenuWrapper';
|
|
|
|
|
import { OpacityMenuWrapper } from './components/OpacityMenu/OpacityMenuWrapper';
|
|
|
|
|
import ModalityLoadBadge from './components/ModalityLoadBadge/ModalityLoadBadge';
|
|
|
|
|
import NavigationComponent from './components/NavigationComponent/NavigationComponent';
|
|
|
|
|
import TrackingStatus from './components/TrackingStatus/TrackingStatus';
|
|
|
|
|
import ViewportColorbarsContainer from './components/ViewportColorbar';
|
|
|
|
|
import AdvancedRenderingControls from './components/AdvancedRenderingControls';
|
2024-03-27 21:01:32 +01:00
|
|
|
|
2024-11-06 13:15:27 +01:00
|
|
|
const getDisabledState = (disabledText?: string) => ({
|
|
|
|
|
disabled: true,
|
|
|
|
|
disabledText: disabledText ?? 'Not available on the current viewport',
|
|
|
|
|
});
|
|
|
|
|
|
2025-05-15 18:08:12 +02:00
|
|
|
export default function getToolbarModule({ servicesManager, extensionManager }: withAppTypes) {
|
2024-03-27 21:01:32 +01:00
|
|
|
const {
|
|
|
|
|
toolGroupService,
|
2024-04-29 17:58:03 +02:00
|
|
|
toolbarService,
|
2024-03-27 21:01:32 +01:00
|
|
|
syncGroupService,
|
|
|
|
|
cornerstoneViewportService,
|
2025-05-15 18:08:12 +02:00
|
|
|
colorbarService,
|
2024-03-27 21:01:32 +01:00
|
|
|
displaySetService,
|
|
|
|
|
viewportGridService,
|
2025-05-15 18:08:12 +02:00
|
|
|
segmentationService,
|
2024-03-27 21:01:32 +01:00
|
|
|
} = servicesManager.services;
|
|
|
|
|
|
|
|
|
|
return [
|
2025-05-15 18:08:12 +02:00
|
|
|
{
|
|
|
|
|
name: 'ohif.advancedRenderingControls',
|
|
|
|
|
defaultComponent: AdvancedRenderingControls,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.advancedRenderingControls',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const hasColorbar = colorbarService?.hasColorbar(viewportId) || false;
|
|
|
|
|
return {
|
|
|
|
|
disabled: !hasColorbar,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.colorbar',
|
|
|
|
|
defaultComponent: ViewportColorbarsContainer,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.trackingStatus',
|
|
|
|
|
defaultComponent: TrackingStatus,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.trackingStatus',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!displaySetUIDs?.length) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: false,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
// ModalityLoadBadge
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.modalityLoadBadge',
|
|
|
|
|
defaultComponent: ModalityLoadBadge,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.modalityLoadBadge',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
// We can't use useViewportDisplaySets hook here since we're in a non-React context,
|
|
|
|
|
// but we'll follow the same pattern by getting only the display sets for this viewport
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!displaySetUIDs?.length) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the display sets that are specifically in this viewport
|
|
|
|
|
const viewportDisplaySets = displaySetUIDs.map(uid =>
|
|
|
|
|
displaySetService.getDisplaySetByUID(uid)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Only show status for supported types like SR, SEG, RTSTRUCT
|
|
|
|
|
const isSupportedType = viewportDisplaySets.some(
|
|
|
|
|
displaySet =>
|
|
|
|
|
displaySet?.Modality === 'SR' ||
|
|
|
|
|
displaySet?.Modality === 'SEG' ||
|
|
|
|
|
displaySet?.Modality === 'RTSTRUCT'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: !isSupportedType,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
// NavigationComponent
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.navigationComponent',
|
|
|
|
|
defaultComponent: NavigationComponent,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.navigationComponent',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const { trackedMeasurementsService } = servicesManager.services;
|
|
|
|
|
// Same logic as statusComponent - only show for SR, SEG, RTSTRUCT
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!displaySetUIDs?.length) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the display sets that are specifically in this viewport
|
|
|
|
|
const viewportDisplaySets = displaySetUIDs.map(uid =>
|
|
|
|
|
displaySetService.getDisplaySetByUID(uid)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Check if there's a need for navigation:
|
|
|
|
|
// 1. Segmentations are present (for SEG/RTSTRUCT navigation)
|
|
|
|
|
// 2. There are tracked measurements in the viewport (for SR navigation)
|
|
|
|
|
|
|
|
|
|
// Check for SEG/RTSTRUCT navigation
|
|
|
|
|
const hasSegmentation =
|
|
|
|
|
segmentationService.getSegmentationRepresentations(viewportId).length > 0;
|
|
|
|
|
|
|
|
|
|
if (!trackedMeasurementsService) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: !hasSegmentation,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if any of the viewport's series are being tracked
|
|
|
|
|
const hasTrackedInViewport = viewportDisplaySets.some(
|
|
|
|
|
displaySet =>
|
|
|
|
|
displaySet?.SeriesInstanceUID &&
|
|
|
|
|
trackedMeasurementsService.isSeriesTracked(displaySet.SeriesInstanceUID)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const isSRDisplaySet = viewportDisplaySets.some(
|
|
|
|
|
displaySet => displaySet?.Modality === 'SR'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Enable navigation if:
|
|
|
|
|
// - There's a segmentation to navigate (SEG/RTSTRUCT)
|
|
|
|
|
// - OR there are tracked measurements in the viewport (SR/etc.)
|
|
|
|
|
const needsNavigation = hasSegmentation || hasTrackedInViewport || isSRDisplaySet;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: !needsNavigation,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.dataOverlayMenu',
|
|
|
|
|
defaultComponent: ViewportDataOverlayMenuWrapper,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.dataOverlayMenu',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Example: Show data overlay menu only for certain modalities
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
if (!displaySetUIDs?.length) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: false,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.orientationMenu',
|
|
|
|
|
defaultComponent: ViewportOrientationMenuWrapper,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.orientationMenu',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only show orientation menu for 3D capable viewports
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
const displaySets = displaySetUIDs.map(displaySetService.getDisplaySetByUID);
|
|
|
|
|
const isNotReconstructable = displaySets.some(displaySet => !displaySet?.isReconstructable);
|
|
|
|
|
|
|
|
|
|
const disabled = isNotReconstructable;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.windowLevelMenu',
|
|
|
|
|
defaultComponent: WindowLevelActionMenuWrapper,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.voiManualControlMenu',
|
|
|
|
|
defaultComponent: VOIManualControlMenuWrapper,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.windowLevelMenuEmbedded',
|
|
|
|
|
defaultComponent: WindowLevelActionMenuWrapper,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.windowLevelMenuEmbedded',
|
|
|
|
|
evaluate: () => {
|
|
|
|
|
return {
|
|
|
|
|
isEmbedded: true,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.thresholdMenu',
|
|
|
|
|
defaultComponent: ThresholdMenuWrapper,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'ohif.opacityMenu',
|
|
|
|
|
defaultComponent: OpacityMenuWrapper,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.windowLevelMenu',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
const displaySets = displaySetUIDs.map(displaySetService.getDisplaySetByUID);
|
|
|
|
|
|
|
|
|
|
const supportWindowLevel = displaySets.some(displaySet => displaySet?.supportsWindowLevel);
|
|
|
|
|
|
|
|
|
|
const isInAnySection = toolbarService.isInAnySection('windowLevelMenuEmbedded');
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: !supportWindowLevel,
|
|
|
|
|
hasEmbeddedVariantToUse: !!isInAnySection,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.voiManualControlMenu',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
const displaySets = displaySetUIDs.map(displaySetService.getDisplaySetByUID);
|
|
|
|
|
|
|
|
|
|
const supportWindowLevel = displaySets.some(displaySet => displaySet?.supportsWindowLevel);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: !supportWindowLevel,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.thresholdMenu',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (viewport.type !== 'orthographic') {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
if (!displaySetUIDs.length) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: false,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.opacityMenu',
|
|
|
|
|
evaluate: ({ viewportId }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport || viewport.type !== 'orthographic') {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (displaySetUIDs.length <= 1) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displaySets = displaySetUIDs.map(displaySetService.getDisplaySetByUID);
|
|
|
|
|
const hasOverlayable = displaySets.some(displaySet => displaySet?.isOverlayDisplaySet);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: hasOverlayable,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-03-27 21:01:32 +01:00
|
|
|
// functions/helpers to be used by the toolbar buttons to decide if they should
|
|
|
|
|
// enabled or not
|
2024-11-06 13:15:27 +01:00
|
|
|
{
|
|
|
|
|
name: 'evaluate.viewport.supported',
|
|
|
|
|
evaluate: ({ viewportId, unsupportedViewportTypes, disabledText }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (viewport && unsupportedViewportTypes?.includes(viewport.type)) {
|
|
|
|
|
return getDisabledState(disabledText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.modality.supported',
|
|
|
|
|
evaluate: ({ viewportId, unsupportedModalities, supportedModalities, disabledText }) => {
|
|
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!displaySetUIDs?.length) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displaySets = displaySetUIDs.map(displaySetService.getDisplaySetByUID);
|
|
|
|
|
|
|
|
|
|
// Check for unsupported modalities (exclusion)
|
|
|
|
|
if (unsupportedModalities?.length) {
|
|
|
|
|
const hasUnsupportedModality = displaySets.some(displaySet =>
|
|
|
|
|
unsupportedModalities.includes(displaySet?.Modality)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (hasUnsupportedModality) {
|
|
|
|
|
return getDisabledState(disabledText);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for supported modalities (inclusion)
|
|
|
|
|
if (supportedModalities?.length) {
|
|
|
|
|
const hasAnySupportedModality = displaySets.some(displaySet =>
|
|
|
|
|
supportedModalities.includes(displaySet?.Modality)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!hasAnySupportedModality) {
|
|
|
|
|
return getDisabledState(disabledText || 'Tool not available for this modality');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-03-27 21:01:32 +01:00
|
|
|
{
|
|
|
|
|
name: 'evaluate.cornerstoneTool',
|
2024-04-29 17:58:03 +02:00
|
|
|
evaluate: ({ viewportId, button, toolNames, disabledText }) => {
|
2024-03-27 21:01:32 +01:00
|
|
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!toolGroup) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-29 17:58:03 +02:00
|
|
|
const toolName = toolbarService.getToolNameForButton(button);
|
2024-03-27 21:01:32 +01:00
|
|
|
|
2024-04-29 17:58:03 +02:00
|
|
|
if (!toolGroup || (!toolGroup.hasTool(toolName) && !toolNames)) {
|
2024-11-06 13:15:27 +01:00
|
|
|
return getDisabledState(disabledText);
|
2024-03-27 21:01:32 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-29 17:58:03 +02:00
|
|
|
const isPrimaryActive = toolNames
|
|
|
|
|
? toolNames.includes(toolGroup.getActivePrimaryMouseButtonTool())
|
|
|
|
|
: toolGroup.getActivePrimaryMouseButtonTool() === toolName;
|
2024-03-27 21:01:32 +01:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: false,
|
|
|
|
|
isActive: isPrimaryActive,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.action',
|
2025-01-29 19:36:52 +01:00
|
|
|
evaluate: () => {
|
2024-03-27 21:01:32 +01:00
|
|
|
return {
|
2025-01-29 19:36:52 +01:00
|
|
|
disabled: false,
|
2024-03-27 21:01:32 +01:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-04-16 17:04:48 +02:00
|
|
|
{
|
|
|
|
|
name: 'evaluate.cornerstoneTool.toggle.ifStrictlyDisabled',
|
|
|
|
|
evaluate: ({ viewportId, button, disabledText }) =>
|
|
|
|
|
_evaluateToggle({
|
|
|
|
|
viewportId,
|
|
|
|
|
button,
|
2024-04-29 17:58:03 +02:00
|
|
|
toolbarService,
|
2024-04-16 17:04:48 +02:00
|
|
|
disabledText,
|
|
|
|
|
offModes: [Enums.ToolModes.Disabled],
|
|
|
|
|
toolGroupService,
|
|
|
|
|
}),
|
|
|
|
|
},
|
2024-03-27 21:01:32 +01:00
|
|
|
{
|
|
|
|
|
name: 'evaluate.cornerstoneTool.toggle',
|
2024-04-16 17:04:48 +02:00
|
|
|
evaluate: ({ viewportId, button, disabledText }) =>
|
|
|
|
|
_evaluateToggle({
|
|
|
|
|
viewportId,
|
|
|
|
|
button,
|
2024-04-29 17:58:03 +02:00
|
|
|
toolbarService,
|
2024-04-16 17:04:48 +02:00
|
|
|
disabledText,
|
|
|
|
|
offModes: [Enums.ToolModes.Disabled, Enums.ToolModes.Passive],
|
|
|
|
|
toolGroupService,
|
|
|
|
|
}),
|
2024-03-27 21:01:32 +01:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.cornerstone.synchronizer',
|
|
|
|
|
evaluate: ({ viewportId, button }) => {
|
|
|
|
|
let synchronizers = syncGroupService.getSynchronizersForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!synchronizers?.length) {
|
|
|
|
|
return {
|
2025-01-29 19:36:52 +01:00
|
|
|
className: utils.getToggledClassName(false),
|
2024-03-27 21:01:32 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-16 17:04:48 +02:00
|
|
|
const isArray = Array.isArray(button.commands);
|
|
|
|
|
|
|
|
|
|
const synchronizerType = isArray
|
|
|
|
|
? button.commands?.[0].commandOptions.type
|
|
|
|
|
: button.commands?.commandOptions.type;
|
2024-03-27 21:01:32 +01:00
|
|
|
|
|
|
|
|
synchronizers = syncGroupService.getSynchronizersOfType(synchronizerType);
|
|
|
|
|
|
|
|
|
|
if (!synchronizers?.length) {
|
|
|
|
|
return {
|
2025-01-29 19:36:52 +01:00
|
|
|
className: utils.getToggledClassName(false),
|
2024-03-27 21:01:32 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Todo: we need a better way to find the synchronizers based on their
|
|
|
|
|
// type, but for now we just check the first one and see if it is
|
|
|
|
|
// enabled
|
|
|
|
|
const synchronizer = synchronizers[0];
|
|
|
|
|
|
|
|
|
|
const isEnabled = synchronizer?._enabled;
|
|
|
|
|
|
|
|
|
|
return {
|
2025-01-29 19:36:52 +01:00
|
|
|
className: utils.getToggledClassName(isEnabled),
|
2024-03-27 21:01:32 +01:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'evaluate.viewportProperties.toggle',
|
|
|
|
|
evaluate: ({ viewportId, button }) => {
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!viewport || viewport.isDisabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const propId = button.id;
|
|
|
|
|
|
|
|
|
|
const properties = viewport.getProperties();
|
|
|
|
|
const camera = viewport.getCamera();
|
|
|
|
|
|
|
|
|
|
const prop = camera?.[propId] || properties?.[propId];
|
|
|
|
|
|
|
|
|
|
if (!prop) {
|
|
|
|
|
return {
|
|
|
|
|
disabled: false,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isToggled = prop;
|
|
|
|
|
|
|
|
|
|
return {
|
2025-01-29 19:36:52 +01:00
|
|
|
className: utils.getToggledClassName(isToggled),
|
2024-03-27 21:01:32 +01:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2025-03-18 03:34:34 +01:00
|
|
|
name: 'evaluate.displaySetIsReconstructable',
|
2024-04-03 05:33:04 +02:00
|
|
|
evaluate: ({ viewportId, disabledText = 'Selected viewport is not reconstructable' }) => {
|
2025-03-18 03:34:34 +01:00
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
2024-03-27 21:01:32 +01:00
|
|
|
|
2025-03-18 03:34:34 +01:00
|
|
|
if (!viewport) {
|
2024-03-27 21:01:32 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 03:34:34 +01:00
|
|
|
const displaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
|
|
|
|
|
|
2024-03-27 21:01:32 +01:00
|
|
|
const displaySets = displaySetUIDs.map(displaySetService.getDisplaySetByUID);
|
|
|
|
|
|
|
|
|
|
const areReconstructable = displaySets.every(displaySet => {
|
2024-06-19 15:32:00 +02:00
|
|
|
return displaySet?.isReconstructable;
|
2024-03-27 21:01:32 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!areReconstructable) {
|
2024-11-06 13:15:27 +01:00
|
|
|
return getDisabledState(disabledText);
|
2024-03-27 21:01:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
disabled: false,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-29 17:58:03 +02:00
|
|
|
function _evaluateToggle({
|
|
|
|
|
viewportId,
|
|
|
|
|
toolbarService,
|
|
|
|
|
button,
|
|
|
|
|
disabledText,
|
|
|
|
|
offModes,
|
|
|
|
|
toolGroupService,
|
|
|
|
|
}) {
|
2024-04-16 17:04:48 +02:00
|
|
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
|
|
|
|
|
|
|
|
|
if (!toolGroup) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-04-29 17:58:03 +02:00
|
|
|
const toolName = toolbarService.getToolNameForButton(button);
|
2024-04-16 17:04:48 +02:00
|
|
|
|
2025-05-05 22:35:05 +02:00
|
|
|
if (!toolGroup?.hasTool(toolName)) {
|
2024-11-06 13:15:27 +01:00
|
|
|
return getDisabledState(disabledText);
|
2024-04-16 17:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isOff = offModes.includes(toolGroup.getToolOptions(toolName).mode);
|
|
|
|
|
|
|
|
|
|
return {
|
2025-01-29 19:36:52 +01:00
|
|
|
className: utils.getToggledClassName(!isOff),
|
2024-04-16 17:04:48 +02:00
|
|
|
};
|
|
|
|
|
}
|