#! python 3 # -*- coding: utf-8 -*- # SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (C) 2026 Karim Gabriele Varano """ _startup_splash.py Petrol-grüner Splash-Screen waehrend des DOSSIER-Plugin-Startups. Borderless Eto-Form mit WebView + Inline-HTML im selben Stil wie der Launcher-Splash. Bedeckt visuell die 3+ Sekunden waehrend Rhino die Panels registriert + WindowLayout neu anwendet. Wird von startup.py beim ersten Idle gezeigt und nach Layout-Apply (oder Timeout) wieder versteckt. """ import scriptcontext as sc _SPLASH_KEY = "_dossier_startup_splash" _SAFETY_TIMEOUT_SEC = 8.0 # spaetestens nach 8s wegmachen, falls Hide-Hook nicht feuert _SPLASH_HTML = ''' Dossier laedt
DOSSIER.
Rhino 8 Plugin
Plugin laedt — Panels werden platziert
AGPL-3.0 · Karim Gabriele Varano CPython 3.9
''' def _try_borderless_mac(form): """Mac-spezifisch: direkter NSWindow-Zugriff via Eto.ControlObject um titlebar/Decorations komplett zu killen + rounded corners zu setzen. Auf Mac ist Eto.Forms.Form.WindowStyle.None inkonsistent — der echte Borderless-Effekt geht nur ueber AppKit. Probiert verschiedene Wege, keiner ist fatal wenn er nicht klappt.""" nswindow = None try: # Eto auf Mac: Form.ControlObject ist die NSWindow-Instanz nswindow = getattr(form, "ControlObject", None) except Exception: pass if nswindow is None: return False # NSBorderlessWindowMask = 0, NSFullSizeContentViewWindowMask = 1<<15 # NSWindowStyleMaskTitled = 1 BORDERLESS = 0 FULL_SIZE = 1 << 15 def _try(method_name, *args): try: m = getattr(nswindow, method_name, None) if m is None: return False m(*args) return True except Exception: return False ok = False # 1) Style-Mask auf borderless (entfernt Titlebar/Border) if _try("setStyleMask_", BORDERLESS): ok = True # 2) Hintergrund transparent damit WebView's eigene rounded box scheint if _try("setOpaque_", False): ok = True if _try("setHasShadow_", True): ok = True # 3) Background color clear try: from AppKit import NSColor as _NSColor # type: ignore clear = _NSColor.clearColor() if _try("setBackgroundColor_", clear): ok = True except Exception: pass # 4) Bewegbar via background-drag if _try("setMovableByWindowBackground_", True): ok = True return ok def show(): """Zeigt den Splash. Idempotent — zweiter Aufruf bringt das bestehende Fenster nur in den Vordergrund. Auto-Hide nach _SAFETY_TIMEOUT_SEC als Fallback falls hide() vergessen wird.""" if sc.sticky.get(_SPLASH_KEY) is not None: print("[SPLASH] schon offen — skip"); return try: import Eto.Forms as ef import Eto.Drawing as ed except Exception as ex: print("[SPLASH] Eto-Import:", ex); return try: form = ef.Form() form.Title = "" # leerer Titel hilft bei Mac-Titlebar-Reduktion # Versuche WindowStyle.None (Eto-API, funktioniert nicht immer auf Mac) try: form.WindowStyle = getattr(ef.WindowStyle, "None") except Exception: pass # Alle Window-Chrome-Optionen aus for attr, val in ( ("Resizable", False), ("Minimizable", False), ("Maximizable", False), ("Closeable", False), ("ShowInTaskbar", False), ("Topmost", True), ): try: setattr(form, attr, val) except Exception: pass try: form.Size = ed.Size(420, 160) except Exception: pass # Transparent so dass WebView's eigene rounded gradient sichtbar wird try: form.BackgroundColor = ed.Colors.Transparent except Exception: try: form.BackgroundColor = ed.Color(0.37, 0.66, 0.59) except Exception: pass wv = ef.WebView() try: # WebView selber transparent damit das Form-Hintergrund durchscheint wv.BackgroundColor = ed.Colors.Transparent except Exception: pass try: wv.LoadHtml(_SPLASH_HTML) except Exception as ex: print("[SPLASH] LoadHtml:", ex) form.Content = wv # Center on screen try: screen = ef.Screen.PrimaryScreen sb = screen.Bounds x = int(sb.X + (sb.Width - form.Size.Width) / 2) y = int(sb.Y + (sb.Height - form.Size.Height) / 2 - 100) form.Location = ed.Point(x, y) except Exception as ex: print("[SPLASH] center:", ex) try: form.Show() except Exception as ex: print("[SPLASH] Show:", ex); return # Mac-spezifischer Borderless-Hack — MUSS nach Show() laufen damit # die NSWindow existiert try: if _try_borderless_mac(form): print("[SPLASH] Borderless (Mac NSWindow) angewendet") except Exception as ex: print("[SPLASH] borderless-mac:", ex) sc.sticky[_SPLASH_KEY] = form print("[SPLASH] visible") # Safety-Timeout — wenn nach 8s niemand hide() ruft, automatisch weg try: import threading def _auto_hide(): try: hide() except Exception: pass threading.Timer(_SAFETY_TIMEOUT_SEC, _auto_hide).start() except Exception: pass except Exception as ex: print("[SPLASH] show:", ex) def hide(): """Versteckt + entsorgt den Splash. Idempotent.""" form = sc.sticky.get(_SPLASH_KEY) if form is None: return try: sc.sticky[_SPLASH_KEY] = None try: form.Close() except Exception: try: form.Visible = False except Exception: pass except Exception as ex: print("[SPLASH] hide:", ex)