feature(segmentation): Add contour tools and utilities in a side panel (#5517)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Dan Rukas <dan.rukas@gmail.com>
This commit is contained in:
73 files changed
+2770
-435
No files matched your search
@@ -3,3 +3,5 @@ export * from './types';
|
||||
export * from './useViewportRef';
|
||||
export * from './useViewportSize';
|
||||
export * from './useViewportMousePosition';
|
||||
export * from './useActiveToolOptions';
|
||||
export * from './useRunCommand';
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useSystem } from '../contextProviders/SystemProvider';
|
||||
import { ButtonProps } from '../services/ToolBarService/types';
|
||||
import { useToolbar } from './useToolbar';
|
||||
|
||||
type UseActiveToolOptionsProps = {
|
||||
buttonSectionId: string;
|
||||
};
|
||||
|
||||
export function useActiveToolOptions({ buttonSectionId }: UseActiveToolOptionsProps) {
|
||||
const { servicesManager } = useSystem();
|
||||
const { toolbarService } = servicesManager.services;
|
||||
|
||||
const { toolbarButtons } = useToolbar({
|
||||
buttonSection: buttonSectionId,
|
||||
});
|
||||
|
||||
// Helper to check a list of buttons for an active tool.
|
||||
const findActiveOptions = (buttons: any[]): unknown => {
|
||||
for (const tool of buttons) {
|
||||
if (tool.componentProps.isActive) {
|
||||
return {
|
||||
activeToolOptions: tool.componentProps.options,
|
||||
activeToolButtonId: tool.componentProps.id,
|
||||
};
|
||||
}
|
||||
if (tool.componentProps.buttonSection) {
|
||||
const nestedButtons = toolbarService.getButtonPropsInButtonSection(
|
||||
tool.componentProps.buttonSection
|
||||
) as ButtonProps[];
|
||||
const activeNested = nestedButtons.find(nested => nested.isActive);
|
||||
if (activeNested) {
|
||||
return {
|
||||
activeToolOptions: activeNested.options,
|
||||
activeToolButtonId: activeNested.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Look for active tool options across all sections.
|
||||
const activeOptions = toolbarButtons.reduce((activeOptions, button) => {
|
||||
if (activeOptions) {
|
||||
return activeOptions;
|
||||
}
|
||||
const sectionId = button.componentProps.buttonSection;
|
||||
const buttons = sectionId ? toolbarService.getButtonSection(sectionId) : [button];
|
||||
return findActiveOptions(buttons);
|
||||
}, null);
|
||||
|
||||
return activeOptions ?? {};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useSystem } from '../contextProviders/SystemProvider';
|
||||
|
||||
/**
|
||||
* Hook that provides a runCommand function for executing commands
|
||||
* @returns A memoized runCommand function
|
||||
*/
|
||||
export function useRunCommand() {
|
||||
const { commandsManager } = useSystem();
|
||||
|
||||
const runCommand = useCallback(
|
||||
(commandName: string, commandOptions: Record<string, unknown> = {}) => {
|
||||
return commandsManager.runCommand(commandName, commandOptions);
|
||||
},
|
||||
[commandsManager]
|
||||
);
|
||||
|
||||
return runCommand;
|
||||
}
|
||||
@@ -38,7 +38,10 @@ export const TOOLBAR_SECTIONS = {
|
||||
},
|
||||
|
||||
// mode specific
|
||||
segmentationToolbox: 'segmentationToolbox',
|
||||
labelMapSegmentationToolbox: 'labelMapSegmentationToolbox',
|
||||
contourSegmentationToolbox: 'contourSegmentationToolbox',
|
||||
labelMapSegmentationUtilities: 'labelMapSegmentationUtilities',
|
||||
contourSegmentationUtilities: 'contourSegmentationUtilities',
|
||||
dynamicToolbox: 'dynamic-toolbox',
|
||||
roiThresholdToolbox: 'ROIThresholdToolbox',
|
||||
};
|
||||
@@ -314,12 +317,22 @@ export default class ToolbarService extends PubSubService {
|
||||
: undefined;
|
||||
// Check hideWhenDisabled at both evaluateProps level and props level
|
||||
const hideWhenDisabled = evaluateProps?.hideWhenDisabled || props.hideWhenDisabled;
|
||||
|
||||
// Visibility is first determined by the evaluate function. If it is not returned from there,
|
||||
// then we check hideWhenDisabled and disabled to determine visibility.
|
||||
const visible =
|
||||
evaluated?.visible === undefined
|
||||
? hideWhenDisabled && evaluated?.disabled
|
||||
? false
|
||||
: true
|
||||
: evaluated?.visible;
|
||||
|
||||
const updatedProps = {
|
||||
...props,
|
||||
...evaluated,
|
||||
disabled: evaluated?.disabled || false,
|
||||
visible: hideWhenDisabled && evaluated?.disabled ? false : true,
|
||||
className: evaluated?.className || '',
|
||||
visible,
|
||||
className: evaluated?.className || props?.className || '',
|
||||
isActive: evaluated?.isActive, // isActive will be undefined for buttons without this prop
|
||||
};
|
||||
evaluationResults.set(button.id, updatedProps);
|
||||
@@ -570,7 +583,8 @@ export default class ToolbarService extends PubSubService {
|
||||
btn.component = buttonType.defaultComponent;
|
||||
}
|
||||
|
||||
if (!buttonType) {
|
||||
if (!buttonType && !btn.component) {
|
||||
console.warn(`Neither button type nor a component found for button: ${id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export type EvaluateObject = {
|
||||
|
||||
export type ButtonOptions = {
|
||||
id: string;
|
||||
type: 'range' | 'radio' | 'double-range' | 'custom';
|
||||
type: 'range' | 'radio' | 'double-range' | 'custom' | 'checkbox' | 'select' | 'button';
|
||||
name?: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
@@ -59,6 +59,7 @@ export type ButtonProps = {
|
||||
listeners?: Record<string, RunCommand>;
|
||||
options?: ButtonOptions[];
|
||||
buttonSection?: string | boolean;
|
||||
isActive?: boolean;
|
||||
};
|
||||
|
||||
export type Button = {
|
||||
|
||||
Reference in new issue
Block a user