mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-09-06 03:20:49 +02:00
80 lines
2.4 KiB
Python
80 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import tkinter as tk
|
|
from collections.abc import Callable, Iterable
|
|
from dataclasses import dataclass
|
|
from tkinter import ttk
|
|
|
|
MessageType = str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class MessageAction:
|
|
label: str
|
|
callback: Callable[[], None]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TabMessage:
|
|
message_type: MessageType
|
|
text: str
|
|
action: MessageAction | None = None
|
|
|
|
|
|
_TYPE_STYLES = {
|
|
"error": "Error",
|
|
"notification": "Notification",
|
|
"warning": "Warning",
|
|
"info": "Info",
|
|
}
|
|
|
|
|
|
class MessageBannerList(ttk.Frame):
|
|
def __init__(self, master: tk.Misc):
|
|
super().__init__(master)
|
|
self.columnconfigure(0, weight=1)
|
|
self._messages: list[TabMessage] = []
|
|
|
|
def set_messages(self, messages: Iterable[TabMessage]) -> None:
|
|
self._messages = [message for message in messages if message.text.strip()]
|
|
self._render()
|
|
if self._messages:
|
|
self.grid()
|
|
else:
|
|
self.grid_remove()
|
|
|
|
def _render(self) -> None:
|
|
for child in self.winfo_children():
|
|
child.destroy()
|
|
for row_index, message in enumerate(self._messages):
|
|
style_name = _message_style_name(message.message_type)
|
|
banner = ttk.Frame(self, style=f"Message{style_name}Border.TFrame", padding=1)
|
|
banner.grid(row=row_index, column=0, sticky="ew", pady=(0, 6))
|
|
banner.columnconfigure(0, weight=1)
|
|
body = ttk.Frame(banner, style=f"Message{style_name}.TFrame", padding=(10, 8))
|
|
body.grid(row=0, column=0, sticky="ew")
|
|
body.columnconfigure(0, weight=1)
|
|
label = ttk.Label(
|
|
body,
|
|
text=message.text,
|
|
style=f"Message{style_name}.TLabel",
|
|
wraplength=900,
|
|
justify="left",
|
|
)
|
|
label.grid(row=0, column=0, sticky="ew")
|
|
body.bind(
|
|
"<Configure>",
|
|
lambda event, target=label: target.configure(wraplength=max(240, event.width - 180)),
|
|
add="+",
|
|
)
|
|
if message.action is not None:
|
|
ttk.Button(
|
|
body,
|
|
text=message.action.label,
|
|
command=message.action.callback,
|
|
).grid(row=0, column=1, sticky="e", padx=(12, 0))
|
|
|
|
|
|
def _message_style_name(message_type: MessageType) -> str:
|
|
return _TYPE_STYLES.get(message_type.casefold(), "Info")
|