UX: WebView native-feel + Context-Menu Redesign + Startup-Fix

- Disable text selection (CSS user-select:none) + block browser
  context menu (contextmenu preventDefault) in all panels
- ContextMenu: pill items, accent hover, entrance animation,
  optional title header — controlled via single ContextMenu.css
- EbenenManager + GeschossManager: show layer name as menu title
- startup.py: skip splash on Cmd+N when plugin already loaded
- startup.py: hook NewDocument so display-modes apply to new docs
This commit is contained in:
2026-06-06 05:27:48 +02:00
parent 18443b60c3
commit 92b4baa285
8 changed files with 185 additions and 43 deletions
+21 -2
View File
@@ -267,10 +267,12 @@ def _build_inline_template():
html = f.read().decode("utf-8")
placeholder_script = '<script>' + _MODE_SCRIPT_PLACEHOLDER + '</script>'
_no_select = '<style>*{-webkit-user-select:none!important;user-select:none!important;}</style>'
_no_ctx = '<script>document.addEventListener("contextmenu",function(e){e.preventDefault();},true);</script>'
if "</head>" in html:
html = html.replace("</head>", placeholder_script + "</head>")
html = html.replace("</head>", placeholder_script + _no_select + _no_ctx + "</head>")
else:
html = placeholder_script + html
html = placeholder_script + _no_select + _no_ctx + html
def inline_css(m):
p = os.path.join(dist_dir, m.group(1).lstrip("./").replace("/", os.sep))
@@ -353,6 +355,15 @@ def attach_webview(panel, bridge, mode):
wv.ExecuteScript("window.RHINO_MODE=true;")
except Exception:
pass
try:
wv.ExecuteScript(
"var _ds=document.createElement('style');"
"_ds.textContent='*{-webkit-user-select:none!important;user-select:none!important;}';"
"document.head.appendChild(_ds);"
"document.addEventListener('contextmenu',function(e){e.preventDefault();},true);"
)
except Exception:
pass
def on_idle(s, e):
Rhino.RhinoApp.Idle -= on_idle
@@ -440,6 +451,14 @@ def open_satellite_window(mode, params=None, title=None, size=(420, 560),
def on_loaded(s, e):
try: wv.ExecuteScript("window.RHINO_MODE=true;")
except Exception: pass
try:
wv.ExecuteScript(
"var _ds=document.createElement('style');"
"_ds.textContent='*{-webkit-user-select:none!important;user-select:none!important;}';"
"document.head.appendChild(_ds);"
"document.addEventListener('contextmenu',function(e){e.preventDefault();},true);"
)
except Exception: pass
wv.DocumentTitleChanged += on_title_
wv.DocumentLoaded += on_loaded
+11 -5
View File
@@ -23,11 +23,13 @@ if _HERE not in sys.path:
# Nutzer waehrend Python-Imports + Panel-Registrierung nicht in eine schwarze
# Rhino-Oberflaeche schaut. Skipt automatisch wenn Launcher seinen eigenen
# Splash zeigt (Owner-Marker-Check).
try:
import _startup_splash as _splash_first
_splash_first.show()
except Exception as _ex_splash:
print("[STARTUP] splash early:", _ex_splash)
# Skipt auch wenn Plugin bereits in dieser Session geladen ist (z.B. Cmd+N).
if not sc.sticky.get("_dossier_startup_scheduled"):
try:
import _startup_splash as _splash_first
_splash_first.show()
except Exception as _ex_splash:
print("[STARTUP] splash early:", _ex_splash)
# DIAGNOSE — welcher Python-Engine laeuft hier wirklich? Einmalig beim Start.
print("[STARTUP] Python: {}".format(sys.version))
@@ -299,6 +301,10 @@ def _load_all(sender, e):
Rhino.RhinoDoc.EndOpenDocument += _on_doc_opened
except Exception as ex:
print("[STARTUP] EndOpenDocument-Hook:", ex)
try:
Rhino.RhinoDoc.NewDocument += _on_doc_opened
except Exception as ex:
print("[STARTUP] NewDocument-Hook:", ex)
# Projekt-Config bestimmt, welche Module geladen werden. Ohne Config
# (kein Launcher benutzt, oder Datei nicht da) laedt der Host alles.
config = _read_project_config()