Path: blob/main/src/vs/workbench/contrib/comments/browser/commentGlyphWidget.ts
5272 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as nls from '../../../../nls.js';6import { Color } from '../../../../base/common/color.js';7import { ContentWidgetPositionPreference, ICodeEditor, IContentWidgetPosition } from '../../../../editor/browser/editorBrowser.js';8import { IModelDecorationOptions, OverviewRulerLane } from '../../../../editor/common/model.js';9import { ModelDecorationOptions } from '../../../../editor/common/model/textModel.js';10import { darken, editorBackground, editorForeground, listInactiveSelectionBackground, opaque, registerColor } from '../../../../platform/theme/common/colorRegistry.js';11import { themeColorFromId } from '../../../../platform/theme/common/themeService.js';12import { IEditorDecorationsCollection } from '../../../../editor/common/editorCommon.js';13import { CommentThreadState } from '../../../../editor/common/languages.js';14import { Disposable, toDisposable } from '../../../../base/common/lifecycle.js';15import { Emitter } from '../../../../base/common/event.js';1617export const overviewRulerCommentingRangeForeground = registerColor('editorGutter.commentRangeForeground', { dark: opaque(listInactiveSelectionBackground, editorBackground), light: darken(opaque(listInactiveSelectionBackground, editorBackground), .05), hcDark: Color.white, hcLight: Color.black }, nls.localize('editorGutterCommentRangeForeground', 'Editor gutter decoration color for commenting ranges. This color should be opaque.'));18const overviewRulerCommentForeground = registerColor('editorOverviewRuler.commentForeground', overviewRulerCommentingRangeForeground, nls.localize('editorOverviewRuler.commentForeground', 'Editor overview ruler decoration color for resolved comments. This color should be opaque.'));19const overviewRulerCommentUnresolvedForeground = registerColor('editorOverviewRuler.commentUnresolvedForeground', overviewRulerCommentForeground, nls.localize('editorOverviewRuler.commentUnresolvedForeground', 'Editor overview ruler decoration color for unresolved comments. This color should be opaque.'));20const overviewRulerCommentDraftForeground = registerColor('editorOverviewRuler.commentDraftForeground', overviewRulerCommentUnresolvedForeground, nls.localize('editorOverviewRuler.commentDraftForeground', 'Editor overview ruler decoration color for comment threads with draft comments. This color should be opaque.'));2122const editorGutterCommentGlyphForeground = registerColor('editorGutter.commentGlyphForeground', { dark: editorForeground, light: editorForeground, hcDark: Color.black, hcLight: Color.white }, nls.localize('editorGutterCommentGlyphForeground', 'Editor gutter decoration color for commenting glyphs.'));23registerColor('editorGutter.commentUnresolvedGlyphForeground', editorGutterCommentGlyphForeground, nls.localize('editorGutterCommentUnresolvedGlyphForeground', 'Editor gutter decoration color for commenting glyphs for unresolved comment threads.'));24registerColor('editorGutter.commentDraftGlyphForeground', editorGutterCommentGlyphForeground, nls.localize('editorGutterCommentDraftGlyphForeground', 'Editor gutter decoration color for commenting glyphs for comment threads with draft comments.'));2526export class CommentGlyphWidget extends Disposable {27public static description = 'comment-glyph-widget';28private _lineNumber!: number;29private _editor: ICodeEditor;30private _threadState: CommentThreadState | undefined;31private _threadHasDraft: boolean = false;32private readonly _commentsDecorations: IEditorDecorationsCollection;33private _commentsOptions: ModelDecorationOptions;3435private readonly _onDidChangeLineNumber = this._register(new Emitter<number>());36public readonly onDidChangeLineNumber = this._onDidChangeLineNumber.event;3738constructor(editor: ICodeEditor, lineNumber: number) {39super();40this._commentsOptions = this.createDecorationOptions();41this._editor = editor;42this._commentsDecorations = this._editor.createDecorationsCollection();43this._register(this._commentsDecorations.onDidChange(e => {44const range = (this._commentsDecorations.length > 0 ? this._commentsDecorations.getRange(0) : null);45if (range && range.endLineNumber !== this._lineNumber) {46this._lineNumber = range.endLineNumber;47this._onDidChangeLineNumber.fire(this._lineNumber);48}49}));50this._register(toDisposable(() => this._commentsDecorations.clear()));51this.setLineNumber(lineNumber);52}5354private createDecorationOptions(): ModelDecorationOptions {55// Priority: draft > unresolved > resolved56let className: string;57if (this._threadHasDraft) {58className = 'comment-range-glyph comment-thread-draft';59} else {60const unresolved = this._threadState === CommentThreadState.Unresolved;61className = `comment-range-glyph comment-thread${unresolved ? '-unresolved' : ''}`;62}6364const decorationOptions: IModelDecorationOptions = {65description: CommentGlyphWidget.description,66isWholeLine: true,67overviewRuler: {68color: themeColorFromId(this._threadHasDraft ? overviewRulerCommentDraftForeground :69(this._threadState === CommentThreadState.Unresolved ? overviewRulerCommentUnresolvedForeground : overviewRulerCommentForeground)),70position: OverviewRulerLane.Center71},72collapseOnReplaceEdit: true,73linesDecorationsClassName: className74};7576return ModelDecorationOptions.createDynamic(decorationOptions);77}7879setThreadState(state: CommentThreadState | undefined, hasDraft: boolean = false): void {80if (this._threadState !== state || this._threadHasDraft !== hasDraft) {81this._threadState = state;82this._threadHasDraft = hasDraft;83this._commentsOptions = this.createDecorationOptions();84this._updateDecorations();85}86}8788private _updateDecorations(): void {89const commentsDecorations = [{90range: {91startLineNumber: this._lineNumber, startColumn: 1,92endLineNumber: this._lineNumber, endColumn: 193},94options: this._commentsOptions95}];9697this._commentsDecorations.set(commentsDecorations);98}99100setLineNumber(lineNumber: number): void {101this._lineNumber = lineNumber;102this._updateDecorations();103}104105getPosition(): IContentWidgetPosition {106const range = (this._commentsDecorations.length > 0 ? this._commentsDecorations.getRange(0) : null);107108return {109position: {110lineNumber: range ? range.endLineNumber : this._lineNumber,111column: 1112},113preference: [ContentWidgetPositionPreference.EXACT]114};115}116}117118119