Move getAllOverviewRulerDecorations to IViewModelLinesCollection

This commit is contained in:
Alex Dima
2017-10-20 08:43:45 +02:00
parent 69952f21a9
commit 30e2d204a0
5 changed files with 193 additions and 58 deletions
@@ -14,9 +14,8 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { editorOverviewRulerBorder, editorCursorForeground } from 'vs/editor/common/view/editorColorRegistry';
import { Color } from 'vs/base/common/color';
import { ITheme, ThemeColor } from 'vs/platform/theme/common/themeService';
import { ITheme } from 'vs/platform/theme/common/themeService';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations';
class Settings {
@@ -275,12 +274,7 @@ export class DecorationsOverviewRuler2 extends ViewPart {
}
public onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean {
// invalidate color cache
const decorations = this._context.model.getAllOverviewRulerDecorations();
for (let i = 0, len = decorations.length; i < len; i++) {
const decoration = decorations[i];
const opts = <ModelDecorationOverviewRulerOptions>decoration.source.options.overviewRuler;
opts._resolvedColor = null;
}
this._context.model.invalidateOverviewRulerColorCache();
return this._updateSettings(false);
}
@@ -303,10 +297,9 @@ export class DecorationsOverviewRuler2 extends ViewPart {
const canvasHeight = this._settings.canvasHeight;
const lineHeight = this._settings.lineHeight;
const viewLayout = this._context.viewLayout;
const theme = this._context.theme;
const outerHeight = this._context.viewLayout.getScrollHeight();
const heightRatio = canvasHeight / outerHeight;
const decorations = this._context.model.getAllOverviewRulerDecorations();
const decorations = this._context.model.getAllOverviewRulerDecorations(this._context.theme);
const minDecorationHeight = (Constants.MIN_DECORATION_HEIGHT * this._settings.pixelRatio) | 0;
const halfMinDecorationHeight = (minDecorationHeight / 2) | 0;
@@ -322,17 +315,12 @@ export class DecorationsOverviewRuler2 extends ViewPart {
const paintQueue = new PaintQueue(canvasCtx, this._settings.x, this._settings.w);
for (let i = 0, len = decorations.length; i < len; i++) {
const decoration = decorations[i];
const opts = <ModelDecorationOverviewRulerOptions>decoration.source.options.overviewRuler;
const lane = opts.position;
if (lane === 0) {
if (decoration.lane === 0) {
continue;
}
const startLineNumber = decoration.range.startLineNumber;
const endLineNumber = decoration.range.endLineNumber;
const color = resolveColor(opts, theme);
let y1 = (viewLayout.getVerticalOffsetForLineNumber(startLineNumber) * heightRatio) | 0;
let y2 = ((viewLayout.getVerticalOffsetForLineNumber(endLineNumber) + lineHeight) * heightRatio) | 0;
let y1 = (viewLayout.getVerticalOffsetForLineNumber(decoration.startLineNumber) * heightRatio) | 0;
let y2 = ((viewLayout.getVerticalOffsetForLineNumber(decoration.endLineNumber) + lineHeight) * heightRatio) | 0;
let height = y2 - y1;
if (height < minDecorationHeight) {
let yCenter = ((y1 + y2) / 2) | 0;
@@ -345,7 +333,7 @@ export class DecorationsOverviewRuler2 extends ViewPart {
y2 = yCenter + halfMinDecorationHeight;
}
paintQueueAccept(paintQueue, color, y1, y2, lane);
paintQueueAccept(paintQueue, decoration.color, y1, y2, decoration.lane);
}
for (let i = 0, len = paintQueue.req.length; i < len; i++) {
paintQueueFlush(paintQueue, paintQueue.req[i]);
@@ -448,7 +436,9 @@ function paintQueueAccept(Q: PaintQueue, color: string, y1: number, y2: number,
if (result !== null) {
// there is already an ongoing request for this color & lane
// => simply merge into it
result.y2 = y2;
if (y2 > result.y2) {
result.y2 = y2;
}
return;
}
@@ -466,23 +456,3 @@ function paintQueueFlush(Q: PaintQueue, req: PaintRequest): void {
Q.ctx.fillStyle = req.color;
Q.ctx.fillRect(Q.x[req.lane], req.y1, Q.w[req.lane], req.y2 - req.y1);
}
function resolveColor(opts: ModelDecorationOverviewRulerOptions, theme: ITheme): string {
if (!opts._resolvedColor) {
const themeType = theme.type;
const color = (themeType === 'dark' ? opts.darkColor : themeType === 'light' ? opts.color : opts.hcColor);
opts._resolvedColor = resolveRulerColor(color, theme);
}
return opts._resolvedColor;
}
function resolveRulerColor(color: string | ThemeColor, theme: ITheme): string {
if (typeof color === 'string') {
return color;
}
let c = color ? theme.getColor(color.id) : null;
if (!c) {
c = Color.transparent;
}
return c.toString();
}
@@ -10,10 +10,12 @@ import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { PrefixSumComputerWithCache } from 'vs/editor/common/viewModel/prefixSumComputer';
import { ViewLineData, ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel';
import { ViewLineData, ICoordinatesConverter, OverviewRulerDecoration } from 'vs/editor/common/viewModel/viewModel';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { WrappingIndent } from 'vs/editor/common/config/editorOptions';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations';
import { ModelDecorationOptions, ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations';
import { ThemeColor, ITheme } from 'vs/platform/theme/common/themeService';
import { Color } from 'vs/base/common/color';
export class OutputPosition {
_outputPositionBrand: void;
@@ -57,6 +59,7 @@ export interface ISplitLine {
getModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number;
getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position;
getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number;
}
export interface IViewModelLinesCollection {
@@ -82,6 +85,8 @@ export interface IViewModelLinesCollection {
getViewLineMaxColumn(viewLineNumber: number): number;
getViewLineData(viewLineNumber: number): ViewLineData;
getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): ViewLineData[];
getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[];
}
export class CoordinatesConverter implements ICoordinatesConverter {
@@ -650,6 +655,42 @@ export class SplitLinesCollection implements IViewModelLinesCollection {
// console.log('in -> out ' + inputLineNumber + ',' + inputColumn + ' ===> ' + r.lineNumber + ',' + r);
return r;
}
private _getViewLineNumberForModelPosition(inputLineNumber: number, inputColumn: number): number {
let lineIndex = inputLineNumber - 1;
if (this.lines[lineIndex].isVisible()) {
// this model line is visible
const deltaLineNumber = 1 + (lineIndex === 0 ? 0 : this.prefixSumComputer.getAccumulatedValue(lineIndex - 1));
return this.lines[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, inputColumn);
}
// this model line is not visible
while (lineIndex > 0 && !this.lines[lineIndex].isVisible()) {
lineIndex--;
}
if (lineIndex === 0 && !this.lines[lineIndex].isVisible()) {
// Could not reach a real line
return 1;
}
const deltaLineNumber = 1 + (lineIndex === 0 ? 0 : this.prefixSumComputer.getAccumulatedValue(lineIndex - 1));
return this.lines[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1));
}
public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[] {
const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation);
const result = new OverviewRulerDecorations();
for (let i = 0, len = decorations.length; i < len; i++) {
const decoration = decorations[i];
const opts = <ModelDecorationOverviewRulerOptions>decoration.options.overviewRuler;
const lane = opts.position;
const color = resolveColor(opts, theme);
const viewStartLineNumber = this._getViewLineNumberForModelPosition(decoration.range.startLineNumber, decoration.range.startColumn);
const viewEndLineNumber = this._getViewLineNumberForModelPosition(decoration.range.endLineNumber, decoration.range.endColumn);
result.accept(color, viewStartLineNumber, viewEndLineNumber, lane);
}
return result.result;
}
}
class VisibleIdentitySplitLine implements ISplitLine {
@@ -711,6 +752,10 @@ class VisibleIdentitySplitLine implements ISplitLine {
public getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position {
return new Position(deltaLineNumber, inputColumn);
}
public getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number {
return deltaLineNumber;
}
}
class InvisibleIdentitySplitLine implements ISplitLine {
@@ -761,6 +806,10 @@ class InvisibleIdentitySplitLine implements ISplitLine {
public getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position {
throw new Error('Not supported');
}
public getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number {
throw new Error('Not supported');
}
}
export class SplitLine implements ISplitLine {
@@ -914,6 +963,14 @@ export class SplitLine implements ISplitLine {
// console.log('in -> out ' + deltaLineNumber + ',' + inputColumn + ' ===> ' + (deltaLineNumber+outputLineIndex) + ',' + outputColumn);
return new Position(deltaLineNumber + outputLineIndex, outputColumn);
}
public getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number {
if (!this._isVisible) {
throw new Error('Not supported');
}
const r = this.positionMapper.getOutputPositionOfInputOffset(inputColumn - 1);
return (deltaLineNumber + r.outputLineIndex);
}
}
function createSplitLine(linePositionMapperFactory: ILineMapperFactory, text: string, tabSize: number, wrappingColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent, isVisible: boolean): ISplitLine {
@@ -1093,4 +1150,99 @@ export class IdentityLinesCollection implements IViewModelLinesCollection {
return result;
}
public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): OverviewRulerDecoration[] {
const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation);
const result = new OverviewRulerDecorations();
for (let i = 0, len = decorations.length; i < len; i++) {
const decoration = decorations[i];
const opts = <ModelDecorationOverviewRulerOptions>decoration.options.overviewRuler;
const lane = opts.position;
const color = resolveColor(opts, theme);
const viewStartLineNumber = decoration.range.startLineNumber;
const viewEndLineNumber = decoration.range.endLineNumber;
result.accept(color, viewStartLineNumber, viewEndLineNumber, lane);
}
result.flushAll();
return result.result;
}
}
class OverviewRulerDecorations {
readonly req: OverviewRulerDecoration[] = [];
readonly result: OverviewRulerDecoration[] = [];
constructor() {
}
public accept(color: string, startLineNumber: number, endLineNumber: number, lane: number): void {
let result: OverviewRulerDecoration = null;
for (let i = 0, len = this.req.length; i < len; i++) {
const req = this.req[i];
if (req.endLineNumber < startLineNumber) {
this._flush(req);
if (i + 1 === len) {
// last element
this.req.pop();
break;
} else {
this.req[i] = this.req.pop();
len--;
i--;
continue;
}
}
if (req.lane === lane && req.color === color) {
result = req;
break;
}
}
if (result !== null) {
// there is already an ongoing request for this color & lane
// => simply merge into it
if (endLineNumber > result.endLineNumber) {
result.endLineNumber = endLineNumber;
}
return;
}
result = new OverviewRulerDecoration(startLineNumber, endLineNumber, lane, color);
this.req.push(result);
}
public flushAll(): void {
for (let i = 0, len = this.req.length; i < len; i++) {
this._flush(this.req[i]);
}
}
private _flush(element: OverviewRulerDecoration): void {
this.result.push(element);
}
}
function resolveColor(opts: ModelDecorationOverviewRulerOptions, theme: ITheme): string {
if (!opts._resolvedColor) {
const themeType = theme.type;
const color = (themeType === 'dark' ? opts.darkColor : themeType === 'light' ? opts.color : opts.hcColor);
opts._resolvedColor = resolveRulerColor(color, theme);
}
return opts._resolvedColor;
}
function resolveRulerColor(color: string | ThemeColor, theme: ITheme): string {
if (typeof color === 'string') {
return color;
}
let c = color ? theme.getColor(color.id) : null;
if (!c) {
c = Color.transparent;
}
return c.toString();
}
+15 -2
View File
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { INewScrollPosition, IModelDecoration, EndOfLinePreference, IViewState } from 'vs/editor/common/editorCommon';
import { INewScrollPosition, IModelDecoration, EndOfLinePreference, IViewState, OverviewRulerLane } from 'vs/editor/common/editorCommon';
import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@@ -14,6 +14,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { Scrollable, IScrollPosition } from 'vs/base/common/scrollable';
import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
import { ITheme } from 'vs/platform/theme/common/themeService';
export interface IViewWhitespaceViewportData {
readonly id: number;
@@ -138,7 +139,8 @@ export interface IViewModel {
getLineMaxColumn(lineNumber: number): number;
getLineFirstNonWhitespaceColumn(lineNumber: number): number;
getLineLastNonWhitespaceColumn(lineNumber: number): number;
getAllOverviewRulerDecorations(): ViewModelDecoration[];
getAllOverviewRulerDecorations(theme: ITheme): OverviewRulerDecoration[];
invalidateOverviewRulerColorCache(): void;
getValueInRange(range: Range, eol: EndOfLinePreference): string;
getModelLineMaxColumn(modelLineNumber: number): number;
@@ -276,6 +278,17 @@ export class ViewModelDecoration {
}
}
export class OverviewRulerDecoration {
_overviewRulerDecorationBrand: void;
constructor(
public readonly startLineNumber: number,
public endLineNumber: number,
public readonly lane: OverviewRulerLane,
public readonly color: string
) { }
}
export class ViewEventsCollector {
private _events: ViewEvent[];
@@ -88,17 +88,6 @@ export class ViewModelDecorations implements IDisposable {
return r;
}
public getAllOverviewRulerDecorations(): ViewModelDecoration[] {
let modelDecorations = this.model.getOverviewRulerDecorations(this.editorId, this.configuration.editor.readOnly);
let result: ViewModelDecoration[] = [], resultLen = 0;
for (let i = 0, len = modelDecorations.length; i < len; i++) {
let modelDecoration = modelDecorations[i];
let viewModelDecoration = this._getOrCreateViewModelDecoration(modelDecoration);
result[resultLen++] = viewModelDecoration;
}
return result;
}
public getDecorationsViewportData(viewRange: Range): IDecorationsViewportData {
var cacheIsValid = true;
cacheIsValid = cacheIsValid && (this._cachedModelDecorationsResolver !== null);
@@ -12,7 +12,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import { TokenizationRegistry, ColorId, LanguageId } from 'vs/editor/common/modes';
import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer';
import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations';
import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, ViewEventsCollector } from 'vs/editor/common/viewModel/viewModel';
import { MinimapLinesRenderingData, ViewLineRenderingData, ViewModelDecoration, IViewModel, ICoordinatesConverter, ViewEventsCollector, OverviewRulerDecoration } from 'vs/editor/common/viewModel/viewModel';
import { SplitLinesCollection, IViewModelLinesCollection, IdentityLinesCollection } from 'vs/editor/common/viewModel/splitLinesCollection';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { MinimapTokensColorTracker } from 'vs/editor/common/view/minimapCharRenderer';
@@ -22,6 +22,8 @@ import { CharacterHardWrappingLineMapperFactory } from 'vs/editor/common/viewMod
import { ViewLayout } from 'vs/editor/common/viewLayout/viewLayout';
import { Color } from 'vs/base/common/color';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ITheme } from 'vs/platform/theme/common/themeService';
import { ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModelWithDecorations';
const USE_IDENTITY_LINES_COLLECTION = true;
@@ -428,8 +430,17 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
);
}
public getAllOverviewRulerDecorations(): ViewModelDecoration[] {
return this.decorations.getAllOverviewRulerDecorations();
public getAllOverviewRulerDecorations(theme: ITheme): OverviewRulerDecoration[] {
return this.lines.getAllOverviewRulerDecorations(this.editorId, this.configuration.editor.readOnly, theme);
}
public invalidateOverviewRulerColorCache(): void {
const decorations = this.model.getOverviewRulerDecorations();
for (let i = 0, len = decorations.length; i < len; i++) {
const decoration = decorations[i];
const opts = <ModelDecorationOverviewRulerOptions>decoration.options.overviewRuler;
opts._resolvedColor = null;
}
}
public getValueInRange(range: Range, eol: editorCommon.EndOfLinePreference): string {