From 38a35612ab6cc90279cc89577310791a811df0b2 Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 28 Jan 2026 11:53:26 +0100 Subject: feat(editor): Implement basic undo/redo functionality Adds the core logic for managing an action history stack and an undo button. - Initializes undoStack, redoStack, and MAX_HISTORY_SIZE. - Implements addAction to record operations and clear redoStack. - Implements handleUndo to revert actions and manage stacks. - Adds placeholder for redrawCanvas and updateUndoRedoButtons. --- tools/editor/script.js | 75 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 7 deletions(-) (limited to 'tools/editor/script.js') diff --git a/tools/editor/script.js b/tools/editor/script.js index 45af325..737a9e6 100644 --- a/tools/editor/script.js +++ b/tools/editor/script.js @@ -5,6 +5,10 @@ let currentSpecData = null; // Stores the parsed spectrogram data let dctSize = 512; // Default DCT size, read from header +let undoStack = []; +let redoStack = []; +const MAX_HISTORY_SIZE = 50; + // --- File Handling --- const specFileInput = document.getElementById('specFileInput'); specFileInput.addEventListener('change', handleFileSelect); @@ -35,7 +39,7 @@ async function handleFileSelect(event) { dctSize = header.dct_size; const dataStart = 16; - const numBytes = header.num_frames * header.dct_size * sizeof(float); + const numBytes = header.num_frames * header.dct_size * Float32Array.BYTES_PER_ELEMENT; const spectralDataFloat = new Float32Array(buffer, dataStart, header.num_frames * header.dct_size); currentSpecData = { @@ -106,20 +110,77 @@ function drawSpectrogram(specData) { const lineToolButton = document.getElementById('lineTool'); const ellipseToolButton = document.getElementById('ellipseTool'); const noiseToolButton = document.getElementById('noiseTool'); +const undoButton = document.getElementById('undoButton'); lineToolButton.addEventListener('click', () => console.log('Line tool selected')); ellipseToolButton.addEventListener('click', () => console.log('Ellipse tool selected')); noiseToolButton.addEventListener('click', () => console.log('Noise tool selected')); -// TODO: Implement canvas event listeners for drawing shapes -// TODO: Implement shape parameter controls -// TODO: Implement save/load JSON -// TODO: Implement .spec export +undoButton.addEventListener('click', handleUndo); + +// --- Undo/Redo Logic --- +function addAction(action) { + undoStack.push(action); + // Limit history size + if (undoStack.length > MAX_HISTORY_SIZE) { + undoStack.shift(); // Remove oldest action + } + redoStack = []; // Clear redo stack on new action + updateUndoRedoButtons(); +} + +function handleUndo() { + if (undoStack.length === 0) { + console.log('Undo stack is empty.'); + return; + } + + const actionToUndo = undoStack.pop(); + actionToUndo.undo(); // Execute the inverse operation + redoStack.push(actionToUndo); + redrawCanvas(); // Redraw canvas to reflect the undo operation + updateUndoRedoButtons(); +} + +function handleRedo() { + if (redoStack.length === 0) { + console.log('Redo stack is empty.'); + return; + } + + const actionToRedo = redoStack.pop(); + actionToRedo.redo(); // Re-apply the action + undoStack.push(actionToRedo); + redrawCanvas(); // Redraw canvas to reflect the redo operation + updateUndoRedoButtons(); +} + +function redrawCanvas() { + // This function needs to be implemented to redraw the entire canvas state + // based on the current undoStack. For now, it's a placeholder. + console.log('Redrawing canvas...'); + if (currentSpecData) { + drawSpectrogram(currentSpecData); + } else { + // Clear canvas if no data is loaded + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#ffffff'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } +} + +function updateUndoRedoButtons() { + // Enable/disable buttons based on stack emptiness + undoButton.disabled = undoStack.length === 0; + // redoButton.disabled = redoStack.length === 0; // If redo button exists +} // Initial setup for canvas size (can be updated on window resize) window.addEventListener('resize', () => { - // Re-draw or re-initialize canvas size if needed if (currentSpecData) { drawSpectrogram(currentSpecData); } -}); \ No newline at end of file +}); + +// Initial call to set button states and potentially draw initial state if any is loaded +updateUndoRedoButtons(); \ No newline at end of file -- cgit v1.2.3