Text-Editor: Default-Stile + Stil-Picker im Dialog

User-Wunsch: vorgespeicherte Stile (Heading, Paragraph Helvetica/Georgia)
direkt im Editor anwendbar.

Backend (text_create.py):
- _DEFAULT_STYLES: 7 sinnvolle Architektur-Defaults — Titel (0.40m bold),
  Heading 1 (0.30m bold), Heading 2 (0.20m bold), Paragraph Helvetica
  (0.15m), Paragraph Georgia (0.15m Georgia), Notiz (0.10m italic),
  Bildlegende (0.08m italic)
- list_styles: seedet die Defaults beim ersten Zugriff falls noch keine
  Styles im Doc existieren (analog mass_style)
- Bestehende save_style/delete_style/apply_style funktionieren weiter

Backend (text_editor.py):
- INIT-Payload erweitert um styles[] (Liste aller verfuegbaren Stile
  mit id/name/font/size/bold/italic/underline/align)

Frontend (TextEditorApp.jsx):
- Neuer Stil-Picker als erstes Dropdown in Toolbar-Row 1 (150px)
- Optionen: "— Stil wählen —" + alle verfuegbaren Stile
- onChange: applyStyle(style) — setzt Toolbar-State + appliziert via
  execCommand auf die aktuelle Selektion im WYSIWYG-Editor (oder als
  Default fuer kommendes Tippen wenn keine Selektion)
- queryCommandState-Check fuer Bold/Italic/Underline damit nur toggled
  wird wenn nicht schon im gewuenschten State

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 01:38:23 +02:00
parent 54aa1c9e84
commit e7a1753519
3 changed files with 82 additions and 2 deletions
+30 -1
View File
@@ -80,11 +80,40 @@ def save_settings(doc, partial):
# Text-Stile (Presets, analog mass_style): doc.Strings JSON-Liste mit
# benannten Settings + aktiver Style-ID.
# Default-Stile fuer Architektur-Workflow — werden bei erstem list_styles
# automatisch erzeugt wenn das Doc noch keine eigenen hat.
_DEFAULT_STYLES = [
{"name": "Titel", "font": "Helvetica", "size": 0.40,
"bold": True, "italic": False, "underline": False, "align": "left"},
{"name": "Heading 1", "font": "Helvetica", "size": 0.30,
"bold": True, "italic": False, "underline": False, "align": "left"},
{"name": "Heading 2", "font": "Helvetica", "size": 0.20,
"bold": True, "italic": False, "underline": False, "align": "left"},
{"name": "Paragraph (Helvetica)", "font": "Helvetica", "size": 0.15,
"bold": False, "italic": False, "underline": False, "align": "left"},
{"name": "Paragraph (Georgia)", "font": "Georgia", "size": 0.15,
"bold": False, "italic": False, "underline": False, "align": "left"},
{"name": "Notiz", "font": "Helvetica", "size": 0.10,
"bold": False, "italic": True, "underline": False, "align": "left"},
{"name": "Bildlegende", "font": "Helvetica", "size": 0.08,
"bold": False, "italic": True, "underline": False, "align": "left"},
]
def list_styles(doc):
if doc is None: return []
try:
raw = doc.Strings.GetValue(_STYLES_KEY)
if not raw: return []
if not raw:
# Seed Defaults bei erstem Zugriff
seeded = [_normalize(s) for s in _DEFAULT_STYLES]
for i, s in enumerate(seeded):
s["id"] = "ts_default_" + str(i)
s["name"] = _DEFAULT_STYLES[i]["name"]
try:
doc.Strings.SetString(_STYLES_KEY, json.dumps(seeded))
except Exception: pass
return seeded
items = json.loads(raw)
if not isinstance(items, list): return []
out = []
+5
View File
@@ -33,9 +33,14 @@ class TextEditorBridge(panel_base.BaseBridge):
self._form_ref = form
def _on_ready(self):
doc = Rhino.RhinoDoc.ActiveDoc
styles = []
try: styles = text_create.list_styles(doc)
except Exception: pass
self.send("INIT", {
"settings": self._initial_settings,
"fonts": self._fonts,
"styles": styles,
})
def handle(self, data):