update
This commit is contained in:
@@ -2,39 +2,43 @@
|
||||
"""
|
||||
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)
|
||||
Kompaktes Fenster mit Kacheln:
|
||||
- Diktat, Chat, Uebersetzer (aktiv)
|
||||
- Presentation Maker (Platzhalter, deaktiviert)
|
||||
|
||||
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.
|
||||
Keine eigene Modul-Logik — nur Weiterleitung an bestehende app-Methoden.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import tkinter as tk
|
||||
from typing import Any
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
# ── AZA-Design-Konstanten (passend zu aza_office_shell_v1.py) ─────────────────
|
||||
_BG = "#E8F4FA" # hellblauer Fenster-Hintergrund
|
||||
_HDR_BG = "#1A4D6D" # Header-Dunkelblau
|
||||
_BG = "#E8F4FA"
|
||||
_HDR_BG = "#1A4D6D"
|
||||
_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
|
||||
_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) -> tk.Frame:
|
||||
"""Erstellt eine Kachel mit Icon, Titel, Untertitel und Klick-Handler."""
|
||||
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")
|
||||
@@ -44,20 +48,22 @@ def _make_tile(parent: tk.Frame,
|
||||
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))
|
||||
bg=_CARD_BG, fg=_TEXT_SUB, wraplength=130,
|
||||
justify="center").pack(padx=8, pady=(0, 12))
|
||||
|
||||
def _on_enter(e):
|
||||
def _on_enter(_e):
|
||||
card.configure(highlightbackground=_ACCENT)
|
||||
def _on_leave(e):
|
||||
|
||||
def _on_leave(_e):
|
||||
card.configure(highlightbackground=_CARD_BD)
|
||||
def _on_click(e):
|
||||
|
||||
def _on_click(_e):
|
||||
try:
|
||||
command()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for w in [card] + card.winfo_children():
|
||||
for w in [card] + list(card.winfo_children()):
|
||||
w.bind("<Enter>", _on_enter)
|
||||
w.bind("<Leave>", _on_leave)
|
||||
w.bind("<Button-1>", _on_click)
|
||||
@@ -65,12 +71,32 @@ def _make_tile(parent: tk.Frame,
|
||||
return card
|
||||
|
||||
|
||||
def open_addon_shell(app: Any) -> None:
|
||||
"""Oeffnet die Add-on-Huelle als Toplevel.
|
||||
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")
|
||||
|
||||
Wird von basis14.py via _open_addon_shell() aufgerufen.
|
||||
Bereits offenes Fenster wird vorne angezeigt, nicht doppelt geoeffnet.
|
||||
"""
|
||||
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:
|
||||
@@ -81,7 +107,7 @@ def open_addon_shell(app: Any) -> None:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
W, H = 540, 340
|
||||
W, H = 920, 350
|
||||
|
||||
win = tk.Toplevel(app)
|
||||
app._addon_shell_win = win
|
||||
@@ -89,7 +115,6 @@ def open_addon_shell(app: Any) -> None:
|
||||
win.configure(bg=_BG)
|
||||
win.resizable(False, False)
|
||||
|
||||
# Bildschirm-Mitte: update_idletasks() vor Positionierung, damit Fenstergrösse bekannt
|
||||
try:
|
||||
win.transient(app)
|
||||
except Exception:
|
||||
@@ -98,12 +123,11 @@ def open_addon_shell(app: Any) -> None:
|
||||
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
|
||||
y = 80
|
||||
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)
|
||||
@@ -116,12 +140,10 @@ def open_addon_shell(app: Any) -> None:
|
||||
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", "")]:
|
||||
@@ -143,16 +165,14 @@ def open_addon_shell(app: Any) -> None:
|
||||
tk.Label(hdr, text="✕", font=(_FF, 11),
|
||||
bg=_HDR_BG, fg="#A0C4D8",
|
||||
cursor="hand2", padx=14).pack(side="right")
|
||||
hdr.winfo_children()[-1].bind("<Button-1>", lambda e: _close())
|
||||
hdr.winfo_children()[-1].bind("<Button-1>", 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)
|
||||
tiles_frame.pack(expand=True, fill="both", pady=(0, 10), padx=12)
|
||||
|
||||
_make_tile(
|
||||
tiles_frame,
|
||||
@@ -160,7 +180,7 @@ def open_addon_shell(app: Any) -> None:
|
||||
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)
|
||||
).grid(row=0, column=0, padx=6, pady=8, sticky="nsew", ipadx=4, ipady=4)
|
||||
|
||||
_make_tile(
|
||||
tiles_frame,
|
||||
@@ -168,7 +188,7 @@ def open_addon_shell(app: Any) -> None:
|
||||
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)
|
||||
).grid(row=0, column=1, padx=6, pady=8, sticky="nsew", ipadx=4, ipady=4)
|
||||
|
||||
_make_tile(
|
||||
tiles_frame,
|
||||
@@ -176,19 +196,24 @@ def open_addon_shell(app: Any) -> None:
|
||||
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)
|
||||
).grid(row=0, column=2, padx=6, pady=8, sticky="nsew", ipadx=4, 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")
|
||||
_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")
|
||||
|
||||
# ── 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
|
||||
@@ -209,7 +234,7 @@ def open_addon_shell(app: Any) -> None:
|
||||
|
||||
|
||||
def _safe_call(app: Any, method: str) -> None:
|
||||
"""Ruft app.method() sicher auf und schliesst die Kachel nicht bei Fehler."""
|
||||
"""Ruft app.method() sicher auf."""
|
||||
try:
|
||||
fn = getattr(app, method, None)
|
||||
if callable(fn):
|
||||
|
||||
Reference in New Issue
Block a user