import { BaseCommand } from './base-command'; import type { Layer, TransformState, TransformBounds } from '@/types'; import { useLayerStore } from '@/store/layer-store'; import { applyTransformToCanvas } from '@/lib/transform-utils'; import { cloneCanvas } from '@/lib/canvas-utils'; export class TransformCommand extends BaseCommand { private layerId: string; private beforeCanvas: HTMLCanvasElement | null = null; private beforePosition: { x: number; y: number }; private afterCanvas: HTMLCanvasElement | null = null; private afterPosition: { x: number; y: number } | null = null; private transformState: TransformState; private originalBounds: TransformBounds; constructor( layer: Layer, transformState: TransformState, originalBounds: TransformBounds ) { super('Transform Layer'); this.layerId = layer.id; this.transformState = transformState; this.originalBounds = originalBounds; // Store before state if (layer.canvas) { this.beforeCanvas = cloneCanvas(layer.canvas); } this.beforePosition = { x: layer.x, y: layer.y }; } /** * Capture the state after applying the transform */ captureAfterState(layer: Layer): void { if (layer.canvas) { this.afterCanvas = cloneCanvas(layer.canvas); } this.afterPosition = { x: layer.x, y: layer.y }; } execute(): void { if (!this.afterCanvas || !this.afterPosition) { // Apply transform for the first time this.applyTransform(); } else { // Restore after state const { updateLayer } = useLayerStore.getState(); const layer = this.getLayer(); if (!layer?.canvas) return; const ctx = layer.canvas.getContext('2d'); if (ctx) { ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height); ctx.drawImage(this.afterCanvas, 0, 0); updateLayer(layer.id, { x: this.afterPosition.x, y: this.afterPosition.y, updatedAt: Date.now(), }); } } } undo(): void { if (!this.beforeCanvas) return; const { updateLayer } = useLayerStore.getState(); const layer = this.getLayer(); if (!layer?.canvas) return; const ctx = layer.canvas.getContext('2d'); if (ctx) { ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height); ctx.drawImage(this.beforeCanvas, 0, 0); updateLayer(layer.id, { x: this.beforePosition.x, y: this.beforePosition.y, updatedAt: Date.now(), }); } } private applyTransform(): void { const layer = this.getLayer(); if (!layer?.canvas || !this.beforeCanvas) return; // Apply transform to canvas const transformedCanvas = applyTransformToCanvas( this.beforeCanvas, this.transformState, this.originalBounds ); // Update layer canvas const ctx = layer.canvas.getContext('2d'); if (ctx) { // Resize canvas if needed if ( layer.canvas.width !== transformedCanvas.width || layer.canvas.height !== transformedCanvas.height ) { layer.canvas.width = transformedCanvas.width; layer.canvas.height = transformedCanvas.height; } ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height); ctx.drawImage(transformedCanvas, 0, 0); // Update layer position and size const { updateLayer } = useLayerStore.getState(); updateLayer(layer.id, { x: this.originalBounds.x + this.transformState.x, y: this.originalBounds.y + this.transformState.y, width: transformedCanvas.width, height: transformedCanvas.height, updatedAt: Date.now(), }); } this.captureAfterState(layer); } private getLayer(): Layer | undefined { const { layers } = useLayerStore.getState(); return layers.find((l) => l.id === this.layerId); } /** * Static method to create and execute a transform command */ static applyToLayer( layer: Layer, transformState: TransformState, originalBounds: TransformBounds ): TransformCommand { const command = new TransformCommand(layer, transformState, originalBounds); command.execute(); return command; } }