Compare commits

...

3 Commits

Author SHA1 Message Date
lm a1c105dba1 Ignore uv artifacts 2025-10-17 13:51:13 +02:00
lm 43c26ce9a6 Remove ttkbootstrap support 2025-10-17 13:11:52 +02:00
lm 7156bbb6c4 Trim toolbar button footprint 2025-10-17 13:08:42 +02:00
6 changed files with 19 additions and 56 deletions

5
.gitignore vendored
View File

@ -145,6 +145,11 @@ cython_debug/
*.ipr *.ipr
*.iws *.iws
# uv / build artifacts
uv.lock
uv/
.uv/
# Git worktree cruft # Git worktree cruft
*.orig *.orig
*.rej *.rej

View File

@ -25,10 +25,6 @@ uv pip install . # install ICRS and dependencies
uv run icrs # launches the GUI uv run icrs # launches the GUI
``` ```
The launcher copies Tcl/Tk resources into the virtualenv on first run, so no manual environment tweaks are needed. The launcher copies Tcl/Tk resources into the virtualenv on first run, so no manual environment tweaks are needed.
To include the optional ttkbootstrap theme pack:
```bash
uv pip install '.[ui]'
```
## Workflow ## Workflow
1. Load an image (`๐Ÿ“‚`) or a folder (`๐Ÿ“`). 1. Load an image (`๐Ÿ“‚`) or a folder (`๐Ÿ“`).

View File

@ -2,13 +2,12 @@
from .color_picker import ColorPickerMixin from .color_picker import ColorPickerMixin
from .exclusions import ExclusionMixin from .exclusions import ExclusionMixin
from .theme import ThemeMixin, HAS_TTKBOOTSTRAP from .theme import ThemeMixin
from .ui import UIBuilderMixin from .ui import UIBuilderMixin
__all__ = [ __all__ = [
"ColorPickerMixin", "ColorPickerMixin",
"ExclusionMixin", "ExclusionMixin",
"ThemeMixin", "ThemeMixin",
"HAS_TTKBOOTSTRAP",
"UIBuilderMixin", "UIBuilderMixin",
] ]

View File

@ -5,14 +5,6 @@ from __future__ import annotations
import platform import platform
from tkinter import ttk from tkinter import ttk
try:
import ttkbootstrap as tb # type: ignore
HAS_TTKBOOTSTRAP = True
except Exception: # pragma: no cover - optional dependency
tb = None
HAS_TTKBOOTSTRAP = False
try: try:
import winreg import winreg
except Exception: # pragma: no cover - platform-specific except Exception: # pragma: no cover - platform-specific
@ -24,27 +16,12 @@ class ThemeMixin:
theme: str theme: str
style: ttk.Style style: ttk.Style
using_tb: bool
scale_style: str scale_style: str
def init_theme(self) -> None: def init_theme(self) -> None:
"""Initialise ttk style handling and apply the detected theme.""" """Initialise ttk style handling and apply the detected theme."""
if HAS_TTKBOOTSTRAP: self.style = ttk.Style()
try: self.style.theme_use("clam")
try:
self.root.tk.call("package", "require", "msgcat") # type: ignore[attr-defined]
except Exception:
pass
self.style = tb.Style()
self.using_tb = True
except Exception:
self.style = ttk.Style()
self.style.theme_use("clam")
self.using_tb = False
else:
self.style = ttk.Style()
self.style.theme_use("clam")
self.using_tb = False
self.theme = "light" self.theme = "light"
self.apply_theme(self.detect_system_theme()) self.apply_theme(self.detect_system_theme())
@ -54,17 +31,7 @@ class ThemeMixin:
mode = (mode or "light").lower() mode = (mode or "light").lower()
self.theme = "dark" if mode == "dark" else "light" self.theme = "dark" if mode == "dark" else "light"
if HAS_TTKBOOTSTRAP: self.scale_style = "Horizontal.TScale"
try:
theme_name = "darkly" if self.theme == "dark" else "flatly"
self.style.theme_use(theme_name)
except Exception:
pass
self.scale_style = (
"info.Horizontal.TScale" if self.theme == "dark" else "primary.Horizontal.TScale"
)
else:
self.scale_style = "Horizontal.TScale"
if self.theme == "dark": if self.theme == "dark":
bg, fg = "#0f0f10", "#f1f1f1" bg, fg = "#0f0f10", "#f1f1f1"
@ -77,11 +44,10 @@ class ThemeMixin:
s = self.style s = self.style
s.configure("TFrame", background=bg) s.configure("TFrame", background=bg)
s.configure("TLabel", background=bg, foreground=fg, font=("Segoe UI", 10)) s.configure("TLabel", background=bg, foreground=fg, font=("Segoe UI", 10))
if not HAS_TTKBOOTSTRAP: s.configure(
s.configure( "TButton", padding=8, relief="flat", background="#e0e0e0", foreground=fg, font=("Segoe UI", 10)
"TButton", padding=8, relief="flat", background="#e0e0e0", foreground=fg, font=("Segoe UI", 10) )
) s.map("TButton", background=[("active", "#d0d0d0")])
s.map("TButton", background=[("active", "#d0d0d0")])
button_refresher = getattr(self, "_refresh_toolbar_buttons_theme", None) button_refresher = getattr(self, "_refresh_toolbar_buttons_theme", None)
if callable(button_refresher): if callable(button_refresher):
@ -123,4 +89,4 @@ class ThemeMixin:
self.update_preview() # type: ignore[attr-defined] self.update_preview() # type: ignore[attr-defined]
__all__ = ["ThemeMixin", "HAS_TTKBOOTSTRAP"] __all__ = ["ThemeMixin"]

View File

@ -192,11 +192,11 @@ class UIBuilderMixin:
swatch.bind("<Leave>", lambda _e: swatch.configure(highlightbackground="#b1b1b6")) swatch.bind("<Leave>", lambda _e: swatch.configure(highlightbackground="#b1b1b6"))
def _add_toolbar_button(self, parent, text: str, command) -> None: def _add_toolbar_button(self, parent, text: str, command) -> None:
font = tkfont.Font(root=self.root, family="Segoe UI", size=10, weight="bold") font = tkfont.Font(root=self.root, family="Segoe UI", size=9)
padding_x = 18 padding_x = 12
width = font.measure(text) + padding_x * 2 width = font.measure(text) + padding_x * 2
height = 32 height = 28
radius = 12 radius = 9
bg = self.root.cget("bg") if hasattr(self.root, "cget") else "#f2f2f7" bg = self.root.cget("bg") if hasattr(self.root, "cget") else "#f2f2f7"
canvas = tk.Canvas( canvas = tk.Canvas(
parent, parent,
@ -209,7 +209,7 @@ class UIBuilderMixin:
cursor="hand2", cursor="hand2",
takefocus=1, takefocus=1,
) )
canvas.pack(side=tk.LEFT, padx=6) canvas.pack(side=tk.LEFT, padx=4, pady=1)
palette = self._toolbar_palette() palette = self._toolbar_palette()
rect_id = self._create_round_rect( rect_id = self._create_round_rect(

View File

@ -10,9 +10,6 @@ dependencies = [
"pillow>=10.0.0", "pillow>=10.0.0",
] ]
[project.optional-dependencies]
ui = ["ttkbootstrap>=1.10.0"]
[project.scripts] [project.scripts]
icrs = "app.launcher:main" icrs = "app.launcher:main"