diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts
index 7f278afa2f05ad86692b94cdbf64ec5dd00d77db..a9802d855c6f0b8de750029ba860d98bcb9d52fd 100644
--- a/src/vs/editor/browser/viewParts/lines/viewLine.ts
+++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts
@@ -122,10 +122,13 @@ export class ViewLine implements IVisibleLineData {
return false;
}
+ let isWhitespaceOnly = /^\s*$/.test(renderLineInput.lineContent);
+
this._renderedViewLine = createRenderedLine(
this._renderedViewLine ? this._renderedViewLine.domNode : null,
renderLineInput,
this._context.model.mightContainRTL(),
+ isWhitespaceOnly,
renderLine(renderLineInput)
);
return true;
@@ -183,12 +186,12 @@ class RenderedViewLine {
*/
private _pixelOffsetCache: number[];
- constructor(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, renderLineOutput: RenderLineOutput) {
+ constructor(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput) {
this.domNode = domNode;
this.input = renderLineInput;
this.html = renderLineOutput.output;
this._characterMapping = renderLineOutput.characterMapping;
- this._isWhitespaceOnly = renderLineOutput.isWhitespaceOnly;
+ this._isWhitespaceOnly = isWhitespaceOnly;
this._cachedWidth = -1;
this._pixelOffsetCache = null;
@@ -376,17 +379,17 @@ class WebKitRenderedViewLine extends RenderedViewLine {
}
}
-const createRenderedLine: (domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, renderLineOutput: RenderLineOutput) => RenderedViewLine = (function () {
+const createRenderedLine: (domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput) => RenderedViewLine = (function () {
if (browser.isWebKit) {
return createWebKitRenderedLine;
}
return createNormalRenderedLine;
})();
-function createWebKitRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
- return new WebKitRenderedViewLine(domNode, renderLineInput, modelContainsRTL, renderLineOutput);
+function createWebKitRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
+ return new WebKitRenderedViewLine(domNode, renderLineInput, modelContainsRTL, isWhitespaceOnly, renderLineOutput);
}
-function createNormalRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
- return new RenderedViewLine(domNode, renderLineInput, modelContainsRTL, renderLineOutput);
+function createNormalRenderedLine(domNode: FastDomNode, renderLineInput: RenderLineInput, modelContainsRTL: boolean, isWhitespaceOnly: boolean, renderLineOutput: RenderLineOutput): RenderedViewLine {
+ return new RenderedViewLine(domNode, renderLineInput, modelContainsRTL, isWhitespaceOnly, renderLineOutput);
}
diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts
index 58621061fbc794ed4bfaab5373907272f833febb..1bc4ee9443e754456e2ccdbf299b8c9158a6fe6e 100644
--- a/src/vs/editor/common/viewLayout/viewLineRenderer.ts
+++ b/src/vs/editor/common/viewLayout/viewLineRenderer.ts
@@ -166,12 +166,10 @@ export class RenderLineOutput {
readonly characterMapping: CharacterMapping;
readonly output: string;
- readonly isWhitespaceOnly: boolean;
- constructor(characterMapping: CharacterMapping, output: string, isWhitespaceOnly: boolean) {
+ constructor(characterMapping: CharacterMapping, output: string) {
this.characterMapping = characterMapping;
this.output = output;
- this.isWhitespaceOnly = isWhitespaceOnly;
}
}
@@ -189,8 +187,7 @@ export function renderLine(input: RenderLineInput): RenderLineOutput {
return new RenderLineOutput(
new CharacterMapping(0),
// This is basically for IE's hit test to work
- ' ',
- true
+ ' '
);
}
@@ -198,7 +195,10 @@ export function renderLine(input: RenderLineInput): RenderLineOutput {
throw new Error('Cannot render non empty line without line parts!');
}
- return renderLineActual(lineText, lineTextLength, tabSize, spaceWidth, actualLineParts, renderWhitespace, renderControlCharacters, charBreakIndex);
+ let viewParts = toViewParts(lineText, lineTextLength, tabSize, spaceWidth, actualLineParts, renderWhitespace, renderControlCharacters, charBreakIndex);
+ return renderViewParts(viewParts);
+
+ // return renderLineActual(lineText, lineTextLength, tabSize, spaceWidth, actualLineParts, renderWhitespace, renderControlCharacters, charBreakIndex);
}
function isWhitespace(type: string): boolean {
@@ -214,20 +214,40 @@ function controlCharacterToPrintable(characterCode: number): string {
return String.fromCharCode(_controlCharacterSequenceConversionStart + characterCode);
}
-function renderLineActual(lineText: string, lineTextLength: number, tabSize: number, spaceWidth: number, actualLineParts: ViewLineToken[], renderWhitespace: 'none' | 'boundary' | 'all', renderControlCharacters: boolean, charBreakIndex: number): RenderLineOutput {
+class ViewPart2 {
+ public readonly className: string;
+ public readonly htmlContent: string;
+ public readonly forceWidth: number;
+
+ constructor(className: string, htmlContent: string, forceWidth: number) {
+ this.className = className;
+ this.htmlContent = htmlContent;
+ this.forceWidth = forceWidth;
+ }
+}
+
+class ViewParts2 {
+ public readonly parts: ViewPart2[];
+ public readonly characterMapping: CharacterMapping;
+
+ constructor(parts: ViewPart2[], characterMapping: CharacterMapping) {
+ this.parts = parts;
+ this.characterMapping = characterMapping;
+ }
+}
+
+function toViewParts(lineText: string, lineTextLength: number, tabSize: number, spaceWidth: number, actualLineParts: ViewLineToken[], renderWhitespace: 'none' | 'boundary' | 'all', renderControlCharacters: boolean, charBreakIndex: number): ViewParts2 {
lineTextLength = +lineTextLength;
tabSize = +tabSize;
charBreakIndex = +charBreakIndex;
let charIndex = 0;
- let out = '';
let charOffsetInPart = 0;
let tabsCharDelta = 0;
- let isWhitespaceOnly = /^\s*$/.test(lineText);
let characterMapping = new CharacterMapping(Math.min(lineTextLength, charBreakIndex) + 1);
- out += '';
+ let result: ViewPart2[] = [], resultLen = 0;
for (let partIndex = 0, partIndexLen = actualLineParts.length; partIndex < partIndexLen; partIndex++) {
let part = actualLineParts[partIndex];
@@ -271,18 +291,14 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
charOffsetInPart++;
if (charIndex >= charBreakIndex) {
- out += `${partContent}…`;
+ result[resultLen++] = new ViewPart2(part.type, partContent + '…', 0);
characterMapping.setPartData(charIndex, partIndex, charOffsetInPart);
- return new RenderLineOutput(
- characterMapping,
- out,
- isWhitespaceOnly
- );
+ return new ViewParts2(result, characterMapping);
}
}
- out += `${partContent}`;
+ result[resultLen++] = new ViewPart2(part.type, partContent, (spaceWidth * partContentCnt));
} else {
- out += ``;
+ let partContent = '';
for (; charIndex < toCharIndex; charIndex++) {
characterMapping.setPartData(charIndex, partIndex, charOffsetInPart);
@@ -294,75 +310,81 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
tabsCharDelta += insertSpacesCount - 1;
charOffsetInPart += insertSpacesCount - 1;
while (insertSpacesCount > 0) {
- out += ' ';
+ partContent += ' ';
insertSpacesCount--;
}
break;
case CharCode.Space:
- out += ' ';
+ partContent += ' ';
break;
case CharCode.LessThan:
- out += '<';
+ partContent += '<';
break;
case CharCode.GreaterThan:
- out += '>';
+ partContent += '>';
break;
case CharCode.Ampersand:
- out += '&';
+ partContent += '&';
break;
case CharCode.Null:
- out += '';
+ partContent += '';
break;
case CharCode.UTF8_BOM:
case CharCode.LINE_SEPARATOR_2028:
- out += '\ufffd';
+ partContent += '\ufffd';
break;
case CharCode.CarriageReturn:
// zero width space, because carriage return would introduce a line break
- out += '';
+ partContent += '';
break;
default:
if (renderControlCharacters && isControlCharacter(charCode)) {
- out += controlCharacterToPrintable(charCode);
+ partContent += controlCharacterToPrintable(charCode);
} else {
- out += lineText.charAt(charIndex);
+ partContent += lineText.charAt(charIndex);
}
}
charOffsetInPart++;
if (charIndex >= charBreakIndex) {
- out += '…';
+ result[resultLen++] = new ViewPart2(part.type, partContent + '…', 0);
characterMapping.setPartData(charIndex, partIndex, charOffsetInPart);
- return new RenderLineOutput(
- characterMapping,
- out,
- isWhitespaceOnly
- );
+ return new ViewParts2(result, characterMapping);
}
}
-
- out += '';
+ result[resultLen++] = new ViewPart2(part.type, partContent, 0);
}
-
}
- out += '';
// When getting client rects for the last character, we will position the
// text range at the end of the span, insteaf of at the beginning of next span
characterMapping.setPartData(lineTextLength, actualLineParts.length - 1, charOffsetInPart);
- return new RenderLineOutput(
- characterMapping,
- out,
- isWhitespaceOnly
- );
+ return new ViewParts2(result, characterMapping);
+}
+
+function renderViewParts(viewParts: ViewParts2): RenderLineOutput {
+ const parts = viewParts.parts;
+
+ let out = '';
+ for (let i = 0, len = parts.length; i < len; i++) {
+ let part = parts[i];
+ if (part.forceWidth) {
+ out += `${part.htmlContent}`;
+ } else {
+ out += `${part.htmlContent}`;
+ }
+ }
+ out += '';
+
+ return new RenderLineOutput(viewParts.characterMapping, out);
}