diff --git a/svelte-app/src/lib/canvas/interactions.ts b/svelte-app/src/lib/canvas/interactions.ts index 6895ba0..e5b0a7c 100644 --- a/svelte-app/src/lib/canvas/interactions.ts +++ b/svelte-app/src/lib/canvas/interactions.ts @@ -1,5 +1,5 @@ import { layout } from '../stores/layout.svelte.js'; -import { isCurvedType, isEpcType, SYMBOLS, EPC_CONFIG } from '../symbols.js'; +import { isCurvedType, isEpcType, getSymbolGroup, SYMBOLS, EPC_CONFIG } from '../symbols.js'; import type { EpcWaypoint } from '../types.js'; import { getAABB, snapToGrid, clamp, findValidPosition } from './collision.js'; import { orientedBoxCorners, pastDragThreshold } from './geometry.js'; @@ -22,7 +22,7 @@ const CONVEYOR_MIN_W = 40; const DRAG_THRESHOLD = 4; // pixels before drag actually starts interface DragState { - type: 'palette' | 'move' | 'multi-move' | 'resize-left' | 'resize-right' | 'resize-spur-top' | 'resize-spur-bottom' | 'epc-waypoint' | 'pdf' | 'assign-label'; + type: 'palette' | 'move' | 'multi-move' | 'resize-left' | 'resize-right' | 'resize-spur-top' | 'resize-spur-bottom' | 'epc-waypoint' | 'pdf' | 'assign-label' | 'marquee'; placedId?: number; offsetX?: number; offsetY?: number; @@ -44,6 +44,9 @@ interface DragState { let dragState: DragState | null = null; let isPanning = false; + +// Marquee selection rectangle (canvas coords), accessible by renderer +export let marqueeRect: { x: number; y: number; w: number; h: number } | null = null; let panStartX = 0; let panStartY = 0; let canvasEl: HTMLCanvasElement | null = null; @@ -243,11 +246,17 @@ function onCanvasMousedown(e: MouseEvent) { } layout.markDirty(); } else { - // Click on empty space + // Empty space: start marquee selection if (!e.shiftKey) { layout.selectedIds = new Set(); - layout.markDirty(); } + dragState = { + type: 'marquee', + startX: pos.x, + startY: pos.y, + dragActivated: false, + }; + layout.markDirty(); } } diff --git a/svelte-app/src/lib/canvas/render-theme.ts b/svelte-app/src/lib/canvas/render-theme.ts index b89c7d8..731e428 100644 --- a/svelte-app/src/lib/canvas/render-theme.ts +++ b/svelte-app/src/lib/canvas/render-theme.ts @@ -33,7 +33,7 @@ export const THEME = { }, label: { color: '#e94560', - font: '10px sans-serif', + font: '3px sans-serif', offsetY: -3, }, resizeHandle: { diff --git a/svelte-app/src/lib/canvas/renderer.ts b/svelte-app/src/lib/canvas/renderer.ts index 549a78a..3dcb8d9 100644 --- a/svelte-app/src/lib/canvas/renderer.ts +++ b/svelte-app/src/lib/canvas/renderer.ts @@ -495,7 +495,7 @@ function drawSymbolOverlays(ctx: CanvasRenderingContext2D, sym: PlacedSymbol) { ctx.fillStyle = THEME.label.color; ctx.font = THEME.label.font; const metrics = ctx.measureText(sym.label); - const textH = 10; // approximate font height + const textH = 3; // approximate font height if (sym.w >= metrics.width + 4 && sym.h >= textH + 4) { ctx.textAlign = 'center'; ctx.textBaseline = 'middle';