mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-08-26 15:25:19 +02:00
feat: initialize CCMA member administration
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import tkinter as tk
|
||||
from importlib import import_module, resources
|
||||
from pathlib import Path
|
||||
from tkinter import ttk
|
||||
|
||||
|
||||
class IconStore:
|
||||
"""Load and cache Material Design icons used by ttk widgets."""
|
||||
|
||||
def __init__(self, master: tk.Misc):
|
||||
self.master = master
|
||||
self.style = ttk.Style(master)
|
||||
self._cache: dict[tuple[str, int, str], tk.PhotoImage | None] = {}
|
||||
self._mat_icon = self._load_mat_icon_class()
|
||||
|
||||
def get(self, name: str, size: int = 16, color: str | None = None) -> tk.PhotoImage | None:
|
||||
resolved_color = color or self._theme_color()
|
||||
key = (name, size, resolved_color)
|
||||
if key not in self._cache:
|
||||
self._cache[key] = self._load(name, size, resolved_color)
|
||||
return self._cache[key]
|
||||
|
||||
def clear(self) -> None:
|
||||
self._cache.clear()
|
||||
|
||||
def _load(self, name: str, size: int, color: str) -> tk.PhotoImage | None:
|
||||
if self._mat_icon:
|
||||
try:
|
||||
return self._mat_icon(name, size=size, color=color).image
|
||||
except Exception:
|
||||
pass
|
||||
return self._load_asset_fallback(name, size)
|
||||
|
||||
def _load_asset_fallback(self, name: str, size: int) -> tk.PhotoImage | None:
|
||||
for module_name in ("ttkbootstrap_icons_mat", "ttkbootstrap_icons"):
|
||||
try:
|
||||
root = resources.files(import_module(module_name))
|
||||
except (ImportError, TypeError):
|
||||
continue
|
||||
candidates = {name, name.replace("-", "_"), name.replace("_", "-")}
|
||||
for candidate in candidates:
|
||||
for extension in (".png", ".gif"):
|
||||
try:
|
||||
path = Path(next(root.rglob(f"{candidate}{extension}")))
|
||||
image = tk.PhotoImage(master=self.master, file=str(path))
|
||||
if size and image.width() > size:
|
||||
factor = max(1, round(image.width() / size))
|
||||
image = image.subsample(factor, factor)
|
||||
return image
|
||||
except (StopIteration, tk.TclError, OSError):
|
||||
continue
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _load_mat_icon_class():
|
||||
try:
|
||||
module = import_module("ttkbootstrap_icons_mat")
|
||||
except ImportError:
|
||||
return None
|
||||
return getattr(module, "MatIcon", None)
|
||||
|
||||
def _theme_color(self) -> str:
|
||||
try:
|
||||
theme_name = self.style.theme_use().lower()
|
||||
except tk.TclError:
|
||||
theme_name = ""
|
||||
if "dark" in theme_name:
|
||||
return "#eeeeee"
|
||||
if "light" in theme_name:
|
||||
return "#313131"
|
||||
background = self.style.lookup("TFrame", "background") or "#ffffff"
|
||||
try:
|
||||
red, green, blue = self.master.winfo_rgb(background)
|
||||
luminance = (0.2126 * red + 0.7152 * green + 0.0722 * blue) / 65535
|
||||
return "#eeeeee" if luminance < 0.5 else "#313131"
|
||||
except tk.TclError:
|
||||
return "#313131"
|
||||
Reference in New Issue
Block a user