milo

ActionsHistory

function
 ActionsHistory() 

Option name Type Description
maxLength Number

Stores list of commands or transactions

function ActionsHistory(maxLength) {
    this._maxLength = maxLength || Infinity;
    this.actions = [];
    this.position = 0;
}


_.extendProto(ActionsHistory, {
    store: ActionsHistory$store,
    deleteLast: ActionsHistory$deleteLast,
    undo: ActionsHistory$undo,
    redo: ActionsHistory$redo,
    undoAll: ActionsHistory$undoAll,
    redoAll: ActionsHistory$redoAll,
    undoAllAsync: ActionsHistory$undoAllAsync,
    redoAllAsync: ActionsHistory$redoAllAsync,
    each: ActionsHistory$each,
    eachReverse: ActionsHistory$eachReverse,
    getLastAction: ActionsHistory$getLastAction,

    getDescription: ActionsHistory$getDescription
});


function ActionsHistory$store(command) {
    _truncateToCurrentPosition.call(this);
    this.actions.push(command);

    if (this.actions.length > this._maxLength) {
        var act = this.actions.shift();
        act.destroy();
    }

    this.position = this.actions.length;
    return this.position - 1;
}


function ActionsHistory$deleteLast() {
    if (!this.actions.length) return;
    this.position--;
    this.actions.length--;
}


function _truncateToCurrentPosition() {
    for (var i = this.position; i < this.actions.length; i++)
        this.actions[i].destroy();
    this.actions.length = this.position;
}


function ActionsHistory$undo(cb) {
    if (this.position === 0) return; // nothing to undo
    var act = this.actions[--this.position];
    act.undo(cb);
    return act;
}


function ActionsHistory$redo(cb) {
    if (this.position == this.actions.length) return; // nothing to redo
    var act = this.actions[this.position++];
    act.redo(cb);
    return act;
}


function ActionsHistory$undoAll() {
    while (this.position) this.undo();
}


function ActionsHistory$redoAll() {
    while (this.position < this.actions.length) this.redo();
}


function ActionsHistory$undoAllAsync(cb) {
    if (this.position) {
        this.undo();
        if (this.position)
            _.deferMethod(this, 'undoAllAsync', cb);
        else
            if (cb) _.defer(cb);
    }
}


function ActionsHistory$redoAllAsync(cb) {
    if (this.position < this.actions.length) {
        this.redo();
        if (this.position < this.actions.length) 
            _.deferMethod(this, 'redoAllAsync', cb);
        else
            if (cb) _.defer(cb);
    }
}


function ActionsHistory$each(funcOrMethod, thisArg) {
    var func = typeof funcOrMethod == 'string'
                ? function(act) { act[funcOrMethod](); }
                : funcOrMethod;

    this.actions.forEach(func, thisArg || this);
}


function ActionsHistory$eachReverse(funcOrMethod, thisArg) {
    this.actions.reverse();
    this.each(funcOrMethod, thisArg);
    this.actions.reverse();
}


function ActionsHistory$getLastAction() {
    return this.position && this.actions[this.position - 1];
}


function ActionsHistory$getDescription() {
    var actions = this.actions.map(function(act) {
        return act.getDescription();
    });
    return {
        actions: actions,
        position: this.position,
        length: actions.length
    };
}