devexpress-gantt
Version:
DevExpress Gantt Control
138 lines (130 loc) • 5.29 kB
text/typescript
import { IHistory } from "./IHistory";
import { HistoryItemInfo } from "./HistoryItems/HistoryItemInfo";
import { CompositionHistoryItem } from "./HistoryItems/CompositionHistoryItem";
import { HistoryItem } from "./HistoryItems/HistoryItem";
import { IHistoryListener } from "../../Interfaces/IHistiryListener";
export class History implements IHistory {
private static MAX_HISTORY_ITEM_COUNT: number = 100;
historyItems: HistoryItem[] = [];
currentIndex: number = -1;
currentProcessingItemInfo: HistoryItemInfo = null;
transaction: CompositionHistoryItem = null;
private transactionLevel: number = -1;
private _listener: IHistoryListener;
constructor(listener?: IHistoryListener) {
this._listener = listener;
}
public undo(): void {
if(this.canUndo()) {
this.activateItem(this.historyItems[this.currentIndex], true);
this.currentIndex--;
}
}
public redo(): void {
if(this.canRedo()) {
this.currentIndex++;
this.activateItem(this.historyItems[this.currentIndex]);
}
}
public beginTransaction(): void {
this.transactionLevel++;
if(this.transactionLevel == 0) {
this.transaction = new CompositionHistoryItem();
this._listener?.onTransactionStart();
}
}
public endTransaction(): void {
if(--this.transactionLevel >= 0)
return;
const transactionLength: number = this.transaction.historyItems.length;
if(transactionLength > 1)
this.addInternal(this.transaction);
else if(transactionLength == 1)
this.addInternal(this.transaction.historyItems.pop());
this.transaction = null;
this._listener?.onTransactionEnd();
}
public addAndRedo(historyItem: HistoryItem): void {
this.add(historyItem);
this.activateItem(historyItem);
}
public add(historyItem: HistoryItem): void {
if(this.transactionLevel >= 0)
this.transaction.add(historyItem);
else
this.addInternal(historyItem);
}
public canUndo(): boolean {
return this.currentIndex >= 0;
}
public canRedo(): boolean {
return this.currentIndex < this.historyItems.length - 1;
}
private addInternal(historyItem: HistoryItem) {
if(this.currentIndex < this.historyItems.length - 1)
this.historyItems.splice(this.currentIndex + 1);
this.historyItems.push(historyItem);
this.currentIndex++;
this.deleteOldItems();
}
private deleteOldItems() {
const exceedItemsCount: number = this.historyItems.length - History.MAX_HISTORY_ITEM_COUNT;
if(exceedItemsCount > 0 && this.currentIndex > exceedItemsCount) {
this.historyItems.splice(0, exceedItemsCount);
this.currentIndex -= exceedItemsCount;
}
}
public clear(): void {
this.currentIndex = -1;
this.historyItems = [];
}
activateItem(historyItem: HistoryItem, isUndo: boolean = false): void {
this.currentProcessingItemInfo = new HistoryItemInfo(historyItem, isUndo);
if(isUndo)
historyItem.undo();
else
historyItem.redo();
this.currentProcessingItemInfo = null;
}
getCurrentProcessingItemInfo(): HistoryItemInfo {
return this.currentProcessingItemInfo;
}
rollBackAndRemove(info: HistoryItemInfo): void {
const item = info.item;
if(!this.checkAndRemoveItem(item)) return;
if(info.isUndo)
item.redo();
else if(item instanceof CompositionHistoryItem)
(item as CompositionHistoryItem).undoItemsQuery();
else
item.undo();
}
checkAndRemoveItem(item: HistoryItem): boolean {
let index = this.historyItems.indexOf(item);
if(index > -1) {
this.historyItems.splice(index, 1);
this.currentIndex--;
}
else if(this.transaction) {
index = this.transaction.historyItems.indexOf(item);
if(index > -1)
this.transaction.historyItems.splice(index, 1);
}
return index > -1;
}
public updateObsoleteInsertedKey(oldKey: string, newKey: string, type: string): void {
if(this.transaction)
this.updateItemsObsoleteInsertedKey(oldKey, newKey, type, [ this.transaction ]);
this.updateItemsObsoleteInsertedKey(oldKey, newKey, type, this.historyItems);
}
updateItemsObsoleteInsertedKey(oldKey: string, newKey: string, type: string, historyItems: HistoryItem[]): void {
if(historyItems)
for(let i = 0; i < historyItems.length; i++) {
const item = historyItems[i];
const keyUpdaters = item.keyUpdaters.filter(k => k.getKey() === oldKey && k.objectType === type);
keyUpdaters.forEach(k => k.updateKey(newKey));
if(item instanceof CompositionHistoryItem)
this.updateItemsObsoleteInsertedKey(oldKey, newKey, type, item.historyItems);
}
}
}