UNPKG

devexpress-gantt

Version:

DevExpress Gantt Control

201 lines (179 loc) 9.71 kB
import { Browser } from "@devexpress/utils/lib/browser"; import { Point } from "@devexpress/utils/lib/geometry/point"; import { Size } from "@devexpress/utils/lib/geometry/size"; import { DomUtils } from "@devexpress/utils/lib/utils/dom"; import { EvtUtils } from "@devexpress/utils/lib/utils/evt"; import { KeyUtils, ModifierKey } from "@devexpress/utils/lib/utils/key"; import { TaskAreaEventArgs } from "../TaskAreaEventArgs"; import { ITaskAreaEventsListener } from "../TaskAreaEventsListener"; import { TaskAreaDomHelper } from "./TaskAreaDomHelper"; import { TaskAreaStateEventNames } from "./TaskAreaStateEventNames"; export abstract class TaskAreaStateBase { private _listener: ITaskAreaEventsListener; private _taskArea: HTMLElement; private _cellSize: Size; protected position: Point = new Point(-1, -1); protected isCursorInArea: boolean = false; constructor(listener: ITaskAreaEventsListener, taskArea: HTMLElement, cellSize: Size) { this._listener = listener; this._taskArea = taskArea; this._cellSize = cellSize; } public start(): void { } public finish(): void { } public isTouchEvent(evt: Event): boolean { return TaskAreaDomHelper.isTouchEvent(evt); } public isPointerEvent(evt: Event): boolean { return TaskAreaDomHelper.isPointerEvent(evt); } public isMouseEvent(evt: Event): boolean { return TaskAreaDomHelper.isMouseEvent(evt); } public onMouseWheel(evt: WheelEvent): void { } public onScroll(evt: Event): void { this.raiseEvent(TaskAreaStateEventNames.TASK_AREA_SCROLL); } public onKeyDown(evt: KeyboardEvent): void { if(this.isCursorInArea) this.raiseEvent(TaskAreaStateEventNames.TASK_AREA_KEY_DOWN, evt, null, { code: this.getShortcutCode(evt) }); } public onContextMenu(evt: MouseEvent): void { const rowIndex = this.getClickedRowIndex(evt); const isDependency = TaskAreaDomHelper.isConnectorLine(evt); if(!isDependency) this.raiseTaskSelection(evt, rowIndex); evt.stopPropagation(); evt.preventDefault(); if(Browser.WebKitFamily) evt.returnValue = false; this.raiseEvent(TaskAreaStateEventNames.CONTEXTMENU_SHOW, evt, rowIndex, { type: isDependency ? "dependency" : "task" }); } public onTaskPointerEnter(evt: PointerEvent): void { this.onTaskPointerEnterBase(evt); } public onDocumentPointerMove(evt: PointerEvent): void { this.processPointerMove(evt); } public onDocumentPointerDown(evt: PointerEvent): void { this.processPointerDown(evt); } public onDocumentPointerUp(evt: PointerEvent): void { this.processPointerUp(evt); } public onTaskTouchStart(evt: TouchEvent): void { this.onTaskPointerEnterBase(evt); } public onTouchMove(evt: TouchEvent): void { this.processPointerMove(evt); } public onTouchStart(evt: TouchEvent): void { this.processPointerDown(evt); } public onTouchEnd(evt: TouchEvent): void { this.processPointerUp(evt); } public onMouseDown(evt: MouseEvent): void { this.processPointerDown(evt); } public onMouseUp(evt: MouseEvent): void { } public onMouseMove(evt: MouseEvent): void { this.processPointerMove(evt); } public onTaskHover(evt: MouseEvent | TouchEvent): void { this.onTaskPointerEnterBase(evt); } public onTaskLeave(evt: MouseEvent): void { this.raiseEvent(TaskAreaStateEventNames.TASK_LEAVE, evt, this.getClickedRowIndex(evt)); } public onClick(evt: Event): void { const rowIndex = this.getClickedRowIndex(evt); this.raiseTaskSelection(evt, rowIndex); this.raiseEvent(TaskAreaStateEventNames.TASK_AREA_CLICK, evt, rowIndex); } public onDblClick(evt: Event): void { evt.preventDefault(); this.raiseEvent(TaskAreaStateEventNames.TASK_AREA_DBLCLICK, evt, this.getClickedRowIndex(evt)); } public onTaskAreaLeave(evt: MouseEvent): void { const isMouseLeave = this.isPointerEvent(evt) ? TaskAreaDomHelper.isMousePointer(evt) : true; if(isMouseLeave) { this.isCursorInArea = false; this.raiseEvent(TaskAreaStateEventNames.TASK_EDIT_END, evt); } this.onTaskAreaLeaveInternal(evt); } protected onTaskPointerEnterBase(evt: MouseEvent | TouchEvent | PointerEvent): void { if(!this.isTouchEvent(evt) && !this.isPointerEvent(evt)) evt.preventDefault(); this.raiseEvent(TaskAreaStateEventNames.TASK_EDIT_START, evt, this.getClickedRowIndex(evt)); } protected processPointerDown(evt: MouseEvent | TouchEvent | PointerEvent): void { const isTouchEvent = this.isTouchEvent(evt); const isPointerEvent = this.isPointerEvent(evt); const isOutsideTouch = (isTouchEvent || isPointerEvent) && this.checkAndProcessTouchOutsideArea(evt); if(isOutsideTouch) return; this.position = new Point(EvtUtils.getEventX(evt), EvtUtils.getEventY(evt)); if(isTouchEvent || isPointerEvent) evt.preventDefault(); if(isTouchEvent) this.onTouchStartInternal(<TouchEvent>evt); else if(isPointerEvent) this.onDocumentPointerDownInternal(<PointerEvent>evt); else this.onMouseDownInternal(<MouseEvent>evt); } protected processPointerMove(evt: MouseEvent | TouchEvent | PointerEvent): void { const isTouchEvent = this.isTouchEvent(evt); const isPointerEvent = this.isPointerEvent(evt); this.position ??= new Point(EvtUtils.getEventX(evt), EvtUtils.getEventY(evt)); const isMove = Math.abs(this.position.x - EvtUtils.getEventX(evt)) > 2 || Math.abs(this.position.y - EvtUtils.getEventY(evt)) > 2; const isOutsideTouch = (isTouchEvent || isPointerEvent) && this.checkAndProcessTouchOutsideArea(evt); if(isOutsideTouch || !isMove) return; if(isTouchEvent || isPointerEvent) evt.preventDefault(); if(this.isTouchEvent(evt)) this.onTouchMoveInternal(evt as TouchEvent); else if(this.isPointerEvent(evt)) this.onDocumentPointerMoveInternal(evt as PointerEvent); else { this.isCursorInArea = true; this.onMouseMoveInternal(evt as MouseEvent); } } protected processPointerUp(evt: TouchEvent | PointerEvent): void { if(!this.checkAndProcessTouchOutsideArea(evt)) { evt.preventDefault(); if(this.isTouchEvent(evt)) this.onTouchEndInternal(evt as TouchEvent); else this.onDocumentPointerUpInternal(evt as PointerEvent); } } protected onMouseDownInternal(evt: MouseEvent): void { } protected onMouseMoveInternal(evt: MouseEvent): void { } protected onDocumentPointerUpInternal(evt: PointerEvent): void { } protected onDocumentPointerDownInternal(evt: PointerEvent): void { } protected onDocumentPointerMoveInternal(evt: PointerEvent): void { } protected onTouchStartInternal(evt: TouchEvent): void { } protected onTouchEndInternal(evt: TouchEvent): void { } protected onTouchMoveInternal(evt: TouchEvent): void { } protected onTaskAreaLeaveInternal(evt: MouseEvent) : void { } protected checkAndProcessTouchOutsideArea(evt: Event): boolean { const isOutside = !this.isInTaskArea(evt); if(isOutside) this.raiseEvent(TaskAreaStateEventNames.TASK_EDIT_END, evt); this.isCursorInArea = !isOutside; return isOutside; } protected raiseEvent(eventKey: string, domEvent?: Event, rowIndex?: number, data?: Record<string, any>): any { const args = new TaskAreaEventArgs(eventKey, domEvent, rowIndex, data); const handler = this._listener.getHandler(eventKey); return handler && handler(args); } protected raiseDependencySelection(evt: Event, key: string): void { this.raiseEvent(TaskAreaStateEventNames.DEPENDENCY_SELECTION, evt, null, { key: key }); } protected raiseTaskSelection(evt: Event, index: number): void { const isFocus = DomUtils.isItParent(this._taskArea, EvtUtils.getEventSource(evt)); if(isFocus && !TaskAreaDomHelper.isConnectorLine(evt)) this.raiseEvent(TaskAreaStateEventNames.TASK_SELECTION, evt, index); } protected getClickedRowIndex(evt: any): number { if(!evt) return -1; const y = EvtUtils.getEventY(evt); const taskAreaY = DomUtils.getAbsolutePositionY(this._taskArea); const relativeY = y - taskAreaY; return Math.floor(relativeY / this._cellSize.height); } protected getRelativePos(absolutePos: Point): Point { const taskAreaX = DomUtils.getAbsolutePositionX(this._taskArea); const taskAreaY = DomUtils.getAbsolutePositionY(this._taskArea); return new Point(absolutePos.x - taskAreaX, absolutePos.y - taskAreaY); } protected isInTaskArea(evt: Event): boolean { return DomUtils.isItParent(this._taskArea, EvtUtils.getEventSource(evt)); } private getShortcutCode(evt: KeyboardEvent): number { const keyCode = KeyUtils.getEventKeyCode(evt); let modifiers = 0; if(evt.altKey) modifiers |= ModifierKey.Alt; if(evt.ctrlKey) modifiers |= ModifierKey.Ctrl; if(evt.shiftKey) modifiers |= ModifierKey.Shift; if(evt.metaKey && Browser.MacOSPlatform) modifiers |= ModifierKey.Meta; return modifiers | keyCode; } }