devexpress-gantt
Version:
DevExpress Gantt Control
201 lines (179 loc) • 9.71 kB
text/typescript
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;
}
}