88from matplotlib .backends .backend_tkagg import FigureCanvasTkAgg
99import customtkinter as ctk
1010from styles import *
11+ from matplotlib .ticker import MaxNLocator
1112
1213APPNAME = "Timer App"
1314FILENAME = "Timer Data.xlsx"
2324WINDOW .title (APPNAME )
2425WINDOW .configure (background = window_color )
2526WINDOW .resizable (False , False )
27+ WINDOW .grid_propagate (False )
2628
2729
2830#---------------------------------------------------------------------------VARIABLES---------------------------------------------------------------------------#
3335start_time = ""
3436goal = 0
3537default_choice = ctk .StringVar (value = "1 hour" )
38+ default_color = ctk .StringVar (value = "Orange" )
39+ color = ""
3640
3741
3842main_frame = ctk .CTkFrame (WINDOW , fg_color = main_frame_color , height = HEIGHT + ((widget_padding_x + frame_padding )* 2 ), width = WIDTH , corner_radius = 0 )
3943main_frame .grid (column = 2 , row = 0 , padx = main_frame_pad_x )
4044main_frame .grid_propagate (False )
4145
42- statistics_frame = ctk .CTkFrame (WINDOW , fg_color = main_frame_color )
46+ statistics_frame = ctk .CTkFrame (WINDOW , fg_color = main_frame_color , height = HEIGHT + (( widget_padding_x + frame_padding ) * 2 ), width = WIDTH , corner_radius = 0 )
4347statistics_frame .grid (column = 2 , row = 0 , padx = main_frame_pad_x )
4448statistics_frame .grid_forget ()
49+ statistics_frame .grid_propagate (False )
50+
51+ settings_frame = ctk .CTkFrame (WINDOW , fg_color = main_frame_color , height = HEIGHT + ((widget_padding_x + frame_padding )* 2 ), width = WIDTH , corner_radius = 0 )
52+ settings_frame .grid (column = 2 , row = 0 , padx = main_frame_pad_x )
53+ settings_frame .grid_forget ()
54+ settings_frame .grid_propagate (False )
4555
4656def customize_excel (worksheet ):
4757 worksheet ["A1" ].value = "Start:"
@@ -58,6 +68,8 @@ def customize_excel(worksheet):
5868 worksheet ["U6" ].value = "Saturday:"
5969 worksheet ["U7" ].value = "Sunday:"
6070
71+ worksheet ["S1" ].value = "Color:"
72+
6173 worksheet ["V1" ].value = monday_amount
6274 worksheet ["V2" ].value = tuesday_amount
6375 worksheet ["V3" ].value = wednesday_amount
@@ -74,6 +86,8 @@ def customize_excel(worksheet):
7486 worksheet ["W6" ].value = saturday_duration
7587 worksheet ["W7" ].value = sunday_duration
7688
89+ worksheet ["T1" ].variable = color
90+
7791 worksheet ["A1" ].font = Font (bold = True , size = 14 )
7892 worksheet ["B1" ].font = Font (bold = True , size = 14 )
7993 worksheet ["C1" ].font = Font (bold = True , size = 14 )
@@ -101,22 +115,23 @@ def create_time_spent_graph(date_list, duration_list):
101115 ax .set_title ("Time Spent by Date" , color = font_color )
102116 ax .tick_params (colors = "white" )
103117 ax .set_facecolor (graph_fg_color )
104- ax .set_xticks (grouped_data ["Date" ])
105- ax .set_yticks (grouped_data ["Duration" ])
106118 fig .set_facecolor (graph_bg_color )
107119 ax .spines ["top" ].set_color (spine_color )
108120 ax .spines ["bottom" ].set_color (spine_color )
109121 ax .spines ["left" ].set_color (spine_color )
110122 ax .spines ["right" ].set_color (spine_color )
111- fig .set_size_inches (5 , 4 , forward = True )
123+ fig .set_size_inches (graph_width / 100 , graph_height / 100 , forward = True )
124+ ax .set_xticklabels (grouped_data ["Date" ], rotation = 45 , ha = 'right' )
112125
113126 date_format = mdates .DateFormatter ("%d/%m" )
114127 ax .xaxis .set_major_formatter (date_format )
115- graph_frame = FigureCanvasTkAgg (fig , master = statistics_frame )
128+ ax .xaxis .set_major_locator (MaxNLocator (integer = True , prune = 'both' ))
129+ time_spent_frame = FigureCanvasTkAgg (fig , master = statistics_frame )
130+ plt .subplots_adjust (bottom = 0.2 )
116131
117- canvas_widget = graph_frame .get_tk_widget ()
118- canvas_widget .grid (row = 4 , column = 0 , padx = 5 , pady = 10 )
119- canvas_widget .config (highlightbackground = frame_border_color , highlightthickness = 2 , background = frame_color )
132+ time_spent_graph = time_spent_frame .get_tk_widget ()
133+ time_spent_graph .grid (row = 0 , column = 0 , padx = 10 , pady = 10 )
134+ time_spent_graph .config (highlightbackground = frame_border_color , highlightthickness = 2 , background = frame_color )
120135
121136 date_list .clear ()
122137 duration_list .clear ()
@@ -188,7 +203,7 @@ def autopct_format(values):
188203 def my_format (pct ):
189204 total = sum (values )
190205 val = int (round (pct * total / 100.0 ))
191- return ' {v:d}' .format (v = val )
206+ return " {v:d}" .format (v = val )
192207 return my_format
193208
194209
@@ -197,14 +212,31 @@ def create_weekday_graph(day_duration_list, day_name_list):
197212 non_zero_names = [name for name , duration in zip (day_name_list , day_duration_list ) if duration != 0 ]
198213
199214 fig , ax = plt .subplots ()
200- ax .pie (non_zero_durations , labels = non_zero_names , autopct = autopct_format (non_zero_durations ), colors = [button_color ], textprops = {'fontsize' : pie_font_size , 'family' : pie_font_family })
201- plt .show ()
215+ ax .pie (non_zero_durations , labels = non_zero_names , autopct = autopct_format (non_zero_durations ),
216+ colors = [pie_color_orange_1 , pie_color_orange_2 , pie_color_orange_3 , pie_color_orange_4 , pie_color_orange_5 , pie_color_orange_6 , pie_color_orange_7 ],
217+ textprops = {"fontsize" : pie_font_size , "family" : pie_font_family , "color" : font_color }, counterclock = False , startangle = 90 )
218+ fig .set_size_inches (graph_width / 100 , graph_height / 100 , forward = True )
219+ fig .set_facecolor (graph_bg_color )
220+ ax .tick_params (colors = "white" )
221+ ax .set_facecolor (graph_fg_color )
222+ ax .set_title ("Time Spent by Weekday" , color = font_color )
223+ ax .spines ["top" ].set_color (spine_color )
224+ ax .spines ["bottom" ].set_color (spine_color )
225+ ax .spines ["left" ].set_color (spine_color )
226+ ax .spines ["right" ].set_color (spine_color )
227+
228+ weekday_frame = FigureCanvasTkAgg (fig , master = statistics_frame )
229+
230+ weekday_graph = weekday_frame .get_tk_widget ()
231+ weekday_graph .grid (row = 0 , column = 1 , padx = 10 , pady = 10 )
232+ weekday_graph .config (highlightbackground = frame_border_color , highlightthickness = 2 , background = frame_color )
202233
203234
204235def collect_data ():
205236 global data_amount , date_list , duration_list
206237 global monday_amount , tuesday_amount , wednesday_amount , thursday_amount , friday_amount , saturday_amount , sunday_amount
207238 global monday_duration , tuesday_duration , wednesday_duration , thursday_duration , friday_duration , saturday_duration , sunday_duration
239+ global color
208240
209241 data_amount = int (worksheet ["Z1" ].value )
210242
@@ -224,11 +256,14 @@ def collect_data():
224256 saturday_duration = int (worksheet ["W6" ].value )
225257 sunday_duration = int (worksheet ["W7" ].value )
226258
259+ color = worksheet ["T1" ].value
260+ if color == "" :
261+ color = "Orange"
262+
227263 day_duration_list = [monday_duration , tuesday_duration , wednesday_duration , thursday_duration , friday_duration , saturday_duration , sunday_duration ]
228264 day_name_list = ["Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" , "Sunday" ]
229265
230- if data_amount > 0 :
231- create_weekday_graph (day_duration_list , day_name_list )
266+ create_weekday_graph (day_duration_list , day_name_list )
232267
233268 for data in range (2 , data_amount + 2 ):
234269 if "/" in str (worksheet ["B" + str (data )].value ):
@@ -337,13 +372,15 @@ def save_data():
337372 start_time = ""
338373 workbook .save (data_file )
339374 print ("Data saved." )
340- collect_data ()
341375 save_weekday ()
376+ collect_data ()
377+
342378
343379def reset_data ():
344380 global data_amount , duration_list , date_list
345381 global timer_time , timer_running , time_display_label
346382 global break_time , break_running , break_display_label
383+ global monday_duration , tuesday_duration , wednesday_duration , thursday_duration , friday_duration , saturday_duration , sunday_duration
347384
348385 data_amount = 0
349386 del workbook [workbook .active .title ]
@@ -357,34 +394,50 @@ def reset_data():
357394
358395 worksheet ["Z1" ].value = int (data_amount )
359396 workbook .save (data_file )
360-
397+ monday_duration , tuesday_duration , wednesday_duration , thursday_duration , friday_duration , saturday_duration , sunday_duration = 0 , 0 , 0 , 0 , 0 , 0 , 0
398+ day_duration_list = [monday_duration , tuesday_duration , wednesday_duration , thursday_duration , friday_duration , saturday_duration , sunday_duration ]
399+ day_name_list = ["Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" , "Sunday" ]
361400 duration_list .clear ()
362401 date_list .clear ()
363402
364403 print ("Data reset." )
365404 create_time_spent_graph (date_list , duration_list )
405+ create_weekday_graph (day_duration_list , day_name_list )
366406 customize_excel (worksheet )
367407
368408
369409def save_on_quit ():
410+ global color
370411 global timer_time
412+
413+ worksheet ["T1" ].value = color
414+ print ("Color saved." )
415+
371416 if timer_time > 0 :
372417 save_data ()
373418 print ("Data saved on exit." )
374419 else : print ("Quit." )
420+
375421 workbook .save (data_file )
376422 WINDOW .destroy ()
377423
378- def to_timer ():
424+ def to_main ():
379425 main_frame .grid (column = 2 , row = 0 , padx = main_frame_pad_x )
380426 main_frame .grid_propagate (False )
381427 statistics_frame .grid_forget ()
382-
428+ settings_frame . grid_forget ()
383429
384430def to_statistics ():
385431 statistics_frame .grid (column = 2 , row = 0 , padx = main_frame_pad_x )
432+ statistics_frame .grid_propagate (False )
386433 main_frame .grid_forget ()
434+ settings_frame .grid_forget ()
387435
436+ def to_settings ():
437+ settings_frame .grid (column = 2 , row = 0 , padx = main_frame_pad_x )
438+ settings_frame .grid_propagate (False )
439+ main_frame .grid_forget ()
440+ statistics_frame .grid_forget ()
388441
389442def get_goal ():
390443 global goal , goal_dropdown
@@ -414,9 +467,27 @@ def set_streak(goal, timer_time, progressbar):
414467 progressbar .set (1 )
415468 worksheet ["E" + str ((data_amount + 1 ))].value = 1
416469
470+ def load_color (color , widget_list , progressbar ):
471+ highlight_colors = {"Orange" : orange_highlight_color , "Green" : green_highlight_color , "Blue" : blue_highlight_color }
472+ highlight_color = highlight_colors [color ]
473+ change_color (color , highlight_color , widget_list , progressbar )
474+
417475
476+ def change_color (color , highlight_color , widget_list , progressbar ):
477+ for widget in widget_list :
478+ widget .configure (fg_color = color , hover_color = highlight_color )
479+ progressbar .configure (progress_color = color )
480+
481+
482+ def set_color (widget ):
483+ global color
484+ color = widget .get ()
485+ colors = {"Orange" : orange_button_color , "Green" : green_button_color , "Blue" : blue_button_color }
486+ highlight_colors = {"Orange" : orange_highlight_color , "Green" : green_highlight_color , "Blue" : blue_highlight_color }
487+ c = colors [color ]
488+ highlight_color = highlight_colors [color ]
489+ change_color (c , highlight_color , widget_list , progressbar )
418490
419-
420491#------------------------------------------------------------------------------GUI------------------------------------------------------------------------------#
421492def change_focus (event ):
422493 event .widget .focus_set ()
@@ -425,9 +496,6 @@ def change_focus(event):
425496tab_frame .grid (column = 0 , row = 0 )
426497tab_frame .pack_propagate (False )
427498
428- border_frame = ctk .CTkFrame (WINDOW , width = BORDER_WIDTH , height = HEIGHT + ((widget_padding_x + frame_padding )* 2 ), fg_color = border_frame_color )
429- border_frame .grid (column = 1 , row = 0 )
430-
431499goal_progress_frame = ctk .CTkFrame (main_frame , height = (HEIGHT - button_height * 1.5 ), width = frame_width )
432500goal_progress_frame .grid (row = 0 , column = 0 )
433501goal_progress_frame .pack_propagate (False )
@@ -497,31 +565,48 @@ def change_focus(event):
497565data_frame .grid_propagate (False )
498566save_data_btn = ctk .CTkButton (data_frame , text = "Save Data" , font = (font_family , font_size ), fg_color = button_color , text_color = button_font_color ,
499567 border_color = frame_border_color , hover_color = button_highlight_color , height = button_height , command = save_data , width = 450 )
500- save_data_btn .place (relx = 0.01 , anchor = "w" , rely = 0.5 )
501- reset_data_btn = ctk .CTkButton (data_frame , text = "Reset Data" , font = (font_family , font_size ), fg_color = button_color , text_color = button_font_color ,
502- border_color = frame_border_color , hover_color = button_highlight_color , height = button_height , command = reset_data , width = 450 )
503- reset_data_btn .place (relx = 0.99 , anchor = "e" , rely = 0.5 )
568+ save_data_btn .place (relx = 0.5 , anchor = "center" , rely = 0.5 )
504569
505570#TABS
506571timer_tab = ctk .CTkFrame (tab_frame , width = tab_frame_width , height = tab_height * 0.8 , fg_color = tab_color )
507572timer_tab .pack (pady = tab_padding_y )
508- timer_tab_btn = ctk .CTkButton (timer_tab , text = "Timer" , font = (tab_font_family , 22 * tab_height / 60 , tab_font_weight ), text_color = font_color ,
509- fg_color = tab_color , width = int (tab_frame_width * 0.95 ), height = int (tab_height * 0.7 ), hover_color = tab_highlight_color , anchor = "w" , command = to_timer )
573+ timer_tab_btn = ctk .CTkButton (timer_tab , text = "Timer" , font = (tab_font_family , 22 * tab_height / 55 , tab_font_weight ), text_color = font_color ,
574+ fg_color = tab_color , width = int (tab_frame_width * 0.95 ), height = int (tab_height * 0.7 ), hover_color = tab_highlight_color , anchor = "w" , command = to_main )
510575timer_tab_btn .place (relx = 0.5 , rely = 0.5 , anchor = "center" )
511576
512577statistics_tab = ctk .CTkFrame (tab_frame , width = tab_frame_width , height = tab_height * 0.8 , fg_color = tab_color )
513578statistics_tab .pack (pady = tab_padding_y )
514- statistics_btn = ctk .CTkButton (statistics_tab , text = "Statistics" , font = (tab_font_family , 22 * tab_height / 60 , tab_font_weight ), text_color = font_color ,
579+ statistics_btn = ctk .CTkButton (statistics_tab , text = "Statistics" , font = (tab_font_family , 22 * tab_height / 55 , tab_font_weight ), text_color = font_color ,
515580 fg_color = tab_color , width = int (tab_frame_width * 0.95 ), height = int (tab_height * 0.7 ), hover_color = tab_highlight_color , anchor = "w" , command = to_statistics )
516581statistics_btn .place (relx = 0.5 , rely = 0.5 , anchor = "center" )
517582
518583settings_tab = ctk .CTkFrame (tab_frame , width = tab_frame_width , height = tab_height * 0.8 , fg_color = tab_color )
519584settings_tab .place (relx = 0.5 , rely = 1 , anchor = "s" )
520- settings_btn = ctk .CTkButton (settings_tab , text = "Settings" , font = (tab_font_family , 22 * tab_height / 60 , tab_font_weight ), text_color = font_color ,
521- fg_color = tab_color , width = int (tab_frame_width * 0.95 ), height = int (tab_height * 0.7 ), hover_color = tab_highlight_color , anchor = "w" )
585+ settings_btn = ctk .CTkButton (settings_tab , text = "Settings" , font = (tab_font_family , 22 * tab_height / 55 , tab_font_weight ), text_color = font_color ,
586+ fg_color = tab_color , width = int (tab_frame_width * 0.95 ), height = int (tab_height * 0.7 ), hover_color = tab_highlight_color , anchor = "w" , command = to_settings )
522587settings_btn .place (relx = 0.5 , rely = 0.5 , anchor = "center" )
523588
524- WINDOW .bind_all ('<Button>' , change_focus )
589+ color_select_frame = ctk .CTkFrame (settings_frame , fg_color = frame_color , height = 200 , width = int (frame_width / 1.25 ), corner_radius = 10 )
590+ color_select_frame .grid (column = 0 , row = 0 , padx = frame_padding , pady = frame_padding )
591+ color_select_frame .pack_propagate (False )
592+ color_label = ctk .CTkLabel (color_select_frame , text = "Color" , font = (font_family , font_size ), text_color = font_color )
593+ color_label .place (anchor = "nw" , relx = 0.05 , rely = 0.05 )
594+ color_dropdown = ctk .CTkComboBox (color_select_frame , values = ["Orange" , "Green" , "Blue" ], variable = default_color , state = "readonly" , width = 150 , height = 30 ,
595+ dropdown_font = (font_family , int (font_size * 0.75 )), font = (font_family , int (font_size )), fg_color = border_frame_color , button_color = border_frame_color )
596+ color_dropdown .place (anchor = "center" , relx = 0.5 , rely = 0.45 )
597+ color_btn = ctk .CTkButton (color_select_frame , text = "Save" , font = (font_family , font_size ), text_color = button_font_color , fg_color = button_color , hover_color = button_highlight_color ,
598+ height = button_height , command = lambda : set_color (color_dropdown ))
599+ color_btn .place (anchor = "s" , relx = 0.5 , rely = 0.9 )
600+
601+ reset_btn_frame = ctk .CTkFrame (settings_frame , fg_color = tab_color )
602+ reset_btn_frame .place (anchor = "s" , relx = 0.5 , rely = 0.985 )
603+ reset_data_btn = ctk .CTkButton (reset_btn_frame , text = "Reset Data" , font = (font_family , font_size ), fg_color = button_color , text_color = button_font_color ,
604+ border_color = frame_border_color , hover_color = button_highlight_color , height = button_height , command = reset_data , width = 450 )
605+ reset_data_btn .pack ()
606+
607+ widget_list = [goal_btn , timer_btn , break_btn , save_data_btn , color_btn , reset_data_btn ]
608+
609+ WINDOW .bind_all ("<Button>" , change_focus )
525610
526611WINDOW .protocol ("WM_DELETE_WINDOW" , save_on_quit )
527612
0 commit comments