Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ivy-lmu committed Feb 6, 2025
1 parent 2fceb57 commit f0deb74
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 89 deletions.
52 changes: 13 additions & 39 deletions packages/editor/src/accessibility/di.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import {
bindAsService,
BindingContext,
configureActionHandler,
configureFocusTrackerTool,
configureElementNavigationTool,
configureMoveZoom,
configureSearchPaletteModule,
configureShortcutHelpTool,
configureToastTool,
DeselectKeyTool,
EnableKeyboardGridAction,
Expand All @@ -13,23 +15,15 @@ import {
KeyboardGrid,
KeyboardGridCellSelectedAction,
KeyboardGridKeyboardEventAction,
KeyShortcutUIExtension,
LocalElementNavigator,
MovementKeyTool,
PositionNavigator,
ResizeElementAction,
ResizeKeyTool,
SearchAutocompletePalette,
SearchAutocompletePaletteTool,
SetAccessibleKeyShortcutAction,
TYPES
} from '@eclipse-glsp/client';
import { IvyAccessibleKeyShortcutTool } from './key-shortcut/accessible-key-shortcut-tool';
import { IvyGlobalKeyListenerTool } from './global-keylistener-tool';
import { IvyElementNavigatorTool } from './element-navigation/diagram-navigation-tool';
import { FocusDomActionHandler } from '../ui-tools/focus-dom-handler';
import { IvyResizeElementHandler } from './resize-key-tool/resize-key-handler';
import { IvyZoomKeyTool } from './zoom-key-tool';
import { IvyZoomKeyTool } from './view-key-tool/zoom-key-tool';
import { FocusDomActionHandler } from './focus-dom-handler';
import { IvyMovementKeyTool } from './view-key-tool/movement-key-tool';

export const ivyAccessibilityModule = new FeatureModule(
(bind, unbind, isBound, rebind) => {
Expand All @@ -42,17 +36,21 @@ export const ivyAccessibilityModule = new FeatureModule(
configureKeyboardControlTools(context);
configureElementNavigationTool(context);
configureToastTool(context);
configureFocusTrackerTool(context);

configureActionHandler(context, FocusDomAction.KIND, FocusDomActionHandler);
},
{
featureId: accessibilityModule.featureId
}
);

function configureResizeTools(context: BindingContext): void {
context.bind(IvyResizeElementHandler).toSelf().inSingletonScope();
configureActionHandler(context, ResizeElementAction.KIND, IvyResizeElementHandler);
bindAsService(context, TYPES.IDefaultTool, ResizeKeyTool);
}

export function configureViewKeyTools(context: BindingContext): void {
bindAsService(context, TYPES.IDefaultTool, MovementKeyTool);
bindAsService(context, TYPES.IDefaultTool, IvyMovementKeyTool);
bindAsService(context, TYPES.IDefaultTool, IvyZoomKeyTool);
configureActionHandler(context, KeyboardGridCellSelectedAction.KIND, IvyZoomKeyTool);
configureActionHandler(context, KeyboardGridKeyboardEventAction.KIND, IvyZoomKeyTool);
Expand All @@ -64,27 +62,3 @@ function configureKeyboardControlTools(context: BindingContext): void {
bindAsService(context, TYPES.IUIExtension, KeyboardGrid);
configureActionHandler(context, EnableKeyboardGridAction.KIND, KeyboardGrid);
}

function configureElementNavigationTool(context: BindingContext): void {
bindAsService(context, TYPES.IDefaultTool, IvyElementNavigatorTool);
bindAsService(context, TYPES.IElementNavigator, PositionNavigator);
bindAsService(context, TYPES.ILocalElementNavigator, LocalElementNavigator);
}

function configureSearchPaletteModule(context: BindingContext): void {
//tbd improve palette
bindAsService(context, TYPES.IUIExtension, SearchAutocompletePalette);
bindAsService(context, TYPES.IDefaultTool, SearchAutocompletePaletteTool);
}

function configureResizeTools(context: BindingContext): void {
context.bind(IvyResizeElementHandler).toSelf().inSingletonScope();
configureActionHandler(context, ResizeElementAction.KIND, IvyResizeElementHandler);
bindAsService(context, TYPES.IDefaultTool, ResizeKeyTool);
}

function configureShortcutHelpTool(context: BindingContext): void {
bindAsService(context, TYPES.IDefaultTool, IvyAccessibleKeyShortcutTool);
bindAsService(context, TYPES.IUIExtension, KeyShortcutUIExtension);
configureActionHandler(context, SetAccessibleKeyShortcutAction.KIND, KeyShortcutUIExtension);
}

This file was deleted.

This file was deleted.

141 changes: 141 additions & 0 deletions packages/editor/src/accessibility/view-key-tool/movement-key-tool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import {
Action,
BoundsAware,
boundsFeature,
ChangeBoundsOperation,
ElementAndBounds,
findParentByFeature,
GChildElement,
getElements,
GModelElement,
Grid,
IMovementRestrictor,
isBoundsAware,
isViewport,
matchesKeystroke,
MoveKeyListener,
MovementKeyTool,
Point,
SetUIExtensionVisibilityAction,
SetViewportAction,
toElementAndBounds,
TYPES,
Viewport
} from '@eclipse-glsp/client';
import { inject, injectable, optional } from 'inversify';
import { QuickActionUI } from '../../ui-tools/quick-action/quick-action-ui';

@injectable()
export class IvyMovementKeyTool extends MovementKeyTool {
@inject(TYPES.IMovementRestrictor) @optional() readonly movementRestrictor: IMovementRestrictor;

enable(): void {
if (!this.movementKeyListener) {
this.movementKeyListener = new IvyMoveKeyListener(this, this.grid);
}
this.keytool.register(this.movementKeyListener);
this.movementKeyListener.registerShortcutKey();
}
}

@injectable()
class IvyMoveKeyListener extends MoveKeyListener {
constructor(
protected readonly tool: IvyMovementKeyTool,
protected grid: Grid = { x: MoveKeyListener.defaultMoveX, y: MoveKeyListener.defaultMoveY }
) {
super(tool, grid);
}

keyDown(element: GModelElement, event: KeyboardEvent): Action[] {
const delta = this.moveDelta(event);
if (delta === undefined) {
return [];
}
if (this.tool.selectionService.hasSelectedElements()) {
return this.moveElements(delta);
}
return this.moveGraph(element, delta);
}

protected moveDelta(event: KeyboardEvent) {
if (matchesKeystroke(event, 'ArrowUp')) {
return { x: 0, y: -this.grid.y };
}
if (matchesKeystroke(event, 'ArrowDown')) {
return { x: 0, y: this.grid.y };
}
if (matchesKeystroke(event, 'ArrowLeft')) {
return { x: -this.grid.x, y: 0 };
}
if (matchesKeystroke(event, 'ArrowRight')) {
return { x: this.grid.x, y: 0 };
}
return undefined;
}

protected moveGraph(element: GModelElement, delta: Point) {
const model = findParentByFeature(element, isViewport);
if (model === undefined) {
return [];
}
const newViewport: Viewport = {
scroll: {
x: model.scroll.x + delta.x,
y: model.scroll.y + delta.y
},
zoom: model.zoom
};
return [SetViewportAction.create(model.id, newViewport, { animate: false })];
}

protected moveElements(delta: Point): Action[] {
let selectedElements = getElements(
this.tool.selectionService.getModelRoot().index,
Array.from(this.tool.selectionService.getSelectedElementIDs()),
isBoundsAware
);
selectedElements = selectedElements.filter(e => !this.isChildOfSelected(selectedElements, e)).filter(e => e.hasFeature(boundsFeature));
if (selectedElements.length === 0) {
return [];
}

const newBounds = selectedElements.filter(e => this.isMovementAllowed(e, delta)).map(e => this.getElementAndUpdatedBound(e, delta));
if (newBounds.length !== selectedElements.length) {
return [];
}
return [
ChangeBoundsOperation.create(newBounds),
SetUIExtensionVisibilityAction.create({
extensionId: QuickActionUI.ID,
visible: true,
contextElementsId: [...selectedElements.map(e => e.id)]
})
];
}

protected isChildOfSelected(selectedElements: GModelElement[], element: GModelElement): boolean {
return element instanceof GChildElement && selectedElements.includes(element.parent);
}

protected isMovementAllowed(element: GModelElement & BoundsAware, delta: Point): boolean {
if (this.tool.movementRestrictor) {
const newPosition = this.updatePosition(element, delta);
return this.tool.movementRestrictor.validate(element, newPosition);
}
return true;
}

protected getElementAndUpdatedBound(element: GModelElement & BoundsAware, delta: Point): ElementAndBounds {
const bound = toElementAndBounds(element);
bound.newPosition = this.updatePosition(element, delta);
return bound;
}

protected updatePosition(element: GModelElement & BoundsAware, delta: Point): Point {
return {
x: element.bounds.x + delta.x,
y: element.bounds.y + delta.y
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
ZoomViewportAction
} from '@eclipse-glsp/client';
import { injectable } from 'inversify';
import { QuickActionUI } from '../ui-tools/quick-action/quick-action-ui';
import { QuickActionUI } from '../../ui-tools/quick-action/quick-action-ui';

@injectable()
export class IvyZoomKeyTool extends ZoomKeyTool {
Expand Down

0 comments on commit f0deb74

Please sign in to comment.