-
Notifications
You must be signed in to change notification settings - Fork 0
/
UI_TrainingPlanViewerPage.py
238 lines (183 loc) · 11.4 KB
/
UI_TrainingPlanViewerPage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
from email import message
from tkinter import ttk
import tkinter as tk
from tkinter import messagebox
class TrainingPlanReviewPage(ttk.Frame):
class ListCircuit():
"""
Will list all the circuits across the page
"""
def __init__(self, page_frame, circuit_obj,column):
self.circuit_frame = ttk.LabelFrame(page_frame,text=f"Circuit {column+1}")
self.circuit_frame.grid(row=0,column=column,padx=15,pady=15)
for station_index, station_obj in enumerate(circuit_obj.stations):
self.ListStations(self.circuit_frame,station_obj, station_index)
class ListStations():
"""
Will list all of the stations inside of a circuit frame
"""
def __init__(self,circuit_frame,station_obj,station_index):
self.station_frame=ttk.LabelFrame(circuit_frame,text=f"Station {station_index+1}")
self.station_frame.grid(row=station_index,column=0,padx=10,pady=(15,0),sticky="ew")
for set_index,set_obj in enumerate(station_obj.sets):
self.ListExercises(self.station_frame,set_obj,set_index)
class ListExercises():
"""
Controls the creation of a single set in the session plan review page. Abstracts functionality:
- Showing the set as well as reps/time/distance
- Allow for set modification (by double clicking on the field that needs changing)
"""
def bindframe(self,frame,sequence,func):
"""
Used to bind a click event to a function
"""
frame.bind(sequence, func)
for child in frame.winfo_children():
child.bind(sequence, func)
def __init__(self, station_frame, set_obj, set_index):
self.set_index = set_index
# container frame for an individual set
self.set_frame = ttk.Frame(station_frame)
self.set_obj=set_obj
self.setname = ""
self.setlength = ""
self.typeofexercise=""
if self.set_obj.overridename != "":
self.setname=self.set_obj.overridename
else:
self.setname=self.set_obj.exercise_obj.descriptor
if self.set_obj.overridelength != str(0):
self.setlength=self.set_obj.overridelength
self.typeofexercise="custom"
else:
# creating the info display (e.g. Reps: 10 OR Time: 30)
if str(self.set_obj.exercise_obj.format) == str(1):
self.typeofexercise="reps"
self.setlength = str(self.set_obj.length)
elif str(self.set_obj.exercise_obj.format) == str(2):
self.typeofexercise="time/s"
self.setlength = str(self.set_obj.length)
elif str(self.set_obj.exercise_obj.format) == str(3) or str(self.set_obj.exercise_obj.format) == str(4):
self.typeofexercise="distance/m"
self.setlength = str(self.set_obj.length)
# creating the set label (e.g. Set 1: Barbell Squats)
self.set_label = ttk.Label(self.set_frame,text=f"Set {set_index+1}: {self.setname}")
self.info_label = ttk.Label(self.set_frame,text=f"{self.typeofexercise.title()}: {self.setlength}")
self.set_label.grid(row=0,column=0,padx=10,pady=(10,3),sticky="w")
self.info_label.grid(row=1, column=0,padx=10,pady=(0,6),sticky="w")
self.set_frame.grid(row=set_index+1, column=0,sticky="w")
self.bindframe(self.set_label,"<Double-Button-1>",self.setchangerequest)
self.bindframe(self.info_label,"<Double-Button-1>",self.infochangerequest)
def setchangerequest(self,event):
"""
Will replace the set desciptor with an Entry box (pre-filled with existing set value) so the user can change it
"""
self.set_label.grid_forget()
self.set_entry = ttk.Entry(self.set_frame)
self.set_entry.insert(tk.END, self.setname)
self.set_entry.grid(row=0,column=0,sticky="w",padx=10,pady=(10,3))
# bind return (save changes) and escape (cancel changes) keys
self.set_entry.bind("<Return>",self.setapplychanges)
self.set_entry.bind("<Escape>",self.setcancelrequest)
def infochangerequest(self,event):
"""
Will replace the set information text with an Entry box (pre-filled with existing set value) so the user can change it
"""
self.info_label.grid_forget()
self.info_entry = ttk.Entry(self.set_frame)
self.info_entry.insert(tk.END, self.setlength)
self.info_entry.grid(row=1,column=0,sticky="w",padx=10,pady=(0,6))
# bind return (save changes) and escape (cancel changes) keys
self.info_entry.bind("<Return>",self.infoapplychanges)
self.info_entry.bind("<Escape>",self.infocancelrequest)
def setcancelrequest(self,*args):
"""
Will replace existing entry box for the set desciptor with the original text. Note this function can be called when:
- the user pressing escape (whereby the function is directly called, destroys entry boxes - cancelling changes)
- the user pressing return (which first directs to another function - setapplychanges - which will add the new user-defined value to the JSON)
"""
self.set_entry.destroy()
self.set_label.grid(row=0,column=0,sticky="w",padx=10,pady=(10,3))
def infocancelrequest(self,*args):
"""
Will replace existing entry box for the set information text entry with the original text. Note this function can be called when:
- the user pressing escape (whereby the function is directly called, destroys entry boxes - cancelling changes)
- the user pressing return (which first directs to another function - infoapplychanges - which will add the new user-defined value to the JSON)
"""
self.info_entry.destroy()
self.info_label.grid(row=1,column=0,sticky="w",padx=10,pady=(0,6))
def setapplychanges(self,event):
"""
Apply user-defined changes in the Entry box to the JSON (note: this does not change them in secondary storage. The user must press "Save" to do so)
"""
# entry widget string value (what the user has entered)
new_text=self.set_entry.get()
# insert a new exercise name for that set (whatever the user entered)
self.set_obj.overridename = new_text
# change the set label to include the new defined value. This label will be shown in the setcancelrequest() function (which also removes the entry widget)
self.set_label["text"] = f"Set {self.set_index+1}: {new_text}"
self.setcancelrequest()
def infoapplychanges(self,event):
"""
Apply user-defined changes in the Entry box to the JSON (note: this does not change them in secondary storage. The user must press "Save" to do so)
"""
# entry widget string value (what the user has entered)
new_text=self.info_entry.get()
# insert a new value for the exercise reps/distance/time into the JSON
self.set_obj.overridelength=new_text
# change the set label to include the new defined value. This label will be shown in the infocancelrequest() function (which also removes the entry widget)
self.info_label["text"] = f"{new_text}"
self.infocancelrequest()
def savedata(self):
"""
Calls a function in the customer object which applies the new JSON to secondary memory
"""
self.customer.writetofile()
def export_pdf(self):
import Process_GeneratePDF
from tkinter.filedialog import askdirectory
directory = ""
directory = askdirectory()
print(directory)
if directory != "":
try:
Process_GeneratePDF.createsessionplanPDF(self.trainingplan, self.customer.name, directory)
except Exception as e:
messagebox.showerror(title="ERROR", message=f"An error occured when exporting to PDF:\n\n{str(e)}")
def completedatechange(self,date):
self.trainingplan.planned_date = str(date)
self.savedata()
self.injectdata(self.trainingplan, self.customer)
def changeplanneddate(self):
import General_ReuseableDatePopUp
General_ReuseableDatePopUp.dateselect("Select Date", self.completedatechange)
def __init__(self, controller):
ttk.Frame.__init__(self, controller.scrollable_frame)
self.controller = controller
self.info_label = ttk.Label(self)
self.info_label.grid(row=0,column=0,columnspan=100, sticky="w", padx=15, pady=15)
self.save_button = ttk.Button(self,text="Save",command=self.savedata)
self.save_button.grid(row=1,column=0,ipadx=15,columnspan=100, padx=15, pady=5, sticky="w")
self.pdf_export_button = ttk.Button(self,text="Export PDF",command=self.export_pdf)
self.pdf_export_button.grid(row=2,column=0,columnspan=100,ipadx=15, padx=15, pady=5, sticky="w")
self.change_planned_date_button = ttk.Button(self,text="Change Planned Date",command=self.changeplanneddate)
self.change_planned_date_button.grid(row=3,column=0,columnspan=100,ipadx=15, padx=15, pady=5, sticky="w")
def injectdata(self,trainingplan, customer):
"""
Inject specific session plan data in to this page.
Params:
- trainingplanjson: the generated/stored JSON for the session plan
- customer: the customer object for the specific customer that the session plan was made for
"""
self.customer=customer
self.trainingplan=trainingplan
try:
self.master_frame.grid_forget()
self.master_frame.destroy()
except Exception as e: pass
self.master_frame = ttk.Frame(self)
self.master_frame.grid(row=5,column=0)
self.info_label["text"] = f"Session Plan for {self.customer.name}\nLast modified: {self.trainingplan.timestamp}\nPlanned date: {self.trainingplan.planned_date}"
# list all circuits across the page
for column,circuit in enumerate(self.trainingplan.circuits):
self.ListCircuit(self.master_frame, circuit, column)