95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
/**
|
||
* 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<string, unknown>),
|
||
[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<string, unknown>;
|
||
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)}`;
|
||
}
|