@mezzy/commands
Version:
A luxurious user experience framework, developed by your friends at Mezzanine.
185 lines • 7.24 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const is_1 = require("@mezzy/is");
const debug_1 = require("@mezzy/debug");
const result_1 = require("@mezzy/result");
const signals_1 = require("@mezzy/signals");
const ids_1 = require("@mezzy/ids");
const collections_1 = require("@mezzy/collections");
const collections_2 = require("@mezzy/collections");
const command_1 = require("./command");
const commandEventArgs_1 = require("./commandEventArgs");
debug_1.default.setCategoryMode('commands', false);
class CommandManager {
constructor(isUndoEnabled = true) {
this._progress = 0;
this._isUndoEnabled = true;
this._commands = new collections_1.MapList();
this._pendingQueue = new collections_2.Queue();
this._undoQueue = new collections_2.Queue();
this._redoQueue = new collections_2.Queue();
this._isRunningAll = false;
this._runStartCount = 0;
this.commandRunStart = new signals_1.Signal();
this.commandRunComplete = new signals_1.Signal();
this._isUndoEnabled = isUndoEnabled;
}
get progress() { return this._progress; }
get pending() { return this._pendingQueue.size; }
get runStartCount() { return this._runStartCount; }
get lastReturnValue() { return this._lastReturnValue; }
register(scope, runFunction, undoFunction, name) {
if (is_1.default.empty(runFunction))
return;
let command = new command_1.default(runFunction, undoFunction, scope);
if (is_1.default.empty(name))
name = 'command_' + ids_1.Identifier.getSessionUniqueInteger();
this._commands.set(name, command);
return name;
}
unregister(name) { this._commands.delete(name); }
get(name) {
let command = this._commands.get(name);
if (is_1.default.empty(command)) {
command = new command_1.default();
this._commands.set(name, command);
return command;
}
else
return command;
}
queue(command, runArgs, undoArgs) {
if (is_1.default.empty(command))
return;
if (is_1.default.notEmpty(runArgs))
command.runArgs = runArgs;
if (is_1.default.notEmpty(undoArgs))
command.undoArgs = undoArgs;
this._pendingQueue.add(command);
return this;
}
run(command, args, undoArgs) {
if (is_1.default.empty(command))
return this._runAll();
else {
let commandFinal;
if (typeof command === 'string')
commandFinal = this.get(command);
else
commandFinal = command;
if (is_1.default.empty(commandFinal))
return result_1.Result.resolve(null);
this.queue(commandFinal, args, undoArgs);
return this._runAll();
}
}
undo(...args) {
if (!this._isUndoEnabled || this._undoQueue.size < 1)
return result_1.Result.resolve(null);
let command = this._undoQueue.deleteLast();
if (is_1.default.empty(command))
return result_1.Result.resolve(null);
let result = command.undo.apply(command, args);
result.then((returnValue) => {
this._redoQueue.add(command);
});
return result;
}
redo(...args) {
if (!this._isUndoEnabled || this._redoQueue.size < 1)
return result_1.Result.resolve(null);
let command = this._redoQueue.deleteLast();
if (is_1.default.empty(command))
return result_1.Result.resolve(null);
let result = command.run.apply(command, args);
result.then((returnValue) => {
let commandEventArgs = new commandEventArgs_1.default(command, 1, returnValue, args);
commandEventArgs.isCommandComplete = true;
this.commandRunComplete.dispatch(commandEventArgs);
this._undoQueue.add(command);
});
return result;
}
clearAllQueues() {
this._pendingQueue.clear();
this._undoQueue.clear();
this._redoQueue.clear();
return this;
}
clearPending() {
this._pendingQueue.clear();
return this;
}
_run(command) {
let pending = this._pendingQueue.size + 1;
let progressStart = 1 - (pending / this._runStartCount);
let argsStart = new commandEventArgs_1.default(command, progressStart);
if (this._isRunningAll) {
argsStart.pending = this._pendingQueue.size + 1;
argsStart.totalRunning = this._runStartCount;
}
this.commandRunStart.dispatch(argsStart);
if (this._isUndoEnabled) {
this._undoQueue.add(command);
this._redoQueue.clear();
}
let result = command.run();
result.then((returnValue) => {
this._lastReturnValue = returnValue;
let progressComplete = 1 - ((pending - 1) / this._runStartCount);
let argsComplete = new commandEventArgs_1.default(command, progressComplete, returnValue);
if (this._isRunningAll) {
argsComplete.pending = this._pendingQueue.size;
argsComplete.totalRunning = this._runStartCount;
}
argsComplete.isCommandComplete = true;
this.commandRunComplete.dispatch(argsComplete);
});
return result;
}
_runNext() {
if (this._pendingQueue.size > 0) {
let command = this._pendingQueue.deleteFirst();
if (is_1.default.empty(command)) {
debug_1.default.error('Expected commands on pending stack, but found none.', 'CommandManager.runNext(...)');
return result_1.Result.resolve(null);
}
debug_1.default.log(command.message + (is_1.default.empty(command.message) ? '' : ' ')
+ 'p = ' + this._progress.toString() + ', remaining: ' + this._pendingQueue.size.toString()
+ ', total: ' + this._runStartCount.toString(), null, 'commands');
return this._run(command);
}
else
return result_1.Result.resolve(null);
}
_runAll() {
if (!this._isRunningAll) {
this._isRunningAll = true;
this._progress = 0;
this._resultRunAll = new result_1.Result();
this._lastReturnValue = null;
this._runStartCount = this._pendingQueue.size;
if (this._runStartCount > 0)
this._runAllNext();
else
this._resultRunAll.resolve(null);
}
return this._resultRunAll;
}
_runAllNext() {
if (this._pendingQueue.size > 0) {
this._runNext().then((result) => {
this._progress = 1 - (this._pendingQueue.size / this._runStartCount);
this._runAllNext();
});
}
else {
this._isRunningAll = false;
this._progress = 1;
this._resultRunAll.resolve(this._lastReturnValue);
}
}
}
exports.CommandManager = CommandManager;
exports.default = CommandManager;
//# sourceMappingURL=commandManager.js.map