UNPKG

devexpress-diagram

Version:

DevExpress Diagram Control

253 lines (229 loc) 11.2 kB
import { MouseHandler } from "../MouseHandler"; import { DiagramDraggingEvent } from "../../Render/Toolbox/Toolbox"; import { DiagramMouseEvent, MouseEventElementType } from "../Event"; import { IShapeDescriptionManager } from "../../Model/Shapes/Descriptions/ShapeDescriptionManager"; import { Point } from "@devexpress/utils/lib/geometry/point"; import { AddShapeHistoryItem } from "../../History/Common/AddShapeHistoryItem"; import { SetSelectionHistoryItem } from "../../History/Common/SetSelectionHistoryItem"; import { MouseHandlerDraggingState } from "./MouseHandlerDraggingState"; import { History } from "../../History/History"; import { Selection } from "../../Selection/Selection"; import { DeleteShapeHistoryItem } from "../../History/Common/DeleteShapeHistoryItem"; import { ModelUtils } from "../../Model/ModelUtils"; import { DiagramModel } from "../../Model/Model"; import { MouseHandlerCancellableState } from "./MouseHandlerStateBase"; import { ItemKey } from "../../Model/DiagramItem"; import { IVisualizerManager } from "../Visualizers/VisualizersManager"; import { Shape } from "../../Model/Shapes/Shape"; import { DiagramModelOperation } from "../../ModelOperationSettings"; const NON_DOCUMENT_TIMER = 500; const LOCK_UPDATEPAGESIZE_TIMER = 300; export class MouseHandlerBeforeToolboxDraggingState extends MouseHandlerCancellableState { dragging: DiagramDraggingEvent; nonPageAreaTimer: number; savedEvt: DiagramMouseEvent; isModelEmpty: boolean; constructor(handler: MouseHandler, protected history: History, protected model: DiagramModel, protected selection: Selection, protected visualizerManager: IVisualizerManager, protected shapeDescriptionManager: IShapeDescriptionManager) { super(handler); this.isModelEmpty = model.items.length === 0; } cancelChanges() { this.tryRemoveTimer(); } onDragStart(evt: DiagramDraggingEvent) { this.dragging = evt; } onDragEnd(evt: DiagramMouseEvent) { this.cancelChanges(); this.handler.switchToDefaultState(); } onMouseMove(evt: DiagramMouseEvent) { if(evt.source.type > MouseEventElementType.Background) { this.tryRemoveTimer(); this.switchToDraggingState(evt, false); } else if(evt.source.type === MouseEventElementType.Background && !this.isModelEmpty) { this.savedEvt = evt; if(this.nonPageAreaTimer === undefined) this.nonPageAreaTimer = setTimeout(() => this.switchToDraggingState(this.savedEvt, true), NON_DOCUMENT_TIMER); } else if(this.nonPageAreaTimer !== undefined) this.tryRemoveTimer(); } switchToDraggingState(evt: DiagramMouseEvent, skipLockUpdatePageSize: boolean) { this.handler.switchState( new MouseHandlerToolboxDraggingState(this.handler, this.history, this.model, this.selection, this.visualizerManager, this.shapeDescriptionManager, skipLockUpdatePageSize) ); this.handler.state.onDragStart(this.dragging); this.handler.state.onMouseMove(evt); } tryRemoveTimer() { if(this.nonPageAreaTimer !== undefined) { clearTimeout(this.nonPageAreaTimer); delete this.nonPageAreaTimer; } } finish() { this.tryRemoveTimer(); } } export class MouseHandlerToolboxDraggingState extends MouseHandlerDraggingState { startPoint: Point; startShapePosition: Point; dragging: DiagramDraggingEvent; shapeKey: ItemKey; deleteHistoryItem: DeleteShapeHistoryItem; updatePageSizeTimer: number; connectorsWithoutBeginItemInfo: any[]; connectorsWithoutEndItemInfo: any[]; constructor(handler: MouseHandler, history: History, protected model: DiagramModel, protected selection: Selection, protected visualizerManager: IVisualizerManager, protected shapeDescriptionManager: IShapeDescriptionManager, skipLockUpdatePageSize: boolean) { super(handler, history); if(!skipLockUpdatePageSize) this.updatePageSizeTimer = setTimeout(() => { this.processAndRemoveUpdatePageSizeTimer(); }, LOCK_UPDATEPAGESIZE_TIMER); } cancelChanges() { this.tryRemoveUpdatePageSizeTimer(); super.cancelChanges(); } tryRemoveUpdatePageSizeTimer() { if(this.updatePageSizeTimer !== undefined) { clearTimeout(this.updatePageSizeTimer); delete this.updatePageSizeTimer; } } processAndRemoveUpdatePageSizeTimer() { if(this.updatePageSizeTimer !== undefined) { this.handler.tryUpdateModelSize(); delete this.updatePageSizeTimer; } } onMouseMove(evt: DiagramMouseEvent) { super.onMouseMove(evt); const shape = this.model.findShape(this.shapeKey); if(shape) { this.visualizerManager.setExtensionLines([shape]); const container = ModelUtils.findContainerByEventKey(this.model, this.selection, evt.source.key); if(container && this.allowInsertToContainer(evt, shape, container)) this.visualizerManager.setContainerTarget(container, evt.source.type); else this.visualizerManager.resetContainerTarget(); } } getDraggingElementKeys(): ItemKey[] { return this.shapeKey === undefined ? [] : [this.shapeKey]; } onApplyChanges(evt: DiagramMouseEvent) { if(evt.source.type === MouseEventElementType.Undefined) { this.dragging.onCaptured(false); if(this.shapeKey !== undefined && !this.deleteHistoryItem) { const shape = this.model.findShape(this.shapeKey); ModelUtils.detachConnectors(this.history, shape); ModelUtils.removeFromContainer(this.history, this.model, shape); this.deleteHistoryItem = new DeleteShapeHistoryItem(this.shapeKey, true); this.history.addAndRedo(this.deleteHistoryItem); } } else { this.dragging.onCaptured(true); if(this.shapeKey === undefined) { this.startPoint = evt.modelPoint; this.shapeKey = this.insertToolboxItem(evt); const shape = this.model.findShape(this.shapeKey); if(shape) this.handler.addInteractingItem(shape, DiagramModelOperation.AddShape); } if(this.deleteHistoryItem) { this.history.undoTransactionTo(this.deleteHistoryItem); delete this.deleteHistoryItem; } const pos = this.getPosition(evt, this.startShapePosition); const shape = this.model.findShape(this.shapeKey); ModelUtils.setShapePosition(this.history, this.model, shape, pos); ModelUtils.updateMovingShapeConnections(this.history, shape, this.connectorsWithoutBeginItemInfo, this.connectorsWithoutEndItemInfo, () => { this.visualizerManager.resetConnectionTarget(); this.visualizerManager.resetConnectionPoints(); }, (shape, connectionPointIndex) => { this.visualizerManager.setConnectionTarget(shape, MouseEventElementType.Shape); this.visualizerManager.setConnectionPoints(shape, MouseEventElementType.Shape, connectionPointIndex, true); }, (connector) => this.handler.addInteractingItem(connector) ); ModelUtils.updateShapeAttachedConnectors(this.history, this.model, shape); const container = ModelUtils.findContainerByEventKey(this.model, this.selection, evt.source.key); if(shape && container && this.allowInsertToContainer(evt, shape, container)) ModelUtils.insertToContainer(this.history, this.model, shape, container); else ModelUtils.removeFromContainer(this.history, this.model, shape); if(this.updatePageSizeTimer === undefined) this.handler.tryUpdateModelSize((offsetLeft, offsetTop) => { this.connectorsWithoutBeginItemInfo.forEach(pi => { pi.point.x += offsetLeft; pi.point.y += offsetTop; }); this.connectorsWithoutEndItemInfo.forEach(pi => { pi.point.x += offsetLeft; pi.point.y += offsetTop; }); }); } } onFinishWithChanges() { if(!this.deleteHistoryItem) this.history.addAndRedo(new SetSelectionHistoryItem(this.selection, [this.shapeKey])); } onDragStart(evt: DiagramDraggingEvent) { this.dragging = evt; this.connectorsWithoutBeginItemInfo = ModelUtils.getConnectorsWithoutBeginItemInfo(this.model); this.connectorsWithoutEndItemInfo = ModelUtils.getConnectorsWithoutEndItemInfo(this.model); } onDragEnd(evt: DiagramMouseEvent) { if(this.shapeKey !== undefined && evt.source.type === MouseEventElementType.Undefined) this.cancelChanges(); this.handler.switchToDefaultState(); } finish() { this.visualizerManager.resetExtensionLines(); this.visualizerManager.resetContainerTarget(); this.visualizerManager.resetConnectionTarget(); this.visualizerManager.resetConnectionPoints(); this.processAndRemoveUpdatePageSizeTimer(); this.dragging.onFinishDragging(); super.finish(); } insertToolboxItem(evt: DiagramMouseEvent): ItemKey { const description = this.shapeDescriptionManager.get(this.dragging.data); this.startShapePosition = this.getSnappedPoint(evt, new Point(evt.modelPoint.x - description.defaultSize.width / 2, evt.modelPoint.y - description.defaultSize.height / 2) ); const historyItem = new AddShapeHistoryItem(description, this.startShapePosition); this.history.addAndRedo(historyItem); ModelUtils.updateNewShapeProperties(this.history, this.selection, historyItem.shapeKey); return historyItem.shapeKey; } private allowInsertToContainer(evt: DiagramMouseEvent, item: Shape, container: Shape): boolean { if(this.handler.canMultipleSelection(evt)) return false; return container && container.expanded && ModelUtils.canInsertToContainer(this.model, item, container); } private getPosition(evt: DiagramMouseEvent, basePoint: Point): Point { return this.getSnappedPoint(evt, new Point( basePoint.x + evt.modelPoint.x - this.startPoint.x, basePoint.y + evt.modelPoint.y - this.startPoint.y)); } }