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:
+37
-11
@@ -871,6 +871,19 @@ export default function App() {
|
|||||||
void engineTick;
|
void engineTick;
|
||||||
const engineView = engine.view();
|
const engineView = engine.view();
|
||||||
const commandActive = engineView.active;
|
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
|
// Live-Echo des Befehlszeilen-Texts fürs Cursor-HUD: der getippte Wert
|
||||||
// erscheint sofort im aktiven Tab-Feld am Cursor (VW-Verhalten).
|
// erscheint sofort im aktiven Tab-Feld am Cursor (VW-Verhalten).
|
||||||
const [cmdTyped, setCmdTyped] = useState("");
|
const [cmdTyped, setCmdTyped] = useState("");
|
||||||
@@ -1037,12 +1050,19 @@ export default function App() {
|
|||||||
return () => window.removeEventListener("keydown", onKey);
|
return () => window.removeEventListener("keydown", onKey);
|
||||||
}, [undo, redo]);
|
}, [undo, redo]);
|
||||||
|
|
||||||
// Nummern-Shortcuts für Zeichenwerkzeuge (Vectorworks-Stil): 2 Linie, 4
|
// Nummern-Shortcuts für Zeichenwerkzeuge (Vectorworks-Stil): 1 Text, 2 Linie,
|
||||||
// Rechteck, 5 Polylinie, 6 Wand, 7 Decke, 8 Fenster, 9 Türe, 0 Raum. Nur auf
|
// 3 Kreis, 4 Rechteck, 5 Polylinie, 6 Wand, 7 Decke, 8 Fenster, 9 Türe, 0 Raum.
|
||||||
// Geschoss-Tabs, nicht beim Tippen in Feldern und nicht mit Modifikator
|
// Nur auf Geschoss-Tabs, nicht mit Modifikator (Ctrl/Cmd/Alt bleiben frei).
|
||||||
// (Ctrl/Cmd/Alt bleiben frei). 1 (Text) und 3 (Kreis) sind bewusst noch
|
// Direkt nach dem Setzen eines Punkts (z. B. „Startpunkt angeben") steht der
|
||||||
// unbelegt — dafür fehlt bislang ein Werkzeug. Der Handler wird einmal
|
// Fokus schon im Befehlsfeld (onSelectTool fokussiert es) — trotzdem soll die
|
||||||
// registriert und liest die aktuelle Auswahl-Funktion/Ebenen-Art über ein Ref.
|
// 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({
|
const toolShortcutRef = useRef({
|
||||||
onSelectTool,
|
onSelectTool,
|
||||||
floor: activeLevel.kind === "floor",
|
floor: activeLevel.kind === "floor",
|
||||||
@@ -1053,7 +1073,9 @@ export default function App() {
|
|||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const MAP: Record<string, ToolId> = {
|
const MAP: Record<string, ToolId> = {
|
||||||
|
"1": "text",
|
||||||
"2": "line",
|
"2": "line",
|
||||||
|
"3": "circle",
|
||||||
"4": "rect",
|
"4": "rect",
|
||||||
"5": "polyline",
|
"5": "polyline",
|
||||||
"6": "wall",
|
"6": "wall",
|
||||||
@@ -1065,11 +1087,15 @@ export default function App() {
|
|||||||
const onKey = (e: KeyboardEvent) => {
|
const onKey = (e: KeyboardEvent) => {
|
||||||
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
||||||
const el = e.target as HTMLElement | null;
|
const el = e.target as HTMLElement | null;
|
||||||
if (
|
const isInput =
|
||||||
el &&
|
!!el && (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable);
|
||||||
(el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable)
|
if (isInput) {
|
||||||
) {
|
const isCmdLineInput = el.classList.contains("cmdline-input");
|
||||||
return;
|
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];
|
const id = MAP[e.key];
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
|
|||||||
@@ -168,6 +168,17 @@ export class CommandEngine {
|
|||||||
return this.currentFields().length > 0;
|
return this.currentFields().length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erwartet der aktuelle Schritt freien Text (z. B. das Textwerkzeug-Label)?
|
||||||
|
* Dort ist JEDE Taste — auch Ziffern — literaler Inhalt, im Unterschied zu
|
||||||
|
* einem reinen Punkt-Pick-Schritt (nur „point"/„number", keine Felder), wo
|
||||||
|
* Ziffern ansonsten ungenutzt sind.
|
||||||
|
*/
|
||||||
|
acceptsFreeText(): boolean {
|
||||||
|
if (!this.command || !this.state) return false;
|
||||||
|
return this.command.accepts(this.state).includes("text");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setzt den Feld-Zustand zurück, wenn der Schritt wechselt — Signatur =
|
* Setzt den Feld-Zustand zurück, wenn der Schritt wechselt — Signatur =
|
||||||
* phase + Feld-IDs + lastPoint. Der lastPoint-Teil sorgt dafür, dass ein
|
* phase + Feld-IDs + lastPoint. Der lastPoint-Teil sorgt dafür, dass ein
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ export interface CommandLineHandle {
|
|||||||
* Zeichnen, ohne dass das Feld fokussiert war): fokussiert + setzt den Text.
|
* Zeichnen, ohne dass das Feld fokussiert war): fokussiert + setzt den Text.
|
||||||
*/
|
*/
|
||||||
beginTyping: (seed: string) => void;
|
beginTyping: (seed: string) => void;
|
||||||
|
/**
|
||||||
|
* Gibt den Eingabefokus frei (z. B. wenn ein Befehl fertig ist), damit die
|
||||||
|
* nächste Zifferntaste sofort wieder das nächste Werkzeug wählt statt im
|
||||||
|
* Eingabefeld zu landen (Vectorworks-Verhalten: kein Esc nötig zwischen zwei
|
||||||
|
* Werkzeugen).
|
||||||
|
*/
|
||||||
|
blur: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CommandLine = forwardRef<CommandLineHandle, CommandLineProps>(
|
export const CommandLine = forwardRef<CommandLineHandle, CommandLineProps>(
|
||||||
@@ -87,6 +94,7 @@ export const CommandLine = forwardRef<CommandLineHandle, CommandLineProps>(
|
|||||||
setText(seed);
|
setText(seed);
|
||||||
inputRef.current?.focus();
|
inputRef.current?.focus();
|
||||||
},
|
},
|
||||||
|
blur: () => inputRef.current?.blur(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Autocomplete nur im Ruhezustand (Befehlsname tippen), nicht in einem Schritt.
|
// Autocomplete nur im Ruhezustand (Befehlsname tippen), nicht in einem Schritt.
|
||||||
|
|||||||
Reference in New Issue
Block a user