Files
web-cad/frontend/src/services/commandRegistry.ts
T

154 lines
10 KiB
TypeScript
Raw Normal View History

/**
* CommandRegistry Zentrale Befehls-Registry für die CAD-Command-Line.
* F-CAD-05: Command Line (L, C, PL, R, A, T, DIM shortcuts)
* F-UI-04: Autovervollständigung
*/
export interface CommandDefinition {
/** Primärer Befehlsname (Großbuchstaben) */
name: string;
/** Aliasse / Kurzformen */
aliases: string[];
/** Tool-ID die aktiviert wird (null für Meta-Befehle wie UNDO) */
toolId: string | null;
/** Beschreibung für Autovervollständigung */
description: string;
/** Kategorie für Gruppierung */
category: 'draw' | 'modify' | 'view' | 'meta' | 'special';
/** Deutsches Label für Command-History-Ausgabe */
label: string;
}
const commands: CommandDefinition[] = [
// ─── Zeichen-Werkzeuge ─────────────────────────────
{ name: 'LINE', aliases: ['L', 'LINIE'], toolId: 'line', description: 'Linie zeichnen', category: 'draw', label: 'Linie-Werkzeug aktiv · Klicken zum Starten' },
{ name: 'CIRCLE', aliases: ['C', 'KREIS'], toolId: 'circle', description: 'Kreis zeichnen', category: 'draw', label: 'Kreis-Werkzeug aktiv · Klicken für Mittelpunkt' },
{ name: 'ARC', aliases: ['A', 'BOGEN'], toolId: 'arc', description: 'Bogen zeichnen', category: 'draw', label: 'Bogen-Werkzeug aktiv · Klicken für Mittelpunkt' },
{ name: 'RECT', aliases: ['R', 'RECTANGLE', 'RECHTECK'], toolId: 'rect', description: 'Rechteck zeichnen', category: 'draw', label: 'Rechteck-Werkzeug aktiv · Klicken für erste Ecke' },
{ name: 'POLYLINE', aliases: ['PL', 'POLYLINIE'], toolId: 'polyline', description: 'Polylinie zeichnen', category: 'draw', label: 'Polylinie-Werkzeug aktiv · Klicken für Punkte, Doppelklick zum Beenden' },
{ name: 'POLYGON', aliases: ['POL', 'POLYGON'], toolId: 'polygon', description: 'Polygon zeichnen', category: 'draw', label: 'Polygon-Werkzeug aktiv · Klicken für Punkte, Doppelklick zum Beenden' },
{ name: 'TEXT', aliases: ['T', 'TXT'], toolId: 'text', description: 'Text platzieren', category: 'draw', label: 'Text-Werkzeug aktiv · Klicken zum Platzieren' },
{ name: 'DIMENSION', aliases: ['DIM', 'BEMASSUNG'], toolId: 'dimension', description: 'Bemaßung erstellen', category: 'draw', label: 'Bemaßung-Werkzeug aktiv · Klicken für Startpunkt' },
{ name: 'LEADER', aliases: ['LD', 'HINWEIS'], toolId: 'leader', description: 'Hinweislinie erstellen', category: 'draw', label: 'Hinweislinie · Klicken für Pfeilspitze, dann für Textposition' },
{ name: 'REVCLOUD', aliases: ['REV', 'REVISIONSWOLKE'], toolId: 'revcloud', description: 'Revisionswolke zeichnen', category: 'draw', label: 'Revisionswolke · Klicken für Punkte, Doppelklick oder Enter zum Beenden' },
{ name: 'HATCH', aliases: ['H', 'SCHRAFFUR'], toolId: 'hatch', description: 'Schraffur erstellen', category: 'draw', label: 'Schraffur-Werkzeug aktiv · Fläche wählen' },
// ─── Änderungs-Werkzeuge ───────────────────────────
{ name: 'MOVE', aliases: ['M', 'VERSCHIEBEN'], toolId: 'move', description: 'Elemente verschieben', category: 'modify', label: 'Verschieben · Elemente auswählen, dann Basispunkt klicken' },
{ name: 'COPY', aliases: ['CO', 'KOPIEREN'], toolId: 'copy', description: 'Elemente kopieren', category: 'modify', label: 'Kopieren · Elemente auswählen, dann Basispunkt klicken' },
{ name: 'ROTATE', aliases: ['RO', 'ROTIEREN'], toolId: 'rotate', description: 'Elemente rotieren', category: 'modify', label: 'Rotieren · Elemente auswählen, dann Basispunkt klicken' },
{ name: 'SCALE', aliases: ['SC', 'SKALIEREN'], toolId: 'scale', description: 'Elemente skalieren', category: 'modify', label: 'Skalieren · Elemente auswählen, dann Basispunkt klicken' },
{ name: 'MIRROR', aliases: ['MI', 'SPIEGELN'], toolId: 'mirror', description: 'Elemente spiegeln', category: 'modify', label: 'Spiegeln · Elemente auswählen, dann Spiegellinie klicken' },
{ name: 'TRIM', aliases: ['TR', 'TRIMMEN'], toolId: 'trim', description: 'Elemente trimmen', category: 'modify', label: 'Trimmen · Begrenzungselement klicken, dann zu trimmendes Element' },
{ name: 'EXTEND', aliases: ['EX', 'VERLANGERN'], toolId: 'extend', description: 'Elemente verlängern', category: 'modify', label: 'Verlängern · Begrenzungselement klicken, dann zu verlängerndes Element' },
{ name: 'FILLET', aliases: ['F', 'ABRUNDEN'], toolId: 'fillet', description: 'Elemente abrunden', category: 'modify', label: 'Abrunden · Erstes Element klicken, dann zweites Element' },
{ name: 'OFFSET', aliases: ['O', 'VERSATZ'], toolId: 'offset', description: 'Versatz erstellen', category: 'modify', label: 'Versatz · Element klicken, dann Richtung und Abstand klicken' },
{ name: 'ERASE', aliases: ['E', 'DEL', 'DELETE', 'LOSCHEN'], toolId: 'delete', description: 'Elemente löschen', category: 'modify', label: 'Löschen · Klicken Sie auf zu löschende Elemente' },
// ─── Ansicht ──────────────────────────────────────
{ name: 'SELECT', aliases: ['V', 'AUSWAHL'], toolId: 'select', description: 'Auswahl-Werkzeug', category: 'view', label: 'Auswahl-Werkzeug aktiv' },
{ name: 'PAN', aliases: ['P'], toolId: 'pan', description: 'Pan-Ansicht', category: 'view', label: 'Pan-Werkzeug aktiv' },
{ name: 'ZOOM', aliases: ['Z'], toolId: 'zoom', description: 'Zoom-Ansicht', category: 'view', label: 'Zoom-Werkzeug aktiv' },
{ name: 'GRID', aliases: ['G', 'GRID'], toolId: null, description: 'Grid ein/aus', category: 'view', label: 'Grid ein/aus' },
{ name: 'ORTHO', aliases: ['OR'], toolId: null, description: 'Ortho-Modus ein/aus', category: 'view', label: 'Ortho-Modus ein/aus' },
{ name: 'SNAP', aliases: ['SN'], toolId: null, description: 'Snap ein/aus', category: 'view', label: 'Snap ein/aus' },
// ─── Meta-Befehle ─────────────────────────────────
{ name: 'UNDO', aliases: ['U'], toolId: null, description: 'Rückgängig', category: 'meta', label: 'Rückgängig: letzte Aktion' },
{ name: 'REDO', aliases: ['RE'], toolId: null, description: 'Wiederherstellen', category: 'meta', label: 'Wiederherstellen: letzte Aktion' },
{ name: 'GROUP', aliases: ['GRP'], toolId: null, description: 'Gruppe erstellen', category: 'meta', label: 'Gruppe erstellt' },
{ name: 'UNGROUP', aliases: ['UNG'], toolId: null, description: 'Gruppe auflösen', category: 'meta', label: 'Gruppe aufgelöst' },
{ name: 'SAVE', aliases: ['S', 'SPEICHERN'], toolId: null, description: 'Projekt speichern', category: 'meta', label: 'Projekt gespeichert' },
{ name: 'NEW', aliases: ['N', 'NEU'], toolId: null, description: 'Neues Projekt', category: 'meta', label: 'Neues Projekt' },
{ name: 'OPEN', aliases: ['OP', 'OFFNEN'], toolId: null, description: 'Projekt öffnen', category: 'meta', label: 'Projekt öffnen' },
{ name: 'IMPORT', aliases: ['IMP', 'I'], toolId: null, description: 'Datei importieren (DXF, SVG, JSON)', category: 'meta', label: 'Datei importieren' },
{ name: 'EXPORT', aliases: ['EXP', 'EX'], toolId: null, description: 'Export als DXF, SVG, PDF, PNG, JSON', category: 'meta', label: 'Export starten' },
// ─── Spezielle Befehle ────────────────────────────
{ name: 'BESTUHLUNG', aliases: ['BEST', 'SEATING'], toolId: null, description: 'Bestuhlung automatisch generieren', category: 'special', label: 'Bestuhlung-Modus' },
{ name: 'BLOCK', aliases: ['B', 'BLOCK'], toolId: null, description: 'Block erstellen', category: 'special', label: 'Block-Erstellung' },
{ name: 'TISCH', aliases: ['TAB', 'TABLE'], toolId: null, description: 'Tisch platzieren', category: 'special', label: 'Tisch-Werkzeug' },
{ name: 'BUHNE', aliases: ['BU', 'STAGE'], toolId: null, description: 'Bühne platzieren', category: 'special', label: 'Bühnen-Werkzeug' },
{ name: 'KI', aliases: ['AI', 'COPilot'], toolId: null, description: 'KI Copilot öffnen', category: 'special', label: 'KI Copilot' },
];
/** Alle Befehle als Map: Schlüssel = NAME + Aliasse (alle Großbuchstaben) */
const commandMap: Map<string, CommandDefinition> = new Map();
for (const cmd of commands) {
commandMap.set(cmd.name, cmd);
for (const alias of cmd.aliases) {
commandMap.set(alias.toUpperCase(), cmd);
}
}
export class CommandRegistry {
/** Alle Befehle zurückgeben */
getAllCommands(): CommandDefinition[] {
return commands;
}
/** Befehl nach Name oder Alias suchen */
lookup(input: string): CommandDefinition | null {
const upper = input.trim().toUpperCase();
return commandMap.get(upper) ?? null;
}
/** Tool-ID für Befehl suchen */
getToolId(input: string): string | null {
const cmd = this.lookup(input);
return cmd?.toolId ?? null;
}
/** Label für Befehl suchen */
getLabel(input: string): string | null {
const cmd = this.lookup(input);
return cmd?.label ?? null;
}
/**
* Autovervollständigung: Sucht Befehle die mit dem Input beginnen.
* Gibt sortierte Liste zurück (max. 10 Einträge).
*/
autocomplete(input: string): CommandDefinition[] {
const upper = input.trim().toUpperCase();
if (upper.length === 0) return [];
const matches = new Map<string, { cmd: CommandDefinition; priority: number }>();
for (const cmd of commands) {
let priority = -1;
if (cmd.name === upper) priority = 0;
else if (cmd.aliases.some(a => a.toUpperCase() === upper)) priority = 1;
else if (cmd.name.startsWith(upper)) priority = 2;
else if (cmd.aliases.some(a => a.toUpperCase().startsWith(upper))) priority = 3;
if (priority >= 0) {
const existing = matches.get(cmd.name);
if (!existing || priority < existing.priority) {
matches.set(cmd.name, { cmd, priority });
}
}
}
return Array.from(matches.values())
.sort((a, b) => a.priority - b.priority || a.cmd.name.localeCompare(b.cmd.name))
.slice(0, 10)
.map(m => m.cmd);
}
/** Alle Befehlsnamen + Aliasse für Autovervollständigung */
getAllNames(): string[] {
const names: string[] = [];
for (const cmd of commands) {
names.push(cmd.name);
names.push(...cmd.aliases);
}
return names.map(n => n.toUpperCase());
}
}
/** Singleton-Instanz */
let registryInstance: CommandRegistry | null = null;
export function getCommandRegistry(): CommandRegistry {
if (!registryInstance) {
registryInstance = new CommandRegistry();
}
return registryInstance;
}