piskel/src/js/service/HistoryService.js

117 lines
3.7 KiB
JavaScript
Raw Normal View History

(function () {
2014-04-17 03:27:49 +04:00
var ns = $.namespace('pskl.service');
var SNAPSHOT_PERIOD = 50;
var LOAD_STATE_INTERVAL = 50;
2014-04-17 03:27:49 +04:00
ns.HistoryService = function (piskelController) {
this.piskelController = piskelController;
2014-04-17 03:27:49 +04:00
this.stateQueue = [];
this.currentIndex = -1;
2013-12-11 00:25:36 +04:00
this.saveState__b = this.saveState.bind(this);
2014-04-17 03:27:49 +04:00
this.lastLoadState = -1;
};
ns.HistoryService.prototype.init = function () {
2014-04-17 03:27:49 +04:00
$.subscribe(Events.PISKEL_SAVE_STATE, this.saveState__b);
pskl.app.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
};
2014-04-17 03:27:49 +04:00
ns.HistoryService.prototype.saveState = function (evt, actionInfo) {
this.stateQueue = this.stateQueue.slice(0, this.currentIndex + 1);
this.currentIndex = this.currentIndex + 1;
var state = {
action : actionInfo,
frameIndex : this.piskelController.currentFrameIndex,
layerIndex : this.piskelController.currentLayerIndex
};
if (actionInfo.type === 'FULL' || this.currentIndex % SNAPSHOT_PERIOD === 0) {
state.piskel = this.piskelController.serialize(false);
}
this.stateQueue.push(state);
};
2012-09-16 15:10:05 +04:00
ns.HistoryService.prototype.undo = function () {
this.loadState(this.currentIndex - 1);
};
2012-09-16 15:10:05 +04:00
ns.HistoryService.prototype.redo = function () {
this.loadState(this.currentIndex + 1);
2014-04-17 03:27:49 +04:00
};
ns.HistoryService.prototype.loadState = function (index) {
if (this.isLoadStateAllowed_(index)) {
this.lastLoadState = Date.now();
var snapshotIndex = this.getPreviousSnapshotIndex_(index);
if (snapshotIndex < 0) {
throw 'Could not find previous SNAPSHOT saved in history stateQueue';
2014-04-17 03:27:49 +04:00
}
var serializedPiskel = this.stateQueue[snapshotIndex].piskel;
2014-04-17 03:27:49 +04:00
if (typeof serializedPiskel === "string") {
this.stateQueue[snapshotIndex].piskel = JSON.parse(serializedPiskel);
serializedPiskel = this.stateQueue[snapshotIndex].piskel;
}
2014-04-17 03:27:49 +04:00
this.loadPiskel(serializedPiskel, this.onPiskelLoadedCallback.bind(this, index, snapshotIndex));
2014-04-17 03:27:49 +04:00
}
};
ns.HistoryService.prototype.isLoadStateAllowed_ = function (index) {
var timeOk = (Date.now() - this.lastLoadState) > LOAD_STATE_INTERVAL;
var indexInRange = index >= 0 && index < this.stateQueue.length;
return timeOk && indexInRange;
};
2014-04-17 03:27:49 +04:00
ns.HistoryService.prototype.getPreviousSnapshotIndex_ = function (index) {
while (this.stateQueue[index] && !this.stateQueue[index].piskel) {
index = index - 1;
}
return index;
2014-04-17 03:27:49 +04:00
};
ns.HistoryService.prototype.onPiskelLoadedCallback = function (index, snapshotIndex, piskel) {
for (var i = snapshotIndex + 1 ; i <= index ; i++) {
var state = this.stateQueue[i];
this.setupState(state);
2014-04-17 03:27:49 +04:00
this.replayState(state);
}
var lastState = this.stateQueue[index];
this.setupState(lastState);
this.currentIndex = index;
$.publish(Events.PISKEL_RESET);
2014-04-17 03:27:49 +04:00
};
ns.HistoryService.prototype.setupState = function (state) {
this.piskelController.setCurrentFrameIndex(state.frameIndex);
this.piskelController.setCurrentLayerIndex(state.layerIndex);
};
2014-04-17 03:27:49 +04:00
ns.HistoryService.prototype.loadPiskel = function (piskel, callback) {
var descriptor = this.piskelController.piskel.getDescriptor();
pskl.utils.serialization.Deserializer.deserialize(piskel, function (piskel) {
piskel.setDescriptor(descriptor);
2014-04-19 22:19:24 +04:00
this.piskelController.setPiskel(piskel);
2014-04-17 03:27:49 +04:00
callback(piskel);
2014-04-19 22:19:24 +04:00
}.bind(this));
2014-04-17 03:27:49 +04:00
};
ns.HistoryService.prototype.replayState = function (state) {
var action = state.action;
var type = action.type;
var layer = this.piskelController.getLayerAt(state.layerIndex);
var frame = layer.getFrameAt(state.frameIndex);
action.scope.replay(frame, action.replay);
};
})();