Skip to content

Commit

Permalink
GLSP-1388 Enhance extensibility of ContainerManager
Browse files Browse the repository at this point in the history
- Added IContainerManager interface for easier customization
- Consume IContainerManager for dependency injection
- Extract isCreationAllowed submethod for element insertion checks

Resolves eclipse-glsp/glsp#1388
  • Loading branch information
ndoschek committed Aug 20, 2024
1 parent da237f0 commit cc8624b
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,36 @@ export interface TrackedInsert {
options: InsertOptions;
}

export interface IContainerManager {
insert(proxy: GModelElement, location: Point, elementTypeId: string, opts?: Partial<InsertOptions>): TrackedInsert;
findContainer(location: Point, ctx: GModelElement, evt?: MouseEvent): ContainerElement | undefined;
addInsertFeedback(feedback: FeedbackEmitter, trackedInsert: TrackedInsert, ctx?: GModelElement, event?: MouseEvent): FeedbackEmitter;
}

/**
* The default {@link IContainerManager} implementation.
* This class class manages the insertion of elements into containers by validating their positions and types,
* providing feedback on the insertion process, and determining the appropriate container based on the location and context.
*/
@injectable()
export class ContainerManager {
export class ContainerManager implements IContainerManager {
@inject(ChangeBoundsManager) protected readonly changeBoundsManager: ChangeBoundsManager;

insert(proxy: GModelElement, location: Point, elementTypeId: string, opts?: Partial<InsertOptions>): TrackedInsert {
const options = { ...DEFAULT_INSERT_OPTIONS, ...opts };
const container = this.findContainer(location, proxy, opts?.evt);
let valid = !container || container.isContainableElement(elementTypeId);
let valid = this.isCreationAllowed(container, elementTypeId, opts);
if (valid && (!container || options.validateLocationInContainer)) {
// we need to check whether the location is valid either because we do not have a container or the option is set
valid = opts?.validLocationOverwrite ?? this.changeBoundsManager.hasValidPosition(proxy, location);
}
return { elementTypeId, container, location, valid, options };
}

protected isCreationAllowed(container: ContainerElement | undefined, elementTypeId: string, opts?: Partial<InsertOptions>): boolean {
return !container || container.isContainableElement(elementTypeId);
}

findContainer(location: Point, ctx: GModelElement, evt?: MouseEvent): ContainerElement | undefined {
// reverse order of children to find the innermost, top-rendered containers first
return findChildrenAtPosition(ctx.root, location)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { InsertIndicatorView } from './node-creation-views';
export const nodeCreationToolModule = new FeatureModule(
(bind, unbind, isBound, rebind) => {
const context = { bind, unbind, isBound, rebind };
bind(ContainerManager).toSelf().inSingletonScope();
bind(TYPES.IContainerManager).to(ContainerManager).inSingletonScope();
bindAsService(context, TYPES.ITool, NodeCreationTool);
configureActionHandler(context, TriggerNodeCreationAction.KIND, NodeCreationTool);
configureModelElement(context, InsertIndicator.TYPE, InsertIndicator, InsertIndicatorView);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { RemoveTemplateElementsAction } from '../../element-template/remove-temp
import { BaseCreationTool } from '../base-tools';
import { ChangeBoundsManager } from '../change-bounds/change-bounds-manager';
import { TrackedMove } from '../change-bounds/change-bounds-tracker';
import { ContainerManager, TrackedInsert } from './container-manager';
import { IContainerManager, TrackedInsert } from './container-manager';
import { InsertIndicator } from './insert-indicator';

@injectable()
Expand All @@ -55,7 +55,7 @@ export class NodeCreationTool extends BaseCreationTool<TriggerNodeCreationAction
protected isTriggerAction = TriggerNodeCreationAction.is;

@inject(ChangeBoundsManager) readonly changeBoundsManager: ChangeBoundsManager;
@inject(ContainerManager) readonly containerManager: ContainerManager;
@inject(TYPES.IContainerManager) readonly containerManager: IContainerManager;
@inject(TYPES.IModelFactory) modelFactory: IModelFactory;

get id(): string {
Expand Down Expand Up @@ -95,7 +95,7 @@ export class NodeCreationTool extends BaseCreationTool<TriggerNodeCreationAction
}

export interface ContainerPositioningTool extends PositioningTool {
readonly containerManager: ContainerManager;
readonly containerManager: IContainerManager;
}

export class NodeInsertTrackingListener extends MouseTrackingElementPositionListener {
Expand Down
1 change: 1 addition & 0 deletions packages/glsp-sprotty/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ export const TYPES = {
IDiagramOptions: Symbol('IDiagramOptions'),
IDiagramStartup: Symbol('IDiagramStartup'),
IToolManager: Symbol('IToolManager'),
IContainerManager: Symbol('IContainerManager'),
Grid: Symbol('Grid')
};

0 comments on commit cc8624b

Please sign in to comment.