2D: Enter in der Befehlszeile bestätigt Punkt-Griff jetzt auch ohne neuen Wert
Nutzer-Report: Enter sollte den Punkt gemäss Maus-/Feld-Stand platzieren
("die Maus steuert bis man Werte eingibt, dann übernimmt es im Feld den
aktuellen Wert, man kann eigene Werte per Tab eingeben") -- aber Enter
tat nach dem Tippen eines Werts (oder auch ganz ohne Tippen) nichts.
Ursache: die Befehlszeile fokussiert sich selbst, sobald man Tab drückt
(Feld-Controller öffnen). Der GLOBALE Enter/Escape-Tastatur-Handler aus
dem vorigen Commit überspringt bewusst fokussierte Eingabefelder (damit
er sich nicht mit der Befehlszeilen-eigenen Enter-Behandlung beisst) --
aber die Befehlszeile selbst kannte für die Griff-Bearbeitung nur den
Fall "Text eingetippt, als Zahl geparst" (submitGripEditValue). Bei
LEERER Eingabe (Enter ohne neuen Wert -- der Normalfall, wenn man nur
bestätigen will) geschah dadurch schlicht nichts.
Fix: PlanViewHandle bekommt eine neue Methode confirmGripEdit() (liest
den bewaffneten Griff aus der lokalen gripDrag-Ref, ruft
gripHandlers.onGripEnd() -- dieselbe Aktion wie ein bestätigender Klick
auf der Zeichenfläche). Die Befehlszeilen-Eingabe in App.tsx ruft sie
jetzt bei leerem/nicht parsbarem Text während der Griff-Bearbeitung auf.
Da das Imperativ-Handle mit leeren Deps memoisiert ist (stabil für die
Oberleiste), braucht es einen frischen gripHandlersRef-Spiegel statt die
gripHandlers-Prop direkt zu schließen (sonst stale closure vom ersten
Render).
This commit is contained in:
@@ -111,6 +111,14 @@ export interface PlanViewHandle {
|
||||
* Leere Punktmenge → No-op (kein Fit, kein Crash).
|
||||
*/
|
||||
fitBounds: (pts: Vec2[]) => void;
|
||||
/**
|
||||
* Einen bewaffneten Punkt-Griff (s. gripDrag) an seiner AKTUELLEN Position
|
||||
* abschließen — dieselbe Aktion wie ein bestätigender Klick/Enter auf der
|
||||
* Zeichenfläche, aber von der Befehlszeile aus angestoßen (Enter dort MIT
|
||||
* leerem Eingabetext: kein neuer Wert zu locken, nur „fertig, so lassen").
|
||||
* No-op ohne bewaffneten Griff.
|
||||
*/
|
||||
confirmGripEdit: () => void;
|
||||
}
|
||||
|
||||
/** Ergebnis eines Links-Klicks (Auswahl) an einer Modellposition. */
|
||||
@@ -707,12 +715,28 @@ export const PlanView = forwardRef<PlanViewHandle, PlanViewProps>(
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [resetKey]);
|
||||
|
||||
// Frischer Spiegel der gripHandlers-Prop für das (unten stabil mit leeren
|
||||
// Deps memoisierte) Imperativ-Handle — direkt referenzieren würde die Prop
|
||||
// vom ERSTEN Render einfrieren (stale closure, s. Kommentar dort).
|
||||
const gripHandlersRef = useRef(gripHandlers);
|
||||
gripHandlersRef.current = gripHandlers;
|
||||
|
||||
// Imperatives Steuerhandle für die Oberleiste (Einpassen / Auswahl / Massstab).
|
||||
// Stabil (leere Deps); liest den frischen Ausschnitt + die Auswahl aus Refs.
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
fit: () => setView(defaultViewRef.current),
|
||||
confirmGripEdit: () => {
|
||||
// Von der Befehlszeile aus angestoßen (Enter mit leerem Eingabetext,
|
||||
// s. App.tsx) — dieselbe Aktion wie ein bestätigender Klick auf der
|
||||
// Zeichenfläche (siehe onPointerDown-Kopf unten), nur eben nicht über
|
||||
// ein Pointer-Event.
|
||||
if (gripDrag.current) {
|
||||
gripDrag.current = null;
|
||||
gripHandlersRef.current?.onGripEnd();
|
||||
}
|
||||
},
|
||||
fitSelection: () => {
|
||||
const sel = selectedRef.current;
|
||||
const prim = sel !== null ? planRef.current.primitives[sel] : undefined;
|
||||
|
||||
Reference in New Issue
Block a user