devexpress-diagram
Version:
DevExpress Diagram Control
90 lines (82 loc) • 3.66 kB
text/typescript
import { IModelChangesListener } from "../Model/ModelManipulator";
import { ItemChange, ItemChangeType } from "../Model/ModelChange";
import { Size } from "@devexpress/utils/lib/geometry/size";
import { CanvasManagerBase } from "./CanvasManagerBase";
export abstract class CanvasManager extends CanvasManagerBase implements IModelChangesListener {
pendingChanges: { [key: number]: ItemChange } = {};
pendingRemoveChanges: { [key: number]: ItemChange } = {};
private updatesLock: number = 0;
beginUpdate() {
this.updatesLock++;
}
endUpdate() {
this.updatesLock--;
if(this.updatesLock === 0)
this.applyPendingChanges();
}
getPendingChanges() {
return Object.keys(this.pendingChanges).map(key => this.pendingChanges[key]);
}
getPendingRemoveChanges() {
return Object.keys(this.pendingRemoveChanges).map(key => this.pendingRemoveChanges[key]);
}
applyPendingChanges() {
const removeChanges = this.getPendingRemoveChanges();
if(removeChanges.length) {
this.applyChangesCore(removeChanges);
this.pendingRemoveChanges = {};
}
const changes = this.getPendingChanges();
if(changes.length) {
this.applyChangesCore(changes);
this.pendingChanges = {};
}
}
applyChangesCore(changes: ItemChange[]) {
const changesToReapply = [];
changes.forEach(change => {
if(!this.applyChange(change))
changesToReapply.push(change);
});
if(changesToReapply.length && changesToReapply.length !== changes.length)
this.applyChangesCore(changesToReapply);
}
abstract applyChange(change: ItemChange);
postponeChanges(changes: ItemChange[]) {
changes.forEach(change => {
if(change.type === ItemChangeType.Remove) {
this.pendingRemoveChanges[change.key] = change;
delete this.pendingChanges[change.key];
}
else if(!this.pendingChanges[change.key]) {
if(this.pendingRemoveChanges[change.key] && change.type !== ItemChangeType.Create)
throw new Error("Incorrect model changes sequence.");
this.pendingChanges[change.key] = change;
}
else if(change.type === ItemChangeType.Create)
this.pendingChanges[change.key] = change;
else if(change.type === ItemChangeType.UpdateStructure) {
if(this.pendingChanges[change.key].type === ItemChangeType.UpdateProperties)
this.pendingChanges[change.key] = change;
}
else if(change.type === ItemChangeType.UpdateProperties) {
if(this.pendingChanges[change.key].type === ItemChangeType.Update)
this.pendingChanges[change.key] = change;
}
else if(change.type === ItemChangeType.UpdateClassName)
if(this.pendingChanges[change.key].type === ItemChangeType.UpdateClassName)
this.pendingChanges[change.key] = change;
});
}
applyOrPostponeChanges(changes: ItemChange[]) {
if(this.updatesLock === 0)
this.applyChangesCore(changes);
else
this.postponeChanges(changes);
}
notifyModelChanged(changes: ItemChange[]) {
this.applyOrPostponeChanges(changes);
}
notifyPageColorChanged(color: number) { }
notifyPageSizeChanged(pageSize: Size, pageLandscape: boolean) { }
}