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>
UI:
- GeschossManager: Master-Eye + Master-Lock im Header (analog EbenenManager).
Scheren-Button pro Geschoss togglet hasClipping. Auge ganz links wie bei
Ebenen. Eye-Logik klar 4-Wege: aktive Z immer hell+on, in 'active'/'all_force'
fuer non-active gedimmt, sonst spiegelt Flag direkt. Schrift wird NIE gegrayt.
Neuer Mode 'all_force' = "Alle anzeigen" (ignoriert Eye), 'all' jetzt mit
Label "Ausgewaehlte" (respektiert Eye). Klick aufs Auge in 'active'/'all_force'
wechselt automatisch in "Ausgewaehlte" damit Aktion sofort wirkt.
- layer_builder.apply_visibility: neuer z_mode 'all_force' vor visible-Check —
zeigt jede Z auch wenn Eye=false war.
- elemente._cmd_create_oeffnung: gruene Live-Preview (vertikales Oeffnungs-
Rechteck + Breiten-Marker + Diagonale) waehrend Fenster/Tuer-Platzierung
entlang der Wand-Achse. Brueest-Offset aus Geschoss-UK korrekt im Z.
Performance Cold-Start:
- panel_base: Inlined-HTML als Modul-Cache (1x build, n-mal mount). Pro
Panel-Mount nur noch str.replace + LoadHtml. Spart bei 10 Panels 9x
~395 KB Disk-Read + Regex-Pass. Cache-Key = mtime von dist/index.html.
- Timing-Instrumentierung: _t_mark + print_startup_summary. Hook in startup.py
feuert 3s nach Plugin-Load + listet Wall-time, Top-10, Aggregat pro Phase.
- OberleisteBridge: Command-Enumeration (~1000 Commands) jetzt lazy via
Rhino.RhinoApp.Idle statt synchron im __init__. Cold-Start nicht blockiert,
Autocomplete kommt ~1 Frame spaeter.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
OVERRIDES war als gedocktes Panel zu schmal. Jetzt: kein Panel mehr,
sondern ein echtes Rhino-Fenster (Eto.Form + WebView, frei verschieb-
und resizable), das vom Oberleiste-Gear-Button geoeffnet wird.
panel_base.open_satellite_window:
- Akzeptiert jetzt optional einen `bridge`-Parameter. Wenn gegeben,
wird die Custom-Bridge (z.B. OverridesBridge) statt der einfachen
inline SAVE/CANCEL-Bridge benutzt. So koennen vollwertige Panels
(mit bidirektionalem Mess-Verkehr) als Satellite-Fenster laufen.
overrides_panel.py:
- register_and_open entfaellt — Overrides wird nicht mehr als Panel
registriert.
- Neue Funktion open_as_window(): erstellt OverridesBridge, registriert
sie in sticky["overrides_bridge"] und oeffnet als Satellite-Window.
Listener werden lazy beim ersten Aufruf installiert
(_ensure_listeners_once).
oberleiste.py:
- OPEN_OVERRIDES_PANEL ruft jetzt overrides_panel.open_as_window()
statt RhinoUI.Panels.OpenPanel().
OberleisteApp.jsx:
- Settings-Gear (ToolButton mit icon="settings") nach dem Preset-
Dropdown im Overrides-Bereich. Click ruft openOverridesPanel() →
oeffnet das Satelliten-Fenster.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Statt Overlay-im-Panel oeffnet sich der Settings-Dialog jetzt als
echtes Rhino-Fenster (verschiebbar, resizable, mehrere parallel).
Infrastruktur in panel_base.py:
- load_inline akzeptiert jetzt `params` (dict) und injiziert sie
als window.PANEL_PARAMS — Satelliten-Apps lesen ihren initialen
State daraus.
- Neue Funktion open_satellite_window(mode, params, title, size,
on_save, on_cancel): erstellt Eto.Forms.Form mit eingebetteter
WebView, eigenem Inline-Bridge fuer SAVE/CANCEL-Messages, ruft
Callbacks auf und schliesst das Fenster.
Backend rhinopanel.py:
- Neue Message-Handler OPEN_GESCHOSS_SETTINGS und OPEN_EBENEN_SETTINGS.
- _open_geschoss_settings: oeffnet das Satelliten-Fenster mit dem
Geschoss als Payload. on_save: replace im doc.Strings z-Liste +
_apply(save_z=True).
- _open_ebenen_settings: gleich, aber fuer Ebene + hatchPatterns.
Neue React-Entries:
- GeschossSettingsApp.jsx: wrappt GeschossSettingsDialog, liest
window.PANEL_PARAMS, schickt SAVE/CANCEL direkt via document.title-
Bridge.
- EbenenSettingsApp.jsx: gleich fuer EbenenSettingsDialog.
main.jsx-Switch erweitert um 'geschoss_settings' und 'ebenen_settings'.
GeschossManager und EbenenManager:
- Inline-Dialog-State und -Rendering entfernt.
- onSettings ruft jetzt openGeschossSettings(z) / openEbenenSettings(e)
in der Bridge auf → Backend oeffnet das Satelliten-Fenster.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stable working state after a long iteration session. The plugin now supports:
- Multi-Surface-Select für alle Element-Typen (Türen/Fenster/Treppen/Tragwerk)
- Wand-Z-Drag → unbound mode (UK/OK-Override, Wand vom Geschoss entkoppelt)
- Wand-Z-Drag nimmt verknüpfte Öffnungen mit (Brüstung += delta_z via Idle-Pfad)
- Öffnungs-XY-Drag snapt direktional auf Wand-Tangente
- Öffnungs-Z-Drag passt Brüstung an (Fenster sofort sync, Tür deferred)
- Wand-Delete kaskadiert Öffnungen (deferred via Idle, robust gegen _Rotate/_Move)
- Source-Cascade beim Öffnungs-Delete (deferred analog Wand-Kaskade)
- Listener-Cleanup robust gegen _reset_panels.py Reload (Refs in
_dossier_runtime_event_refs gespeichert, vor Re-Install deregistriert)
- _count_same_id_type filtert IsDeleted (verhindert Source-Duplikat-Bug bei Move)
- Frontend: Brüstungs-Slider für Tür ("Schwelle"), Flügel-Block nur bei Fenster
Plus aus früherer Phase dieser Session:
- Dossier-Launcher Auto-Load via Rhinos StartupCommands-XML
- Default-Pfad zeigt auf gebundeltes startup.py (out-of-the-box für neue User)
- Splash-Window beim Plugin-Load mit native macOS rounded corners
- Diverse Launcher-Verbesserungen (Brüstungs-Default, tauri.conf, capabilities)
Known issue: bei Multi-Select-Move mit vielen Sub-Volumen kann sporadisch
"Unable to transform" auftreten (Rhinos Move-Operation kollidiert mit Wand-
Regen). Tür-spezifischer Defer-Pfad mildert das, Fenster läuft sync.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>