ace/lib/ace/Selection.js
2010-10-29 20:14:41 +02:00

389 lines
11 KiB
JavaScript

/**
* Ajax.org Code Editor (ACE)
*
* @copyright 2010, Ajax.org Services B.V.
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org>
*/
require.def("ace/Selection", [
"ace/lib/oop",
"ace/lib/lang",
"ace/MEventEmitter",
"ace/Range"
], function(oop, lang, MEventEmitter, Range) {
var Selection = function(doc) {
this.doc = doc;
this.clearSelection();
this.selectionLead = {
row: 0,
column: 0
};
};
(function() {
oop.implement(this, MEventEmitter);
this.isEmpty = function() {
return (!this.selectionAnchor ||
(this.selectionAnchor.row == this.selectionLead.row &&
this.selectionAnchor.column == this.selectionLead.column));
};
this.isMultiLine = function() {
if (this.isEmpty()) {
return false;
}
return this.getRange().isMultiLine();
};
this.getCursor = function() {
return this.selectionLead;
};
this.setSelectionAnchor = function(row, column) {
var anchor = this.$clipPositionToDocument(row, column);
if (!this.selectionAnchor) {
this.selectionAnchor = anchor;
this.$dispatchEvent("changeSelection", {});
}
else if (this.selectionAnchor.row !== anchor.row || this.selectionAnchor.column !== anchor.column) {
this.selectionAnchor = anchor;
this.$dispatchEvent("changeSelection", {});
}
};
this.getSelectionAnchor = function() {
if (this.selectionAnchor) {
return this.$clone(this.selectionAnchor);
} else {
return this.$clone(this.selectionLead);
}
};
this.getSelectionLead = function() {
return this.$clone(this.selectionLead);
};
this.shiftSelection = function(columns) {
if (this.isEmpty()) {
this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);
return;
};
var anchor = this.getSelectionAnchor();
var lead = this.getSelectionLead();
var isBackwards = this.isBackwards();
if (!isBackwards || anchor.column !== 0)
this.setSelectionAnchor(anchor.row, anchor.column + columns);
if (isBackwards || lead.column !== 0) {
this.$moveSelection(function() {
this.moveCursorTo(lead.row, lead.column + columns);
});
}
};
this.isBackwards = function() {
var anchor = this.selectionAnchor || this.selectionLead;
var lead = this.selectionLead;
return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
};
this.getRange = function() {
var anchor = this.selectionAnchor || this.selectionLead;
var lead = this.selectionLead;
if (this.isBackwards()) {
return Range.fromPoints(lead, anchor);
}
else {
return Range.fromPoints(anchor, lead);
}
};
this.clearSelection = function() {
if (this.selectionAnchor) {
this.selectionAnchor = null;
this.$dispatchEvent("changeSelection", {});
}
};
this.selectAll = function() {
var lastRow = this.doc.getLength() - 1;
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
this.$moveSelection(function() {
this.moveCursorTo(0, 0);
});
};
this.setSelectionRange = function(range, reverse) {
if (reverse) {
this.setSelectionAnchor(range.end.row, range.end.column);
this.selectTo(range.start.row, range.start.column);
} else {
this.setSelectionAnchor(range.start.row, range.start.column);
this.selectTo(range.end.row, range.end.column);
}
};
this.$moveSelection = function(mover) {
var changed = false;
if (!this.selectionAnchor) {
changed = true;
this.selectionAnchor = this.$clone(this.selectionLead);
}
var cursor = this.$clone(this.selectionLead);
mover.call(this);
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
changed = true;
}
if (changed)
this.$dispatchEvent("changeSelection", {});
};
this.selectTo = function(row, column) {
this.$moveSelection(function() {
this.moveCursorTo(row, column);
});
};
this.selectToPosition = function(pos) {
this.$moveSelection(function() {
this.moveCursorToPosition(pos);
});
};
this.selectUp = function() {
this.$moveSelection(this.moveCursorUp);
};
this.selectDown = function() {
this.$moveSelection(this.moveCursorDown);
};
this.selectRight = function() {
this.$moveSelection(this.moveCursorRight);
};
this.selectLeft = function() {
this.$moveSelection(this.moveCursorLeft);
};
this.selectLineStart = function() {
this.$moveSelection(this.moveCursorLineStart);
};
this.selectLineEnd = function() {
this.$moveSelection(this.moveCursorLineEnd);
};
this.selectFileEnd = function() {
this.$moveSelection(this.moveCursorFileEnd);
};
this.selectFileStart = function() {
this.$moveSelection(this.moveCursorFileStart);
};
this.selectWordRight = function() {
this.$moveSelection(this.moveCursorWordRight);
};
this.selectWordLeft = function() {
this.$moveSelection(this.moveCursorWordLeft);
};
this.selectWord = function() {
var cursor = this.selectionLead;
var column = cursor.column;
var range = this.doc.getWordRange(cursor.row, column);
this.setSelectionRange(range);
/*this.setSelectionAnchor(cursor.row, start);
this.$moveSelection(function() {
this.moveCursorTo(cursor.row, end);
});*/
};
this.selectLine = function() {
this.setSelectionAnchor(this.selectionLead.row, 0);
this.$moveSelection(function() {
this.moveCursorTo(this.selectionLead.row + 1, 0);
});
};
this.moveCursorUp = function() {
this.moveCursorBy(-1, 0);
};
this.moveCursorDown = function() {
this.moveCursorBy(1, 0);
};
this.moveCursorLeft = function() {
if (this.selectionLead.column == 0) {
if (this.selectionLead.row > 0) {
this.moveCursorTo(this.selectionLead.row - 1, this.doc
.getLine(this.selectionLead.row - 1).length);
}
}
else {
this.moveCursorBy(0, -1);
}
};
this.moveCursorRight = function() {
if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {
if (this.selectionLead.row < this.doc.getLength() - 1) {
this.moveCursorTo(this.selectionLead.row + 1, 0);
}
}
else {
this.moveCursorBy(0, 1);
}
};
this.moveCursorLineStart = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var beforeCursor = this.doc.getLine(row).slice(0, column);
var leadingSpace = beforeCursor.match(/^\s+/);
if (!leadingSpace || leadingSpace[0].length >= column)
this.moveCursorTo(this.selectionLead.row, 0);
else
this.moveCursorTo(this.selectionLead.row, leadingSpace[0].length);
};
this.moveCursorLineEnd = function() {
this.moveCursorTo(this.selectionLead.row,
this.doc.getLine(this.selectionLead.row).length);
};
this.moveCursorFileEnd = function() {
var row = this.doc.getLength() - 1;
var column = this.doc.getLine(row).length;
this.moveCursorTo(row, column);
};
this.moveCursorFileStart = function() {
this.moveCursorTo(0, 0);
};
this.moveCursorWordRight = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var line = this.doc.getLine(row);
var rightOfCursor = line.substring(column);
var match;
this.doc.nonTokenRe.lastIndex = 0;
this.doc.tokenRe.lastIndex = 0;
if (column == line.length) {
this.moveCursorRight();
return;
}
else if (match = this.doc.nonTokenRe.exec(rightOfCursor)) {
column += this.doc.nonTokenRe.lastIndex;
this.doc.nonTokenRe.lastIndex = 0;
}
else if (match = this.doc.tokenRe.exec(rightOfCursor)) {
column += this.doc.tokenRe.lastIndex;
this.doc.tokenRe.lastIndex = 0;
}
this.moveCursorTo(row, column);
};
this.moveCursorWordLeft = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var line = this.doc.getLine(row);
var leftOfCursor = lang.stringReverse(line.substring(0, column));
var match;
this.doc.nonTokenRe.lastIndex = 0;
this.doc.tokenRe.lastIndex = 0;
if (column == 0) {
this.moveCursorLeft();
return;
}
else if (match = this.doc.nonTokenRe.exec(leftOfCursor)) {
column -= this.doc.nonTokenRe.lastIndex;
this.doc.nonTokenRe.lastIndex = 0;
}
else if (match = this.doc.tokenRe.exec(leftOfCursor)) {
column -= this.doc.tokenRe.lastIndex;
this.doc.tokenRe.lastIndex = 0;
}
this.moveCursorTo(row, column);
};
this.moveCursorBy = function(rows, chars) {
this.moveCursorTo(this.selectionLead.row + rows, this.selectionLead.column + chars);
};
this.moveCursorToPosition = function(position) {
this.moveCursorTo(position.row, position.column);
};
this.moveCursorTo = function(row, column) {
var cursor = this.$clipPositionToDocument(row, column);
// only dispatch change if the cursor actually changed
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
this.selectionLead = cursor;
this.$dispatchEvent("changeCursor", { data: this.getCursor() });
}
};
this.moveCursorUp = function() {
this.moveCursorBy(-1, 0);
};
this.$clipPositionToDocument = function(row, column) {
var pos = {};
if (row >= this.doc.getLength()) {
pos.row = Math.max(0, this.doc.getLength() - 1);
pos.column = this.doc.getLine(pos.row).length;
}
else if (row < 0) {
pos.row = 0;
pos.column = 0;
}
else {
pos.row = row;
pos.column = Math.min(this.doc.getLine(pos.row).length,
Math.max(0, column));
}
return pos;
};
this.$clone = function(pos) {
return {
row: pos.row,
column: pos.column
};
};
}).call(Selection.prototype);
return Selection;
});