/** * core-annotate – Built-in V2-Plugin (Task A4.4). * * Werkzeuge: text (Platzierung — Inhalt via InlineTextEditor/PropertiesPanel, * Bestandskanal onTextEdit bleibt), dimension (2-Punkt linear), leader * (2-Punkt Pfeil+Label). */ import type { PluginV2, ToolExtensionV2, FullToolContext } from '../../types'; import type { CADElement } from '../../../types/cad.types'; import type { Pt } from '../../../tools/modification/geometry'; const uid = (prefix: string): string => `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`; /** Gemeinsamer 2-Punkt-Sitzungsstart für dimension/leader. */ let twoPointStart: Pt | null = null; function optsOf(ctx: FullToolContext): { stroke: string; layerId: string } { return { stroke: (ctx.options.strokeColor as string | undefined) ?? '#e0e0e0', layerId: (ctx.options.layerId as string | undefined) ?? 'layer-0', }; } function buildDimension(start: Pt, end: Pt, ctx: FullToolContext): CADElement { const o = optsOf(ctx); return { id: uid('dim'), type: 'dimension', layerId: o.layerId, x: (start.x + end.x) / 2, y: (start.y + end.y) / 2, width: Math.hypot(end.x - start.x, end.y - start.y), // Legacy: dist als Breite height: 20, properties: { x1: start.x, y1: start.y, x2: end.x, y2: end.y }, } as unknown as CADElement; } function buildLeader(start: Pt, end: Pt, ctx: FullToolContext): CADElement { const o = optsOf(ctx); return { id: uid('leader'), type: 'leader', layerId: o.layerId, x: end.x, y: end.y, width: Math.abs(end.x - start.x), height: Math.abs(end.y - start.y), properties: { x1: start.x, y1: start.y, x2: end.x, y2: end.y, text: '', fontSize: 12, stroke: o.stroke, strokeWidth: 1 }, } as unknown as CADElement; } /** Generischer 2-Punkt-Annotate-Fluss (down→Preview→up commit). */ function make2PointAnnotate( id: 'dimension' | 'leader', label: string, icon: string, build: (a: Pt, b: Pt, ctx: FullToolContext) => CADElement, ): ToolExtensionV2 { return { manifest: { id, label, icon, ribbonTab: 'format', tags: ['basic'] }, optionsSchema: [{ key: 'strokeColor', label: 'Farbe', type: 'color' }], handlers: { down(e, ctx) { twoPointStart = e.world; ctx.setStatus(`${label}: Startpunkt gesetzt – Ende wählen`); }, move(e, ctx) { if (!twoPointStart) return; ctx.setPreview?.(build(twoPointStart, e.world, ctx as FullToolContext)); }, up(e, ctx) { const c = ctx as FullToolContext; if (!twoPointStart || !c.doc) { twoPointStart = null; return; } const el = build(twoPointStart, e.world, c); c.doc.transact(() => c.doc!.addElement(el)); twoPointStart = null; ctx.setPreview?.(null); ctx.setStatus(`${label} erstellt (${el.id})`); }, cancel(ctx) { twoPointStart = null; ctx.setPreview?.(null); ctx.setStatus(`${label} abgebrochen`); }, }, }; } /** * text-Werkzeug (A4.4): Klick platziert Textelement mit leerem Inhalt; * Bearbeitung läuft über den bestehenden InlineTextEditor/onTextEdit-Kanal. */ export const textTool: ToolExtensionV2 = { manifest: { id: 'text', label: 'Text', icon: 'T', ribbonTab: 'format', tags: ['basic'], description: 'Text platzieren und über Editor beschriften', }, optionsSchema: [{ key: 'fontSize', label: 'Größe', type: 'number', min: 6, max: 72 }], handlers: { down(e, ctx) { const c = ctx as FullToolContext; if (!c.doc) return; const layerId = (c.options.layerId as string | undefined) ?? 'layer-0'; const fontSize = (c.options.fontSize as number | undefined) ?? 12; const el = { id: uid('text'), type: 'text', layerId, x: e.world.x, y: e.world.y, width: 100, height: 20, properties: { text: '', fontSize }, } as unknown as CADElement; c.doc.transact(() => c.doc!.addElement(el)); ctx.setStatus(`Text platziert (${el.id}) – now via Editor`); }, }, }; export const dimensionTool: ToolExtensionV2 = make2PointAnnotate('dimension', 'Bemaßung', '\u2194', buildDimension); export const leaderTool: ToolExtensionV2 = make2PointAnnotate('leader', 'Leader', '\u21b1', buildLeader); /** V2-Plugin: Beschriftung/Bemaßung (A4.4). */ export const coreAnnotatePlugin: PluginV2 = { manifest: { id: 'core-annotate', name: 'Beschriftung (Kern)', version: '1.0.0', author: 'web-cad team', description: 'Text, Bemaßung, Leader (V2).', category: 'tools', enabledByDefault: true, }, tools: [textTool, dimensionTool, leaderTool], };