sprotty-vscode
Version:
Glue code to integrate Sprotty diagrams in VSCode extensions (extension part)
153 lines • 6.43 kB
JavaScript
"use strict";
/********************************************************************************
* Copyright (c) 2022 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
********************************************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebviewEndpoint = exports.isWebviewView = exports.isWebviewPanel = void 0;
const sprotty_protocol_1 = require("sprotty-protocol");
const sprotty_vscode_protocol_1 = require("sprotty-vscode-protocol");
const vscode = require("vscode");
function isWebviewPanel(container) {
return typeof container.onDidChangeViewState === 'function';
}
exports.isWebviewPanel = isWebviewPanel;
function isWebviewView(container) {
return typeof container.onDidChangeVisibility === 'function';
}
exports.isWebviewView = isWebviewView;
/**
* Wrapper class around a webview panel or webview view. This service takes care of the communication between the webview
* and the host extension.
*/
class WebviewEndpoint {
constructor(options) {
this.actionHandlers = new Map();
this.disposables = [];
this.webviewReady = new Promise(resolve => this.resolveWebviewReady = resolve);
this.webviewContainer = options.webviewContainer;
this.messenger = options.messenger;
this.messageParticipant = options.messageParticipant;
this.diagramIdentifier = options.identifier;
if (options.diagramServer) {
this.diagramServer = options.diagramServer;
}
else if (options.diagramServerFactory) {
const dispatch = (action) => this.sendAction(action);
this.diagramServer = options.diagramServerFactory(dispatch);
}
this.connect();
}
get ready() {
return this.webviewReady;
}
connect() {
this.disposables.push(this.webviewContainer.onDidDispose(() => {
this.disposables.forEach(disposable => disposable.dispose());
}));
if (isWebviewPanel(this.webviewContainer)) {
this.disposables.push(this.webviewContainer.onDidChangeViewState(event => {
this.setWebviewActiveContext(event.webviewPanel.active);
}));
}
this.disposables.push(this.messenger.onNotification(sprotty_vscode_protocol_1.ActionNotification, message => this.receiveAction(message), { sender: this.messageParticipant }));
this.disposables.push(this.messenger.onNotification(sprotty_vscode_protocol_1.WebviewReadyNotification, message => {
this.resolveWebviewReady();
this.sendDiagramIdentifier();
}, { sender: this.messageParticipant }));
}
/**
* Enable or disable a context variable to be used in UI contributions in the package.json file.
*/
setWebviewActiveContext(isActive) {
if (this.diagramIdentifier) {
vscode.commands.executeCommand('setContext', this.diagramIdentifier.diagramType + '-focused', isActive);
}
}
/**
* Trigger loading of new content in the webview. The content is identified by the URI and diagram type.
*/
async reloadContent(newIdentifier) {
if (this.diagramIdentifier) {
this.diagramIdentifier.uri = newIdentifier.uri;
this.diagramIdentifier.diagramType = newIdentifier.diagramType;
}
else {
this.diagramIdentifier = newIdentifier;
}
await this.sendDiagramIdentifier();
}
async sendDiagramIdentifier() {
await this.ready;
if (this.diagramIdentifier) {
this.messenger.sendNotification(sprotty_vscode_protocol_1.DiagramIdentifierNotification, this.messageParticipant, this.diagramIdentifier);
}
}
/**
* Send an action to the webview to be processed by the Sprotty frontend.
*/
async sendAction(action) {
var _a;
const message = (0, sprotty_protocol_1.isActionMessage)(action) ? action : {
clientId: (_a = this.diagramIdentifier) === null || _a === void 0 ? void 0 : _a.clientId,
action
};
const handlers = this.actionHandlers.get(message.action.kind);
if (handlers && handlers.length > 0) {
return Promise.all(handlers.map(handler => handler(message.action)));
}
this.messenger.sendNotification(sprotty_vscode_protocol_1.ActionNotification, this.messageParticipant, message);
}
/**
* Process an action received from the webview.
*/
receiveAction(message) {
const action = message.action;
const handlers = this.actionHandlers.get(action.kind);
if (handlers && handlers.length > 0) {
return Promise.all(handlers.map(handler => handler(action)));
}
if (this.diagramServer) {
return this.diagramServer.accept(action);
}
return Promise.resolve();
}
/**
* Add an action handler for actions that are sent or received. If one or more handlers are registered for an
* action kind, the corresponding actions are sent to those handlers and are not propagated further.
*/
addActionHandler(kind, handler) {
const handlers = this.actionHandlers.get(kind);
if (handlers) {
handlers.push(handler);
}
else {
this.actionHandlers.set(kind, [handler]);
}
}
/**
* Remove a previously registered action handler.
*/
removeActionHandler(kind, handler) {
const handlers = this.actionHandlers.get(kind);
if (handlers) {
const index = handlers.indexOf(handler);
if (index >= 0) {
handlers.splice(index, 1);
}
}
}
}
exports.WebviewEndpoint = WebviewEndpoint;
//# sourceMappingURL=webview-endpoint.js.map