Fix problems when scolling + wrapped lines

This commit is contained in:
Julian Viereck 2011-01-08 23:01:34 +01:00
commit 609f062803
5 changed files with 82 additions and 20 deletions

View file

@ -772,10 +772,14 @@ var Document = function(text, mode) {
this.$useWrapMode = false;
this.setUseWrapMode = function(useWrapMode) {
var _self = this;
function computeWrapData(e) {
var lines = _self.lines, wrapData = _self.$wrapData;
var wrapLimit = _self.$wrapLimit;
// Remove lines that are no longer there.
wrapData.splice(lines.length, wrapData.length - lines.length);
if (!e.data.lastRow) {
e.data.lastRow = _self.lines.length - 1;
}
@ -857,6 +861,21 @@ var Document = function(text, mode) {
return docColumn;
};
this.screenToDocumentRow = function(row) {
if (!this.$useWrapMode) {
return row;
}
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 ++;
}
return docRow;
};
this.screenToDocumentPosition = function(row, column) {
if (!this.$useWrapMode) {
return {
@ -903,7 +922,7 @@ var Document = function(text, mode) {
return screenColumn;
};
this.documentToScreenPosition = function(row, column) {
this.documentToScreenRow = function(row) {
if (!this.$useWrapMode) {
return {
row: row,
@ -919,19 +938,27 @@ var Document = function(text, mode) {
for (row = 0; row < wrapData.length; row ++) {
screenRow += wrapData[row].length + 1;
}
return {
row: screenRow,
column: 0
}
return screenRow;
}
for (var i = 0; i < row; i++) {
screenRow += wrapData[i].length + 1;
}
return screenRow;
}
this.documentToScreenPosition = function(row, column) {
if (!this.$useWrapMode) {
return {
row: row,
column: this.documentToScreenColumn(row, column)
}
}
var screenRow = this.documentToScreenRow(row);
var screenColumn = column;
var wrapRowData = wrapData[row];
for (var split = 0; split < wrapRowData.length; split++) {
var wrapRowData = this.$wrapData[row];
for (var split = 0; wrapRowData && split < wrapRowData.length; split++) {
if (column > wrapRowData[split]) {
screenColumn = column - wrapRowData[split];
screenRow ++;
@ -946,6 +973,18 @@ var Document = function(text, mode) {
};
};
this.getScreenLength = function() {
if (!this.$useWrapMode) {
return this.getLength();
}
var screenRows = 0;
for (var row = 0; row < this.$wrapData.length; row++) {
screenRows += this.$wrapData[row].length + 1;
}
return screenRows;
}
}).call(Document.prototype)
exports.Document = Document;

View file

@ -100,7 +100,7 @@ var Cursor = function(parentEl) {
}, 1000);
};
this.getPixelPosition = function() {
this.getPixelPosition = function(onScreen) {
if (!this.config || !this.position) {
return {
left : 0,
@ -111,7 +111,8 @@ var Cursor = function(parentEl) {
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;
var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
this.config.lineHeight;
return {
left : cursorLeft,
@ -125,7 +126,7 @@ var Cursor = function(parentEl) {
this.config = config;
this.pixelPos = this.getPixelPosition();
this.pixelPos = this.getPixelPosition(true);
this.cursor.style.left = this.pixelPos.left + "px";
this.cursor.style.top = this.pixelPos.top + "px";

View file

@ -102,6 +102,10 @@ var Marker = function(parentEl) {
this.element.innerHTML = html.join("");
};
this.$getTop = function(row, layerConfig) {
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
};
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
// selection start
var row = range.start.row;
@ -125,7 +129,7 @@ var Marker = function(parentEl) {
// from selection start to the end of the line
var height = layerConfig.lineHeight;
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
var top = this.$getTop(range.start.row, layerConfig);
var left = Math.round(range.start.column * layerConfig.characterWidth);
stringBuilder.push(
@ -137,7 +141,7 @@ var Marker = function(parentEl) {
);
// from start of the last line to the selection end
var top = (range.end.row - layerConfig.firstRow) * layerConfig.lineHeight;
var top = this.$getTop(range.start.end, layerConfig);
var width = Math.round(range.end.column * layerConfig.characterWidth);
stringBuilder.push(
@ -151,7 +155,7 @@ var Marker = function(parentEl) {
var height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
if (height < 0)
return;
var top = (range.start.row + 1 - layerConfig.firstRow) * layerConfig.lineHeight;
var top = this.$getTop(range.start.row + 1, layerConfig);
stringBuilder.push(
"<div class='", clazz, "' style='",
@ -164,7 +168,7 @@ var Marker = function(parentEl) {
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig) {
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;
var top = this.$getTop(range.start.row, layerConfig);
var left = Math.round(range.start.column * layerConfig.characterWidth);
stringBuilder.push(

View file

@ -96,15 +96,15 @@ var Text = function(parentEl) {
if (!this.$measureNode) {
var measureNode = this.$measureNode = document.createElement("div");
var style = measureNode.style;
style.width = style.height = "auto";
style.left = style.top = "-1000px";
style.visibility = "hidden";
style.position = "absolute";
style.overflow = "visible";
style.whiteSpace = "nowrap";
// in FF 3.6 monospace fonts can have a fixed sub pixel width.
// that's why we have to measure many characters
// Note: characterWidth can be a float!
@ -151,6 +151,12 @@ var Text = function(parentEl) {
this.updateLines = function(config, firstRow, lastRow) {
console.log("layer.text.updateLines", firstRow, lastRow);
this.$computeTabString();
// Due to wrap line changes there can be new lines if e.g.
// the line to updated wrapped in the meantime.
if (this.config.lastRow != config.lastRow ||
this.config.firstRow != config.firstRow) {
this.scrollLines(config);
}
this.config = config;
var first = Math.max(firstRow, config.firstRow);
@ -273,6 +279,7 @@ var Text = function(parentEl) {
};
this.$renderLine = function(stringBuilder, row, tokens) {
console.log("layer.text.renderLine", 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;

View file

@ -326,7 +326,7 @@ var VirtualRenderer = function(container, theme) {
};
this.$updateScrollBar = function() {
this.scrollBar.setInnerHeight(this.doc.getLength() * this.lineHeight);
this.scrollBar.setInnerHeight(this.doc.getScreenLength() * this.lineHeight);
this.scrollBar.setScrollTop(this.scrollTop);
};
@ -399,12 +399,23 @@ var VirtualRenderer = function(container, theme) {
var lineCount = Math.ceil(minHeight / this.lineHeight);
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 lastRow = Math.max(0, Math.min(this.lines.length, firstRow + lineCount) - 1);
var lastRow = firstRow + lineCount - 1;
// Add support for wrapped lines.
var lineHeight = { lineHeight: this.lineHeight };
firstRow = this.doc.screenToDocumentRow(firstRow);
var firstRowScreen = this.doc.documentToScreenRow(firstRow);
lastRow = Math.min(this.doc.screenToDocumentRow(lastRow), this.doc.lines.length - 1);
offset = this.scrollTop % this.doc.getRowHeight(lineHeight, firstRow);
console.log("renderer.computeLayerConfig", firstRow, lastRow);
var layerConfig = this.layerConfig = {
width : longestLine,
padding : this.$padding,
firstRow : firstRow,
firstRowScreen: firstRowScreen,
lastRow : lastRow,
lineHeight : this.lineHeight,
characterWidth : this.characterWidth,
@ -542,7 +553,7 @@ var VirtualRenderer = function(container, theme) {
};
this.scrollToY = function(scrollTop) {
var maxHeight = this.lines.length * this.lineHeight - this.$size.scrollerHeight;
var maxHeight = this.doc.getScreenLength() * this.lineHeight - this.$size.scrollerHeight;
var scrollTop = Math.max(0, Math.min(maxHeight, scrollTop));
if (this.scrollTop !== scrollTop) {