/** * Task CAD-5 – Block-Editor-Service. * * openBlockForEdit legt markierte KOPIEN der Block-Elemente ins * Dokument (Original unangetastet); saveBlockEdit schreibt die * bearbeiteten Kopien als neue Blockdefinition zurueck und * raeumt die Edit-Kopien auf; discardBlockEdit verwirft alles. * Marker: BLOCK_EDIT_MARKER (properties-Flag + __blockEdit-IDs). */ import type { CADElement, BlockDefinition } from '../types/cad.types'; import type { CADDocument } from '../kernel/document/CADDocument'; /** Marker-Flag in properties der Edit-Kopien. */ export const BLOCK_EDIT_MARKER = '__blockEdit'; /** Aktive Edit-Sitzung (Service-State). */ let editSession: { blockId: string; copyIds: string[] } | null = null; /** * Oeffnet einen Block zur Bearbeitung: Kopien aller Elemente mit * Edit-Marker werden ins Dokument gelegt (Original bleibt). * @returns true wenn geoeffnet, false bei unbekannter ID oder * bereits offener Sitzung. */ export function openBlockForEdit(doc: CADDocument, blockId: string): boolean { if (editSession) return false; const block = doc.getBlock(blockId); if (!block) return false; const copyIds: string[] = []; doc.transact(() => { for (const el of block.elements) { const copy: CADElement = { ...el, id: `__blockEdit_${blockId}_${copyIds.length}`, properties: { ...(el.properties as Record), [BLOCK_EDIT_MARKER]: true, }, } as unknown as CADElement; doc.addElement(copy); copyIds.push(copy.id); } }); editSession = { blockId, copyIds }; return true; } /** * Speichert die Bearbeitung: die markierten Kopien werden als * neue Elementliste in die Blockdefinition geschrieben (Marker * entfernt); Edit-Kopien werden aus dem Dokument geloescht. * @returns blockId der gespeicherten Definition oder null. */ export function saveBlockEdit(doc: CADDocument): string | null { if (!editSession) return null; const { blockId, copyIds } = editSession; const elements: CADElement[] = []; for (const id of copyIds) { const el = doc.getElement(id); if (!el) continue; const { [BLOCK_EDIT_MARKER]: _marker, ...cleanProps } = el.properties as Record; elements.push({ ...el, id: uid('blk'), properties: cleanProps } as unknown as CADElement); } const block = doc.getBlock(blockId); if (block) { doc.addBlock({ ...block, elements }); } doc.deleteElements(copyIds); editSession = null; return blockId; } /** * Verwirft die Bearbeitung: Edit-Kopien werden geloescht, die * Blockdefinition bleibt unveraendert. * @returns true wenn verworfen, false ohne offene Sitzung. */ export function discardBlockEdit(doc: CADDocument): boolean { if (!editSession) return false; doc.deleteElements(editSession.copyIds); editSession = null; return true; } /** Ist gerade eine Block-Bearbeitung offen? */ export function isBlockEditOpen(): boolean { return editSession !== null; } let uidCounter = 0; function uid(prefix: string): string { return `${prefix}_${Date.now().toString(36)}_${uidCounter++}_${Math.random().toString(36).slice(2, 8)}`; }