React WYSIWYG Text-Editor (Topmost Satellite-WebView) — Phase 1
User-Wunsch: eigener WYSIWYG-Editor im React/Topbar-GUI-Stil. Topmost. Verschiedene Schriftarten/-Dicken sichtbar im Editor selbst. Neues Backend (rhino/text_editor.py): - TextEditorBridge mit Frame-Daten im Konstruktor, INIT-Push mit Settings + Font-Liste, COMMIT erstellt TextEntity, CANCEL schliesst - open_with_frame(p1, p2, origin, width, height): oeffnet Satellite- Window mit mode='text_editor' + topmost=True - panel_base.open_satellite_window: neuer Parameter topmost (default False) der form.Topmost setzt text_create.create_text: ruft jetzt text_editor.open_with_frame nach dem Frame-Pick. Eto-basierter _dossier_text_editor bleibt im Modul als Fallback aber wird nicht mehr verwendet. Neues Frontend (src/TextEditorApp.jsx, mode='text_editor'): - Layout im DOSSIER-Topbar-Stil (dunkle Pills, accent on hover) - Pill-Helper-Komponente fuer alle Toggle/Action-Buttons - Dropdown-Helper fuer Font + Size - Toolbar Row 1: Font-Dropdown | Size-Dropdown | Color-Picker | Layer-Reset - Toolbar Row 2: B/I/U mit Material-Icons | L/C/R Align | x²/x₂ Sup/Sub - Sonderzeichen-Palette: 41 Unicode-Symbole (Architektur/Math/Pfeile/ Auszeichnungen), Klick inserted am Cursor - WYSIWYG-Editor: contentEditable div mit fontFamily=ausgewaehlt, textAlign=ausgewaehlt — Format-Toolbar wirkt via document.execCommand (bold/italic/underline/justifyLeft/Center/Right/superscript/subscript/ fontName/foreColor) - "Einfuegen" sendet COMMIT mit text (innerText) + settings - "Abbrechen" CANCEL → Bridge schliesst Form Phase 1 Limitation: rendert in Rhino als PlainText mit den globalen Settings (font/size/bold/italic/align/color) — verschiedene Schriftarten INNERHALB des Texts sind im Editor sichtbar aber nicht im finalen Rhino-TextEntity. Phase 2: HTML → Rhino RichText/RTF Mapping. rhinoBridge.js: send() jetzt exportiert (war intern) damit TextEditorApp generisch COMMIT/CANCEL senden kann. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+7
-55
@@ -862,69 +862,21 @@ def read_selection_settings(doc):
|
||||
|
||||
|
||||
def create_text():
|
||||
"""DOSSIER Custom Text-Workflow:
|
||||
"""DOSSIER Custom Text-Workflow (React WYSIWYG-Editor):
|
||||
1. Frame ziehen (Live-Rechteck-Vorschau)
|
||||
2. _dossier_text_editor (eigener Editor mit Toolbar, Sonderzeichen,
|
||||
Farbe, Sub/Superscript) oeffnet sich neben dem Frame
|
||||
3. TextEntity wird im Frame mit allen gewaehlten Settings erstellt
|
||||
und mit UserString "dossier_text=1" getagged (fuer evtl. spaeteren
|
||||
Double-Click-Hook auf unseren Editor)
|
||||
2. text_editor.open_with_frame oeffnet das React-WYSIWYG-Fenster
|
||||
(Topmost, neben dem Frame). Editor handlet die Eingabe + erstellt
|
||||
die TextEntity bei COMMIT.
|
||||
"""
|
||||
import System
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
if doc is None: return
|
||||
settings = load_settings(doc)
|
||||
fonts = available_fonts()
|
||||
|
||||
frame = _pick_text_frame()
|
||||
if frame is None: return
|
||||
p1, p2, origin, width, height = frame
|
||||
|
||||
new_state = _dossier_text_editor(p1, p2, settings, fonts)
|
||||
if not new_state: return
|
||||
text = (new_state.get("text") or "").strip()
|
||||
if not text: return
|
||||
|
||||
# Defaults aus Editor uebernehmen (ohne color)
|
||||
save_settings(doc, {
|
||||
"font": new_state.get("font"),
|
||||
"size": new_state.get("size"),
|
||||
"bold": new_state.get("bold"),
|
||||
"italic": new_state.get("italic"),
|
||||
"underline": new_state.get("underline"),
|
||||
"align": new_state.get("align"),
|
||||
})
|
||||
|
||||
try:
|
||||
te = rg.TextEntity()
|
||||
te.Plane = rg.Plane(origin, rg.Vector3d.ZAxis)
|
||||
te.PlainText = text
|
||||
try: te.TextHeight = float(new_state.get("size") or 0.2)
|
||||
except Exception: pass
|
||||
_apply_font(te, new_state.get("font") or "Helvetica",
|
||||
new_state.get("bold"), new_state.get("italic"),
|
||||
new_state.get("underline"))
|
||||
_apply_align(te, new_state.get("align") or "left")
|
||||
for attr in ("FormatWidth", "TextWidth", "MaskWidth"):
|
||||
try: setattr(te, attr, width); break
|
||||
except Exception: pass
|
||||
try: te.TextIsWrapped = True
|
||||
except Exception:
|
||||
try: te.TextWrap = True
|
||||
except Exception: pass
|
||||
|
||||
# Object-Attribute: Farbe wenn explizit gesetzt + DOSSIER-Tag
|
||||
attrs = Rhino.DocObjects.ObjectAttributes()
|
||||
col = new_state.get("color")
|
||||
if col is not None:
|
||||
try:
|
||||
attrs.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
|
||||
attrs.ObjectColor = System.Drawing.Color.FromArgb(
|
||||
int(col[0]), int(col[1]), int(col[2]))
|
||||
except Exception as ex:
|
||||
print("[TEXT] color attr:", ex)
|
||||
attrs.SetUserString("dossier_text", "1")
|
||||
doc.Objects.AddText(te, attrs)
|
||||
doc.Views.Redraw()
|
||||
import text_editor
|
||||
text_editor.open_with_frame(p1, p2, origin, width, height)
|
||||
except Exception as ex:
|
||||
print("[TEXT] create:", ex)
|
||||
print("[TEXT] open editor:", ex)
|
||||
|
||||
Reference in New Issue
Block a user