diff --git a/examples/workflow-glsp/src/di.config.ts b/examples/workflow-glsp/src/di.config.ts index 0f0458a9..dee9c398 100644 --- a/examples/workflow-glsp/src/di.config.ts +++ b/examples/workflow-glsp/src/di.config.ts @@ -17,7 +17,7 @@ import { configureDefaultModelElements, configureModelElement, ConsoleLogger, - createClientContainer, + createDiagramContainer, DeleteElementContextMenuItemProvider, DiamondNodeView, editLabelFeature, @@ -74,7 +74,7 @@ const workflowDiagramModule = new ContainerModule((bind, unbind, isBound, rebind }); export default function createContainer(widgetId: string): Container { - const container = createClientContainer(workflowDiagramModule, directTaskEditor); + const container = createDiagramContainer(workflowDiagramModule, directTaskEditor); overrideViewerOptions(container, { baseDiv: widgetId, hiddenDiv: widgetId + '_hidden' diff --git a/packages/client/src/base/container-modules.ts b/packages/client/src/base/container-modules.ts index 286d0beb..de156160 100644 --- a/packages/client/src/base/container-modules.ts +++ b/packages/client/src/base/container-modules.ts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2021 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 @@ -14,6 +14,7 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ +import { remove } from '@eclipse-glsp/protocol'; import { Container, ContainerModule } from 'inversify'; import { buttonModule, @@ -21,7 +22,6 @@ import { edgeIntersectionModule, edgeLayoutModule, expandModule, - exportModule, fadeModule, labelEditUiModule, modelSourceModule, @@ -35,6 +35,7 @@ import glspContextMenuModule from '../features/context-menu/di.config'; import { glspServerCopyPasteModule } from '../features/copy-paste/di.config'; import glspDecorationModule from '../features/decoration/di.config'; import glspEditLabelModule from '../features/edit-label/di.config'; +import glspExportModule from '../features/export/di.config'; import modelHintsModule from '../features/hints/di.config'; import glspHoverModule from '../features/hover/di.config'; import layoutModule from '../features/layout/di.config'; @@ -56,7 +57,7 @@ export const DEFAULT_MODULES = [ edgeIntersectionModule, edgeLayoutModule, expandModule, - exportModule, + glspExportModule, fadeModule, glspBoundsModule, glspCommandPaletteModule, @@ -83,7 +84,51 @@ export const DEFAULT_MODULES = [ enableDefaultToolsOnFocusLossModule, validationModule, zorderModule -]; +] as const; + +/** + * Creates a GLSP Diagram container with the GLSP default modules and the specified custom `modules`. + * Default modules can be excluded using {@link ExcludeDescription}s. + * + * This means, you can still customize the default modules in two ways. + * + * First, you can exclude default modules and add a module with your custom code. + * + * ```typescript + * const container = createDiagramContainer(myModule1, {exclude: modelSourceWatcherModule},myModelSourceWatcherModule ); + * ``` + * + * Second, you can unbind or rebind implementations that are originally bound in one of the default modules. + * + * ```typescript + * rebind(NavigationTargetResolver).to(MyNavigationTargetResolver); + * ``` + * + * @param customModules Custom modules to be loaded in addition to the default modules and/or default modules that should be excluded. + * @param options Options to customize the module loading + * @returns The created container. + */ +export function createDiagramContainer(...customModules: Array): Container { + const container = new Container(); + + const modules = [...DEFAULT_MODULES]; + customModules.forEach(customModule => { + if (customModule instanceof ContainerModule) { + modules.push(customModule); + } else { + remove(modules, customModule.exclude); + } + }); + container.load(...modules); + return container; +} + +/** + * Can be passed to the {@link createDiagramContainer} utility function to exclude (i.e. not load) a specific default module. + */ +export interface ExcludeDescription { + exclude: ContainerModule; +} /** * Creates a GLSP Client container with the GLSP default modules and the specified custom `modules`. @@ -105,9 +150,8 @@ export const DEFAULT_MODULES = [ * ``` * @param modules Custom modules to be loaded in addition to the default modules. * @returns The created container. + * @deprecated Please use `createDiagramContainer` from `@eclipse-glsp/client` instead */ export function createClientContainer(...modules: ContainerModule[]): Container { - const container = new Container(); - container.load(...DEFAULT_MODULES, ...modules); - return container; + return createDiagramContainer(...modules); } diff --git a/packages/client/src/features/export/di.config.ts b/packages/client/src/features/export/di.config.ts new file mode 100644 index 00000000..2630afbc --- /dev/null +++ b/packages/client/src/features/export/di.config.ts @@ -0,0 +1,28 @@ +/******************************************************************************** + * 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 { ContainerModule } from 'inversify'; +import { configureCommand, ExportSvgCommand, ExportSvgKeyListener, ExportSvgPostprocessor, TYPES } from 'sprotty'; +import { GLSPSvgExporter } from './glsp-svg-exporter'; + +const glspExportSvgModule = new ContainerModule((bind, _unbind, isBound) => { + bind(ExportSvgKeyListener).toSelf().inSingletonScope(); + bind(TYPES.KeyListener).toService(ExportSvgKeyListener); + bind(TYPES.HiddenVNodePostprocessor).to(ExportSvgPostprocessor).inSingletonScope(); + configureCommand({ bind, isBound }, ExportSvgCommand); + bind(TYPES.SvgExporter).to(GLSPSvgExporter).inSingletonScope(); +}); + +export default glspExportSvgModule; diff --git a/packages/client/src/features/layout/tests/layouter-test-util.ts b/packages/client/src/features/layout/tests/layouter-test-util.ts index 362821a6..577f7900 100644 --- a/packages/client/src/features/layout/tests/layouter-test-util.ts +++ b/packages/client/src/features/layout/tests/layouter-test-util.ts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2022 STMicroelectronics and others. + * Copyright (c) 2022-2023 STMicroelectronics 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 @@ -30,7 +30,7 @@ import { SParentElement, TYPES } from 'sprotty'; -import { createClientContainer } from '../../../base/container-modules'; +import { createDiagramContainer } from '../../../base/container-modules'; import { GLSPGraph } from '../../../lib/model'; import { StatefulLayouterExt } from '../layouter'; @@ -117,6 +117,6 @@ export function layout( export function setupLayoutRegistry(): LayoutRegistry { // Generic Test setup // create client container that registers all default modules including the layoutModule - const layoutContainer = createClientContainer(); + const layoutContainer = createDiagramContainer(); return layoutContainer.get(TYPES.LayoutRegistry); } diff --git a/packages/client/src/features/tools/di.config.ts b/packages/client/src/features/tools/di.config.ts index a0ba9c79..9413fda6 100644 --- a/packages/client/src/features/tools/di.config.ts +++ b/packages/client/src/features/tools/di.config.ts @@ -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 @@ -18,7 +18,6 @@ import { ContainerModule, interfaces } from 'inversify'; import { configureActionHandler, configureModelElement, ManhattanEdgeRouter } from 'sprotty'; import { FocusStateChangedAction } from '../../base/actions/focus-change-action'; import { TYPES } from '../../base/types'; -import { GLSPSvgExporter } from '../export/glsp-svg-exporter'; import { MARQUEE } from '../tool-feedback/marquee-tool-feedback'; import { ChangeBoundsTool } from './change-bounds-tool'; import { DelKeyDeleteTool, MouseDeleteTool } from './delete-tool'; @@ -53,9 +52,6 @@ export const toolsModule = new ContainerModule((bind, _unbind, isBound, rebind) configureActionHandler({ bind, isBound }, TriggerNodeCreationAction.KIND, NodeCreationTool); configureActionHandler({ bind, isBound }, TriggerEdgeCreationAction.KIND, EdgeCreationTool); - bind(GLSPSvgExporter).toSelf().inSingletonScope(); - rebind(TYPES.SvgExporter).toService(GLSPSvgExporter); - bind(GSLPManhattanEdgeRouter).toSelf().inSingletonScope(); rebind(ManhattanEdgeRouter).toService(GSLPManhattanEdgeRouter); });