提交 07b89fa3 编写于 作者: A Alex Dima

Optimize view overlays rendering

上级 32ee0c31
......@@ -13,7 +13,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
export interface IDynamicViewOverlay extends IDisposable {
shouldCallRender2(ctx:IRenderingContext): boolean;
render2(lineNumber:number): string[];
render2(startLineNumber:number, lineNumber:number): string;
}
export interface IContentWidgetData {
......
......@@ -23,7 +23,7 @@ export interface IVisibleLineData {
getLineOuterHTML(out:string[], lineNumber: number, deltaTop: number): void;
getLineInnerHTML(lineNumber: number): string;
shouldUpdateHTML(lineNumber:number, inlineDecorations:editorCommon.IModelDecoration[]): boolean;
shouldUpdateHTML(startLineNumber:number, lineNumber:number, inlineDecorations:editorCommon.IModelDecoration[]): boolean;
layoutLine(lineNumber: number, deltaTop:number): void;
}
......@@ -556,7 +556,7 @@ class ViewLayerRenderer {
line = ctx.lines[i];
lineNumber = i + ctx.rendLineNumberStart;
if (line.shouldUpdateHTML(lineNumber, inlineDecorations[i])) {
if (line.shouldUpdateHTML(ctx.rendLineNumberStart, lineNumber, inlineDecorations[i])) {
var lineDomNode = line.getDomNode();
if (!lineDomNode) {
// Line is new
......
......@@ -89,14 +89,14 @@ class ViewOverlayLine implements IVisibleLineData {
private _context:editorBrowser.IViewContext;
private _dynamicOverlays:editorBrowser.IDynamicViewOverlay[];
private _domNode: HTMLElement;
private _renderPieces: string[];
private _renderPieces: string;
constructor(context:editorBrowser.IViewContext, dynamicOverlays:editorBrowser.IDynamicViewOverlay[]) {
this._context = context;
this._dynamicOverlays = dynamicOverlays;
this._domNode = null;
this._renderPieces = null;
this._renderPieces = '';
}
public getDomNode(): HTMLElement {
......@@ -125,41 +125,14 @@ class ViewOverlayLine implements IVisibleLineData {
// Nothing
}
private _piecesEqual(newPieces: string[]): boolean {
if (!this._renderPieces) {
return false;
shouldUpdateHTML(startLineNumber:number, lineNumber:number, inlineDecorations:IModelDecoration[]): boolean {
let newPieces = '';
for (let i = 0; i < this._dynamicOverlays.length; i++) {
newPieces += this._dynamicOverlays[i].render2(startLineNumber, lineNumber);
}
let myLen = this._renderPieces.length;
let newLen = newPieces.length;
let piecesEqual = (this._renderPieces === newPieces);
if (myLen !== newLen) {
return false;
}
if (newLen === 0) {
return true;
}
for (let i = 0; i < newLen; i++) {
if (this._renderPieces[i] !== newPieces[i]) {
return false;
}
}
return true;
}
shouldUpdateHTML(lineNumber:number, inlineDecorations:IModelDecoration[]): boolean {
var newPieces: string[] = [];
for (var i = 0; i < this._dynamicOverlays.length; i++) {
var pieces = this._dynamicOverlays[i].render2(lineNumber);
if (pieces && pieces.length > 0) {
newPieces = newPieces.concat(pieces);
}
}
var piecesEqual = this._piecesEqual(newPieces);
if (!piecesEqual) {
this._renderPieces = newPieces;
}
......@@ -182,7 +155,7 @@ class ViewOverlayLine implements IVisibleLineData {
}
getLineInnerHTML(lineNumber: number): string {
return this._renderPieces.join('');
return this._renderPieces;
}
layoutLine(lineNumber: number, deltaTop:number): void {
......
......@@ -101,21 +101,21 @@ export class CurrentLineHighlightOverlay extends ViewEventHandler implements IDy
return true;
}
public render2(lineNumber:number): string[] {
public render2(startLineNumber:number, lineNumber:number): string {
if (lineNumber === this._primaryCursorLineNumber) {
if (this._shouldShowCurrentLine()) {
return [
'<div class="current-line" style="width:',
String(this._scrollWidth),
'px; height:',
String(this._context.configuration.editor.lineHeight),
'px;"></div>'
];
return (
'<div class="current-line" style="width:'
+ String(this._scrollWidth)
+ 'px; height:'
+ String(this._context.configuration.editor.lineHeight)
+ 'px;"></div>'
);
} else {
return null;
return '';
}
}
return null;
return '';
}
private _shouldShowCurrentLine(): boolean {
......
......@@ -10,14 +10,10 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler';
import {IDynamicViewOverlay, IRenderingContext, IViewContext} from 'vs/editor/browser/editorBrowser';
interface IRenderResult {
[lineNumber:string]:string[];
}
export class DecorationsOverlay extends ViewEventHandler implements IDynamicViewOverlay {
private _context:IViewContext;
private _renderResult:IRenderResult;
private _renderResult: string[];
constructor(context:IViewContext) {
super();
......@@ -112,8 +108,15 @@ export class DecorationsOverlay extends ViewEventHandler implements IDynamicView
return a.range.startLineNumber - b.range.startLineNumber;
});
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
output[lineIndex] = '';
}
// Render first whole line decorations and then regular decorations
let output: IRenderResult = {};
this._renderWholeLineDecorations(ctx, decorations, output);
this._renderNormalDecorations(ctx, decorations, output);
this._renderResult = output;
......@@ -121,8 +124,10 @@ export class DecorationsOverlay extends ViewEventHandler implements IDynamicView
return true;
}
private _renderWholeLineDecorations(ctx:IRenderingContext, decorations:editorCommon.IModelDecoration[], output: IRenderResult): void {
private _renderWholeLineDecorations(ctx:IRenderingContext, decorations:editorCommon.IModelDecoration[], output: string[]): void {
let lineHeight = String(this._context.configuration.editor.lineHeight);
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
for (let i = 0, lenI = decorations.length; i < lenI; i++) {
let d = decorations[i];
......@@ -131,33 +136,26 @@ export class DecorationsOverlay extends ViewEventHandler implements IDynamicView
continue;
}
let decorationOutput = [
'<div class="cdr ',
d.options.className,
'" style="left:0;width:100%;height:',
lineHeight,
'px;"></div>'
].join('');
let decorationOutput = (
'<div class="cdr '
+ d.options.className
+ '" style="left:0;width:100%;height:'
+ lineHeight
+ 'px;"></div>'
);
let startLineNumber = d.range.startLineNumber;
let endLineNumber = d.range.endLineNumber;
let startLineNumber = Math.max(d.range.startLineNumber, visibleStartLineNumber);
let endLineNumber = Math.min(d.range.endLineNumber, visibleEndLineNumber);
for (let j = startLineNumber; j <= endLineNumber; j++) {
if (!ctx.lineIsVisible(j)) {
continue;
}
let strLineNumber = String(j);
if (output.hasOwnProperty(strLineNumber)) {
output[strLineNumber].push(decorationOutput);
} else {
output[strLineNumber] = [decorationOutput];
}
let lineIndex = j - visibleStartLineNumber;
output[lineIndex] += decorationOutput;
}
}
}
private _renderNormalDecorations(ctx:IRenderingContext, decorations:editorCommon.IModelDecoration[], output: IRenderResult): void {
private _renderNormalDecorations(ctx:IRenderingContext, decorations:editorCommon.IModelDecoration[], output: string[]): void {
let lineHeight = String(this._context.configuration.editor.lineHeight);
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
for (let i = 0, lenI = decorations.length; i < lenI; i++) {
let d = decorations[i];
......@@ -173,37 +171,35 @@ export class DecorationsOverlay extends ViewEventHandler implements IDynamicView
let className = d.options.className;
for (let j = 0, lenJ = linesVisibleRanges.length; j < lenJ; j++) {
let lineVisibleRanges = linesVisibleRanges[j];
let strLineNumber = String(lineVisibleRanges.lineNumber);
let lineOutput: string[];
if (output.hasOwnProperty(strLineNumber)) {
lineOutput = output[strLineNumber];
} else {
lineOutput = [];
output[strLineNumber] = lineOutput;
}
let lineIndex = lineVisibleRanges.lineNumber - visibleStartLineNumber;
for (let k = 0, lenK = lineVisibleRanges.ranges.length; k < lenK; k++) {
let visibleRange = lineVisibleRanges.ranges[k];
lineOutput.push('<div class="cdr ');
lineOutput.push(className);
lineOutput.push('" style="left:');
lineOutput.push(String(visibleRange.left));
lineOutput.push('px;width:');
lineOutput.push(String(visibleRange.width));
lineOutput.push('px;height:');
lineOutput.push(lineHeight);
lineOutput.push('px;"></div>');
let decorationOutput = (
'<div class="cdr '
+ className
+ '" style="left:'
+ String(visibleRange.left)
+ 'px;width:'
+ String(visibleRange.width)
+ 'px;height:'
+ lineHeight
+ 'px;"></div>'
);
output[lineIndex] += decorationOutput;
}
}
}
}
public render2(lineNumber:number): string[] {
if (this._renderResult && this._renderResult.hasOwnProperty(lineNumber.toString())) {
return this._renderResult[lineNumber.toString()];
public render2(startLineNumber:number, lineNumber:number): string {
if (!this._renderResult) {
return '';
}
let lineIndex = lineNumber - startLineNumber;
if (lineIndex < 0 || lineIndex >= this._renderResult.length) {
throw new Error('Unexpected render request');
}
return null;
return this._renderResult[lineIndex];
}
}
......@@ -10,16 +10,107 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler';
import {IDynamicViewOverlay, IRenderingContext, IViewContext} from 'vs/editor/browser/editorBrowser';
interface IRenderResult {
[lineNumber:string]:string[];
export class DecorationToRender {
public _decorationToRenderTrait:void;
public startLineNumber:number;
public endLineNumber:number;
public className:string;
public classNameId:number;
constructor(startLineNumber:number, endLineNumber:number, className:string) {
this.startLineNumber = +startLineNumber;
this.endLineNumber = +endLineNumber;
this.className = String(className);
this.classNameId = 0;
}
}
export abstract class DedupOverlay extends ViewEventHandler {
protected _render(visibleStartLineNumber:number, visibleEndLineNumber:number, decorations:DecorationToRender[]): string[] {
if (decorations.length === 0) {
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
output[lineIndex] = '';
}
return output;
}
// Give each unique class name a numeric id
let className2Id: {[className:string]:number;} = Object.create(null);
let id2Classname: string[] = [null];
let lastAssignedId = 0;
for (let i = 0, len = decorations.length; i < len; i++) {
let d = decorations[i];
d.startLineNumber = Math.max(d.startLineNumber, visibleStartLineNumber);
d.endLineNumber = Math.min(d.endLineNumber, visibleEndLineNumber);
if (d.startLineNumber > d.endLineNumber) {
continue;
}
let className = d.className;
let classNameId:number;
let tmp = className2Id[className];
if (tmp) {
classNameId = tmp;
} else {
classNameId = (++lastAssignedId);
id2Classname[classNameId] = className;
className2Id[className] = classNameId;
}
d.classNameId = classNameId;
}
let uniqueRender: boolean[][] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
let uniqueRenderLine:boolean[] = [];
for (let id = 0; id < lastAssignedId; id++) {
uniqueRenderLine[id] = false;
}
uniqueRender[lineIndex] = uniqueRenderLine;
}
for (let i = 0, len = decorations.length; i < len; i++) {
let r = decorations[i];
for (let lineNumber = r.startLineNumber; lineNumber <= r.endLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
uniqueRender[lineIndex][r.classNameId] = true;
}
}
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
let uniqueRenderLine = uniqueRender[lineIndex];
let allClassNames = '';
for (let id = 0; id < lastAssignedId; id++) {
if (uniqueRenderLine[id]) {
allClassNames += ' ' + id2Classname[id];
}
}
output[lineIndex] = allClassNames;
}
return output;
}
}
export class GlyphMarginOverlay extends ViewEventHandler implements IDynamicViewOverlay {
export class GlyphMarginOverlay extends DedupOverlay implements IDynamicViewOverlay {
private _context:IViewContext;
private _glyphMarginLeft:number;
private _glyphMarginWidth:number;
private _renderResult:IRenderResult;
private _renderResult: string[];
constructor(context:IViewContext) {
super();
......@@ -85,6 +176,18 @@ export class GlyphMarginOverlay extends ViewEventHandler implements IDynamicView
// --- end event handlers
protected _getDecorations(ctx:IRenderingContext): DecorationToRender[] {
let decorations = ctx.getDecorationsInViewport();
let r:DecorationToRender[] = [];
for (let i = 0, len = decorations.length; i < len; i++) {
let d = decorations[i];
if (d.options.glyphMarginClassName) {
r.push(new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, d.options.glyphMarginClassName));
}
}
return r;
}
public shouldCallRender2(ctx:IRenderingContext): boolean {
if (!this.shouldRender) {
return false;
......@@ -96,70 +199,42 @@ export class GlyphMarginOverlay extends ViewEventHandler implements IDynamicView
return false;
}
var output: IRenderResult = {};
var count = 0;
var decorations = ctx.getDecorationsInViewport(),
lineHeight = this._context.configuration.editor.lineHeight.toString(),
d:editorCommon.IModelDecoration,
rng:editorCommon.IRange,
i:number, lenI:number,
classNames:{[lineNumber:string]:{[className:string]:boolean;};} = {},
lineClassNames:{[className:string]:boolean;},
className:string,
lineOutput:string[],
lineNumber: number,
lineNumberStr: string;
for (i = 0, lenI = decorations.length; i < lenI; i++) {
d = decorations[i];
if (!d.options.glyphMarginClassName) {
continue;
}
rng = d.range;
for (lineNumber = rng.startLineNumber; lineNumber <= rng.endLineNumber; lineNumber++) {
if (!ctx.lineIsVisible(lineNumber)) {
continue;
}
lineNumberStr = lineNumber.toString();
if (!classNames.hasOwnProperty(lineNumberStr)) {
classNames[lineNumberStr] = {};
}
classNames[lineNumberStr][d.options.glyphMarginClassName] = true;
}
}
var left = this._glyphMarginLeft.toString(),
width = this._glyphMarginWidth.toString();
var common = '" style="left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;"></div>';
for (lineNumberStr in classNames) {
lineClassNames = classNames[lineNumberStr];
lineOutput = [];
lineOutput.push('<div class="cgmr');
for (className in lineClassNames) {
// Count one more glyph
count++;
lineOutput.push(' ');
lineOutput.push(className);
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
let toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));
let lineHeight = this._context.configuration.editor.lineHeight.toString();
let left = this._glyphMarginLeft.toString();
let width = this._glyphMarginWidth.toString();
let common = '" style="left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;"></div>';
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
let classNames = toRender[lineIndex];
if (classNames.length === 0) {
output[lineIndex] = '';
} else {
output[lineIndex] = (
'<div class="cgmr'
+ classNames
+ common
);
}
lineOutput.push(common);
output[lineNumberStr] = lineOutput;
}
this._renderResult = output;
return true;
}
public render2(lineNumber:number): string[] {
if (this._renderResult && this._renderResult.hasOwnProperty(lineNumber.toString())) {
return this._renderResult[lineNumber.toString()];
public render2(startLineNumber:number, lineNumber:number): string {
if (!this._renderResult) {
return '';
}
let lineIndex = lineNumber - startLineNumber;
if (lineIndex < 0 || lineIndex >= this._renderResult.length) {
throw new Error('Unexpected render request');
}
return null;
return this._renderResult[lineIndex];
}
}
\ No newline at end of file
......@@ -11,16 +11,12 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler';
import {ClassNames, IDynamicViewOverlay, IRenderingContext, IViewContext} from 'vs/editor/browser/editorBrowser';
interface IRenderResult {
[lineNumber:string]:string[];
}
export class LineNumbersOverlay extends ViewEventHandler implements IDynamicViewOverlay {
private _context:IViewContext;
private _lineNumbersLeft:number;
private _lineNumbersWidth:number;
private _renderResult:IRenderResult;
private _renderResult:string[];
constructor(context:IViewContext) {
super();
......@@ -97,26 +93,25 @@ export class LineNumbersOverlay extends ViewEventHandler implements IDynamicView
return false;
}
var output: IRenderResult = {};
var lineHeightClassName = (platform.isLinux ? (this._context.configuration.editor.lineHeight % 2 === 0 ? ' lh-even': ' lh-odd') : '');
var lineHeight = this._context.configuration.editor.lineHeight.toString(),
lineNumber:number,
renderLineNumber:string;
var common = '<div class="' + ClassNames.LINE_NUMBERS + lineHeightClassName + '" style="left:' + this._lineNumbersLeft.toString() + 'px;width:' + this._lineNumbersWidth.toString() + 'px;height:' + lineHeight + 'px;">';
let lineHeightClassName = (platform.isLinux ? (this._context.configuration.editor.lineHeight % 2 === 0 ? ' lh-even': ' lh-odd') : '');
let lineHeight = this._context.configuration.editor.lineHeight.toString();
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
let common = '<div class="' + ClassNames.LINE_NUMBERS + lineHeightClassName + '" style="left:' + this._lineNumbersLeft.toString() + 'px;width:' + this._lineNumbersWidth.toString() + 'px;height:' + lineHeight + 'px;">';
for (lineNumber = ctx.visibleRange.startLineNumber; lineNumber <= ctx.visibleRange.endLineNumber; lineNumber++) {
renderLineNumber = this._context.model.getLineRenderLineNumber(lineNumber);
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
let renderLineNumber = this._context.model.getLineRenderLineNumber(lineNumber);
if (renderLineNumber) {
var lineOutput:string[] = [
common,
this._context.model.getLineRenderLineNumber(lineNumber),
'</div>'
];
output[lineNumber.toString()] = lineOutput;
output[lineIndex] = (
common
+ renderLineNumber
+ '</div>'
);
} else {
output[lineIndex] = '';
}
}
......@@ -125,10 +120,14 @@ export class LineNumbersOverlay extends ViewEventHandler implements IDynamicView
return true;
}
public render2(lineNumber:number): string[] {
if (this._renderResult && this._renderResult.hasOwnProperty(lineNumber.toString())) {
return this._renderResult[lineNumber.toString()];
public render2(startLineNumber:number, lineNumber:number): string {
if (!this._renderResult) {
return '';
}
let lineIndex = lineNumber - startLineNumber;
if (lineIndex < 0 || lineIndex >= this._renderResult.length) {
throw new Error('Unexpected render request');
}
return null;
return this._renderResult[lineIndex];
}
}
\ No newline at end of file
......@@ -70,7 +70,7 @@ export class ViewLine implements IVisibleLineData {
this._isInvalid = true;
}
public shouldUpdateHTML(lineNumber:number, inlineDecorations:IModelDecoration[]): boolean {
public shouldUpdateHTML(startLineNumber:number, lineNumber:number, inlineDecorations:IModelDecoration[]): boolean {
let newLineParts:ILineParts = null;
if (this._isMaybeInvalid || this._isInvalid) {
......
......@@ -7,20 +7,16 @@
import 'vs/css!./linesDecorations';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler';
import {IDynamicViewOverlay, IRenderingContext, IViewContext} from 'vs/editor/browser/editorBrowser';
import {DecorationToRender, DedupOverlay} from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';
interface IRenderResult {
[lineNumber:string]:string[];
}
export class LinesDecorationsOverlay extends ViewEventHandler implements IDynamicViewOverlay {
export class LinesDecorationsOverlay extends DedupOverlay implements IDynamicViewOverlay {
private _context:IViewContext;
private _decorationsLeft:number;
private _decorationsWidth:number;
private _renderResult:IRenderResult;
private _renderResult:string[];
constructor(context:IViewContext) {
super();
......@@ -86,78 +82,62 @@ export class LinesDecorationsOverlay extends ViewEventHandler implements IDynami
// --- end event handlers
protected _getDecorations(ctx:IRenderingContext): DecorationToRender[] {
let decorations = ctx.getDecorationsInViewport();
let r:DecorationToRender[] = [];
for (let i = 0, len = decorations.length; i < len; i++) {
let d = decorations[i];
if (d.options.linesDecorationsClassName) {
r.push(new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, d.options.linesDecorationsClassName));
}
}
return r;
}
public shouldCallRender2(ctx:IRenderingContext): boolean {
if (!this.shouldRender) {
return false;
}
this.shouldRender = false;
var output: IRenderResult = {};
var renderedCount = 0;
var decorations = ctx.getDecorationsInViewport(),
lineHeight = this._context.configuration.editor.lineHeight.toString(),
d:editorCommon.IModelDecoration,
rng:editorCommon.IRange,
i:number, lenI:number,
classNames:{[top:string]:{[className:string]:boolean;};} = {},
lineClassNames:{[className:string]:boolean;},
className:string,
lineOutput:string[],
lineNumber: number,
lineNumberStr: string;
for (i = 0, lenI = decorations.length; i < lenI; i++) {
d = decorations[i];
if (!d.options.linesDecorationsClassName) {
continue;
}
rng = d.range;
for (lineNumber = rng.startLineNumber; lineNumber <= rng.endLineNumber; lineNumber++) {
if (!ctx.lineIsVisible(lineNumber)) {
continue;
}
lineNumberStr = lineNumber.toString();
// oldTop = ctx.getViewportVerticalOffsetForLineNumber(j);
if (!classNames.hasOwnProperty(lineNumberStr)) {
classNames[lineNumberStr] = {};
}
classNames[lineNumberStr][d.options.linesDecorationsClassName] = true;
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
let toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));
let lineHeight = this._context.configuration.editor.lineHeight.toString();
let left = this._decorationsLeft.toString();
let width = this._decorationsWidth.toString();
let common = '" style="left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;"></div>';
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
let classNames = toRender[lineIndex];
if (classNames.length === 0) {
output[lineIndex] = '';
} else {
output[lineIndex] = (
'<div class="cldr'
+ classNames
+ common
);
}
}
var left = this._decorationsLeft.toString(),
width = this._decorationsWidth.toString();
var common = '" style="left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;"></div>';
for (lineNumberStr in classNames) {
lineClassNames = classNames[lineNumberStr];
lineOutput = [];
lineOutput.push('<div class="cldr');
for (className in lineClassNames) {
// Count one more glyph
renderedCount++;
lineOutput.push(' ');
lineOutput.push(className);
}
lineOutput.push(common);
output[lineNumberStr] = lineOutput;
}
this._renderResult = output;
return true;
}
public render2(lineNumber:number): string[] {
if (this._renderResult && this._renderResult.hasOwnProperty(lineNumber.toString())) {
return this._renderResult[lineNumber.toString()];
public render2(startLineNumber:number, lineNumber:number): string {
if (!this._renderResult) {
return '';
}
let lineIndex = lineNumber - startLineNumber;
if (lineIndex < 0 || lineIndex >= this._renderResult.length) {
throw new Error('Unexpected render request');
}
return null;
return this._renderResult[lineIndex];
}
}
\ No newline at end of file
......@@ -13,10 +13,6 @@ import {IDynamicViewOverlay, IRenderingContext, IViewContext} from 'vs/editor/br
type HorizontalRange = editorCommon.HorizontalRange;
type LineVisibleRanges = editorCommon.LineVisibleRanges;
interface IRenderResult {
[lineNumber:string]:string[];
}
enum CornerStyle {
EXTERN,
INTERN,
......@@ -82,7 +78,7 @@ export class SelectionsOverlay extends ViewEventHandler implements IDynamicViewO
private _context:IViewContext;
private _selections:editorCommon.IEditorRange[];
private _renderResult:IRenderResult;
private _renderResult:string[];
constructor(context:IViewContext) {
super();
......@@ -285,92 +281,79 @@ export class SelectionsOverlay extends ViewEventHandler implements IDynamicViewO
return linesVisibleRanges;
}
private _createSelectionPiece(lineOutput:string[], top:number, height:string, className:string, left:number, width:number): void {
lineOutput.push('<div class="cslr ');
lineOutput.push(className);
lineOutput.push('" style="top:');
lineOutput.push(top.toString());
lineOutput.push('px;left:');
lineOutput.push(left.toString());
lineOutput.push('px;width:');
lineOutput.push(width.toString());
lineOutput.push('px;height:');
lineOutput.push(height);
lineOutput.push('px;"></div>');
private _createSelectionPiece(top:number, height:string, className:string, left:number, width:number): string {
return (
'<div class="cslr '
+ className
+ '" style="top:'
+ top.toString()
+ 'px;left:'
+ left.toString()
+ 'px;width:'
+ width.toString()
+ 'px;height:'
+ height
+ 'px;"></div>'
);
}
private _actualRenderOneSelection(output:IRenderResult, hasMultipleSelections:boolean, visibleRanges:LineVisibleRangesWithStyle[]): number {
var visibleRangesHaveStyle = (visibleRanges.length > 0 && visibleRanges[0].ranges[0].startStyle),
lineVisibleRanges:LineVisibleRangesWithStyle,
lineOutput: string[],
className:string,
fullLineHeight = (this._context.configuration.editor.lineHeight).toString(),
reducedLineHeight = (this._context.configuration.editor.lineHeight - 1).toString(),
i:number, len:number,
j:number, lenJ:number,
piecesCount = 0,
visibleRange:HorizontalRangeWithStyle;
private _actualRenderOneSelection(output2:string[], visibleStartLineNumber:number, hasMultipleSelections:boolean, visibleRanges:LineVisibleRangesWithStyle[]): void {
let visibleRangesHaveStyle = (visibleRanges.length > 0 && visibleRanges[0].ranges[0].startStyle);
let fullLineHeight = (this._context.configuration.editor.lineHeight).toString();
let reducedLineHeight = (this._context.configuration.editor.lineHeight - 1).toString();
let firstLineNumber = (visibleRanges.length > 0 ? visibleRanges[0].lineNumber : 0);
let lastLineNumber = (visibleRanges.length > 0 ? visibleRanges[visibleRanges.length - 1].lineNumber : 0);
for (i = 0, len = visibleRanges.length; i < len; i++) {
lineVisibleRanges = visibleRanges[i];
for (let i = 0, len = visibleRanges.length; i < len; i++) {
let lineVisibleRanges = visibleRanges[i];
let lineNumber = lineVisibleRanges.lineNumber;
let lineIndex = lineNumber - visibleStartLineNumber;
let lineHeight = hasMultipleSelections ? (lineNumber === lastLineNumber || lineNumber === firstLineNumber ? reducedLineHeight : fullLineHeight) : fullLineHeight;
let top = hasMultipleSelections ? (lineNumber === firstLineNumber ? 1 : 0) : 0;
if (output.hasOwnProperty(lineNumber.toString())) {
lineOutput = output[lineNumber.toString()];
} else {
lineOutput = [];
output[lineNumber.toString()] = lineOutput;
}
let lineOutput = '';
for (j = 0, lenJ = lineVisibleRanges.ranges.length; j < lenJ; j++) {
visibleRange = lineVisibleRanges.ranges[j];
for (let j = 0, lenJ = lineVisibleRanges.ranges.length; j < lenJ; j++) {
let visibleRange = lineVisibleRanges.ranges[j];
if (visibleRangesHaveStyle) {
if (visibleRange.startStyle.top === CornerStyle.INTERN || visibleRange.startStyle.bottom === CornerStyle.INTERN) {
// Reverse rounded corner to the left
// First comes the selection (blue layer)
piecesCount++;
this._createSelectionPiece(lineOutput, top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
lineOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
// Second comes the background (white layer) with inverse border radius
className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;
let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;
if (visibleRange.startStyle.top === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_TOP_RIGHT;
}
if (visibleRange.startStyle.bottom === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT;
}
piecesCount++;
this._createSelectionPiece(lineOutput, top, lineHeight, className, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
}
if (visibleRange.endStyle.top === CornerStyle.INTERN || visibleRange.endStyle.bottom === CornerStyle.INTERN) {
// Reverse rounded corner to the right
// First comes the selection (blue layer)
piecesCount++;
this._createSelectionPiece(lineOutput, top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
lineOutput += this._createSelectionPiece(top, lineHeight, SelectionsOverlay.SELECTION_CLASS_NAME, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
// Second comes the background (white layer) with inverse border radius
className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;
let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;
if (visibleRange.endStyle.top === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_TOP_LEFT;
}
if (visibleRange.endStyle.bottom === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_LEFT;
}
piecesCount++;
this._createSelectionPiece(lineOutput, top, lineHeight, className, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
}
}
className = SelectionsOverlay.SELECTION_CLASS_NAME;
let className = SelectionsOverlay.SELECTION_CLASS_NAME;
if (visibleRangesHaveStyle) {
if (visibleRange.startStyle.top === CornerStyle.EXTERN) {
className += ' ' + SelectionsOverlay.SELECTION_TOP_LEFT;
......@@ -385,12 +368,11 @@ export class SelectionsOverlay extends ViewEventHandler implements IDynamicViewO
className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT;
}
}
piecesCount++;
this._createSelectionPiece(lineOutput, top, lineHeight, className, visibleRange.left, visibleRange.width);
lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left, visibleRange.width);
}
}
return piecesCount;
output2[lineIndex] += lineOutput;
}
}
private _previousFrameVisibleRangesWithStyle: LineVisibleRangesWithStyle[][] = [];
......@@ -400,23 +382,25 @@ export class SelectionsOverlay extends ViewEventHandler implements IDynamicViewO
}
this.shouldRender = false;
var output: IRenderResult = {},
selection:editorCommon.IEditorRange,
visibleRangesWithStyle:LineVisibleRangesWithStyle[],
piecesCount = 0,
i:number,
thisFrameVisibleRangesWithStyle: LineVisibleRangesWithStyle[][] = [];
let output: string[] = [];
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
output[lineIndex] = '';
}
for (i = 0; i < this._selections.length; i++) {
selection = this._selections[i];
let thisFrameVisibleRangesWithStyle: LineVisibleRangesWithStyle[][] = [];
for (let i = 0, len = this._selections.length; i < len; i++) {
let selection = this._selections[i];
if (selection.isEmpty()) {
thisFrameVisibleRangesWithStyle.push(null);
continue;
}
visibleRangesWithStyle = this._getVisibleRangesWithStyle(selection, ctx, this._previousFrameVisibleRangesWithStyle[i]);
let visibleRangesWithStyle = this._getVisibleRangesWithStyle(selection, ctx, this._previousFrameVisibleRangesWithStyle[i]);
thisFrameVisibleRangesWithStyle.push(visibleRangesWithStyle);
piecesCount += this._actualRenderOneSelection(output, this._selections.length > 1, visibleRangesWithStyle);
this._actualRenderOneSelection(output, visibleStartLineNumber, this._selections.length > 1, visibleRangesWithStyle);
}
this._previousFrameVisibleRangesWithStyle = thisFrameVisibleRangesWithStyle;
......@@ -425,10 +409,14 @@ export class SelectionsOverlay extends ViewEventHandler implements IDynamicViewO
return true;
}
public render2(lineNumber:number): string[] {
if (this._renderResult && this._renderResult.hasOwnProperty(lineNumber.toString())) {
return this._renderResult[lineNumber.toString()];
public render2(startLineNumber:number, lineNumber:number): string {
if (!this._renderResult) {
return '';
}
let lineIndex = lineNumber - startLineNumber;
if (lineIndex < 0 || lineIndex >= this._renderResult.length) {
throw new Error('Unexpected render request');
}
return null;
return this._renderResult[lineIndex];
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册