Implemented undo function

This commit is contained in:
Lewis Hemens 2014-01-21 22:34:56 +00:00
parent 6fe66a1358
commit 3f9384e727
3 changed files with 72 additions and 9 deletions

View File

@ -7,6 +7,8 @@ goog.provide('ascii');
/** @const */ var MAX_GRID_SIZE = 1000;
/** @const */ var SPECIAL_VALUE = '+';
/** @const */ var MAX_UNDO = 50;
/** @const */ var SPECIAL_LINE_H = '\u2014';
/** @const */ var SPECIAL_LINE_V = '|';
@ -130,3 +132,23 @@ ascii.CellContext = function(left, right, up, down) {
ascii.CellContext.prototype.sum = function() {
return this.left + this.right + this.up + this.down;
};
/**
* A pair of a vector and a string value. Used in history management.
* @constructor
* @struct
*/
ascii.MappedValue = function(position, value) {
this.position = position;
this.value = value;
}
/**
* A pair of a vector and a cell. Used in history management.
* @constructor
* @struct
*/
ascii.MappedCell = function(position, cell) {
this.position = position;
this.cell = cell;
}

View File

@ -217,7 +217,7 @@ ascii.Controller.prototype.handleKeyDown = function(event) {
if (event.ctrlKey || event.metaKey) {
if (event.keyCode == 67) { specialKeyCode = KEY_COPY; }
if (event.keyCode == 86) { specialKeyCode = KEY_PASTE; }
// if (event.keyCode == 90) { this.state.undo() }
if (event.keyCode == 90) { this.state.undo(); this.view.dirty = true; }
// if (event.keyCode == 89) { this.state.redo(); }
if (event.keyCode == 88) { specialKeyCode = KEY_CUT; }
}

View File

@ -7,9 +7,12 @@
ascii.State = function() {
/** @type {Array.<Array.<ascii.Cell>>} */
this.cells = new Array(MAX_GRID_SIZE);
/** @type {Array.<ascii.Cell>} */
/** @type {Array.<ascii.MappedCell>} */
this.scratchCells = new Array();
/** @type {Array.<Array.<ascii.MappedValue>>} */
this.undoStates = new Array();
for (var i = 0; i < this.cells.length; i++) {
this.cells[i] = new Array(MAX_GRID_SIZE);
for (var j = 0; j < this.cells[i].length; j++) {
@ -47,7 +50,7 @@ ascii.State.prototype.setValue = function(position, value) {
*/
ascii.State.prototype.drawValue = function(position, value) {
var cell = this.getCell(position);
this.scratchCells.push(cell);
this.scratchCells.push(new ascii.MappedCell(position, cell));
cell.scratchValue = value;
};
@ -56,7 +59,7 @@ ascii.State.prototype.drawValue = function(position, value) {
*/
ascii.State.prototype.clearDraw = function() {
for (var i in this.scratchCells) {
this.scratchCells[i].scratchValue = null;
this.scratchCells[i].cell.scratchValue = null;
}
this.scratchCells.length = 0;
};
@ -103,16 +106,54 @@ ascii.State.prototype.getContext = function(position) {
/**
* Ends the current draw, commiting anything currently drawn the scratchpad.
* @param {boolean=} opt_skipSave
*/
ascii.State.prototype.commitDraw = function() {
for (var i in this.scratchCells) {
var newValue = this.scratchCells[i].getRawValue();
ascii.State.prototype.commitDraw = function(opt_skipSave) {
var oldValues = [];
// Dedupe the scratch values, or this causes havoc for history management.
var positions = this.scratchCells.map(function (value) {
return value.position.x.toString() + value.position.y.toString();
});
var scratchCellsUnique = this.scratchCells.filter(function (value, index, arr) {
return positions.indexOf(positions[index]) == index;
});
this.scratchCells.length = 0;
for (var i in scratchCellsUnique) {
var position = scratchCellsUnique[i].position;
var cell = scratchCellsUnique[i].cell;
// Push the effective old value unto the array.
oldValues.push(new ascii.MappedValue(position, cell.value != null ? cell.value : ' '));
var newValue = cell.getRawValue();
// Cheeky little hack for making erase play nicely.
if (newValue == ' ') {
newValue = null;
}
this.scratchCells[i].scratchValue = null;
this.scratchCells[i].value = newValue;
cell.scratchValue = null;
cell.value = newValue;
}
// If we have too many undo states, clear one out.
if(this.undoStates.length > MAX_UNDO) {
this.undoStates.shift();
}
// Don't save a new state if we are undoing an old one.
if (!opt_skipSave && oldValues.length > 0) {
this.undoStates.push(oldValues);
}
};
ascii.State.prototype.undo = function() {
if (this.undoStates.length == 0) { return; }
var lastState = this.undoStates.pop();
for (var i in lastState) {
var mappedValue = lastState[i];
this.drawValue(mappedValue.position, mappedValue.value);
}
this.commitDraw(true);
};