devexpress-diagram
Version:
DevExpress Diagram Control
118 lines (112 loc) • 5.77 kB
text/typescript
import { ClipboardCommand } from "./ClipboardCommand";
import { SimpleCommandState } from "../CommandStates";
import { Importer } from "../../ImportAndExport/Importer";
import { Shape } from "../../Model/Shapes/Shape";
import { ImportShapeHistoryItem } from "../../History/Common/ImportShapeHistoryItem";
import { Connector } from "../../Model/Connectors/Connector";
import { ImportConnectorHistoryItem } from "../../History/Common/ImportConnectorHistoryItem";
import { ModelUtils } from "../../Model/ModelUtils";
import { SetSelectionHistoryItem } from "../../History/Common/SetSelectionHistoryItem";
import { DiagramItem } from "../../Model/DiagramItem";
import { Point } from "@devexpress/utils/lib/geometry/point";
import { UnitConverter } from "@devexpress/utils/lib/class/unit-converter";
export abstract class PasteSelectionCommandBase extends ClipboardCommand {
static readonly positionOffset = UnitConverter.pixelsToTwips(10);
isEnabled(): boolean {
return super.isEnabled() && (this.isPasteSupportedByBrowser() || ClipboardCommand.clipboardData !== undefined);
}
isVisible(): boolean {
return this.isPasteSupportedByBrowser() || ClipboardCommand.clipboardData !== undefined;
}
parseClipboardData(data: string): DiagramItem[] {
let items: DiagramItem[] = [];
const importer = new Importer(this.control.shapeDescriptionManager, data);
items = importer.importItems(this.control.model);
const offset = this.getEventPositionOffset(items, this.control.contextMenuPosition);
for(let i = 0; i < items.length; i++) {
const item = items[i];
if(item instanceof Shape)
item.position.offsetByPoint(offset);
else if(item instanceof Connector) {
item.points.forEach(p => p.offsetByPoint(offset));
item.clearRenderPoints();
}
}
return items;
}
protected abstract getEventPositionOffset(items: DiagramItem[], evtPosition?: Point): Point;
executeCore(state: SimpleCommandState, parameter?: string): boolean {
let ret = true;
if(parameter === undefined)
this.getClipboardData(data => {
ret = this.execute(data);
});
else
this.performPaste(parameter);
return ret;
}
addItemForSortingRecursive(itemsHashtable: {[key: string]: number}, item: DiagramItem): number {
if(itemsHashtable[item.key])
return itemsHashtable[item.key];
if(item instanceof Connector) {
if(item.endItem)
itemsHashtable[item.key] = this.addItemForSortingRecursive(itemsHashtable, item.endItem) - 0.5;
else if(item.beginItem)
itemsHashtable[item.key] = this.addItemForSortingRecursive(itemsHashtable, item.beginItem) + 0.5;
else
itemsHashtable[item.key] = -1;
return itemsHashtable[item.key];
}
if(item.attachedConnectors.length === 0)
return itemsHashtable[item.key] = 0;
else
for(let i = 0; i < item.attachedConnectors.length; i++) {
const beginItem = item.attachedConnectors[i].beginItem;
if(item.attachedConnectors[i].endItem === item && beginItem && beginItem !== item.attachedConnectors[i].endItem)
return itemsHashtable[item.key] = this.addItemForSortingRecursive(itemsHashtable, beginItem) + 1;
else
return itemsHashtable[item.key] = 0;
}
}
getSortedPasteItems(items: DiagramItem[]): DiagramItem[] {
const sortedItems: DiagramItem[] = [];
const connectors = [];
const itemsHashtable = {};
for(let i = 0; i < items.length; i++) {
const item = items[i];
if(item instanceof Shape)
sortedItems.push(item);
else if(item instanceof Connector) {
connectors.push(item);
this.addItemForSortingRecursive(itemsHashtable, item);
}
}
connectors.sort((a, b) => itemsHashtable[b.key] - itemsHashtable[a.key]);
return sortedItems.concat(connectors);
}
performPaste(data: string): void {
this.control.beginUpdateCanvas();
this.control.history.beginTransaction();
const idsForSelection: {[id: string]: boolean} = {};
let items = this.parseClipboardData(data);
items = this.getSortedPasteItems(items);
for(let i = 0; i < items.length; i++) {
const item = items[i];
if(item instanceof Shape)
this.control.history.addAndRedo(new ImportShapeHistoryItem(item));
else if(item instanceof Connector)
this.control.history.addAndRedo(new ImportConnectorHistoryItem(item));
const containerKey = item.container && item.container.key;
if(!containerKey || idsForSelection[containerKey] === undefined)
idsForSelection[item.key] = true;
else if(containerKey && idsForSelection[containerKey] !== undefined)
idsForSelection[item.key] = false;
}
ModelUtils.tryUpdateModelRectangle(this.control.history);
this.control.history.addAndRedo(new SetSelectionHistoryItem(this.control.selection, Object.keys(idsForSelection).filter(id => idsForSelection[id])));
this.control.history.endTransaction();
this.control.endUpdateCanvas();
this.control.barManager.updateItemsState();
}
protected get isPermissionsRequired(): boolean { return true; }
}