| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import { Position } from '../core/position.js';
- import { Range } from '../core/range.js';
- import { InlineDecoration, ViewModelDecoration } from '../viewModel.js';
- import { filterValidationDecorations } from '../config/editorOptions.js';
- export class ViewModelDecorations {
- constructor(editorId, model, configuration, linesCollection, coordinatesConverter) {
- this.editorId = editorId;
- this.model = model;
- this.configuration = configuration;
- this._linesCollection = linesCollection;
- this._coordinatesConverter = coordinatesConverter;
- this._decorationsCache = Object.create(null);
- this._cachedModelDecorationsResolver = null;
- this._cachedModelDecorationsResolverViewRange = null;
- }
- _clearCachedModelDecorationsResolver() {
- this._cachedModelDecorationsResolver = null;
- this._cachedModelDecorationsResolverViewRange = null;
- }
- dispose() {
- this._decorationsCache = Object.create(null);
- this._clearCachedModelDecorationsResolver();
- }
- reset() {
- this._decorationsCache = Object.create(null);
- this._clearCachedModelDecorationsResolver();
- }
- onModelDecorationsChanged() {
- this._decorationsCache = Object.create(null);
- this._clearCachedModelDecorationsResolver();
- }
- onLineMappingChanged() {
- this._decorationsCache = Object.create(null);
- this._clearCachedModelDecorationsResolver();
- }
- _getOrCreateViewModelDecoration(modelDecoration) {
- const id = modelDecoration.id;
- let r = this._decorationsCache[id];
- if (!r) {
- const modelRange = modelDecoration.range;
- const options = modelDecoration.options;
- let viewRange;
- if (options.isWholeLine) {
- const start = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.startLineNumber, 1), 0 /* PositionAffinity.Left */);
- const end = this._coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber)), 1 /* PositionAffinity.Right */);
- viewRange = new Range(start.lineNumber, start.column, end.lineNumber, end.column);
- }
- else {
- // For backwards compatibility reasons, we want injected text before any decoration.
- // Thus, move decorations to the right.
- viewRange = this._coordinatesConverter.convertModelRangeToViewRange(modelRange, 1 /* PositionAffinity.Right */);
- }
- r = new ViewModelDecoration(viewRange, options);
- this._decorationsCache[id] = r;
- }
- return r;
- }
- getDecorationsViewportData(viewRange) {
- let cacheIsValid = (this._cachedModelDecorationsResolver !== null);
- cacheIsValid = cacheIsValid && (viewRange.equalsRange(this._cachedModelDecorationsResolverViewRange));
- if (!cacheIsValid) {
- this._cachedModelDecorationsResolver = this._getDecorationsInRange(viewRange);
- this._cachedModelDecorationsResolverViewRange = viewRange;
- }
- return this._cachedModelDecorationsResolver;
- }
- getInlineDecorationsOnLine(lineNumber) {
- const range = new Range(lineNumber, this._linesCollection.getViewLineMinColumn(lineNumber), lineNumber, this._linesCollection.getViewLineMaxColumn(lineNumber));
- return this._getDecorationsInRange(range).inlineDecorations[0];
- }
- _getDecorationsInRange(viewRange) {
- const modelDecorations = this._linesCollection.getDecorationsInRange(viewRange, this.editorId, filterValidationDecorations(this.configuration.options));
- const startLineNumber = viewRange.startLineNumber;
- const endLineNumber = viewRange.endLineNumber;
- const decorationsInViewport = [];
- let decorationsInViewportLen = 0;
- const inlineDecorations = [];
- for (let j = startLineNumber; j <= endLineNumber; j++) {
- inlineDecorations[j - startLineNumber] = [];
- }
- for (let i = 0, len = modelDecorations.length; i < len; i++) {
- const modelDecoration = modelDecorations[i];
- const decorationOptions = modelDecoration.options;
- if (!isModelDecorationVisible(this.model, modelDecoration)) {
- continue;
- }
- const viewModelDecoration = this._getOrCreateViewModelDecoration(modelDecoration);
- const viewRange = viewModelDecoration.range;
- decorationsInViewport[decorationsInViewportLen++] = viewModelDecoration;
- if (decorationOptions.inlineClassName) {
- const inlineDecoration = new InlineDecoration(viewRange, decorationOptions.inlineClassName, decorationOptions.inlineClassNameAffectsLetterSpacing ? 3 /* InlineDecorationType.RegularAffectingLetterSpacing */ : 0 /* InlineDecorationType.Regular */);
- const intersectedStartLineNumber = Math.max(startLineNumber, viewRange.startLineNumber);
- const intersectedEndLineNumber = Math.min(endLineNumber, viewRange.endLineNumber);
- for (let j = intersectedStartLineNumber; j <= intersectedEndLineNumber; j++) {
- inlineDecorations[j - startLineNumber].push(inlineDecoration);
- }
- }
- if (decorationOptions.beforeContentClassName) {
- if (startLineNumber <= viewRange.startLineNumber && viewRange.startLineNumber <= endLineNumber) {
- const inlineDecoration = new InlineDecoration(new Range(viewRange.startLineNumber, viewRange.startColumn, viewRange.startLineNumber, viewRange.startColumn), decorationOptions.beforeContentClassName, 1 /* InlineDecorationType.Before */);
- inlineDecorations[viewRange.startLineNumber - startLineNumber].push(inlineDecoration);
- }
- }
- if (decorationOptions.afterContentClassName) {
- if (startLineNumber <= viewRange.endLineNumber && viewRange.endLineNumber <= endLineNumber) {
- const inlineDecoration = new InlineDecoration(new Range(viewRange.endLineNumber, viewRange.endColumn, viewRange.endLineNumber, viewRange.endColumn), decorationOptions.afterContentClassName, 2 /* InlineDecorationType.After */);
- inlineDecorations[viewRange.endLineNumber - startLineNumber].push(inlineDecoration);
- }
- }
- }
- return {
- decorations: decorationsInViewport,
- inlineDecorations: inlineDecorations
- };
- }
- }
- export function isModelDecorationVisible(model, decoration) {
- if (decoration.options.hideInCommentTokens && isModelDecorationInComment(model, decoration)) {
- return false;
- }
- if (decoration.options.hideInStringTokens && isModelDecorationInString(model, decoration)) {
- return false;
- }
- return true;
- }
- export function isModelDecorationInComment(model, decoration) {
- return testTokensInRange(model, decoration.range, (tokenType) => tokenType === 1 /* StandardTokenType.Comment */);
- }
- export function isModelDecorationInString(model, decoration) {
- return testTokensInRange(model, decoration.range, (tokenType) => tokenType === 2 /* StandardTokenType.String */);
- }
- /**
- * Calls the callback for every token that intersects the range.
- * If the callback returns `false`, iteration stops and `false` is returned.
- * Otherwise, `true` is returned.
- */
- function testTokensInRange(model, range, callback) {
- for (let lineNumber = range.startLineNumber; lineNumber <= range.endLineNumber; lineNumber++) {
- const lineTokens = model.tokenization.getLineTokens(lineNumber);
- const isFirstLine = lineNumber === range.startLineNumber;
- const isEndLine = lineNumber === range.endLineNumber;
- let tokenIdx = isFirstLine ? lineTokens.findTokenIndexAtOffset(range.startColumn - 1) : 0;
- while (tokenIdx < lineTokens.getCount()) {
- if (isEndLine) {
- const startOffset = lineTokens.getStartOffset(tokenIdx);
- if (startOffset > range.endColumn - 1) {
- break;
- }
- }
- const callbackResult = callback(lineTokens.getStandardTokenType(tokenIdx));
- if (!callbackResult) {
- return false;
- }
- tokenIdx++;
- }
- }
- return true;
- }
|