Text-Editor zurueck auf Dialog.ShowModal (chromeloses Form ging nicht)
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>
This commit is contained in:
+70
-47
@@ -198,40 +198,47 @@ def _prompt_for_text(default=""):
|
||||
|
||||
|
||||
def _inline_editor(p1, p2, initial=""):
|
||||
"""Inline-Editor: chromeloses Eto.Form ueber dem gepickten Frame im
|
||||
Viewport positioniert. Cmd+Enter / Ctrl+Enter = commit, Esc = abbrechen.
|
||||
Returns Text-String oder None."""
|
||||
"""Editor-Dialog mit Multi-Line-TextArea, positioniert NEBEN dem
|
||||
gepickten Frame (statt zentriert). Eto.Dialog.ShowModal — reliable
|
||||
auf Mac/Win. Returns Text-String oder None."""
|
||||
import Eto.Forms as forms
|
||||
import Eto.Drawing as drawing
|
||||
|
||||
# Frame-Position im Screen ermitteln (fuer Dialog-Positionierung)
|
||||
sx = sy = None
|
||||
sw = max(360, 280)
|
||||
sh = max(180, 150)
|
||||
try:
|
||||
view = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView
|
||||
vp = view.ActiveViewport
|
||||
# WorldToScreen → (bool, int_x, int_y) viewport-lokale Pixel
|
||||
ok1, x1, y1 = vp.WorldToScreen(p1)
|
||||
ok2, x2, y2 = vp.WorldToScreen(p2)
|
||||
view_rect = view.ScreenRectangle # absolute Viewport-Position
|
||||
if ok1 and ok2:
|
||||
view_rect = view.ScreenRectangle
|
||||
fx = view_rect.X + min(x1, x2)
|
||||
fy = view_rect.Y + min(y1, y2)
|
||||
fw = abs(x2 - x1); fh = abs(y2 - y1)
|
||||
# Dialog rechts neben dem Frame platzieren (oder darunter wenn
|
||||
# rechts kein Platz). Falls Frame klein, Dialog hat eigene Min-
|
||||
# Groesse.
|
||||
sx = int(fx + fw + 20)
|
||||
sy = int(fy)
|
||||
sw = max(360, fw)
|
||||
sh = max(180, fh)
|
||||
except Exception as ex:
|
||||
print("[TEXT] viewport-coords:", ex)
|
||||
return None
|
||||
if not (ok1 and ok2):
|
||||
return None
|
||||
# Frame-Rect in absoluten Screen-Pixeln
|
||||
sx = view_rect.X + min(x1, x2)
|
||||
sy = view_rect.Y + min(y1, y2)
|
||||
sw = max(60, abs(x2 - x1))
|
||||
sh = max(28, abs(y2 - y1))
|
||||
|
||||
form = forms.Form()
|
||||
try: form.WindowStyle = forms.WindowStyle.None_
|
||||
except Exception:
|
||||
try: form.WindowStyle = getattr(forms.WindowStyle, "None")
|
||||
dlg = forms.Dialog()
|
||||
dlg.Title = "Text einfuegen"
|
||||
dlg.Resizable = True
|
||||
dlg.Padding = drawing.Padding(8)
|
||||
try: dlg.MinimumSize = drawing.Size(360, 180)
|
||||
except Exception: pass
|
||||
try: form.Topmost = True
|
||||
try: dlg.ClientSize = drawing.Size(int(sw), int(sh))
|
||||
except Exception: pass
|
||||
form.Resizable = False
|
||||
form.ClientSize = drawing.Size(int(sw), int(sh))
|
||||
try:
|
||||
form.Location = drawing.Point(int(sx), int(sy))
|
||||
# Position neben dem Frame (falls verfuegbar)
|
||||
if sx is not None and sy is not None:
|
||||
try: dlg.Location = drawing.Point(sx, sy)
|
||||
except Exception: pass
|
||||
|
||||
ta = forms.TextArea()
|
||||
@@ -241,12 +248,26 @@ def _inline_editor(p1, p2, initial=""):
|
||||
ta.Text = initial or ""
|
||||
try: ta.Font = drawing.Font("Helvetica", 13)
|
||||
except Exception: pass
|
||||
try: ta.BackgroundColor = drawing.Color.FromArgb(245, 245, 245)
|
||||
except Exception: pass
|
||||
ta.ShowBorder = False
|
||||
|
||||
result = {"text": None, "committed": False}
|
||||
|
||||
ok_btn = forms.Button()
|
||||
ok_btn.Text = "Einfuegen"
|
||||
cancel_btn = forms.Button()
|
||||
cancel_btn.Text = "Abbrechen"
|
||||
|
||||
def on_ok(s, e):
|
||||
result["text"] = ta.Text or ""
|
||||
result["committed"] = True
|
||||
try: dlg.Close()
|
||||
except Exception: pass
|
||||
def on_cancel(s, e):
|
||||
try: dlg.Close()
|
||||
except Exception: pass
|
||||
ok_btn.Click += on_ok
|
||||
cancel_btn.Click += on_cancel
|
||||
|
||||
# Cmd/Ctrl+Enter Shortcut im TextArea
|
||||
def on_keydown(sender, e):
|
||||
try:
|
||||
is_cmd = (e.Modifiers == forms.Keys.Application or
|
||||
@@ -254,34 +275,36 @@ def _inline_editor(p1, p2, initial=""):
|
||||
except Exception:
|
||||
is_cmd = False
|
||||
if e.Key == forms.Keys.Enter and is_cmd:
|
||||
result["text"] = ta.Text or ""
|
||||
result["committed"] = True
|
||||
try: form.Close()
|
||||
except Exception: pass
|
||||
e.Handled = True
|
||||
on_ok(sender, e); e.Handled = True
|
||||
elif e.Key == forms.Keys.Escape:
|
||||
try: form.Close()
|
||||
except Exception: pass
|
||||
e.Handled = True
|
||||
|
||||
on_cancel(sender, e); e.Handled = True
|
||||
ta.KeyDown += on_keydown
|
||||
form.Content = ta
|
||||
|
||||
try: form.Show()
|
||||
except Exception as ex:
|
||||
print("[TEXT] inline editor show:", ex)
|
||||
return None
|
||||
try: ta.Focus()
|
||||
layout = forms.DynamicLayout()
|
||||
layout.Spacing = drawing.Size(6, 6)
|
||||
layout.BeginVertical()
|
||||
layout.AddRow(ta)
|
||||
layout.EndVertical()
|
||||
layout.BeginVertical()
|
||||
layout.BeginHorizontal()
|
||||
layout.Add(None, True, False)
|
||||
layout.Add(cancel_btn)
|
||||
layout.Add(ok_btn)
|
||||
layout.EndHorizontal()
|
||||
layout.EndVertical()
|
||||
dlg.Content = layout
|
||||
try:
|
||||
dlg.DefaultButton = ok_btn
|
||||
dlg.AbortButton = cancel_btn
|
||||
except Exception: pass
|
||||
|
||||
# Warten bis User Esc oder Cmd+Enter drueckt
|
||||
while True:
|
||||
try:
|
||||
if form.Closed: break
|
||||
except Exception:
|
||||
break
|
||||
try: Rhino.RhinoApp.Wait()
|
||||
except Exception: break
|
||||
parent = Rhino.UI.RhinoEtoApp.MainWindow
|
||||
if parent is not None: dlg.ShowModal(parent)
|
||||
else: dlg.ShowModal()
|
||||
except Exception as ex:
|
||||
print("[TEXT] dialog show:", ex)
|
||||
return None
|
||||
|
||||
if not result["committed"]: return None
|
||||
return (result["text"] or "").strip() or None
|
||||
|
||||
Reference in New Issue
Block a user