2023-09-22 10:23:44 -04:00
|
|
|
import React, { useEffect, useState } from 'react';
|
2022-11-16 14:19:52 -05:00
|
|
|
import PropTypes from 'prop-types';
|
2023-09-22 10:23:44 -04:00
|
|
|
import { PanelSection } from '../../components';
|
2022-11-16 14:19:52 -05:00
|
|
|
import SegmentationConfig from './SegmentationConfig';
|
2023-09-22 10:23:44 -04:00
|
|
|
import SegmentationDropDownRow from './SegmentationDropDownRow';
|
|
|
|
|
import NoSegmentationRow from './NoSegmentationRow';
|
|
|
|
|
import AddSegmentRow from './AddSegmentRow';
|
|
|
|
|
import SegmentationGroupSegment from './SegmentationGroupSegment';
|
2022-11-16 14:19:52 -05:00
|
|
|
|
|
|
|
|
const SegmentationGroupTable = ({
|
|
|
|
|
segmentations,
|
2023-09-22 10:23:44 -04:00
|
|
|
// segmentation initial config
|
|
|
|
|
segmentationConfig,
|
|
|
|
|
// UI show/hide
|
|
|
|
|
disableEditing,
|
|
|
|
|
showAddSegmentation,
|
|
|
|
|
showAddSegment,
|
|
|
|
|
showDeleteSegment,
|
|
|
|
|
// segmentation/segment handlers
|
2022-11-16 14:19:52 -05:00
|
|
|
onSegmentationAdd,
|
|
|
|
|
onSegmentationEdit,
|
|
|
|
|
onSegmentationClick,
|
|
|
|
|
onSegmentationDelete,
|
2023-09-22 10:23:44 -04:00
|
|
|
onSegmentationDownload,
|
2023-10-06 15:00:04 -04:00
|
|
|
onSegmentationDownloadRTSS,
|
2023-09-22 10:23:44 -04:00
|
|
|
storeSegmentation,
|
|
|
|
|
// segment handlers
|
2022-11-16 14:19:52 -05:00
|
|
|
onSegmentClick,
|
|
|
|
|
onSegmentAdd,
|
|
|
|
|
onSegmentDelete,
|
|
|
|
|
onSegmentEdit,
|
|
|
|
|
onToggleSegmentationVisibility,
|
|
|
|
|
onToggleSegmentVisibility,
|
2023-09-22 10:23:44 -04:00
|
|
|
onToggleSegmentLock,
|
2022-11-16 14:19:52 -05:00
|
|
|
onSegmentColorClick,
|
2023-09-22 10:23:44 -04:00
|
|
|
// segmentation config handlers
|
2022-11-16 14:19:52 -05:00
|
|
|
setFillAlpha,
|
|
|
|
|
setFillAlphaInactive,
|
|
|
|
|
setOutlineWidthActive,
|
|
|
|
|
setOutlineOpacityActive,
|
|
|
|
|
setRenderFill,
|
|
|
|
|
setRenderInactiveSegmentations,
|
|
|
|
|
setRenderOutline,
|
|
|
|
|
}) => {
|
2023-09-22 10:23:44 -04:00
|
|
|
const [isConfigOpen, setIsConfigOpen] = useState(false);
|
|
|
|
|
const [activeSegmentationId, setActiveSegmentationId] = useState(null);
|
|
|
|
|
|
|
|
|
|
const onActiveSegmentationChange = segmentationId => {
|
|
|
|
|
onSegmentationClick(segmentationId);
|
|
|
|
|
setActiveSegmentationId(segmentationId);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
// find the first active segmentation to set
|
|
|
|
|
let activeSegmentationIdToSet = segmentations?.find(segmentation => segmentation.isActive)?.id;
|
|
|
|
|
|
|
|
|
|
// If there is no active segmentation, set the first one to be active
|
|
|
|
|
if (!activeSegmentationIdToSet && segmentations?.length > 0) {
|
|
|
|
|
activeSegmentationIdToSet = segmentations[0].id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there is no segmentation, set the active segmentation to null
|
|
|
|
|
if (segmentations?.length === 0) {
|
|
|
|
|
activeSegmentationIdToSet = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setActiveSegmentationId(activeSegmentationIdToSet);
|
|
|
|
|
}, [segmentations]);
|
|
|
|
|
|
|
|
|
|
const activeSegmentation = segmentations?.find(
|
|
|
|
|
segmentation => segmentation.id === activeSegmentationId
|
|
|
|
|
);
|
|
|
|
|
|
2022-11-16 14:19:52 -05:00
|
|
|
return (
|
2023-09-22 10:23:44 -04:00
|
|
|
<div className="flex min-h-0 flex-col bg-black text-[13px] font-[300]">
|
|
|
|
|
<PanelSection
|
|
|
|
|
title="Segmentation"
|
|
|
|
|
actionIcons={
|
|
|
|
|
activeSegmentation && [
|
|
|
|
|
{
|
|
|
|
|
name: 'settings-bars',
|
|
|
|
|
onClick: () => setIsConfigOpen(isOpen => !isOpen),
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{isConfigOpen && (
|
|
|
|
|
<SegmentationConfig
|
|
|
|
|
setFillAlpha={setFillAlpha}
|
|
|
|
|
setFillAlphaInactive={setFillAlphaInactive}
|
|
|
|
|
setOutlineWidthActive={setOutlineWidthActive}
|
|
|
|
|
setOutlineOpacityActive={setOutlineOpacityActive}
|
|
|
|
|
setRenderFill={setRenderFill}
|
|
|
|
|
setRenderInactiveSegmentations={setRenderInactiveSegmentations}
|
|
|
|
|
setRenderOutline={setRenderOutline}
|
|
|
|
|
segmentationConfig={segmentationConfig}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
<div className="bg-primary-dark">
|
|
|
|
|
{segmentations?.length === 0 ? (
|
|
|
|
|
<div className="select-none rounded-[4px]">
|
|
|
|
|
{showAddSegmentation && !disableEditing && (
|
|
|
|
|
<NoSegmentationRow onSegmentationAdd={onSegmentationAdd} />
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<div className="mt-1 select-none">
|
2023-10-05 22:13:08 -04:00
|
|
|
<SegmentationDropDownRow
|
|
|
|
|
segmentations={segmentations}
|
|
|
|
|
disableEditing={disableEditing}
|
|
|
|
|
activeSegmentation={activeSegmentation}
|
|
|
|
|
onActiveSegmentationChange={onActiveSegmentationChange}
|
|
|
|
|
onSegmentationDelete={onSegmentationDelete}
|
|
|
|
|
onSegmentationEdit={onSegmentationEdit}
|
|
|
|
|
onSegmentationDownload={onSegmentationDownload}
|
2023-10-06 15:00:04 -04:00
|
|
|
onSegmentationDownloadRTSS={onSegmentationDownloadRTSS}
|
2023-10-05 22:13:08 -04:00
|
|
|
storeSegmentation={storeSegmentation}
|
|
|
|
|
onSegmentationAdd={onSegmentationAdd}
|
|
|
|
|
onToggleSegmentationVisibility={onToggleSegmentationVisibility}
|
|
|
|
|
/>
|
2023-09-22 10:23:44 -04:00
|
|
|
{!disableEditing && showAddSegment && (
|
|
|
|
|
<AddSegmentRow onClick={() => onSegmentAdd(activeSegmentationId)} />
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2022-11-16 14:19:52 -05:00
|
|
|
</div>
|
2023-09-22 10:23:44 -04:00
|
|
|
{activeSegmentation && (
|
|
|
|
|
<div className="ohif-scrollbar mt-1.5 flex min-h-0 flex-col overflow-y-hidden">
|
|
|
|
|
{activeSegmentation?.segments?.map(segment => {
|
|
|
|
|
if (!segment) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { segmentIndex, color, label, isVisible, isLocked } = segment;
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className="mb-[1px]"
|
|
|
|
|
key={segmentIndex}
|
|
|
|
|
>
|
|
|
|
|
<SegmentationGroupSegment
|
|
|
|
|
segmentationId={activeSegmentationId}
|
|
|
|
|
segmentIndex={segmentIndex}
|
|
|
|
|
label={label}
|
|
|
|
|
color={color}
|
|
|
|
|
isActive={activeSegmentation.activeSegmentIndex === segmentIndex}
|
|
|
|
|
disableEditing={disableEditing}
|
|
|
|
|
isLocked={isLocked}
|
|
|
|
|
isVisible={isVisible}
|
|
|
|
|
onClick={onSegmentClick}
|
|
|
|
|
onEdit={onSegmentEdit}
|
|
|
|
|
onDelete={onSegmentDelete}
|
|
|
|
|
showDelete={showDeleteSegment}
|
|
|
|
|
onColor={onSegmentColorClick}
|
|
|
|
|
onToggleVisibility={onToggleSegmentVisibility}
|
|
|
|
|
onToggleLocked={onToggleSegmentLock}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</PanelSection>
|
2022-11-16 14:19:52 -05:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
SegmentationGroupTable.propTypes = {
|
2023-09-22 10:23:44 -04:00
|
|
|
segmentations: PropTypes.arrayOf(
|
|
|
|
|
PropTypes.shape({
|
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
|
isActive: PropTypes.bool.isRequired,
|
|
|
|
|
segments: PropTypes.arrayOf(
|
|
|
|
|
PropTypes.shape({
|
|
|
|
|
segmentIndex: PropTypes.number.isRequired,
|
|
|
|
|
color: PropTypes.array.isRequired,
|
|
|
|
|
label: PropTypes.string.isRequired,
|
|
|
|
|
isVisible: PropTypes.bool.isRequired,
|
|
|
|
|
isLocked: PropTypes.bool.isRequired,
|
|
|
|
|
})
|
|
|
|
|
),
|
|
|
|
|
})
|
|
|
|
|
),
|
|
|
|
|
segmentationConfig: PropTypes.object.isRequired,
|
2023-08-16 11:26:28 -03:00
|
|
|
disableEditing: PropTypes.bool,
|
2023-09-22 10:23:44 -04:00
|
|
|
showAddSegmentation: PropTypes.bool,
|
|
|
|
|
showAddSegment: PropTypes.bool,
|
|
|
|
|
showDeleteSegment: PropTypes.bool,
|
|
|
|
|
onSegmentationAdd: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentationEdit: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentationClick: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentationDelete: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentationDownload: PropTypes.func.isRequired,
|
2023-10-06 15:00:04 -04:00
|
|
|
onSegmentationDownloadRTSS: PropTypes.func.isRequired,
|
2023-09-22 10:23:44 -04:00
|
|
|
storeSegmentation: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentClick: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentAdd: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentDelete: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentEdit: PropTypes.func.isRequired,
|
|
|
|
|
onToggleSegmentationVisibility: PropTypes.func.isRequired,
|
|
|
|
|
onToggleSegmentVisibility: PropTypes.func.isRequired,
|
|
|
|
|
onToggleSegmentLock: PropTypes.func.isRequired,
|
|
|
|
|
onSegmentColorClick: PropTypes.func.isRequired,
|
|
|
|
|
setFillAlpha: PropTypes.func.isRequired,
|
|
|
|
|
setFillAlphaInactive: PropTypes.func.isRequired,
|
|
|
|
|
setOutlineWidthActive: PropTypes.func.isRequired,
|
|
|
|
|
setOutlineOpacityActive: PropTypes.func.isRequired,
|
|
|
|
|
setRenderFill: PropTypes.func.isRequired,
|
|
|
|
|
setRenderInactiveSegmentations: PropTypes.func.isRequired,
|
|
|
|
|
setRenderOutline: PropTypes.func.isRequired,
|
2022-11-16 14:19:52 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
SegmentationGroupTable.defaultProps = {
|
|
|
|
|
segmentations: [],
|
2023-09-22 10:23:44 -04:00
|
|
|
disableEditing: false,
|
|
|
|
|
showAddSegmentation: true,
|
|
|
|
|
showAddSegment: true,
|
|
|
|
|
showDeleteSegment: true,
|
|
|
|
|
onSegmentationAdd: () => {},
|
|
|
|
|
onSegmentationEdit: () => {},
|
|
|
|
|
onSegmentationClick: () => {},
|
|
|
|
|
onSegmentationDelete: () => {},
|
|
|
|
|
onSegmentationDownload: () => {},
|
2023-10-06 15:00:04 -04:00
|
|
|
onSemgnetationDownloadRTSS: () => {},
|
2023-09-22 10:23:44 -04:00
|
|
|
storeSegmentation: () => {},
|
|
|
|
|
onSegmentClick: () => {},
|
|
|
|
|
onSegmentAdd: () => {},
|
|
|
|
|
onSegmentDelete: () => {},
|
|
|
|
|
onSegmentEdit: () => {},
|
|
|
|
|
onToggleSegmentationVisibility: () => {},
|
|
|
|
|
onToggleSegmentVisibility: () => {},
|
|
|
|
|
onToggleSegmentLock: () => {},
|
|
|
|
|
onSegmentColorClick: () => {},
|
2022-11-16 14:19:52 -05:00
|
|
|
setFillAlpha: () => {},
|
|
|
|
|
setFillAlphaInactive: () => {},
|
|
|
|
|
setOutlineWidthActive: () => {},
|
|
|
|
|
setOutlineOpacityActive: () => {},
|
|
|
|
|
setRenderFill: () => {},
|
|
|
|
|
setRenderInactiveSegmentations: () => {},
|
|
|
|
|
setRenderOutline: () => {},
|
|
|
|
|
};
|
|
|
|
|
export default SegmentationGroupTable;
|