diff --git a/taskon/config.py b/taskon/config.py index a772fdf..ff6a8a3 100644 --- a/taskon/config.py +++ b/taskon/config.py @@ -30,3 +30,44 @@ def __init__(self, work_min=20, short_break_min=5, long_break_min=20, self.WORK_REPS = work_reps self.COUNTER_SECOND = counter_second self.INITIAL_VALUE = initial_value + + @property + def work_min(self): + return self.WORK_MIN + + @work_min.setter + def work_min(self, value): + if value < 0: + raise ValueError("Work minutes must be non-negative.") + self.WORK_MIN = value + + @property + def short_break_min(self): + return self.SHORT_BREAK_MIN + + @short_break_min.setter + def short_break_min(self, value): + if value < 0: + raise ValueError("Short break must be non-negative.") + self.SHORT_BREAK_MIN = value + + @property + def long_break_min(self): + return self.LONG_BREAK_MIN + + @long_break_min.setter + def long_break_min(self, value): + if value < 0: + raise ValueError("Long break must be non-negative.") + self.LONG_BREAK_MIN = value + + @property + def work_reps(self): + return self.WORK_REPS + + @work_reps.setter + def work_reps(self, value): + if value < 0: + raise ValueError("Work repetitions must be non-negative.") + self.WORK_REPS = value + diff --git a/taskon/main.py b/taskon/main.py index 1d38803..6154203 100644 --- a/taskon/main.py +++ b/taskon/main.py @@ -8,6 +8,7 @@ from tkinter import Tk from taskon.app import TaskOnApp +from taskon.messagebox import CustomInputDialog from taskon.resources import ResourceLoader from taskon.audio_service import PygameAudionService from taskon.config import TaskConfig @@ -17,8 +18,10 @@ def main(): """ Initialize and run the TaskOn application. """ - # Create the main application window + # Create the main application window and hide root = Tk() + root.withdraw() + root.title("TaskOn") root.geometry("250x350") root.config(padx=5, pady=5, bg="#fdfdfd") @@ -29,6 +32,7 @@ def main(): icon_path = loader.get_resource_path("growing-seed.ico") root.iconbitmap(icon_path) + images = { "moon": loader.load_image("clock-green.png"), "oak": loader.load_image("growing-seed.png"), @@ -44,11 +48,29 @@ def main(): audio = PygameAudionService() config = TaskConfig() - # Start the TaskOn application - TaskOnApp(root, images, audio, config) + # Ask for user input + dialog = CustomInputDialog(root, prompt="Enter number of study minutes:", icon_path=icon_path) + root.wait_window(dialog) + + value = dialog.result + + if value is not None: + try: + minutes = int(value) + config.work_min = minutes + + # Show main window + root.deiconify() + + # Start the TaskOn application + TaskOnApp(root, images, audio, config) - # Run the Tkinter main loop - root.mainloop() + # Run the Tkinter main loop + root.mainloop() + except ValueError: + raise ValueError("Invalid input. Please enter a valid number.") + else: + root.destroy() if __name__ == "__main__": diff --git a/taskon/messagebox.py b/taskon/messagebox.py new file mode 100644 index 0000000..7ff350e --- /dev/null +++ b/taskon/messagebox.py @@ -0,0 +1,73 @@ +import tkinter as tk + +class CustomInputDialog(tk.Toplevel): + """ + Custom input dialog that accepts an integer value. + + Args: + parent (tk.Widget): Parent widget. + prompt (str): Prompt text to display. + default (str): Default value in the entry field (default "20"). + icon_path (str, optional): Path to icon file for the window. + """ + + def __init__(self, parent, prompt, default="20", icon_path=None): + super().__init__(parent) + self.title("TaskOn") + self.geometry("220x100") + self.result = None + + + if icon_path: + try: + self.iconbitmap(icon_path) + except Exception as e: + print("Failed to set icon:", e) + + # Prompt label + tk.Label(self, text=prompt).pack(pady=3) + + # Entry field + self.entry = tk.Entry(self, width=30) + self.entry.insert(0, default) + self.entry.pack(pady=5, padx=10) + self.entry.focus_set() + + # Button frame + btn_frame = tk.Frame(self) + btn_frame.pack(pady=10) + + # Button style configuration + button_style = { + "width": 10, + "height": 1, + "bg": "#4CAF50", + "fg": "white", + "activebackground": "#45a049", + "activeforeground": "white", + "bd": 0, + "font": ("Arial", 9, "bold") + } + + cancel_style = button_style.copy() + cancel_style["bg"] = "#f44336" + cancel_style["activebackground"] = "#d32f2f" + + # OK and Cancel buttons + tk.Button(btn_frame, text="OK", command=self.on_ok, **button_style).pack(side="left", padx=5) + tk.Button(btn_frame, text="Cancel", command=self.on_cancel, **cancel_style).pack(side="left", padx=5) + + # Key bindings + self.bind("", lambda event: self.on_ok()) + self.bind("", lambda event: self.on_cancel()) + + def on_ok(self): + value = self.entry.get() + if not value.isdigit(): + raise ValueError("Work minutes must be an integer.") + self.result = int(value) + self.destroy() + + def on_cancel(self): + self.result = None + self.destroy()