# -*- coding: utf-8 -*- """ aza_addon_shell.py — AZA Add-on-Huelle Kompaktes Fenster mit Kacheln: - Diktat, Chat, Uebersetzer (aktiv) - Presentation Maker (Platzhalter, deaktiviert) Keine eigene Modul-Logik — nur Weiterleitung an bestehende app-Methoden. """ from __future__ import annotations import tkinter as tk from typing import Any, Callable, Optional # ── AZA-Design-Konstanten (passend zu aza_office_shell_v1.py) ───────────────── _BG = "#E8F4FA" _HDR_BG = "#1A4D6D" _HDR_FG = "#FFFFFF" _CARD_BG = "#FFFFFF" _CARD_BD = "#C8D8E8" _ACCENT = "#5B8DB3" _ACCENT_H = "#4A7A9E" _TEXT = "#1A3D55" _TEXT_SUB = "#607890" _TEXT_MUTED = "#8AA0B5" _FF = "Segoe UI" def open_presentation_maker_placeholder() -> None: """Platzhalter — Presentation Maker folgt in separatem Block.""" return None def _make_tile(parent: tk.Frame, icon: str, title: str, subtitle: str, command: Callable[[], None]) -> tk.Frame: """Erstellt eine klickbare Kachel mit Icon, Titel und Untertitel.""" card = tk.Frame(parent, bg=_CARD_BG, bd=0, highlightbackground=_CARD_BD, highlightthickness=1, cursor="hand2") tk.Label(card, text=icon, font=(_FF, 22), bg=_CARD_BG, fg=_ACCENT, pady=8).pack() tk.Label(card, text=title, font=(_FF, 11, "bold"), bg=_CARD_BG, fg=_TEXT).pack(pady=(0, 2)) tk.Label(card, text=subtitle, font=(_FF, 8), bg=_CARD_BG, fg=_TEXT_SUB, wraplength=130, justify="center").pack(padx=8, pady=(0, 12)) def _on_enter(_e): card.configure(highlightbackground=_ACCENT) def _on_leave(_e): card.configure(highlightbackground=_CARD_BD) def _on_click(_e): try: command() except Exception: pass for w in [card] + list(card.winfo_children()): w.bind("", _on_enter) w.bind("", _on_leave) w.bind("", _on_click) return card def _make_tile_disabled(parent: tk.Frame, icon: str, title: str, subtitle: str, status_hint: str) -> tk.Frame: """Deaktivierte Kachel — sichtbar, nicht klickbar, kein API-/Modulstart.""" card = tk.Frame(parent, bg=_CARD_BG, bd=0, highlightbackground=_CARD_BD, highlightthickness=1, cursor="arrow") tk.Label(card, text=icon, font=(_FF, 22), bg=_CARD_BG, fg=_TEXT_MUTED, pady=8).pack() tk.Label(card, text=title, font=(_FF, 11, "bold"), bg=_CARD_BG, fg=_TEXT_MUTED).pack(pady=(0, 2)) tk.Label(card, text=subtitle, font=(_FF, 8), bg=_CARD_BG, fg=_TEXT_MUTED, wraplength=130, justify="center").pack(padx=8, pady=(0, 2)) tk.Label(card, text=status_hint, font=(_FF, 8, "italic"), bg=_CARD_BG, fg=_ACCENT, wraplength=130, justify="center").pack(padx=8, pady=(0, 10)) return card def open_addon_shell(app: Any) -> None: """Oeffnet die Add-on-Huelle als Toplevel.""" existing = getattr(app, "_addon_shell_win", None) if existing is not None: try: if existing.winfo_exists(): existing.lift() existing.focus_force() return except Exception: pass W, H = 920, 350 win = tk.Toplevel(app) app._addon_shell_win = win win.title("AzA Add-on Beta") win.configure(bg=_BG) win.resizable(False, False) try: win.transient(app) except Exception: pass try: win.update_idletasks() sw = win.winfo_screenwidth() x = max(0, (sw - W) // 2) y = 80 win.geometry(f"{W}x{H}+{x}+{y}") except Exception: win.geometry(f"{W}x{H}") try: win.attributes("-topmost", True) win.after(800, lambda: win.attributes("-topmost", False) if win.winfo_exists() else None) except Exception: pass try: win.lift() win.focus_force() except Exception: pass hdr = tk.Frame(win, bg=_HDR_BG) hdr.pack(fill="x") try: import os for _base in [os.path.dirname(os.path.abspath(__file__)), getattr(__import__("sys"), "_MEIPASS", "")]: _ico = os.path.join(_base, "logo.ico") if _base else "" if _ico and os.path.isfile(_ico): try: win.iconbitmap(_ico) except Exception: pass break except Exception: pass tk.Label(hdr, text="🧩 AzA Add-on Beta", font=(_FF, 13, "bold"), bg=_HDR_BG, fg=_HDR_FG, padx=18, pady=12).pack(side="left") tk.Label(hdr, text="✕", font=(_FF, 11), bg=_HDR_BG, fg="#A0C4D8", cursor="hand2", padx=14).pack(side="right") hdr.winfo_children()[-1].bind("", lambda _e: _close()) tk.Label(win, text="Zusätzliche Werkzeuge für Ihre Praxis", font=(_FF, 9), bg=_BG, fg=_TEXT_SUB, pady=10).pack() tiles_frame = tk.Frame(win, bg=_BG) tiles_frame.pack(expand=True, fill="both", pady=(0, 10), padx=12) _make_tile( tiles_frame, icon="🎙", title="Diktat", subtitle="Aufnahme starten", command=lambda: _safe_call(app, "open_diktat_window"), ).grid(row=0, column=0, padx=6, pady=8, sticky="nsew", ipadx=4, ipady=4) _make_tile( tiles_frame, icon="💬", title="Chat", subtitle="Praxis-Chat öffnen", command=lambda: _safe_call(app, "_send_to_empfang"), ).grid(row=0, column=1, padx=6, pady=8, sticky="nsew", ipadx=4, ipady=4) _make_tile( tiles_frame, icon="🌐", title="Übersetzer", subtitle="Medizinischer Übersetzer", command=lambda: _safe_call(app, "_open_uebersetzer"), ).grid(row=0, column=2, padx=6, pady=8, sticky="nsew", ipadx=4, ipady=4) _make_tile_disabled( tiles_frame, icon="📊", title="Presentation Maker", subtitle="Präsentationen erstellen", status_hint="In Vorbereitung", ).grid(row=0, column=3, padx=6, pady=8, sticky="nsew", ipadx=4, ipady=4) for col in range(4): tiles_frame.columnconfigure(col, weight=1, uniform="tile") tk.Label(win, text="Weitere Add-ons können später ergänzt werden.", font=(_FF, 7), bg=_BG, fg=_TEXT_SUB, pady=6).pack() def _close(): try: app._addon_shell_win = None except Exception: pass try: win.destroy() except Exception: pass win.protocol("WM_DELETE_WINDOW", _close) try: if hasattr(app, "_register_window"): app._register_window(win) except Exception: pass def _safe_call(app: Any, method: str) -> None: """Ruft app.method() sicher auf.""" try: fn = getattr(app, method, None) if callable(fn): fn() except Exception: pass