Overrides als Satelliten-Fenster vom Oberleiste-Gear öffnen
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>
This commit is contained in:
+3
-4
@@ -915,11 +915,10 @@ class OberleisteBridge(panel_base.BaseBridge):
|
|||||||
print("[OBERLEISTE] notify overrides:", ex)
|
print("[OBERLEISTE] notify overrides:", ex)
|
||||||
elif t == "OPEN_OVERRIDES_PANEL":
|
elif t == "OPEN_OVERRIDES_PANEL":
|
||||||
try:
|
try:
|
||||||
import System
|
import overrides_panel
|
||||||
import Rhino.UI as RhinoUI
|
overrides_panel.open_as_window()
|
||||||
RhinoUI.Panels.OpenPanel(System.Guid(OVERRIDES_PANEL_GUID_STR))
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print("[OBERLEISTE] OpenPanel Overrides:", ex)
|
print("[OBERLEISTE] open_as_window Overrides:", ex)
|
||||||
|
|
||||||
# --- Command-Line Integration -----------------------------------
|
# --- Command-Line Integration -----------------------------------
|
||||||
elif t == "RUN_COMMAND":
|
elif t == "RUN_COMMAND":
|
||||||
|
|||||||
@@ -211,16 +211,37 @@ class OverridesBridge(panel_base.BaseBridge):
|
|||||||
self._send_state()
|
self._send_state()
|
||||||
|
|
||||||
|
|
||||||
def _bridge_factory():
|
def _ensure_listeners_once():
|
||||||
|
"""Overrides-Listener nur EINMAL global installieren (statt bei jedem
|
||||||
|
open_as_window)."""
|
||||||
|
if sc.sticky.get("overrides_listeners_installed"):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
overrides.install_listeners()
|
||||||
|
sc.sticky["overrides_listeners_installed"] = True
|
||||||
|
except Exception as ex:
|
||||||
|
print("[OVERRIDES] install_listeners:", ex)
|
||||||
|
|
||||||
|
|
||||||
|
def open_as_window():
|
||||||
|
"""Oeffnet OVERRIDES als echtes Rhino-Fenster (Eto.Form + WebView).
|
||||||
|
Wird vom Oberleiste-Bridge bei OPEN_OVERRIDES_PANEL gerufen.
|
||||||
|
|
||||||
|
Pro Fenster eine eigene OverridesBridge-Instanz. Die letzte Instanz
|
||||||
|
landet in sticky["overrides_bridge"] — andere Panels (Oberleiste) die
|
||||||
|
Cross-Updates an Overrides senden, treffen das aktive Fenster."""
|
||||||
|
_ensure_listeners_once()
|
||||||
b = OverridesBridge()
|
b = OverridesBridge()
|
||||||
try: overrides.install_listeners()
|
|
||||||
except Exception as ex: print("[OVERRIDES] install_listeners:", ex)
|
|
||||||
# Bridge im sticky ablegen, damit andere Panels (z.B. Oberleiste) sie
|
|
||||||
# bei Cross-Panel-Updates erreichen koennen.
|
|
||||||
sc.sticky["overrides_bridge"] = b
|
sc.sticky["overrides_bridge"] = b
|
||||||
return b
|
panel_base.open_satellite_window(
|
||||||
|
"overrides",
|
||||||
|
title="OVERRIDES",
|
||||||
|
size=(760, 580),
|
||||||
|
bridge=b)
|
||||||
|
|
||||||
|
|
||||||
panel_base.register_and_open("overrides", "OVERRIDES", PANEL_GUID_STR, _bridge_factory,
|
# OVERRIDES laeuft jetzt als Satelliten-Fenster (geoeffnet vom Oberleiste-
|
||||||
icon_spec=("tune", "#b5621e"),
|
# Gear-Button), nicht mehr als gedocktes Panel. Listener werden lazy beim
|
||||||
min_size=(720, 560))
|
# ersten open_as_window installiert. Falls jemand das alte Panel via
|
||||||
|
# Workspace-Layout noch geoeffnet hat, wird es nicht mehr registriert →
|
||||||
|
# Rhino zeigt es leer / nicht mehr an.
|
||||||
|
|||||||
+34
-32
@@ -281,16 +281,20 @@ def attach_webview(panel, bridge, mode):
|
|||||||
# --- Satelliten-Fenster (echtes Rhino-Fenster mit eingebetteter WebView) ----
|
# --- Satelliten-Fenster (echtes Rhino-Fenster mit eingebetteter WebView) ----
|
||||||
|
|
||||||
def open_satellite_window(mode, params=None, title=None, size=(420, 560),
|
def open_satellite_window(mode, params=None, title=None, size=(420, 560),
|
||||||
on_save=None, on_cancel=None):
|
on_save=None, on_cancel=None, bridge=None):
|
||||||
"""Oeffnet ein echtes Rhino-Fenster (Eto.Form) mit eingebetteter WebView.
|
"""Oeffnet ein echtes Rhino-Fenster (Eto.Form) mit eingebetteter WebView.
|
||||||
Die WebView laedt die React-App mit dem gegebenen `mode` und `params`.
|
Die WebView laedt die React-App mit dem gegebenen `mode` und `params`.
|
||||||
|
|
||||||
Die React-App sendet via Bridge `SAVE`/`CANCEL`-Messages. Wir rufen
|
Zwei Bridge-Modi:
|
||||||
dann die jeweilige Callback-Funktion auf (mit dem Save-Payload) und
|
- **Default (kein `bridge`-Arg):** inline SAVE/CANCEL-Bridge. React
|
||||||
schliessen das Fenster.
|
sendet SAVE/CANCEL → on_save/on_cancel-Callback → Fenster zu. Fuer
|
||||||
|
einfache One-Shot-Dialoge (Settings etc.).
|
||||||
|
- **`bridge` uebergeben:** eine vollwertige BaseBridge-Subklasse (z.B.
|
||||||
|
OverridesBridge). Das Fenster nutzt die wie ein normales Panel,
|
||||||
|
mit allen Mess-Typen die der Bridge handlet. Save/Cancel sind dort
|
||||||
|
nicht standard; Fenster bleibt offen bis User es manuell schliesst.
|
||||||
|
|
||||||
Returns die Form-Instance (User kann sie speichern um sie spaeter
|
Returns die Form-Instance."""
|
||||||
programmatisch zu schliessen)."""
|
|
||||||
|
|
||||||
form = forms.Form()
|
form = forms.Form()
|
||||||
if title is None: title = mode.replace('_', ' ').title()
|
if title is None: title = mode.replace('_', ' ').title()
|
||||||
@@ -303,33 +307,31 @@ def open_satellite_window(mode, params=None, title=None, size=(420, 560),
|
|||||||
|
|
||||||
wv = forms.WebView()
|
wv = forms.WebView()
|
||||||
|
|
||||||
# Inline-Bridge fuer Satelliten-Fenster: handle SAVE/CANCEL, schliesse
|
if bridge is None:
|
||||||
# bei beiden das Fenster.
|
# Inline-Bridge fuer einfache Settings-Dialoge: SAVE/CANCEL, schliesse
|
||||||
class _SatelliteBridge(BaseBridge):
|
# bei beiden das Fenster.
|
||||||
def __init__(self):
|
class _SatelliteBridge(BaseBridge):
|
||||||
BaseBridge.__init__(self, mode)
|
def __init__(self):
|
||||||
def handle(self, data):
|
BaseBridge.__init__(self, mode)
|
||||||
t = data.get("type", "")
|
def handle(self, data):
|
||||||
p = data.get("payload") or {}
|
t = data.get("type", "")
|
||||||
if t == "READY":
|
p = data.get("payload") or {}
|
||||||
# React liest PANEL_PARAMS direkt vom window-Object — wir
|
if t == "READY":
|
||||||
# muessen also nichts mehr aktiv senden.
|
pass
|
||||||
pass
|
elif t == "SAVE":
|
||||||
elif t == "SAVE":
|
if on_save is not None:
|
||||||
if on_save is not None:
|
try: on_save(p)
|
||||||
try: on_save(p)
|
except Exception as ex:
|
||||||
except Exception as ex:
|
print("[{}] on_save: {}".format(mode.upper(), ex))
|
||||||
print("[{}] on_save: {}".format(mode.upper(), ex))
|
try: form.Close()
|
||||||
try: form.Close()
|
|
||||||
except Exception: pass
|
|
||||||
elif t == "CANCEL":
|
|
||||||
if on_cancel is not None:
|
|
||||||
try: on_cancel()
|
|
||||||
except Exception: pass
|
except Exception: pass
|
||||||
try: form.Close()
|
elif t == "CANCEL":
|
||||||
except Exception: pass
|
if on_cancel is not None:
|
||||||
|
try: on_cancel()
|
||||||
bridge = _SatelliteBridge()
|
except Exception: pass
|
||||||
|
try: form.Close()
|
||||||
|
except Exception: pass
|
||||||
|
bridge = _SatelliteBridge()
|
||||||
bridge.set_webview(wv)
|
bridge.set_webview(wv)
|
||||||
|
|
||||||
def on_title_(s, e):
|
def on_title_(s, e):
|
||||||
|
|||||||
@@ -374,6 +374,11 @@ export default function OberleisteApp() {
|
|||||||
<option disabled>──────────</option>
|
<option disabled>──────────</option>
|
||||||
<option value="__configure__">Konfigurieren…</option>
|
<option value="__configure__">Konfigurieren…</option>
|
||||||
</select>
|
</select>
|
||||||
|
<ToolButton
|
||||||
|
onClick={openOverridesPanel}
|
||||||
|
icon="settings"
|
||||||
|
title="Overrides-Regel-Editor öffnen"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Spacer am rechten Rand */}
|
{/* Spacer am rechten Rand */}
|
||||||
<div style={{ flex: 1 }} />
|
<div style={{ flex: 1 }} />
|
||||||
|
|||||||
Reference in New Issue
Block a user