Skip to content

Commit

Permalink
GLSP-960 Introduce GlspDiagramOptions
Browse files Browse the repository at this point in the history
Wrap common configuration properties in a `GlspDiagramOptions` configuration object and bind it in the diagram container
Part of eclipse-glsp/glsp#960
  • Loading branch information
tortmayr committed Mar 19, 2023
1 parent 1021fd1 commit f835934
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- [node] Update minimum requirements for Node to >=16.11.0 [#210](https://github.com/eclipse-glsp/glsp-client/pull/210)
- [protocol] Renamed `UndoOperation` and `RedoOperation` to `UndoAction` and `RedoAction` to match operation specification [#216](https://github.com/eclipse-glsp/glsp-client/pull/216)
- [protocol] Remove dependency to `vscode-ws-jsonrpc`. The protocol package now directly offers functions to create a websocket rpc connections [#215](https://github.com/eclipse-glsp/glsp-client/pull/215)
- [DI] Introduced a `GlSPDiagramOptions` which now have to be configured for each GLSP diagram container. The `configureDiagramContainer` helper function can be used for that. [#238](https://github.com/eclipse-glsp/glsp-client/pull/238)

## [v1.0.0 - 30/06/2022](https://github.com/eclipse-glsp/glsp-client/releases/tag/v1.0.0)

Expand Down
17 changes: 9 additions & 8 deletions examples/workflow-glsp/src/di.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
GridSnapper,
initializeDiagramContainer,
LogLevel,
overrideViewerOptions,
RectangularNodeView,
RevealNamedElementActionProvider,
RoundedCornerNodeView,
Expand All @@ -38,6 +37,7 @@ import {
StructureCompartmentView,
TYPES
} from '@eclipse-glsp/client';
import { configureDiagramContainer, PartialGLSPDiagramOptions } from '@eclipse-glsp/client/lib/base/diagram-options';
import { bindOrRebind, ContainerConfiguration, DefaultTypes } from '@eclipse-glsp/protocol';
import 'balloon-css/balloon.min.css';
import { Container, ContainerModule } from 'inversify';
Expand Down Expand Up @@ -75,19 +75,20 @@ export const workflowDiagramModule = new ContainerModule((bind, unbind, isBound,
configureModelElement(context, 'struct', SCompartment, StructureCompartmentView);
});

export function createWorkflowDiagramContainer(widgetId: string, ...containerConfiguration: ContainerConfiguration): Container {
return initializeWorkflowDiagramContainer(new Container(), widgetId, ...containerConfiguration);
export function createWorkflowDiagramContainer(
options: PartialGLSPDiagramOptions,
...containerConfiguration: ContainerConfiguration
): Container {
return initializeWorkflowDiagramContainer(new Container(), options, ...containerConfiguration);
}

export function initializeWorkflowDiagramContainer(
container: Container,
widgetId: string,
options: PartialGLSPDiagramOptions,
...containerConfiguration: ContainerConfiguration
): Container {
initializeDiagramContainer(container, workflowDiagramModule, directTaskEditor, ...containerConfiguration);
overrideViewerOptions(container, {
baseDiv: widgetId,
hiddenDiv: widgetId + '_hidden'
});
configureDiagramContainer(container, options);

return container;
}
2 changes: 1 addition & 1 deletion examples/workflow-standalone/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const currentDir = loc.substring(0, loc.lastIndexOf('/'));
const examplePath = resolve(join(currentDir, '../app/example1.wf'));
const clientId = ApplicationIdProvider.get() + '_' + examplePath;

const container = createContainer();
const container = createContainer(diagramType, clientId);
const diagramServer = container.get<GLSPDiagramServer>(TYPES.ModelSource);
diagramServer.clientId = clientId;

Expand Down
6 changes: 3 additions & 3 deletions examples/workflow-standalone/src/di.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019-2022 EclipseSource and others.
* Copyright (c) 2019-2023 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 @@ -18,8 +18,8 @@ import { bindAsService, bindOrRebind, ConsoleLogger, GLSPDiagramServer, LogLevel
import { Container } from 'inversify';
import '../css/diagram.css';

export default function createContainer(): Container {
const container = createWorkflowDiagramContainer('sprotty');
export default function createContainer(diagramType: string, clientId: string): Container {
const container = createWorkflowDiagramContainer({ diagramType, clientId });
bindAsService(container, TYPES.ModelSource, GLSPDiagramServer);
bindOrRebind(container, TYPES.ModelSource).toService(GLSPDiagramServer);
bindOrRebind(container, TYPES.ILogger).to(ConsoleLogger).inSingletonScope();
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/base/di.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { FeedbackAwareUpdateModelCommand, SetModelActionHandler } from './model/
import { SelectionClearingMouseListener } from './selection-clearing-mouse-listener';
import { GLSPToolManager } from './tool-manager/glsp-tool-manager';
import { TYPES } from './types';
import { GLSPViewRegistry } from './view/view-registry';
import { GLSPViewRegistry } from './views/view-registry';

const defaultGLSPModule = new ContainerModule((bind, _unbind, isBound, rebind) => {
const context = { bind, _unbind, isBound, rebind };
Expand Down
73 changes: 73 additions & 0 deletions packages/client/src/base/diagram-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/********************************************************************************
* Copyright (c) 2023 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 { BindingContext, bindOrRebind } from '@eclipse-glsp/protocol';
import { configureViewerOptions } from 'sprotty';
import { TYPES } from './types';

/**
* Provides core configuration options for a GLSP diagram
*/
export interface GLSPDiagramOptions {
/**
* The diagram type (i.e. language identifier) of the diagram
*/
diagramType: string;
/**
* The base id of the diagram (i.e. the id of the base div it is rendered in)
*/
widgetId: string;
/**
* The client id of this diagram. Used to initialize a new GLSP server session for the diagram.
* If not defined the {@link widgetId} will serve as client id.
*/
clientId: string;
/**
* Uri of the source model file for this diagram. Can be `undefined` for cases where
* the source model is not loaded from a file input.
*/
sourceUri?: string;
}

export const defaultWidgetId = 'sprotty';

/**
* Utility {@link GLSPDiagramOptions} which is used in the {@link configureDiagramContainer} utility function
* to partially set diagram options. The only required property is the `diagramType`, for every other property
* fallback values will be used if they are `undefined`.
*/
export type PartialGLSPDiagramOptions = Partial<GLSPDiagramOptions> & { diagramType: string };

/**
* Utility function to (partially) configure the {@link GLSPDiagramOptions} for a given diagram container.
* The currently configured {@link ViewerOptions} will be overridden so that {@link ViewerOptions.baseDiv}
* matches the given {@link GLSPDiagramOptions.widgetId}.
* If a required property is undefined in the given (partial) options fallback values will be used.
* Fallback:
* - widgetId: "sprotty"
* - clientId: value of widgetId
* */
export function configureDiagramContainer(context: Omit<BindingContext, 'unbind'>, options: PartialGLSPDiagramOptions): void {
const widgetId = options.widgetId ?? defaultWidgetId;
const clientId = options.clientId ?? widgetId;
const resolvedOptions: GLSPDiagramOptions = {
widgetId,
clientId,
...options
};
bindOrRebind(context, TYPES.GLSPDiagramOptions).toConstantValue(resolvedOptions);
configureViewerOptions(context, { baseDiv: resolvedOptions.widgetId, hiddenDiv: `${resolvedOptions.widgetId}_hidden` });
}
24 changes: 14 additions & 10 deletions packages/client/src/base/editor-context-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
********************************************************************************/
import { Action, Args, distinctAdd, EditMode, EditorContext, remove, SetEditModeAction } from '@eclipse-glsp/protocol';
import { inject, injectable, multiInject, optional } from 'inversify';
import { IActionHandler, ModelSource, MousePositionTracker, SModelElement, SModelRoot } from 'sprotty';
import { IActionHandler, MousePositionTracker, SModelElement, SModelRoot } from 'sprotty';
import { SelectionService } from '../features/select/selection-service';
import { isSourceUriAware } from './source-uri-aware';
import { GLSPDiagramOptions } from './diagram-options';
import { TYPES } from './types';

export interface EditModeListener {
Expand Down Expand Up @@ -48,8 +48,8 @@ export class EditorContextService implements IActionHandler {
@optional()
protected editModeListeners: EditModeListener[] = [];

@inject(TYPES.ModelSourceProvider)
protected modelSourceProvider: () => Promise<ModelSource>;
@inject(TYPES.GLSPDiagramOptions)
protected diagramOptions: GLSPDiagramOptions;

protected _editMode: string;

Expand Down Expand Up @@ -89,12 +89,16 @@ export class EditorContextService implements IActionHandler {
this.editModeListeners.forEach(listener => listener.editModeChanged(oldValue, this.editMode));
}

async getSourceUri(): Promise<string | undefined> {
const modelSource = await this.modelSourceProvider();
if (isSourceUriAware(modelSource)) {
return modelSource.sourceURI;
}
return undefined;
/**
*
* @deprecated Use `EditorContextService.sourceUri` instead.
*/
getSourceUri(): Promise<string | undefined> {
return Promise.resolve(this.sourceUri);
}

get sourceUri(): string | undefined {
return this.diagramOptions.sourceUri;
}

get editMode(): string {
Expand Down
9 changes: 8 additions & 1 deletion packages/client/src/base/source-uri-aware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2020-2022 EclipseSource and others.
* Copyright (c) 2020-2023 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 @@ -14,10 +14,17 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { AnyObject, hasStringProp } from '@eclipse-glsp/protocol';
/**
* @deprecated No longer in use. Might be removed in future versions
*/
export interface SourceUriAware {
sourceURI: string;
}

/**
* @deprecated No longer in use. Might be removed in future versions
*/
// eslint-disable-next-line deprecation/deprecation
export function isSourceUriAware(obj: any): obj is SourceUriAware {
return AnyObject.is(obj) && hasStringProp(obj, 'sourceURI');
}
5 changes: 3 additions & 2 deletions packages/client/src/base/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2019-2022 EclipseSource and others.
* Copyright (c) 2019-2023 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 Down Expand Up @@ -35,7 +35,8 @@ export const TYPES = {
ITool: Symbol('ITool'),
IDefaultTool: Symbol('IDefaultTool'),
IEditModeListener: Symbol('IEditModeListener'),
IMarqueeBehavior: Symbol('IMarqueeBehavior')
IMarqueeBehavior: Symbol('IMarqueeBehavior'),
GLSPDiagramOptions: Symbol('GLSPDiagramOptions')
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2021-2022 EclipseSource and others.
* Copyright (c) 2021-2023 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 Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import { NavigationTarget, ResolveNavigationTargetAction, ResponseAction, SetResolvedNavigationTargetAction } from '@eclipse-glsp/protocol';
import { inject, injectable } from 'inversify';
import { IActionDispatcher, ILogger } from 'sprotty';
import { EditorContextServiceProvider } from '../../base/editor-context-service';
import { GLSPDiagramOptions } from '../../base/diagram-options';
import { TYPES } from '../../base/types';

/**
Expand All @@ -27,14 +27,17 @@ import { TYPES } from '../../base/types';
*/
@injectable()
export class NavigationTargetResolver {
@inject(TYPES.IEditorContextServiceProvider) protected editorContextService: EditorContextServiceProvider;
@inject(TYPES.IActionDispatcher) protected dispatcher: IActionDispatcher;
@inject(TYPES.ILogger) protected readonly logger: ILogger;
@inject(TYPES.IActionDispatcher)
protected dispatcher: IActionDispatcher;

@inject(TYPES.ILogger)
protected readonly logger: ILogger;

@inject(TYPES.GLSPDiagramOptions)
protected readonly diagramOptions: GLSPDiagramOptions;

async resolve(navigationTarget: NavigationTarget): Promise<SetResolvedNavigationTargetAction | undefined> {
const contextService = await this.editorContextService();
const sourceUri = await contextService.getSourceUri();
return this.resolveWithSourceUri(sourceUri, navigationTarget);
return this.resolveWithSourceUri(this.diagramOptions.sourceUri, navigationTarget);
}

async resolveWithSourceUri(
Expand Down
13 changes: 6 additions & 7 deletions packages/client/src/features/validation/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, DeleteMarkersAction, hasArrayProp, Marker, SetMarkersAction } from '@eclipse-glsp/protocol';
import { Action, DeleteMarkersAction, hasArrayProp, Marker, MaybePromise, SetMarkersAction } from '@eclipse-glsp/protocol';
import { inject, injectable, optional } from 'inversify';
import { CommandExecutionContext, CommandReturn, IActionDispatcher, IActionHandler, ICommand, SIssueMarker, SParentElement } from 'sprotty';
import { EditorContextService } from '../../base/editor-context-service';
import { GLSPDiagramOptions } from '../../base/diagram-options';
import { TYPES } from '../../base/types';
import { removeCssClasses } from '../../utils/smodel-util';
import { IFeedbackActionDispatcher, IFeedbackEmitter } from '../tool-feedback/feedback-action-dispatcher';
Expand Down Expand Up @@ -92,17 +92,16 @@ export class SetMarkersActionHandler implements IActionHandler {
@optional()
protected externalMarkerManager?: ExternalMarkerManager;

@inject(EditorContextService)
protected editorContextService: EditorContextService;
@inject(TYPES.GLSPDiagramOptions)
protected diagramOptions: GLSPDiagramOptions;

handle(action: SetMarkersAction): void | Action | ICommand {
const markers: Marker[] = action.markers;
this.setMarkers(markers);
}

async setMarkers(markers: Marker[]): Promise<void> {
const uri = await this.editorContextService.getSourceUri();
this.externalMarkerManager?.setMarkers(markers, uri);
setMarkers(markers: Marker[]): MaybePromise<void> {
this.externalMarkerManager?.setMarkers(markers, this.diagramOptions.sourceUri);
const applyMarkersAction = ApplyMarkersAction.create(markers);
this.validationFeedbackEmitter.registerValidationFeedbackAction(applyMarkersAction);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export * from './base/source-uri-aware';
export * from './base/tool-manager/glsp-tool-manager';
export * from './base/tool-manager/tool-actions';
export * from './base/types';
export * from './base/view/view-registry';
export * from './base/views/view-registry';
//
// ------------------ Features ------------------
export * from './features/bounds/freeform-layout';
Expand Down
3 changes: 1 addition & 2 deletions packages/client/src/model-source/glsp-diagram-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ import {
} from '@eclipse-glsp/protocol';
import { injectable } from 'inversify';
import { ActionHandlerRegistry, DiagramServerProxy, ExportSvgAction, ICommand, ServerStatusAction, SwitchEditModeCommand } from 'sprotty';
import { SourceUriAware } from '../base/source-uri-aware';

const receivedFromServerProperty = '__receivedFromServer';

@injectable()
export class GLSPDiagramServer extends DiagramServerProxy implements SourceUriAware {
export class GLSPDiagramServer extends DiagramServerProxy {
protected _sourceUri: string;
protected _glspClient?: GLSPClient;
protected ready = false;
Expand Down

0 comments on commit f835934

Please sign in to comment.