| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- };
- var __param = (this && this.__param) || function (paramIndex, decorator) {
- return function (target, key) { decorator(target, key, paramIndex); }
- };
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- var _a;
- import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
- import { registerEditorContribution } from '../../../browser/editorExtensions.js';
- import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';
- import { OutlineModel, OutlineElement } from '../../documentSymbols/browser/outlineModel.js';
- import { CancellationTokenSource } from '../../../../base/common/cancellation.js';
- import * as dom from '../../../../base/browser/dom.js';
- import { createStringBuilder } from '../../../common/core/stringBuilder.js';
- import { RenderLineInput, renderViewLine } from '../../../common/viewLayout/viewLineRenderer.js';
- import { LineDecoration } from '../../../common/viewLayout/lineDecorations.js';
- import { RunOnceScheduler } from '../../../../base/common/async.js';
- import { Position } from '../../../common/core/position.js';
- let StickyScrollController = class StickyScrollController extends Disposable {
- constructor(editor, _languageFeaturesService) {
- super();
- this._sessionStore = new DisposableStore();
- this._ranges = [];
- this._rangesVersionId = 0;
- this._editor = editor;
- this._languageFeaturesService = _languageFeaturesService;
- this.stickyScrollWidget = new StickyScrollWidget(this._editor);
- this._register(this._editor.onDidChangeConfiguration(e => {
- if (e.hasChanged(34 /* EditorOption.experimental */)) {
- this.onConfigurationChange();
- }
- }));
- this._updateSoon = this._register(new RunOnceScheduler(() => this._update(true), 50));
- this.onConfigurationChange();
- }
- onConfigurationChange() {
- const options = this._editor.getOption(34 /* EditorOption.experimental */);
- if (options.stickyScroll.enabled === false) {
- this.stickyScrollWidget.emptyRootNode();
- this._editor.removeOverlayWidget(this.stickyScrollWidget);
- this._sessionStore.clear();
- return;
- }
- else {
- this._editor.addOverlayWidget(this.stickyScrollWidget);
- this._sessionStore.add(this._editor.onDidChangeModel(() => this._update(true)));
- this._sessionStore.add(this._editor.onDidScrollChange(() => this._update(false)));
- this._sessionStore.add(this._editor.onDidChangeHiddenAreas(() => this._update(true)));
- this._sessionStore.add(this._editor.onDidChangeModelTokens((e) => this._onTokensChange(e)));
- this._sessionStore.add(this._editor.onDidChangeModelContent(() => this._updateSoon.schedule()));
- this._sessionStore.add(this._languageFeaturesService.documentSymbolProvider.onDidChange(() => this._update(true)));
- this._update(true);
- }
- }
- _needsUpdate(event) {
- const stickyLineNumbers = this.stickyScrollWidget.getCurrentLines();
- for (const stickyLineNumber of stickyLineNumbers) {
- for (const range of event.ranges) {
- if (stickyLineNumber >= range.fromLineNumber && stickyLineNumber <= range.toLineNumber) {
- return true;
- }
- }
- }
- return false;
- }
- _onTokensChange(event) {
- if (this._needsUpdate(event)) {
- this._update(false);
- }
- }
- _update(updateOutline = false) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- if (updateOutline) {
- (_a = this._cts) === null || _a === void 0 ? void 0 : _a.dispose(true);
- this._cts = new CancellationTokenSource();
- yield this._updateOutlineModel(this._cts.token);
- }
- const hiddenRanges = (_b = this._editor._getViewModel()) === null || _b === void 0 ? void 0 : _b.getHiddenAreas();
- if (hiddenRanges) {
- for (const hiddenRange of hiddenRanges) {
- this._ranges = this._ranges.filter(range => { return !(range[0] >= hiddenRange.startLineNumber && range[1] <= hiddenRange.endLineNumber + 1); });
- }
- }
- this._renderStickyScroll();
- });
- }
- _findLineRanges(outlineElement, depth) {
- if (outlineElement === null || outlineElement === void 0 ? void 0 : outlineElement.children.size) {
- let didRecursion = false;
- for (const outline of outlineElement === null || outlineElement === void 0 ? void 0 : outlineElement.children.values()) {
- const kind = outline.symbol.kind;
- if (kind === 4 /* SymbolKind.Class */ || kind === 8 /* SymbolKind.Constructor */ || kind === 11 /* SymbolKind.Function */ || kind === 10 /* SymbolKind.Interface */ || kind === 5 /* SymbolKind.Method */ || kind === 1 /* SymbolKind.Module */) {
- didRecursion = true;
- this._findLineRanges(outline, depth + 1);
- }
- }
- if (!didRecursion) {
- this._addOutlineRanges(outlineElement, depth);
- }
- }
- else {
- this._addOutlineRanges(outlineElement, depth);
- }
- }
- _addOutlineRanges(outlineElement, depth) {
- let currentStartLine = 0;
- let currentEndLine = 0;
- while (outlineElement) {
- const kind = outlineElement.symbol.kind;
- if (kind === 4 /* SymbolKind.Class */ || kind === 8 /* SymbolKind.Constructor */ || kind === 11 /* SymbolKind.Function */ || kind === 10 /* SymbolKind.Interface */ || kind === 5 /* SymbolKind.Method */ || kind === 1 /* SymbolKind.Module */) {
- currentStartLine = outlineElement === null || outlineElement === void 0 ? void 0 : outlineElement.symbol.range.startLineNumber;
- currentEndLine = outlineElement === null || outlineElement === void 0 ? void 0 : outlineElement.symbol.range.endLineNumber;
- this._ranges.push([currentStartLine, currentEndLine, depth]);
- depth--;
- }
- if (outlineElement.parent instanceof OutlineElement) {
- outlineElement = outlineElement.parent;
- }
- else {
- break;
- }
- }
- }
- _updateOutlineModel(token) {
- return __awaiter(this, void 0, void 0, function* () {
- if (this._editor.hasModel()) {
- const model = this._editor.getModel();
- const modelVersionId = model.getVersionId();
- const outlineModel = yield OutlineModel.create(this._languageFeaturesService.documentSymbolProvider, model, token);
- if (token.isCancellationRequested) {
- return;
- }
- this._ranges = [];
- this._rangesVersionId = modelVersionId;
- for (const outline of outlineModel.children.values()) {
- if (outline instanceof OutlineElement) {
- const kind = outline.symbol.kind;
- if (kind === 4 /* SymbolKind.Class */ || kind === 8 /* SymbolKind.Constructor */ || kind === 11 /* SymbolKind.Function */ || kind === 10 /* SymbolKind.Interface */ || kind === 5 /* SymbolKind.Method */ || kind === 1 /* SymbolKind.Module */) {
- this._findLineRanges(outline, 1);
- }
- else {
- this._findLineRanges(outline, 0);
- }
- }
- this._ranges = this._ranges.sort(function (a, b) {
- if (a[0] !== b[0]) {
- return a[0] - b[0];
- }
- else if (a[1] !== b[1]) {
- return b[1] - a[1];
- }
- else {
- return a[2] - b[2];
- }
- });
- let previous = [];
- for (const [index, arr] of this._ranges.entries()) {
- const [start, end, _depth] = arr;
- if (previous[0] === start && previous[1] === end) {
- this._ranges.splice(index, 1);
- }
- else {
- previous = arr;
- }
- }
- }
- }
- });
- }
- _renderStickyScroll() {
- if (!(this._editor.hasModel())) {
- return;
- }
- const lineHeight = this._editor.getOption(61 /* EditorOption.lineHeight */);
- const model = this._editor.getModel();
- if (this._rangesVersionId !== model.getVersionId()) {
- // Old _ranges not updated yet
- return;
- }
- const scrollTop = this._editor.getScrollTop();
- this.stickyScrollWidget.emptyRootNode();
- const beginningLinesConsidered = new Set();
- for (const [index, arr] of this._ranges.entries()) {
- const [start, end, depth] = arr;
- if (end - start > 0 && model.getLineContent(start) !== '') {
- const topOfElementAtDepth = (depth - 1) * lineHeight;
- const bottomOfElementAtDepth = depth * lineHeight;
- const bottomOfBeginningLine = this._editor.getBottomForLineNumber(start) - scrollTop;
- const topOfEndLine = this._editor.getTopForLineNumber(end) - scrollTop;
- const bottomOfEndLine = this._editor.getBottomForLineNumber(end) - scrollTop;
- if (!beginningLinesConsidered.has(start)) {
- if (topOfElementAtDepth >= topOfEndLine - 1 && topOfElementAtDepth < bottomOfEndLine - 2) {
- beginningLinesConsidered.add(start);
- this.stickyScrollWidget.pushCodeLine(new StickyScrollCodeLine(start, depth, this._editor, -1, bottomOfEndLine - bottomOfElementAtDepth));
- break;
- }
- else if (bottomOfElementAtDepth > bottomOfBeginningLine && bottomOfElementAtDepth < bottomOfEndLine - 1) {
- beginningLinesConsidered.add(start);
- this.stickyScrollWidget.pushCodeLine(new StickyScrollCodeLine(start, depth, this._editor, 0, 0));
- }
- }
- else {
- this._ranges.splice(index, 1);
- }
- }
- }
- this.stickyScrollWidget.updateRootNode();
- }
- dispose() {
- super.dispose();
- this._sessionStore.dispose();
- }
- };
- StickyScrollController.ID = 'store.contrib.stickyScrollController';
- StickyScrollController = __decorate([
- __param(1, ILanguageFeaturesService)
- ], StickyScrollController);
- const _ttPolicy = (_a = window.trustedTypes) === null || _a === void 0 ? void 0 : _a.createPolicy('stickyScrollViewLayer', { createHTML: value => value });
- class StickyScrollCodeLine {
- constructor(_lineNumber, _depth, _editor, _zIndex, _relativePosition) {
- this._lineNumber = _lineNumber;
- this._depth = _depth;
- this._editor = _editor;
- this._zIndex = _zIndex;
- this._relativePosition = _relativePosition;
- this.effectiveLineHeight = 0;
- this.effectiveLineHeight = this._editor.getOption(61 /* EditorOption.lineHeight */) + this._relativePosition;
- }
- get lineNumber() {
- return this._lineNumber;
- }
- getDomNode() {
- const root = document.createElement('div');
- const viewModel = this._editor._getViewModel();
- const viewLineNumber = viewModel.coordinatesConverter.convertModelPositionToViewPosition(new Position(this._lineNumber, 1)).lineNumber;
- const lineRenderingData = viewModel.getViewLineRenderingData(viewLineNumber);
- let actualInlineDecorations;
- try {
- actualInlineDecorations = LineDecoration.filter(lineRenderingData.inlineDecorations, viewLineNumber, lineRenderingData.minColumn, lineRenderingData.maxColumn);
- }
- catch (err) {
- actualInlineDecorations = [];
- }
- const renderLineInput = new RenderLineInput(true, true, lineRenderingData.content, lineRenderingData.continuesWithWrappedLine, lineRenderingData.isBasicASCII, lineRenderingData.containsRTL, 0, lineRenderingData.tokens, actualInlineDecorations, lineRenderingData.tabSize, lineRenderingData.startVisibleColumn, 1, 1, 1, 100, 'none', true, true, null);
- const sb = createStringBuilder(400);
- renderViewLine(renderLineInput, sb);
- let newLine;
- if (_ttPolicy) {
- newLine = _ttPolicy.createHTML(sb.build());
- }
- else {
- newLine = sb.build();
- }
- const lineHTMLNode = document.createElement('span');
- lineHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- lineHTMLNode.style.overflow = 'hidden';
- lineHTMLNode.style.whiteSpace = 'nowrap';
- lineHTMLNode.style.display = 'inline-block';
- lineHTMLNode.style.lineHeight = this._editor.getOption(61 /* EditorOption.lineHeight */).toString() + 'px';
- lineHTMLNode.innerHTML = newLine;
- const lineNumberHTMLNode = document.createElement('span');
- lineNumberHTMLNode.style.width = this._editor.getLayoutInfo().contentLeft.toString() + 'px';
- lineNumberHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- lineNumberHTMLNode.style.color = 'var(--vscode-editorLineNumber-foreground)';
- lineNumberHTMLNode.style.display = 'inline-block';
- lineNumberHTMLNode.style.lineHeight = this._editor.getOption(61 /* EditorOption.lineHeight */).toString() + 'px';
- const innerLineNumberHTML = document.createElement('span');
- innerLineNumberHTML.innerText = this._lineNumber.toString();
- innerLineNumberHTML.style.paddingLeft = this._editor.getLayoutInfo().lineNumbersLeft.toString() + 'px';
- innerLineNumberHTML.style.width = this._editor.getLayoutInfo().lineNumbersWidth.toString() + 'px';
- innerLineNumberHTML.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- innerLineNumberHTML.style.textAlign = 'right';
- innerLineNumberHTML.style.float = 'left';
- innerLineNumberHTML.style.lineHeight = this._editor.getOption(61 /* EditorOption.lineHeight */).toString() + 'px';
- lineNumberHTMLNode.appendChild(innerLineNumberHTML);
- root.onclick = e => {
- e.stopPropagation();
- e.preventDefault();
- this._editor.revealPosition({ lineNumber: this._lineNumber - this._depth + 1, column: 1 });
- };
- root.onmouseover = e => {
- innerLineNumberHTML.style.background = `var(--vscode-editorStickyScrollHover-background)`;
- lineHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScrollHover-background)`;
- lineNumberHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScrollHover-background)`;
- root.style.backgroundColor = `var(--vscode-editorStickyScrollHover-background)`;
- innerLineNumberHTML.style.cursor = `pointer`;
- lineHTMLNode.style.cursor = `pointer`;
- root.style.cursor = `pointer`;
- lineNumberHTMLNode.style.cursor = `pointer`;
- };
- root.onmouseleave = e => {
- innerLineNumberHTML.style.background = `var(--vscode-editorStickyScroll-background)`;
- lineHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- lineNumberHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- root.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- };
- this._editor.applyFontInfo(lineHTMLNode);
- this._editor.applyFontInfo(innerLineNumberHTML);
- root.appendChild(lineNumberHTMLNode);
- root.appendChild(lineHTMLNode);
- root.style.zIndex = this._zIndex.toString();
- root.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- root.style.overflow = 'hidden';
- root.style.whiteSpace = 'nowrap';
- root.style.width = '100%';
- root.style.lineHeight = this._editor.getOption(61 /* EditorOption.lineHeight */).toString() + 'px';
- root.style.height = this._editor.getOption(61 /* EditorOption.lineHeight */).toString() + 'px';
- // Special case for last line of sticky scroll
- if (this._relativePosition) {
- root.style.position = 'relative';
- root.style.top = this._relativePosition + 'px';
- root.style.width = '100%';
- }
- return root;
- }
- }
- class StickyScrollWidget {
- constructor(_editor) {
- this._editor = _editor;
- this.arrayOfCodeLines = [];
- this.rootDomNode = document.createElement('div');
- this.rootDomNode = document.createElement('div');
- this.rootDomNode.style.width = '100%';
- this.rootDomNode.style.boxShadow = `var(--vscode-scrollbar-shadow) 0 6px 6px -6px`;
- }
- getCurrentLines() {
- const widgetLineRange = [];
- for (const codeLine of this.arrayOfCodeLines) {
- widgetLineRange.push(codeLine.lineNumber);
- }
- return widgetLineRange;
- }
- pushCodeLine(codeLine) {
- this.arrayOfCodeLines.push(codeLine);
- }
- updateRootNode() {
- let widgetHeight = 0;
- for (const line of this.arrayOfCodeLines) {
- widgetHeight += line.effectiveLineHeight;
- this.rootDomNode.appendChild(line.getDomNode());
- }
- this.rootDomNode.style.height = widgetHeight.toString() + 'px';
- }
- emptyRootNode() {
- this.arrayOfCodeLines.length = 0;
- dom.clearNode(this.rootDomNode);
- }
- getId() {
- return 'editor.contrib.stickyScrollWidget';
- }
- getDomNode() {
- this.rootDomNode.style.zIndex = '2';
- this.rootDomNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
- return this.rootDomNode;
- }
- getPosition() {
- return {
- preference: null
- };
- }
- }
- registerEditorContribution(StickyScrollController.ID, StickyScrollController);
|