7.5 KiB
7.5 KiB
Phase 3: Drawing Tools — React Wiring & State Management
Goal
Wire Phase 1 canvas/interaction engines to React state so drawing tools actually create, render, and manage elements. Implement undo/redo, command-line shortcuts, and drawing flow improvements.
Requirements Covered
- F-CAD-01: Zeichnen von Grundelementen (Linie, Kreis, Bogen, Rechteck, Polygon, Polylinie)
- F-CAD-03: Bemaßung
- F-CAD-05: Command Line (L, C, PL, R, A, T, DIM shortcuts)
- F-CAD-09: Undo/Redo mit History
- F-CAD-11: Text
Current State
src/interaction/index.ts(591 lines): InteractionEngine with drawing logic for all types, callbacks (onElementCreated, onElementsDeleted, onToolStateChanged, onCursorMoved, onCommandTrigger)src/canvas/RenderEngine.ts(588 lines): Renders all element typessrc/components/CanvasArea.tsx(103 lines): Creates engine instances in useEffect but does NOT wire callbacks to React statesrc/App.tsx(223 lines): Has mock state but no element management, no engine ref, no undo/redo
Tasks
Task 1: Refactor CanvasArea to expose engine instances
File: src/components/CanvasArea.tsx
Current: engines created in useEffect, no external access.
Required:
- Use
useRefto hold engine instances (InteractionEngine, RenderEngine, ZoomPanController, etc.) - Accept new props:
onElementCreated,onElementsDeleted,onCursorMoved,onToolStateChanged,onToolChange(tool from App → engine),elements(element array → engine.setElements),snapEnabled,orthoEnabled,gridEnabled(from App → engine state) - In useEffect: create engines, wire all callbacks to props, call
interaction.setCallbacks({...}) - Add a separate useEffect for
elementschanges →interaction.setElements(elements)+spatialIndex.bulkInsert(elements)+renderEngine.render() - Add a separate useEffect for
snapEnabled/orthoEnabled/gridEnabled→ update engine state + renderEngine options - Add a separate useEffect for
activeTool→interaction.setTool(tool) - Expose zoomPan via ref callback prop
onZoomPanReadyso App can call zoomFit - Add
onZoomIn,onZoomOut,onZoomFitto actually call zoomPan methods (not just log) - Add double-click handler: on dblclick, if drawing polyline/polygon → call confirmDraw via interaction
New CanvasAreaProps (add to src/types/ui.types.ts):
export interface CanvasAreaProps {
cursorPos: CursorPos;
viewMode: ViewMode;
onViewChange: (mode: ViewMode) => void;
gridEnabled: boolean;
orthoEnabled: boolean;
snapEnabled: boolean;
activeTool: string;
elements: CADElement[];
onElementCreated: (el: CADElement) => void;
onElementsDeleted: (ids: string[]) => void;
onCursorMoved: (x: number, y: number) => void;
onToolStateChanged: (state: ToolState) => void;
onToggleGrid: () => void;
onToggleOrtho: () => void;
onToggleSnap: () => void;
onZoomIn: () => void;
onZoomOut: () => void;
onZoomFit: () => void;
}
Task 2: Implement undo/redo stack in App.tsx
File: src/App.tsx
Required:
- Add
elementsstate:useState<CADElement[]>([]) - Add
undoStackandredoStackasuseState<CADElement[][]> handleElementCreated: push current elements to undoStack, add new element, clear redoStackhandleElementsDeleted: push current elements to undoStack, remove deleted, clear redoStackhandleUndo: if undoStack not empty, push current to redoStack, pop undoStack → set elementshandleRedo: if redoStack not empty, push current to undoStack, pop redoStack → set elements- Pass
elementsto CanvasArea - Pass
onElementCreated,onElementsDeletedto CanvasArea - Wire
onCursorMovedto updatecursorPosstate - Wire
onToolStateChangedto update any relevant UI state
Task 3: Wire tool selection from LeftSidebar to CanvasArea
File: src/App.tsx
Required:
activeToolstate already exists in App.tsx- Pass
activeToolto CanvasArea as prop - CanvasArea useEffect watches
activeTool→ callsinteraction.setTool(tool as ToolType) - LeftSidebar
onToolChangealready updatesactiveToolin App
Task 4: Command line shortcuts (F-CAD-05)
File: src/App.tsx
Required:
- In
handleCommand(cmd), parse command and map to tool:LorLINE→ setTool('line')CorCIRCLE→ setTool('circle')AorARC→ setTool('arc')RorRECTorRECTANGLE→ setTool('rect')PLorPOLYLINE→ setTool('polyline')POLorPOLYGON→ setTool('polygon')TorTEXT→ setTool('text')DIMorDIMENSION→ setTool('dimension')VorSELECT→ setTool('select')PorPAN→ setTool('pan')MorMOVE→ setTool('move')COorCOPY→ setTool('copy')ROorROTATE→ setTool('rotate')SCorSCALE→ setTool('scale')MIorMIRROR→ setTool('mirror')DELorERASE→ setTool('delete')UNDOorU→ handleUndo()REDO→ handleRedo()
- Add command to history with prefix '›'
- Add response to history with prefix '·' (e.g. 'Linie-Werkzeug aktiv · Klicken zum Starten')
Task 5: Drawing flow improvements
File: src/interaction/index.ts
Required:
- Polyline/Polygon: Add
handleDoubleClickmethod — if activeTool is polyline/polygon and phase is drawing, call confirmDraw() - Wire dblclick event in
attach():this.addListener('dblclick', this.onDoubleClick.bind(this)) - Arc: Improve 3-point arc — first click = center, second click = start point (sets radius + startAngle), third click = end point (sets endAngle). Update handleDrawDown to handle multi-point arc.
- Text: After placing text element, trigger an inline edit prompt. For now, use a simple
prompt()dialog or addonTextEditcallback.
Task 6: Grid/Snap/Ortho toggle wiring
File: src/components/CanvasArea.tsx
Required:
- When
gridEnabledprop changes:renderEngine.setOptions({ showGrid: gridEnabled })+ re-render - When
snapEnabledprop changes:interaction.state.snapEnabled = snapEnabled+renderEngine.setOptions({ showSnapPoints: snapEnabled })+ re-render - When
orthoEnabledprop changes:interaction.state.ortho = orthoEnabled+renderEngine.setOptions({ showOrtho: orthoEnabled })+ re-render
Constraints
- TypeScript functional components, no inline styles (except where mockup uses style)
- No styled-components, no Tailwind
npx tsc --noEmitmust pass with 0 errorsnpx vite buildmust succeed- Minimal changes — extend existing files, don't rewrite
- Keep all existing CSS class names
- Import ToolState type from interaction/index.ts where needed
File Summary
src/types/ui.types.ts— update CanvasAreaPropssrc/components/CanvasArea.tsx— expose engines, wire callbacks, add useEffectssrc/App.tsx— element state, undo/redo, command shortcuts, wire all callbackssrc/interaction/index.ts— double-click handler, arc 3-point, text edit callback
Test Criteria
npx tsc --noEmit— 0 errorsnpx vite build— success- Drawing a line: select Line tool → click start → move mouse → Enter → element appears
- Drawing a rect: select Rect tool → click corner → move mouse → Enter → element appears
- Drawing a circle: select Circle tool → click center → move mouse → Enter → element appears
- Polyline: select Polyline → click multiple points → double-click → element appears
- Command line: type 'L' → line tool activates
- Undo/Redo: draw element → Ctrl+Z → element disappears → Ctrl+Y → element reappears
- Grid toggle: click grid button → grid appears/disappears
- Snap toggle: click snap button → snap points appear/disappear on hover