devexpress-diagram
Version:
DevExpress Diagram Control
314 lines (282 loc) • 13.3 kB
text/typescript
import { DiagramControl } from "../Diagram";
import { MouseHandler } from "./MouseHandler";
import { DiagramMouseEvent, IMouseOperationsListener, ITextInputOperationListener, DiagramEvent, DiagramKeyboardEvent, DiagramFocusEvent, DiagramClipboardEvent, DiagramWheelEvent, DiagramContextMenuEvent } from "./Event";
import { EventDispatcher, EventUtils } from "../Utils";
import { Rectangle } from "@devexpress/utils/lib/geometry/rectangle";
import { Size } from "@devexpress/utils/lib/geometry/size";
import { Point } from "@devexpress/utils/lib/geometry/point";
import { DiagramItem, ItemKey } from "../Model/DiagramItem";
import { TextInputHandler } from "./TextInputHandler";
import { DiagramDraggingEvent, Toolbox } from "../Render/Toolbox/Toolbox";
import { ExtensionLine } from "./Visualizers/ExtensionLinesVisualizer";
import { ConnectionPointInfo } from "./Visualizers/ConnectionPointsVisualizer";
import { ContextMenuHandler } from "./ContextMenu/ContextMenuHandler";
import { ContextMenuTouchHandler } from "./ContextMenu/ContextMenuTouchHandler";
import { VisualizerManager } from "./Visualizers/VisualizersManager";
import { VisualizerTouchManager } from "./Visualizers/VisualizersTouchManager";
import { ContextToolboxHandler } from "./ContextToolboxHandler";
import { Browser } from "@devexpress/utils/lib/browser";
import { ConnectorPosition } from "../Model/Connectors/Connector";
import { ConnectionTargetInfo } from "./Visualizers/ConnectionTargetVisualizer";
import { ContainerTargetInfo } from "./Visualizers/ContainerTargetVisualizer";
import { KeyCode, ModifierKey } from "@devexpress/utils/lib/utils/key";
import { IReadOnlyChangesListener } from "../Settings";
export class EventManager implements IEventManager {
control: DiagramControl;
mouseHandler: MouseHandler;
textInputHandler: TextInputHandler;
contextMenuHandler: ContextMenuHandler;
contextToolboxHandler: ContextToolboxHandler;
visualizersManager: VisualizerManager;
onMouseOperation: EventDispatcher<IMouseOperationsListener> = new EventDispatcher();
onTextInputOperation: EventDispatcher<ITextInputOperationListener> = new EventDispatcher();
private draggingEvent: DiagramDraggingEvent;
private toolboxes: Toolbox[] = [];
get onVisualizersUpdate(): EventDispatcher<IVisualizersListener> {
return this.visualizersManager.onVisualizersUpdate;
}
constructor(control: DiagramControl) {
this.control = control;
this.visualizersManager = EventUtils.isTouchMode() ?
new VisualizerTouchManager(control.selection, control.model, this, control.settings) :
new VisualizerManager(control.selection, control.model, this, control.settings);
this.onMouseOperation.add(this.visualizersManager);
this.contextMenuHandler = Browser.TouchUI ?
new ContextMenuTouchHandler(control.selection) :
new ContextMenuHandler();
this.contextMenuHandler.onVisibilityChanged.add(control);
this.onMouseOperation.add(this.contextMenuHandler);
this.onTextInputOperation.add(this.contextMenuHandler);
this.contextToolboxHandler = new ContextToolboxHandler();
this.contextToolboxHandler.onVisibilityChanged.add(control);
this.contextToolboxHandler.onVisibilityChanged.add(this.contextMenuHandler);
this.mouseHandler = new MouseHandler(control.history, control.selection, control.model, this,
control.settings.readOnly, control.view, this.visualizersManager, this.contextToolboxHandler,
control.shapeDescriptionManager, control.settings, control.permissionsProvider);
this.textInputHandler = new TextInputHandler(control);
this.visualizersManager.onVisualizersUpdate.add(this.mouseHandler);
}
registerToolbox(toolbox: Toolbox) {
this.toolboxes.push(toolbox);
}
cleanToolboxes(eventDispatcher: EventDispatcher<IReadOnlyChangesListener>) {
this.toolboxes.forEach(toolbox => {
eventDispatcher.remove(toolbox);
});
this.toolboxes = [];
}
initialize() {
this.visualizersManager.initialize(this.control.model);
this.mouseHandler.initialize(this.control.model);
}
beginUpdate(lockUpdateCanvas?: boolean) {
this.contextMenuHandler.beginUpdate();
this.visualizersManager.beginUpdate();
}
endUpdate() {
this.contextMenuHandler.endUpdate();
this.visualizersManager.endUpdate();
}
onMouseDown(evt: DiagramMouseEvent) {
this.mouseHandler.onMouseDown(evt);
this.contextMenuHandler.onMouseDown(evt);
this.visualizersManager.onMouseDown(evt);
this.contextToolboxHandler.onMouseDown(evt);
}
onMouseMove(evt: DiagramMouseEvent) {
this.processDragging(evt);
this.mouseHandler.onMouseMove(evt);
}
onMouseUp(evt: DiagramMouseEvent) {
this.contextToolboxHandler.onMouseUp(evt);
this.mouseHandler.onMouseUp(evt);
this.contextMenuHandler.onMouseUp(evt);
this.visualizersManager.onMouseUp(evt);
this.processDragging(evt);
}
onMouseEnter(evt: DiagramEvent) {
this.visualizersManager.onMouseEnter(evt);
}
onMouseLeave(evt: DiagramEvent) {
this.visualizersManager.onMouseLeave(evt);
}
onDblClick(evt: DiagramMouseEvent) {
this.mouseHandler.onMouseDblClick(evt);
this.textInputHandler.onDblClick(evt);
this.control.apiController.notifyDblClick(evt);
}
onClick(evt: DiagramMouseEvent) {
this.mouseHandler.onMouseClick(evt);
this.control.apiController.notifyClick(evt);
}
onContextMenu(evt: DiagramContextMenuEvent) {
this.contextMenuHandler.onContextMenu(evt);
}
onLongTouch(evt: DiagramMouseEvent) {
this.mouseHandler.onLongTouch(evt);
this.contextMenuHandler.onLongTouch(evt);
}
onBlur(evt: DiagramFocusEvent) {
this.contextMenuHandler.onBlur(evt);
this.contextToolboxHandler.onBlur(evt);
this.visualizersManager.onBlur(evt);
}
onFocus(evt: DiagramEvent) {
this.contextMenuHandler.onFocus(evt);
this.contextToolboxHandler.onFocus(evt);
this.visualizersManager.onFocus(evt);
}
onKeyDown(evt: DiagramKeyboardEvent): void {
const scCode = evt.getShortcutCode();
if(this.onShortcut(scCode)) {
this.visualizersManager.updateConnectionPoints();
this.contextMenuHandler.onShortcut(evt);
this.contextToolboxHandler.onShortcut(evt);
evt.preventDefault = true;
}
else if(this.isShortcutForFocusInput(scCode))
evt.preventDefault = true;
this.contextMenuHandler.onKeyDown(evt);
this.contextToolboxHandler.onKeyDown(evt);
this.mouseHandler.onKeyDown(evt);
}
onKeyUp(evt: DiagramKeyboardEvent): void {
this.mouseHandler.onKeyUp(evt);
}
onTextInputBlur(evt: DiagramFocusEvent) {
this.textInputHandler.onBlur(evt);
this.contextMenuHandler.onTextInputBlur(evt);
}
onTextInputFocus(evt: DiagramEvent) {
this.textInputHandler.onFocus(evt);
this.contextMenuHandler.onTextInputFocus(evt);
}
onTextInputKeyDown(evt: DiagramKeyboardEvent) {
this.textInputHandler.onKeyDown(evt);
}
onShortcut(code: number) {
if(this.control.commandManager.processShortcut(code))
return true;
if(this.mouseHandler.onShortcut(code))
return true;
}
isShortcutForFocusInput(code: number) {
return code === KeyCode.Delete || code === (KeyCode.Delete | ModifierKey.Ctrl) || code === (KeyCode.Delete | ModifierKey.Meta) ||
(code === KeyCode.Backspace) || code === (KeyCode.Backspace | ModifierKey.Ctrl) || code === (KeyCode.Backspace | ModifierKey.Shift) || code === (KeyCode.Backspace | ModifierKey.Meta) ||
code === KeyCode.Home || code === KeyCode.End ||
code === KeyCode.Up || code === (KeyCode.Up | ModifierKey.Ctrl) || code === (KeyCode.Up | ModifierKey.Meta) ||
code === KeyCode.Down || code === (KeyCode.Down | ModifierKey.Ctrl) || code === (KeyCode.Down | ModifierKey.Meta) ||
code === KeyCode.Left || code === (KeyCode.Left | ModifierKey.Ctrl) || code === (KeyCode.Left | ModifierKey.Meta) ||
code === KeyCode.Right || code === (KeyCode.Right | ModifierKey.Ctrl) || code === (KeyCode.Right | ModifierKey.Meta);
}
onPaste(evt: DiagramClipboardEvent) {
if(!this.textInputHandler.isTextInputActive() && this.control.commandManager.processPaste(evt.clipboardData)) {
this.visualizersManager.updateConnectionPoints();
evt.preventDefault = true;
}
}
onMouseWheel(evt: DiagramWheelEvent) {
if(this.mouseHandler.onWheel(evt))
evt.preventDefault = true;
}
isFocused(): boolean {
return this.control.isFocused();
}
private processDragging(evt: DiagramMouseEvent) {
const draggingEvt = this.getDraggingEvent();
if(draggingEvt && this.draggingEvent !== draggingEvt) {
this.draggingEvent = draggingEvt;
this.mouseHandler.onDragStart(this.draggingEvent);
this.control.captureFocus();
}
else if(!draggingEvt && this.draggingEvent) {
delete this.draggingEvent;
this.mouseHandler.onDragEnd(evt);
}
}
private getDraggingEvent(): DiagramDraggingEvent {
return this.toolboxes
.filter(t => t.draggingObject)
.map(t => t.draggingObject.evt)[0];
}
onDocumentDragStart(itemKeys: ItemKey[]) {
this.control.beginUpdate();
this.control.captureFocus();
this.onMouseOperation.raise("notifyDragStart", itemKeys);
}
onDocumentDragEnd(itemKeys: ItemKey[]) {
this.onMouseOperation.raise("notifyDragEnd", itemKeys);
this.control.endUpdate();
this.control.barManager.updateItemsState();
}
onDocumentDragScrollStart() {
this.onMouseOperation.raise1(l => l.notifyDragScrollStart());
}
onDocumentDragScrollEnd() {
this.onMouseOperation.raise1(l => l.notifyDragScrollEnd());
}
onDocumentClick(itemKeys: ItemKey[]) {
this.control.beginUpdate();
this.control.endUpdate();
this.control.barManager.updateItemsState();
}
raiseTextInputStart(item: DiagramItem, text: string, position: Point, size?: Size): void {
this.onTextInputOperation.raise("notifyTextInputStart", item, text, position, size);
}
raiseTextInputEnd(item: DiagramItem, captureFocus?: boolean): void {
this.onTextInputOperation.raise("notifyTextInputEnd", item, captureFocus);
}
raiseTextInputPermissionsCheck(item: DiagramItem, allowed: boolean): void {
this.onTextInputOperation.raise("notifyTextInputPermissionsCheck", item, allowed);
}
canFinishTextEditing(): boolean {
return this.textInputHandler.canFinishTextEditing();
}
}
export interface IEventManager {
onMouseDown(evt: DiagramMouseEvent);
onMouseMove(evt: DiagramMouseEvent);
onMouseUp(evt: DiagramMouseEvent);
onMouseEnter(evt: DiagramEvent);
onMouseLeave(evt: DiagramEvent);
onMouseWheel(evt: DiagramWheelEvent);
onDblClick(evt: DiagramMouseEvent);
onClick(evt: DiagramMouseEvent);
onContextMenu(evt: DiagramContextMenuEvent);
onLongTouch(evt: DiagramMouseEvent);
onBlur(evt: DiagramFocusEvent);
onFocus(evt: DiagramEvent);
onKeyDown(evt: DiagramKeyboardEvent);
onKeyUp(evt: DiagramKeyboardEvent);
onTextInputKeyDown(evt: DiagramKeyboardEvent);
onTextInputBlur(evt: DiagramFocusEvent);
onTextInputFocus(evt: DiagramEvent);
onPaste(evt: DiagramClipboardEvent);
onDocumentDragStart(itemKeys: ItemKey[]);
onDocumentDragEnd(itemKeys: ItemKey[]);
onDocumentDragScrollStart();
onDocumentDragScrollEnd();
onDocumentClick(itemKeys: ItemKey[]);
isFocused(): boolean;
canFinishTextEditing(): boolean;
}
export interface IVisualizersListener {
notifySelectionRectShow(rect: Rectangle);
notifySelectionRectHide();
notifyResizeInfoShow(point: Point, text: string);
notifyResizeInfoHide();
notifyConnectionPointsShow(key: ItemKey, points: ConnectionPointInfo[], activePointIndex: number, outsideRectangle: Rectangle);
notifyConnectionPointsHide();
notifyConnectionTargetShow(key: ItemKey, info: ConnectionTargetInfo);
notifyConnectionTargetHide();
notifyContainerTargetShow(key: ItemKey, info: ContainerTargetInfo);
notifyContainerTargetHide();
notifyExtensionLinesShow(lines: ExtensionLine[]);
notifyExtensionLinesHide();
}
export interface IConnectionChangeOperationParams {
item?: DiagramItem;
oldItem?: DiagramItem;
position: ConnectorPosition;
connectionPointIndex: number;
}