2D: Text/Textspalte auf Inline-Editing direkt auf der Zeichenfläche umgestellt
Nutzer-Report: Textfelder waren nicht mehrzeilig. Ursache: die Text-/ Textspalte-Werkzeuge holten ihre Eingabe über die Befehlszeile (CommandLine.tsx) — ein einzeiliges <input>, Enter committet sofort, kein Zeilenumbruch möglich. Das betraf auch "Textspalte", obwohl die explizit für mehrzeiligen Wortumbruch gedacht ist. Lösung (Nutzer-Vorgabe: kein Dialog, direktes Editieren auf der Fläche wie im Layout-System): text.ts/textbox.ts committen nach dem Platzieren (Anker bzw. Anker+Breite) sofort ein LEERES Text-Element und melden `focusDrawingId` — dafür CommandResult/EngineHost um einen Passthrough erweitert (engine.ts applyResult ruft host.focusDrawing(id)). App.tsx setzt darauf Auswahl + editTextId (dieselbe State-Variable wie beim bisherigen Doppelklick-Editieren). PlanView rendert bei gesetztem editTextId jetzt einen RichTextEditor-Overlay direkt über dem Element (position:fixed via vbToClient/toScreen, eigene Mini-Toolbar erscheint darüber) statt des bisherigen TextEditorDialog-Modals — Prinzip 1:1 vom Layout-Blatt-Inline- Editor (LayoutSheet.tsx) übernommen. Die neuen Props (editTextId/ onCommitTextEdit/onCloseTextEdit) laufen durch Content/LevelPlanView/ SectionPlanView (viewportContent.tsx) bis zu PlanView durch. Verhalten der beiden Werkzeuge (Nutzer-Vorgabe): "text" bleibt ohne Wortumbruch (kein `width`) — Enter erzeugt weitere Zeilen, aber keine automatische Breite. "textbox" setzt `width` und verhält sich damit wie ein InDesign-Textrahmen (echter Wortumbruch live beim Tippen, kein reines Render-Detail mehr). commitTextEdit (useMouseSelectionHandlers.ts) schreibt jetzt bei JEDEM Tastendruck (kein Guard mehr gegen leeren Text — nötig, damit Löschen bis auf null Zeichen sich sofort spiegelt); neues closeTextEdit räumt ein beim Schliessen noch leeres Element auf (verhindert Leichen bei abgebrochener Neuerstellung). 4 neue Tests (text/textbox: sofortiger Commit + focusDrawingId). tsc -b / vitest run (918/918) / npm run build grün. Rendering/Positionierung des Overlays selbst nicht automatisiert testbar — Nutzer prüft visuell in der Tauri-App.
This commit is contained in:
+28
-18
@@ -796,6 +796,25 @@ export default function App() {
|
||||
setDraft: (d) => cmdLatest.current.setDraft(d),
|
||||
commit: (mutate) => cmdLatest.current.setProject(mutate),
|
||||
isFloor: () => cmdLatest.current.activeLevel.kind === "floor",
|
||||
// Frisch über `text`/`textbox` erzeugtes Element sofort inline editieren
|
||||
// (kein Lookup nötig — der Commit hat es bereits angehängt, s. engine.ts
|
||||
// applyResult-Reihenfolge commit→focusDrawing). Auswahl-Löschen wie
|
||||
// onEditDrawingText (useMouseSelectionHandlers.ts), damit kein anderes
|
||||
// Element gleichzeitig markiert bleibt.
|
||||
focusDrawing: (id) => {
|
||||
setSelectedWallIds([]);
|
||||
setSelectedCeilingIds([]);
|
||||
setSelectedOpeningIds([]);
|
||||
setSelectedStairIds([]);
|
||||
setSelectedRoomIds([]);
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedContextObjectIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
setSelectedDrawingId(id);
|
||||
setEditTextId(id);
|
||||
},
|
||||
};
|
||||
engineRef.current = new CommandEngine(host);
|
||||
}
|
||||
@@ -2226,6 +2245,7 @@ export default function App() {
|
||||
onOpenStampEditor,
|
||||
onEditDrawingText,
|
||||
commitTextEdit,
|
||||
closeTextEdit,
|
||||
onPlanSelect,
|
||||
onPlanMarquee,
|
||||
onPlanContextMenu,
|
||||
@@ -2715,6 +2735,9 @@ export default function App() {
|
||||
onStampMove={moveRoomStamp}
|
||||
onStampEdit={onOpenStampEditor}
|
||||
onEditDrawingText={onEditDrawingText}
|
||||
editTextId={editTextId}
|
||||
onCommitTextEdit={commitTextEdit}
|
||||
onCloseTextEdit={closeTextEdit}
|
||||
onPlanSelect={onPlanSelect}
|
||||
onPlanMarquee={onPlanMarquee}
|
||||
onSegmentCut={onSegmentCut}
|
||||
@@ -3022,24 +3045,11 @@ export default function App() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Rich-Text-Editor: per Doppelklick auf ein Text-2D-Element geöffnet (wie
|
||||
beim Raum-Stempel) — mehrere Absätze, gemischte Formatierung pro
|
||||
Zeichen (InDesign-/Affinity-artig). Alt-Elemente ohne `doc` starten
|
||||
aus ihrem bisherigen String + einheitlichen `marks`. */}
|
||||
{editTextId &&
|
||||
(() => {
|
||||
const d = project.drawings2d.find((x) => x.id === editTextId);
|
||||
if (!d || d.geom.shape !== "text") return null;
|
||||
const g = d.geom;
|
||||
const doc = g.doc ?? docFromText(g.text, g.marks ?? {});
|
||||
return (
|
||||
<TextEditorDialog
|
||||
value={doc}
|
||||
onApply={commitTextEdit}
|
||||
onCancel={() => setEditTextId(null)}
|
||||
/>
|
||||
);
|
||||
})()}
|
||||
{/* Inline-Text-Editor für Drawing2D-Text (`editTextId`) rendert PlanView
|
||||
jetzt direkt auf der Zeichenfläche (kein Dialog mehr, Nutzer-Wunsch —
|
||||
gleiches Prinzip wie der Layout-Blatt-Inline-Editor). Ausgelöst über
|
||||
`text`/`textbox` (sofort nach Platzieren, s. host.focusDrawing) oder
|
||||
Doppelklick auf ein bestehendes Element (onEditDrawingText). */}
|
||||
|
||||
{/* Text-Editor (schwebendes Fenster): Doppelklick auf einen Raumstempel bzw.
|
||||
Button in der Objekt-Info öffnet ihn. „Übernehmen" schreibt das
|
||||
|
||||
Reference in New Issue
Block a user