From 7be06d1de3a5aa2006aa4ae5c7fbcfe82ae2dc8a Mon Sep 17 00:00:00 2001 From: Ives van Hoorne Date: Tue, 7 Nov 2023 18:51:58 +0100 Subject: [PATCH] feat: add support for creating custom editors for files --- demo/src/features/customView.ts | 2 ++ src/service-override/views.ts | 32 ++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/demo/src/features/customView.ts b/demo/src/features/customView.ts index ae439b53..4372abc3 100644 --- a/demo/src/features/customView.ts +++ b/demo/src/features/customView.ts @@ -54,6 +54,8 @@ const { CustomEditorInput } = registerEditorPane({ return { dispose () { + }, + setInput(input: EditorInput) { } } } diff --git a/src/service-override/views.ts b/src/service-override/views.ts index d1dceae2..d910d5f7 100644 --- a/src/service-override/views.ts +++ b/src/service-override/views.ts @@ -54,8 +54,8 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService' import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService' import { EditorInput, IEditorCloseHandler } from 'vs/workbench/common/editor/editorInput' -import { EditorExtensions, Verbosity } from 'vs/workbench/common/editor' -import { IEditorOptions } from 'vs/platform/editor/common/editor' +import { EditorExtensions, IEditorOpenContext, Verbosity } from 'vs/workbench/common/editor' +import { IEditorOptions, IResourceEditorInput, ITextResourceEditorInput } from 'vs/platform/editor/common/editor' import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService' import { ITextEditorService, TextEditorService } from 'vs/workbench/services/textfile/common/textEditorService' import { CodeEditorService } from 'vs/workbench/services/editor/browser/codeEditorService' @@ -96,6 +96,7 @@ import getKeybindingsOverride from './keybindings' import { changeUrlDomain } from './tools/url' import { registerAssets } from '../assets' import { registerServiceInitializePostParticipant } from '../lifecycle' +import { CancellationToken } from 'vs/base/common/cancellation' function createPart (id: string, role: string, classes: string[]): HTMLElement { const part = document.createElement(role === 'status' ? 'footer' /* Use footer element for status bar #98376 */ : 'div') @@ -190,6 +191,10 @@ function renderStatusBarPart (container: HTMLElement): IDisposable { return attachPart(Parts.STATUSBAR_PART, container) } +interface BodyRenderer extends IDisposable { + setInput? (input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise +} + type Label = string | { short: string medium: string @@ -198,7 +203,7 @@ type Label = string | { interface EditorPanelOption { readonly id: string name: string - renderBody (container: HTMLElement): IDisposable + renderBody (container: HTMLElement): BodyRenderer } interface SimpleEditorInput extends EditorInput { @@ -211,6 +216,7 @@ interface SimpleEditorInput extends EditorInput { function registerEditorPane (options: EditorPanelOption): { disposable: IDisposable, CustomEditorInput: new (closeHandler?: IEditorCloseHandler) => SimpleEditorInput } { class CustomEditorPane extends EditorPane { private content?: HTMLElement + private bodyRenderer?: BodyRenderer constructor ( @ITelemetryService telemetryService: ITelemetryService, @IThemeService themeService: IThemeService, @@ -224,13 +230,22 @@ function registerEditorPane (options: EditorPanelOption): { disposable: IDisposa this.content.style.display = 'flex' this.content.style.alignItems = 'stretch' append(parent, this.content) - this._register(options.renderBody(this.content)) + this.bodyRenderer = options.renderBody(this.content) + this._register(this.bodyRenderer) } override layout (dimension: Dimension): void { this.content!.style.height = `${dimension.height}px` this.content!.style.width = `${dimension.width}px` } + + override async setInput (input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + if (this.bodyRenderer != null && this.bodyRenderer.setInput != null) { + await this.bodyRenderer.setInput(input, options, context, token) + } + + return super.setInput(input, options, context, token) + } } class CustomEditorInput extends EditorInput implements SimpleEditorInput { @@ -241,7 +256,7 @@ function registerEditorPane (options: EditorPanelOption): { disposable: IDisposa private description: Label = options.name private dirty: boolean = false - constructor (public override readonly closeHandler?: IEditorCloseHandler) { + constructor (public override readonly closeHandler?: IEditorCloseHandler, public baseInput?: IResourceEditorInput | ITextResourceEditorInput | undefined, private internalEditorId?: string | undefined) { super() } @@ -250,6 +265,9 @@ function registerEditorPane (options: EditorPanelOption): { disposable: IDisposa } override get resource (): URI | undefined { + if (this.baseInput != null) { + return this.baseInput.resource + } return undefined } @@ -681,5 +699,7 @@ export { SidebarPart, ActivitybarPart, PanelPart, - Parts + Parts, + + BodyRenderer }