Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/common/viewModel.ts
3292 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
import * as arrays from '../../base/common/arrays.js';
7
import { IScrollPosition, Scrollable } from '../../base/common/scrollable.js';
8
import * as strings from '../../base/common/strings.js';
9
import { ISimpleModel } from './viewModel/screenReaderSimpleModel.js';
10
import { ICoordinatesConverter } from './coordinatesConverter.js';
11
import { IPosition, Position } from './core/position.js';
12
import { Range } from './core/range.js';
13
import { CursorConfiguration, CursorState, EditOperationType, IColumnSelectData, ICursorSimpleModel, PartialCursorState } from './cursorCommon.js';
14
import { CursorChangeReason } from './cursorEvents.js';
15
import { INewScrollPosition, ScrollType } from './editorCommon.js';
16
import { EditorTheme } from './editorTheme.js';
17
import { EndOfLinePreference, IGlyphMarginLanesModel, IModelDecorationOptions, ITextModel, TextDirection } from './model.js';
18
import { ILineBreaksComputer, InjectedText } from './modelLineProjectionData.js';
19
import { BracketGuideOptions, IActiveIndentGuideInfo, IndentGuide } from './textModelGuides.js';
20
import { IViewLineTokens } from './tokens/lineTokens.js';
21
import { ViewEventHandler } from './viewEventHandler.js';
22
import { VerticalRevealType } from './viewEvents.js';
23
import { InlineDecoration, SingleLineInlineDecoration } from './viewModel/inlineDecorations.js';
24
25
export interface IViewModel extends ICursorSimpleModel, ISimpleModel {
26
27
readonly model: ITextModel;
28
29
readonly coordinatesConverter: ICoordinatesConverter;
30
31
readonly viewLayout: IViewLayout;
32
33
readonly cursorConfig: CursorConfiguration;
34
35
readonly glyphLanes: IGlyphMarginLanesModel;
36
37
addViewEventHandler(eventHandler: ViewEventHandler): void;
38
removeViewEventHandler(eventHandler: ViewEventHandler): void;
39
40
/**
41
* Gives a hint that a lot of requests are about to come in for these line numbers.
42
*/
43
setViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void;
44
visibleLinesStabilized(): void;
45
setHasFocus(hasFocus: boolean): void;
46
setHasWidgetFocus(hasWidgetFocus: boolean): void;
47
onCompositionStart(): void;
48
onCompositionEnd(): void;
49
50
getFontSizeAtPosition(position: IPosition): string | null;
51
getMinimapDecorationsInRange(range: Range): ViewModelDecoration[];
52
getDecorationsInViewport(visibleRange: Range): ViewModelDecoration[];
53
getTextDirection(lineNumber: number): TextDirection;
54
getViewportViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData;
55
getViewLineRenderingData(lineNumber: number): ViewLineRenderingData;
56
getViewLineData(lineNumber: number): ViewLineData;
57
getMinimapLinesRenderingData(startLineNumber: number, endLineNumber: number, needed: boolean[]): MinimapLinesRenderingData;
58
getCompletelyVisibleViewRange(): Range;
59
getCompletelyVisibleViewRangeAtScrollTop(scrollTop: number): Range;
60
61
getHiddenAreas(): Range[];
62
63
getLineCount(): number;
64
getLineContent(lineNumber: number): string;
65
getLineLength(lineNumber: number): number;
66
getActiveIndentGuide(lineNumber: number, minLineNumber: number, maxLineNumber: number): IActiveIndentGuideInfo;
67
getLinesIndentGuides(startLineNumber: number, endLineNumber: number): number[];
68
getBracketGuidesInRangeByLine(startLineNumber: number, endLineNumber: number, activePosition: IPosition | null, options: BracketGuideOptions): IndentGuide[][];
69
getLineMinColumn(lineNumber: number): number;
70
getLineMaxColumn(lineNumber: number): number;
71
getLineFirstNonWhitespaceColumn(lineNumber: number): number;
72
getLineLastNonWhitespaceColumn(lineNumber: number): number;
73
getAllOverviewRulerDecorations(theme: EditorTheme): OverviewRulerDecorationsGroup[];
74
getValueInRange(range: Range, eol: EndOfLinePreference): string;
75
getValueLengthInRange(range: Range, eol: EndOfLinePreference): number;
76
modifyPosition(position: Position, offset: number): Position;
77
78
getInjectedTextAt(viewPosition: Position): InjectedText | null;
79
80
deduceModelPositionRelativeToViewPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position;
81
getPlainTextToCopy(modelRanges: Range[], emptySelectionClipboard: boolean, forceCRLF: boolean): string | string[];
82
getRichTextToCopy(modelRanges: Range[], emptySelectionClipboard: boolean): { html: string; mode: string } | null;
83
84
createLineBreaksComputer(): ILineBreaksComputer;
85
86
//#region cursor
87
getPrimaryCursorState(): CursorState;
88
getLastAddedCursorIndex(): number;
89
getCursorStates(): CursorState[];
90
setCursorStates(source: string | null | undefined, reason: CursorChangeReason, states: PartialCursorState[] | null): boolean;
91
getCursorColumnSelectData(): IColumnSelectData;
92
getCursorAutoClosedCharacters(): Range[];
93
setCursorColumnSelectData(columnSelectData: IColumnSelectData): void;
94
getPrevEditOperationType(): EditOperationType;
95
setPrevEditOperationType(type: EditOperationType): void;
96
revealAllCursors(source: string | null | undefined, revealHorizontal: boolean, minimalReveal?: boolean): void;
97
revealPrimaryCursor(source: string | null | undefined, revealHorizontal: boolean, minimalReveal?: boolean): void;
98
revealTopMostCursor(source: string | null | undefined): void;
99
revealBottomMostCursor(source: string | null | undefined): void;
100
revealRange(source: string | null | undefined, revealHorizontal: boolean, viewRange: Range, verticalType: VerticalRevealType, scrollType: ScrollType): void;
101
//#endregion
102
103
//#region viewLayout
104
changeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): void;
105
//#endregion
106
107
batchEvents(callback: () => void): void;
108
}
109
110
export interface IViewLayout {
111
112
getScrollable(): Scrollable;
113
114
getScrollWidth(): number;
115
getScrollHeight(): number;
116
117
getCurrentScrollLeft(): number;
118
getCurrentScrollTop(): number;
119
getCurrentViewport(): Viewport;
120
121
getFutureViewport(): Viewport;
122
123
setScrollPosition(position: INewScrollPosition, type: ScrollType): void;
124
deltaScrollNow(deltaScrollLeft: number, deltaScrollTop: number): void;
125
126
validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition;
127
128
setMaxLineWidth(maxLineWidth: number): void;
129
setOverlayWidgetsMinWidth(overlayWidgetsMinWidth: number): void;
130
131
getLinesViewportData(): IPartialViewLinesViewportData;
132
getLinesViewportDataAtScrollTop(scrollTop: number): IPartialViewLinesViewportData;
133
getWhitespaces(): IEditorWhitespace[];
134
135
isAfterLines(verticalOffset: number): boolean;
136
isInTopPadding(verticalOffset: number): boolean;
137
isInBottomPadding(verticalOffset: number): boolean;
138
getLineNumberAtVerticalOffset(verticalOffset: number): number;
139
getVerticalOffsetForLineNumber(lineNumber: number, includeViewZones?: boolean): number;
140
getVerticalOffsetAfterLineNumber(lineNumber: number, includeViewZones?: boolean): number;
141
getLineHeightForLineNumber(lineNumber: number): number;
142
getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null;
143
144
/**
145
* Get the layout information for whitespaces currently in the viewport
146
*/
147
getWhitespaceViewportData(): IViewWhitespaceViewportData[];
148
}
149
150
export interface IEditorWhitespace {
151
readonly id: string;
152
readonly afterLineNumber: number;
153
readonly height: number;
154
}
155
156
/**
157
* An accessor that allows for whitespace to be added, removed or changed in bulk.
158
*/
159
export interface IWhitespaceChangeAccessor {
160
insertWhitespace(afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string;
161
changeOneWhitespace(id: string, newAfterLineNumber: number, newHeight: number): void;
162
removeWhitespace(id: string): void;
163
}
164
165
export interface ILineHeightChangeAccessor {
166
insertOrChangeCustomLineHeight(decorationId: string, startLineNumber: number, endLineNumber: number, lineHeight: number): void;
167
removeCustomLineHeight(decorationId: string): void;
168
}
169
170
export interface IPartialViewLinesViewportData {
171
/**
172
* Value to be substracted from `scrollTop` (in order to vertical offset numbers < 1MM)
173
*/
174
readonly bigNumbersDelta: number;
175
/**
176
* The first (partially) visible line number.
177
*/
178
readonly startLineNumber: number;
179
/**
180
* The last (partially) visible line number.
181
*/
182
readonly endLineNumber: number;
183
/**
184
* relativeVerticalOffset[i] is the `top` position for line at `i` + `startLineNumber`.
185
*/
186
readonly relativeVerticalOffset: number[];
187
/**
188
* The centered line in the viewport.
189
*/
190
readonly centeredLineNumber: number;
191
/**
192
* The first completely visible line number.
193
*/
194
readonly completelyVisibleStartLineNumber: number;
195
/**
196
* The last completely visible line number.
197
*/
198
readonly completelyVisibleEndLineNumber: number;
199
200
/**
201
* The height of a line.
202
*/
203
readonly lineHeight: number;
204
}
205
206
export interface IViewWhitespaceViewportData {
207
readonly id: string;
208
readonly afterLineNumber: number;
209
readonly verticalOffset: number;
210
readonly height: number;
211
}
212
213
export class Viewport {
214
readonly _viewportBrand: void = undefined;
215
216
readonly top: number;
217
readonly left: number;
218
readonly width: number;
219
readonly height: number;
220
221
constructor(top: number, left: number, width: number, height: number) {
222
this.top = top | 0;
223
this.left = left | 0;
224
this.width = width | 0;
225
this.height = height | 0;
226
}
227
}
228
229
export class MinimapLinesRenderingData {
230
public readonly tabSize: number;
231
public readonly data: Array<ViewLineData | null>;
232
233
constructor(
234
tabSize: number,
235
data: Array<ViewLineData | null>
236
) {
237
this.tabSize = tabSize;
238
this.data = data;
239
}
240
}
241
242
export class ViewLineData {
243
_viewLineDataBrand: void = undefined;
244
245
/**
246
* The content at this view line.
247
*/
248
public readonly content: string;
249
/**
250
* Does this line continue with a wrapped line?
251
*/
252
public readonly continuesWithWrappedLine: boolean;
253
/**
254
* The minimum allowed column at this view line.
255
*/
256
public readonly minColumn: number;
257
/**
258
* The maximum allowed column at this view line.
259
*/
260
public readonly maxColumn: number;
261
/**
262
* The visible column at the start of the line (after the fauxIndent).
263
*/
264
public readonly startVisibleColumn: number;
265
/**
266
* The tokens at this view line.
267
*/
268
public readonly tokens: IViewLineTokens;
269
270
/**
271
* Additional inline decorations for this line.
272
*/
273
public readonly inlineDecorations: readonly SingleLineInlineDecoration[] | null;
274
275
constructor(
276
content: string,
277
continuesWithWrappedLine: boolean,
278
minColumn: number,
279
maxColumn: number,
280
startVisibleColumn: number,
281
tokens: IViewLineTokens,
282
inlineDecorations: readonly SingleLineInlineDecoration[] | null
283
) {
284
this.content = content;
285
this.continuesWithWrappedLine = continuesWithWrappedLine;
286
this.minColumn = minColumn;
287
this.maxColumn = maxColumn;
288
this.startVisibleColumn = startVisibleColumn;
289
this.tokens = tokens;
290
this.inlineDecorations = inlineDecorations;
291
}
292
}
293
294
export class ViewLineRenderingData {
295
/**
296
* The minimum allowed column at this view line.
297
*/
298
public readonly minColumn: number;
299
/**
300
* The maximum allowed column at this view line.
301
*/
302
public readonly maxColumn: number;
303
/**
304
* The content at this view line.
305
*/
306
public readonly content: string;
307
/**
308
* Does this line continue with a wrapped line?
309
*/
310
public readonly continuesWithWrappedLine: boolean;
311
/**
312
* Describes if `content` contains RTL characters.
313
*/
314
public readonly containsRTL: boolean;
315
/**
316
* Describes if `content` contains non basic ASCII chars.
317
*/
318
public readonly isBasicASCII: boolean;
319
/**
320
* The tokens at this view line.
321
*/
322
public readonly tokens: IViewLineTokens;
323
/**
324
* Inline decorations at this view line.
325
*/
326
public readonly inlineDecorations: InlineDecoration[];
327
/**
328
* The tab size for this view model.
329
*/
330
public readonly tabSize: number;
331
/**
332
* The visible column at the start of the line (after the fauxIndent)
333
*/
334
public readonly startVisibleColumn: number;
335
/**
336
* The direction to use for rendering the line.
337
*/
338
public readonly textDirection: TextDirection;
339
/**
340
* Whether the line has variable fonts
341
*/
342
public readonly hasVariableFonts: boolean;
343
344
constructor(
345
minColumn: number,
346
maxColumn: number,
347
content: string,
348
continuesWithWrappedLine: boolean,
349
mightContainRTL: boolean,
350
mightContainNonBasicASCII: boolean,
351
tokens: IViewLineTokens,
352
inlineDecorations: InlineDecoration[],
353
tabSize: number,
354
startVisibleColumn: number,
355
textDirection: TextDirection,
356
hasVariableFonts: boolean
357
) {
358
this.minColumn = minColumn;
359
this.maxColumn = maxColumn;
360
this.content = content;
361
this.continuesWithWrappedLine = continuesWithWrappedLine;
362
363
this.isBasicASCII = ViewLineRenderingData.isBasicASCII(content, mightContainNonBasicASCII);
364
this.containsRTL = ViewLineRenderingData.containsRTL(content, this.isBasicASCII, mightContainRTL);
365
366
this.tokens = tokens;
367
this.inlineDecorations = inlineDecorations;
368
this.tabSize = tabSize;
369
this.startVisibleColumn = startVisibleColumn;
370
this.textDirection = textDirection;
371
this.hasVariableFonts = hasVariableFonts;
372
}
373
374
public static isBasicASCII(lineContent: string, mightContainNonBasicASCII: boolean): boolean {
375
if (mightContainNonBasicASCII) {
376
return strings.isBasicASCII(lineContent);
377
}
378
return true;
379
}
380
381
public static containsRTL(lineContent: string, isBasicASCII: boolean, mightContainRTL: boolean): boolean {
382
if (!isBasicASCII && mightContainRTL) {
383
return strings.containsRTL(lineContent);
384
}
385
return false;
386
}
387
}
388
389
export class ViewModelDecoration {
390
_viewModelDecorationBrand: void = undefined;
391
392
public readonly range: Range;
393
public readonly options: IModelDecorationOptions;
394
395
constructor(range: Range, options: IModelDecorationOptions) {
396
this.range = range;
397
this.options = options;
398
}
399
}
400
401
export class OverviewRulerDecorationsGroup {
402
403
constructor(
404
public readonly color: string,
405
public readonly zIndex: number,
406
/**
407
* Decorations are encoded in a number array using the following scheme:
408
* - 3*i = lane
409
* - 3*i+1 = startLineNumber
410
* - 3*i+2 = endLineNumber
411
*/
412
public readonly data: number[]
413
) { }
414
415
public static compareByRenderingProps(a: OverviewRulerDecorationsGroup, b: OverviewRulerDecorationsGroup): number {
416
if (a.zIndex === b.zIndex) {
417
if (a.color < b.color) {
418
return -1;
419
}
420
if (a.color > b.color) {
421
return 1;
422
}
423
return 0;
424
}
425
return a.zIndex - b.zIndex;
426
}
427
428
public static equals(a: OverviewRulerDecorationsGroup, b: OverviewRulerDecorationsGroup): boolean {
429
return (
430
a.color === b.color
431
&& a.zIndex === b.zIndex
432
&& arrays.equals(a.data, b.data)
433
);
434
}
435
436
public static equalsArr(a: OverviewRulerDecorationsGroup[], b: OverviewRulerDecorationsGroup[]): boolean {
437
return arrays.equals(a, b, OverviewRulerDecorationsGroup.equals);
438
}
439
}
440
441