store position as row column fields directly on

the anchor and always clip position to document
This commit is contained in:
Fabian Jakobs 2011-02-11 08:09:55 +01:00
commit 30923b0b1e
2 changed files with 79 additions and 49 deletions

View file

@ -46,11 +46,14 @@ var EventEmitter = require("pilot/event_emitter").EventEmitter;
*/
var Anchor = exports.Anchor = function(doc, row, column) {
this.document = doc;
this.pos = {
row: row,
column: column
};
doc.on("change", this.onChange.bind(this));
if (typeof column == "undefined")
this.setPosition(row.row, row.column)
else
this.setPosition(row, column);
this.$onChange = this.onChange.bind(this);
doc.on("change", this.$onChange);
};
(function() {
@ -58,10 +61,7 @@ var Anchor = exports.Anchor = function(doc, row, column) {
oop.implement(this, EventEmitter);
this.getPosition = function() {
return {
row: this.pos.row,
column: this.pos.column
};
return this.$clipPositionToDocument(this.row, this.column);
};
this.getDocument = function() {
@ -72,80 +72,103 @@ var Anchor = exports.Anchor = function(doc, row, column) {
var delta = e.data;
var range = delta.range;
if (range.start.row == range.end.row && range.start.row != this.pos.row)
if (range.start.row == range.end.row && range.start.row != this.row)
return;
if (range.start.row > this.pos.row)
if (range.start.row > this.row)
return;
if (range.start.row == this.pos.row && range.start.column > this.pos.column)
if (range.start.row == this.row && range.start.column > this.column)
return;
var pos = this.getPosition();
var row = this.row;
var column = this.column;
if (delta.action === "insertText") {
if (range.start.row === pos.row && range.start.column <= pos.column) {
if (range.start.row === row && range.start.column <= column) {
if (range.start.row === range.end.row) {
pos.column += range.end.column - range.start.column;
column += range.end.column - range.start.column;
}
else {
pos.column -= range.start.column;
pos.row += range.end.row - range.start.row;
column -= range.start.column;
row += range.end.row - range.start.row;
}
}
else if (range.start.row !== range.end.row && range.start.row < pos.row) {
pos.row += range.end.row - range.start.row;
else if (range.start.row !== range.end.row && range.start.row < row) {
row += range.end.row - range.start.row;
}
} else if (delta.action === "insertLines") {
if (range.start.row <= pos.row) {
pos.row += range.end.row - range.start.row;
if (range.start.row <= row) {
row += range.end.row - range.start.row;
}
}
else if (delta.action == "removeText") {
if (range.start.row == pos.row && range.start.column < pos.column) {
if (range.end.column >= pos.column)
pos.column = range.start.column;
if (range.start.row == row && range.start.column < column) {
if (range.end.column >= column)
column = range.start.column;
else
pos.column = Math.max(0, pos.column - (range.end.column - range.start.column));
column = Math.max(0, column - (range.end.column - range.start.column));
} else if (range.start.row !== range.end.row && range.start.row < pos.row) {
if (range.end.row == pos.row) {
pos.column = Math.max(0, pos.column - range.end.column) + range.start.column;
} else if (range.start.row !== range.end.row && range.start.row < row) {
if (range.end.row == row) {
column = Math.max(0, column - range.end.column) + range.start.column;
}
pos.row -= (range.end.row - range.start.row);
row -= (range.end.row - range.start.row);
}
else if (range.end.row == pos.row) {
pos.row -= range.end.row - range.start.row;
pos.column = Math.max(0, pos.column - range.end.column) + range.start.column;
else if (range.end.row == row) {
row -= range.end.row - range.start.row;
column = Math.max(0, column - range.end.column) + range.start.column;
}
} else if (delta.action == "removeLines") {
if (range.start.row <= pos.row) {
if (range.end.row <= pos.row)
pos.row -= range.end.row - range.start.row;
if (range.start.row <= row) {
if (range.end.row <= row)
row -= range.end.row - range.start.row;
else {
pos.row = range.start.row;
pos.column = 0;
row = range.start.row;
column = 0;
}
}
}
// clip
var len = this.document.getLength();
if (pos.row > len) {
pos.row = len - 1;
pos.column = this.document.getLine(len-1).length;
}
this.setPosition(pos);
this.setPosition(row, column);
};
this.setPosition = function(pos) {
if (this.pos.row == pos.row && this.pos.column == pos.column)
this.setPosition = function(row, column) {
pos = this.$clipPositionToDocument(row, column);
if (this.row == row && this.column == column)
return;
this.pos = pos;
this.row = row;
this.column = column;
this._dispatchEvent("change");
};
this.detach = function() {
this.document.removeEventListener("change", this.$onChange);
};
this.$clipPositionToDocument = function(row, column) {
var pos = {};
if (row >= this.document.getLength()) {
pos.row = Math.max(0, this.document.getLength() - 1);
pos.column = this.document.getLine(pos.row).length;
}
else if (row < 0) {
pos.row = 0;
pos.column = 0;
}
else {
pos.row = row;
pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
}
if (column < 0)
pos.column = 0;
return pos;
};
}).call(Anchor.prototype);
});

View file

@ -59,6 +59,14 @@ var Test = {
assert.position(anchor.getPosition(), 1, 7);
},
"test insert text at line start in same row before cursor should move anchor column": function() {
var doc = new Document("juhu\nkinners");
var anchor = new Anchor(doc, 1, 4);
doc.insert({row: 1, column: 0}, "//");
assert.position(anchor.getPosition(), 1, 6);
},
"test insert lines before cursor should move anchor row": function() {
var doc = new Document("juhu\nkinners");
var anchor = new Anchor(doc, 1, 4);
@ -104,7 +112,6 @@ var Test = {
var anchor = new Anchor(doc, 1, 4);
doc.remove(new Range(1, 4, 1, 5));
console.log(doc.$lines);
assert.position(anchor.getPosition(), 1, 4);
},