import tkinter as tk from tkinter import ttk from PIL import Image, ImageDraw, ImageChops import time import math from .base import View class TimerView(View): def __init__(self, parent, size, center, width=5, **kwargs): self.start_time = None self.elapsed_time = 0 self.is_running = False self.goal_minutes = 0 # 0 means no goal set self.radius = min(center)-width self.width = width super().__init__(parent, size, center, **kwargs) def init_ui(self, parent): self.ui = tk.Frame(parent) self.ui.pack(pady=10) # Goal input self.goal_label = ttk.Label(self.ui, text="Goal (sec):") self.goal_label.pack() self.goal_entry = ttk.Entry(self.ui, width=8) self.goal_entry.insert(0, "0") self.goal_entry.pack() # Timer buttons self.start_stop_button = ttk.Button(self.ui, text="Start", command=self.toggle_timer) self.start_stop_button.pack(side=tk.LEFT, padx=2) self.reset_button = ttk.Button(self.ui, text="Reset", command=self.reset_timer) self.reset_button.pack(side=tk.LEFT, padx=2) def toggle_timer(self): if self.is_running: # Stop timer self.is_running = False if self.start_time: self.elapsed_time += time.time() - self.start_time self.start_stop_button.config(text="Start") else: # Start timer self.is_running = True self.start_time = time.time() self.start_stop_button.config(text="Stop") def reset_timer(self): self.is_running = False self.start_time = None self.elapsed_time = 0 self.start_stop_button.config(text="Start") def get_current_time(self): """Get current elapsed time in seconds""" if self.is_running and self.start_time: return self.elapsed_time + (time.time() - self.start_time) return self.elapsed_time def update_weight(self, weight): """Override to update timer display instead of weight""" current_time = self.get_current_time() # Create base image im = self.bkg_im.copy() draw = ImageDraw.Draw(im) # Format time display (MM:SS) minutes = int(current_time // 60) seconds = int(current_time % 60) time_text = f"{minutes:02d}:{seconds:02d}" if time_text != "00:00" or self.is_running: # Draw timer text in center # Estimate text size for centering text_width = len(time_text) * 10 # Rough estimate text_height = 20 text_x = self.center[0] - text_width // 2 text_y = self.center[1] - text_height // 2 draw.text((text_x, text_y), time_text, fill='black') # Draw progress circle if goal is set try: goal_sec = float(self.goal_entry.get()) if goal_sec > 0: progress = current_time / goal_sec else: progress = current_time / 60 if progress > 0: inverted = int(progress) % 2 == 1 progress = progress % 1.0 # Loop every full circle start = self.center[0] - self.radius, self.center[1] - self.radius end = self.center[0] + self.radius, self.center[1] + self.radius if inverted: draw.arc((start, end), 360 * progress - 90, 270, fill='black', width=self.width) else: draw.arc((start, end), 270, 360 * progress - 90, fill='black', width=self.width) except (ValueError, tk.TclError): # Invalid goal value, just show time without progress pass return im def _draw_progress_arc(self, draw, progress): """Draw a progress arc around the outer circle""" if progress <= 0: return # Draw filled arc by drawing multiple lines from center to circumference center_x, center_y = self.center # Start from top (270 degrees) and go clockwise start_angle = 270 num_steps = max(1, int(360 * progress)) for i in range(num_steps): angle = math.radians(start_angle + i) end_x = center_x + self.outer_radius * math.cos(angle) end_y = center_y + self.outer_radius * math.sin(angle) draw.line([(center_x, center_y), (end_x, end_y)], fill='black', width=1)