Add marquee selection: click and drag on empty space to select multiple symbols
- Blue dashed rectangle drawn while dragging - Selects all visible symbols whose bounding box intersects the marquee - Respects hidden symbols and hidden groups Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3c532b8cfe
commit
18c0e03287
@ -548,6 +548,31 @@ function onMousemove(e: MouseEvent) {
|
||||
}
|
||||
layout.markDirty();
|
||||
}
|
||||
|
||||
if (dragState.type === 'marquee') {
|
||||
const pos = screenToCanvas(e.clientX, e.clientY);
|
||||
if (!dragState.dragActivated) {
|
||||
if (!pastDragThreshold(pos.x, pos.y, dragState.startX!, dragState.startY!, DRAG_THRESHOLD)) return;
|
||||
dragState.dragActivated = true;
|
||||
}
|
||||
const x1 = Math.min(dragState.startX!, pos.x);
|
||||
const y1 = Math.min(dragState.startY!, pos.y);
|
||||
const x2 = Math.max(dragState.startX!, pos.x);
|
||||
const y2 = Math.max(dragState.startY!, pos.y);
|
||||
marqueeRect = { x: x1, y: y1, w: x2 - x1, h: y2 - y1 };
|
||||
|
||||
// Select all visible symbols whose AABB intersects the marquee
|
||||
const selected = new Set<number>();
|
||||
for (const sym of layout.symbols) {
|
||||
if (sym.hidden || layout.hiddenGroups.has(getSymbolGroup(sym.symbolId))) continue;
|
||||
const bb = getAABB(sym.x, sym.y, sym.w, sym.h, sym.rotation);
|
||||
if (bb.x + bb.w >= x1 && bb.x <= x2 && bb.y + bb.h >= y1 && bb.y <= y2) {
|
||||
selected.add(sym.id);
|
||||
}
|
||||
}
|
||||
layout.selectedIds = selected;
|
||||
layout.markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseup(e: MouseEvent) {
|
||||
@ -643,6 +668,11 @@ function onMouseup(e: MouseEvent) {
|
||||
layout.saveMcmState();
|
||||
}
|
||||
|
||||
if (dragState.type === 'marquee') {
|
||||
marqueeRect = null;
|
||||
layout.markDirty();
|
||||
}
|
||||
|
||||
dragState = null;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { layout } from '../stores/layout.svelte.js';
|
||||
import { getSymbolImage, isResizable, isCurvedType, isSpurType, isEpcType, isInductionType, isPhotoeyeType, getCurveGeometry, getSymbolGroup, SPACING_EXEMPT, EPC_CONFIG, INDUCTION_CONFIG, PHOTOEYE_CONFIG } from '../symbols.js';
|
||||
import { checkSpacingViolation } from './collision.js';
|
||||
import { marqueeRect } from './interactions.js';
|
||||
import { THEME } from './render-theme.js';
|
||||
import type { PlacedSymbol } from '../types.js';
|
||||
|
||||
@ -79,6 +80,17 @@ export function render() {
|
||||
if (SPACING_EXEMPT.has(sym.symbolId)) drawSymbol(ctx, sym as PlacedSymbol);
|
||||
}
|
||||
|
||||
// Marquee selection rectangle
|
||||
if (marqueeRect) {
|
||||
ctx.strokeStyle = '#4a9eff';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.setLineDash([4, 3]);
|
||||
ctx.fillStyle = 'rgba(74, 158, 255, 0.1)';
|
||||
ctx.fillRect(marqueeRect.x, marqueeRect.y, marqueeRect.w, marqueeRect.h);
|
||||
ctx.strokeRect(marqueeRect.x, marqueeRect.y, marqueeRect.w, marqueeRect.h);
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user