diff --git a/timer.py b/timer.py index d01d7e7..e626c0f 100755 --- a/timer.py +++ b/timer.py @@ -1,23 +1,24 @@ #!/bin/env python3 import datetime -from tkinter import Tk, CENTER, Label +from tkinter import Tk, CENTER, Label, font import click import typing as t DELTA_SECONDS = "+%Ss" DELTA_MINUTES = "+%Mm" DELTA_HOURS = "+%Hh" -HOURS = "%H:%M" +TIME_TODAY = "%H:%M" DATETIME_FORMAT = [ "%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M", - HOURS, + TIME_TODAY, DELTA_HOURS, DELTA_MINUTES, DELTA_SECONDS, ] +FONT = "Liberation Sans" class DateTime(click.DateTime): @@ -36,7 +37,7 @@ class DateTime(click.DateTime): return datetime.datetime.now() + datetime.timedelta( hours=int(value[1:-1]) ) - if format == HOURS: + if format == TIME_TODAY: return datetime.datetime.combine( datetime.datetime.now().date(), datetime.datetime.strptime(value, format).time(), @@ -46,37 +47,89 @@ class DateTime(click.DateTime): return None -def start_app(end_date): - root = Tk() - root.geometry("300x100+200+200") - root.configure(background="#000") - timer_label = Label(root, text="", font=("Arial", -100), fg="#fff", bg="#000") - timer_label.pack() - timer_label.place(relx=0.5, rely=0.5, anchor=CENTER) +class Timer: + def __init__(self, end_date): + self.end_date = end_date + self.update() - def format_delta(t): - days, remainder = divmod(t.total_seconds(), 60 * 60 * 24) + def update(self): + self.delta = self.end_date - datetime.datetime.now() + + def calc_delta(self): + days, remainder = divmod(self.delta.total_seconds(), 60 * 60 * 24) hours, remainder = divmod(remainder, 3600) minutes, seconds = divmod(remainder, 60) + return int(days), int(hours), int(minutes), int(seconds) + + @classmethod + def get_format(cls, days, hours, minutes, seconds): if days == 0: if hours == 0: if minutes == 0: - return f"{int(seconds):02d}" - return f"{int(minutes):02d}:{int(seconds):02d}" - return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}" - return f"{int(days):02d}:{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}" + return "{seconds:02d}" + return "{minutes:02d}:{seconds:02d}" + return "{hours:02d}:{minutes:02d}:{seconds:02d}" + return "{days:02d}:{hours:02d}:{minutes:02d}:{seconds:02d}" + + def __str__(self): + days, hours, minutes, seconds = self.calc_delta() + return self.get_format(days, hours, minutes, seconds).format( + days=days, hours=hours, minutes=minutes, seconds=seconds + ) + + +current_size = { + "format": Timer.get_format(9, 9, 9, 9), + "height": 800, + "width": 800, +} + + +def start_app(end_date): + timer = Timer(end_date) + root = Tk() + root.geometry("300x100+200+200") + root.configure(background="#000") + font_instance = font.Font(font=(FONT, -100)) + timer_label = Label(root, text="", font=font_instance, fg="#fff", bg="#000") + timer_label.pack() + timer_label.place(relx=0.5, rely=0.5, anchor=CENTER) + fixed_font_instance = font.Font(font=(FONT, -100)) def resize(_): - ratio = root.winfo_width() / 1920 - timer_label.configure(font=("Chicago", int(ratio * -200))) + global current_size + try: + next_size = { + "format": timer.get_format( + *(99 if x else 0 for x in timer.calc_delta()) + ), + "height": root.winfo_height(), + "width": root.winfo_width(), + } + if current_size != next_size: + next_font_height = int( + min( + root.winfo_height(), + ( + root.winfo_width() + / fixed_font_instance.measure(next_size["format"]) + ) + * 250, + ) + ) + font_instance.config(size=next_font_height) + timer_label.configure(font=font_instance) + current_size = next_size + except ZeroDivisionError: + pass def update(): - delta = end_date - datetime.datetime.now() - if delta.total_seconds() < 0: + timer.update() + if timer.delta.total_seconds() <= 0: timer_label.configure(text="Now") timer_label.config(fg="red") else: - timer_label.configure(text=format_delta(delta)) + timer_label.configure(text=str(timer)) root.after(1000 - datetime.datetime.now().microsecond // 1000, update) root.bind("", resize)