feat: Enhance create_edit_window method with dynamic fields and improved layout
This commit is contained in:
@@ -602,52 +602,199 @@ class UIManager:
|
||||
pass
|
||||
|
||||
def create_edit_window(self, values, callbacks):
|
||||
"""Minimal edit window allowing date and note changes.
|
||||
"""Create the full edit window with dynamic fields.
|
||||
|
||||
This simplified version passes missing pathology/medicine values as zeros
|
||||
and an empty dose mapping to the caller's save callback for compatibility.
|
||||
Expected `values` format (as provided by main._create_edit_window):
|
||||
(date,
|
||||
[pathology values...],
|
||||
[for each medicine: taken, doses_string],
|
||||
note)
|
||||
|
||||
On save, call the provided callback with:
|
||||
(window, date, pathology_values..., medicine_values..., note, dose_data_dict)
|
||||
"""
|
||||
win = tk.Toplevel(master=self.root)
|
||||
win.title("Edit Entry")
|
||||
win.transient(self.root)
|
||||
win.minsize(400, 240)
|
||||
win.minsize(520, 420)
|
||||
|
||||
container = ttk.Frame(win, padding=12)
|
||||
container.pack(fill=tk.BOTH, expand=True)
|
||||
# Scrollable content area
|
||||
outer = ttk.Frame(win, padding=12)
|
||||
outer.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
ttk.Label(container, text="Date (mm/dd/yyyy):").grid(
|
||||
row=0, column=0, sticky="w"
|
||||
)
|
||||
date_var = tk.StringVar(value=values[0] if values else "")
|
||||
canvas = tk.Canvas(outer, highlightthickness=0)
|
||||
vscroll = ttk.Scrollbar(outer, orient="vertical", command=canvas.yview)
|
||||
content = ttk.Frame(canvas)
|
||||
content.grid_columnconfigure(1, weight=1)
|
||||
canvas_window_id = canvas.create_window((0, 0), window=content, anchor="nw")
|
||||
canvas.configure(yscrollcommand=vscroll.set)
|
||||
canvas.grid(row=0, column=0, sticky="nsew")
|
||||
vscroll.grid(row=0, column=1, sticky="ns")
|
||||
outer.grid_rowconfigure(0, weight=1)
|
||||
outer.grid_columnconfigure(0, weight=1)
|
||||
|
||||
def _on_configure(_evt=None):
|
||||
canvas.configure(scrollregion=canvas.bbox("all"))
|
||||
|
||||
def _on_canvas_width(_evt=None):
|
||||
# Keep inner frame width in sync so widgets expand
|
||||
bbox = canvas.bbox("all")
|
||||
if bbox:
|
||||
canvas.itemconfigure(canvas_window_id, width=canvas.winfo_width())
|
||||
|
||||
content.bind("<Configure>", _on_configure)
|
||||
canvas.bind("<Configure>", _on_canvas_width)
|
||||
|
||||
# Unpack incoming values using managers' key orders
|
||||
pathology_keys = list(self.pathology_manager.get_pathology_keys())
|
||||
medicine_keys = list(self.medicine_manager.get_medicine_keys())
|
||||
|
||||
idx = 0
|
||||
date_str = values[idx] if values else ""
|
||||
idx += 1
|
||||
|
||||
# Pathology values
|
||||
pathology_values: dict[str, int] = {}
|
||||
for key in pathology_keys:
|
||||
try:
|
||||
pathology_values[key] = int(values[idx])
|
||||
except Exception:
|
||||
pathology_values[key] = 0
|
||||
idx += 1
|
||||
|
||||
# Medicine taken and stored dose strings
|
||||
medicine_taken: dict[str, int] = {}
|
||||
medicine_doses_str: dict[str, str] = {}
|
||||
for key in medicine_keys:
|
||||
try:
|
||||
medicine_taken[key] = int(values[idx])
|
||||
except Exception:
|
||||
medicine_taken[key] = 0
|
||||
idx += 1
|
||||
try:
|
||||
medicine_doses_str[key] = str(values[idx])
|
||||
except Exception:
|
||||
medicine_doses_str[key] = ""
|
||||
idx += 1
|
||||
|
||||
note_val = values[idx] if idx < len(values) else ""
|
||||
|
||||
# --- Build UI ---
|
||||
# Date
|
||||
ttk.Label(content, text="Date (mm/dd/yyyy):").grid(row=0, column=0, sticky="w")
|
||||
date_var = tk.StringVar(value=str(date_str))
|
||||
ttk.Entry(
|
||||
container, textvariable=date_var, justify="center", style="Modern.TEntry"
|
||||
content,
|
||||
textvariable=date_var,
|
||||
justify="center",
|
||||
style="Modern.TEntry",
|
||||
).grid(row=0, column=1, sticky="ew", padx=8, pady=4)
|
||||
|
||||
ttk.Label(container, text="Note:").grid(row=1, column=0, sticky="w")
|
||||
note_val = values[-1] if values else ""
|
||||
# Pathologies section
|
||||
row = 1
|
||||
ttk.Label(content, text="Pathologies:").grid(row=row, column=0, sticky="w")
|
||||
path_frame = ttk.Frame(content)
|
||||
path_frame.grid(row=row, column=1, sticky="ew", padx=8, pady=4)
|
||||
path_frame.grid_columnconfigure(1, weight=1)
|
||||
row += 1
|
||||
|
||||
pathology_vars: dict[str, tk.IntVar] = {}
|
||||
for i, key in enumerate(pathology_keys):
|
||||
pathology_vars[key] = tk.IntVar(value=pathology_values.get(key, 0))
|
||||
pathology = self.pathology_manager.get_pathology(key)
|
||||
label = (
|
||||
pathology.display_name
|
||||
if getattr(pathology, "display_name", None)
|
||||
else key.capitalize()
|
||||
)
|
||||
ttk.Label(path_frame, text=f"{label}:").grid(
|
||||
row=i, column=0, sticky="w", padx=2
|
||||
)
|
||||
scale = ttk.Scale(path_frame, from_=0, to=10, orient=tk.HORIZONTAL)
|
||||
scale.grid(row=i, column=1, sticky="ew", padx=4)
|
||||
with suppress(Exception):
|
||||
scale.set(pathology_vars[key].get())
|
||||
|
||||
# Keep IntVar in sync when dragging
|
||||
def _mk_scale_cmd(k: str, s: ttk.Scale):
|
||||
def _cmd(_evt=None):
|
||||
with suppress(Exception):
|
||||
pathology_vars[k].set(int(float(s.get())))
|
||||
|
||||
return _cmd
|
||||
|
||||
scale.bind("<ButtonRelease-1>", _mk_scale_cmd(key, scale))
|
||||
|
||||
# Medicines section
|
||||
ttk.Label(content, text="Medicines:").grid(row=row, column=0, sticky="w")
|
||||
meds_frame = ttk.Frame(content)
|
||||
meds_frame.grid(row=row, column=1, sticky="ew", padx=8, pady=4)
|
||||
meds_frame.grid_columnconfigure(0, weight=1)
|
||||
row += 1
|
||||
|
||||
medicine_vars: dict[str, tk.IntVar] = {}
|
||||
for i, key in enumerate(medicine_keys):
|
||||
medicine_vars[key] = tk.IntVar(value=medicine_taken.get(key, 0))
|
||||
med = self.medicine_manager.get_medicine(key)
|
||||
text = (
|
||||
med.display_name
|
||||
if getattr(med, "display_name", None)
|
||||
else key.capitalize()
|
||||
)
|
||||
chk = ttk.Checkbutton(
|
||||
meds_frame,
|
||||
text=text,
|
||||
variable=medicine_vars[key],
|
||||
style="Modern.TCheckbutton",
|
||||
)
|
||||
chk.grid(row=i, column=0, sticky="w", padx=2, pady=2)
|
||||
|
||||
# Note field
|
||||
ttk.Label(content, text="Note:").grid(row=row, column=0, sticky="nw")
|
||||
note_var = tk.StringVar(value=str(note_val))
|
||||
ttk.Entry(container, textvariable=note_var, style="Modern.TEntry").grid(
|
||||
row=1, column=1, sticky="ew", padx=8, pady=4
|
||||
ttk.Entry(content, textvariable=note_var, style="Modern.TEntry").grid(
|
||||
row=row, column=1, sticky="ew", padx=8, pady=4
|
||||
)
|
||||
row += 1
|
||||
|
||||
container.grid_columnconfigure(1, weight=1)
|
||||
|
||||
buttons = ttk.Frame(container)
|
||||
buttons.grid(row=2, column=0, columnspan=2, pady=10)
|
||||
# Buttons
|
||||
buttons = ttk.Frame(content)
|
||||
buttons.grid(row=row, column=0, columnspan=2, pady=10)
|
||||
|
||||
def _on_save():
|
||||
# Only provide date and note; caller will default others.
|
||||
# Build args matching main._save_edit expectation
|
||||
args: list[object] = [date_var.get()]
|
||||
# Pathology values in key order
|
||||
for key in pathology_keys:
|
||||
args.append(int(pathology_vars[key].get()))
|
||||
# Medicine 'taken' values in key order
|
||||
for key in medicine_keys:
|
||||
args.append(int(medicine_vars[key].get()))
|
||||
# Note
|
||||
args.append(note_var.get())
|
||||
# Preserve existing dose strings unless caller offers an editor elsewhere
|
||||
dose_map = {k: medicine_doses_str.get(k, "") for k in medicine_keys}
|
||||
args.append(dose_map)
|
||||
with suppress(Exception):
|
||||
callbacks.get("save")(win, date_var.get(), note_var.get(), {})
|
||||
callbacks.get("save")(win, *args)
|
||||
|
||||
def _on_delete():
|
||||
with suppress(Exception):
|
||||
callbacks.get("delete")(win)
|
||||
|
||||
def _on_cancel():
|
||||
with suppress(Exception):
|
||||
win.destroy()
|
||||
|
||||
ttk.Button(buttons, text="Save", command=_on_save, style="Action.TButton").pack(
|
||||
side="left", padx=5
|
||||
)
|
||||
ttk.Button(buttons, text="Delete", command=_on_delete).pack(side="left", padx=5)
|
||||
ttk.Button(buttons, text="Cancel", command=_on_cancel).pack(side="left", padx=5)
|
||||
|
||||
# Finalize scroll region
|
||||
content.update_idletasks()
|
||||
canvas.configure(scrollregion=canvas.bbox("all"))
|
||||
|
||||
return win
|
||||
|
||||
|
||||
Reference in New Issue
Block a user