Store single-line deltas as .text instead of .lines in undo history

Stores single-line delta content as .text instead of .lines in undo
history. This is done without modifying the original delta object in
case the caller still retains a handle to the original.
This commit is contained in:
aldendaniels 2014-01-11 14:43:47 -06:00
commit ddd695ee3f

View file

@ -61,14 +61,19 @@ var UndoManager = function() {
* *
**/ **/
this.execute = function(options) { this.execute = function(options) {
var deltas = options.args[0];
// Normalize deltas for storage.
var deltaSets = this.$serializeDeltas(options.args[0]);
// Add deltas to undo stack.
this.$doc = options.args[1]; this.$doc = options.args[1];
if (options.merge && this.hasUndo()){ if (options.merge && this.hasUndo()){
deltas = this.$undoStack.pop().concat(deltas); deltaSets = this.$undoStack.pop().concat(deltaSets);
} }
this.$undoStack.push(deltas); this.$undoStack.push(deltaSets);
// Reset redo stack.
this.$redoStack = []; this.$redoStack = [];
if (this.dirtyCounter < 0) { if (this.dirtyCounter < 0) {
// The user has made a change after undoing past the last clean state. // The user has made a change after undoing past the last clean state.
// We can never get back to a clean state now until markClean() is called. // We can never get back to a clean state now until markClean() is called.
@ -85,12 +90,11 @@ var UndoManager = function() {
* @returns {Range} The range of the undo. * @returns {Range} The range of the undo.
**/ **/
this.undo = function(dontSelect) { this.undo = function(dontSelect) {
var deltas = this.$undoStack.pop(); var deltaSets = this.$undoStack.pop();
var undoSelectionRange = null; var undoSelectionRange = null;
if (deltas) { if (deltaSets) {
undoSelectionRange = undoSelectionRange = this.$doc.undoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
this.$doc.undoChanges(deltas, dontSelect); this.$redoStack.push(deltaSets);
this.$redoStack.push(deltas);
this.dirtyCounter--; this.dirtyCounter--;
} }
@ -104,15 +108,14 @@ var UndoManager = function() {
* *
**/ **/
this.redo = function(dontSelect) { this.redo = function(dontSelect) {
var deltas = this.$redoStack.pop(); var deltaSets = this.$redoStack.pop();
var redoSelectionRange = null; var redoSelectionRange = null;
if (deltas) { if (deltaSets) {
redoSelectionRange = redoSelectionRange =
this.$doc.redoChanges(deltas, dontSelect); this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
this.$undoStack.push(deltas); this.$undoStack.push(deltaSets);
this.dirtyCounter++; this.dirtyCounter++;
} }
return redoSelectionRange; return redoSelectionRange;
}; };
@ -160,7 +163,54 @@ var UndoManager = function() {
this.isClean = function() { this.isClean = function() {
return this.dirtyCounter === 0; return this.dirtyCounter === 0;
}; };
// Serializes deltaSets to reduce memory usage.
this.$serializeDeltas = function(deltaSets)
{
return this.$cloneDeltaSetsObj(deltaSets, $serializeDelta);
}
function $serializeDelta(delta){
return {
action: delta.action,
range: delta.range,
lines: (delta.lines.length == 1 ? null : delta.lines),
text: (delta.lines.length == 1 ? delta.lines[0] : null ),
};
}
// Deserializes deltaSets to allow application to the document.
this.$deserializeDeltas = function(deltaSets)
{
return this.$cloneDeltaSetsObj(deltaSets, $deserializeDelta);
}
function $deserializeDelta(delta){
return {
action: delta.action,
range: delta.range,
lines: (delta.text === null ? delta.lines : [delta.text])
};
}
// Helper for delta serialization and deserialization.
this.$cloneDeltaSetsObj = function(deltaSets_old, fnGetModifiedDelta)
{
var deltaSets_new = new Array(deltaSets_old.length);
for (var i in deltaSets_old)
{
var deltaSet_old = deltaSets_old[i];
var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)};
for (var i_ in deltaSet_old.deltas)
{
var delta_old = deltaSet_old.deltas[i_];
deltaSet_new.deltas[i_] = fnGetModifiedDelta(delta_old);
}
deltaSets_new[i] = deltaSet_new;
}
return deltaSets_new;
}
}).call(UndoManager.prototype); }).call(UndoManager.prototype);
exports.UndoManager = UndoManager; exports.UndoManager = UndoManager;