devexpress-diagram
Version:
DevExpress Diagram Control
127 lines (118 loc) • 4.67 kB
text/typescript
import { DiagramModel } from "../Model/Model";
import { EventDispatcher } from "../Utils";
import { Rectangle } from "@devexpress/utils/lib/geometry/rectangle";
import { InputPosition } from "./InputPosition";
import { ItemKey, DiagramItem } from "../Model/DiagramItem";
import { Shape } from "../Model/Shapes/Shape";
import { Connector } from "../Model/Connectors/Connector";
import { Data } from "../Utils/Data";
export class Selection {
model: DiagramModel;
inputPosition: InputPosition;
onChanged: EventDispatcher<ISelectionChangesListener> = new EventDispatcher();
private keys: ItemKey[];
constructor(model: DiagramModel) {
this.inputPosition = new InputPosition(this);
this.onChanged.add(this.inputPosition);
this.initialize(model);
}
initialize(model: DiagramModel) {
this.model = model;
this.keys = [];
this.inputPosition.initialize();
}
add(key: ItemKey) {
if(this.keys.indexOf(key) < 0) {
this.keys.push(key);
this.raiseSelectionChanged();
}
}
remove(key: ItemKey) {
if(this.keys.indexOf(key) >= 0) {
this.keys.splice(this.keys.indexOf(key), 1);
this.raiseSelectionChanged();
}
}
clear() {
if(this.keys.length > 0) {
this.keys = [];
this.raiseSelectionChanged();
}
}
set(keys: ItemKey[], forceChange?: boolean) {
if(forceChange || !Data.ArrayEqual(keys, this.keys)) {
this.keys = keys;
this.raiseSelectionChanged();
}
}
getKeys(): ItemKey[] {
return this.keys;
}
getKey(index: number) {
return this.keys[index];
}
private getSelectedItemsInsideContainers(items: DiagramItem[]): DiagramItem[] {
const result = items.slice();
items.forEach(item => {
if(item instanceof Shape) {
const children = this.getSelectedItemsInsideContainers(this.model.getChildren(item));
children.forEach(child => {
if(result.indexOf(child) === -1 && !this.hasKey(child.key))
result.push(child);
});
}
});
return result;
}
getSelectedItemsCore(includeLocked?: boolean) {
return this.keys.map(key => this.model.findItem(key))
.filter(item => item && (includeLocked || !item.isLocked));
}
getSelectedItems(includeLocked?: boolean, includeInsideContainers?: boolean) {
if(includeInsideContainers)
return this.getSelectedItemsInsideContainers(this.getSelectedItemsCore(includeLocked));
return this.getSelectedItemsCore(includeLocked);
}
getSelectedShapes(includeLocked?: boolean, includeInsideContainers?: boolean): Shape[] {
if(includeInsideContainers) {
const items = this.getSelectedItemsCore(includeLocked);
return this.getSelectedItemsInsideContainers(items)
.map(item => item instanceof Shape ? item : undefined)
.filter(shape => shape);
}
else
return this.keys.map(key => this.model.findShape(key))
.filter(shape => shape && (includeLocked || !shape.isLocked));
}
getSelectedConnectors(includeLocked?: boolean, includeInsideContainers?: boolean): Connector[] {
if(includeInsideContainers) {
const items = this.keys.map(key => this.model.findItem(key));
return this.getSelectedItemsInsideContainers(items)
.map(item => item instanceof Connector ? item : undefined)
.filter(connector => connector && (includeLocked || !connector.isLocked));
}
else
return this.keys.map(key => this.model.findConnector(key))
.filter(conn => conn && (includeLocked || !conn.isLocked));
}
hasKey(key: ItemKey) {
return this.keys.indexOf(key) >= 0;
}
isEmpty(includeLocked?: boolean): boolean {
return !this.getSelectedItems(includeLocked).length;
}
selectRect(rect: Rectangle) {
const keys: ItemKey[] = [];
this.model.iterateItems(item => {
if(item.intersectedByRect(rect))
keys.push(item.key);
});
this.set(keys);
}
raiseSelectionChanged() {
this.onChanged.raise("notifySelectionChanged", this);
}
}
export interface ISelectionChangesListener {
notifySelectionChanged(selection: Selection);
}