fix(grid):Grid service wasn't being reset (#3068)

* fix(grid):Grid service wasn't being reset

* fix(service):Fix the initial service state

Services with mode specific state differed in internal state between
initial and subsequent load.  This fix address that structurally by
allows the mode to store/manage service state, but makes the
responsibility of service state central to the service.
This commit is contained in:
Bill Wallace authored and GitHub committed 2022-12-09 10:58:01 -05:00
1 parent 42dca11ae3
commit beb4517450
17 files changed
+120 -28

No files matched your search

@@ -40,6 +40,9 @@ export default class ExtensionManager {
_extensionLifeCycleHooks,
} = this;
// The onModeEnter of the service must occur BEFORE the extension
// onModeEnter in order to reset the state to a standard state
// before the extension restores and cached data.
for (const service of Object.values(_servicesManager.services)) {
service?.onModeEnter?.();
}
@@ -65,10 +68,6 @@ export default class ExtensionManager {
_extensionLifeCycleHooks,
} = this;
for (const service of Object.values(_servicesManager.services)) {
service?.onModeExit?.();
}
registeredExtensionIds.forEach(extensionId => {
const onModeExit = _extensionLifeCycleHooks.onModeExit[extensionId];
@@ -79,6 +78,16 @@ export default class ExtensionManager {
});
}
});
// The service onModeExit calls must occur after the extension ones
// so that extension ones can store/restore data.
for (const service of Object.values(_servicesManager.services)) {
try {
service?.onModeExit?.();
} catch (e) {
console.warn('onModeExit caught', e);
}
}
}
/**
@@ -104,7 +104,6 @@ export default class CustomizationService extends PubSubService {
commands.forEach(({ commandName, commandOptions, context }) => {
if (commandName) {
console.log('Running command', commandName);
commandsManager.runCommand(
commandName,
{
@@ -128,7 +127,6 @@ export default class CustomizationService extends PubSubService {
customizationId: string,
customization: Customization
): void {
console.log('** Set mode customization', customizationId, customization);
this.modeCustomizations[customizationId] = merge(
this.modeCustomizations[customizationId] || {},
customization
@@ -194,7 +192,6 @@ export default class CustomizationService extends PubSubService {
}
setGlobalCustomization(id: string, value: Customization): void {
console.log('*** Set global', id, value);
this.globalCustomizations[id] = value;
this._broadcastGlobalCustomizationModified();
}
@@ -234,7 +231,6 @@ export default class CustomizationService extends PubSubService {
if (!value) return;
if (typeof value === 'string') {
const extensionValue = this.findExtensionValue(value);
console.log('Adding extension values', value, extensionValue);
this.addReferences(extensionValue);
} else if (Array.isArray(value)) {
this.addReferences(value, isGlobal);
@@ -49,7 +49,15 @@ function createStudyMetadata(StudyInstanceUID) {
);
if (existingSeries) {
existingSeries.instances.push(...instances);
// Only add instances not already present, so generate a map
// of existing instances and filter the to add by things
// already present.
const sopMap = {};
existingSeries.instances.forEach(
it => (sopMap[it.SOPInstanceUID] = it)
);
const newInstances = instances.filter(it => !sopMap[it.SOPInstanceUID]);
existingSeries.instances.push(...newInstances);
} else {
const series = createSeriesMetadata(instances);
this.series.push(series);
@@ -53,7 +53,12 @@ export default class DisplaySetService {
const activeDisplaySets = this.activeDisplaySets;
displaySets.forEach(displaySet => {
activeDisplaySets.push(displaySet);
// This test makes adding display sets an N^2 operation, so it might
// become important to do this in an efficient manner for large
// numbers of display sets.
if (!activeDisplaySets.includes(displaySet)) {
activeDisplaySets.push(displaySet);
}
});
}
@@ -194,6 +199,17 @@ export default class DisplaySetService {
}
};
/**
* The onModeExit returns the display set service to the initial state,
* that is without any display sets. To avoid recreating display sets,
* the mode specific onModeExit is called before this method and should
* store the active display sets and the cached data.
*/
onModeExit() {
this.getDisplaySetCache().length = 0;
this.activeDisplaySets.length = 0;
}
makeDisplaySetForInstances(instancesSrc, settings) {
let instances = instancesSrc;
const instance = instances[0];
@@ -122,6 +122,11 @@ class HangingProtocolService {
this.displaySetMatchDetails = new Map();
}
/** Leave the hanging protocol in the initialized state */
public onModeExit() {
this.reset();
}
public getActiveProtocol(): {
protocol: HangingProtocol.Protocol;
stage: number;
@@ -570,6 +570,15 @@ class MeasurementService {
this._broadcastEvent(this.EVENTS.MEASUREMENTS_CLEARED, { measurements });
}
/**
* Called after the mode.onModeExit is called to reset the state.
* To store measurements for later use, store them in the mode.onModeExit
* and restore them in the mode onModeEnter.
*/
onModeExit() {
this.clearMeasurements();
}
jumpToMeasurement(viewportIndex, measurementUID) {
const measurement = this.measurements[measurementUID];
@@ -96,6 +96,16 @@ class ViewportGridService {
this.serviceImplementation._reset();
}
/**
* The onModeExit must set the state of the viewport grid to a standard/clean
* state. To implement store/recover of the viewport grid, perform
* a state store in the mode or extension onModeExit, and recover that
* data if appropriate in the onModeEnter of the mode or extension.
*/
public onModeExit(): void {
this.serviceImplementation._onModeExit();
}
public setCachedLayout({ cacheId, cachedLayout }) {
this.serviceImplementation._setCachedLayout({ cacheId, cachedLayout });
}