feat(segmentation): segment statistics, labelmap interpolation and segment bidirectional (#4865)
This commit is contained in:
1 parent
694f3e9611
commit
ec79b5523e
73 files changed
+3603
-1563
No files matched your search
@@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PanelSection } from '../PanelSection';
|
||||
import { Tabs, TabsList, TabsTrigger } from '../Tabs';
|
||||
import { Slider } from '../Slider';
|
||||
import { Icons } from '../Icons';
|
||||
import { Switch } from '../Switch';
|
||||
import { Label } from '../Label';
|
||||
import { Input } from '../Input';
|
||||
import { useSegmentationTableContext } from './SegmentationTableContext';
|
||||
import { useSegmentationTableContext } from './contexts';
|
||||
|
||||
export const SegmentationTableConfig: React.FC<{ children?: React.ReactNode }> = ({ children }) => {
|
||||
const { t } = useTranslation('SegmentationTable.AppearanceSettings');
|
||||
@@ -26,152 +25,134 @@ export const SegmentationTableConfig: React.FC<{ children?: React.ReactNode }> =
|
||||
renderInactiveSegmentations,
|
||||
toggleRenderInactiveSegmentations,
|
||||
data,
|
||||
} = useSegmentationTableContext('styles');
|
||||
} = useSegmentationTableContext('SegmentationTableConfig');
|
||||
|
||||
if (!data?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<PanelSection defaultOpen={false}>
|
||||
<PanelSection.Header>
|
||||
<div className="flex items-center">
|
||||
<Icons.Settings className="mr-2 h-4 w-4" />
|
||||
<span>{t('Appearance Settings')}</span>
|
||||
<div className="bg-muted mb-0.5 space-y-2 rounded-b px-1.5 pt-0.5 pb-3">
|
||||
<div className="my-1 flex items-center justify-between">
|
||||
<span className="text-aqua-pale text-xs">
|
||||
{t('Show')}:{' '}
|
||||
{renderFill && renderOutline
|
||||
? t('Fill & Outline')
|
||||
: renderOutline
|
||||
? t('Outline Only')
|
||||
: t('Fill Only')}
|
||||
</span>
|
||||
<Tabs
|
||||
value={
|
||||
renderFill && renderOutline ? 'fill-and-outline' : renderOutline ? 'outline' : 'fill'
|
||||
}
|
||||
onValueChange={value => {
|
||||
if (value === 'fill-and-outline') {
|
||||
setRenderFill({ type: activeRepresentation.type }, true);
|
||||
setRenderOutline({ type: activeRepresentation.type }, true);
|
||||
} else if (value === 'outline') {
|
||||
setRenderFill({ type: activeRepresentation.type }, false);
|
||||
setRenderOutline({ type: activeRepresentation.type }, true);
|
||||
} else {
|
||||
setRenderFill({ type: activeRepresentation.type }, true);
|
||||
setRenderOutline({ type: activeRepresentation.type }, false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TabsList>
|
||||
<TabsTrigger value="fill-and-outline">
|
||||
<Icons.FillAndOutline className="text-primary-active" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="outline">
|
||||
<Icons.OutlineOnly className="text-primary-active" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="fill">
|
||||
<Icons.FillOnly className="text-primary-active" />
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="my-2 flex items-center">
|
||||
<Label className="text-muted-foreground w-14 flex-none whitespace-nowrap text-xs">
|
||||
Opacity
|
||||
</Label>
|
||||
<Slider
|
||||
className="mx-1 flex-1"
|
||||
value={[fillAlpha]}
|
||||
onValueChange={([value]) => setFillAlpha({ type: activeRepresentation.type }, value)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
/>
|
||||
<Input
|
||||
className="mx-1 w-10 flex-none"
|
||||
value={fillAlpha}
|
||||
onChange={e =>
|
||||
setFillAlpha({ type: activeRepresentation.type }, Number(e.target.value))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</PanelSection.Header>
|
||||
<PanelSection.Content>
|
||||
<div className="bg-muted mb-0.5 space-y-2 rounded-b px-1.5 pt-0.5 pb-3">
|
||||
<div className="my-1 flex items-center justify-between">
|
||||
<span className="text-aqua-pale text-xs">
|
||||
{t('Show')}:{' '}
|
||||
{renderFill && renderOutline
|
||||
? t('Fill & Outline')
|
||||
: renderOutline
|
||||
? t('Outline Only')
|
||||
: t('Fill Only')}
|
||||
</span>
|
||||
<Tabs
|
||||
value={
|
||||
renderFill && renderOutline
|
||||
? 'fill-and-outline'
|
||||
: renderOutline
|
||||
? 'outline'
|
||||
: 'fill'
|
||||
}
|
||||
onValueChange={value => {
|
||||
if (value === 'fill-and-outline') {
|
||||
setRenderFill({ type: activeRepresentation.type }, true);
|
||||
setRenderOutline({ type: activeRepresentation.type }, true);
|
||||
} else if (value === 'outline') {
|
||||
setRenderFill({ type: activeRepresentation.type }, false);
|
||||
setRenderOutline({ type: activeRepresentation.type }, true);
|
||||
} else {
|
||||
setRenderFill({ type: activeRepresentation.type }, true);
|
||||
setRenderOutline({ type: activeRepresentation.type }, false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TabsList>
|
||||
<TabsTrigger value="fill-and-outline">
|
||||
<Icons.FillAndOutline className="text-primary-active" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="outline">
|
||||
<Icons.OutlineOnly className="text-primary-active" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="fill">
|
||||
<Icons.FillOnly className="text-primary-active" />
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="my-2 flex items-center">
|
||||
<Label className="text-muted-foreground w-14 flex-none whitespace-nowrap text-xs">
|
||||
Opacity
|
||||
</Label>
|
||||
<Slider
|
||||
className="mx-1 flex-1"
|
||||
value={[fillAlpha]}
|
||||
onValueChange={([value]) =>
|
||||
setFillAlpha({ type: activeRepresentation.type }, value)
|
||||
}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
/>
|
||||
<Input
|
||||
className="mx-1 w-10 flex-none"
|
||||
value={fillAlpha}
|
||||
onChange={e =>
|
||||
setFillAlpha({ type: activeRepresentation.type }, Number(e.target.value))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="my-2 flex items-center">
|
||||
<Label className="text-muted-foreground w-14 flex-none whitespace-nowrap text-xs">
|
||||
{t('Border')}
|
||||
</Label>
|
||||
<Slider
|
||||
value={[outlineWidth]}
|
||||
onValueChange={([value]) =>
|
||||
setOutlineWidth({ type: activeRepresentation.type }, value)
|
||||
}
|
||||
max={10}
|
||||
min={0}
|
||||
step={0.1}
|
||||
className="mx-1 flex-1"
|
||||
/>
|
||||
<Input
|
||||
value={outlineWidth}
|
||||
onChange={e =>
|
||||
setOutlineWidth({ type: activeRepresentation.type }, Number(e.target.value))
|
||||
}
|
||||
className="mx-1 w-10 flex-none text-center"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-input w-full border"></div>
|
||||
|
||||
<div className="my-2 flex items-center pl-1">
|
||||
<Switch
|
||||
checked={renderInactiveSegmentations}
|
||||
onCheckedChange={toggleRenderInactiveSegmentations}
|
||||
/>
|
||||
<Label className="text-muted-foreground mx-2 text-xs">
|
||||
{t('Display inactive segmentations')}
|
||||
</Label>
|
||||
</div>
|
||||
{renderInactiveSegmentations && (
|
||||
<div className="my-2 flex items-center">
|
||||
<Label className="text-muted-foreground w-14 flex-none whitespace-nowrap text-xs">
|
||||
Opacity
|
||||
</Label>
|
||||
<Slider
|
||||
className="mx-1 flex-1"
|
||||
value={[fillAlphaInactive]}
|
||||
onValueChange={([value]) =>
|
||||
setFillAlphaInactive({ type: activeRepresentation.type }, value)
|
||||
}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
/>
|
||||
<Input
|
||||
className="mx-1 w-10 flex-none"
|
||||
value={fillAlphaInactive}
|
||||
onChange={e =>
|
||||
setFillAlphaInactive({ type: activeRepresentation.type }, Number(e.target.value))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="my-2 flex items-center">
|
||||
<Label className="text-muted-foreground w-14 flex-none whitespace-nowrap text-xs">
|
||||
{t('Border')}
|
||||
</Label>
|
||||
<Slider
|
||||
value={[outlineWidth]}
|
||||
onValueChange={([value]) => setOutlineWidth({ type: activeRepresentation.type }, value)}
|
||||
max={10}
|
||||
min={0}
|
||||
step={0.1}
|
||||
className="mx-1 flex-1"
|
||||
/>
|
||||
<Input
|
||||
value={outlineWidth}
|
||||
onChange={e =>
|
||||
setOutlineWidth({ type: activeRepresentation.type }, Number(e.target.value))
|
||||
}
|
||||
className="mx-1 w-10 flex-none text-center"
|
||||
/>
|
||||
</div>
|
||||
{children}
|
||||
</PanelSection.Content>
|
||||
</PanelSection>
|
||||
</div>
|
||||
|
||||
<div className="border-input w-full border"></div>
|
||||
|
||||
<div className="my-2 flex items-center pl-1">
|
||||
<Switch
|
||||
checked={renderInactiveSegmentations}
|
||||
onCheckedChange={toggleRenderInactiveSegmentations}
|
||||
/>
|
||||
<Label className="text-muted-foreground mx-2 text-xs">
|
||||
{t('Display inactive segmentations')}
|
||||
</Label>
|
||||
</div>
|
||||
{renderInactiveSegmentations && (
|
||||
<div className="my-2 flex items-center">
|
||||
<Label className="text-muted-foreground w-14 flex-none whitespace-nowrap text-xs">
|
||||
Opacity
|
||||
</Label>
|
||||
<Slider
|
||||
className="mx-1 flex-1"
|
||||
value={[fillAlphaInactive]}
|
||||
onValueChange={([value]) =>
|
||||
setFillAlphaInactive({ type: activeRepresentation.type }, value)
|
||||
}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
/>
|
||||
<Input
|
||||
className="mx-1 w-10 flex-none"
|
||||
value={fillAlphaInactive}
|
||||
onChange={e =>
|
||||
setFillAlphaInactive({ type: activeRepresentation.type }, Number(e.target.value))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user