[OHIF 284] - JumpToMeasurement + prevent layout change on scroll Prevent layout change on scroll (#1889)

* No more setting on debounce, jumpToMeasurement service set up.

* Fix bug causing a race condition sometimes if you click super fast.

* Optimise rendering of Tracking viewport slightly.

* element => targetElement

* Remove complete TODO

* Respond to reviewer comments.

* Fix e2e workflow.

* Fix regression that removed highlighting on jump to.

* Make sure jump to works from panel as well as viewport.

* Fix typo and remove debugger.

Co-authored-by: Danny Brown <danny.ri.brown@gmail.com>
This commit is contained in:
James PettsandDanny Brown authored and GitHub committed 2020-07-22 19:40:40 +02:00
1 parent 4985fbf5a6
commit a4f286feee
26 files changed
+438 -196

No files matched your search

@@ -161,29 +161,7 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
}
const jumpToImage = ({ id, isActive }) => {
const measurement = MeasurementService.getMeasurement(id);
const { referenceSeriesUID, SOPInstanceUID } = measurement;
setCornerstoneMeasurementActive(measurement);
const displaySets = DisplaySetService.getDisplaySetsForSeries(
referenceSeriesUID
);
const displaySet = displaySets.find(ds => {
return (
ds.images && ds.images.some(i => i.SOPInstanceUID === SOPInstanceUID)
);
});
const imageIndex = displaySet.images
.map(i => i.SOPInstanceUID)
.indexOf(SOPInstanceUID);
viewportGridService.setDisplaysetForViewport({
viewportIndex: viewportGrid.activeViewportIndex,
displaySetInstanceUID: displaySet.displaySetInstanceUID,
imageIndex,
});
MeasurementService.jumpToMeasurement(viewportGrid.activeViewportIndex, id);
onMeasurementItemClickHandler({ id, isActive });
};
@@ -16,6 +16,7 @@ import ViewportOverlay from './ViewportOverlay';
import ViewportLoadingIndicator from './ViewportLoadingIndicator';
import setCornerstoneMeasurementActive from '../_shared/setCornerstoneMeasurementActive';
const scrollToIndex = cornerstoneTools.importInternal('util/scrollToIndex');
const { formatDate } = utils;
// TODO -> Get this list from the list of tracked measurements.
@@ -47,12 +48,13 @@ function TrackedCornerstoneViewport({
viewportIndex,
servicesManager,
}) {
const { ToolBarService, DisplaySetService } = servicesManager.services;
const {
ToolBarService,
DisplaySetService,
MeasurementService,
} = servicesManager.services;
const [trackedMeasurements] = useTrackedMeasurements();
const [
{ activeViewportIndex, viewports },
viewportGridService,
] = useViewportGrid();
const [{ activeViewportIndex, viewports }] = useViewportGrid();
// viewportIndex, onSubmit
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
const [viewportData, setViewportData] = useState(null);
@@ -69,6 +71,28 @@ function TrackedCornerstoneViewport({
};
}, []);
useEffect(() => {
const unsubcribeFromJumpToMeasurementEvents = _subscribeToJumpToMeasurementEvents(
MeasurementService,
DisplaySetService,
element,
viewportIndex,
displaySet.displaySetInstanceUID
);
_checkForCachedJumpToMeasurementEvents(
MeasurementService,
DisplaySetService,
element,
viewportIndex,
displaySet.displaySetInstanceUID
);
return () => {
unsubcribeFromJumpToMeasurementEvents();
};
}, [element, displaySet]);
useEffect(() => {
if (!element) {
return;
@@ -167,13 +191,6 @@ function TrackedCornerstoneViewport({
);
}
/*
* This grabs `imageIndex from first matching
* We actually want whichever is at our `viewportIndex`
*/
const { imageIndex } = viewports[viewportIndex];
displaySet.imageIndex = imageIndex;
_getViewportData(dataSource, displaySet).then(setViewportData);
}, [dataSource, displaySet, viewports, viewportIndex]);
@@ -275,19 +292,10 @@ function TrackedCornerstoneViewport({
setCornerstoneMeasurementActive(measurement);
const {
displaySetInstanceUID,
imageIndex,
} = _getViewportDataFromTrackedMeasurementId(
measurement,
DisplaySetService
);
viewportGridService.setDisplaysetForViewport({
MeasurementService.jumpToMeasurement(
viewportIndex,
displaySetInstanceUID,
imageIndex,
});
newTrackedMeasurementId
);
}
const showNavArrows = isTracked && viewportIndex === activeViewportIndex;
@@ -336,14 +344,6 @@ function TrackedCornerstoneViewport({
viewportIndex={viewportIndex}
imageIds={imageIds}
imageIdIndex={currentImageIdIndex}
onNewImageDebounceTime={700}
onNewImageDebounced={({ currentImageIdIndex }) => {
viewportGridService.setDisplaysetForViewport({
viewportIndex: activeViewportIndex,
displaySetInstanceUID: displaySet.displaySetInstanceUID,
imageIndex: currentImageIdIndex,
});
}}
// Sync resize throttle w/ sidepanel animation duration to prevent
// seizure inducing strobe blinking effect
resizeRefreshRateMs={150}
@@ -402,16 +402,12 @@ const _viewportLabels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
* @return {Object} CornerstoneTools Stack
*/
function _getCornerstoneStack(displaySet, dataSource) {
const { imageIndex } = displaySet;
// Get stack from Stack Manager
const storedStack = StackManager.findOrCreateStack(displaySet, dataSource);
// Clone the stack here so we don't mutate it
const stack = Object.assign({}, storedStack);
stack.currentImageIdIndex = imageIndex;
return stack;
}
@@ -498,26 +494,111 @@ function _getNextMeasurementId(
return newTrackedMeasurementId;
}
function _getViewportDataFromTrackedMeasurementId(
function _subscribeToJumpToMeasurementEvents(
MeasurementService,
DisplaySetService,
element,
viewportIndex,
displaySetInstanceUID
) {
const { unsubscribe } = MeasurementService.subscribe(
MeasurementService.EVENTS.JUMP_TO_MEASUREMENT,
({ viewportIndex: jumpToMeasurementViewportIndex, measurement }) => {
// check if the correct viewport index.
if (viewportIndex !== jumpToMeasurementViewportIndex) {
// Event for a different viewport.
return;
}
if (measurement.displaySetInstanceUID !== displaySetInstanceUID) {
// Not for this displaySet.
return;
}
_jumpToMeasurement(
measurement,
element,
viewportIndex,
MeasurementService,
DisplaySetService
);
}
);
return unsubscribe;
}
function _checkForCachedJumpToMeasurementEvents(
MeasurementService,
DisplaySetService,
element,
viewportIndex,
displaySetInstanceUID
) {
// Check if there is a queued jumpToMeasurement event
const measurementIdToJumpTo = MeasurementService.getJumpToMeasurement(
viewportIndex
);
if (measurementIdToJumpTo && element) {
// Jump to measurement if the measurement exists
const measurement = MeasurementService.getMeasurement(
measurementIdToJumpTo
);
if (measurement.displaySetInstanceUID === displaySetInstanceUID) {
_jumpToMeasurement(
measurement,
element,
viewportIndex,
MeasurementService,
DisplaySetService
);
}
}
}
function _jumpToMeasurement(
measurement,
targetElement,
viewportIndex,
MeasurementService,
DisplaySetService
) {
const { referenceSeriesUID: SeriesInstanceUID, SOPInstanceUID } = measurement;
const { displaySetInstanceUID, SOPInstanceUID } = measurement;
const activeDisplaySets = DisplaySetService.getActiveDisplaySets();
const displaySet = activeDisplaySets.find(
ds => ds.SeriesInstanceUID === SeriesInstanceUID
const referencedDisplaySet = DisplaySetService.getDisplaySetByUID(
displaySetInstanceUID
);
const imageIndex = displaySet.images.findIndex(
image => image.SOPInstanceUID === SOPInstanceUID
const imageIndex = referencedDisplaySet.images.findIndex(
i => i.SOPInstanceUID === SOPInstanceUID
);
return {
imageIndex,
displaySetInstanceUID: displaySet.displaySetInstanceUID,
};
setCornerstoneMeasurementActive(measurement);
if (targetElement !== null) {
const enabledElement = cornerstone.getEnabledElement(targetElement);
if (enabledElement.image) {
// Wait for the image to update or we get a race condition when the element has only just been enabled.
const scrollToHandler = evt => {
scrollToIndex(targetElement, imageIndex);
targetElement.removeEventListener(
'cornerstoneimagerendered',
scrollToHandler
);
};
targetElement.addEventListener(
'cornerstoneimagerendered',
scrollToHandler
);
cornerstone.updateImage(targetElement);
}
// Jump to measurement consumed, remove.
MeasurementService.removeJumpToMeasurement(viewportIndex);
}
}
export default TrackedCornerstoneViewport;