Mercurial > hg > dml-open-vis
view src/DML/MainVisBundle/Resources/assets/marionette/modules/ContextModule/ContextModule.30-StateHistory.js @ 1:f38015048f48 tip
Added GPL
author | Daniel Wolff |
---|---|
date | Sat, 13 Feb 2016 20:43:38 +0100 |
parents | 493bcb69166c |
children |
line wrap: on
line source
"use strict"; App.module("ContextModule", function(ContextModule, App, Backbone, Marionette, $, _, Logger) { // Define private variables var logger = null; ContextModule.addInitializer(function(options){ // logger = Logger.get("ContextModule.StateBookmark"); // logger.setLevel(Logger.DEBUG); /** * StateHistory stores a history of a serialized state * and provides an API to switch between these states * * A user simply updates the value of currentSerializedState attribute * and calls undo(), redo() or reset() to move along the history * There is no direct access to undo and redo stacks, but it is possible * to know about them by calling canUndo() and canRedo() * * serialize / unserialize deal with the object of the following structure * { * undoStack: [{recent}, {less recent}, ... {the oldest}] * redoStack: [{next}, {the following}, ... {the last}] * currentSerializedState: {} * } * * attribute compoundChangeDetector is a function that helps decide if the changes between * the given three serialized states can be treated as a single change. * This is needed to avoid too many undo states on simple actions like text typing * compoundChangeDetector returns true if the change between the first, the second * and the third object can be considered as a single compound change * (i.e. there is no need to create an extra undo action) */ ContextModule.StateHistory = Backbone.Model.extend({ defaults: { maxStackSize: 50, currentSerializedState: undefined, compoundChangeDetector: undefined }, _NONE: 0, _UNDO: 1, _REDO: 2, _UNSERIALIZE: 3, /** * @memberOf App.ContextModule.StateBookmark */ initialize: function() { this._undoStack = []; this._redoStack = []; this._currentSerializedStateChangeMode = this._NONE; this.on("change:maxStackSize", this._trimStacks, this); this.on("change:currentSerializedState", this._registerNewSerializedState, this); }, _registerNewSerializedState: function() { var previousSerialisedState = this.previous("currentSerializedState"); if (this._currentSerializedStateChangeMode == this._UNDO) { this._redoStack.unshift(previousSerialisedState); } else if (this._currentSerializedStateChangeMode == this._REDO) { this._undoStack.unshift(previousSerialisedState); } else if (this._currentSerializedStateChangeMode == this._UNSERIALIZE) { } else { if (!_.isEqual(previousSerialisedState, this.attributes.currentSerializedState)) { if (this._undoStack.length == 0 || !_.isFunction(this.attributes.compoundChangeDetector) || !this.attributes.compoundChangeDetector.call(currentSerializedState, previousSerialisedState, this._undoStack[0])) { this._undoStack.unshift(previousSerialisedState); } this._redoStack = []; } } this._trimStacks(); }, getCurrentSerializedState: function() { }, undo: function() { if (this._undoStack.length) { this._currentSerializedStateChangeMode = this._UNDO; this.set("currentSerializedState", this._undoStack.shift()); this._currentSerializedStateChangeMode = this._NONE; } else { throw "Undo was called when undo stack was empty"; } }, redo: function() { if (this._redoStack.length) { this._currentSerializedStateChangeMode = this._REDO; this.set("currentSerializedState", this._redoStack.shift()); this._currentSerializedStateChangeMode = this._NONE; } else { throw "Redo was called when undo stack was empty"; } }, reset: function() { var stacksWereNotEmpty = this._undoStack.length || this._redoStack.length; this._undoStack = []; this._redoStack = []; if (stacksWereNotEmpty) { this.trigger("change"); } }, canUndo: function() { return !!this._undoStack.length; }, canRedo: function() { return !!this._redoStack.length; }, serialize: function() { // logger.debug("method called: StateHistory::serialize"); var result = { currentSerializedState: this.attributes.currentSerializedState, undoStack: _.clone(this._undoStack), redoStack: _.clone(this._redoStack), }; return result; }, unserialize: function(serializedAttributes) { this._currentSerializedStateChangeMode = this._UNSERIALIZE; var fixedSerializedAttributes = serializedAttributes; if (!_.isSimpleObject(serializedAttributes)) { fixedSerializedAttributes = {}; } this._undoStack = _.isArray(fixedSerializedAttributes.undoStack) ? fixedSerializedAttributes.undoStack : []; this._redoStack = _.isArray(fixedSerializedAttributes.redoStack) ? fixedSerializedAttributes.redoStack : []; this._trimStacks(); this.set("currentSerializedState", fixedSerializedAttributes.currentSerializedState); this._currentSerializedStateChangeMode = this._NONE; }, _trimStacks: function() { if (this._undoStack.length > this.attributes.maxStackSize) { this._undoStack = this._undoStack.slice(0, this.attributes.maxStackSize); } if (this._redoStack.length > this.attributes.maxStackSize) { this._redoStack = this._redoStack.slice(0, this.attributes.maxStackSize); } } }); }); }, Logger);