Path: blob/main/src/vs/workbench/contrib/comments/browser/simpleCommentEditor.ts
5240 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 { EditorOption, IEditorOptions } from '../../../../editor/common/config/editorOptions.js';6import { EditorAction, EditorContributionInstantiation, EditorExtensionsRegistry, IEditorContributionDescription } from '../../../../editor/browser/editorExtensions.js';7import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';8import { CodeEditorWidget, ICodeEditorWidgetOptions } from '../../../../editor/browser/widget/codeEditor/codeEditorWidget.js';9import { IContextKeyService, RawContextKey, IContextKey } from '../../../../platform/contextkey/common/contextkey.js';10import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';11import { ICommandService } from '../../../../platform/commands/common/commands.js';1213// Allowed Editor Contributions:14import { MenuPreventer } from '../../codeEditor/browser/menuPreventer.js';15import { EditorDictation } from '../../codeEditor/browser/dictation/editorDictation.js';16import { ContextMenuController } from '../../../../editor/contrib/contextmenu/browser/contextmenu.js';17import { SuggestController } from '../../../../editor/contrib/suggest/browser/suggestController.js';18import { SnippetController2 } from '../../../../editor/contrib/snippet/browser/snippetController2.js';19import { TabCompletionController } from '../../snippets/browser/tabCompletion.js';20import { IThemeService } from '../../../../platform/theme/common/themeService.js';21import { INotificationService } from '../../../../platform/notification/common/notification.js';22import { IAccessibilityService } from '../../../../platform/accessibility/common/accessibility.js';23import { ICommentThreadWidget } from '../common/commentThreadWidget.js';24import { CommentContextKeys } from '../common/commentContextKeys.js';25import { ILanguageConfigurationService } from '../../../../editor/common/languages/languageConfigurationRegistry.js';26import { ILanguageFeaturesService } from '../../../../editor/common/services/languageFeatures.js';27import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';28import { ICodeEditor } from '../../../../editor/browser/editorBrowser.js';29import { clamp } from '../../../../base/common/numbers.js';30import { CopyPasteController } from '../../../../editor/contrib/dropOrPasteInto/browser/copyPasteController.js';31import { CodeActionController } from '../../../../editor/contrib/codeAction/browser/codeActionController.js';32import { DropIntoEditorController } from '../../../../editor/contrib/dropOrPasteInto/browser/dropIntoEditorController.js';33import { InlineCompletionsController } from '../../../../editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.js';34import { LinkDetector } from '../../../../editor/contrib/links/browser/links.js';35import { MessageController } from '../../../../editor/contrib/message/browser/messageController.js';36import { SelectionClipboardContributionID } from '../../codeEditor/browser/selectionClipboard.js';37import { MenuId } from '../../../../platform/actions/common/actions.js';38import { ContentHoverController } from '../../../../editor/contrib/hover/browser/contentHoverController.js';39import { GlyphHoverController } from '../../../../editor/contrib/hover/browser/glyphHoverController.js';40import { PlaceholderTextContribution } from '../../../../editor/contrib/placeholderText/browser/placeholderTextContribution.js';41import { IUserInteractionService } from '../../../../platform/userInteraction/browser/userInteractionService.js';4243export const ctxCommentEditorFocused = new RawContextKey<boolean>('commentEditorFocused', false);44export const MIN_EDITOR_HEIGHT = 5 * 18;45export const MAX_EDITOR_HEIGHT = 25 * 18;4647export interface LayoutableEditor {48getLayoutInfo(): { height: number };49}5051export class SimpleCommentEditor extends CodeEditorWidget {52private _parentThread: ICommentThreadWidget;53private _commentEditorFocused: IContextKey<boolean>;54private _commentEditorEmpty: IContextKey<boolean>;5556constructor(57domElement: HTMLElement,58options: IEditorOptions,59scopedContextKeyService: IContextKeyService,60parentThread: ICommentThreadWidget,61@IInstantiationService instantiationService: IInstantiationService,62@ICodeEditorService codeEditorService: ICodeEditorService,63@ICommandService commandService: ICommandService,64@IThemeService themeService: IThemeService,65@INotificationService notificationService: INotificationService,66@IAccessibilityService accessibilityService: IAccessibilityService,67@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService,68@ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,69@IUserInteractionService userInteractionService: IUserInteractionService,70) {71const codeEditorWidgetOptions: ICodeEditorWidgetOptions = {72contributions: <IEditorContributionDescription[]>[73{ id: MenuPreventer.ID, ctor: MenuPreventer, instantiation: EditorContributionInstantiation.BeforeFirstInteraction },74{ id: ContextMenuController.ID, ctor: ContextMenuController, instantiation: EditorContributionInstantiation.BeforeFirstInteraction },75{ id: SuggestController.ID, ctor: SuggestController, instantiation: EditorContributionInstantiation.Eager },76{ id: SnippetController2.ID, ctor: SnippetController2, instantiation: EditorContributionInstantiation.Lazy },77{ id: TabCompletionController.ID, ctor: TabCompletionController, instantiation: EditorContributionInstantiation.Eager }, // eager because it needs to define a context key78{ id: EditorDictation.ID, ctor: EditorDictation, instantiation: EditorContributionInstantiation.Lazy },79...EditorExtensionsRegistry.getSomeEditorContributions([80CopyPasteController.ID,81DropIntoEditorController.ID,82LinkDetector.ID,83MessageController.ID,84ContentHoverController.ID,85GlyphHoverController.ID,86SelectionClipboardContributionID,87InlineCompletionsController.ID,88CodeActionController.ID,89PlaceholderTextContribution.ID90])91],92contextMenuId: MenuId.SimpleEditorContext93};9495super(domElement, options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, scopedContextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService, userInteractionService);9697this._commentEditorFocused = ctxCommentEditorFocused.bindTo(scopedContextKeyService);98this._commentEditorEmpty = CommentContextKeys.commentIsEmpty.bindTo(scopedContextKeyService);99this._commentEditorEmpty.set(!this.getModel()?.getValueLength());100this._parentThread = parentThread;101102this._register(this.onDidFocusEditorWidget(_ => this._commentEditorFocused.set(true)));103104this._register(this.onDidChangeModelContent(e => this._commentEditorEmpty.set(!this.getModel()?.getValueLength())));105this._register(this.onDidBlurEditorWidget(_ => this._commentEditorFocused.reset()));106}107108getParentThread(): ICommentThreadWidget {109return this._parentThread;110}111112protected _getActions(): Iterable<EditorAction> {113return EditorExtensionsRegistry.getEditorActions();114}115116public override updateOptions(newOptions: Readonly<IEditorOptions> | undefined): void {117const withLineNumberRemoved: Readonly<IEditorOptions> = { ...newOptions, lineNumbers: 'off' };118super.updateOptions(withLineNumberRemoved);119}120121public static getEditorOptions(configurationService: IConfigurationService): IEditorOptions {122return {123wordWrap: 'on',124glyphMargin: false,125lineNumbers: 'off',126folding: false,127selectOnLineNumbers: false,128scrollbar: {129vertical: 'visible',130verticalScrollbarSize: 14,131horizontal: 'auto',132useShadows: true,133verticalHasArrows: false,134horizontalHasArrows: false,135alwaysConsumeMouseWheel: false136},137overviewRulerLanes: 2,138lineDecorationsWidth: 0,139scrollBeyondLastLine: false,140renderLineHighlight: 'none',141fixedOverflowWidgets: true,142acceptSuggestionOnEnter: 'smart',143minimap: {144enabled: false145},146dropIntoEditor: { enabled: true },147autoClosingBrackets: configurationService.getValue('editor.autoClosingBrackets'),148quickSuggestions: false,149accessibilitySupport: configurationService.getValue<'auto' | 'off' | 'on'>('editor.accessibilitySupport'),150fontFamily: configurationService.getValue('editor.fontFamily'),151fontSize: configurationService.getValue('editor.fontSize'),152allowVariableLineHeights: false153};154}155}156157export function calculateEditorHeight(parentEditor: LayoutableEditor, editor: ICodeEditor, currentHeight: number): number {158const layoutInfo = editor.getLayoutInfo();159const lineHeight = editor.getOption(EditorOption.lineHeight);160const contentHeight = (editor._getViewModel()?.getLineCount()! * lineHeight); // Can't just call getContentHeight() because it returns an incorrect, large, value when the editor is first created.161if ((contentHeight > layoutInfo.height) ||162(contentHeight < layoutInfo.height && currentHeight > MIN_EDITOR_HEIGHT)) {163const linesToAdd = Math.ceil((contentHeight - layoutInfo.height) / lineHeight);164const proposedHeight = layoutInfo.height + (lineHeight * linesToAdd);165return clamp(proposedHeight, MIN_EDITOR_HEIGHT, clamp(parentEditor.getLayoutInfo().height - 90, MIN_EDITOR_HEIGHT, MAX_EDITOR_HEIGHT));166}167return currentHeight;168}169170171