168 lines
5.0 KiB
TypeScript
168 lines
5.0 KiB
TypeScript
|
|
import { Injector } from 'didi';
|
||
|
|
|
||
|
|
import CommandHandler from './CommandHandler';
|
||
|
|
|
||
|
|
import EventBus from '../core/EventBus';
|
||
|
|
|
||
|
|
export type CommandContext = any;
|
||
|
|
|
||
|
|
export type CommandStackAction = {
|
||
|
|
command: string;
|
||
|
|
context: any;
|
||
|
|
};
|
||
|
|
|
||
|
|
export type CommandHandlerConstructor = {
|
||
|
|
new (...args: any[]) : CommandHandler
|
||
|
|
};
|
||
|
|
|
||
|
|
export type CommandHandlerInstance = Object;
|
||
|
|
|
||
|
|
export type CommandHandlerMap = {
|
||
|
|
[key: string]: CommandHandler;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A service that offers un- and redoable execution of commands.
|
||
|
|
*
|
||
|
|
* The command stack is responsible for executing modeling actions
|
||
|
|
* in a un- and redoable manner. To do this it delegates the actual
|
||
|
|
* command execution to {@link CommandHandler}s.
|
||
|
|
*
|
||
|
|
* Command handlers provide {@link CommandHandler#execute(ctx)} and
|
||
|
|
* {@link CommandHandler#revert(ctx)} methods to un- and redo a command
|
||
|
|
* identified by a command context.
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* ## Life-Cycle events
|
||
|
|
*
|
||
|
|
* In the process the command stack fires a number of life-cycle events
|
||
|
|
* that other components to participate in the command execution.
|
||
|
|
*
|
||
|
|
* * preExecute
|
||
|
|
* * preExecuted
|
||
|
|
* * execute
|
||
|
|
* * executed
|
||
|
|
* * postExecute
|
||
|
|
* * postExecuted
|
||
|
|
* * revert
|
||
|
|
* * reverted
|
||
|
|
*
|
||
|
|
* A special event is used for validating, whether a command can be
|
||
|
|
* performed prior to its execution.
|
||
|
|
*
|
||
|
|
* * canExecute
|
||
|
|
*
|
||
|
|
* Each of the events is fired as `commandStack.{eventName}` and
|
||
|
|
* `commandStack.{commandName}.{eventName}`, respectively. This gives
|
||
|
|
* components fine grained control on where to hook into.
|
||
|
|
*
|
||
|
|
* The event object fired transports `command`, the name of the
|
||
|
|
* command and `context`, the command context.
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* ## Creating Command Handlers
|
||
|
|
*
|
||
|
|
* Command handlers should provide the {@link CommandHandler#execute(ctx)}
|
||
|
|
* and {@link CommandHandler#revert(ctx)} methods to implement
|
||
|
|
* redoing and undoing of a command.
|
||
|
|
*
|
||
|
|
* A command handler _must_ ensure undo is performed properly in order
|
||
|
|
* not to break the undo chain. It must also return the shapes that
|
||
|
|
* got changed during the `execute` and `revert` operations.
|
||
|
|
*
|
||
|
|
* Command handlers may execute other modeling operations (and thus
|
||
|
|
* commands) in their `preExecute` and `postExecute` phases. The command
|
||
|
|
* stack will properly group all commands together into a logical unit
|
||
|
|
* that may be re- and undone atomically.
|
||
|
|
*
|
||
|
|
* Command handlers must not execute other commands from within their
|
||
|
|
* core implementation (`execute`, `revert`).
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* ## Change Tracking
|
||
|
|
*
|
||
|
|
* During the execution of the CommandStack it will keep track of all
|
||
|
|
* elements that have been touched during the command's execution.
|
||
|
|
*
|
||
|
|
* At the end of the CommandStack execution it will notify interested
|
||
|
|
* components via an 'elements.changed' event with all the dirty
|
||
|
|
* elements.
|
||
|
|
*
|
||
|
|
* The event can be picked up by components that are interested in the fact
|
||
|
|
* that elements have been changed. One use case for this is updating
|
||
|
|
* their graphical representation after moving / resizing or deletion.
|
||
|
|
*
|
||
|
|
* @see CommandHandler
|
||
|
|
*
|
||
|
|
* @param eventBus
|
||
|
|
* @param injector
|
||
|
|
*/
|
||
|
|
export default class CommandStack {
|
||
|
|
constructor(eventBus: EventBus, injector: Injector);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Execute a command.
|
||
|
|
*
|
||
|
|
* @param command The command to execute.
|
||
|
|
* @param context The context with which to execute the command.
|
||
|
|
*/
|
||
|
|
execute(command: string, context: CommandContext): void;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check whether a command can be executed.
|
||
|
|
*
|
||
|
|
* Implementors may hook into the mechanism on two ways:
|
||
|
|
*
|
||
|
|
* * in event listeners:
|
||
|
|
*
|
||
|
|
* Users may prevent the execution via an event listener.
|
||
|
|
* It must prevent the default action for `commandStack.(<command>.)canExecute` events.
|
||
|
|
*
|
||
|
|
* * in command handlers:
|
||
|
|
*
|
||
|
|
* If the method {@link CommandHandler#canExecute} is implemented in a handler
|
||
|
|
* it will be called to figure out whether the execution is allowed.
|
||
|
|
*
|
||
|
|
* @param {string} command The command to execute.
|
||
|
|
* @param {CommandContext} context The context with which to execute the command.
|
||
|
|
*
|
||
|
|
* @return {boolean} Whether the command can be executed with the given context.
|
||
|
|
*/
|
||
|
|
canExecute(command: string, context: CommandContext): boolean;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Clear the command stack, erasing all undo / redo history.
|
||
|
|
*
|
||
|
|
* @param emit Whether to fire an event. Defaults to `true`.
|
||
|
|
*/
|
||
|
|
clear(emit?: boolean): void;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Undo last command(s)
|
||
|
|
*/
|
||
|
|
undo(): void;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Redo last command(s)
|
||
|
|
*/
|
||
|
|
redo(): void;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Register a handler instance with the command stack.
|
||
|
|
*
|
||
|
|
* @param command Command to be executed.
|
||
|
|
* @param handler Handler to execute the command.
|
||
|
|
*/
|
||
|
|
register(command: string, handler: CommandHandler): void;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Register a handler type with the command stack by instantiating it and
|
||
|
|
* injecting its dependencies.
|
||
|
|
*
|
||
|
|
* @param {string} command Command to be executed.
|
||
|
|
* @param {CommandHandlerConstructor} handlerCls Constructor to instantiate a {@link CommandHandler}.
|
||
|
|
*/
|
||
|
|
registerHandler(command: string, handlerCls: CommandHandlerConstructor);
|
||
|
|
canUndo(): boolean;
|
||
|
|
canRedo(): boolean;
|
||
|
|
}
|