fix(microscopy): Prevent measurement clearing on viewport resize (#5796)
Wrap DicomMicroscopyViewport with React.memo and custom areEqual to prevent unnecessary re-renders that trigger clearAnnotations(). --------- Co-authored-by: Joe Boccanfuso <joe.boccanfuso@radicalimaging.com>
This commit is contained in:
parent
7cdc54c86d
commit
baef707e46
@ -7,252 +7,324 @@ import getDicomWebClient from './utils/dicomWebClient';
|
|||||||
import dcmjs from 'dcmjs';
|
import dcmjs from 'dcmjs';
|
||||||
import { useSystem } from '@ohif/core';
|
import { useSystem } from '@ohif/core';
|
||||||
|
|
||||||
function DicomMicroscopyViewport({
|
// This component is wrapped with React.memo and uses a custom areEqual comparison
|
||||||
activeViewportId,
|
// function to prevent unnecessary re-renders when props are semantically identical
|
||||||
setViewportActive,
|
// (e.g. `displaySets` reference changes, but the content is the same).
|
||||||
displaySets,
|
// Note: If this component starts depending on additional props,
|
||||||
viewportId,
|
// update `areEqual` accordingly.
|
||||||
dataSource,
|
const DicomMicroscopyViewport = React.memo(
|
||||||
resizeRef,
|
({
|
||||||
}: {
|
activeViewportId,
|
||||||
activeViewportId: string;
|
setViewportActive,
|
||||||
setViewportActive: Function;
|
displaySets,
|
||||||
displaySets: any[];
|
viewportId,
|
||||||
viewportId: string;
|
dataSource,
|
||||||
dataSource: any;
|
resizeRef,
|
||||||
resizeRef: any;
|
}: {
|
||||||
}) {
|
activeViewportId: string;
|
||||||
const { servicesManager, extensionManager } = useSystem();
|
setViewportActive: Function;
|
||||||
const [isLoaded, setIsLoaded] = useState(false);
|
displaySets: any[];
|
||||||
const [viewer, setViewer] = useState(null);
|
viewportId: string;
|
||||||
const [managedViewer, setManagedViewer] = useState(null);
|
dataSource: any;
|
||||||
const overlayElement = useRef();
|
resizeRef: any;
|
||||||
const container = useRef();
|
}) => {
|
||||||
const { microscopyService, customizationService } = servicesManager.services;
|
const { servicesManager, extensionManager } = useSystem();
|
||||||
|
const [isLoaded, setIsLoaded] = useState(false);
|
||||||
|
const [viewer, setViewer] = useState(null);
|
||||||
|
const [managedViewer, setManagedViewer] = useState(null);
|
||||||
|
const overlayElement = useRef();
|
||||||
|
const container = useRef();
|
||||||
|
const { microscopyService, customizationService } = servicesManager.services;
|
||||||
|
|
||||||
const overlayData = customizationService.getCustomization('microscopyViewport.overlay');
|
const overlayData = customizationService.getCustomization('microscopyViewport.overlay');
|
||||||
|
|
||||||
// install the microscopy renderer into the web page.
|
// install the microscopy renderer into the web page.
|
||||||
// you should only do this once.
|
// you should only do this once.
|
||||||
const installOpenLayersRenderer = useCallback(
|
const installOpenLayersRenderer = useCallback(
|
||||||
async (container, displaySet) => {
|
async (container, displaySet) => {
|
||||||
const loadViewer = async metadata => {
|
const loadViewer = async metadata => {
|
||||||
const dicomMicroscopyModule = await microscopyService.importDicomMicroscopyViewer();
|
const dicomMicroscopyModule = await microscopyService.importDicomMicroscopyViewer();
|
||||||
const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = dicomMicroscopyModule;
|
const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = dicomMicroscopyModule;
|
||||||
|
|
||||||
const microscopyViewer = DicomMicroscopyViewer.VolumeImageViewer;
|
const microscopyViewer = DicomMicroscopyViewer.VolumeImageViewer;
|
||||||
|
|
||||||
const client = getDicomWebClient({
|
const client = getDicomWebClient({
|
||||||
extensionManager,
|
extensionManager,
|
||||||
servicesManager,
|
servicesManager,
|
||||||
});
|
|
||||||
|
|
||||||
// Parse, format, and filter metadata
|
|
||||||
const volumeImages: any[] = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This block of code is the original way of loading DICOM into dicom-microscopy-viewer
|
|
||||||
* as in their documentation.
|
|
||||||
* But we have the metadata already loaded by our loaders.
|
|
||||||
* As the metadata for microscopy DIOM files tends to be big and we don't
|
|
||||||
* want to double load it, below we have the mechanism to reconstruct the
|
|
||||||
* DICOM JSON structure (denaturalized) from naturalized metadata.
|
|
||||||
* (NOTE: Our loaders cache only naturalized metadata, not the denaturalized.)
|
|
||||||
*/
|
|
||||||
// {
|
|
||||||
// const retrieveOptions = {
|
|
||||||
// studyInstanceUID: metadata[0].StudyInstanceUID,
|
|
||||||
// seriesInstanceUID: metadata[0].SeriesInstanceUID,
|
|
||||||
// };
|
|
||||||
// metadata = await client.retrieveSeriesMetadata(retrieveOptions);
|
|
||||||
// // Parse, format, and filter metadata
|
|
||||||
// metadata.forEach(m => {
|
|
||||||
// if (
|
|
||||||
// volumeImages.length > 0 &&
|
|
||||||
// m['00200052'].Value[0] != volumeImages[0].FrameOfReferenceUID
|
|
||||||
// ) {
|
|
||||||
// console.warn(
|
|
||||||
// 'Expected FrameOfReferenceUID of difference instances within a series to be the same, found multiple different values',
|
|
||||||
// m['00200052'].Value[0]
|
|
||||||
// );
|
|
||||||
// m['00200052'].Value[0] = volumeImages[0].FrameOfReferenceUID;
|
|
||||||
// }
|
|
||||||
// NOTE: depending on different data source, image.ImageType sometimes
|
|
||||||
// is a string, not a string array.
|
|
||||||
// m['00080008'] = transformImageTypeUnnaturalized(m['00080008']);
|
|
||||||
|
|
||||||
// const image = new metadataUtils.VLWholeSlideMicroscopyImage({
|
|
||||||
// metadata: m,
|
|
||||||
// });
|
|
||||||
// const imageFlavor = image.ImageType[2];
|
|
||||||
// if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
|
|
||||||
// volumeImages.push(image);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
metadata.forEach(m => {
|
|
||||||
// NOTE: depending on different data source, image.ImageType sometimes
|
|
||||||
// is a string, not a string array.
|
|
||||||
m.ImageType = typeof m.ImageType === 'string' ? m.ImageType.split('\\') : m.ImageType;
|
|
||||||
|
|
||||||
const inst = cleanDenaturalizedDataset(
|
|
||||||
dcmjs.data.DicomMetaDictionary.denaturalizeDataset(m),
|
|
||||||
{
|
|
||||||
StudyInstanceUID: m.StudyInstanceUID,
|
|
||||||
SeriesInstanceUID: m.SeriesInstanceUID,
|
|
||||||
dataSourceConfig: dataSource.getConfig(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!inst['00480105']) {
|
|
||||||
// Optical Path Sequence, no OpticalPathIdentifier?
|
|
||||||
// NOTE: this is actually a not-well formatted DICOM VL Whole Slide Microscopy Image.
|
|
||||||
inst['00480105'] = {
|
|
||||||
vr: 'SQ',
|
|
||||||
Value: [
|
|
||||||
{
|
|
||||||
'00480106': {
|
|
||||||
vr: 'SH',
|
|
||||||
Value: ['1'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const image = new metadataUtils.VLWholeSlideMicroscopyImage({
|
|
||||||
metadata: inst,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const imageFlavor = image.ImageType[2];
|
// Parse, format, and filter metadata
|
||||||
if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
|
const volumeImages: any[] = [];
|
||||||
volumeImages.push(image);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// format metadata for microscopy-viewer
|
/**
|
||||||
const options = {
|
* This block of code is the original way of loading DICOM into dicom-microscopy-viewer
|
||||||
client,
|
* as in their documentation.
|
||||||
metadata: volumeImages,
|
* But we have the metadata already loaded by our loaders.
|
||||||
retrieveRendered: false,
|
* As the metadata for microscopy DIOM files tends to be big and we don't
|
||||||
controls: ['overview', 'position'],
|
* want to double load it, below we have the mechanism to reconstruct the
|
||||||
|
* DICOM JSON structure (denaturalized) from naturalized metadata.
|
||||||
|
* (NOTE: Our loaders cache only naturalized metadata, not the denaturalized.)
|
||||||
|
*/
|
||||||
|
// {
|
||||||
|
// const retrieveOptions = {
|
||||||
|
// studyInstanceUID: metadata[0].StudyInstanceUID,
|
||||||
|
// seriesInstanceUID: metadata[0].SeriesInstanceUID,
|
||||||
|
// };
|
||||||
|
// metadata = await client.retrieveSeriesMetadata(retrieveOptions);
|
||||||
|
// // Parse, format, and filter metadata
|
||||||
|
// metadata.forEach(m => {
|
||||||
|
// if (
|
||||||
|
// volumeImages.length > 0 &&
|
||||||
|
// m['00200052'].Value[0] != volumeImages[0].FrameOfReferenceUID
|
||||||
|
// ) {
|
||||||
|
// console.warn(
|
||||||
|
// 'Expected FrameOfReferenceUID of difference instances within a series to be the same, found multiple different values',
|
||||||
|
// m['00200052'].Value[0]
|
||||||
|
// );
|
||||||
|
// m['00200052'].Value[0] = volumeImages[0].FrameOfReferenceUID;
|
||||||
|
// }
|
||||||
|
// NOTE: depending on different data source, image.ImageType sometimes
|
||||||
|
// is a string, not a string array.
|
||||||
|
// m['00080008'] = transformImageTypeUnnaturalized(m['00080008']);
|
||||||
|
|
||||||
|
// const image = new metadataUtils.VLWholeSlideMicroscopyImage({
|
||||||
|
// metadata: m,
|
||||||
|
// });
|
||||||
|
// const imageFlavor = image.ImageType[2];
|
||||||
|
// if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
|
||||||
|
// volumeImages.push(image);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
metadata.forEach(m => {
|
||||||
|
// NOTE: depending on different data source, image.ImageType sometimes
|
||||||
|
// is a string, not a string array.
|
||||||
|
m.ImageType = typeof m.ImageType === 'string' ? m.ImageType.split('\\') : m.ImageType;
|
||||||
|
|
||||||
|
const inst = cleanDenaturalizedDataset(
|
||||||
|
dcmjs.data.DicomMetaDictionary.denaturalizeDataset(m),
|
||||||
|
{
|
||||||
|
StudyInstanceUID: m.StudyInstanceUID,
|
||||||
|
SeriesInstanceUID: m.SeriesInstanceUID,
|
||||||
|
dataSourceConfig: dataSource.getConfig(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (!inst['00480105']) {
|
||||||
|
// Optical Path Sequence, no OpticalPathIdentifier?
|
||||||
|
// NOTE: this is actually a not-well formatted DICOM VL Whole Slide Microscopy Image.
|
||||||
|
inst['00480105'] = {
|
||||||
|
vr: 'SQ',
|
||||||
|
Value: [
|
||||||
|
{
|
||||||
|
'00480106': {
|
||||||
|
vr: 'SH',
|
||||||
|
Value: ['1'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const image = new metadataUtils.VLWholeSlideMicroscopyImage({
|
||||||
|
metadata: inst,
|
||||||
|
});
|
||||||
|
|
||||||
|
const imageFlavor = image.ImageType[2];
|
||||||
|
if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
|
||||||
|
volumeImages.push(image);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// format metadata for microscopy-viewer
|
||||||
|
const options = {
|
||||||
|
client,
|
||||||
|
metadata: volumeImages,
|
||||||
|
retrieveRendered: false,
|
||||||
|
controls: ['overview', 'position'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewer = new microscopyViewer(options);
|
||||||
|
|
||||||
|
if (overlayElement && overlayElement.current && viewer.addViewportOverlay) {
|
||||||
|
viewer.addViewportOverlay({
|
||||||
|
element: overlayElement.current,
|
||||||
|
coordinates: [0, 0], // TODO: dicom-microscopy-viewer documentation says this can be false to be automatically, but it is not.
|
||||||
|
navigate: true,
|
||||||
|
className: 'OpenLayersOverlay',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer.render({ container });
|
||||||
|
|
||||||
|
const { StudyInstanceUID, SeriesInstanceUID } = displaySet;
|
||||||
|
|
||||||
|
const managedViewer = microscopyService.addViewer(
|
||||||
|
viewer,
|
||||||
|
viewportId,
|
||||||
|
container,
|
||||||
|
StudyInstanceUID,
|
||||||
|
SeriesInstanceUID
|
||||||
|
);
|
||||||
|
|
||||||
|
managedViewer.addContextMenuCallback((event: Event) => {
|
||||||
|
// TODO: refactor this after Bill's changes on ContextMenu feature get merged
|
||||||
|
// const roiAnnotationNearBy = this.getNearbyROI(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
setViewer(viewer);
|
||||||
|
setManagedViewer(managedViewer);
|
||||||
};
|
};
|
||||||
|
|
||||||
const viewer = new microscopyViewer(options);
|
microscopyService.clearAnnotations();
|
||||||
|
|
||||||
if (overlayElement && overlayElement.current && viewer.addViewportOverlay) {
|
let smDisplaySet = displaySet;
|
||||||
viewer.addViewportOverlay({
|
if (displaySet.isOverlayDisplaySet) {
|
||||||
element: overlayElement.current,
|
// for SR displaySet, let's load the actual image displaySet
|
||||||
coordinates: [0, 0], // TODO: dicom-microscopy-viewer documentation says this can be false to be automatically, but it is not.
|
smDisplaySet = displaySet.getSourceDisplaySet();
|
||||||
navigate: true,
|
|
||||||
className: 'OpenLayersOverlay',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
console.log('Loading viewer metadata', smDisplaySet);
|
||||||
|
|
||||||
viewer.render({ container });
|
await loadViewer(smDisplaySet.others);
|
||||||
|
|
||||||
const { StudyInstanceUID, SeriesInstanceUID } = displaySet;
|
if (displaySet.isOverlayDisplaySet && !displaySet.isLoaded && !displaySet.isLoading) {
|
||||||
|
const referencedDisplaySet = displaySet.getSourceDisplaySet();
|
||||||
|
displaySet.load(referencedDisplaySet);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dataSource, extensionManager, microscopyService, servicesManager, viewportId]
|
||||||
|
);
|
||||||
|
|
||||||
const managedViewer = microscopyService.addViewer(
|
useEffect(() => {
|
||||||
viewer,
|
if (!viewer) {
|
||||||
viewportId,
|
const displaySet = displaySets[0];
|
||||||
container,
|
installOpenLayersRenderer(container.current, displaySet).then(() => {
|
||||||
StudyInstanceUID,
|
setIsLoaded(true);
|
||||||
SeriesInstanceUID
|
|
||||||
);
|
|
||||||
|
|
||||||
managedViewer.addContextMenuCallback((event: Event) => {
|
|
||||||
// TODO: refactor this after Bill's changes on ContextMenu feature get merged
|
|
||||||
// const roiAnnotationNearBy = this.getNearbyROI(event);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setViewer(viewer);
|
return () => {
|
||||||
setManagedViewer(managedViewer);
|
if (viewer) {
|
||||||
|
microscopyService.removeViewer(viewer);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
}, [viewer]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const displaySet = displaySets[0];
|
||||||
|
|
||||||
microscopyService.clearAnnotations();
|
microscopyService.clearAnnotations();
|
||||||
|
|
||||||
let smDisplaySet = displaySet;
|
// loading SR - only if not already loaded and not currently loading
|
||||||
if (displaySet.isOverlayDisplaySet) {
|
|
||||||
// for SR displaySet, let's load the actual image displaySet
|
|
||||||
smDisplaySet = displaySet.getSourceDisplaySet();
|
|
||||||
}
|
|
||||||
console.log('Loading viewer metadata', smDisplaySet);
|
|
||||||
|
|
||||||
await loadViewer(smDisplaySet.others);
|
|
||||||
|
|
||||||
if (displaySet.isOverlayDisplaySet && !displaySet.isLoaded && !displaySet.isLoading) {
|
if (displaySet.isOverlayDisplaySet && !displaySet.isLoaded && !displaySet.isLoading) {
|
||||||
displaySet.load(smDisplaySet);
|
const referencedDisplaySet = displaySet.getSourceDisplaySet();
|
||||||
|
displaySet.load(referencedDisplaySet);
|
||||||
}
|
}
|
||||||
},
|
}, [managedViewer, displaySets, microscopyService]);
|
||||||
[dataSource, extensionManager, microscopyService, servicesManager, viewportId]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
const style = { width: '100%', height: '100%' };
|
||||||
const displaySet = displaySets[0];
|
const displaySet = displaySets[0];
|
||||||
installOpenLayersRenderer(container.current, displaySet).then(() => {
|
const firstInstance = displaySet.firstInstance || displaySet.instance;
|
||||||
setIsLoaded(true);
|
const LoadingIndicatorProgress = customizationService.getCustomization(
|
||||||
});
|
'ui.loadingIndicatorProgress'
|
||||||
|
);
|
||||||
|
|
||||||
return () => {
|
return (
|
||||||
if (viewer) {
|
<div
|
||||||
microscopyService.removeViewer(viewer);
|
className={'DicomMicroscopyViewer'}
|
||||||
}
|
style={style}
|
||||||
};
|
onClick={() => {
|
||||||
}, []);
|
if (viewportId !== activeViewportId) {
|
||||||
|
setViewportActive(viewportId);
|
||||||
useEffect(() => {
|
}
|
||||||
const displaySet = displaySets[0];
|
}}
|
||||||
|
>
|
||||||
microscopyService.clearAnnotations();
|
<div style={{ ...style, display: 'none' }}>
|
||||||
|
<div style={{ ...style }} ref={overlayElement}>
|
||||||
// loading SR - only if not already loaded and not currently loading
|
<div style={{ position: 'relative', height: '100%', width: '100%' }}>
|
||||||
if (displaySet.isOverlayDisplaySet && !displaySet.isLoaded && !displaySet.isLoading) {
|
{displaySet && firstInstance.imageId && (
|
||||||
const referencedDisplaySet = displaySet.getSourceDisplaySet();
|
<ViewportOverlay
|
||||||
displaySet.load(referencedDisplaySet);
|
overlayData={overlayData}
|
||||||
}
|
displaySet={displaySet}
|
||||||
}, [managedViewer, displaySets, microscopyService]);
|
instance={displaySet.instance}
|
||||||
|
metadata={displaySet.metadata}
|
||||||
const style = { width: '100%', height: '100%' };
|
/>
|
||||||
const displaySet = displaySets[0];
|
)}
|
||||||
const firstInstance = displaySet.firstInstance || displaySet.instance;
|
</div>
|
||||||
const LoadingIndicatorProgress = customizationService.getCustomization(
|
|
||||||
'ui.loadingIndicatorProgress'
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={'DicomMicroscopyViewer'}
|
|
||||||
style={style}
|
|
||||||
onClick={() => {
|
|
||||||
if (viewportId !== activeViewportId) {
|
|
||||||
setViewportActive(viewportId);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ ...style, display: 'none' }}>
|
|
||||||
<div style={{ ...style }} ref={overlayElement}>
|
|
||||||
<div style={{ position: 'relative', height: '100%', width: '100%' }}>
|
|
||||||
{displaySet && firstInstance.imageId && (
|
|
||||||
<ViewportOverlay
|
|
||||||
overlayData={overlayData}
|
|
||||||
displaySet={displaySet}
|
|
||||||
instance={displaySet.instance}
|
|
||||||
metadata={displaySet.metadata}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
style={style}
|
||||||
|
ref={(ref: any) => {
|
||||||
|
container.current = ref;
|
||||||
|
resizeRef.current = ref;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{isLoaded ? null : <LoadingIndicatorProgress className={'h-full w-full bg-black'} />}
|
||||||
</div>
|
</div>
|
||||||
<div
|
);
|
||||||
style={style}
|
},
|
||||||
ref={(ref: any) => {
|
areEqual
|
||||||
container.current = ref;
|
);
|
||||||
resizeRef.current = ref;
|
|
||||||
}}
|
// Check if the props are the same
|
||||||
/>
|
function areEqual(prevProps, nextProps) {
|
||||||
{isLoaded ? null : <LoadingIndicatorProgress className={'h-full w-full bg-black'} />}
|
if (prevProps.setViewportActive !== nextProps.setViewportActive) {
|
||||||
</div>
|
return false;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
if (prevProps.resizeRef !== nextProps.resizeRef) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevProps.viewportId !== nextProps.viewportId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevProps.activeViewportId !== nextProps.activeViewportId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevProps.dataSource !== nextProps.dataSource) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevDisplaySets = prevProps.displaySets;
|
||||||
|
const nextDisplaySets = nextProps.displaySets;
|
||||||
|
|
||||||
|
if (prevDisplaySets.length !== nextDisplaySets.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the displaySets are the same
|
||||||
|
for (let i = 0; i < prevDisplaySets.length; i++) {
|
||||||
|
const prevDisplaySet = prevDisplaySets[i];
|
||||||
|
|
||||||
|
const foundDisplaySet = nextDisplaySets.find(
|
||||||
|
nextDisplaySet =>
|
||||||
|
nextDisplaySet.displaySetInstanceUID === prevDisplaySet.displaySetInstanceUID
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!foundDisplaySet) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check if the displaySet's images are the same
|
||||||
|
if (foundDisplaySet.images?.length !== prevDisplaySet.images?.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the displaySet's imageIds are the same
|
||||||
|
if (foundDisplaySet.images?.length) {
|
||||||
|
for (let j = 0; j < foundDisplaySet.images.length; j++) {
|
||||||
|
if (foundDisplaySet.images[j].imageId !== prevDisplaySet.images[j].imageId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DicomMicroscopyViewport.displayName = 'DicomMicroscopyViewport';
|
||||||
|
|
||||||
export default DicomMicroscopyViewport;
|
export default DicomMicroscopyViewport;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { id } from './id';
|
import { id } from './id';
|
||||||
import React, { Suspense, useMemo } from 'react';
|
import React, { Suspense, useCallback, useMemo } from 'react';
|
||||||
import getPanelModule from './getPanelModule';
|
import getPanelModule from './getPanelModule';
|
||||||
import getCommandsModule from './getCommandsModule';
|
import getCommandsModule from './getCommandsModule';
|
||||||
import getCustomizationModule from './getCustomizationModule';
|
import getCustomizationModule from './getCustomizationModule';
|
||||||
@ -81,13 +81,18 @@ const extension: Types.Extensions.Extension = {
|
|||||||
handleWidth: true,
|
handleWidth: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const setViewportActive = useCallback(
|
||||||
|
(viewportId: string) => {
|
||||||
|
viewportGridService.setActiveViewportId(viewportId);
|
||||||
|
},
|
||||||
|
[viewportGridService]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MicroscopyViewport
|
<MicroscopyViewport
|
||||||
key={displaySetsKey}
|
key={displaySetsKey}
|
||||||
activeViewportId={activeViewportId}
|
activeViewportId={activeViewportId}
|
||||||
setViewportActive={(viewportId: string) => {
|
setViewportActive={setViewportActive}
|
||||||
viewportGridService.setActiveViewportId(viewportId);
|
|
||||||
}}
|
|
||||||
viewportData={viewportOptions}
|
viewportData={viewportOptions}
|
||||||
resizeRef={resizeRef}
|
resizeRef={resizeRef}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user