devexpress-diagram
Version:
DevExpress Diagram Control
138 lines (124 loc) • 5.56 kB
text/typescript
import { INativeActionListener } from "./INativeActionListener";
import { EventDispatcher } from "../Utils";
import { BatchUpdatableObject } from "@devexpress/utils/lib/class/batch-updatable";
import { DiagramModel } from "../Model/Model";
import { Selection, ISelectionChangesListener } from "../Selection/Selection";
import { DiagramMouseEvent, MouseEventElementType } from "../Events/Event";
import { INativeConnector, INativeItem, INativeShape } from "./INativeItem";
import { IToolboxDragListener } from "../Render/Toolbox/Toolbox";
import { DiagramItem } from "../Model/DiagramItem";
import { DataSource } from "../Data/DataSource";
import { ModelUtils } from "../Model/ModelUtils";
import { Point, Size } from "..";
import { Connector } from "../Model/Connectors/Connector";
import { Shape } from "../Model/Shapes/Shape";
export interface IApiController {
createNativeItem(item: DiagramItem): INativeItem;
createNativeShape(shape: Shape): INativeShape;
createNativeConnector(connector: Connector): INativeConnector;
convertPoint(point: Point): Point;
convertSize(size: Size): Size;
convertUnit(value: number): number;
}
export class ApiController extends BatchUpdatableObject implements ISelectionChangesListener, IToolboxDragListener, IApiController {
private events: EventDispatcher<INativeActionListener>;
model: DiagramModel;
private selection: Selection;
private dataSource: DataSource;
constructor(events: EventDispatcher<INativeActionListener>, selection: Selection, model: DiagramModel) {
super();
this.events = events;
this.model = model;
this.selection = selection;
}
notifySelectionChanged(selection: Selection): void {
if(this.isUpdateLocked())
this.registerOccurredEvent(ApiControllerAction.SelectionChanged);
else
this.raiseSelectionChanged();
}
notifyToolboxDragStart(): void {
this.events.raise("notifyToolboxItemDragStart");
}
notifyToolboxDragEnd(): void {
this.events.raise("notifyToolboxItemDragEnd");
}
notifyToolboxDraggingMouseMove(): void {
}
notifyClick(evt: DiagramMouseEvent): void {
this.tryRaiseUserAction(evt, (i) => this.events.raise("notifyItemClick", i));
}
notifyDblClick(evt: DiagramMouseEvent): void {
this.tryRaiseUserAction(evt, (i) => this.events.raise("notifyItemDblClick", i));
}
createNativeItem(item: DiagramItem): INativeItem {
return item && this.cleanupNativeItem(item.toNative(this.model.units));
}
createNativeShape(shape: Shape): INativeShape {
return <INativeShape> this.createNativeItem(shape);
}
createNativeConnector(connector: Connector): INativeConnector {
return <INativeConnector> this.createNativeItem(connector);
}
convertUnit(value: number): number {
return ModelUtils.getlUnitValue(this.model.units, value);
}
convertPoint(point: Point): Point {
return new Point(
this.convertUnit(point.x),
this.convertUnit(point.y)
);
}
convertSize(size: Size): Size {
return new Size(
this.convertUnit(size.width),
this.convertUnit(size.height)
);
}
private cleanupNativeItem(item: INativeItem) {
const ds = this.dataSource;
if(ds) {
if(ds.isAutoGeneratedKey((<INativeConnector>item).fromKey))
(<INativeConnector>item).fromKey = undefined;
if(ds.isAutoGeneratedKey(item.key))
item.key = undefined;
if(ds.isAutoGeneratedKey((<INativeConnector>item).toKey))
(<INativeConnector>item).toKey = undefined;
}
return item;
}
setDataSource(dataSource?: DataSource) {
this.dataSource = dataSource;
}
private tryRaiseUserAction(evt: DiagramMouseEvent, callEvent: (item: INativeItem) => void) {
if(this.isUserAction(evt)) {
const item = this.model.findItem(evt.source.key);
item && this.events.raise1(l => callEvent(this.createNativeItem(item)));
}
}
private isUserAction(evt: DiagramMouseEvent): boolean {
return evt.source && (
evt.source.type === MouseEventElementType.Shape ||
evt.source.type === MouseEventElementType.ShapeExpandButton ||
evt.source.type === MouseEventElementType.ShapeParameterBox ||
evt.source.type === MouseEventElementType.ShapeResizeBox ||
evt.source.type === MouseEventElementType.ShapeConnectionPoint ||
evt.source.type === MouseEventElementType.Connector ||
evt.source.type === MouseEventElementType.ConnectorPoint ||
evt.source.type === MouseEventElementType.ConnectorSide ||
evt.source.type === MouseEventElementType.ConnectorOrthogonalSide ||
evt.source.type === MouseEventElementType.ConnectorText
);
}
onUpdateUnlocked(occurredEvents: number) {
if(occurredEvents & ApiControllerAction.SelectionChanged)
this.raiseSelectionChanged();
}
private raiseSelectionChanged() {
const items = this.selection.getKeys().map(key => this.createNativeItem(this.model.findItem(key)));
this.events.raise1(l => l.notifySelectionChanged(items));
}
}
enum ApiControllerAction {
SelectionChanged = 1 << 0,
}