CommandManager
The plugin allows you to undo and redo changes made to the graph. It also provides a transaction mechanism to group multiple changes into a single command.
To learn more about the plugin, check out the Undo & Redo section.
constructorβ
constructor(options: CommandManager.Options);
The dia.CommandManager
constructor accepts several parameters:
graphβ
Is the graph the CommandManager listens to.
cmdBeforeAddβ
A function evaluated before any command is added. If the function returns false
, the command does not get stored. This way you can control which commands do not get registered for undo/redo.
const commandManager = new dia.CommandManager({
graph,
cmdBeforeAdd: (cmdName, cell, collection, options = {}) => {
return !options.ignoreCommandManager;
}
});
// ...
// Note that the last argument to set() is an options object
// that gets passed to the cmdBeforeAdd() function.
element.set({ foo: 'bar' }, { ignoreCommandManager: true });
cmdNameRegexβ
A regular expression specifying what cell's attributes the CommandManager listens to.
The default regex is /^(?:add|remove|change:\w+)$/
.
revertOptionsListβ
An array of options property names that are meant to be passed in undo actions. It defaults to ['propertyPath']
.
const commandManager = new dia.CommandManager({
/* ... */
revertOptionsList: ['myOptionAttribute1']
});
element.set('attribute', 'value', { myOptionAttribute1: 5, myOptionAttribute2: 6 });
/* `undo()` calls element.set('attribute', 'prevValue', { myOptionAttribute1: 5 }); */
commandManager.undo();
Alternatively the revertOptionList
can be defined as a function.
/* pass over everything except `doNotPassMe` attribute */
revertOptionsList: (attrValue, attrName) => attrName !== 'doNotPassMe';
applyOptionsListβ
An array of options property names that are meant to be passed in redo actions. It defaults to ['propertyPath']
.
const commandManager = new dia.CommandManager({
/* ... */
applyOptionsList: ['myOptionAttribute1']
});
element.set('attribute', 'value', { myOptionAttribute1: 5, myOptionAttribute2: 6 });
commandManager.undo();
/* `redo()` calls element.set('attribute', 'value', { myOptionAttribute1: 5 }); */
commandManager.redo();
Alternatively the applyOptionList
can be defined as a function.
/* pass over everything except `doNotPassMe` attribute */
applyOptionsList: (attrValue, attrName) => attrName !== 'doNotPassMe';
stackLimitβ
The maximum number of commands in the stack. If the number of commands exceeds the stackLimit
, the oldest commands in the undoStack are forgotten. It defaults to Infinity
.
Methodsβ
undo()β
commandManager.undo(opt?: CommandManager.EventOptions): void;
The undo()
method travels the history one command back. It accepts an option parameter (opt
) that is applied when function makes changes to the graph. e.g.
commandManager.undo({ undoneBy: 'user123' });
redo()β
commandManager.redo(opt?: CommandManager.EventOptions): void;
The redo()
method travels the history one command forward (to what was previously undo()
ed). It accepts an option parameter (opt
) that is applied when function makes changes to the graph. e.g.
commandManager.redo({ redoneBy: 'user123' });
cancel()β
commandManager.cancel(opt?: CommandManager.EventOptions): void;
Function is the same as undo()
but does not store the undo-ed command to the redoStack. Canceled command therefore cannot be redo-ed. It accepts an option parameter (opt
) that is applied when function makes changes to the graph. e.g.
commandManager.cancel({ canceledBy: 'user123' });
hasUndo()β
commandManager.hasUndo(): boolean;
Function returns true
if there is something in the undoStack.
hasRedo()β
commandManager.hasRedo(): boolean;
Function returns true
if there is something in the redoStack.
squashUndo()β
commandManager.squashUndo(n?: number): void;
The method squashUndo([n])
merges n
number of commands in the undo stack into a single batch command. If no n
is provided all commands are merged.
squashRedo()β
commandManager.squashRedo(n?: number): void;
The method squashRedo([n])
merges n
number of commands in the redo stack into a single batch command. If no n
is provided all commands are merged.
reset()β
commandManager.reset(opt?: CommandManager.EventOptions): void;
Function reset()
clears both undoStack and redoStack.
toJSON()β
commandManager.toJSON(): CommandManager.JSON;
The method exports the current state of the undo and redo stack to JSON. The export depends on the current state of graph and should be always accompanied by the graph export.
const graphJSON = graph.toJSON();
const historyJSON = commandManager.toJSON();
// a user-defined method to store data
await saveToDB({ historyJSON, graphJSON });
fromJSON()β
commandManager.fromJSON(
json: CommandManager.JSON,
opt?: CommandManager.EventOptions
): void;
The method fromJSON(json, [opt])
imports an existing undo and redo stack.
// a user-defined method to retrieve data
const { historyJSON, graphJSON } = await loadFromDB();
graph.fromJSON(graphJSON);
commandManager.fromJSON(historyJSON);
initBatchCommand()β
commandManager.initBatchCommand(): void;
Function initBatchCommand()
gives you the ability to gather multiple changes into a single command. These commands could be revert with single undo()
call.
From the moment the function is called every change made on graph is not stored into the undoStack. Changes are temporarily kept in the CommandManager until storeBatchCommand()
is called.
storeBatchCommand()β
commandManager.storeBatchCommand(opt?: CommandManager.EventOptions): void;
Calling function storeBatchCommand()
tells the CommandManager to store all changes temporarily kept in the undoStack. In order to store changes you have to call this function as many times as initBatchCommand()
had been called.
Propertiesβ
There are several properties that can be accessed:
undoStackβ
commandManager.undoStack: CommandManager.Commands;
The undoStack
is an array of commands that can be reverted. It is automatically populated when the graph is modified.
redoStackβ
commandManager.redoStack: CommandManager.Commands;
The redoStack
is an array of commands that has been reverted and can be re-applied.
The redoStack is reset every time the graph is modified other than by redo()
or undo()
.
Eventsβ
The plugin fires the following events:
stack:undoβ
Triggered when a command was undone.
commandManager.on('stack:undo', (
commandUndone: CommandManager.BatchCommand,
opt: CommandManager.EventOptions
) => {
// the `commandUndone` has been reverted
});
stack:redoβ
Triggered when a command were redone.
commandManager.on('stack:redo', (
commandRedone: CommandManager.BatchCommand,
opt: CommandManager.EventOptions
) => {
// the `commandRedone` has been re-applied
});
stack:pushβ
Triggered when a command were added to the undoStack.
commandManager.on('stack:push', (
commandPushedToUndoStack: CommandManager.BatchCommand,
opt: CommandManager.EventOptions
) => {
// the `commandPushedToUndoStack` has been added to the undo stack
});
stack:cancelβ
Triggered when a command was canceled.
commandManager.on('stack:cancel', (
commandCanceled: CommandManager.BatchCommand,
opt: CommandManager.EventOptions
) => {
// the `commandCanceled` has been canceled (undone and removed from history)
});
stack:resetβ
Triggered when all commands were reset or loaded from JSON.
commandManager.on('stack:reset', (opt: CommandManager.EventOptions) => {
// the stack has been reset
});
stackβ
Triggered when any change was made to stacks.
commandManager.on('stack', (opt: CommandManager.EventOptions) => {
if (commandManager.hasUndo()) { /* do something */ }
if (commandManager.hasRedo()) { /* do something else */ }
});
Typesβ
The plugin uses the following types:
BatchCommandβ
An array of commands.
type BatchCommand = Command[];
Commandβ
A structure representing a single command.
interface Command {
// is part of a batch command?
batch: boolean;
// the type of graph change
// (e.g. 'add', 'remove', 'change:attrs', ...)
action: string;
// options when the graph change set(), prop(), attr() methods.
options: any;
// is graph model or a cell changed
graphChange: boolean;
// see `CommandData` interface
data: CommandData;
}
CommandDataβ
The delta of the cell/graph attributes.
interface CommandData {
// the cell id
id: string | number;
// the cell type
type: string;
// the cell previous state if action is `change`
previous?: Partial<Cell.Attributes>;
// the cell next state if action is `change`
next?: Partial<Cell.Attributes>;
// the cell attributes if action is `add` or `remove`
attributes?: Cell.Attributes;
}
Commandsβ
An array of commands or batch commands.
type Commands = Array<Command | BatchCommand>;
EventOptionsβ
interface EventOptions {
[key: string]: any;
}
JSONβ
interface JSON {
undoStack: BatchCommand[];
redoStack: BatchCommand[];
[key: string]: any;
}
Optionsβ
interface Options {
graph: dia.Graph;
cmdBeforeAdd?: (eventName: string, ...eventArgs: any[]) => boolean;
cmdNameRegex?: RegExp;
applyOptionsList?: string[] | ReduceOptionsCallback;
revertOptionsList?: string[] | ReduceOptionsCallback;
stackLimit?: number;
}
ReduceOptionsCallbackβ
type ReduceOptionsCallback = (attrValue: any, attrName: string) => boolean;