Stempel-Stil-Bulk-Apply + Manager-Tab in ProjectSettings

PHASE 1 — Bulk-Apply auf mehrere selektierte Raeume:
- Backend _cmd_apply_raum_stil: leere ids im Patch → nimmt automatisch
  alle aktuell SELEKTIERTEN raum_outlines aus dem Doc (Bulk-Fallback)
- Frontend sendet leere ids fuer die Default-Bulk-Variante. User
  selektiert N Raeume im Viewport → klickt Stil im Properties-Picker →
  Stil wird auf alle angewendet. Inkludiert immer den Properties-Raum.

PHASE 2 — Stil-Manager als Settings-Tab:
- Neuer Tab "Raumstile" in ProjectSettings-Dialog
- Liste aller Stile mit Drag-Reorder (HTML5 native), Inline-Rename,
  Duplicate (content_copy-Icon), Delete (mit Confirm)
- Mini-Preview: zeigt Layout-Struktur (z.B. "nummer·name / funktion / area")
  und der Name wird mit Font/Bold/Italic des Stils gerendert als Vorschau
- Backend _cmd_reorder_raum_stile + _cmd_duplicate_raum_stil in elemente.py
- ProjectSettings-Bridge dispatcht direkt zu elemente.load/save_raum_stempel_stile
  (kein Roundtrip via Elemente-Bridge noetig)
- STILE_UPDATED-Message nach jeder Op pusht die neue Liste zum Dialog
- params bei _open_project_settings enthalten jetzt raumStempelStile + fonts

Bridge-Exports: reorderRaumStile / duplicateRaumStil in rhinoBridge.js
This commit is contained in:
2026-05-26 23:47:38 +02:00
parent f208e7fc00
commit 7fbda8c289
5 changed files with 308 additions and 5 deletions
+68 -4
View File
@@ -6457,6 +6457,12 @@ class ElementeBridge(panel_base.BaseBridge):
# Wendet einen gespeicherten Stil auf die im Patch genannten
# raum_outline element_ids an. p = {stilId, ids=[…]}.
self._cmd_apply_raum_stil(p)
elif t == "REORDER_RAUM_STILE":
# p = {ids: [stil_id, ...]} in neuer Reihenfolge
self._cmd_reorder_raum_stile(p)
elif t == "DUPLICATE_RAUM_STIL":
# p = {id, newName?} → kopiert Stil mit neuer uuid + Name
self._cmd_duplicate_raum_stil(p)
elif t == "OPEN_ELEMENTE_UEBERSICHT":
try:
import elemente_uebersicht
@@ -8601,16 +8607,74 @@ class ElementeBridge(panel_base.BaseBridge):
print("[ELEMENTE] Stempel-Stil {} geloescht".format(sid))
self._send_state()
def _cmd_reorder_raum_stile(self, p):
"""Setzt die Reihenfolge der Stile auf die uebergebene id-Liste.
Nicht-erwaehnte Stile bleiben am Ende erhalten."""
doc = Rhino.RhinoDoc.ActiveDoc
if doc is None: return
new_order = p.get("ids") or []
if not isinstance(new_order, list) or not new_order: return
stile = load_raum_stempel_stile(doc)
by_id = {s.get("id"): s for s in stile if s.get("id")}
ordered = []
seen = set()
for sid in new_order:
if sid in by_id and sid not in seen:
ordered.append(by_id[sid]); seen.add(sid)
# Reste anhaengen
for s in stile:
sid = s.get("id")
if sid and sid not in seen:
ordered.append(s); seen.add(sid)
save_raum_stempel_stile(doc, ordered)
self._send_state()
def _cmd_duplicate_raum_stil(self, p):
"""Kopiert einen Stil mit neuer uuid. Payload: {id, newName?}."""
doc = Rhino.RhinoDoc.ActiveDoc
if doc is None: return
sid = (p.get("id") or "").strip()
if not sid: return
stile = load_raum_stempel_stile(doc)
src = next((s for s in stile if s.get("id") == sid), None)
if src is None: return
new_name = (p.get("newName") or "").strip() or (
"{} (Kopie)".format(src.get("name", "Stil")))
new_stil = dict(src)
new_stil["id"] = "stil_" + uuid.uuid4().hex[:8]
new_stil["name"] = new_name
# Einfuegen direkt nach Original
try:
i = next(j for j, s in enumerate(stile) if s.get("id") == sid)
stile.insert(i + 1, new_stil)
except StopIteration:
stile.append(new_stil)
save_raum_stempel_stile(doc, stile)
print("[ELEMENTE] Stempel-Stil '{}' dupliziert -> '{}'".format(
src.get("name"), new_name))
self._send_state()
def _cmd_apply_raum_stil(self, p):
"""Wendet einen Stil auf eine Liste von raum_outline-Element-IDs
an. Payload: {stilId, ids: [element_id, ...]}. Schreibt die Stil-
Felder auf die Source-Outlines + triggert Regen pro Raum.
"""Wendet einen Stil auf raum_outline-Element-IDs an. Payload:
{stilId, ids: [element_id, ...]}. Wenn ids leer/missing nimmt
alle aktuell SELEKTIERTEN raum_outline-Objekte (Bulk-Apply).
Schreibt Stil-Felder auf die Source-Outlines + triggert Regen.
"""
doc = Rhino.RhinoDoc.ActiveDoc
if doc is None: return
sid = (p.get("stilId") or "").strip()
ids = p.get("ids") or []
if not sid or not ids: return
if not sid: return
# Bulk-Fallback: keine ids im Patch → alle selektierten Raeume
if not ids:
for obj in doc.Objects:
try:
if obj.IsSelected(False) <= 0: continue
m = _read_meta(obj)
if m and m.get("type") == "raum_outline":
ids.append(m["id"])
except Exception: pass
if not ids: return
stile = load_raum_stempel_stile(doc)
stil = next((s for s in stile if s.get("id") == sid), None)
if stil is None: