devexpress-diagram
Version:
DevExpress Diagram Control
117 lines (98 loc) • 4.68 kB
text/typescript
import { Rectangle } from "@devexpress/utils/lib/geometry/rectangle";
import { Point } from "@devexpress/utils/lib/geometry/point";
import { Metrics } from "@devexpress/utils/lib/geometry/metrics";
import { Connector } from "./Connectors/Connector";
import { SvgPrimitive } from "../Render/Primitives/Primitive";
import { ObjectUtils } from "../Utils";
import { IKeyOwner } from "../Interfaces";
import { Style, TextStyle } from "./Style";
import { ConnectionPoint } from "./ConnectionPoint";
import { Shape } from "./Shapes/Shape";
import { INativeItem } from "../Api/INativeItem";
import { DiagramUnit } from "../Enums";
export enum ConnectionPointSide { Undefined = -1, North = 0, East = 1, South = 2, West = 3 }
export type ItemKey = string;
export type ItemDataKey = string | number;
export type ItemsMap = {[key: string]: boolean};
export const DEFAULT_ZINDEX = 0;
export abstract class DiagramItem implements IKeyOwner {
key: ItemKey = undefined;
dataKey: ItemDataKey = undefined;
customData: any = undefined;
attachedConnectors: Connector[] = [];
zIndex: number = DEFAULT_ZINDEX;
locked: boolean = false;
container: Shape = undefined;
style: Style = new Style();
styleText: TextStyle = new TextStyle();
abstract createPrimitives(): SvgPrimitive<SVGGraphicsElement>[];
abstract createSelectorPrimitives(): SvgPrimitive<SVGGraphicsElement>[];
assign(item: DiagramItem) {
item.key = this.key;
item.dataKey = this.dataKey;
item.customData = ObjectUtils.cloneObject(this.customData);
item.locked = this.locked;
item.attachedConnectors = this.attachedConnectors.slice();
item.style = <Style> this.style.clone();
item.styleText = <TextStyle> this.styleText.clone();
item.zIndex = this.zIndex;
item.container = this.container;
}
getConnectionPointPosition(index: number, targetPoint?: Point): Point {
return this.getConnectionPoint(index, targetPoint).toPoint();
}
protected getConnectionPoint(index: number, targetPoint?: Point): ConnectionPoint {
if(index < 0 && targetPoint)
index = this.getNearestConnectionPoint(targetPoint);
const connectionPoints = this.getConnectionPoints();
return connectionPoints[index] || connectionPoints[0];
}
protected getNearestConnectionPoint(targetPoint: Point): number {
let distance = Number.MAX_VALUE;
let result: number;
this.getConnectionPoints().forEach((pt, index) => {
const ptDistance = Metrics.euclideanDistance(pt, targetPoint);
if(ptDistance < distance) {
distance = ptDistance;
result = index;
}
});
return result;
}
getConnectionPointIndex(side: ConnectionPointSide): number {
const points = this.getConnectionPoints();
return points.reduce((prevIndex, pt, index) => {
if(side === ConnectionPointSide.North && pt.y < points[prevIndex].y)
return index;
if(side === ConnectionPointSide.South && pt.y > points[prevIndex].y)
return index;
if(side === ConnectionPointSide.West && pt.x < points[prevIndex].x)
return index;
if(side === ConnectionPointSide.East && pt.x > points[prevIndex].x)
return index;
return prevIndex;
}, 0);
}
getConnectionPointSideByIndex(index: number, targetPoint?: Point): ConnectionPointSide {
const point = this.getConnectionPoint(index, targetPoint);
return this.getConnectionPointSide(point, targetPoint);
}
getConnectionPointIndexForSide(side: ConnectionPointSide): number {
return side;
}
abstract get rectangle(): Rectangle;
get enableText() { return true; }
get allowEditText() { return true; }
get hasTemplate() { return false; }
get enableChildren() { return false; }
get isLocked() { return this.locked || (this.container && this.container.isLocked); }
get allowResizeHorizontally() { return false; }
get allowResizeVertically() { return false; }
get strokeWidth() { return this.style.strokeWidth; }
abstract getConnectionPoints(): ConnectionPoint[];
abstract getConnectionPointSide(point: ConnectionPoint, targetPoint?: Point): ConnectionPointSide;
abstract toNative(units?: DiagramUnit): INativeItem;
intersectedByRect(rect: Rectangle): boolean {
return Rectangle.areIntersected(this.rectangle, rect);
}
}