import { SerializableItem } from "./serializableitem"; interface SavePoint<DataType> { description: string; data: DataType; } export class History<HistoryDataType> { public maxCheckpoints: number; public currentCheckpoint: number; private data: SerializableItem<unknown, HistoryDataType>; private checkpoints: SavePoint<HistoryDataType>[]; constructor( data: SerializableItem<unknown, HistoryDataType>, maxCheckpoints = 20, initialMessage = "New History" ) { this.data = data; this.maxCheckpoints = maxCheckpoints; this.checkpoints = []; this.currentCheckpoint = -1; this.checkpoint(initialMessage); } checkpoint(description: string) { const checkpointData = this.data.toHistorySerializableObject(); const checkpoint = { description: description, data: JSON.parse(JSON.stringify(checkpointData)), // deepcopy }; // Remove potential history which is not relevant anymore (maybe caused by undo ops) this.currentCheckpoint++; this.checkpoints.length = this.currentCheckpoint; this.checkpoints.push(checkpoint); } public historyDescription(): Array<string> { return this.checkpoints.map((savepoint) => savepoint.description); } public undo(): SavePoint<HistoryDataType> { if (this.hasUndoCheckpoints()) { return this.checkpoints[this.currentCheckpoint--]; } else { return this.checkpoints[0]; } } public redo(): SavePoint<HistoryDataType> { if (this.hasRedoCheckpoints()) { return this.checkpoints[this.currentCheckpoint++]; } else { return this.checkpoints[this.checkpoints.length - 1]; } } public hasUndoCheckpoints(): boolean { return this.currentCheckpoint > 0; } public hasRedoCheckpoints(): boolean { return this.currentCheckpoint < this.checkpoints.length; } }