diff --git a/rhino/text_create.py b/rhino/text_create.py index ff0214c..2ffd42b 100644 --- a/rhino/text_create.py +++ b/rhino/text_create.py @@ -211,20 +211,18 @@ def _inline_editor(p1, p2, initial=""): try: view = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView vp = view.ActiveViewport - ok1, x1, y1 = vp.WorldToScreen(p1) - ok2, x2, y2 = vp.WorldToScreen(p2) - 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) + # WorldToClient → System.Drawing.Point (viewport-lokale Pixel) + c1 = vp.WorldToClient(p1) + c2 = vp.WorldToClient(p2) + view_rect = view.ScreenRectangle # absolute Viewport-Position + fx = view_rect.X + int(min(c1.X, c2.X)) + fy = view_rect.Y + int(min(c1.Y, c2.Y)) + fw = abs(int(c2.X - c1.X)) + fh = abs(int(c2.Y - c1.Y)) + 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) @@ -248,6 +246,11 @@ def _inline_editor(p1, p2, initial=""): ta.Text = initial or "" try: ta.Font = drawing.Font("Helvetica", 13) except Exception: pass + # Explizit Groesse setzen — DynamicLayout expandiert TextArea sonst + # nicht zuverlaessig (zeigte sich als 1-Zeilen-Streifen) + try: + ta.Size = drawing.Size(int(sw) - 20, max(120, int(sh) - 70)) + except Exception: pass result = {"text": None, "committed": False} @@ -381,9 +384,14 @@ def _apply_font(te, face, bold, italic, underline=False): face = face[:-len(suffix)].strip(); break print("[TEXT] _apply_font face={!r} bold={} italic={} underline={}".format( face, bold, italic, underline)) - # Pfad 1: 5-arg Font-Konstruktor (mit underline+strikethrough) + # Pfad 1: 5-arg Font-Konstruktor mit echten Enums (Python.NET 3 erlaubt + # keinen impliziten bool→Enum-Cast mehr). Underline-Support nur hier. try: - font = Rhino.DocObjects.Font(face, bold, italic, underline, False) + FW = Rhino.DocObjects.Font.FontWeight + FS = Rhino.DocObjects.Font.FontStyle + weight = FW.Bold if bold else FW.Normal + style = FS.Italic if italic else FS.Upright + font = Rhino.DocObjects.Font(face, weight, style, underline, False) if font is not None: te.Font = font return True @@ -454,37 +462,50 @@ def apply_settings_to_selection(doc, patch): if doc is None or not isinstance(patch, dict): return 0 selected = _selected_text_objects(doc) if not selected: return 0 + import System n = 0 for obj in selected: try: - te = obj.Geometry.Duplicate() - if "size" in patch: - try: te.TextHeight = float(patch["size"]) + old = obj.Geometry + # Aktuelle Werte lesen (vor Modifikation) + cur = old.Font + try: cur_face = cur.QuartetName if cur else "Helvetica" + except Exception: cur_face = "Helvetica" + try: cur_bold = bool(cur.Bold) if cur else False + except Exception: cur_bold = False + try: cur_italic = bool(cur.Italic) if cur else False + except Exception: cur_italic = False + try: cur_underline = bool(cur.Underlined) if cur else False + except Exception: cur_underline = False + + # Neue Werte aus Patch + Fallback auf aktuell + face = patch.get("font") or cur_face + bold = patch["bold"] if "bold" in patch else cur_bold + italic = patch["italic"] if "italic" in patch else cur_italic + underline = patch["underline"] if "underline" in patch else cur_underline + size = float(patch["size"]) if "size" in patch else float(old.TextHeight) + align = patch["align"] if patch.get("align") in _ALIGNS else None + + # FRESH TextEntity bauen statt Duplicate-Modify. Bypassed + # Probleme wo te.Font-Setter wegen Rich-Text-Runs oder + # DimensionStyle-Override nicht greift. + te = rg.TextEntity() + te.Plane = old.Plane + try: te.PlainText = old.PlainText + except Exception: pass + te.TextHeight = size + # DimensionStyle entkoppeln damit unser Font nicht von Style + # ueberschrieben wird. + try: te.DimensionStyleId = System.Guid.Empty + except Exception: pass + _apply_font(te, face, bool(bold), bool(italic), bool(underline)) + # Alignment: aus Patch oder vom alten Entity uebernehmen + if align: + _apply_align(te, align) + else: + try: te.TextHorizontalAlignment = old.TextHorizontalAlignment except Exception: pass - # Font: bei jeder Aenderung neu setzen. Vorher PlainText- - # Reset damit eventuelle RichText-Formatierungs-Runs nicht - # das neue te.Font ueberschreiben. - if any(k in patch for k in ("font", "bold", "italic", "underline")): - try: - plain = te.PlainText - te.PlainText = plain # reset zu plain-mode - except Exception: pass - cur = te.Font - try: cur_face = cur.QuartetName if cur else "Helvetica" - except Exception: cur_face = "Helvetica" - try: cur_bold = bool(cur.Bold) if cur else False - except Exception: cur_bold = False - try: cur_italic = bool(cur.Italic) if cur else False - except Exception: cur_italic = False - try: cur_underline = bool(cur.Underlined) if cur else False - except Exception: cur_underline = False - face = patch.get("font") or cur_face - bold = patch["bold"] if "bold" in patch else cur_bold - italic = patch["italic"] if "italic" in patch else cur_italic - underline = patch["underline"] if "underline" in patch else cur_underline - _apply_font(te, face, bool(bold), bool(italic), bool(underline)) - if "align" in patch and patch["align"] in _ALIGNS: - _apply_align(te, patch["align"]) + doc.Objects.Replace(obj.Id, te) n += 1 except Exception as ex: