Zeichenwerkzeug-Zifferntasten: 1 (Text) und 3 (Kreis) fehlten in der

Shortcut-Map, obwohl beide Befehle längst fertig implementiert waren.

Zusätzlich musste man nach jedem gesetzten Punkt Esc drücken, bevor eine
Zifferntaste das nächste Werkzeug wählte — der Fokus blieb im Befehlsfeld
hängen (dort wird nach Abschluss nicht mehr geblurred) und die globale
Kürzel-Prüfung ignorierte jede Eingabe im Feld pauschal. Jetzt gibt die
Engine den Fokus frei, sobald ein Befehl fertig ist (Commit/Abbruch), und
eine Zifferntaste wählt direkt das nächste Werkzeug (Vectorworks-Stil) —
aber nur, wenn das Feld leer ist UND der aktuelle Schritt weder Tab-Felder
noch Freitext erwartet (Textlabel-Eingabe wie „Raum 101" bleibt geschützt).
This commit is contained in:
2026-07-31 17:00:57 +02:00
parent 1ba6f7bcf4
commit 31fe93c122
3 changed files with 56 additions and 11 deletions
+37 -11
View File
@@ -871,6 +871,19 @@ export default function App() {
void engineTick;
const engineView = engine.view();
const commandActive = engineView.active;
// Fokus wieder freigeben, sobald ein Befehl fertig ist (Commit ODER Abbruch):
// beim Start wird das Befehlsfeld fokussiert (onSelectTool), bliebe es das
// auch danach, würde die nächste Zifferntaste im (inaktiven) Feld landen
// statt beim globalen Werkzeug-Kürzel anzukommen — Esc wäre nötig. Mit dem
// Blur bei aktiv→inaktiv wählt man wie in Vectorworks sofort das nächste
// Werkzeug per Zifferntaste, ohne dazwischen Esc zu drücken.
const prevCommandActiveRef = useRef(commandActive);
useEffect(() => {
if (prevCommandActiveRef.current && !commandActive) {
commandLineRef.current?.blur();
}
prevCommandActiveRef.current = commandActive;
}, [commandActive]);
// Live-Echo des Befehlszeilen-Texts fürs Cursor-HUD: der getippte Wert
// erscheint sofort im aktiven Tab-Feld am Cursor (VW-Verhalten).
const [cmdTyped, setCmdTyped] = useState("");
@@ -1037,12 +1050,19 @@ export default function App() {
return () => window.removeEventListener("keydown", onKey);
}, [undo, redo]);
// Nummern-Shortcuts für Zeichenwerkzeuge (Vectorworks-Stil): 2 Linie, 4
// Rechteck, 5 Polylinie, 6 Wand, 7 Decke, 8 Fenster, 9 Türe, 0 Raum. Nur auf
// Geschoss-Tabs, nicht beim Tippen in Feldern und nicht mit Modifikator
// (Ctrl/Cmd/Alt bleiben frei). 1 (Text) und 3 (Kreis) sind bewusst noch
// unbelegt — dafür fehlt bislang ein Werkzeug. Der Handler wird einmal
// registriert und liest die aktuelle Auswahl-Funktion/Ebenen-Art über ein Ref.
// Nummern-Shortcuts für Zeichenwerkzeuge (Vectorworks-Stil): 1 Text, 2 Linie,
// 3 Kreis, 4 Rechteck, 5 Polylinie, 6 Wand, 7 Decke, 8 Fenster, 9 Türe, 0 Raum.
// Nur auf Geschoss-Tabs, nicht mit Modifikator (Ctrl/Cmd/Alt bleiben frei).
// Direkt nach dem Setzen eines Punkts (z. B. „Startpunkt angeben") steht der
// Fokus schon im Befehlsfeld (onSelectTool fokussiert es) — trotzdem soll die
// nächste Zifferntaste OHNE Esc gleich das nächste Werkzeug wählen, wie in
// Vectorworks. Das ist nur sicher, wenn dort gerade nichts Sinnvolles getippt
// werden könnte: das Feld ist noch leer UND der Schritt hat weder Tab-Felder
// (Länge/Winkel/Radius, hasFields()) noch erwartet er Freitext (Text-Label,
// acceptsFreeText()) — sonst wäre die Ziffer selbst Nutzinhalt (z. B. „Raum
// 101" oder eine getippte Koordinate) und darf nicht als Werkzeugwechsel
// verschluckt werden. Der Handler wird einmal registriert und liest die
// aktuelle Auswahl-Funktion/Ebenen-Art über ein Ref.
const toolShortcutRef = useRef({
onSelectTool,
floor: activeLevel.kind === "floor",
@@ -1053,7 +1073,9 @@ export default function App() {
};
useEffect(() => {
const MAP: Record<string, ToolId> = {
"1": "text",
"2": "line",
"3": "circle",
"4": "rect",
"5": "polyline",
"6": "wall",
@@ -1065,11 +1087,15 @@ export default function App() {
const onKey = (e: KeyboardEvent) => {
if (e.ctrlKey || e.metaKey || e.altKey) return;
const el = e.target as HTMLElement | null;
if (
el &&
(el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable)
) {
return;
const isInput =
!!el && (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable);
if (isInput) {
const isCmdLineInput = el.classList.contains("cmdline-input");
const empty = isCmdLineInput && (el as HTMLInputElement).value === "";
const eng = engineRef.current;
const cmdLineFreeToSwitch =
empty && !eng?.hasFields() && !eng?.acceptsFreeText();
if (!cmdLineFreeToSwitch) return;
}
const id = MAP[e.key];
if (!id) return;