Files
2026-05-23 16:11:16 -04:00

110 lines
3.4 KiB
Python

"""
ui/widgets.py
-------------
Shared reusable widgets.
ball_color(number, is_bonus) -> (bg_hex, fg_hex)
BallsBar — tk.Canvas that draws a horizontal row of numbered lottery balls
"""
import tkinter as tk
# (low, high, bg_hex, fg_hex) — range-based colour scheme
_RANGES = [
( 1, 9, "#f0f0f0", "#333333"),
(10, 19, "#ffd700", "#333333"),
(20, 29, "#ff7f50", "#ffffff"),
(30, 39, "#4a9edd", "#ffffff"),
(40, 49, "#3cb371", "#ffffff"),
(50, 59, "#9b59b6", "#ffffff"),
(60, 69, "#e74c3c", "#ffffff"),
(70, 99, "#555555", "#ffffff"),
]
_BONUS_BG = "#e74c3c"
_BONUS_FG = "#ffffff"
_FALLBACK = ("#aaaaaa", "#333333")
def ball_color(number: int, is_bonus: bool = False) -> tuple[str, str]:
"""Return (bg_hex, fg_hex) for a lottery ball. Pure function, no Tk needed."""
if is_bonus:
return _BONUS_BG, _BONUS_FG
for lo, hi, bg, fg in _RANGES:
if lo <= number <= hi:
return bg, fg
return _FALLBACK
class BallsBar(tk.Canvas):
"""
Horizontal row of numbered lottery balls drawn on a tk.Canvas.
numbers — list of main ball integers
bonus — optional single bonus ball integer (drawn after a gap, in red)
radius — ball radius in pixels (default 14 → 28 px diameter)
highlights — {number: (bg_hex, fg_hex)} overrides for specific balls
(e.g. green for matched, grey for unmatched in ticket checker)
"""
_GAP = 3 # px between adjacent balls
_SEP = 10 # extra px gap before the bonus ball
def __init__(
self,
parent,
numbers: list[int],
bonus: int | None = None,
radius: int = 14,
highlights: dict | None = None,
**kwargs,
):
self._radius = radius
self._highlights = highlights or {}
diam = radius * 2
n_main = len(numbers)
n_bonus = 1 if bonus is not None else 0
width = (
n_main * (diam + self._GAP)
+ (self._SEP + n_bonus * (diam + self._GAP) if n_bonus else 0)
+ 4
)
height = diam + 4
# Inherit parent background so the canvas blends in seamlessly
if "bg" not in kwargs and "background" not in kwargs:
try:
kwargs["background"] = parent.cget("background")
except Exception:
pass
kwargs.setdefault("highlightthickness", 0)
kwargs.setdefault("bd", 0)
super().__init__(parent, width=width, height=height, **kwargs)
self._draw(numbers, bonus, diam)
def _draw(self, numbers: list[int], bonus: int | None, diam: int):
r = self._radius
x = 2 + r
y = r + 2
for num in numbers:
bg, fg = self._highlights.get(num) or ball_color(num, False)
self._ball(x, y, num, bg, fg)
x += diam + self._GAP
if bonus is not None:
x += self._SEP
bg, fg = self._highlights.get(bonus) or ball_color(bonus, True)
self._ball(x, y, bonus, bg, fg)
def _ball(self, cx: int, cy: int, number: int, bg: str, fg: str):
r = self._radius - 1
self.create_oval(cx - r, cy - r, cx + r, cy + r,
fill=bg, outline="#aaaaaa", width=1)
size = 7 if number >= 10 else 8
self.create_text(cx, cy, text=str(number),
font=("TkDefaultFont", size, "bold"), fill=fg)