123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import * as dom from '../../../base/browser/dom.js';
- import { renderLabelWithIcons } from '../../../base/browser/ui/iconLabel/iconLabels.js';
- import './codelensWidget.css';
- import { Range } from '../../common/core/range.js';
- import { ModelDecorationOptions } from '../../common/model/textModel.js';
- class CodeLensViewZone {
- constructor(afterLineNumber, heightInPx, onHeight) {
- this.afterLineNumber = afterLineNumber;
- this.heightInPx = heightInPx;
- this._onHeight = onHeight;
- this.suppressMouseDown = true;
- this.domNode = document.createElement('div');
- }
- onComputedHeight(height) {
- if (this._lastHeight === undefined) {
- this._lastHeight = height;
- }
- else if (this._lastHeight !== height) {
- this._lastHeight = height;
- this._onHeight();
- }
- }
- isVisible() {
- return this._lastHeight !== 0
- && this.domNode.hasAttribute('monaco-visible-view-zone');
- }
- }
- class CodeLensContentWidget {
- constructor(editor, className, line) {
- // Editor.IContentWidget.allowEditorOverflow
- this.allowEditorOverflow = false;
- this.suppressMouseDown = true;
- this._commands = new Map();
- this._isEmpty = true;
- this._editor = editor;
- this._id = `codelens.widget-${(CodeLensContentWidget._idPool++)}`;
- this.updatePosition(line);
- this._domNode = document.createElement('span');
- this._domNode.className = `codelens-decoration ${className}`;
- }
- withCommands(lenses, animate) {
- this._commands.clear();
- let children = [];
- let hasSymbol = false;
- for (let i = 0; i < lenses.length; i++) {
- const lens = lenses[i];
- if (!lens) {
- continue;
- }
- hasSymbol = true;
- if (lens.command) {
- const title = renderLabelWithIcons(lens.command.title.trim());
- if (lens.command.id) {
- children.push(dom.$('a', { id: String(i), title: lens.command.tooltip }, ...title));
- this._commands.set(String(i), lens.command);
- }
- else {
- children.push(dom.$('span', { title: lens.command.tooltip }, ...title));
- }
- if (i + 1 < lenses.length) {
- children.push(dom.$('span', undefined, '\u00a0|\u00a0'));
- }
- }
- }
- if (!hasSymbol) {
- // symbols but no commands
- dom.reset(this._domNode, dom.$('span', undefined, 'no commands'));
- }
- else {
- // symbols and commands
- dom.reset(this._domNode, ...children);
- if (this._isEmpty && animate) {
- this._domNode.classList.add('fadein');
- }
- this._isEmpty = false;
- }
- }
- getCommand(link) {
- return link.parentElement === this._domNode
- ? this._commands.get(link.id)
- : undefined;
- }
- getId() {
- return this._id;
- }
- getDomNode() {
- return this._domNode;
- }
- updatePosition(line) {
- const column = this._editor.getModel().getLineFirstNonWhitespaceColumn(line);
- this._widgetPosition = {
- position: { lineNumber: line, column: column },
- preference: [1 /* ABOVE */]
- };
- }
- getPosition() {
- return this._widgetPosition || null;
- }
- }
- CodeLensContentWidget._idPool = 0;
- export class CodeLensHelper {
- constructor() {
- this._removeDecorations = [];
- this._addDecorations = [];
- this._addDecorationsCallbacks = [];
- }
- addDecoration(decoration, callback) {
- this._addDecorations.push(decoration);
- this._addDecorationsCallbacks.push(callback);
- }
- removeDecoration(decorationId) {
- this._removeDecorations.push(decorationId);
- }
- commit(changeAccessor) {
- let resultingDecorations = changeAccessor.deltaDecorations(this._removeDecorations, this._addDecorations);
- for (let i = 0, len = resultingDecorations.length; i < len; i++) {
- this._addDecorationsCallbacks[i](resultingDecorations[i]);
- }
- }
- }
- export class CodeLensWidget {
- constructor(data, editor, className, helper, viewZoneChangeAccessor, heightInPx, updateCallback) {
- this._isDisposed = false;
- this._editor = editor;
- this._className = className;
- this._data = data;
- // create combined range, track all ranges with decorations,
- // check if there is already something to render
- this._decorationIds = [];
- let range;
- let lenses = [];
- this._data.forEach((codeLensData, i) => {
- if (codeLensData.symbol.command) {
- lenses.push(codeLensData.symbol);
- }
- helper.addDecoration({
- range: codeLensData.symbol.range,
- options: ModelDecorationOptions.EMPTY
- }, id => this._decorationIds[i] = id);
- // the range contains all lenses on this line
- if (!range) {
- range = Range.lift(codeLensData.symbol.range);
- }
- else {
- range = Range.plusRange(range, codeLensData.symbol.range);
- }
- });
- this._viewZone = new CodeLensViewZone(range.startLineNumber - 1, heightInPx, updateCallback);
- this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone);
- if (lenses.length > 0) {
- this._createContentWidgetIfNecessary();
- this._contentWidget.withCommands(lenses, false);
- }
- }
- _createContentWidgetIfNecessary() {
- if (!this._contentWidget) {
- this._contentWidget = new CodeLensContentWidget(this._editor, this._className, this._viewZone.afterLineNumber + 1);
- this._editor.addContentWidget(this._contentWidget);
- }
- else {
- this._editor.layoutContentWidget(this._contentWidget);
- }
- }
- dispose(helper, viewZoneChangeAccessor) {
- this._decorationIds.forEach(helper.removeDecoration, helper);
- this._decorationIds = [];
- if (viewZoneChangeAccessor) {
- viewZoneChangeAccessor.removeZone(this._viewZoneId);
- }
- if (this._contentWidget) {
- this._editor.removeContentWidget(this._contentWidget);
- this._contentWidget = undefined;
- }
- this._isDisposed = true;
- }
- isDisposed() {
- return this._isDisposed;
- }
- isValid() {
- return this._decorationIds.some((id, i) => {
- const range = this._editor.getModel().getDecorationRange(id);
- const symbol = this._data[i].symbol;
- return !!(range && Range.isEmpty(symbol.range) === range.isEmpty());
- });
- }
- updateCodeLensSymbols(data, helper) {
- this._decorationIds.forEach(helper.removeDecoration, helper);
- this._decorationIds = [];
- this._data = data;
- this._data.forEach((codeLensData, i) => {
- helper.addDecoration({
- range: codeLensData.symbol.range,
- options: ModelDecorationOptions.EMPTY
- }, id => this._decorationIds[i] = id);
- });
- }
- updateHeight(height, viewZoneChangeAccessor) {
- this._viewZone.heightInPx = height;
- viewZoneChangeAccessor.layoutZone(this._viewZoneId);
- if (this._contentWidget) {
- this._editor.layoutContentWidget(this._contentWidget);
- }
- }
- computeIfNecessary(model) {
- if (!this._viewZone.isVisible()) {
- return null;
- }
- // Read editor current state
- for (let i = 0; i < this._decorationIds.length; i++) {
- const range = model.getDecorationRange(this._decorationIds[i]);
- if (range) {
- this._data[i].symbol.range = range;
- }
- }
- return this._data;
- }
- updateCommands(symbols) {
- this._createContentWidgetIfNecessary();
- this._contentWidget.withCommands(symbols, true);
- for (let i = 0; i < this._data.length; i++) {
- const resolved = symbols[i];
- if (resolved) {
- const { symbol } = this._data[i];
- symbol.command = resolved.command || symbol.command;
- }
- }
- }
- getCommand(link) {
- var _a;
- return (_a = this._contentWidget) === null || _a === void 0 ? void 0 : _a.getCommand(link);
- }
- getLineNumber() {
- const range = this._editor.getModel().getDecorationRange(this._decorationIds[0]);
- if (range) {
- return range.startLineNumber;
- }
- return -1;
- }
- update(viewZoneChangeAccessor) {
- if (this.isValid()) {
- const range = this._editor.getModel().getDecorationRange(this._decorationIds[0]);
- if (range) {
- this._viewZone.afterLineNumber = range.startLineNumber - 1;
- viewZoneChangeAccessor.layoutZone(this._viewZoneId);
- if (this._contentWidget) {
- this._contentWidget.updatePosition(range.startLineNumber);
- this._editor.layoutContentWidget(this._contentWidget);
- }
- }
- }
- }
- getItems() {
- return this._data;
- }
- }
|