Skip to content
Snippets Groups Projects
history.ts 1.98 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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;
        }