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({
|
||||
action: "removeFolds",
|
||||
folds: removedFolds
|
||||
}, this);
|
||||
}, this.mergeUndoDeltas);
|
||||
this.mergeUndoDeltas = true;
|
||||
}
|
||||
this.$undoManager.add(delta, this);
|
||||
this.$undoManager.add(delta, this.mergeUndoDeltas);
|
||||
this.mergeUndoDeltas = true;
|
||||
|
||||
this.$informUndoManager.schedule();
|
||||
|
@ -376,7 +376,7 @@ var EditSession = function(text, mode) {
|
|||
|
||||
if (undoManager) {
|
||||
var self = this;
|
||||
undoManager.$session = this;
|
||||
undoManager.setSession(this);
|
||||
this.$syncInformUndoManager = function() {
|
||||
self.$informUndoManager.cancel();
|
||||
self.mergeUndoDeltas = false;
|
||||
|
@ -402,6 +402,7 @@ var EditSession = function(text, mode) {
|
|||
add: function() {},
|
||||
addSelection: function() {},
|
||||
startNewGroup: function() {},
|
||||
setSession: function() {},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,11 +44,15 @@ define(function(require, exports, module) {
|
|||
var UndoManager = function() {
|
||||
this.$maxRev = 0;
|
||||
this.mark = 0;
|
||||
this.$fromUndo = false;
|
||||
this.reset();
|
||||
};
|
||||
|
||||
(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:
|
||||
*
|
||||
|
@ -58,8 +62,9 @@ var UndoManager = function() {
|
|||
* @param {Object} options Contains additional properties
|
||||
*
|
||||
**/
|
||||
this.add = function(delta) {
|
||||
if (this.$session.mergeUndoDeltas === false || !this.lastDeltas) {
|
||||
this.add = function(delta, allowMerge) {
|
||||
if (this.$fromUndo) return;
|
||||
if (allowMerge === false || !this.lastDeltas) {
|
||||
this.lastDeltas = [];
|
||||
this.$undoStack.push(this.lastDeltas);
|
||||
delta.id = this.$rev = ++this.$maxRev;
|
||||
|
@ -84,10 +89,10 @@ var UndoManager = function() {
|
|||
var stack = this.$undoStack;
|
||||
for (var i = stack.length; i--;) {
|
||||
var delta = stack[i][0];
|
||||
if (delta.id < to)
|
||||
delta.ignore = true;
|
||||
if (delta.id <= from)
|
||||
break;
|
||||
if (delta.id < to)
|
||||
delta.ignore = true;
|
||||
}
|
||||
this.lastDeltas = null;
|
||||
};
|
||||
|
@ -125,10 +130,12 @@ var UndoManager = function() {
|
|||
};
|
||||
|
||||
this.getChangedRanges = function(from, to) {
|
||||
if (to == null) to = this.$rev + 1;
|
||||
|
||||
};
|
||||
|
||||
this.getChangedLines = function(from, to) {
|
||||
if (to == null) to = this.$rev + 1;
|
||||
|
||||
};
|
||||
|
||||
|
@ -141,18 +148,24 @@ var UndoManager = function() {
|
|||
this.undo = function(dontSelect) {
|
||||
this.lastDeltas = null;
|
||||
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 undoSelectionRange = null;
|
||||
if (deltaSet && deltaSet.length) {
|
||||
var id = deltaSet[0].id;
|
||||
undoSelectionRange = this.$session.undoChanges(deltaSet, dontSelect);
|
||||
if (this.$redoStackBaseRev !== id) {
|
||||
this.$redoStack = [];
|
||||
}
|
||||
this.$redoStack.push(deltaSet);
|
||||
this.$syncRev();
|
||||
}
|
||||
|
||||
this.$fromUndo = false;
|
||||
|
||||
return undoSelectionRange;
|
||||
};
|
||||
|
@ -164,6 +177,8 @@ var UndoManager = function() {
|
|||
**/
|
||||
this.redo = function(dontSelect) {
|
||||
this.lastDeltas = null;
|
||||
|
||||
this.$fromUndo = true;
|
||||
if (this.$redoStackBaseRev != this.$rev) {
|
||||
var diff = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1);
|
||||
rebaseRedoStack(this.$redoStack, diff);
|
||||
|
@ -180,13 +195,15 @@ var UndoManager = function() {
|
|||
this.$undoStack.push(deltaSet);
|
||||
this.$syncRev();
|
||||
}
|
||||
this.$fromUndo = false;
|
||||
|
||||
return redoSelectionRange;
|
||||
};
|
||||
|
||||
this.$syncRev = function() {
|
||||
var stack = this.$undoStack;
|
||||
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.$rev = id;
|
||||
};
|
||||
|
@ -202,11 +219,12 @@ var UndoManager = function() {
|
|||
this.selections = [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns `true` if there are undo operations left to perform.
|
||||
* @returns {Boolean}
|
||||
**/
|
||||
this.hasUndo = function() {
|
||||
this.canUndo = function() {
|
||||
return this.$undoStack.length > 0;
|
||||
};
|
||||
|
||||
|
@ -214,15 +232,14 @@ var UndoManager = function() {
|
|||
* Returns `true` if there are redo operations left to perform.
|
||||
* @returns {Boolean}
|
||||
**/
|
||||
this.hasRedo = function() {
|
||||
this.canRedo = function() {
|
||||
return this.$redoStack.length > 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Marks the current status clean
|
||||
**/
|
||||
this.bookmark =
|
||||
this.markClean = function(rev) {
|
||||
this.bookmark = function(rev) {
|
||||
if (rev == undefined)
|
||||
rev = this.$rev;
|
||||
this.mark = rev;
|
||||
|
@ -232,14 +249,26 @@ var UndoManager = function() {
|
|||
* Returns if the current status is clean
|
||||
* @returns {Boolean}
|
||||
**/
|
||||
this.isClean = function() {
|
||||
this.isAtBookmark = function() {
|
||||
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);
|
||||
|
||||
function findDelta(stack, pos) {
|
||||
function rearrangeUndoStack(stack, pos) {
|
||||
for (var i = pos; i--; ) {
|
||||
var deltaSet = stack[i];
|
||||
if (deltaSet && !deltaSet[0].ignore) {
|
||||
|
@ -249,7 +278,7 @@ function findDelta(stack, pos) {
|
|||
stack[i + 1] = swapped[1];
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -282,14 +282,24 @@ define(function(require, exports, module) {
|
|||
/***** Undo Manager *****/
|
||||
|
||||
function AceUndoManager(undoManager, session) {
|
||||
var state = undoManager.getState();
|
||||
this.$session = session;
|
||||
this.$undo = undoManager;
|
||||
this.$aceUndo = new UndoManager();
|
||||
var _self = this;
|
||||
var Item = this.Item;
|
||||
this.$undo.on("itemFind", function(e) {
|
||||
return Item(_self, e.state);
|
||||
});
|
||||
this.$aceUndo.c9UndoProxy = undoManager;
|
||||
undoManager.$aceUndo = this.$aceUndo;
|
||||
undoManager.add = this.add;
|
||||
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) {
|
||||
if (deltas[0] && deltas[0].deltas) {
|
||||
|
@ -299,81 +309,74 @@ define(function(require, exports, module) {
|
|||
deltas.push.apply(deltas, x.deltas);
|
||||
});
|
||||
}
|
||||
return deltas;
|
||||
}
|
||||
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) {
|
||||
if (doc.mergeUndoDeltas === false || !this.lastDeltas) {
|
||||
this.lastDeltas = [];
|
||||
this.$undo.add(this.Item(this, this.lastDeltas));
|
||||
}
|
||||
this.lastDeltas.push(delta);
|
||||
this.$aceUndo.add(delta, doc);
|
||||
this._emit("change");
|
||||
},
|
||||
addSelection: function(range, rev) {
|
||||
this.$aceUndo.addSelection(range, rev);
|
||||
},
|
||||
|
||||
undo: function(dontSelect) {
|
||||
this.dontSelect = dontSelect;
|
||||
this.lastDeltas = null;
|
||||
this.$undo.undo();
|
||||
this.$aceUndo.undo(dontSelect);
|
||||
this._emit("change");
|
||||
},
|
||||
redo: function(dontSelect) {
|
||||
this.dontSelect = dontSelect;
|
||||
this.lastDeltas = null;
|
||||
this.$undo.redo();
|
||||
this.$aceUndo.redo(dontSelect);
|
||||
this._emit("change");
|
||||
},
|
||||
reset: function(){
|
||||
this.lastDeltas = null;
|
||||
this.$undo.reset();
|
||||
this.$aceUndo.reset();
|
||||
this._emit("change");
|
||||
},
|
||||
hasUndo: function() {
|
||||
return this.$undo.length > this.$undo.position + 1;
|
||||
canUndo: function() {
|
||||
return this.$aceUndo.canUndo();
|
||||
},
|
||||
hasRedo: function() {
|
||||
return this.$undo.length <= this.$undo.position + 1;
|
||||
canRedo: function() {
|
||||
return this.$aceUndo.canRedo();
|
||||
},
|
||||
get $undoStack() {
|
||||
return this.$undo.stack.slice(0, this.$undo.position + 1)
|
||||
.map(function(e){ return e.getState ? e.getState() : e });
|
||||
clearUndo: function() {
|
||||
this.$aceUndo.$undoStack = [];
|
||||
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() {
|
||||
this.execute = function(options) {
|
||||
this.$u.execute(options);
|
||||
this.add = function(delta, doc) {
|
||||
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() {
|
||||
var selectionRange = this.$u.undo(true);
|
||||
|
@ -1410,7 +1423,7 @@ define(function(require, exports, module) {
|
|||
undoManager = session.getUndoManager();
|
||||
if (undoManager) {
|
||||
var undoManagerProxy = new UndoManagerProxy(undoManager, s);
|
||||
s.setUndoManager(undoManagerProxy);
|
||||
s.setUndoManager(undoManagerProxy.$aceUndo);
|
||||
}
|
||||
|
||||
// Overwrite the default $informUndoManager function such that new deltas
|
||||
|
@ -2211,9 +2224,9 @@ define(function(require, exports, module) {
|
|||
var c9Session = doc.getSession();
|
||||
|
||||
// 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
|
||||
progress.noFadeIn = !currentDocument;
|
||||
progress.noFadeIn = !currentDocument || !currentDocument.tab.active;
|
||||
|
||||
// Value Retrieval
|
||||
doc.on("getValue", function get(e) {
|
||||
|
|
|
@ -150,6 +150,8 @@ define(function(require, module, exports) {
|
|||
emit("change");
|
||||
}
|
||||
|
||||
plugin.freezePublicAPI.baseclass();
|
||||
|
||||
/**
|
||||
* The Undo Manager class of Cloud9. Each {@link Document}
|
||||
* has a single instance of the undo manager that
|
||||
|
@ -212,10 +214,6 @@ define(function(require, module, exports) {
|
|||
*
|
||||
**/
|
||||
plugin.freezePublicAPI({
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
get stack() { return stack; },
|
||||
/**
|
||||
* The number of items on the stack. This number will stay the
|
||||
* same when using {@link UndoManager#undo} and
|
||||
|
|
Ładowanie…
Reference in New Issue