mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-08-26 07:15:20 +02:00
80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
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"
|