feat: Allow configurable context menus (#2894)

* feat: Context menu

feat: Custom context menu

Adding documentation

PR updates

* fix: Capture tool exception

* PR updates

* Add fully worked out examples in the basic test mode/extension

* Fix the menu display

* fix: Make the commands on clicks much more configurable

* Wait for load before double clicking

* docs

* PR changes - nothing functional, just moving things endlessly

* PR comments

* PR changes - rename the default context menu

* Renamed the cornerstoneContextMenu to measurementsContextMenu

* Add chevron right to the sub-menus
This commit is contained in:
Bill Wallace authored and GitHub committed 2023-03-22 17:45:28 -04:00
1 parent 4e94b588a7
commit bc642fd2b6
40 files changed
+1472 -280

No files matched your search

+1 -1
View File
@@ -106,7 +106,7 @@ export class CommandsManager {
* @param {String} commandName - Command to find
* @param {String} [contextName] - Specific command to look in. Defaults to current activeContexts
*/
getCommand = (commandName, contextName) => {
getCommand = (commandName: string, contextName?: string) => {
const contexts = [];
if (contextName) {
@@ -36,7 +36,10 @@ export interface ExtensionParams extends ExtensionConstructor {
*/
export interface Extension {
id: string;
preRegistration?: (p: ExtensionParams) => void;
preRegistration?: (p: ExtensionParams) => Promise<void> | void;
onModeExit?: () => void;
getHangingProtocolModule?: (p: ExtensionParams) => unknown;
getCommandsModule?: (p: ExtensionParams) => CommandsModule;
}
export type ExtensionRegister = {
@@ -44,6 +47,12 @@ export type ExtensionRegister = {
create: (p: ExtensionParams) => Extension;
};
export type CommandsModule = {
actions: Record<string, unknown>;
definitions: Record<string, unknown>;
defaultContext?: string;
};
export default class ExtensionManager {
private _commandsManager: CommandsManager;
private _servicesManager: ServicesManager;
@@ -331,7 +340,7 @@ export default class ExtensionManager {
}
try {
const extensionModule = getModuleFn({
const extensionModule = extension[getModuleFnName]({
appConfig: this._appConfig,
commandsManager: this._commandsManager,
servicesManager: this._servicesManager,
@@ -348,6 +357,7 @@ export default class ExtensionManager {
return extensionModule;
} catch (ex) {
console.log(ex);
throw new Error(
`Exception thrown while trying to call ${getModuleFnName} for the ${extensionId} extension`
);
@@ -123,7 +123,7 @@ export default class CustomizationService extends PubSubService {
* may have been extended with any customizationType extensions provided,
* so you cannot just use `|| defaultValue`
* @return A customization to use if one is found, or the default customization,
* both enhanced with any customizationType inheritance (see applyType)
* both enhanced with any customizationType inheritance (see transform)
*/
public getCustomization(
customizationId: string,
@@ -145,7 +145,7 @@ export default class CustomizationService extends PubSubService {
this.globalCustomizations[customizationId] ??
this.modeCustomizations[customizationId] ??
defaultValue;
return this.applyType(customization);
return this.transform(customization);
}
public hasModeCustomization(customizationId: string) {
@@ -154,6 +154,16 @@ export default class CustomizationService extends PubSubService {
this.modeCustomizations[customizationId]
);
}
/**
* get is an alias for getModeCustomization, as it is the generic getter
* which will return both mode and global customizations, and should be
* used generally.
* Note that the second parameter, defaultValue, will be expanded to include
* any customizationType values defined in it, so it is not the same as doing:
* `customizationService.get('key') || defaultValue`
* unless the defaultValue does not contain any customizationType definitions.
*/
public get = this.getModeCustomization;
/**
* Applies any inheritance due to UI Type customization.
@@ -161,14 +171,16 @@ export default class CustomizationService extends PubSubService {
* and if that is found, will assign all iterable values from that
* type into the new type, allowing default behaviour to be configured.
*/
public applyType(customization: Customization): Customization {
public transform(customization: Customization): Customization {
if (!customization) return customization;
const { customizationType } = customization;
if (!customizationType) return customization;
const parent = this.getCustomization(customizationType);
return parent
const result = parent
? Object.assign(Object.create(parent), customization)
: customization;
// Execute an nested type information
return result.transform?.(this) || result;
}
public addModeCustomizations(modeCustomizations): void {
@@ -195,7 +207,7 @@ export default class CustomizationService extends PubSubService {
id: string,
defaultValue?: Customization
): Customization | void {
return this.applyType(this.globalCustomizations[id] ?? defaultValue);
return this.transform(this.globalCustomizations[id] ?? defaultValue);
}
setGlobalCustomization(id: string, value: Customization): void {
@@ -235,7 +247,7 @@ export default class CustomizationService extends PubSubService {
const extensionValue = this.findExtensionValue(value);
// The child of a reference is only a set of references when an array,
// so call the addReference direct. It could be a secondary reference perhaps
this.addReference(extensionValue);
this.addReference(extensionValue.value, isGlobal, extensionValue.name);
} else if (Array.isArray(value)) {
this.addReferences(value, isGlobal);
} else {
+2 -4
View File
@@ -4,9 +4,7 @@ export interface Command {
context?: string;
}
/**
* This is the format used within many items for multiple commands
*/
/** A set of commands, typically contained in a tool item or other configuration */
export interface Commands {
commands: [];
commands: Commands[];
}