-
Hi, I have written a simple UIExtension in a separate module extending my diagram ContainerModule to display an additional property panel. The Implementation looks like this: import { inject, injectable, postConstruct } from 'inversify';
import {
AbstractUIExtension,
Action,
EnableDefaultToolsAction,
EnableToolsAction,
SetUIExtensionVisibilityAction,
SModelRoot,
SelectAction,
TYPES
} from 'sprotty';
import { codiconCSSClasses } from 'sprotty/lib/utils/codicon';
import {
GLSPActionDispatcher,
EditModeListener,
EditorContextService
} from '@eclipse-glsp/client';
@injectable()
export class EnableBPMNPropertyPanelAction implements Action {
static readonly KIND = 'enableBPMNPropertyPanel';
readonly kind = EnableBPMNPropertyPanelAction.KIND;
}
@injectable()
export class PropertyPanel extends AbstractUIExtension implements EditModeListener {
static readonly ID = 'bpmn-property-panel';
@inject(TYPES.IActionDispatcher) protected readonly actionDispatcher: GLSPActionDispatcher;
@inject(EditorContextService) protected readonly editorContext: EditorContextService;
protected bodyDiv?: HTMLElement;
modelRootId: string;
id(): string {
return PropertyPanel.ID;
}
containerClass(): string {
return PropertyPanel.ID;
}
@postConstruct()
postConstruct(): void {
this.editorContext.register(this);
}
initialize(): boolean {
return super.initialize();
}
protected initializeContents(_containerElement: HTMLElement): void {
this.createHeader();
this.createBody();
}
protected onBeforeShow(_containerElement: HTMLElement, root: Readonly<SModelRoot>): void {
this.modelRootId = root.id;
}
protected createHeader(): void {
const headerCompartment = document.createElement('div');
headerCompartment.classList.add('bpmn-property-header');
headerCompartment.append(this.createHeaderTitle());
headerCompartment.appendChild(this.createHeaderTools());
this.containerElement.appendChild(headerCompartment);
}
protected createBody(): void {
const bodyDiv = document.createElement('div');
bodyDiv.classList.add('properties-body');
this.containerElement.appendChild(bodyDiv);
this.bodyDiv = bodyDiv;
}
protected createHeaderTitle(): HTMLElement {
const header = document.createElement('div');
header.classList.add('header-icon');
header.appendChild(createIcon('layers'));
header.insertAdjacentText('beforeend', 'BPMN Properties');
return header;
}
private createHeaderTools(): HTMLElement {
const headerTools = document.createElement('div');
..........
return headerTools;
}
protected onClickResizePanel(button: HTMLElement, toolId?: string) {
return (_ev: MouseEvent) => {
............
};
}
editModeChanged(_oldValue: string, _newValue: string): void {
console.log('...bin in editModeChanged: '+_newValue);
this.actionDispatcher.dispatch(new SetUIExtensionVisibilityAction(PropertyPanel.ID, !this.editorContext.isReadonly));
}
handle(action: SelectAction): void | Action {
console.log('.....selection action :-)');
}
}
export function createIcon(codiconId: string): HTMLElement {
const icon = document.createElement('i');
icon.classList.add(...codiconCSSClasses(codiconId));
return icon;
} I register my UI Extension with a di.config: import { ContainerModule } from 'inversify';
import {
TYPES
} from 'sprotty';
import {
PropertyPanel
} from './property-panel';
export const propertyViewModule = new ContainerModule((bind, _unbind, isBound) => {
bind(PropertyPanel).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).toService(PropertyPanel);
}); So far everything works: My PropertyPanel also implements a handle(action: SelectAction): void | Action {
console.log('.....selection action :-)');
} Of course the handle method is not triggered as I have not registered the actionHandler. If I do extend my di.confg with calling import { ContainerModule } from 'inversify';
import {
TYPES,
configureActionHandler
} from 'sprotty';
import {
SelectAction
} from '@eclipse-glsp/client';
import {
PropertyPanel
} from './property-panel';
export const propertyViewModule = new ContainerModule((bind, _unbind, isBound) => {
bind(PropertyPanel).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).toService(PropertyPanel);
configureActionHandler({ bind, isBound }, SelectAction.KIND, PropertyPanel);
}); I got no compilation errors or runtime errors. Also Selection Events are transfered successfull into my UIExtension. The only problem is, that my UIExtension is no longer shown: Why is this happen? Have I to do more stuff in my Thanks for any help === |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 7 replies
-
Hi @rsoika, I have created #585 to track this issue. |
Beta Was this translation helpful? Give feedback.
-
Here is an alternative solution that worked for me: I tested this with a small example extension at it seems to work fine: @injectable()
export class MyUIExtension extends AbstractUIExtension implements EditModeListener, SelectionListener {
static readonly ID = 'test-extension';
@inject(TYPES.IActionDispatcher)
protected actionDispatcher: ActionDispatcher;
@inject(EditorContextService)
protected editorContext: EditorContextService;
@inject(SelectionService)
protected selectionService: SelectionService;
@postConstruct()
postConstruct(): void {
this.editorContext.register(this);
this.selectionService.register(this);
}
id(): string {
return MyUIExtension.ID;
}
containerClass(): string {
return 'test-extension';
}
protected initializeContents(containerElement: HTMLElement): void {
const div = document.createElement('div');
div.innerHTML = 'hello world';
containerElement.appendChild(div);
}
selectionChanged(root: Readonly<SModelRoot>, selectedElements: string[]): void {
console.log('selection change received:', root, selectedElements);
}
editModeChanged(_oldValue: string, _newValue: string): void {
this.actionDispatcher.dispatch(new SetUIExtensionVisibilityAction(MyUIExtension.ID, !this.editorContext.isReadonly));
}
} //di.config
import { TYPES } from '@eclipse-glsp/client';
import { ContainerModule } from 'inversify';
import { MyUIExtension } from './test-ui-extension';
const extensionModule = new ContainerModule((bind, unbind, isBound, rebind) => {
bind(MyUIExtension).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).toService(MyUIExtension);
});
export default extensionModule; |
Beta Was this translation helpful? Give feedback.
Here is an alternative solution that worked for me:
Since retrieving the current selection and listening to selection changes are common use cases we have created a dedicated
SelectionService
that can be used for that. You could register yourUIExtension
as aSelectionListener
in theSelectionService
to receive change notifications.Another benefit of using
SelectionListeners
over a SelectAction handler is that these listeners can also be dynamically deregistered during runtime.I tested this with a small example extension at it seems to work fine: