Fix problems when scolling + wrapped lines
This commit is contained in:
parent
c30b9ece8f
commit
609f062803
5 changed files with 82 additions and 20 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue