Implemented undo function
This commit is contained in:
parent
6fe66a1358
commit
3f9384e727
|
@ -7,6 +7,8 @@ goog.provide('ascii');
|
||||||
/** @const */ var MAX_GRID_SIZE = 1000;
|
/** @const */ var MAX_GRID_SIZE = 1000;
|
||||||
/** @const */ var SPECIAL_VALUE = '+';
|
/** @const */ var SPECIAL_VALUE = '+';
|
||||||
|
|
||||||
|
/** @const */ var MAX_UNDO = 50;
|
||||||
|
|
||||||
/** @const */ var SPECIAL_LINE_H = '\u2014';
|
/** @const */ var SPECIAL_LINE_H = '\u2014';
|
||||||
/** @const */ var SPECIAL_LINE_V = '|';
|
/** @const */ var SPECIAL_LINE_V = '|';
|
||||||
|
|
||||||
|
@ -130,3 +132,23 @@ ascii.CellContext = function(left, right, up, down) {
|
||||||
ascii.CellContext.prototype.sum = function() {
|
ascii.CellContext.prototype.sum = function() {
|
||||||
return this.left + this.right + this.up + this.down;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ ascii.Controller.prototype.handleKeyDown = function(event) {
|
||||||
if (event.ctrlKey || event.metaKey) {
|
if (event.ctrlKey || event.metaKey) {
|
||||||
if (event.keyCode == 67) { specialKeyCode = KEY_COPY; }
|
if (event.keyCode == 67) { specialKeyCode = KEY_COPY; }
|
||||||
if (event.keyCode == 86) { specialKeyCode = KEY_PASTE; }
|
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 == 89) { this.state.redo(); }
|
||||||
if (event.keyCode == 88) { specialKeyCode = KEY_CUT; }
|
if (event.keyCode == 88) { specialKeyCode = KEY_CUT; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
ascii.State = function() {
|
ascii.State = function() {
|
||||||
/** @type {Array.<Array.<ascii.Cell>>} */
|
/** @type {Array.<Array.<ascii.Cell>>} */
|
||||||
this.cells = new Array(MAX_GRID_SIZE);
|
this.cells = new Array(MAX_GRID_SIZE);
|
||||||
/** @type {Array.<ascii.Cell>} */
|
/** @type {Array.<ascii.MappedCell>} */
|
||||||
this.scratchCells = new Array();
|
this.scratchCells = new Array();
|
||||||
|
|
||||||
|
/** @type {Array.<Array.<ascii.MappedValue>>} */
|
||||||
|
this.undoStates = new Array();
|
||||||
|
|
||||||
for (var i = 0; i < this.cells.length; i++) {
|
for (var i = 0; i < this.cells.length; i++) {
|
||||||
this.cells[i] = new Array(MAX_GRID_SIZE);
|
this.cells[i] = new Array(MAX_GRID_SIZE);
|
||||||
for (var j = 0; j < this.cells[i].length; j++) {
|
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) {
|
ascii.State.prototype.drawValue = function(position, value) {
|
||||||
var cell = this.getCell(position);
|
var cell = this.getCell(position);
|
||||||
this.scratchCells.push(cell);
|
this.scratchCells.push(new ascii.MappedCell(position, cell));
|
||||||
cell.scratchValue = value;
|
cell.scratchValue = value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,7 +59,7 @@ ascii.State.prototype.drawValue = function(position, value) {
|
||||||
*/
|
*/
|
||||||
ascii.State.prototype.clearDraw = function() {
|
ascii.State.prototype.clearDraw = function() {
|
||||||
for (var i in this.scratchCells) {
|
for (var i in this.scratchCells) {
|
||||||
this.scratchCells[i].scratchValue = null;
|
this.scratchCells[i].cell.scratchValue = null;
|
||||||
}
|
}
|
||||||
this.scratchCells.length = 0;
|
this.scratchCells.length = 0;
|
||||||
};
|
};
|
||||||
|
@ -103,16 +106,54 @@ ascii.State.prototype.getContext = function(position) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ends the current draw, commiting anything currently drawn the scratchpad.
|
* Ends the current draw, commiting anything currently drawn the scratchpad.
|
||||||
|
* @param {boolean=} opt_skipSave
|
||||||
*/
|
*/
|
||||||
ascii.State.prototype.commitDraw = function() {
|
ascii.State.prototype.commitDraw = function(opt_skipSave) {
|
||||||
for (var i in this.scratchCells) {
|
var oldValues = [];
|
||||||
var newValue = this.scratchCells[i].getRawValue();
|
|
||||||
|
// 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.
|
// Cheeky little hack for making erase play nicely.
|
||||||
if (newValue == ' ') {
|
if (newValue == ' ') {
|
||||||
newValue = null;
|
newValue = null;
|
||||||
}
|
}
|
||||||
this.scratchCells[i].scratchValue = null;
|
cell.scratchValue = null;
|
||||||
this.scratchCells[i].value = newValue;
|
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);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue