import { BaseTool } from './base-tool'; import type { PointerState } from '@/types'; import { useSelectionStore } from '@/store/selection-store'; import { useLayerStore } from '@/store/layer-store'; import { createRectangularMask, createSelection, combineMasks, } from '@/lib/selection-utils'; export class RectangularSelectionTool extends BaseTool { private startX = 0; private startY = 0; private currentX = 0; private currentY = 0; private previewCanvas: HTMLCanvasElement | null = null; constructor() { super('Rectangular Selection'); } onPointerDown(pointer: PointerState): void { this.isActive = true; this.isDrawing = true; this.startX = pointer.x; this.startY = pointer.y; this.currentX = pointer.x; this.currentY = pointer.y; } onPointerMove(pointer: PointerState, ctx: CanvasRenderingContext2D): void { if (!this.isDrawing) return; this.currentX = pointer.x; this.currentY = pointer.y; // Draw preview rectangle const layer = this.getActiveLayer(); if (!layer?.canvas) return; ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height); ctx.save(); ctx.strokeStyle = '#000'; ctx.lineWidth = 1; ctx.setLineDash([4, 4]); const x = Math.min(this.startX, this.currentX); const y = Math.min(this.startY, this.currentY); const w = Math.abs(this.currentX - this.startX); const h = Math.abs(this.currentY - this.startY); ctx.strokeRect(x, y, w, h); ctx.strokeStyle = '#fff'; ctx.lineDashOffset = 4; ctx.strokeRect(x, y, w, h); ctx.restore(); } onPointerUp(): void { if (!this.isDrawing) return; const layer = this.getActiveLayer(); if (!layer?.canvas) return; const x = Math.min(this.startX, this.currentX); const y = Math.min(this.startY, this.currentY); const width = Math.abs(this.currentX - this.startX); const height = Math.abs(this.currentY - this.startY); if (width > 0 && height > 0) { const { selectionMode, feather, activeSelection } = useSelectionStore.getState(); const newMask = createRectangularMask( x, y, width, height, layer.canvas.width, layer.canvas.height ); let finalMask = newMask; // Combine with existing selection if needed if (activeSelection && selectionMode !== 'new') { finalMask = combineMasks(activeSelection.mask, newMask, selectionMode); } const selection = createSelection(layer.id, finalMask, feather); useSelectionStore.getState().setActiveSelection(selection); } this.isDrawing = false; this.isActive = false; } getCursor(): string { return 'crosshair'; } private getActiveLayer() { const { activeLayerId, layers } = useLayerStore.getState(); return layers.find((l) => l.id === activeLayerId); } }