Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/common/viewModel/overviewZoneManager.ts
3294 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
const enum Constants {
7
MINIMUM_HEIGHT = 4
8
}
9
10
export class ColorZone {
11
_colorZoneBrand: void = undefined;
12
13
public readonly from: number;
14
public readonly to: number;
15
public readonly colorId: number;
16
17
constructor(from: number, to: number, colorId: number) {
18
this.from = from | 0;
19
this.to = to | 0;
20
this.colorId = colorId | 0;
21
}
22
23
public static compare(a: ColorZone, b: ColorZone): number {
24
if (a.colorId === b.colorId) {
25
if (a.from === b.from) {
26
return a.to - b.to;
27
}
28
return a.from - b.from;
29
}
30
return a.colorId - b.colorId;
31
}
32
}
33
34
/**
35
* A zone in the overview ruler
36
*/
37
export class OverviewRulerZone {
38
_overviewRulerZoneBrand: void = undefined;
39
40
public readonly startLineNumber: number;
41
public readonly endLineNumber: number;
42
/**
43
* If set to 0, the height in lines will be determined based on `endLineNumber`.
44
*/
45
public readonly heightInLines: number;
46
public readonly color: string;
47
48
private _colorZone: ColorZone | null;
49
50
constructor(
51
startLineNumber: number,
52
endLineNumber: number,
53
heightInLines: number,
54
color: string
55
) {
56
this.startLineNumber = startLineNumber;
57
this.endLineNumber = endLineNumber;
58
this.heightInLines = heightInLines;
59
this.color = color;
60
this._colorZone = null;
61
}
62
63
public static compare(a: OverviewRulerZone, b: OverviewRulerZone): number {
64
if (a.color === b.color) {
65
if (a.startLineNumber === b.startLineNumber) {
66
if (a.heightInLines === b.heightInLines) {
67
return a.endLineNumber - b.endLineNumber;
68
}
69
return a.heightInLines - b.heightInLines;
70
}
71
return a.startLineNumber - b.startLineNumber;
72
}
73
return a.color < b.color ? -1 : 1;
74
}
75
76
public setColorZone(colorZone: ColorZone): void {
77
this._colorZone = colorZone;
78
}
79
80
public getColorZones(): ColorZone | null {
81
return this._colorZone;
82
}
83
}
84
85
export class OverviewZoneManager {
86
87
private readonly _getVerticalOffsetForLine: (lineNumber: number) => number;
88
private _zones: OverviewRulerZone[];
89
private _colorZonesInvalid: boolean;
90
private _lineHeight: number;
91
private _domWidth: number;
92
private _domHeight: number;
93
private _outerHeight: number;
94
private _pixelRatio: number;
95
96
private _lastAssignedId: number;
97
private readonly _color2Id: { [color: string]: number };
98
private readonly _id2Color: string[];
99
100
constructor(getVerticalOffsetForLine: (lineNumber: number) => number) {
101
this._getVerticalOffsetForLine = getVerticalOffsetForLine;
102
this._zones = [];
103
this._colorZonesInvalid = false;
104
this._lineHeight = 0;
105
this._domWidth = 0;
106
this._domHeight = 0;
107
this._outerHeight = 0;
108
this._pixelRatio = 1;
109
110
this._lastAssignedId = 0;
111
this._color2Id = Object.create(null);
112
this._id2Color = [];
113
}
114
115
public getId2Color(): string[] {
116
return this._id2Color;
117
}
118
119
public setZones(newZones: OverviewRulerZone[]): void {
120
this._zones = newZones;
121
this._zones.sort(OverviewRulerZone.compare);
122
}
123
124
public setLineHeight(lineHeight: number): boolean {
125
if (this._lineHeight === lineHeight) {
126
return false;
127
}
128
this._lineHeight = lineHeight;
129
this._colorZonesInvalid = true;
130
return true;
131
}
132
133
public setPixelRatio(pixelRatio: number): void {
134
this._pixelRatio = pixelRatio;
135
this._colorZonesInvalid = true;
136
}
137
138
public getDOMWidth(): number {
139
return this._domWidth;
140
}
141
142
public getCanvasWidth(): number {
143
return this._domWidth * this._pixelRatio;
144
}
145
146
public setDOMWidth(width: number): boolean {
147
if (this._domWidth === width) {
148
return false;
149
}
150
this._domWidth = width;
151
this._colorZonesInvalid = true;
152
return true;
153
}
154
155
public getDOMHeight(): number {
156
return this._domHeight;
157
}
158
159
public getCanvasHeight(): number {
160
return this._domHeight * this._pixelRatio;
161
}
162
163
public setDOMHeight(height: number): boolean {
164
if (this._domHeight === height) {
165
return false;
166
}
167
this._domHeight = height;
168
this._colorZonesInvalid = true;
169
return true;
170
}
171
172
public getOuterHeight(): number {
173
return this._outerHeight;
174
}
175
176
public setOuterHeight(outerHeight: number): boolean {
177
if (this._outerHeight === outerHeight) {
178
return false;
179
}
180
this._outerHeight = outerHeight;
181
this._colorZonesInvalid = true;
182
return true;
183
}
184
185
public resolveColorZones(): ColorZone[] {
186
const colorZonesInvalid = this._colorZonesInvalid;
187
const lineHeight = Math.floor(this._lineHeight);
188
const totalHeight = Math.floor(this.getCanvasHeight());
189
const outerHeight = Math.floor(this._outerHeight);
190
const heightRatio = totalHeight / outerHeight;
191
const halfMinimumHeight = Math.floor(Constants.MINIMUM_HEIGHT * this._pixelRatio / 2);
192
193
const allColorZones: ColorZone[] = [];
194
for (let i = 0, len = this._zones.length; i < len; i++) {
195
const zone = this._zones[i];
196
197
if (!colorZonesInvalid) {
198
const colorZone = zone.getColorZones();
199
if (colorZone) {
200
allColorZones.push(colorZone);
201
continue;
202
}
203
}
204
205
const offset1 = this._getVerticalOffsetForLine(zone.startLineNumber);
206
const offset2 = (
207
zone.heightInLines === 0
208
? this._getVerticalOffsetForLine(zone.endLineNumber) + lineHeight
209
: offset1 + zone.heightInLines * lineHeight
210
);
211
212
const y1 = Math.floor(heightRatio * offset1);
213
const y2 = Math.floor(heightRatio * offset2);
214
215
let ycenter = Math.floor((y1 + y2) / 2);
216
let halfHeight = (y2 - ycenter);
217
218
if (halfHeight < halfMinimumHeight) {
219
halfHeight = halfMinimumHeight;
220
}
221
222
if (ycenter - halfHeight < 0) {
223
ycenter = halfHeight;
224
}
225
if (ycenter + halfHeight > totalHeight) {
226
ycenter = totalHeight - halfHeight;
227
}
228
229
const color = zone.color;
230
let colorId = this._color2Id[color];
231
if (!colorId) {
232
colorId = (++this._lastAssignedId);
233
this._color2Id[color] = colorId;
234
this._id2Color[colorId] = color;
235
}
236
const colorZone = new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId);
237
238
zone.setColorZone(colorZone);
239
allColorZones.push(colorZone);
240
}
241
242
this._colorZonesInvalid = false;
243
244
allColorZones.sort(ColorZone.compare);
245
return allColorZones;
246
}
247
}
248
249