Move wrapping logging into Document.
This commit is contained in:
parent
511de83908
commit
c30b9ece8f
8 changed files with 244 additions and 177 deletions
|
|
@ -58,6 +58,7 @@ exports.launch = function(env) {
|
|||
var docs = {};
|
||||
|
||||
docs.js = new Document(document.getElementById("jstext").innerHTML);
|
||||
docs.js.setUseWrapMode(true);
|
||||
docs.js.setMode(new JavaScriptMode());
|
||||
docs.js.setUndoManager(new UndoManager());
|
||||
|
||||
|
|
|
|||
|
|
@ -45,17 +45,18 @@ var TextMode = require("ace/mode/text").Mode;
|
|||
var Range = require("ace/range").Range;
|
||||
|
||||
var Document = function(text, mode) {
|
||||
|
||||
|
||||
this.modified = true;
|
||||
this.lines = [];
|
||||
this.selection = new Selection(this);
|
||||
this.$breakpoints = [];
|
||||
this.$wrapData = [];
|
||||
|
||||
this.listeners = [];
|
||||
if (mode) {
|
||||
this.setMode(mode);
|
||||
}
|
||||
|
||||
|
||||
if (Array.isArray(text)) {
|
||||
this.$insertLines(0, text);
|
||||
} else {
|
||||
|
|
@ -159,7 +160,7 @@ var Document = function(text, mode) {
|
|||
this.getTabSize = function() {
|
||||
return this.$tabSize;
|
||||
};
|
||||
|
||||
|
||||
this.isTabStop = function(position) {
|
||||
return this.$useSoftTabs && (position.column % this.$tabSize == 0);
|
||||
};
|
||||
|
|
@ -199,13 +200,13 @@ var Document = function(text, mode) {
|
|||
this.$autoNewLine = "\n";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.tokenRe = /^[\w\d]+/g;
|
||||
this.nonTokenRe = /^[^\w\d]+/g;
|
||||
|
||||
|
||||
this.getWordRange = function(row, column) {
|
||||
var line = this.getLine(row);
|
||||
|
||||
|
||||
var inToken = false;
|
||||
if (column > 0) {
|
||||
inToken = !!line.charAt(column - 1).match(this.tokenRe);
|
||||
|
|
@ -321,12 +322,12 @@ var Document = function(text, mode) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Get a verbatim copy of the given line as it is in the document
|
||||
* Get a verbatim copy of the given line as it is in the document
|
||||
*/
|
||||
this.getLine = function(row) {
|
||||
return this.lines[row] || "";
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a line as it is displayed on screen. Tabs are replaced by spaces.
|
||||
*/
|
||||
|
|
@ -455,18 +456,18 @@ var Document = function(text, mode) {
|
|||
: undefined);
|
||||
return end;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param rows Array[Integer] sorted list of rows
|
||||
*/
|
||||
this.multiRowInsert = function(rows, column, text) {
|
||||
var lines = this.lines;
|
||||
|
||||
|
||||
for (var i=rows.length-1; i>=0; i--) {
|
||||
var row = rows[i];
|
||||
if (row >= lines.length)
|
||||
continue;
|
||||
|
||||
|
||||
var diff = column - lines[row].length;
|
||||
if ( diff > 0) {
|
||||
var padded = lang.stringRepeat(" ", diff) + text;
|
||||
|
|
@ -476,10 +477,10 @@ var Document = function(text, mode) {
|
|||
padded = text;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
var end = this.$insert({row: row, column: column+offset}, padded, false);
|
||||
}
|
||||
|
||||
|
||||
if (end) {
|
||||
this.fireChangeEvent(rows[0], rows[rows.length-1] + end.row - rows[0]);
|
||||
return {
|
||||
|
|
@ -593,16 +594,16 @@ var Document = function(text, mode) {
|
|||
this.multiRowRemove = function(rows, range) {
|
||||
if (range.start.row !== rows[0])
|
||||
throw new TypeError("range must start in the first row!");
|
||||
|
||||
|
||||
var height = range.end.row - rows[0];
|
||||
for (var i=rows.length-1; i>=0; i--) {
|
||||
var row = rows[i];
|
||||
if (row >= this.lines.length)
|
||||
continue;
|
||||
|
||||
|
||||
var end = this.$remove(new Range(row, range.start.column, row+height, range.end.column), false);
|
||||
}
|
||||
|
||||
|
||||
if (end) {
|
||||
if (height < 0)
|
||||
this.fireChangeEvent(rows[0]+height, undefined);
|
||||
|
|
@ -610,7 +611,7 @@ var Document = function(text, mode) {
|
|||
this.fireChangeEvent(rows[0], height == 0 ? rows[rows.length-1] : undefined);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.$remove = function(range, fromUndo) {
|
||||
if (range.isEmpty())
|
||||
return;
|
||||
|
|
@ -639,7 +640,7 @@ var Document = function(text, mode) {
|
|||
this.lines.splice(firstRow, lastRow - firstRow + 1, "");
|
||||
return range.start;
|
||||
};
|
||||
|
||||
|
||||
this.undoChanges = function(deltas) {
|
||||
this.selection.clearSelection();
|
||||
for (var i=deltas.length-1; i>=0; i--) {
|
||||
|
|
@ -685,7 +686,7 @@ var Document = function(text, mode) {
|
|||
return end;
|
||||
};
|
||||
|
||||
this.indentRows = function(startRow, endRow, indentString) {
|
||||
this.indentRows = function(startRow, endRow, indentString) {
|
||||
indentString = indentString.replace("\t", this.getTabString());
|
||||
for (var row=startRow; row<=endRow; row++) {
|
||||
this.$insert({row: row, column:0}, indentString);
|
||||
|
|
@ -698,15 +699,15 @@ var Document = function(text, mode) {
|
|||
var rowRange = range.collapseRows();
|
||||
var deleteRange = new Range(0, 0, 0, 0);
|
||||
var size = this.getTabSize();
|
||||
|
||||
|
||||
for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
|
||||
var line = this.getLine(i);
|
||||
|
||||
|
||||
deleteRange.start.row = i;
|
||||
deleteRange.end.row = i;
|
||||
for (var j = 0; j < size; ++j)
|
||||
if (line.charAt(j) != ' ')
|
||||
break;
|
||||
break;
|
||||
if (j < size && line.charAt(j) == '\t') {
|
||||
deleteRange.start.column = j;
|
||||
deleteRange.end.column = j + 1;
|
||||
|
|
@ -722,7 +723,7 @@ var Document = function(text, mode) {
|
|||
}
|
||||
this.fireChangeEvent(range.start.row, range.end.row);
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
this.moveLinesUp = function(firstRow, lastRow) {
|
||||
if (firstRow <= 0) return 0;
|
||||
|
|
@ -730,7 +731,7 @@ var Document = function(text, mode) {
|
|||
var removed = this.lines.slice(firstRow, lastRow + 1);
|
||||
this.$remove(new Range(firstRow-1, this.lines[firstRow-1].length, lastRow, this.lines[lastRow].length));
|
||||
this.$insertLines(firstRow - 1, removed);
|
||||
|
||||
|
||||
this.fireChangeEvent(firstRow - 1, lastRow);
|
||||
return -1;
|
||||
};
|
||||
|
|
@ -741,7 +742,7 @@ var Document = function(text, mode) {
|
|||
var removed = this.lines.slice(firstRow, lastRow + 1);
|
||||
this.$remove(new Range(firstRow, 0, lastRow + 1, 0));
|
||||
this.$insertLines(firstRow+1, removed);
|
||||
|
||||
|
||||
this.fireChangeEvent(firstRow, lastRow + 1);
|
||||
return 1;
|
||||
};
|
||||
|
|
@ -763,26 +764,72 @@ var Document = function(text, mode) {
|
|||
return Math.max(0, Math.min(row, this.lines.length-1));
|
||||
};
|
||||
|
||||
this.documentToScreenColumn = function(row, docColumn) {
|
||||
var tabSize = this.getTabSize();
|
||||
}).call(Document.prototype);
|
||||
|
||||
var screenColumn = 0;
|
||||
var remaining = docColumn;
|
||||
|
||||
var line = this.getLine(row).split("\t");
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var len = line[i].length;
|
||||
if (remaining > len) {
|
||||
remaining -= (len + 1);
|
||||
screenColumn += len + tabSize;
|
||||
(function() {
|
||||
this.$wrapLimit = 12;
|
||||
this.$useWrapMode = false;
|
||||
this.setUseWrapMode = function(useWrapMode) {
|
||||
var _self = this;
|
||||
function computeWrapData(e) {
|
||||
var lines = _self.lines, wrapData = _self.$wrapData;
|
||||
var wrapLimit = _self.$wrapLimit;
|
||||
|
||||
if (!e.data.lastRow) {
|
||||
e.data.lastRow = _self.lines.length - 1;
|
||||
}
|
||||
else {
|
||||
screenColumn += remaining;
|
||||
break;
|
||||
|
||||
for (var row = e.data.firstRow; row <= e.data.lastRow; row++) {
|
||||
var col = wrapLimit;
|
||||
wrapData[row] = [];
|
||||
while (col < lines[row].length) {
|
||||
wrapData[row].push(col);
|
||||
col += wrapLimit;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.$useWrapMode = useWrapMode;
|
||||
computeWrapData({ data: { firstRow: 0 } });
|
||||
this._dispatchEvent("changeWrapMode");
|
||||
|
||||
if (useWrapMode) {
|
||||
this.addEventListener("change", computeWrapData);
|
||||
} else {
|
||||
this.removeEventListener("change", computeWrapData);
|
||||
}
|
||||
};
|
||||
|
||||
this.getUseWrapMode = function() {
|
||||
return this.$useWrapMode;
|
||||
};
|
||||
|
||||
this.setWrapLimit = function(wrapLimit) {
|
||||
this.$wrapLimit = wrapLimit;
|
||||
};
|
||||
|
||||
this.getWrapLimit = function() {
|
||||
return this.$wrapLimit;
|
||||
};
|
||||
|
||||
this.getRowHeight = function(config, row) {
|
||||
var rows;
|
||||
if (!this.$useWrapMode) {
|
||||
rows = 1;
|
||||
} else {
|
||||
rows = this.$wrapData[row].length + 1;
|
||||
}
|
||||
|
||||
return screenColumn;
|
||||
return rows * config.lineHeight;
|
||||
};
|
||||
|
||||
this.getRowSplitData = function(row) {
|
||||
if (!this.$useWrapMode) {
|
||||
return undefined;
|
||||
} else {
|
||||
return this.$wrapData[row];
|
||||
}
|
||||
};
|
||||
|
||||
this.screenToDocumentColumn = function(row, screenColumn) {
|
||||
|
|
@ -810,7 +857,96 @@ var Document = function(text, mode) {
|
|||
return docColumn;
|
||||
};
|
||||
|
||||
}).call(Document.prototype);
|
||||
this.screenToDocumentPosition = function(row, column) {
|
||||
if (!this.$useWrapMode) {
|
||||
return {
|
||||
row: row,
|
||||
column: this.screenToDocumentColumn(row, column)
|
||||
}
|
||||
}
|
||||
|
||||
var wrapData = this.$wrapData, linesCount = this.lines.length;
|
||||
|
||||
var docRow = 0;
|
||||
while (docRow < linesCount && row >= wrapData[docRow].length + 1) {
|
||||
row -= wrapData[docRow].length + 1;
|
||||
docRow ++;
|
||||
}
|
||||
var docColumn = column +
|
||||
(docRow < linesCount ? wrapData[docRow][row - 1] || 0 : 0);
|
||||
|
||||
return {
|
||||
row: docRow,
|
||||
column: docColumn
|
||||
};
|
||||
};
|
||||
|
||||
this.documentToScreenColumn = function(row, docColumn) {
|
||||
var tabSize = this.getTabSize();
|
||||
|
||||
var screenColumn = 0;
|
||||
var remaining = docColumn;
|
||||
|
||||
var line = this.getLine(row).split("\t");
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var len = line[i].length;
|
||||
if (remaining > len) {
|
||||
remaining -= (len + 1);
|
||||
screenColumn += len + tabSize;
|
||||
}
|
||||
else {
|
||||
screenColumn += remaining;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return screenColumn;
|
||||
};
|
||||
|
||||
this.documentToScreenPosition = function(row, column) {
|
||||
if (!this.$useWrapMode) {
|
||||
return {
|
||||
row: row,
|
||||
column: this.documentToScreenColumn(row, column)
|
||||
}
|
||||
}
|
||||
|
||||
var wrapData = this.$wrapData;
|
||||
var screenRow = 0;
|
||||
|
||||
// Handle special case where the row is outside of the range of lines.
|
||||
if (row > wrapData.length - 1) {
|
||||
for (row = 0; row < wrapData.length; row ++) {
|
||||
screenRow += wrapData[row].length + 1;
|
||||
}
|
||||
return {
|
||||
row: screenRow,
|
||||
column: 0
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < row; i++) {
|
||||
screenRow += wrapData[i].length + 1;
|
||||
}
|
||||
|
||||
var screenColumn = column;
|
||||
var wrapRowData = wrapData[row];
|
||||
for (var split = 0; split < wrapRowData.length; split++) {
|
||||
if (column > wrapRowData[split]) {
|
||||
screenColumn = column - wrapRowData[split];
|
||||
screenRow ++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
row: screenRow,
|
||||
column: screenColumn
|
||||
};
|
||||
};
|
||||
|
||||
}).call(Document.prototype)
|
||||
|
||||
exports.Document = Document;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -107,8 +107,16 @@ var Cursor = function(parentEl) {
|
|||
top : 0
|
||||
};
|
||||
}
|
||||
|
||||
return this.config.getPixelPosition(this.position.row, this.position.column);
|
||||
|
||||
var pos = this.doc.documentToScreenPosition(this.position.row,
|
||||
this.position.column);
|
||||
var cursorLeft = Math.round(pos.column * this.config.characterWidth);
|
||||
var cursorTop = pos.row * this.config.lineHeight;
|
||||
|
||||
return {
|
||||
left : cursorLeft,
|
||||
top : cursorTop
|
||||
};
|
||||
};
|
||||
|
||||
this.update = function(config) {
|
||||
|
|
|
|||
|
|
@ -48,14 +48,18 @@ var Gutter = function(parentEl) {
|
|||
|
||||
(function() {
|
||||
|
||||
this.setDocument = function(doc) {
|
||||
this.doc = doc;
|
||||
};
|
||||
|
||||
this.addGutterDecoration = function(row, className){
|
||||
if (!this.$decorations[row])
|
||||
if (!this.$decorations[row])
|
||||
this.$decorations[row] = "";
|
||||
this.$decorations[row] += " ace_" + className;
|
||||
}
|
||||
|
||||
|
||||
this.removeGutterDecoration = function(row, className){
|
||||
this.$decorations[row] =
|
||||
this.$decorations[row] =
|
||||
this.$decorations[row].replace(" ace_" + className, "");
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +75,7 @@ var Gutter = function(parentEl) {
|
|||
html.push("<div class='ace_gutter-cell",
|
||||
this.$decorations[i] || "",
|
||||
this.$breakpoints[i] ? " ace_breakpoint" : "",
|
||||
"' style='height:", (config.wrapped[i].length + 1) * config.lineHeight, "px;'>", (i+1), "</div>");
|
||||
"' style='height:", this.doc.getRowHeight(config, i) + "px'>", (i+1), "</div>");
|
||||
html.push("</div>");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,10 +85,8 @@ var Marker = function(parentEl) {
|
|||
|
||||
var range = marker.range.clipRows(config.firstRow, config.lastRow);
|
||||
if (range.isEmpty()) continue;
|
||||
|
||||
// TODO: Add this conversion to the range object directly!
|
||||
range.start = this.config.posToWrappedPos(range.start.row, range.start.column);
|
||||
range.end = this.config.posToWrappedPos(range.end.row, range.end.column);
|
||||
|
||||
range = range.toScreenRange(this.doc);
|
||||
|
||||
if (range.isMultiLine()) {
|
||||
if (marker.type == "text") {
|
||||
|
|
@ -105,7 +103,6 @@ var Marker = function(parentEl) {
|
|||
};
|
||||
|
||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
|
||||
// selection start
|
||||
var row = range.start.row;
|
||||
var lineRange = new Range(row, range.start.column, row, this.doc.getLine(row).length);
|
||||
|
|
@ -125,9 +122,6 @@ var Marker = function(parentEl) {
|
|||
};
|
||||
|
||||
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
// TODO: Add this back.
|
||||
// var range = range.toScreenRange(this.doc);
|
||||
|
||||
// from selection start to the end of the line
|
||||
var height = layerConfig.lineHeight;
|
||||
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
|
||||
|
|
@ -168,9 +162,6 @@ var Marker = function(parentEl) {
|
|||
};
|
||||
|
||||
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig) {
|
||||
// TODO: Add this back.
|
||||
//var range = range.toScreenRange(this.doc);
|
||||
|
||||
var height = layerConfig.lineHeight;
|
||||
var width = Math.round((range.end.column - range.start.column) * layerConfig.characterWidth);
|
||||
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
|
||||
|
|
|
|||
|
|
@ -148,18 +148,19 @@ var Text = function(parentEl) {
|
|||
}
|
||||
};
|
||||
|
||||
this.updateLines = function(layerConfig, firstRow, lastRow) {
|
||||
this.updateLines = function(config, firstRow, lastRow) {
|
||||
console.log("layer.text.updateLines", firstRow, lastRow);
|
||||
this.$computeTabString();
|
||||
this.config = layerConfig;
|
||||
this.config = config;
|
||||
|
||||
var first = Math.max(firstRow, layerConfig.firstRow);
|
||||
var last = Math.min(lastRow, layerConfig.lastRow);
|
||||
var first = Math.max(firstRow, config.firstRow);
|
||||
var last = Math.min(lastRow, config.lastRow);
|
||||
|
||||
var lineElements = this.element.childNodes;
|
||||
var _self = this;
|
||||
this.tokenizer.getTokens(first, last, function(tokens) {
|
||||
for ( var i = first; i <= last; i++) {
|
||||
var lineElement = lineElements[i - layerConfig.firstRow];
|
||||
var lineElement = lineElements[i - config.firstRow];
|
||||
if (!lineElement)
|
||||
continue;
|
||||
|
||||
|
|
@ -168,7 +169,8 @@ var Text = function(parentEl) {
|
|||
lineElement.innerHTML = html.join("");
|
||||
// The height of the line might have changed if wrapped mode
|
||||
// is active.
|
||||
lineElement.style.height = (layerConfig.wrapped[i].length + 1) * layerConfig.lineHeight + "px";
|
||||
lineElement.style.height =
|
||||
_self.doc.getRowHeight(config, i) + "px";
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -229,7 +231,7 @@ var Text = function(parentEl) {
|
|||
var lineEl = document.createElement("div");
|
||||
lineEl.className = "ace_line";
|
||||
var style = lineEl.style;
|
||||
style.height = (config.wrapped[row].length + 1) * config.lineHeight + "px";
|
||||
style.height = _self.doc.getRowHeight(config, row) + "px";
|
||||
style.width = config.width + "px";
|
||||
|
||||
var html = [];
|
||||
|
|
@ -242,6 +244,7 @@ var Text = function(parentEl) {
|
|||
};
|
||||
|
||||
this.update = function(config) {
|
||||
console.log("layer.text.update()");
|
||||
this.$computeTabString();
|
||||
this.config = config;
|
||||
|
||||
|
|
@ -270,8 +273,6 @@ var Text = function(parentEl) {
|
|||
};
|
||||
|
||||
this.$renderLine = function(stringBuilder, row, tokens) {
|
||||
stringBuilder.push("<div>");
|
||||
var wrappedInfo = this.config.wrapped[row];
|
||||
// if (this.$showInvisibles) {
|
||||
// var self = this;
|
||||
// var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]+/g;
|
||||
|
|
@ -302,25 +303,31 @@ var Text = function(parentEl) {
|
|||
}
|
||||
}
|
||||
|
||||
var chars = 0;
|
||||
var wrapSection = 0;
|
||||
var maxChars = wrappedInfo[wrapSection] || 9999;
|
||||
var value;
|
||||
var splits = this.doc.getRowSplitData(row);
|
||||
var chars = 0, split = 0, splitChars;
|
||||
|
||||
if (!splits || splits.length == 0) {
|
||||
splitChars = Number.MAX_VALUE;
|
||||
} else {
|
||||
splitChars = splits[0];
|
||||
}
|
||||
|
||||
stringBuilder.push("<div>");
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var token = tokens[i];
|
||||
var value = token.value;
|
||||
|
||||
if (chars + token.value.length < maxChars) {
|
||||
addToken(token, token.value);
|
||||
chars += token.value.length;
|
||||
if (chars + value.length < splitChars) {
|
||||
addToken(token, value);
|
||||
chars += value.length;
|
||||
} else {
|
||||
value = token.value;
|
||||
while (chars + value.length >= maxChars) {
|
||||
addToken(token, value.substring(0, maxChars - chars));
|
||||
value = value.substring(maxChars - chars);
|
||||
chars = maxChars;
|
||||
while (chars + value.length >= splitChars) {
|
||||
addToken(token, value.substring(0, splitChars - chars));
|
||||
value = value.substring(splitChars - chars);
|
||||
chars = splitChars;
|
||||
stringBuilder.push("</div><div>");
|
||||
wrapSection ++;
|
||||
maxChars = wrappedInfo[wrapSection] || 9999;
|
||||
split ++;
|
||||
splitChars = splits[split] || Number.MAX_VALUE;
|
||||
}
|
||||
if (value.length != 0) {
|
||||
chars += value.length;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
|||
this.clone = function() {
|
||||
return Range.fromPoints(this.start, this.end);
|
||||
};
|
||||
|
||||
|
||||
this.collapseRows = function() {
|
||||
if (this.end.column == 0)
|
||||
return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
|
||||
|
|
@ -146,9 +146,13 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
|
|||
};
|
||||
|
||||
this.toScreenRange = function(doc) {
|
||||
var screenPosStart =
|
||||
doc.documentToScreenPosition(this.start.row, this.start.column);
|
||||
var screenPosEnd =
|
||||
doc.documentToScreenPosition(this.end.row, this.end.column);
|
||||
return new Range(
|
||||
this.start.row, doc.documentToScreenColumn(this.start.row, this.start.column),
|
||||
this.end.row, doc.documentToScreenColumn(this.end.row, this.end.column)
|
||||
screenPosStart.row, screenPosStart.column,
|
||||
screenPosEnd.row, screenPosEnd.column
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.$cursorLayer = new CursorLayer(this.content);
|
||||
|
||||
this.layers = [ this.$markerLayer, textLayer, this.$cursorLayer ];
|
||||
|
||||
|
||||
this.scrollBar = new ScrollBar(container);
|
||||
this.scrollBar.addEventListener("scroll", this.onScroll.bind(this));
|
||||
|
||||
|
|
@ -118,10 +118,6 @@ var VirtualRenderer = function(container, theme) {
|
|||
};
|
||||
|
||||
(function() {
|
||||
this.layerConfig = {
|
||||
wrapped: []
|
||||
};
|
||||
|
||||
this.showGutter = true;
|
||||
|
||||
this.CHANGE_CURSOR = 1;
|
||||
|
|
@ -140,30 +136,16 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.doc = doc;
|
||||
this.$cursorLayer.setDocument(doc);
|
||||
this.$markerLayer.setDocument(doc);
|
||||
this.$gutterLayer.setDocument(doc);
|
||||
this.$textLayer.setDocument(doc);
|
||||
|
||||
this.$loop.schedule(this.CHANGE_FULL);
|
||||
};
|
||||
|
||||
this.$updateWrappedLinesInfo = function(firstRow, lastRow) {
|
||||
var WRAPSIZE = 12;
|
||||
var wrappedInfo = this.layerConfig.wrapped;
|
||||
var lines = this.lines;
|
||||
for (var row = firstRow; row <= lastRow; row++) {
|
||||
var col = 12;
|
||||
wrappedInfo[row] = [];
|
||||
while (col < lines[row].length) {
|
||||
wrappedInfo[row].push(col);
|
||||
col += 12;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggers partial update of the text layer
|
||||
*/
|
||||
this.updateLines = function(firstRow, lastRow) {
|
||||
this.$updateWrappedLinesInfo(firstRow, lastRow);
|
||||
console.log("updateLines", firstRow, lastRow);
|
||||
if (lastRow === undefined)
|
||||
lastRow = Infinity;
|
||||
|
|
@ -351,7 +333,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.$renderChanges = function(changes) {
|
||||
if (!changes || !this.doc || !this.$tokenizer)
|
||||
return;
|
||||
|
||||
|
||||
// text, scrolling and resize changes can cause the view port size to change
|
||||
if (!this.layerConfig ||
|
||||
changes & this.CHANGE_FULL ||
|
||||
|
|
@ -419,7 +401,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
|
||||
var lastRow = Math.max(0, Math.min(this.lines.length, firstRow + lineCount) - 1);
|
||||
|
||||
var layerConfig = oop.mixin(this.layerConfig, {
|
||||
var layerConfig = this.layerConfig = {
|
||||
width : longestLine,
|
||||
padding : this.$padding,
|
||||
firstRow : firstRow,
|
||||
|
|
@ -429,11 +411,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
minHeight : minHeight,
|
||||
offset : offset,
|
||||
height : this.$size.scrollerHeight
|
||||
});
|
||||
|
||||
// Ensure that there is a wrapped array for all the rows in the current
|
||||
// view port.
|
||||
this.$updateWrappedLinesInfo(firstRow, lastRow);
|
||||
};
|
||||
|
||||
for ( var i = 0; i < this.layers.length; i++) {
|
||||
var layer = this.layers[i];
|
||||
|
|
@ -593,84 +571,22 @@ var VirtualRenderer = function(container, theme) {
|
|||
var row = Math.floor((pageY + this.scrollTop - canvasPos.top)
|
||||
/ this.lineHeight);
|
||||
|
||||
return this.layerConfig.wrappedPosToPos(
|
||||
row,
|
||||
col
|
||||
// TODO: Figure out how to calculate tabs here...
|
||||
//this.doc.screenToDocumentColumn(Math.max(0, Math.min(row, this.doc.getLength()-1)), col)
|
||||
);
|
||||
return this.doc.screenToDocumentPosition(row, col);
|
||||
};
|
||||
|
||||
this.textToScreenCoordinates = function(row, column) {
|
||||
var canvasPos = this.scroller.getBoundingClientRect();
|
||||
var pos = this.doc.documentToScreenPosition(row, column);
|
||||
|
||||
var x = this.padding + Math.round(this.doc.documentToScreenColumn(row, column) * this.characterWidth);
|
||||
var y = row * this.lineHeight;
|
||||
|
||||
var x = this.padding + Math.round(pos.column * this.characterWidth);
|
||||
var y = pos.row * this.lineHeight;
|
||||
|
||||
return {
|
||||
pageX: canvasPos.left + x - this.getScrollLeft(),
|
||||
pageY: canvasPos.top + y - this.getScrollTop()
|
||||
}
|
||||
};
|
||||
|
||||
this.wrappedPosToPos = function(row, column) {
|
||||
var linesCount = this.wrapped.length;
|
||||
var realRow = 0;
|
||||
while (realRow < linesCount && row >= this.wrapped[realRow].length + 1) {
|
||||
row -= this.wrapped[realRow].length + 1;
|
||||
realRow ++;
|
||||
}
|
||||
return {
|
||||
row: realRow,
|
||||
column: column + (realRow < linesCount ? this.wrapped[realRow][row - 1] || 0 : 0)
|
||||
};
|
||||
};
|
||||
|
||||
this.posToWrappedPos = function(row, column) {
|
||||
// TODO: Why can it happen, that row is higher then the current count
|
||||
// of lines (note lines in doc, not only in wrapped!). Happens when
|
||||
// the cursor is in the last line and the marker "ace_active_line" is
|
||||
// painted.
|
||||
if (row > this.wrapped.length - 1) {
|
||||
row = this.wrapped.length - 1;
|
||||
column = 99999;
|
||||
}
|
||||
|
||||
var rows = 0;
|
||||
for (var i = 0; i < row; i++) {
|
||||
rows += this.wrapped[i].length + 1;
|
||||
}
|
||||
|
||||
var col = column;
|
||||
for (var s = 0; s < this.wrapped[row].length; s++) {
|
||||
if (column > this.wrapped[row][s]) {
|
||||
col = column - this.wrapped[row][s];
|
||||
rows ++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
row: rows,
|
||||
column: col
|
||||
};
|
||||
};
|
||||
|
||||
this.getPixelPosition = function(row, column) {
|
||||
var pos = this.posToWrappedPos(row, column);
|
||||
var cursorLeft = Math.round(pos.column * this.characterWidth);
|
||||
var cursorTop = pos.row * this.lineHeight;
|
||||
|
||||
return {
|
||||
left : cursorLeft,
|
||||
top : cursorTop
|
||||
};
|
||||
};
|
||||
|
||||
// TODO: This should get passed in a different way to the cursorLayer!
|
||||
this.layerConfig.getPixelPosition = this.getPixelPosition;
|
||||
this.layerConfig.posToWrappedPos = this.posToWrappedPos;
|
||||
this.layerConfig.wrappedPosToPos = this.wrappedPosToPos;
|
||||
|
||||
this.visualizeFocus = function() {
|
||||
dom.addCssClass(this.container, "ace_focus");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue