2019-08-13 21:36:46 +02:00
|
|
|
import log from '../log.js';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The definition of a command
|
|
|
|
|
*
|
|
|
|
|
* @typedef {Object} CommandDefinition
|
|
|
|
|
* @property {Function} commandFn - Command to call
|
|
|
|
|
* @property {Object} options - Object of params to pass action
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The Commands Manager tracks named commands (or functions) that are scoped to
|
|
|
|
|
* a context. When we attempt to run a command with a given name, we look for it
|
|
|
|
|
* in our active contexts. If found, we run the command, passing in any application
|
|
|
|
|
* or call specific data specified in the command's definition.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: A more robust version of the CommandsManager lives in v1. If you're looking
|
|
|
|
|
* to extend this class, please check it's source before adding new methods.
|
|
|
|
|
*/
|
|
|
|
|
export class CommandsManager {
|
2022-07-27 18:39:04 +02:00
|
|
|
constructor({} = {}) {
|
2019-08-13 21:36:46 +02:00
|
|
|
this.contexts = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Allows us to create commands "per context". An example would be the "Cornerstone"
|
|
|
|
|
* context having a `SaveImage` command, and the "VTK" context having a `SaveImage`
|
|
|
|
|
* command. The distinction of a context allows us to call the command in either
|
|
|
|
|
* context, and have faith that the correct command will be run.
|
|
|
|
|
*
|
|
|
|
|
* @method
|
|
|
|
|
* @param {string} contextName - Namespace for commands
|
|
|
|
|
* @returns {undefined}
|
|
|
|
|
*/
|
|
|
|
|
createContext(contextName) {
|
|
|
|
|
if (!contextName) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.contexts[contextName]) {
|
|
|
|
|
return this.clearContext(contextName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.contexts[contextName] = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns all command definitions for a given context
|
|
|
|
|
*
|
|
|
|
|
* @method
|
|
|
|
|
* @param {string} contextName - Namespace for commands
|
2019-12-09 18:47:23 +01:00
|
|
|
* @returns {Object} - the matched context
|
2019-08-13 21:36:46 +02:00
|
|
|
*/
|
|
|
|
|
getContext(contextName) {
|
|
|
|
|
const context = this.contexts[contextName];
|
|
|
|
|
|
|
|
|
|
if (!context) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return context;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Clears all registered commands for a given context.
|
|
|
|
|
*
|
|
|
|
|
* @param {string} contextName - Namespace for commands
|
|
|
|
|
* @returns {undefined}
|
|
|
|
|
*/
|
|
|
|
|
clearContext(contextName) {
|
|
|
|
|
if (!contextName) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.contexts[contextName] = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register a new command with the command manager. Scoped to a context, and
|
|
|
|
|
* with a definition to assist command callers w/ providing the necessary params
|
|
|
|
|
*
|
|
|
|
|
* @method
|
|
|
|
|
* @param {string} contextName - Namespace for command; often scoped to the extension that added it
|
|
|
|
|
* @param {string} commandName - Unique name identifying the command
|
|
|
|
|
* @param {CommandDefinition} definition - {@link CommandDefinition}
|
|
|
|
|
*/
|
|
|
|
|
registerCommand(contextName, commandName, definition) {
|
|
|
|
|
if (typeof definition !== 'object') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const context = this.getContext(contextName);
|
|
|
|
|
if (!context) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context[commandName] = definition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Finds a command with the provided name if it exists in the specified context,
|
|
|
|
|
* or a currently active context.
|
|
|
|
|
*
|
|
|
|
|
* @method
|
|
|
|
|
* @param {String} commandName - Command to find
|
|
|
|
|
* @param {String} [contextName] - Specific command to look in. Defaults to current activeContexts
|
|
|
|
|
*/
|
2020-05-18 23:21:41 +02:00
|
|
|
getCommand = (commandName, contextName) => {
|
2019-08-13 21:36:46 +02:00
|
|
|
let contexts = [];
|
|
|
|
|
|
|
|
|
|
if (contextName) {
|
|
|
|
|
const context = this.getContext(contextName);
|
|
|
|
|
if (context) {
|
|
|
|
|
contexts.push(context);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2022-07-27 18:39:04 +02:00
|
|
|
Object.keys(this.contexts).forEach(contextName => {
|
|
|
|
|
contexts.push(this.getContext(contextName));
|
2019-08-13 21:36:46 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (contexts.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let foundCommand;
|
|
|
|
|
contexts.forEach(context => {
|
|
|
|
|
if (context[commandName]) {
|
|
|
|
|
foundCommand = context[commandName];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return foundCommand;
|
2020-05-18 23:21:41 +02:00
|
|
|
};
|
2019-08-13 21:36:46 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @method
|
|
|
|
|
* @param {String} commandName
|
|
|
|
|
* @param {Object} [options={}] - Extra options to pass the command. Like a mousedown event
|
|
|
|
|
* @param {String} [contextName]
|
|
|
|
|
*/
|
|
|
|
|
runCommand(commandName, options = {}, contextName) {
|
|
|
|
|
const definition = this.getCommand(commandName, contextName);
|
|
|
|
|
if (!definition) {
|
|
|
|
|
log.warn(`Command "${commandName}" not found in current context`);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-15 03:18:46 +02:00
|
|
|
const { commandFn } = definition;
|
|
|
|
|
const commandParams = Object.assign(
|
2019-08-13 21:36:46 +02:00
|
|
|
{},
|
2020-09-15 03:18:46 +02:00
|
|
|
definition.options, // "Command configuration"
|
2019-08-13 21:36:46 +02:00
|
|
|
options // "Time of call" info
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (typeof commandFn !== 'function') {
|
|
|
|
|
log.warn(`No commandFn was defined for command "${commandName}"`);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
return commandFn(commandParams);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default CommandsManager;
|