Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#315 Refactor base protocol #86

Merged
merged 1 commit into from
Aug 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import 'sprotty-theia/css/theia-sprotty.css';

import { createWorkflowDiagramContainer } from '@eclipse-glsp-examples/workflow-glsp/lib';
import { GLSPDiagramConfiguration } from '@eclipse-glsp/theia-integration';
import { configureDiagramServer, GLSPDiagramConfiguration } from '@eclipse-glsp/theia-integration';
import { Container, injectable } from '@theia/core/shared/inversify';

import { WorkflowLanguage } from '../../common/workflow-language';
Expand All @@ -28,7 +28,7 @@ export class WorkflowDiagramConfiguration extends GLSPDiagramConfiguration {

doCreateContainer(widgetId: string): Container {
const container = createWorkflowDiagramContainer(widgetId);
this.configureDiagramServer(container, WorkflowDiagramServer);
configureDiagramServer(container, WorkflowDiagramServer);
return container;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { ContainerContext, GLSPTheiaFrontendModule } from '@eclipse-glsp/theia-integration';
import { ContainerContext, GLSPClientContribution, GLSPTheiaFrontendModule } from '@eclipse-glsp/theia-integration';
import { CommandContribution, MenuContribution } from '@theia/core';
import { KeybindingContext, KeybindingContribution } from '@theia/core/lib/browser';
import { DiagramConfiguration } from 'sprotty-theia';
Expand All @@ -34,6 +34,7 @@ import {
WorkflowTaskEditMenuContribution
} from './diagram/workflow-task-editing-context-menu';
import { ExampleNavigationCommandContribution } from './external-navigation-example/external-navigation-example';
import { WorkflowGLSPClientContribution } from './workflow-glsp-client-contribution';

export class WorkflowTheiaFrontendModule extends GLSPTheiaFrontendModule {
protected enableCopyPaste = true;
Expand Down Expand Up @@ -61,6 +62,10 @@ export class WorkflowTheiaFrontendModule extends GLSPTheiaFrontendModule {
context.bind(CommandContribution).toService(WorkflowDiagramReadonlyViewContribution);
}

bindGLSPClientContribution(context: ContainerContext): void {
context.bind(GLSPClientContribution).to(WorkflowGLSPClientContribution);
}

}

export default new WorkflowTheiaFrontendModule();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/********************************************************************************
* Copyright (c) 2019-2021 EclipseSource 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 { Args } from '@eclipse-glsp/client';
import { MaybePromise } from '@eclipse-glsp/protocol';
import { BaseGLSPClientContribution } from '@eclipse-glsp/theia-integration/lib/browser';
import { injectable } from '@theia/core/shared/inversify';

import { WorkflowLanguage } from '../common/workflow-language';

export interface WorkflowInitializeOptions {
timestamp: Date;
message: string;
}

@injectable()
export class WorkflowGLSPClientContribution extends BaseGLSPClientContribution {
readonly id = WorkflowLanguage.contributionId;
readonly fileExtensions = WorkflowLanguage.fileExtensions;

protected createInitializeOptions(): MaybePromise<Args | undefined> {
return {
['timestamp']: new Date().toString(),
['message']: 'Custom Options Available'
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
ServerMessageAction,
ServerStatusAction
} from '@eclipse-glsp/client';
import { GLSPClient } from '@eclipse-glsp/protocol';
import { GLSPClient, InitializeResult } from '@eclipse-glsp/protocol';
import { ContributionProvider, MessageService } from '@theia/core';
import { ConfirmDialog, WidgetManager } from '@theia/core/lib/browser';
import { Message, MessageType } from '@theia/core/lib/common';
Expand Down Expand Up @@ -76,11 +76,13 @@ export abstract class BaseTheiaGLSPConnector implements TheiaGLSPConnector {

connect(diagramServer: TheiaDiagramServer): void {
this.servers.set(diagramServer.clientId, diagramServer);
this.glspClient.then(client => client.initializeClientSession({ clientSessionId: diagramServer.clientId, diagramType: this.diagramType }));
diagramServer.connect(this);
}

disconnect(diagramServer: TheiaDiagramServer): void {
this.servers.delete(diagramServer.clientId);
this.glspClient.then(client => client.disposeClientSession({ clientSessionId: diagramServer.clientId }));
diagramServer.disconnect();
}

Expand Down Expand Up @@ -214,13 +216,17 @@ export abstract class BaseTheiaGLSPConnector implements TheiaGLSPConnector {
}

sendMessage(message: ActionMessage): void {
this.glspClientContribution.glspClient.then(client => client.sendActionMessage(message));
this.glspClient.then(client => client.sendActionMessage(message));
}

getGLSPClient(): Promise<GLSPClient> {
get glspClient(): Promise<GLSPClient> {
return this.glspClientContribution.glspClient;
}

get initializeResult(): Promise<InitializeResult> {
return this.glspClientContribution.initializeResult;
}

onMessageReceived(message: ActionMessage): void {
const diagramServer = this.servers.get(message.clientId);
if (diagramServer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export abstract class GLSPDiagramConfiguration implements DiagramConfiguration {

createContainer(widgetId: string): Container {
const container = this.doCreateContainer(widgetId);

this.initializeContainer(container);
return container;
}
Expand All @@ -69,9 +70,11 @@ export abstract class GLSPDiagramConfiguration implements DiagramConfiguration {
configureActionHandler(container, NavigateToExternalTargetAction.KIND, TheiaNavigateToExternalTargetHandler);
}

protected configureDiagramServer<T>(container: Container, server: { new(...args: any[]): T }): void {
container.bind(TYPES.ModelSource).to(server).inSingletonScope();
container.bind(TheiaDiagramServer).toService(server);
}
}

export function configureDiagramServer<T>(container: Container, server: { new(...args: any[]): T }): void {
container.bind(server).toSelf().inSingletonScope();
container.bind(TYPES.ModelSource).toService(server);
container.bind(TheiaDiagramServer).toService(server);
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { EditMode, GLSPActionDispatcher } from '@eclipse-glsp/client';
import { configureServerActions, EditMode, GLSPActionDispatcher } from '@eclipse-glsp/client';
import {
ApplicationShell,
FrontendApplicationContribution,
Expand Down Expand Up @@ -81,8 +81,11 @@ export abstract class GLSPDiagramManager extends DiagramManager {
protected _diagramConnector: TheiaGLSPConnector;

@postConstruct()
protected initialize(): void {
this.connectorProvider(this.diagramType).then(connector => this._diagramConnector = connector);
protected async initialize(): Promise<void> {
this._diagramConnector = await this.connectorProvider(this.diagramType);
if (!this._diagramConnector) {
throw new Error(`No diagram connector is registered for diagramType: ${this.diagramType}!`);
}
}

async doOpen(widget: DiagramWidget, options?: WidgetOpenerOptions): Promise<void> {
Expand All @@ -103,6 +106,8 @@ export abstract class GLSPDiagramManager extends DiagramManager {
const widgetId = this.createWidgetId(options);
const config = this.getDiagramConfiguration(options);
const diContainer = config.createContainer(clientId);
const initializeResult = await this.diagramConnector.initializeResult;
await configureServerActions(initializeResult, this.diagramType, diContainer);
const widget = new GLSPDiagramWidget(options, widgetId, diContainer, this.editorPreferences, this.theiaSelectionService, this.diagramConnector);
widget.listenToFocusState(this.shell);
return widget;
Expand Down Expand Up @@ -138,7 +143,7 @@ export abstract class GLSPDiagramManager extends DiagramManager {
return 0;
}

get diagramConnector(): TheiaGLSPConnector | undefined {
get diagramConnector(): TheiaGLSPConnector {
return this._diagramConnector;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019-2020 EclipseSource and others.
* Copyright (c) 2019-2021 EclipseSource 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
Expand All @@ -16,15 +16,13 @@
import {
Args,
DiagramServer,
DisposeClientSessionAction,
EditorContextService,
EnableToolPaletteAction,
FocusStateChangedAction,
FocusTracker,
GLSP_TYPES,
IActionDispatcher,
ICopyPasteHandler,
InitializeClientSessionAction,
ModelSource,
RequestModelAction,
RequestTypeHintsAction,
Expand All @@ -40,10 +38,11 @@ import { SelectionService } from '@theia/core/lib/common/selection-service';
import { Container } from '@theia/core/shared/inversify';
import { EditorPreferences } from '@theia/editor/lib/browser';
import { pickBy } from 'lodash';
import { DiagramWidget, DiagramWidgetOptions, isDiagramWidgetContainer, TheiaSprottyConnector } from 'sprotty-theia';
import { DiagramWidget, DiagramWidgetOptions, isDiagramWidgetContainer } from 'sprotty-theia';

import { GLSPWidgetOpenerOptions, GLSPWidgetOptions } from './glsp-diagram-manager';
import { DirtyStateNotifier, GLSPTheiaDiagramServer } from './glsp-theia-diagram-server';
import { TheiaGLSPConnector } from './theia-glsp-connector';

export class GLSPDiagramWidget extends DiagramWidget implements SaveableSource {

Expand All @@ -53,15 +52,14 @@ export class GLSPDiagramWidget extends DiagramWidget implements SaveableSource {
protected requestModelOptions: Args;

constructor(options: DiagramWidgetOptions & GLSPWidgetOpenerOptions, readonly widgetId: string, readonly diContainer: Container,
readonly editorPreferences: EditorPreferences, readonly theiaSelectionService: SelectionService, readonly connector?: TheiaSprottyConnector) {
readonly editorPreferences: EditorPreferences, readonly theiaSelectionService: SelectionService, readonly connector: TheiaGLSPConnector) {
super(options, widgetId, diContainer, connector);
this.saveable = new SaveableGLSPModelSource(this.actionDispatcher, this.diContainer.get<ModelSource>(TYPES.ModelSource));
this.updateSaveable();
this.title.caption = this.uri.path.toString();
const prefUpdater = editorPreferences.onPreferenceChanged(() => this.updateSaveable());
this.toDispose.push(prefUpdater);
this.toDispose.push(this.saveable);
this.toDispose.push(Disposable.create(() => this.actionDispatcher.dispatch(new DisposeClientSessionAction(this.widgetId))));
}

protected updateSaveable(): void {
Expand All @@ -74,23 +72,27 @@ export class GLSPDiagramWidget extends DiagramWidget implements SaveableSource {
if (modelSource instanceof DiagramServer) {
modelSource.clientId = this.id;
}
if (modelSource instanceof GLSPTheiaDiagramServer && this.connector) {
if (modelSource instanceof GLSPTheiaDiagramServer) {
this.connector.connect(modelSource);
}

this.disposed.connect(() => {
if (modelSource instanceof GLSPTheiaDiagramServer && this.connector) {
if (modelSource instanceof GLSPTheiaDiagramServer) {
this.connector.disconnect(modelSource);
}
});

this.actionDispatcher.dispatch(new InitializeClientSessionAction(this.widgetId));
// Filter options to only contain defined primitive values
const definedOptions: any = pickBy(this.options, v => v !== undefined && typeof v !== 'object');
this.requestModelOptions = {
sourceUri: this.uri.path.toString(),
...definedOptions
};

this.dispatchInitialActions();
}

protected dispatchInitialActions(): void {
this.actionDispatcher.dispatch(new RequestModelAction(this.requestModelOptions));
this.actionDispatcher.dispatch(new RequestTypeHintsAction(this.options.diagramType));
this.actionDispatcher.dispatch(new EnableToolPaletteAction());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,23 @@ import {
SourceUriAware
} from '@eclipse-glsp/client';
import { Emitter, Event } from '@theia/core/lib/common';
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
import { injectable } from '@theia/core/shared/inversify';
import { TheiaDiagramServer } from 'sprotty-theia';

import { TheiaGLSPConnector } from './theia-glsp-connector';
import { isTheiaGLSPConnector, TheiaGLSPConnector } from './theia-glsp-connector';

const receivedFromServerProperty = '__receivedFromServer';

@injectable()
export class GLSPTheiaDiagramServer extends TheiaDiagramServer implements DirtyStateNotifier, SourceUriAware {

@inject(TheiaGLSPConnector) protected readonly theiaConnector: TheiaGLSPConnector;

readonly dirtyStateChangeEmitter: Emitter<DirtyState> = new Emitter<DirtyState>();

protected dirtyState: DirtyState = { isDirty: false };

@postConstruct()
protected postConstruct(): void {
this.connect(this.theiaConnector);
}

initialize(registry: ActionHandlerRegistry): void {
registry.register(SetDirtyStateAction.KIND, this);
registry.register(ServerMessageAction.KIND, this);
registry.register(ExportSvgAction.KIND, this);
registerDefaultGLSPServerActions(registry, this);
registry.register(SetDirtyStateAction.KIND, this);
}

public getSourceURI(): string {
Expand Down Expand Up @@ -97,9 +88,19 @@ export class GLSPTheiaDiagramServer extends TheiaDiagramServer implements DirtyS
}

protected handleServerMessageAction(status: ServerMessageAction): boolean {
this.theiaConnector.showMessage(this.clientId, status);
this.connector.showMessage(this.clientId, status);
return false;
}

get connector(): TheiaGLSPConnector {
if (!this._connector) {
throw Error('TheiaDiagramServer is not connected.');
}
if (!isTheiaGLSPConnector(this._connector)) {
throw new Error('Connector needs to be a instance of "TheiaGLSPConnector');
}
return this._connector;
}
}
export class SetDirtyStateAction implements Action {
static readonly KIND = 'setDirtyState';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { InstanceRegistry, ServerMessageAction } from '@eclipse-glsp/client';
import { InitializeResult } from '@eclipse-glsp/protocol';
import { injectable, multiInject, optional } from '@theia/core/shared/inversify';
import { TheiaSprottyConnector } from 'sprotty-theia';

Expand All @@ -22,9 +23,16 @@ export const TheiaGLSPConnector = Symbol('TheiaGLSPConnector');
export interface TheiaGLSPConnector extends TheiaSprottyConnector {
readonly diagramType: string;
readonly diagramManagerId: string;
readonly initializeResult: Promise<InitializeResult>;
showMessage(widgetId: string, action: ServerMessageAction): void;
}

export function isTheiaGLSPConnector(connector?: TheiaSprottyConnector): connector is TheiaGLSPConnector {
return connector !== undefined && 'diagramType' in connector && typeof connector['diagramType'] === 'string'
&& 'diagramManagerId' in connector && typeof connector['diagramManagerId'] === 'string' &&
'showMessage' in connector && typeof connector['showMessage'] === 'function';
}

@injectable()
export class TheiaGLSPConnectorRegistry extends InstanceRegistry<TheiaGLSPConnector> {
constructor(@multiInject(TheiaGLSPConnector) @optional() connectors: TheiaGLSPConnector[]) {
Expand Down
Loading