User: Doppelklick auf DOSSIER-Text oeffnet weiterhin Rhinos Editor.
Verschiedene Groessen im Editor erscheinen nicht in Rhino.
Doppelklick-Hook (rhino/text_editor.py):
- _DossierTextDoubleClickHook subklassiert Rhino.UI.MouseCallback.
OnMouseDoubleClick prueft selektierte TextEntities auf UserString
"dossier_text"="1" und cancelled das Event (= blockt Rhinos
Standard-TextEdit-Dialog), setzt sticky["dossier_pending_text_edit"]
mit der Obj-ID
- _on_idle_check_pending_edit (RhinoApp.Idle event): nimmt sticky-ID
auf naechstem Idle-Tick und ruft open_for_edit(obj) — defer noetig
weil Eto-Form aus MouseCallback heraus oeffnen Re-Entrancy macht
- _ensure_double_click_hook() installiert Hook + Idle-Handler einmalig
pro Rhino-Session (idempotent)
- startup.py ruft das jetzt direkt nach Modul-Load auf
Edit-Mode (open_for_edit):
- Liest aus bestehendem TextEntity die Settings (Font, Size, Bold,
Italic, Underline, Align) + PlainText
- Frame fuer Dialog-Positionierung aus BBox abgeleitet
- TextEditorBridge mit edit_obj_id + initial_text gestartet
- INIT-Payload um initialText + editMode erweitert
- COMMIT: bei edit_obj_id gesetzt → doc.Objects.Replace statt AddText.
Plane wird vom Original uebernommen wenn keine explizite Rotation,
damit der Text an seinem Platz bleibt
Frontend (TextEditorApp.jsx):
- Bei INIT mit initialText: editor.innerText wird damit befuellt
- htmlToRuns extrahiert font-size in Pixel pro Run (inline style oder
computed style != base)
- baseCtx _basePx aus computed style des Editor-divs
Size-Mapping (rhino/text_editor.py _runs_to_rtf):
- fontSizePx in Runs triggert non-trivial (RTF wird generiert)
- Pro Run: \fs in Halb-Punkten = 20 * (run_px / 14_base_px) round
- 14px = \fs20 (1.0× TextEntity.TextHeight)
- 21px = \fs30 (1.5×)
- 28px = \fs40 (2.0×)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User-Wunsch: vorgespeicherte Stile (Heading, Paragraph Helvetica/Georgia)
direkt im Editor anwendbar.
Backend (text_create.py):
- _DEFAULT_STYLES: 7 sinnvolle Architektur-Defaults — Titel (0.40m bold),
Heading 1 (0.30m bold), Heading 2 (0.20m bold), Paragraph Helvetica
(0.15m), Paragraph Georgia (0.15m Georgia), Notiz (0.10m italic),
Bildlegende (0.08m italic)
- list_styles: seedet die Defaults beim ersten Zugriff falls noch keine
Styles im Doc existieren (analog mass_style)
- Bestehende save_style/delete_style/apply_style funktionieren weiter
Backend (text_editor.py):
- INIT-Payload erweitert um styles[] (Liste aller verfuegbaren Stile
mit id/name/font/size/bold/italic/underline/align)
Frontend (TextEditorApp.jsx):
- Neuer Stil-Picker als erstes Dropdown in Toolbar-Row 1 (150px)
- Optionen: "— Stil wählen —" + alle verfuegbaren Stile
- onChange: applyStyle(style) — setzt Toolbar-State + appliziert via
execCommand auf die aktuelle Selektion im WYSIWYG-Editor (oder als
Default fuer kommendes Tippen wenn keine Selektion)
- queryCommandState-Check fuer Bold/Italic/Underline damit nur toggled
wird wenn nicht schon im gewuenschten State
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User-Wunsch: eigener WYSIWYG-Editor im React/Topbar-GUI-Stil. Topmost.
Verschiedene Schriftarten/-Dicken sichtbar im Editor selbst.
Neues Backend (rhino/text_editor.py):
- TextEditorBridge mit Frame-Daten im Konstruktor, INIT-Push mit
Settings + Font-Liste, COMMIT erstellt TextEntity, CANCEL schliesst
- open_with_frame(p1, p2, origin, width, height): oeffnet Satellite-
Window mit mode='text_editor' + topmost=True
- panel_base.open_satellite_window: neuer Parameter topmost (default
False) der form.Topmost setzt
text_create.create_text: ruft jetzt text_editor.open_with_frame nach
dem Frame-Pick. Eto-basierter _dossier_text_editor bleibt im Modul als
Fallback aber wird nicht mehr verwendet.
Neues Frontend (src/TextEditorApp.jsx, mode='text_editor'):
- Layout im DOSSIER-Topbar-Stil (dunkle Pills, accent on hover)
- Pill-Helper-Komponente fuer alle Toggle/Action-Buttons
- Dropdown-Helper fuer Font + Size
- Toolbar Row 1: Font-Dropdown | Size-Dropdown | Color-Picker | Layer-Reset
- Toolbar Row 2: B/I/U mit Material-Icons | L/C/R Align | x²/x₂ Sup/Sub
- Sonderzeichen-Palette: 41 Unicode-Symbole (Architektur/Math/Pfeile/
Auszeichnungen), Klick inserted am Cursor
- WYSIWYG-Editor: contentEditable div mit fontFamily=ausgewaehlt,
textAlign=ausgewaehlt — Format-Toolbar wirkt via document.execCommand
(bold/italic/underline/justifyLeft/Center/Right/superscript/subscript/
fontName/foreColor)
- "Einfuegen" sendet COMMIT mit text (innerText) + settings
- "Abbrechen" CANCEL → Bridge schliesst Form
Phase 1 Limitation: rendert in Rhino als PlainText mit den globalen
Settings (font/size/bold/italic/align/color) — verschiedene Schriftarten
INNERHALB des Texts sind im Editor sichtbar aber nicht im finalen
Rhino-TextEntity. Phase 2: HTML → Rhino RichText/RTF Mapping.
rhinoBridge.js: send() jetzt exportiert (war intern) damit
TextEditorApp generisch COMMIT/CANCEL senden kann.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1. Dialog-Positionierung: vp.WorldToScreen existiert nicht auf dieser
Rhino-Version. Ersetzt durch vp.WorldToClient → System.Drawing.Point
(viewport-lokale Pixel) + view.ScreenRectangle fuer absolute Position.
→ Dialog poppt jetzt wirklich neben dem Frame statt random.
2. TextArea-Hoehe: DynamicLayout expandiert die TextArea nicht
zuverlaessig (zeigte sich als 1-Zeilen-Streifen mit Buttons riesig
daneben). Fix: ta.Size = drawing.Size(...) explizit setzen.
3. 5-arg Font(face, FontWeight, FontStyle, underline, strike): Python.NET
3.0 erlaubt keinen bool→Enum-Cast mehr (Log: "int can not be converted
to Enum implicitly"). Fix: echte Enums Rhino.DocObjects.Font.FontWeight.
Bold/Normal + FontStyle.Italic/Upright benutzen. Damit funktioniert
auch Underline-Support endlich.
apply_settings_to_selection: kompletter Rewrite — statt Duplicate-Modify
wird eine FRESH TextEntity gebaut + alle Properties (Plane, PlainText,
TextHeight, Font, Align) gesetzt + per Replace eingebunden. DimStyle
wird auf Guid.Empty entkoppelt damit nicht die Style das Font-Setting
ueberschreibt. Sollte Bold/Italic-Un-Toggle-Bug fixen.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User: Frame wird gezeichnet aber Editor erscheint nicht — kann nicht
schreiben. Eto.Form mit WindowStyle.None + Form.Show() funktioniert auf
Mac WebKit/Rhino-Build nicht zuverlaessig (kein Render oder hinter Rhino-
Window).
Fix: Eto.Dialog mit ShowModal — laeuft proven auf Mac+Windows. Dialog
hat normale Chrome (Title-Bar, OK/Cancel-Buttons) aber wird neben dem
gepickten Frame positioniert (via vp.WorldToScreen + view.ScreenRectangle
→ Dialog.Location 20px rechts vom Frame). Tradeoff zu "inline im
Viewport": Dialog hat Rahmen, aber ist sichtbar und funktional.
Workflow: pick Frame → Dialog poppt neben Frame mit TextArea + OK/Cancel
+ Cmd/Ctrl+Enter Shortcut + Esc-Abbruch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User-Wunsch:
- Rechteck als Frame statt 2-Punkte-Linie picken
- Direkt im Viewport schreiben statt zentrierter Dialog
- Bold/Italic/Underline echt anwendbar
Aenderungen:
_pick_text_frame: DynamicDraw-Event auf GetPoint zeichnet Live-
Rechteck-Vorschau in petrol-accent waehrend User die 2. Ecke picked
(analog Rhinos _Rectangle). Returns jetzt (p1, p2, origin, w, h).
_inline_editor (neu, ersetzt _frame_editor_dialog): chromeloses
Eto.Form (WindowStyle.None_) absolut positioniert ueber dem gepickten
Frame im Viewport via vp.WorldToScreen + view.ScreenRectangle. TextArea
fuellt den Frame. Cmd+Enter / Ctrl+Enter = commit, Esc = abbrechen.
Look-and-feel: schreibst direkt "im" Feld auf der Arbeitsflaeche.
_apply_font: erweitert um 5-arg Font(face,bold,italic,underline,strike)
Konstruktor als Pfad 1 (falls Rhino-Version das unterstuetzt). Fallback
3-arg Font, FromQuartetProperties, FindOrCreate.
apply_settings_to_selection: vor jedem Font-Set ein PlainText-Reset
damit eventuelle Rich-Text-Formatierungs-Runs nicht das neue te.Font
ueberschreiben — vermutlicher Bold-Toggle-Bug-Fix. Underline jetzt im
patch-Loop mit drin.
read_selection_settings: liest auch font.Underlined wenn vorhanden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User: Bold/Kursiv liessen sich nicht zurueck auf normal stellen.
Diagnose: te.Font.QuartetName kann je nach RhinoCommon-Version den Bold/
Italic-Suffix im Namen mitfuehren (z.B. "Helvetica-Bold"). Dann liest
read_selection_settings face="Helvetica-Bold" → wird in updateTs ans
Backend zurueckgeschickt → _apply_font ruft FindOrCreate("Helvetica-Bold",
False, False) → das matcht intern wieder die Bold-Variante = bleibt fett.
Fix in _apply_font:
- Suffix-Stripping: -Bold, -Italic, -Oblique, -BoldItalic etc. werden vom
face-String entfernt damit nur die Base-Family ("Helvetica") bleibt
- FromQuartetProperties zuerst (konstruiert Font direkt, unabhaengig vom
FontTable-Cache). FindOrCreate als Fallback.
- Diagnostic print: "[TEXT] _apply_font face=... bold=... italic=..."
damit sich nachvollziehen laesst was tatsaechlich angewendet wird
Plus textSettings/textStyles im State-Sig hinzugefuegt damit Idle-Pushes
Aenderungen nicht dedupelt verschlucken.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User-Wunsch: Text-Editor war unfertig — keine Fonts sichtbar, Bold liess
sich nicht entfernen, Size soll Dropdown mit Eigene, Text-Stile noetig,
Unterstrichen + Links/Mitte/Rechts fehlten, schoenere Icons.
Backend (text_create.py):
- DEFAULTS erweitert um underline + align (left/center/right)
- _normalize() validiert Settings (align nur left/center/right)
- Text-Style-Preset-System analog mass_style:
- list_styles / save_style / delete_style / apply_style
- get_active_style_id / set_active_style_id
- doc.Strings["dossier_text_styles"] (JSON list mit id/name + settings)
- doc.Strings["dossier_text_style_active"]
- _apply_align(te, "left"|"center"|"right") setzt TextHorizontalAlignment
- apply_settings_to_selection + create_text rufen _apply_align mit auf
- read_selection_settings liest auch align
- available_fonts mit Fallback-Liste (Helvetica, Arial, Times, etc.) wenn
Rhino.DocObjects.Font.AvailableFontFaceNames leer ist
- underline: in Settings + Styles persistiert, NOCH NICHT visuell
appliziert (braucht TextEntity-RichText-API)
Backend (oberleiste.py):
- Neue Handler APPLY_TEXT_STYLE / SAVE_TEXT_STYLE / DELETE_TEXT_STYLE
- State liefert textStyles + textStyleActiveId
- textFonts jetzt bei jedem _send_state mitgeschickt (vorher one-shot mit
_fonts_sent flag — verlor sich nach Panel-Re-Mount und User sah keine
Fonts mehr)
Frontend (OberleisteApp):
- Text-Block komplett neu gelayoutet (3 Spalten Grid):
Reihe 1: [Style ▼] [Font ▼] [Size ▼]
Reihe 2: [B|I|U] [L|C|R] [+]
- Style-Dropdown mit Optionen "+ Speichern…" und "🗑 Aktiven loeschen"
- Size-Dropdown mit Preset-Werten (0.05/0.10/.../1.00 m) + "Eigene…"
→ toggle zu Custom-Number-Input bei "Eigene"-Auswahl
- B/I/U mit Material-Icons format_bold/italic/underlined statt B/I-Text
- L/C/R Alignment-Buttons mit format_align_left/center/right
- ToggleBtn-Helper-Komponente fuer alle 6 Toggles
- "+" Insert-Button bleibt klein (Icon size 14)
- Accent-Border auf allen Pills wenn Text selektiert (visuelles Feedback
"Aenderungen wirken auf Selektion")
- Bold/Italic/Underline lassen sich jetzt sauber togglen (waren als
proper Booleans serialisiert — vorher Bug evtl. durch fehlende Font-
Liste maskiert)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User-Probleme:
1. Floating Eto-Dialog erschien nicht nach GetPoint (Mac-Bug)
2. UI war zu klobig, sollte vectorworks-mässig kompakt sein, "+" als
kleines Icon-Symbol
3. Selektierten Text aendern war nicht moeglich
Fix 1 — Bug: _floating_input geloescht, ersetzt durch
_prompt_for_text() das Rhino.UI.Dialogs.ShowEditBox benutzt. Nativer
cross-platform Dialog ohne Eto-Modal-Bug. Workflow:
GetPoint → ShowEditBox → AddText. Funktioniert auf Mac.
Fix 2 — UI: Text-Block kompakt umgebaut.
Reihe 1: [Font ▼] | [Size m] (130 + 60 = 196px)
Reihe 2: [B][I][+] segmented pill (gleiche Breite wie Reihe 1)
"+" ist jetzt kleines add-icon (size 13), kein "+ Text" Label mehr.
Fix 3 — Edit-Selection: neue Funktionen in text_create.py:
- _selected_text_objects(doc) → Liste der selektierten TextEntities
- read_selection_settings(doc) → Settings der ersten Selektion
- apply_settings_to_selection(doc, patch) → wendet font/size/bold/italic
auf alle selektierten TextEntities an
oberleiste.SET_TEXT_SETTINGS handler appliziert die Aenderung jetzt
ZUSAETZLICH auf die Selection (wenn vorhanden) — UND speichert als
Default. State enthaelt textSelectionSettings, UI nutzt diese als
Anzeige-Werte wenn vorhanden (Werte spiegeln Selektion live).
Visual: Border-Color der Size/Segmented-Pill wird accent wenn Selection
aktiv ist (Hinweis dass Aenderungen auf Selektion wirken).
Sig-Update: textSelectionSettings + lastSetView in last_state_sig damit
State neu gepusht wird wenn sich Selection/View aendert.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>