kopia lustrzana https://github.com/c9/core
use the new undoManager in ace.js
rodzic
c9f492a916
commit
caad98e5d2
|
@ -260,10 +260,10 @@ var EditSession = function(text, mode) {
|
||||||
this.$undoManager.add({
|
this.$undoManager.add({
|
||||||
action: "removeFolds",
|
action: "removeFolds",
|
||||||
folds: removedFolds
|
folds: removedFolds
|
||||||
}, this);
|
}, this.mergeUndoDeltas);
|
||||||
this.mergeUndoDeltas = true;
|
this.mergeUndoDeltas = true;
|
||||||
}
|
}
|
||||||
this.$undoManager.add(delta, this);
|
this.$undoManager.add(delta, this.mergeUndoDeltas);
|
||||||
this.mergeUndoDeltas = true;
|
this.mergeUndoDeltas = true;
|
||||||
|
|
||||||
this.$informUndoManager.schedule();
|
this.$informUndoManager.schedule();
|
||||||
|
@ -376,7 +376,7 @@ var EditSession = function(text, mode) {
|
||||||
|
|
||||||
if (undoManager) {
|
if (undoManager) {
|
||||||
var self = this;
|
var self = this;
|
||||||
undoManager.$session = this;
|
undoManager.setSession(this);
|
||||||
this.$syncInformUndoManager = function() {
|
this.$syncInformUndoManager = function() {
|
||||||
self.$informUndoManager.cancel();
|
self.$informUndoManager.cancel();
|
||||||
self.mergeUndoDeltas = false;
|
self.mergeUndoDeltas = false;
|
||||||
|
@ -402,6 +402,7 @@ var EditSession = function(text, mode) {
|
||||||
add: function() {},
|
add: function() {},
|
||||||
addSelection: function() {},
|
addSelection: function() {},
|
||||||
startNewGroup: function() {},
|
startNewGroup: function() {},
|
||||||
|
setSession: function() {},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,11 +44,15 @@ define(function(require, exports, module) {
|
||||||
var UndoManager = function() {
|
var UndoManager = function() {
|
||||||
this.$maxRev = 0;
|
this.$maxRev = 0;
|
||||||
this.mark = 0;
|
this.mark = 0;
|
||||||
|
this.$fromUndo = false;
|
||||||
this.reset();
|
this.reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
this.setSession = function(session) {
|
||||||
|
this.$session = session;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Provides a means for implementing your own undo manager. `options` has one property, `args`, an [[Array `Array`]], with two elements:
|
* Provides a means for implementing your own undo manager. `options` has one property, `args`, an [[Array `Array`]], with two elements:
|
||||||
*
|
*
|
||||||
|
@ -58,8 +62,9 @@ var UndoManager = function() {
|
||||||
* @param {Object} options Contains additional properties
|
* @param {Object} options Contains additional properties
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
this.add = function(delta) {
|
this.add = function(delta, allowMerge) {
|
||||||
if (this.$session.mergeUndoDeltas === false || !this.lastDeltas) {
|
if (this.$fromUndo) return;
|
||||||
|
if (allowMerge === false || !this.lastDeltas) {
|
||||||
this.lastDeltas = [];
|
this.lastDeltas = [];
|
||||||
this.$undoStack.push(this.lastDeltas);
|
this.$undoStack.push(this.lastDeltas);
|
||||||
delta.id = this.$rev = ++this.$maxRev;
|
delta.id = this.$rev = ++this.$maxRev;
|
||||||
|
@ -84,10 +89,10 @@ var UndoManager = function() {
|
||||||
var stack = this.$undoStack;
|
var stack = this.$undoStack;
|
||||||
for (var i = stack.length; i--;) {
|
for (var i = stack.length; i--;) {
|
||||||
var delta = stack[i][0];
|
var delta = stack[i][0];
|
||||||
if (delta.id < to)
|
|
||||||
delta.ignore = true;
|
|
||||||
if (delta.id <= from)
|
if (delta.id <= from)
|
||||||
break;
|
break;
|
||||||
|
if (delta.id < to)
|
||||||
|
delta.ignore = true;
|
||||||
}
|
}
|
||||||
this.lastDeltas = null;
|
this.lastDeltas = null;
|
||||||
};
|
};
|
||||||
|
@ -125,10 +130,12 @@ var UndoManager = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getChangedRanges = function(from, to) {
|
this.getChangedRanges = function(from, to) {
|
||||||
|
if (to == null) to = this.$rev + 1;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getChangedLines = function(from, to) {
|
this.getChangedLines = function(from, to) {
|
||||||
|
if (to == null) to = this.$rev + 1;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,18 +148,24 @@ var UndoManager = function() {
|
||||||
this.undo = function(dontSelect) {
|
this.undo = function(dontSelect) {
|
||||||
this.lastDeltas = null;
|
this.lastDeltas = null;
|
||||||
var stack = this.$undoStack;
|
var stack = this.$undoStack;
|
||||||
findDelta(stack, stack.length);
|
|
||||||
|
if (!rearrangeUndoStack(stack, stack.length))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.$redoStackBaseRev !== this.$rev && this.$redoStack.length)
|
||||||
|
this.$redoStack = [];
|
||||||
|
|
||||||
|
this.$fromUndo = true;
|
||||||
|
|
||||||
var deltaSet = stack.pop();
|
var deltaSet = stack.pop();
|
||||||
var undoSelectionRange = null;
|
var undoSelectionRange = null;
|
||||||
if (deltaSet && deltaSet.length) {
|
if (deltaSet && deltaSet.length) {
|
||||||
var id = deltaSet[0].id;
|
|
||||||
undoSelectionRange = this.$session.undoChanges(deltaSet, dontSelect);
|
undoSelectionRange = this.$session.undoChanges(deltaSet, dontSelect);
|
||||||
if (this.$redoStackBaseRev !== id) {
|
|
||||||
this.$redoStack = [];
|
|
||||||
}
|
|
||||||
this.$redoStack.push(deltaSet);
|
this.$redoStack.push(deltaSet);
|
||||||
this.$syncRev();
|
this.$syncRev();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$fromUndo = false;
|
||||||
|
|
||||||
return undoSelectionRange;
|
return undoSelectionRange;
|
||||||
};
|
};
|
||||||
|
@ -164,6 +177,8 @@ var UndoManager = function() {
|
||||||
**/
|
**/
|
||||||
this.redo = function(dontSelect) {
|
this.redo = function(dontSelect) {
|
||||||
this.lastDeltas = null;
|
this.lastDeltas = null;
|
||||||
|
|
||||||
|
this.$fromUndo = true;
|
||||||
if (this.$redoStackBaseRev != this.$rev) {
|
if (this.$redoStackBaseRev != this.$rev) {
|
||||||
var diff = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1);
|
var diff = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1);
|
||||||
rebaseRedoStack(this.$redoStack, diff);
|
rebaseRedoStack(this.$redoStack, diff);
|
||||||
|
@ -180,13 +195,15 @@ var UndoManager = function() {
|
||||||
this.$undoStack.push(deltaSet);
|
this.$undoStack.push(deltaSet);
|
||||||
this.$syncRev();
|
this.$syncRev();
|
||||||
}
|
}
|
||||||
|
this.$fromUndo = false;
|
||||||
|
|
||||||
return redoSelectionRange;
|
return redoSelectionRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$syncRev = function() {
|
this.$syncRev = function() {
|
||||||
var stack = this.$undoStack;
|
var stack = this.$undoStack;
|
||||||
var nextDelta = stack[stack.length - 1];
|
var nextDelta = stack[stack.length - 1];
|
||||||
var id = nextDelta && nextDelta[0].id || 0;
|
var id = nextDelta && nextDelta[0] && nextDelta[0].id || 0;
|
||||||
this.$redoStackBaseRev = id;
|
this.$redoStackBaseRev = id;
|
||||||
this.$rev = id;
|
this.$rev = id;
|
||||||
};
|
};
|
||||||
|
@ -202,11 +219,12 @@ var UndoManager = function() {
|
||||||
this.selections = [];
|
this.selections = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns `true` if there are undo operations left to perform.
|
* Returns `true` if there are undo operations left to perform.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
**/
|
**/
|
||||||
this.hasUndo = function() {
|
this.canUndo = function() {
|
||||||
return this.$undoStack.length > 0;
|
return this.$undoStack.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -214,15 +232,14 @@ var UndoManager = function() {
|
||||||
* Returns `true` if there are redo operations left to perform.
|
* Returns `true` if there are redo operations left to perform.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
**/
|
**/
|
||||||
this.hasRedo = function() {
|
this.canRedo = function() {
|
||||||
return this.$redoStack.length > 0;
|
return this.$redoStack.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the current status clean
|
* Marks the current status clean
|
||||||
**/
|
**/
|
||||||
this.bookmark =
|
this.bookmark = function(rev) {
|
||||||
this.markClean = function(rev) {
|
|
||||||
if (rev == undefined)
|
if (rev == undefined)
|
||||||
rev = this.$rev;
|
rev = this.$rev;
|
||||||
this.mark = rev;
|
this.mark = rev;
|
||||||
|
@ -232,14 +249,26 @@ var UndoManager = function() {
|
||||||
* Returns if the current status is clean
|
* Returns if the current status is clean
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
**/
|
**/
|
||||||
this.isClean = function() {
|
this.isAtBookmark = function() {
|
||||||
return this.$rev === this.mark;
|
return this.$rev === this.mark;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.toJSON = function() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.fromJSON = function() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hasUndo = this.canUndo;
|
||||||
|
this.hasRedo = this.canRedo;
|
||||||
|
this.isClean = this.isAtBookmark;
|
||||||
|
this.markClean = this.bookmark;
|
||||||
|
|
||||||
}).call(UndoManager.prototype);
|
}).call(UndoManager.prototype);
|
||||||
|
|
||||||
function findDelta(stack, pos) {
|
function rearrangeUndoStack(stack, pos) {
|
||||||
for (var i = pos; i--; ) {
|
for (var i = pos; i--; ) {
|
||||||
var deltaSet = stack[i];
|
var deltaSet = stack[i];
|
||||||
if (deltaSet && !deltaSet[0].ignore) {
|
if (deltaSet && !deltaSet[0].ignore) {
|
||||||
|
@ -249,7 +278,7 @@ function findDelta(stack, pos) {
|
||||||
stack[i + 1] = swapped[1];
|
stack[i + 1] = swapped[1];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,14 +282,24 @@ define(function(require, exports, module) {
|
||||||
/***** Undo Manager *****/
|
/***** Undo Manager *****/
|
||||||
|
|
||||||
function AceUndoManager(undoManager, session) {
|
function AceUndoManager(undoManager, session) {
|
||||||
|
var state = undoManager.getState();
|
||||||
this.$session = session;
|
this.$session = session;
|
||||||
this.$undo = undoManager;
|
this.$undo = undoManager;
|
||||||
this.$aceUndo = new UndoManager();
|
this.$aceUndo = new UndoManager();
|
||||||
var _self = this;
|
this.$aceUndo.c9UndoProxy = undoManager;
|
||||||
var Item = this.Item;
|
undoManager.$aceUndo = this.$aceUndo;
|
||||||
this.$undo.on("itemFind", function(e) {
|
undoManager.add = this.add;
|
||||||
return Item(_self, e.state);
|
undoManager.addSelection = this.addSelection;
|
||||||
});
|
undoManager.undo = this.undo;
|
||||||
|
undoManager.redo = this.redo;
|
||||||
|
undoManager.reset = this.reset;
|
||||||
|
undoManager.canUndo = this.canUndo;
|
||||||
|
undoManager.canRedo = this.canRedo;
|
||||||
|
undoManager.getState = this.getState;
|
||||||
|
undoManager.setState = this.setState;
|
||||||
|
this._emit = undoManager.getEmitter();
|
||||||
|
|
||||||
|
undoManager.setState(state);
|
||||||
}
|
}
|
||||||
function updateDeltas(deltas) {
|
function updateDeltas(deltas) {
|
||||||
if (deltas[0] && deltas[0].deltas) {
|
if (deltas[0] && deltas[0].deltas) {
|
||||||
|
@ -299,81 +309,74 @@ define(function(require, exports, module) {
|
||||||
deltas.push.apply(deltas, x.deltas);
|
deltas.push.apply(deltas, x.deltas);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return deltas;
|
||||||
}
|
}
|
||||||
AceUndoManager.prototype = {
|
AceUndoManager.prototype = {
|
||||||
rebase: function() {
|
|
||||||
var pos = this.$undo.position + 2;
|
|
||||||
var stack = this.$undo.stack;
|
|
||||||
for (var i = pos; i--; ) {
|
|
||||||
var deltaSet = stack[i].deltas;
|
|
||||||
if (deltaSet[0] && !deltaSet[0].disabled) {
|
|
||||||
while(i < pos - 1) {
|
|
||||||
var swapped = UndoManager.swapGroups(stack[i].deltas, stack[i + 1].deltas);
|
|
||||||
stack[i].deltas = swapped[0];
|
|
||||||
stack[i + 1].deltas = swapped[1];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
deltaSet = stack[pos - 1].deltas;
|
|
||||||
if (deltaSet[0].disabled)
|
|
||||||
deltaSet[0].disabled = false;
|
|
||||||
return deltaSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Item: function(_self, deltas) {
|
|
||||||
return {
|
|
||||||
deltas: deltas,
|
|
||||||
undo: function(){
|
|
||||||
updateDeltas(this.deltas); // change to the new format
|
|
||||||
var deltas = _self.rebase();
|
|
||||||
if (!deltas)
|
|
||||||
return false;
|
|
||||||
_self.$session.session.undoChanges(deltas, _self.dontSelect);
|
|
||||||
},
|
|
||||||
redo: function(){
|
|
||||||
updateDeltas(this.deltas);
|
|
||||||
_self.$session.session.redoChanges(this.deltas, _self.dontSelect);
|
|
||||||
},
|
|
||||||
getState: function(){
|
|
||||||
updateDeltas(this.deltas);
|
|
||||||
return this.deltas.filter(function (d) {
|
|
||||||
return d.action == "insert" || d.action == "remove";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
add: function(delta, doc) {
|
add: function(delta, doc) {
|
||||||
if (doc.mergeUndoDeltas === false || !this.lastDeltas) {
|
this.$aceUndo.add(delta, doc);
|
||||||
this.lastDeltas = [];
|
this._emit("change");
|
||||||
this.$undo.add(this.Item(this, this.lastDeltas));
|
},
|
||||||
}
|
addSelection: function(range, rev) {
|
||||||
this.lastDeltas.push(delta);
|
this.$aceUndo.addSelection(range, rev);
|
||||||
},
|
},
|
||||||
|
|
||||||
undo: function(dontSelect) {
|
undo: function(dontSelect) {
|
||||||
this.dontSelect = dontSelect;
|
this.$aceUndo.undo(dontSelect);
|
||||||
this.lastDeltas = null;
|
this._emit("change");
|
||||||
this.$undo.undo();
|
|
||||||
},
|
},
|
||||||
redo: function(dontSelect) {
|
redo: function(dontSelect) {
|
||||||
this.dontSelect = dontSelect;
|
this.$aceUndo.redo(dontSelect);
|
||||||
this.lastDeltas = null;
|
this._emit("change");
|
||||||
this.$undo.redo();
|
|
||||||
},
|
},
|
||||||
reset: function(){
|
reset: function(){
|
||||||
this.lastDeltas = null;
|
this.$aceUndo.reset();
|
||||||
this.$undo.reset();
|
this._emit("change");
|
||||||
},
|
},
|
||||||
hasUndo: function() {
|
canUndo: function() {
|
||||||
return this.$undo.length > this.$undo.position + 1;
|
return this.$aceUndo.canUndo();
|
||||||
},
|
},
|
||||||
hasRedo: function() {
|
canRedo: function() {
|
||||||
return this.$undo.length <= this.$undo.position + 1;
|
return this.$aceUndo.canRedo();
|
||||||
},
|
},
|
||||||
get $undoStack() {
|
clearUndo: function() {
|
||||||
return this.$undo.stack.slice(0, this.$undo.position + 1)
|
this.$aceUndo.$undoStack = [];
|
||||||
.map(function(e){ return e.getState ? e.getState() : e });
|
this._emit("change");
|
||||||
|
},
|
||||||
|
clearRedo: function() {
|
||||||
|
this.$aceUndo.$redoStack = [];
|
||||||
|
this._emit("change");
|
||||||
|
},
|
||||||
|
getState: function() {
|
||||||
|
console.log("getState()");
|
||||||
|
var aceUndo = this.$aceUndo;
|
||||||
|
var stack = aceUndo.$undoStack.map(function(deltaSet) {
|
||||||
|
return deltaSet.filter(function (d) {
|
||||||
|
return d.action == "insert" || d.action == "remove";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
stack: stack,
|
||||||
|
mark: aceUndo.mark,
|
||||||
|
position: aceUndo.$rev
|
||||||
|
};
|
||||||
|
},
|
||||||
|
setState: function(e) {
|
||||||
|
console.log("setState()");
|
||||||
|
var aceUndo = this.$aceUndo;
|
||||||
|
aceUndo.$undoStack = (e.stack || []).filter(function(x) {
|
||||||
|
return x.length;
|
||||||
|
});
|
||||||
|
aceUndo.$rev = e.position;
|
||||||
|
this.bookmark(e.mark);
|
||||||
|
},
|
||||||
|
isAtBookmark: function() {
|
||||||
|
return this.$aceUndo.isAtBookmark();
|
||||||
|
},
|
||||||
|
bookmark: function(index) {
|
||||||
|
this.$aceUndo.bookmark(index);
|
||||||
|
this._emit("change");
|
||||||
|
},
|
||||||
|
setSession: function(session) {
|
||||||
|
this.$aceUndo.setSession(session);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -383,9 +386,19 @@ define(function(require, exports, module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
this.execute = function(options) {
|
this.add = function(delta, doc) {
|
||||||
this.$u.execute(options);
|
this.$u.add(delta, doc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(this, "", {
|
||||||
|
configurable: true,
|
||||||
|
get: function() {
|
||||||
|
return this.$u.lastDeltas;
|
||||||
|
},
|
||||||
|
set: function(v) {
|
||||||
|
this.$u.lastDeltas = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.undo = function() {
|
this.undo = function() {
|
||||||
var selectionRange = this.$u.undo(true);
|
var selectionRange = this.$u.undo(true);
|
||||||
|
@ -1410,7 +1423,7 @@ define(function(require, exports, module) {
|
||||||
undoManager = session.getUndoManager();
|
undoManager = session.getUndoManager();
|
||||||
if (undoManager) {
|
if (undoManager) {
|
||||||
var undoManagerProxy = new UndoManagerProxy(undoManager, s);
|
var undoManagerProxy = new UndoManagerProxy(undoManager, s);
|
||||||
s.setUndoManager(undoManagerProxy);
|
s.setUndoManager(undoManagerProxy.$aceUndo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite the default $informUndoManager function such that new deltas
|
// Overwrite the default $informUndoManager function such that new deltas
|
||||||
|
@ -2211,9 +2224,9 @@ define(function(require, exports, module) {
|
||||||
var c9Session = doc.getSession();
|
var c9Session = doc.getSession();
|
||||||
|
|
||||||
// if load starts from another editor type
|
// if load starts from another editor type
|
||||||
// tabmanager will show as instantly
|
// tabmanager will show us instantly
|
||||||
// so we need to show progress bar instantly
|
// so we need to show progress bar instantly
|
||||||
progress.noFadeIn = !currentDocument;
|
progress.noFadeIn = !currentDocument || !currentDocument.tab.active;
|
||||||
|
|
||||||
// Value Retrieval
|
// Value Retrieval
|
||||||
doc.on("getValue", function get(e) {
|
doc.on("getValue", function get(e) {
|
||||||
|
|
|
@ -150,6 +150,8 @@ define(function(require, module, exports) {
|
||||||
emit("change");
|
emit("change");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin.freezePublicAPI.baseclass();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Undo Manager class of Cloud9. Each {@link Document}
|
* The Undo Manager class of Cloud9. Each {@link Document}
|
||||||
* has a single instance of the undo manager that
|
* has a single instance of the undo manager that
|
||||||
|
@ -212,10 +214,6 @@ define(function(require, module, exports) {
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
plugin.freezePublicAPI({
|
plugin.freezePublicAPI({
|
||||||
/**
|
|
||||||
* @ignore
|
|
||||||
*/
|
|
||||||
get stack() { return stack; },
|
|
||||||
/**
|
/**
|
||||||
* The number of items on the stack. This number will stay the
|
* The number of items on the stack. This number will stay the
|
||||||
* same when using {@link UndoManager#undo} and
|
* same when using {@link UndoManager#undo} and
|
||||||
|
|
Ładowanie…
Reference in New Issue