ohif-viewer/platform/ui-next/src/components/SegmentationTable/SegmentationSegments.tsx

146 lines
5.0 KiB
TypeScript

import React from 'react';
import { ScrollArea, DataRow } from '../../components';
import { HoverCard, HoverCardTrigger, HoverCardContent } from '../../components/HoverCard';
import { useSegmentationTableContext, useSegmentationExpanded } from './contexts';
import { SegmentStatistics } from './SegmentStatistics';
import { useDynamicMaxHeight } from '../../hooks/useDynamicMaxHeight';
export const SegmentationSegments = ({ children = null }: { children?: React.ReactNode }) => {
const {
activeSegmentationId,
disableEditing,
onSegmentColorClick,
onToggleSegmentVisibility,
onToggleSegmentLock,
onSegmentClick,
onSegmentEdit,
onSegmentDelete,
data,
} = useSegmentationTableContext('SegmentationSegments');
// Try to get segmentation data from expanded context first, then fall back to table context
let segmentation;
let representation;
try {
// Try to use the SegmentationExpanded context if available
const segmentationInfo = useSegmentationExpanded('SegmentationSegments');
segmentation = segmentationInfo.segmentation;
representation = segmentationInfo.representation;
} catch (e) {
// Not within SegmentationExpanded context, get from active segmentation
const segmentationInfo = data.find(
entry => entry.segmentation.segmentationId === activeSegmentationId
);
segmentation = segmentationInfo?.segmentation;
representation = segmentationInfo?.representation;
}
const segments = Object.values(representation.segments);
const isActiveSegmentation = segmentation.segmentationId === activeSegmentationId;
const { ref: scrollableContainerRef, maxHeight } = useDynamicMaxHeight(segments);
if (!representation || !segmentation) {
return null;
}
return (
<ScrollArea
className={`bg-bkg-low space-y-px`}
showArrows={true}
>
<div
ref={scrollableContainerRef}
style={{ maxHeight: maxHeight }}
>
{segments.map(segment => {
if (!segment) {
return null;
}
const { segmentIndex, color, visible } = segment as {
segmentIndex: number;
color: number[];
visible: boolean;
};
const segmentFromSegmentation = segmentation.segments[segmentIndex];
if (!segmentFromSegmentation) {
return null;
}
const { locked, active, label, displayText } = segmentFromSegmentation;
const cssColor = `rgb(${color[0]},${color[1]},${color[2]})`;
const hasStats = segmentFromSegmentation.cachedStats?.namedStats;
const DataRowComponent = (
<DataRow
key={segmentIndex}
number={segmentIndex}
title={label}
// details={displayText}
description={displayText}
colorHex={cssColor}
isSelected={active}
isVisible={visible}
isLocked={locked}
disableEditing={disableEditing}
className={!isActiveSegmentation ? 'opacity-80' : ''}
onColor={() => onSegmentColorClick(segmentation.segmentationId, segmentIndex)}
onToggleVisibility={() =>
onToggleSegmentVisibility(
segmentation.segmentationId,
segmentIndex,
representation.type
)
}
onToggleLocked={() => onToggleSegmentLock(segmentation.segmentationId, segmentIndex)}
onSelect={() => onSegmentClick(segmentation.segmentationId, segmentIndex)}
onRename={() => onSegmentEdit(segmentation.segmentationId, segmentIndex)}
onDelete={() => onSegmentDelete(segmentation.segmentationId, segmentIndex)}
/>
);
return hasStats ? (
<HoverCard
key={`hover-${segmentIndex}`}
openDelay={300}
>
<HoverCardTrigger asChild>
<div>{DataRowComponent}</div>
</HoverCardTrigger>
<HoverCardContent
side="left"
align="start"
className="w-72 border"
>
<div className="mb-4 flex items-center space-x-2">
<div
className="h-2.5 w-2.5 flex-shrink-0 rounded-full"
style={{ backgroundColor: cssColor }}
></div>
<h3 className="text-muted-foreground break-words font-semibold">{label}</h3>
</div>
<SegmentStatistics
segment={{
...segmentFromSegmentation,
segmentIndex,
}}
segmentationId={segmentation.segmentationId}
>
{children}
</SegmentStatistics>
</HoverCardContent>
</HoverCard>
) : (
DataRowComponent
);
})}
</div>
</ScrollArea>
);
};
SegmentationSegments.displayName = 'SegmentationTable.Segments';