# -*- coding: utf-8 -*- """ aza_addon_shell.py — AZA Add-on-Huelle Modernes, kompaktes Fenster mit zwei Kacheln: - Chat → _send_to_empfang (bestehende Funktion) - Uebersetzer → _open_uebersetzer (bestehende Funktion) Keine eigene Chat-/Uebersetzungslogik. Nur Weiterleitung. Schliesst sich nicht, wenn AZA geschlossen wird — wird als Toplevel an das Hauptfenster gehaengt und durch WM_DELETE_WINDOW sauber beendet. """ from __future__ import annotations import tkinter as tk from typing import Any # ── AZA-Design-Konstanten (passend zu aza_office_shell_v1.py) ───────────────── _BG = "#E8F4FA" # hellblauer Fenster-Hintergrund _HDR_BG = "#1A4D6D" # Header-Dunkelblau _HDR_FG = "#FFFFFF" _CARD_BG = "#FFFFFF" # Kartenhintergrund _CARD_BD = "#C8D8E8" # Kartenrahmen _ACCENT = "#5B8DB3" # Akzentblau _ACCENT_H = "#4A7A9E" # Hover _TEXT = "#1A3D55" # Haupttext _TEXT_SUB = "#607890" # Untertitel / subtile Texte _FF = "Segoe UI" def _make_tile(parent: tk.Frame, icon: str, title: str, subtitle: str, command) -> tk.Frame: """Erstellt eine Kachel mit Icon, Titel, Untertitel und Klick-Handler.""" 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=160, justify="center").pack(padx=10, 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] + card.winfo_children(): w.bind("", _on_enter) w.bind("", _on_leave) w.bind("", _on_click) return card def open_addon_shell(app: Any) -> None: """Oeffnet die Add-on-Huelle als Toplevel. Wird von basis14.py via _open_addon_shell() aufgerufen. Bereits offenes Fenster wird vorne angezeigt, nicht doppelt geoeffnet. """ 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 = 540, 340 win = tk.Toplevel(app) app._addon_shell_win = win win.title("AzA Add-on Beta") win.configure(bg=_BG) win.resizable(False, False) # Bildschirm-Mitte: update_idletasks() vor Positionierung, damit Fenstergrösse bekannt try: win.transient(app) except Exception: pass try: win.update_idletasks() sw = win.winfo_screenwidth() x = max(0, (sw - W) // 2) y = 80 # oben-mittig: horizontal zentriert, ca. 80 px vom oberen Rand win.geometry(f"{W}x{H}+{x}+{y}") except Exception: win.geometry(f"{W}x{H}") # Kurz topmost damit das Fenster klar vorne ist, danach wieder normal. 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 # ── Header ──────────────────────────────────────────────────────────────── hdr = tk.Frame(win, bg=_HDR_BG) hdr.pack(fill="x") try: from aza_config import get_writable_data_dir 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()) # ── Untertitel ──────────────────────────────────────────────────────────── tk.Label(win, text="Zusätzliche Werkzeuge für Ihre Praxis", font=(_FF, 9), bg=_BG, fg=_TEXT_SUB, pady=10).pack() # ── Kacheln ─────────────────────────────────────────────────────────────── tiles_frame = tk.Frame(win, bg=_BG) tiles_frame.pack(expand=True, pady=(0, 10), padx=16) _make_tile( tiles_frame, icon="🎙", title="Diktat", subtitle="Aufnahme starten", command=lambda: _safe_call(app, "open_diktat_window"), ).grid(row=0, column=0, padx=8, pady=8, sticky="nsew", ipadx=10, 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=8, pady=8, sticky="nsew", ipadx=10, 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=8, pady=8, sticky="nsew", ipadx=10, ipady=4) tiles_frame.columnconfigure(0, weight=1, uniform="tile") tiles_frame.columnconfigure(1, weight=1, uniform="tile") tiles_frame.columnconfigure(2, weight=1, uniform="tile") # ── Fusszeile ───────────────────────────────────────────────────────────── 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() # ── Close-Handler ───────────────────────────────────────────────────────── 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 und schliesst die Kachel nicht bei Fehler.""" try: fn = getattr(app, method, None) if callable(fn): fn() except Exception: pass