Skip to content

Commit

Permalink
GLSP-1349 Improve container configuration
Browse files Browse the repository at this point in the history
- Add `replace` property to `ModulConfiguration` interface. When resolving feature modules of the replace property, any potential already configured module with the same id will be replaced with the defined module. If there is nothing to replace, the module will be added to the end of the resolved configuration
- Add check for non-unique feature module ids to `resolveContainerConfiguration` function.
- Add option to enable additional debug logging when loading feature modules. This is usefull during development to get insights about why the container modules are not loaded as expected
- Add dedicated `featureIds` to all default modules. If no featureId is provided the number id of the module is reused for creating the featureId. While this works perfectly fine, it makes debugging harder because feature modules are hard to indentify based on their featureid.
With this change its now easier to derive the corresponding feature module from the featureid.

Fixes eclipse-glsp/glsp#1349
  • Loading branch information
tortmayr committed Jun 6, 2024
1 parent 65b68e3 commit 696854b
Show file tree
Hide file tree
Showing 50 changed files with 670 additions and 453 deletions.
9 changes: 6 additions & 3 deletions examples/workflow-glsp/src/direct-task-editing/di.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
import { bindAsService, FeatureModule, TYPES } from '@eclipse-glsp/client';
import { TaskEditor } from './direct-task-editor';

export const directTaskEditor = new FeatureModule((bind, _unbind, _isBound) => {
bindAsService(bind, TYPES.IUIExtension, TaskEditor);
});
export const directTaskEditor = new FeatureModule(
(bind, _unbind, _isBound) => {
bindAsService(bind, TYPES.IUIExtension, TaskEditor);
},
{ featureId: Symbol('directTaskEditor') }
);
4 changes: 2 additions & 2 deletions examples/workflow-glsp/src/workflow-diagram-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ export function createWorkflowDiagramContainer(...containerConfiguration: Contai
export function initializeWorkflowDiagramContainer(container: Container, ...containerConfiguration: ContainerConfiguration): Container {
return initializeDiagramContainer(
container,
...containerConfiguration,
directTaskEditor,
helperLineModule,
gridModule,
debugModule,
workflowDiagramModule,
...containerConfiguration
workflowDiagramModule
);
}
153 changes: 80 additions & 73 deletions packages/client/src/base/default.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,76 +62,83 @@ import { GViewRegistry } from './view/view-registry';
* The default module provides all of GLSP's base functionality and services.
* It builds on top of sprotty's default module {@link `sprottyDefaultModule`}.
*/
export const defaultModule = new FeatureModule((bind, unbind, isBound, rebind, ...rest) => {
// load bindings from sprotty's default module to avoid code duplication
sprottyDefaultModule.registry(bind, unbind, isBound, rebind, ...rest);
const context = { bind, unbind, isBound, rebind };

bindLazyInjector(context);

bind(EditorContextService).toSelf().inSingletonScope();
bind(TYPES.IDiagramStartup).toService(EditorContextService);
bind(TYPES.IEditorContextServiceProvider).toProvider<EditorContextService>(ctx => async () => ctx.container.get(EditorContextService));

configureActionHandler(context, SetEditModeAction.KIND, EditorContextService);
configureActionHandler(context, SetDirtyStateAction.KIND, EditorContextService);

bind(FocusTracker).toSelf().inSingletonScope();
configureActionHandler(context, FocusStateChangedAction.KIND, FocusTracker);

// Model update initialization ------------------------------------
bind(TYPES.IFeedbackActionDispatcher).to(FeedbackActionDispatcher).inSingletonScope();
configureCommand(context, FeedbackAwareUpdateModelCommand);
rebind(SetModelCommand).to(FeedbackAwareSetModelCommand);

bind(GLSPMouseTool).toSelf().inSingletonScope();
bindOrRebind(context, MouseTool).toService(GLSPMouseTool);
bind(TYPES.IDiagramStartup).toService(GLSPMouseTool);
bind(GLSPMousePositionTracker).toSelf().inSingletonScope();
bindOrRebind(context, MousePositionTracker).toService(GLSPMousePositionTracker);
bind(GLSPKeyTool).toSelf().inSingletonScope();
bindOrRebind(context, KeyTool).toService(GLSPKeyTool);
bind(TYPES.IDiagramStartup).toService(GLSPKeyTool);

bindAsService(context, TYPES.MouseListener, SelectionClearingMouseListener);
bindOrRebind(context, TYPES.ICommandStack).to(GLSPCommandStack).inSingletonScope();
bind(GLSPActionDispatcher).toSelf().inSingletonScope();
bindOrRebind(context, TYPES.IActionDispatcher).toService(GLSPActionDispatcher);

bindOrRebind(context, ActionHandlerRegistry).to(GLSPActionHandlerRegistry).inSingletonScope();

bindAsService(context, TYPES.ModelSource, GLSPModelSource);
bind(DiagramLoader).toSelf().inSingletonScope();
bind(ModelInitializationConstraint).to(DefaultModelInitializationConstraint).inSingletonScope();

// support re-registration of model elements and views
bindOrRebind(context, TYPES.SModelRegistry).to(GModelRegistry).inSingletonScope();
bindOrRebind(context, TYPES.ViewRegistry).to(GViewRegistry).inSingletonScope();

bind(SelectionService).toSelf().inSingletonScope();
bind(TYPES.IGModelRootListener).toService(SelectionService);
bind(TYPES.IDiagramStartup).toService(SelectionService);

// Feedback Support ------------------------------------
// Generic re-usable feedback modifying css classes
configureCommand(context, ModifyCssFeedbackCommand);
// We support using sprotty's MoveCommand as client-side visual feedback
configureCommand(context, MoveCommand);

bindAsService(context, TYPES.IVNodePostprocessor, LocationPostprocessor);
bind(TYPES.HiddenVNodePostprocessor).toService(LocationPostprocessor);

// Tool manager initialization ------------------------------------
bind(TYPES.IToolManager).to(ToolManager).inSingletonScope();
bind(TYPES.IDiagramStartup).toService(TYPES.IToolManager);
bind(TYPES.IEditModeListener).toService(TYPES.IToolManager);
bind(DefaultToolsEnablingKeyListener).toSelf().inSingletonScope();
bind(TYPES.KeyListener).toService(DefaultToolsEnablingKeyListener);
bind(ToolManagerActionHandler).toSelf().inSingletonScope();
configureActionHandler(context, EnableDefaultToolsAction.KIND, ToolManagerActionHandler);
configureActionHandler(context, EnableToolsAction.KIND, ToolManagerActionHandler);

bind(GLSPUIExtensionRegistry).toSelf().inSingletonScope();
bindOrRebind(context, TYPES.UIExtensionRegistry).toService(GLSPUIExtensionRegistry);
bind(TYPES.IDiagramStartup).toService(GLSPUIExtensionRegistry);
});
export const defaultModule = new FeatureModule(
(bind, unbind, isBound, rebind, ...rest) => {
// load bindings from sprotty's default module to avoid code duplication
sprottyDefaultModule.registry(bind, unbind, isBound, rebind, ...rest);
const context = { bind, unbind, isBound, rebind };

bindLazyInjector(context);

bind(EditorContextService).toSelf().inSingletonScope();
bind(TYPES.IDiagramStartup).toService(EditorContextService);
bind(TYPES.IEditorContextServiceProvider).toProvider<EditorContextService>(
ctx => async () => ctx.container.get(EditorContextService)
);

configureActionHandler(context, SetEditModeAction.KIND, EditorContextService);
configureActionHandler(context, SetDirtyStateAction.KIND, EditorContextService);

bind(FocusTracker).toSelf().inSingletonScope();
configureActionHandler(context, FocusStateChangedAction.KIND, FocusTracker);

// Model update initialization ------------------------------------
bind(TYPES.IFeedbackActionDispatcher).to(FeedbackActionDispatcher).inSingletonScope();
configureCommand(context, FeedbackAwareUpdateModelCommand);
rebind(SetModelCommand).to(FeedbackAwareSetModelCommand);

bind(GLSPMouseTool).toSelf().inSingletonScope();
bindOrRebind(context, MouseTool).toService(GLSPMouseTool);
bind(TYPES.IDiagramStartup).toService(GLSPMouseTool);
bind(GLSPMousePositionTracker).toSelf().inSingletonScope();
bindOrRebind(context, MousePositionTracker).toService(GLSPMousePositionTracker);
bind(GLSPKeyTool).toSelf().inSingletonScope();
bindOrRebind(context, KeyTool).toService(GLSPKeyTool);
bind(TYPES.IDiagramStartup).toService(GLSPKeyTool);

bindAsService(context, TYPES.MouseListener, SelectionClearingMouseListener);
bindOrRebind(context, TYPES.ICommandStack).to(GLSPCommandStack).inSingletonScope();
bind(GLSPActionDispatcher).toSelf().inSingletonScope();
bindOrRebind(context, TYPES.IActionDispatcher).toService(GLSPActionDispatcher);

bindOrRebind(context, ActionHandlerRegistry).to(GLSPActionHandlerRegistry).inSingletonScope();

bindAsService(context, TYPES.ModelSource, GLSPModelSource);
bind(DiagramLoader).toSelf().inSingletonScope();
bind(ModelInitializationConstraint).to(DefaultModelInitializationConstraint).inSingletonScope();

// support re-registration of model elements and views
bindOrRebind(context, TYPES.SModelRegistry).to(GModelRegistry).inSingletonScope();
bindOrRebind(context, TYPES.ViewRegistry).to(GViewRegistry).inSingletonScope();

bind(SelectionService).toSelf().inSingletonScope();
bind(TYPES.IGModelRootListener).toService(SelectionService);
bind(TYPES.IDiagramStartup).toService(SelectionService);

// Feedback Support ------------------------------------
// Generic re-usable feedback modifying css classes
configureCommand(context, ModifyCssFeedbackCommand);
// We support using sprotty's MoveCommand as client-side visual feedback
configureCommand(context, MoveCommand);

bindAsService(context, TYPES.IVNodePostprocessor, LocationPostprocessor);
bind(TYPES.HiddenVNodePostprocessor).toService(LocationPostprocessor);

// Tool manager initialization ------------------------------------
bind(TYPES.IToolManager).to(ToolManager).inSingletonScope();
bind(TYPES.IDiagramStartup).toService(TYPES.IToolManager);
bind(TYPES.IEditModeListener).toService(TYPES.IToolManager);
bind(DefaultToolsEnablingKeyListener).toSelf().inSingletonScope();
bind(TYPES.KeyListener).toService(DefaultToolsEnablingKeyListener);
bind(ToolManagerActionHandler).toSelf().inSingletonScope();
configureActionHandler(context, EnableDefaultToolsAction.KIND, ToolManagerActionHandler);
configureActionHandler(context, EnableToolsAction.KIND, ToolManagerActionHandler);

bind(GLSPUIExtensionRegistry).toSelf().inSingletonScope();
bindOrRebind(context, TYPES.UIExtensionRegistry).toService(GLSPUIExtensionRegistry);
bind(TYPES.IDiagramStartup).toService(GLSPUIExtensionRegistry);
},
{
featureId: Symbol('default')
}
);
41 changes: 23 additions & 18 deletions packages/client/src/features/accessibility/accessibility-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,35 @@
********************************************************************************/

import { FeatureModule } from '@eclipse-glsp/sprotty';
import { configureElementNavigationTool } from './element-navigation/element-navigation-module';
import { configureFocusTrackerTool } from './focus-tracker/focus-tracker-module';
import { configureShortcutHelpTool } from './key-shortcut/di.config';
import { configureKeyboardControlTools } from './keyboard-pointer/keyboard-pointer-module';
import { configureKeyboardToolPaletteTool } from './keyboard-tool-palette/keyboard-tool-palette-module';
import { configureMoveZoom } from './move-zoom/move-zoom-module';
import { configureResizeTools } from './resize-key-tool/resize-key-module';
import { configureSearchPaletteModule } from './search/search-palette-module';
import { configureViewKeyTools } from './view-key-tools/view-key-tools-module';
import { configureKeyboardToolPaletteTool } from './keyboard-tool-palette/keyboard-tool-palette-module';
import { configureKeyboardControlTools } from './keyboard-pointer/keyboard-pointer-module';
import { configureElementNavigationTool } from './element-navigation/element-navigation-module';
import { configureFocusTrackerTool } from './focus-tracker/focus-tracker-module';
import { configureToastTool } from './toast/toast-module';
import { configureViewKeyTools } from './view-key-tools/view-key-tools-module';

/**
* Enables the accessibility tools for a keyboard-only-usage
*/
export const accessibilityModule = new FeatureModule((bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureResizeTools(context);
configureViewKeyTools(context);
configureMoveZoom(context);
configureSearchPaletteModule(context);
configureShortcutHelpTool(context);
configureKeyboardToolPaletteTool(context);
configureKeyboardControlTools(context);
configureElementNavigationTool(context);
configureFocusTrackerTool(context);
configureToastTool(context);
});
export const accessibilityModule = new FeatureModule(
(bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureResizeTools(context);
configureViewKeyTools(context);
configureMoveZoom(context);
configureSearchPaletteModule(context);
configureShortcutHelpTool(context);
configureKeyboardToolPaletteTool(context);
configureKeyboardControlTools(context);
configureElementNavigationTool(context);
configureFocusTrackerTool(context);
configureToastTool(context);
},
{
featureId: Symbol('accessibility')
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,35 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
BindingContext,
FeatureModule,
TYPES,
bindAsService,
configureActionHandler,
TriggerEdgeCreationAction,
TriggerNodeCreationAction,
FeatureModule,
BindingContext,
TriggerEdgeCreationAction
bindAsService,
configureActionHandler
} from '@eclipse-glsp/sprotty';
import { GlobalKeyListenerTool } from '../global-keylistener-tool';
import { KeyboardPointer } from './keyboard-pointer';
import { KeyboardGrid } from '../keyboard-grid/keyboard-grid';
import { SetKeyboardPointerRenderPositionAction } from './actions';
import { SetEdgeTargetSelectionAction } from '../edge-autocomplete/action';
import { EdgeAutocompletePalette } from '../edge-autocomplete/edge-autocomplete-palette';
import { EdgeAutocompletePaletteTool } from '../edge-autocomplete/edge-autocomplete-tool';
import { SetEdgeTargetSelectionAction } from '../edge-autocomplete/action';
import { GlobalKeyListenerTool } from '../global-keylistener-tool';
import { EnableKeyboardGridAction, KeyboardGridCellSelectedAction } from '../keyboard-grid/action';
import { KeyboardGrid } from '../keyboard-grid/keyboard-grid';
import { GridSearchPalette } from '../keyboard-grid/keyboard-grid-search-palette';
import { KeyboardNodeGrid } from '../keyboard-grid/keyboard-node-grid';
import { EnableKeyboardGridAction, KeyboardGridCellSelectedAction } from '../keyboard-grid/action';
import { SetKeyboardPointerRenderPositionAction } from './actions';
import { KeyboardPointer } from './keyboard-pointer';

/**
* Handles the pointer used via grid to position new elements.
*/
export const keyboardControlModule = new FeatureModule((bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureKeyboardControlTools(context);
});
export const keyboardControlModule = new FeatureModule(
(bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureKeyboardControlTools(context);
},
{ featureId: Symbol('keyboardControl') }
);

export function configureKeyboardControlTools(context: BindingContext): void {
bindAsService(context, TYPES.IDefaultTool, GlobalKeyListenerTool);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ import { EnableToolPaletteAction } from '../../tool-palette/tool-palette';
import { FocusDomAction } from '../actions';
import { KeyboardToolPalette } from './keyboard-tool-palette';

export const keyboardToolPaletteModule = new FeatureModule((bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureKeyboardToolPaletteTool(context);
});
export const keyboardToolPaletteModule = new FeatureModule(
(bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureKeyboardToolPaletteTool(context);
},
{ featureId: Symbol('keyboardToolPalette') }
);

export function configureKeyboardToolPaletteTool(context: BindingContext): void {
bindAsService(context, TYPES.IUIExtension, KeyboardToolPalette);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ import { ZoomElementAction, ZoomElementHandler, ZoomViewportAction, ZoomViewport
/**
* Handles move and zoom actions.
*/
export const moveZoomModule = new FeatureModule((bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureMoveZoom(context);
});
export const moveZoomModule = new FeatureModule(
(bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureMoveZoom(context);
},
{ featureId: Symbol('moveZoom') }
);

export function configureMoveZoom(context: BindingContext): void {
context.bind(MoveViewportHandler).toSelf().inSingletonScope();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ import { ResizeKeyTool } from './resize-key-tool';
/**
* Handles resize actions.
*/
export const resizeKeyModule = new FeatureModule((bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureResizeTools(context);
});
export const resizeKeyModule = new FeatureModule(
(bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
configureResizeTools(context);
},
{ featureId: Symbol('resizeKey') }
);

export function configureResizeTools(context: BindingContext): void {
context.bind(ResizeElementHandler).toSelf().inSingletonScope();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ import { bindAsService, BindingContext, FeatureModule, TYPES } from '@eclipse-gl
import { SearchAutocompletePalette } from './search-palette';
import { SearchAutocompletePaletteTool } from './search-tool';

export const searchPaletteModule = new FeatureModule((bind, _unbind, isBound, rebind) => {
const context = { bind, isBound, rebind };
configureSearchPaletteModule(context);
});
export const searchPaletteModule = new FeatureModule(
(bind, _unbind, isBound, rebind) => {
const context = { bind, isBound, rebind };
configureSearchPaletteModule(context);
},
{ featureId: Symbol('searchPalette') }
);

export function configureSearchPaletteModule(context: Pick<BindingContext, 'bind'>): void {
bindAsService(context, TYPES.IUIExtension, SearchAutocompletePalette);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,20 @@
********************************************************************************/

import { bindAsService, BindingContext, configureActionHandler, FeatureModule, TYPES } from '@eclipse-glsp/sprotty';
import { KeyboardGridCellSelectedAction, KeyboardGridKeyboardEventAction } from '../keyboard-grid/action';
import { DeselectKeyTool } from './deselect-key-tool';
import { MovementKeyTool } from './movement-key-tool';
import { ZoomKeyTool } from './zoom-key-tool';
import { KeyboardGridCellSelectedAction, KeyboardGridKeyboardEventAction } from '../keyboard-grid/action';

export const viewKeyToolsModule = new FeatureModule((bind, _unbind, isBound, rebind) => {
const context = { bind, isBound, rebind };
configureViewKeyTools(context);
});
export const viewKeyToolsModule = new FeatureModule(
(bind, _unbind, isBound, rebind) => {
const context = { bind, isBound, rebind };
configureViewKeyTools(context);
},
{
featureId: Symbol('viewKeyTools')
}
);

export function configureViewKeyTools(context: Pick<BindingContext, 'bind' | 'isBound'>): void {
bindAsService(context, TYPES.IDefaultTool, MovementKeyTool);
Expand Down
Loading

0 comments on commit 696854b

Please sign in to comment.