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:
parent
f59708a5ba
commit
ddd695ee3f
1 changed files with 65 additions and 15 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue