Skip to content

Commit

Permalink
feat(toolbar): new Toolbar to enable reactive state synchronization (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sedghi authored Mar 27, 2024
1 parent 79d5c36 commit 566b25a
Show file tree
Hide file tree
Showing 155 changed files with 6,237 additions and 6,503 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ version: 2.1
##
orbs:
codecov: codecov/[email protected]
cypress: cypress-io/cypress@3.2.1
cypress: cypress-io/cypress@3.3.1

executors:
cypress-custom:
Expand Down
22 changes: 0 additions & 22 deletions .github/workflows/codespell.yml

This file was deleted.

67 changes: 67 additions & 0 deletions extensions/cornerstone-dicom-seg/src/commandsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { cache, metaData } from '@cornerstonejs/core';
import {
segmentation as cornerstoneToolsSegmentation,
Enums as cornerstoneToolsEnums,
utilities,
} from '@cornerstonejs/tools';
import { adaptersRT, helpers, adaptersSEG } from '@cornerstonejs/adapters';
import { classes, DicomMetadataStore } from '@ohif/core';
Expand All @@ -18,6 +19,7 @@ import {
getUpdatedViewportsForSegmentation,
getTargetViewport,
} from './utils/hydrationUtils';
const { segmentation: segmentationUtils } = utilities;

const { datasetToBlob } = dcmjs.data;

Expand Down Expand Up @@ -45,6 +47,7 @@ const commandsModule = ({
uiDialogService,
displaySetService,
viewportGridService,
toolGroupService,
} = (servicesManager as ServicesManager).services;

const actions = {
Expand Down Expand Up @@ -397,6 +400,60 @@ const commandsModule = ({
console.warn(e);
}
},
setBrushSize: ({ value, toolNames }) => {
const brushSize = Number(value);

toolGroupService.getToolGroupIds()?.forEach(toolGroupId => {
if (toolNames?.length === 0) {
segmentationUtils.setBrushSizeForToolGroup(toolGroupId, brushSize);
} else {
toolNames?.forEach(toolName => {
segmentationUtils.setBrushSizeForToolGroup(toolGroupId, brushSize, toolName);
});
}
});
},
setThresholdRange: ({
value,
toolNames = ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
}) => {
toolGroupService.getToolGroupIds()?.forEach(toolGroupId => {
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
toolNames?.forEach(toolName => {
toolGroup.setToolConfiguration(toolName, {
strategySpecificConfiguration: {
THRESHOLD: {
threshold: value,
},
},
});
});
});
},
toggleThresholdRangeAndDynamic() {
const toolGroupIds = toolGroupService.getToolGroupIds();

if (!toolGroupIds) {
return;
}

toolGroupIds.forEach(toolGroupId => {
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
const brushInstances = segmentationUtils.getBrushToolInstances(toolGroup.id);

brushInstances.forEach(({ configuration }) => {
const { activeStrategy, strategySpecificConfiguration } = configuration;

if (activeStrategy.startsWith('THRESHOLD')) {
const thresholdConfig = strategySpecificConfiguration.THRESHOLD;

if (thresholdConfig) {
thresholdConfig.isDynamic = !thresholdConfig.isDynamic;
}
}
});
});
},
};

const definitions = {
Expand Down Expand Up @@ -424,11 +481,21 @@ const commandsModule = ({
downloadRTSS: {
commandFn: actions.downloadRTSS,
},
setBrushSize: {
commandFn: actions.setBrushSize,
},
setThresholdRange: {
commandFn: actions.setThresholdRange,
},
toggleThresholdRangeAndDynamic: {
commandFn: actions.toggleThresholdRangeAndDynamic,
},
};

return {
actions,
definitions,
defaultContext: 'SEGMENTATION',
};
};

Expand Down
15 changes: 11 additions & 4 deletions extensions/cornerstone-dicom-seg/src/getPanelModule.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import React from 'react';

import { useAppConfig } from '@state';
import { Toolbox } from '@ohif/ui';
import PanelSegmentation from './panels/PanelSegmentation';
import SegmentationToolbox from './panels/SegmentationToolbox';

const getPanelModule = ({ commandsManager, servicesManager, extensionManager, configuration }) => {
const getPanelModule = ({
commandsManager,
servicesManager,
extensionManager,
configuration,
title,
}) => {
const { customizationService } = servicesManager.services;

const wrappedPanelSegmentation = configuration => {
Expand All @@ -26,13 +32,14 @@ const getPanelModule = ({ commandsManager, servicesManager, extensionManager, co
};

const wrappedPanelSegmentationWithTools = configuration => {
const [appConfig] = useAppConfig();
return (
<>
<SegmentationToolbox
<Toolbox
commandsManager={commandsManager}
servicesManager={servicesManager}
extensionManager={extensionManager}
buttonSectionId="segmentationToolbox"
title="Segmentation Tools"
configuration={{
...configuration,
}}
Expand Down
65 changes: 65 additions & 0 deletions extensions/cornerstone-dicom-seg/src/getToolbarModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
export function getToolbarModule({ commandsManager, servicesManager }) {
const { segmentationService, toolGroupService } = servicesManager.services;
return [
{
name: 'evaluate.cornerstone.segmentation',
evaluate: ({ viewportId, button, toolNames }) => {
// Todo: we need to pass in the button section Id since we are kind of
// forcing the button to have black background since initially
// it is designed for the toolbox not the toolbar on top
// we should then branch the buttonSectionId to have different styles
const segmentations = segmentationService.getSegmentations();
if (!segmentations?.length) {
return {
disabled: true,
className: '!text-common-bright !bg-black opacity-50',
};
}

const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);

if (!toolGroup) {
return;
}

const toolName = getToolNameForButton(button);

if (!toolGroup || !toolGroup.hasTool(toolName)) {
return {
disabled: true,
className: '!text-common-bright ohif-disabled',
};
}

const isPrimaryActive = toolNames
? toolNames.includes(toolGroup.getActivePrimaryMouseButtonTool())
: toolGroup.getActivePrimaryMouseButtonTool() === toolName;

return {
disabled: false,
className: isPrimaryActive
? '!text-black !bg-primary-light hover:bg-primary-light hover-text-black hover:cursor-pointer'
: '!text-common-bright !bg-black hover:bg-primary-light hover:cursor-pointer hover:text-black',
// Todo: isActive right now is used for nested buttons where the primary
// button needs to be fully rounded (vs partial rounded) when active
// otherwise it does not have any other use
isActive: isPrimaryActive,
};
},
},
];
}

function getToolNameForButton(button) {
const { props } = button;

const commands = props?.commands || button.commands;

if (commands && commands.length) {
const command = commands[0];
const { commandOptions } = command;
const { toolName } = commandOptions || { toolName: props?.id ?? button.id };
return toolName;
}
return null;
}
6 changes: 3 additions & 3 deletions extensions/cornerstone-dicom-seg/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import getSopClassHandlerModule from './getSopClassHandlerModule';
import getHangingProtocolModule from './getHangingProtocolModule';
import getPanelModule from './getPanelModule';
import getCommandsModule from './commandsModule';
import { getToolbarModule } from './getToolbarModule';
import preRegistration from './init';

const Component = React.lazy(() => {
Expand All @@ -29,7 +30,6 @@ const extension = {
*/
id,
preRegistration,

/**
* PanelModule should provide a list of panels that will be available in OHIF
* for Modes to consume and render. Each panel is defined by a {name,
Expand All @@ -38,8 +38,8 @@ const extension = {
*/
getPanelModule,
getCommandsModule,

getViewportModule({ servicesManager, extensionManager }) {
getToolbarModule,
getViewportModule({ servicesManager, extensionManager, commandsManager }) {
const ExtendedOHIFCornerstoneSEGViewport = props => {
return (
<OHIFCornerstoneSEGViewport
Expand Down
2 changes: 1 addition & 1 deletion extensions/cornerstone-dicom-seg/src/init.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { addTool, BrushTool } from '@cornerstonejs/tools';

export default function init({ configuration = {} }): void {
export default function init({ servicesManager }): void {
addTool(BrushTool);
}
Loading

0 comments on commit 566b25a

Please sign in to comment.