From c2a70b1779955a303cdc144fda4845801ec54f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Spo=CC=88nemann?= Date: Fri, 14 Jun 2024 11:33:47 +0200 Subject: [PATCH] Added editing features to Langium-based example --- .../states-langium/extension/package.json | 16 ++-- .../extension/src/states-extension.ts | 19 ++-- .../language-server/src/code-actions.ts | 89 +++++++++++++++++++ .../language-server/src/diagram-generator.ts | 26 +++--- .../language-server/src/states-module.ts | 4 + examples/states-webview/css/popup.css | 15 ++++ examples/states-webview/src/di.config.ts | 3 +- .../extension/src/states-extension.ts | 19 ++-- .../codeActions/StatesCodeActionService.xtend | 22 ++--- .../editing/vscode-lsp-edit-diagram-server.ts | 6 +- .../src/lsp/lsp-sprotty-editor-provider.ts | 4 +- .../src/lsp/lsp-sprotty-view-provider.ts | 4 +- .../src/lsp/lsp-webview-panel-manager.ts | 4 +- .../src/sprotty-editor-provider.ts | 5 +- .../src/sprotty-view-provider.ts | 5 +- .../src/webview-panel-manager.ts | 19 ++-- 16 files changed, 195 insertions(+), 65 deletions(-) create mode 100644 examples/states-langium/language-server/src/code-actions.ts create mode 100644 examples/states-webview/css/popup.css diff --git a/examples/states-langium/extension/package.json b/examples/states-langium/extension/package.json index 75481db..bfd8b61 100644 --- a/examples/states-langium/extension/package.json +++ b/examples/states-langium/extension/package.json @@ -106,19 +106,19 @@ }, { "command": "states.diagram.fit", - "when": "states-diagram-focused" + "when": "states-focused" }, { "command": "states.diagram.center", - "when": "states-diagram-focused" + "when": "states-focused" }, { "command": "states.diagram.delete", - "when": "states-diagram-focused" + "when": "states-focused" }, { "command": "states.diagram.export", - "when": "states-diagram-focused" + "when": "states-focused" } ], "editor/context": [ @@ -148,25 +148,25 @@ "key": "alt+f", "mac": "alt+f", "command": "states.diagram.fit", - "when": "states-diagram-focused" + "when": "states-focused" }, { "key": "alt+c", "mac": "alt+c", "command": "states.diagram.center", - "when": "states-diagram-focused" + "when": "states-focused" }, { "key": "alt+e", "mac": "alt+e", "command": "states.diagram.export", - "when": "states-diagram-focused" + "when": "states-focused" }, { "key": "delete", "mac": "delete", "command": "states.diagram.delete", - "when": "states-diagram-focused" + "when": "states-focused" } ] }, diff --git a/examples/states-langium/extension/src/states-extension.ts b/examples/states-langium/extension/src/states-extension.ts index 1cccc50..a17c139 100644 --- a/examples/states-langium/extension/src/states-extension.ts +++ b/examples/states-langium/extension/src/states-extension.ts @@ -16,10 +16,11 @@ import * as path from 'path'; import { - SprottyDiagramIdentifier, WebviewContainer, createFileUri, createWebviewHtml as doCreateWebviewHtml, - registerDefaultCommands, registerTextEditorSync + SprottyDiagramIdentifier, WebviewContainer, WebviewEndpoint, createFileUri, createWebviewHtml as doCreateWebviewHtml, + registerDefaultCommands, registerLspEditCommands, registerTextEditorSync } from 'sprotty-vscode'; -import { LspSprottyEditorProvider, LspSprottyViewProvider, LspWebviewPanelManager } from 'sprotty-vscode/lib/lsp'; +import { LspSprottyEditorProvider, LspSprottyViewProvider, LspWebviewEndpoint, LspWebviewPanelManager } from 'sprotty-vscode/lib/lsp'; +import { addLspLabelEditActionHandler, addWorkspaceEditActionHandler } from 'sprotty-vscode/lib/lsp/editing'; import * as vscode from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; import { Messenger } from 'vscode-messenger'; @@ -39,6 +40,10 @@ export function activate(context: vscode.ExtensionContext) { scriptUri: createFileUri(extensionPath, 'pack', 'diagram', 'main.js'), cssUri: createFileUri(extensionPath, 'pack', 'diagram', 'main.css') }); + const configureEndpoint = (endpoint: WebviewEndpoint) => { + addWorkspaceEditActionHandler(endpoint as LspWebviewEndpoint); + addLspLabelEditActionHandler(endpoint as LspWebviewEndpoint); + }; if (diagramMode === 'panel') { // Set up webview panel manager for freestyle webviews @@ -48,9 +53,11 @@ export function activate(context: vscode.ExtensionContext) { languageClient, supportedFileExtensions: ['.sm'], localResourceRoots, - createWebviewHtml + createWebviewHtml, + configureEndpoint }); registerDefaultCommands(webviewPanelManager, context, { extensionPrefix: 'states' }); + registerLspEditCommands(webviewPanelManager, context, { extensionPrefix: 'states' }); } if (diagramMode === 'editor') { @@ -61,7 +68,8 @@ export function activate(context: vscode.ExtensionContext) { languageClient, supportedFileExtensions: ['.sm'], localResourceRoots, - createWebviewHtml + createWebviewHtml, + configureEndpoint }); context.subscriptions.push( vscode.window.registerCustomEditorProvider('states', webviewEditorProvider, { @@ -69,6 +77,7 @@ export function activate(context: vscode.ExtensionContext) { }) ); registerDefaultCommands(webviewEditorProvider, context, { extensionPrefix: 'states' }); + registerLspEditCommands(webviewEditorProvider, context, { extensionPrefix: 'states' }); } if (diagramMode === 'view') { diff --git a/examples/states-langium/language-server/src/code-actions.ts b/examples/states-langium/language-server/src/code-actions.ts new file mode 100644 index 0000000..cf76812 --- /dev/null +++ b/examples/states-langium/language-server/src/code-actions.ts @@ -0,0 +1,89 @@ +/******************************************************************************** + * Copyright (c) 2023 TypeFox and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { LangiumDocument, MaybePromise, URI } from 'langium'; +import { CodeActionProvider } from 'langium/lsp'; +import { CodeActionParams, Command, CodeAction, Position, WorkspaceEdit } from 'vscode-languageserver'; +import { StateMachine } from './generated/ast.js'; + +const CREATE_STATE_KIND = 'sprotty.create.state'; +const CREATE_EVENT_KIND = 'sprotty.create.event'; + +export class StatesCodeActionProvider implements CodeActionProvider { + + getCodeActions(document: LangiumDocument, params: CodeActionParams): MaybePromise<(Command | CodeAction)[] | undefined> { + const sm = document.parseResult.value; + const result: CodeAction[] = []; + const endOfDocument = document.textDocument.positionAt(document.textDocument.getText().length); + if (matchesContext(CREATE_STATE_KIND, params)) { + result.push({ + kind: CREATE_STATE_KIND, + title: 'new State', + edit: createInsertWorkspaceEdit( + document.uri, + endOfDocument, + '\n' + 'state ' + getNewName('state', sm.states.map(s => s.name)) + ) + }); + } + if (matchesContext(CREATE_EVENT_KIND, params)) { + result.push({ + kind: CREATE_EVENT_KIND, + title: 'new Event', + edit: createInsertWorkspaceEdit( + document.uri, + endOfDocument, + '\n' + 'event '+ getNewName('event', sm.events.map(e => e.name)) + ) + }); + } + return result; + } + +} + +function matchesContext(kind: string, params: CodeActionParams): boolean { + if (!params.context?.only) { + return true; + } else { + return params.context.only.some(k => kind.startsWith(k)); + } +} + +function getNewName(prefix: string, siblings: string[]): string { + for (let i = 0;; i++) { + const currentName = prefix + i; + if (!siblings.some(s => s === currentName)) { + return currentName; + } + } +} + +function createInsertWorkspaceEdit(uri: URI, position: Position, text: string): WorkspaceEdit { + return { + changes: { + [uri.toString()]: [ + { + range: { + start: position, + end: position + }, + newText: text + } + ] + } + }; +} diff --git a/examples/states-langium/language-server/src/diagram-generator.ts b/examples/states-langium/language-server/src/diagram-generator.ts index 885a7f1..5dd9959 100644 --- a/examples/states-langium/language-server/src/diagram-generator.ts +++ b/examples/states-langium/language-server/src/diagram-generator.ts @@ -15,7 +15,7 @@ ********************************************************************************/ import { GeneratorContext, LangiumDiagramGenerator } from 'langium-sprotty'; -import { SEdge, SLabel, SModelRoot, SNode, SPort, EdgeLayoutable } from 'sprotty-protocol'; +import { SEdge, SLabel, SModelRoot, SNode, SPort } from 'sprotty-protocol'; import { State, StateMachine, Transition } from './generated/ast.js'; export class StatesDiagramGenerator extends LangiumDiagramGenerator { @@ -38,15 +38,17 @@ export class StatesDiagramGenerator extends LangiumDiagramGenerator { protected generateNode(state: State, ctx: GeneratorContext): SNode { const { idCache } = ctx; const nodeId = idCache.uniqueId(state.name, state); + const label: SLabel = { + type: 'label', + id: idCache.uniqueId(nodeId + '.label'), + text: state.name + }; + this.traceProvider.trace(label, state, 'name'); const node = { type: 'node', id: nodeId, children: [ - { - type: 'label', - id: idCache.uniqueId(nodeId + '.label'), - text: state.name - }, + label, { type: 'port', id: idCache.uniqueId(nodeId + '.newTransition') @@ -70,17 +72,19 @@ export class StatesDiagramGenerator extends LangiumDiagramGenerator { const sourceId = idCache.getId(transition.$container); const targetId = idCache.getId(transition.state?.ref); const edgeId = idCache.uniqueId(`${sourceId}:${transition.event?.ref?.name}:${targetId}`, transition); + const label: SLabel = { + type: 'label:xref', + id: idCache.uniqueId(edgeId + '.label'), + text: transition.event?.ref?.name ?? '' + } + this.traceProvider.trace(label, transition, 'event'); const edge = { type: 'edge', id: edgeId, sourceId: sourceId!, targetId: targetId!, children: [ - { - type: 'label:xref', - id: idCache.uniqueId(edgeId + '.label'), - text: transition.event?.ref?.name - } + label ] }; this.traceProvider.trace(edge, transition); diff --git a/examples/states-langium/language-server/src/states-module.ts b/examples/states-langium/language-server/src/states-module.ts index 6aa92dd..2b73f2a 100644 --- a/examples/states-langium/language-server/src/states-module.ts +++ b/examples/states-langium/language-server/src/states-module.ts @@ -23,6 +23,7 @@ import { StatesDiagramGenerator } from './diagram-generator.js'; import { StatesGeneratedModule, StatesGeneratedSharedModule } from './generated/module.js'; import { StatesLayoutConfigurator } from './layout-config.js'; import { registerValidationChecks, StatesValidator } from './states-validator.js'; +import { StatesCodeActionProvider } from './code-actions.js'; /** * Declaration of custom services - add your own service classes here. @@ -61,6 +62,9 @@ export const StatesModule: Module () => new ElkConstructor({ algorithms: ['layered'] }), ElementFilter: () => new DefaultElementFilter, LayoutConfigurator: () => new StatesLayoutConfigurator + }, + lsp: { + CodeActionProvider: () => new StatesCodeActionProvider() } }; diff --git a/examples/states-webview/css/popup.css b/examples/states-webview/css/popup.css new file mode 100644 index 0000000..f318eb2 --- /dev/null +++ b/examples/states-webview/css/popup.css @@ -0,0 +1,15 @@ +.sprotty-popup { + padding: 0; + color: var(--vscode-editorHoverWidget-foreground); + background: var(--vscode-editorHoverWidget-background); + border-color: var(--vscode-editorHoverWidget-border); +} + +.sprotty-palette > div { + padding: 0 4px; + cursor: pointer; +} + +.sprotty-palette > div:hover { + color: var(--vscode-textLink-activeForeground); +} diff --git a/examples/states-webview/src/di.config.ts b/examples/states-webview/src/di.config.ts index 62482b1..b9c8f42 100644 --- a/examples/states-webview/src/di.config.ts +++ b/examples/states-webview/src/di.config.ts @@ -14,8 +14,9 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import '../css/diagram.css'; import 'sprotty/css/sprotty.css'; +import '../css/diagram.css'; +import '../css/popup.css'; import { Container, ContainerModule } from 'inversify'; import { diff --git a/examples/states-xtext/extension/src/states-extension.ts b/examples/states-xtext/extension/src/states-extension.ts index d972935..9d9b853 100644 --- a/examples/states-xtext/extension/src/states-extension.ts +++ b/examples/states-xtext/extension/src/states-extension.ts @@ -15,7 +15,7 @@ ********************************************************************************/ import * as path from 'path'; -import { registerDefaultCommands, registerLspEditCommands, SprottyDiagramIdentifier } from 'sprotty-vscode'; +import { registerDefaultCommands, registerLspEditCommands } from 'sprotty-vscode'; import { LspWebviewEndpoint, LspWebviewPanelManager } from 'sprotty-vscode/lib/lsp'; import { addLspLabelEditActionHandler, addWorkspaceEditActionHandler } from 'sprotty-vscode/lib/lsp/editing'; import * as vscode from 'vscode'; @@ -25,11 +25,15 @@ let languageClient: LanguageClient; export function activate(context: vscode.ExtensionContext) { languageClient = createLanguageClient(context); - const webviewPanelManager = new StatesWebviewPanelManager({ + const webviewPanelManager = new LspWebviewPanelManager({ extensionUri: context.extensionUri, defaultDiagramType: 'states-diagram', languageClient, - supportedFileExtensions: ['.sm'] + supportedFileExtensions: ['.sm'], + configureEndpoint: endpoint => { + addWorkspaceEditActionHandler(endpoint as LspWebviewEndpoint); + addLspLabelEditActionHandler(endpoint as LspWebviewEndpoint); + } }); registerDefaultCommands(webviewPanelManager, context, { extensionPrefix: 'states' }); registerLspEditCommands(webviewPanelManager, context, { extensionPrefix: 'states' }); @@ -57,15 +61,6 @@ function createLanguageClient(context: vscode.ExtensionContext): LanguageClient return languageClient; } -class StatesWebviewPanelManager extends LspWebviewPanelManager { - protected override createEndpoint(identifier: SprottyDiagramIdentifier): LspWebviewEndpoint { - const endpoint = super.createEndpoint(identifier); - addWorkspaceEditActionHandler(endpoint); - addLspLabelEditActionHandler(endpoint); - return endpoint; - } -} - export async function deactivate(): Promise { if (languageClient) { await languageClient.stop(); diff --git a/examples/states-xtext/language-server/io.typefox.examples.theia.states.ide/src/main/java/io/typefox/examples/theia/states/ide/server/codeActions/StatesCodeActionService.xtend b/examples/states-xtext/language-server/io.typefox.examples.theia.states.ide/src/main/java/io/typefox/examples/theia/states/ide/server/codeActions/StatesCodeActionService.xtend index f8a20cd..d8ada94 100644 --- a/examples/states-xtext/language-server/io.typefox.examples.theia.states.ide/src/main/java/io/typefox/examples/theia/states/ide/server/codeActions/StatesCodeActionService.xtend +++ b/examples/states-xtext/language-server/io.typefox.examples.theia.states.ide/src/main/java/io/typefox/examples/theia/states/ide/server/codeActions/StatesCodeActionService.xtend @@ -22,7 +22,7 @@ class StatesCodeActionService implements ICodeActionService2 { override getCodeActions(Options options) { - var root = options.resource.contents.head + var root = options.resource?.contents?.head if (root instanceof StateMachine) createCodeActions(root, options.codeActionParams, options.document) else @@ -34,10 +34,10 @@ class StatesCodeActionService implements ICodeActionService2 { if (CREATE_STATE_KIND.matchesContext(params)) { result.add(Either.forRight(new CodeAction => [ kind = CREATE_STATE_KIND - title = 'new State' + title = 'new State' edit = createInsertWorkspaceEdit( - stateMachine.eResource.URI, - document.getPosition(document.contents.length), + stateMachine.eResource.URI, + document.getPosition(document.contents.length), '''«'\n'»state «getNewName('state', stateMachine.states.map[name])»''' ) ])); @@ -45,21 +45,21 @@ class StatesCodeActionService implements ICodeActionService2 { if (CREATE_EVENT_KIND.matchesContext(params)) { result.add(Either.forRight(new CodeAction => [ kind = CREATE_EVENT_KIND - title = 'new Event' + title = 'new Event' edit = createInsertWorkspaceEdit( - stateMachine.eResource.URI, - document.getPosition(document.contents.length), + stateMachine.eResource.URI, + document.getPosition(document.contents.length), '''«'\n'»event «getNewName('event', stateMachine.events.map[name])»''' ) ])); } - return result + return result } private def matchesContext(String kind, CodeActionParams params) { if (params.context?.only === null) return true - else + else return params.context.only.exists[kind.startsWith(it)] } @@ -72,12 +72,12 @@ class StatesCodeActionService implements ICodeActionService2 { } private def dispatch List> createCodeActions(EObject element, CodeActionParams params, Document document) { - return emptyList + return emptyList } private def createInsertWorkspaceEdit(URI uri, Position position, String text) { new WorkspaceEdit => [ changes = #{uri.toString -> #[ new TextEdit(new Range(position, position), text) ]} ] - } + } } \ No newline at end of file diff --git a/packages/sprotty-vscode-webview/src/lsp/editing/vscode-lsp-edit-diagram-server.ts b/packages/sprotty-vscode-webview/src/lsp/editing/vscode-lsp-edit-diagram-server.ts index 334a416..71afe90 100644 --- a/packages/sprotty-vscode-webview/src/lsp/editing/vscode-lsp-edit-diagram-server.ts +++ b/packages/sprotty-vscode-webview/src/lsp/editing/vscode-lsp-edit-diagram-server.ts @@ -16,7 +16,7 @@ import { ActionHandlerRegistry, EditLabelAction } from 'sprotty'; import { - Action, getBasicType, getSubType, SModelElement as SModelElementSchema, SModelIndex + Action, getBasicType, getSubType, SModelElement as SModelElementSchema, findElement } from 'sprotty-protocol'; import { LspLabelEditAction, WorkspaceEditAction } from 'sprotty-vscode-protocol/lib/lsp/editing'; @@ -53,8 +53,6 @@ export class VscodeLspEditDiagramServer extends VscodeDiagramServer { } protected getElement(elementId: string): SModelElementSchema | undefined { - const index = new SModelIndex(); - index.add(this.currentRoot); - return index.getById(elementId); + return findElement(this.currentRoot, elementId); } } diff --git a/packages/sprotty-vscode/src/lsp/lsp-sprotty-editor-provider.ts b/packages/sprotty-vscode/src/lsp/lsp-sprotty-editor-provider.ts index 29f9e02..ac6042c 100644 --- a/packages/sprotty-vscode/src/lsp/lsp-sprotty-editor-provider.ts +++ b/packages/sprotty-vscode/src/lsp/lsp-sprotty-editor-provider.ts @@ -45,13 +45,15 @@ export class LspSprottyEditorProvider extends SprottyEditorProvider { protected override createEndpoint(identifier: SprottyDiagramIdentifier, webviewContainer: vscode.WebviewPanel): WebviewEndpoint { const participant = this.messenger.registerWebviewPanel(webviewContainer); - return new LspWebviewEndpoint({ + const endpoint = new LspWebviewEndpoint({ languageClient: this.languageClient, webviewContainer, messenger: this.messenger, messageParticipant: participant, identifier }); + this.options.configureEndpoint?.(endpoint); + return endpoint; } protected override disposeDocument(document: SprottyDocument): void { diff --git a/packages/sprotty-vscode/src/lsp/lsp-sprotty-view-provider.ts b/packages/sprotty-vscode/src/lsp/lsp-sprotty-view-provider.ts index 6249867..50e6bda 100644 --- a/packages/sprotty-vscode/src/lsp/lsp-sprotty-view-provider.ts +++ b/packages/sprotty-vscode/src/lsp/lsp-sprotty-view-provider.ts @@ -45,13 +45,15 @@ export class LspSprottyViewProvider extends SprottyViewProvider { protected override createEndpoint(webviewContainer: vscode.WebviewView, identifier?: SprottyDiagramIdentifier): WebviewEndpoint { const participant = this.messenger.registerWebviewView(webviewContainer); - return new LspWebviewEndpoint({ + const endpoint = new LspWebviewEndpoint({ languageClient: this.languageClient, webviewContainer, messenger: this.messenger, messageParticipant: participant, identifier }); + this.options.configureEndpoint?.(endpoint); + return endpoint; } protected override didCloseWebview(endpoint: WebviewEndpoint): void { diff --git a/packages/sprotty-vscode/src/lsp/lsp-webview-panel-manager.ts b/packages/sprotty-vscode/src/lsp/lsp-webview-panel-manager.ts index 44e62b9..be633a1 100644 --- a/packages/sprotty-vscode/src/lsp/lsp-webview-panel-manager.ts +++ b/packages/sprotty-vscode/src/lsp/lsp-webview-panel-manager.ts @@ -45,13 +45,15 @@ export class LspWebviewPanelManager extends WebviewPanelManager { protected override createEndpoint(identifier: SprottyDiagramIdentifier): LspWebviewEndpoint { const webviewContainer = this.createWebview(identifier); const participant = this.messenger.registerWebviewPanel(webviewContainer); - return new LspWebviewEndpoint({ + const endpoint = new LspWebviewEndpoint({ languageClient: this.languageClient, webviewContainer, messenger: this.messenger, messageParticipant: participant, identifier }); + this.options.configureEndpoint?.(endpoint); + return endpoint; } protected override didCloseWebview(endpoint: WebviewEndpoint): void { diff --git a/packages/sprotty-vscode/src/sprotty-editor-provider.ts b/packages/sprotty-vscode/src/sprotty-editor-provider.ts index 6492cee..6f28710 100644 --- a/packages/sprotty-vscode/src/sprotty-editor-provider.ts +++ b/packages/sprotty-vscode/src/sprotty-editor-provider.ts @@ -26,6 +26,7 @@ export interface SprottyEditorProviderOptions { messenger?: Messenger supportedFileExtensions?: string[] createWebviewHtml?: (identifier: SprottyDiagramIdentifier, container: WebviewContainer) => string + configureEndpoint?: (endpoint: WebviewEndpoint) => void localResourceRoots?: vscode.Uri[] } @@ -102,12 +103,14 @@ export class SprottyEditorProvider implements vscode.CustomEditorProvider, IWebv protected createEndpoint(identifier: SprottyDiagramIdentifier, webviewContainer: vscode.WebviewPanel): WebviewEndpoint { const participant = this.messenger.registerWebviewPanel(webviewContainer); - return new WebviewEndpoint({ + const endpoint = new WebviewEndpoint({ webviewContainer, messenger: this.messenger, messageParticipant: participant, identifier }); + this.options.configureEndpoint?.(endpoint); + return endpoint; } /** diff --git a/packages/sprotty-vscode/src/sprotty-view-provider.ts b/packages/sprotty-vscode/src/sprotty-view-provider.ts index fe1aafd..7295cde 100644 --- a/packages/sprotty-vscode/src/sprotty-view-provider.ts +++ b/packages/sprotty-vscode/src/sprotty-view-provider.ts @@ -27,6 +27,7 @@ export interface SprottyViewProviderOptions { supportedFileExtensions?: string[] openActiveEditor?: boolean createWebviewHtml?: (identifier: SprottyDiagramIdentifier, container: WebviewContainer) => string + configureEndpoint?: (endpoint: WebviewEndpoint) => void localResourceRoots?: vscode.Uri[] } @@ -99,12 +100,14 @@ export class SprottyViewProvider implements vscode.WebviewViewProvider, IWebview protected createEndpoint(webviewContainer: vscode.WebviewView, identifier?: SprottyDiagramIdentifier): WebviewEndpoint { const participant = this.messenger.registerWebviewView(webviewContainer); - return new WebviewEndpoint({ + const endpoint = new WebviewEndpoint({ webviewContainer, messenger: this.messenger, messageParticipant: participant, identifier }); + this.options.configureEndpoint?.(endpoint); + return endpoint; } /** diff --git a/packages/sprotty-vscode/src/webview-panel-manager.ts b/packages/sprotty-vscode/src/webview-panel-manager.ts index eb88043..a8317f1 100644 --- a/packages/sprotty-vscode/src/webview-panel-manager.ts +++ b/packages/sprotty-vscode/src/webview-panel-manager.ts @@ -21,13 +21,14 @@ import { isWebviewPanel, IWebviewEndpointManager, OpenDiagramOptions, WebviewCon import { createFileUri, createWebviewHtml, createWebviewTitle, getExtname, serializeUri } from './webview-utils'; export interface WebviewPanelManagerOptions { - extensionUri: vscode.Uri; - messenger?: Messenger; - defaultDiagramType?: string; - supportedFileExtensions?: string[]; - singleton?: boolean; - createWebviewHtml?: (identifier: SprottyDiagramIdentifier, container: WebviewContainer) => string; - localResourceRoots?: vscode.Uri[]; + extensionUri: vscode.Uri + messenger?: Messenger + defaultDiagramType?: string + supportedFileExtensions?: string[] + singleton?: boolean + createWebviewHtml?: (identifier: SprottyDiagramIdentifier, container: WebviewContainer) => string + configureEndpoint?: (endpoint: WebviewEndpoint) => void + localResourceRoots?: vscode.Uri[] } export interface OpenPanelOptions extends OpenDiagramOptions { @@ -93,12 +94,14 @@ export class WebviewPanelManager implements IWebviewEndpointManager { protected createEndpoint(identifier: SprottyDiagramIdentifier): WebviewEndpoint { const webviewContainer = this.createWebview(identifier); const participant = this.messenger.registerWebviewPanel(webviewContainer); - return new WebviewEndpoint({ + const endpoint = new WebviewEndpoint({ webviewContainer, messenger: this.messenger, messageParticipant: participant, identifier }); + this.options.configureEndpoint?.(endpoint); + return endpoint; } /**