UNPKG

devexpress-diagram

Version:

DevExpress Diagram Control

164 lines (152 loc) 8.45 kB
import { Point } from "@devexpress/utils/lib/geometry/point"; import { History } from "../../History/History"; import { Connector } from "../../Model/Connectors/Connector"; import { ConnectionPointSide, DiagramItem, ItemKey } from "../../Model/DiagramItem"; import { DiagramModel } from "../../Model/Model"; import { ModelUtils } from "../../Model/ModelUtils"; import { DiagramMouseEvent } from "../Event"; import { MouseHandler } from "../MouseHandler"; import { MouseHandlerDraggingState } from "./MouseHandlerDraggingState"; import { GeometryUtils } from "../../Utils"; import { ConnectorRenderPoint } from "../../Model/Connectors/ConnectorRenderPoint"; export class MouseHandlerMoveConnectorOrthogonalSideState extends MouseHandlerDraggingState { startPoint: Point; connector: Connector; canCreatePoints: boolean = true; leftRenderPointIndex: number; rightRenderPointIndex: number; isHorizontal: boolean; leftPointIndex: number; rightPointIndex: number; constructor(handler: MouseHandler, history: History, protected model: DiagramModel) { super(handler, history); } private saveSidePoints(markLeftRenderPointIndex: number, markRightRenderPointIndex: number): void { const renderPoints = this.connector.getRenderPoints(true); this.isHorizontal = renderPoints[markLeftRenderPointIndex].y === renderPoints[markRightRenderPointIndex].y; this.iterateRenderPoints(renderPoints, markLeftRenderPointIndex, false, (pt, i) => { if(pt.pointIndex !== -1) this.leftPointIndex = pt.pointIndex; this.leftRenderPointIndex = i; }, (pt) => !GeometryUtils.arePointsOfOrthogonalLine(renderPoints[markLeftRenderPointIndex], pt, this.isHorizontal)); this.iterateRenderPoints(renderPoints, this.leftRenderPointIndex, true, (pt, i) => { if(pt.pointIndex !== -1) this.rightPointIndex = pt.pointIndex; this.rightRenderPointIndex = i; }, (pt) => !GeometryUtils.arePointsOfOrthogonalLine(renderPoints[markLeftRenderPointIndex], pt, this.isHorizontal)); } private iterateRenderPoints(renderPoints: ConnectorRenderPoint[], startIndex: number, direction: boolean, callback: (renderPoint: ConnectorRenderPoint, index: number) => void, stopPredicate?: (renderPoint: ConnectorRenderPoint, index: number) => boolean) { for(let i = startIndex; direction ? i < renderPoints.length : i >= 0; direction ? i++ : i--) { const point = renderPoints[i]; if(stopPredicate && stopPredicate(point, i)) break; callback(point, i); } } onMouseDown(evt: DiagramMouseEvent): void { this.startPoint = evt.modelPoint; this.connector = this.model.findConnector(evt.source.key); this.handler.addInteractingItem(this.connector); const renderPointIndexes = evt.source.value.split("_"); this.saveSidePoints(parseInt(renderPointIndexes[0]), parseInt(renderPointIndexes[1])); super.onMouseDown(evt); } private shouldCreatePoint(isLeft: boolean): boolean { if(!this.canCreatePoints) return false; if(isLeft && (this.leftPointIndex === undefined || this.leftPointIndex === 0)) return true; if(!isLeft && (this.rightPointIndex === undefined || this.rightPointIndex === this.connector.points.length - 1)) return true; const renderPoints = this.connector.getRenderPoints(true); if(isLeft && !this.connector.points[this.leftPointIndex].equals(renderPoints[this.leftRenderPointIndex])) return true; if(!isLeft && !this.connector.points[this.rightPointIndex].equals(renderPoints[this.rightRenderPointIndex])) return true; return false; } onApplyChanges(evt: DiagramMouseEvent): void { if(this.shouldCreatePoint(true) || this.shouldCreatePoint(false)) { let renderPoints = this.connector.getRenderPoints(true); const leftRenderPoint = renderPoints[this.leftRenderPointIndex]; const rightRenderPoint = renderPoints[this.rightRenderPointIndex]; if(this.shouldCreatePoint(true)) { const leftPoint = new Point(leftRenderPoint.x, leftRenderPoint.y); if(this.leftPointIndex === 0) { this.leftPointIndex = 1; this.correctEdgePoint(leftPoint, rightRenderPoint, this.connector.beginItem, this.connector.beginConnectionPointIndex); } else if(this.leftPointIndex === undefined) this.iterateRenderPoints(renderPoints, this.leftRenderPointIndex, true, pt => { if(pt.pointIndex !== -1) this.leftPointIndex = pt.pointIndex; }, () => this.leftPointIndex !== undefined); ModelUtils.addConnectorPoint(this.history, this.connector.key, this.leftPointIndex, leftPoint); if(this.rightPointIndex !== undefined) this.rightPointIndex++; } if(this.shouldCreatePoint(false)) { renderPoints = this.connector.getRenderPoints(true); const rightPoint = new Point(rightRenderPoint.x, rightRenderPoint.y); if(this.rightPointIndex === this.connector.points.length - 1) { this.correctEdgePoint(rightPoint, leftRenderPoint, this.connector.endItem, this.connector.endConnectionPointIndex); this.rightPointIndex--; } else if(this.rightPointIndex === undefined) this.iterateRenderPoints(renderPoints, this.rightRenderPointIndex, false, pt => { if(pt.pointIndex !== -1) this.rightPointIndex = pt.pointIndex; }, () => this.rightPointIndex === this.leftPointIndex); this.rightPointIndex++; ModelUtils.addConnectorPoint(this.history, this.connector.key, this.rightPointIndex, rightPoint); } } this.canCreatePoints = false; const point = this.getSnappedPoint(evt, evt.modelPoint); ModelUtils.moveConnectorRightAnglePoints(this.history, this.connector, this.leftPointIndex, this.rightPointIndex, this.isHorizontal ? undefined : point.x, this.isHorizontal ? point.y : undefined); this.handler.tryUpdateModelSize(); } onFinishWithChanges(): void { ModelUtils.deleteConnectorUnnecessaryPoints(this.history, this.connector); ModelUtils.fixConnectorBeginEndConnectionIndex(this.history, this.connector); this.handler.tryUpdateModelSize(); } correctEdgePoint(point: Point, directionPoint: Point, item: DiagramItem, connectionPointIndex: number): void { let offset = 0; if(item) { const side = item.getConnectionPointSideByIndex(connectionPointIndex); const rect = item.rectangle; offset = Connector.minOffset; switch(side) { case ConnectionPointSide.South: offset += rect.bottom - point.y; break; case ConnectionPointSide.North: offset += point.y - rect.y; break; case ConnectionPointSide.East: offset += rect.right - point.x; break; case ConnectionPointSide.West: offset += point.x - rect.x; break; } } if(this.isHorizontal) if(point.x > directionPoint.x) point.x -= Math.min(offset, point.x - directionPoint.x); else point.x += Math.min(offset, directionPoint.x - point.x); else if(point.y > directionPoint.y) point.y -= Math.min(offset, point.y - directionPoint.y); else point.y += Math.min(offset, directionPoint.y - point.y); } getDraggingElementKeys(): ItemKey[] { return [this.connector.key]; } }