class HistoryManager { constructor(app) { this.app = app; this.history = []; this.currentIndex = -1; this.maxHistorySize = 50; // Save initial state this.saveState(); } // Save current state to history saveState() { // Remove any states after current index (when user makes new action after undo) this.history = this.history.slice(0, this.currentIndex + 1); // Create a deep copy of current design elements const state = { designElements: JSON.parse(JSON.stringify(this.app.designElements)), timestamp: Date.now() }; this.history.push(state); this.currentIndex++; // Limit history size if (this.history.length > this.maxHistorySize) { this.history.shift(); this.currentIndex--; } this.updateButtonStates(); console.log('State saved. History size:', this.history.length, 'Current index:', this.currentIndex); } // Undo last action undo() { if (!this.canUndo()) { console.log('Cannot undo - at beginning of history'); return; } this.currentIndex--; this.restoreState(this.history[this.currentIndex]); this.updateButtonStates(); console.log('Undo performed. Current index:', this.currentIndex); } // Redo last undone action redo() { if (!this.canRedo()) { console.log('Cannot redo - at end of history'); return; } this.currentIndex++; this.restoreState(this.history[this.currentIndex]); this.updateButtonStates(); console.log('Redo performed. Current index:', this.currentIndex); } // Check if undo is possible canUndo() { return this.currentIndex > 0; } // Check if redo is possible canRedo() { return this.currentIndex < this.history.length - 1; } // Restore a state from history restoreState(state) { // Deep copy the state to avoid reference issues this.app.designElements = JSON.parse(JSON.stringify(state.designElements)); // Redraw the canvas this.app.canvasDrawingManager.redraw(); // Update 3D view if active if (this.app.threeJSManager.is3DViewActive()) { this.app.viewManager.convertTo3D(); } // Clear selection this.app.uiManager.clearSelection(); } // Update button states (enabled/disabled) updateButtonStates() { const undoBtn = document.getElementById('undoBtn'); const redoBtn = document.getElementById('redoBtn'); if (undoBtn) { if (this.canUndo()) { undoBtn.disabled = false; undoBtn.classList.remove('opacity-50', 'cursor-not-allowed'); undoBtn.classList.add('hover:bg-gray-200'); } else { undoBtn.disabled = true; undoBtn.classList.add('opacity-50', 'cursor-not-allowed'); undoBtn.classList.remove('hover:bg-gray-200'); } } if (redoBtn) { if (this.canRedo()) { redoBtn.disabled = false; redoBtn.classList.remove('opacity-50', 'cursor-not-allowed'); redoBtn.classList.add('hover:bg-gray-200'); } else { redoBtn.disabled = true; redoBtn.classList.add('opacity-50', 'cursor-not-allowed'); redoBtn.classList.remove('hover:bg-gray-200'); } } } // Clear history (useful for new design) clear() { this.history = []; this.currentIndex = -1; this.saveState(); console.log('History cleared'); } // Get history info for debugging getInfo() { return { historySize: this.history.length, currentIndex: this.currentIndex, canUndo: this.canUndo(), canRedo: this.canRedo() }; } }