refactor: Improve dose entry handling in UIManager for better synchronization and user experience
This commit is contained in:
+65
-63
@@ -1,3 +1,4 @@
|
||||
import contextlib
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
@@ -1446,60 +1447,10 @@ class UIManager:
|
||||
quick_frame = ttk.Frame(entry_frame)
|
||||
quick_frame.grid(row=0, column=1, padx=10, pady=5, sticky="w")
|
||||
|
||||
# Create the dose StringVar that will be used for saving
|
||||
dose_string_var = tk.StringVar(value=str(dose_str))
|
||||
# Create the dose StringVar; we'll keep it in sync with the text widget
|
||||
dose_string_var = tk.StringVar(value="")
|
||||
vars_dict[f"{medicine_key}_doses"] = dose_string_var
|
||||
|
||||
# Punch button - updated to use the StringVar properly
|
||||
def create_punch_callback(med_key, entry_var, dose_var):
|
||||
def punch_dose():
|
||||
dose = entry_var.get().strip()
|
||||
if dose:
|
||||
from datetime import datetime
|
||||
|
||||
# Format timestamp for display (12-hour format with AM/PM)
|
||||
timestamp = datetime.now().strftime("%I:%M %p")
|
||||
new_dose = f"• {timestamp} - {dose}"
|
||||
|
||||
current_doses = dose_var.get()
|
||||
if current_doses and current_doses.strip():
|
||||
# Check if current content is placeholder text
|
||||
if "No doses recorded" in current_doses:
|
||||
dose_var.set(new_dose)
|
||||
else:
|
||||
dose_var.set(current_doses + f"\n{new_dose}")
|
||||
else:
|
||||
dose_var.set(new_dose)
|
||||
|
||||
entry_var.set("")
|
||||
|
||||
return punch_dose
|
||||
|
||||
punch_btn = ttk.Button(
|
||||
quick_frame,
|
||||
text=f"Take {medicine.display_name}",
|
||||
command=create_punch_callback(
|
||||
medicine_key, dose_entry_var, dose_string_var
|
||||
),
|
||||
width=15,
|
||||
)
|
||||
punch_btn.grid(row=0, column=0, padx=5)
|
||||
|
||||
# Quick dose buttons
|
||||
quick_doses = self.medicine_manager.get_quick_doses(medicine_key)
|
||||
for i, dose in enumerate(quick_doses[:3]): # Limit to 3 quick doses
|
||||
|
||||
def create_quick_callback(d, entry_var=dose_entry_var):
|
||||
return lambda: entry_var.set(d)
|
||||
|
||||
btn = ttk.Button(
|
||||
quick_frame,
|
||||
text=f"{dose}mg",
|
||||
command=create_quick_callback(dose),
|
||||
width=8,
|
||||
)
|
||||
btn.grid(row=0, column=i + 1, padx=2)
|
||||
|
||||
# Dose history section
|
||||
history_frame = ttk.LabelFrame(
|
||||
tab_frame, text="Dose History (HH:MM: dose)", padding="10"
|
||||
@@ -1521,6 +1472,12 @@ class UIManager:
|
||||
|
||||
# Populate with existing doses using the proper formatting method
|
||||
self._populate_dose_history(dose_text, dose_str)
|
||||
# Initialize the StringVar from the displayed content for consistency
|
||||
try:
|
||||
current_display = dose_text.get("1.0", tk.END).strip()
|
||||
dose_string_var.set(current_display)
|
||||
except Exception:
|
||||
dose_string_var.set("")
|
||||
|
||||
# Bind text widget to update string var - fixed closure issue
|
||||
def create_update_callback(text_widget, dose_var):
|
||||
@@ -1534,21 +1491,66 @@ class UIManager:
|
||||
dose_text.bind("<KeyRelease>", update_callback)
|
||||
dose_text.bind("<FocusOut>", update_callback)
|
||||
|
||||
# Also update text widget when StringVar changes (for punch button)
|
||||
def create_var_to_text_callback(text_widget, string_var):
|
||||
def update_text_from_var(*args):
|
||||
current_text = text_widget.get("1.0", tk.END).strip()
|
||||
var_content = string_var.get()
|
||||
if current_text != var_content:
|
||||
# Do not mirror StringVar back to Text automatically to avoid overwriting
|
||||
# user edits or formatted history; we keep var in sync from Text only.
|
||||
|
||||
# Punch button - append to the Text widget then sync the StringVar
|
||||
def create_punch_callback(med_key, entry_var, text_widget, dose_var):
|
||||
def punch_dose():
|
||||
dose = entry_var.get().strip()
|
||||
if not dose:
|
||||
return
|
||||
from datetime import datetime
|
||||
|
||||
# Format timestamp for display (12-hour format with AM/PM)
|
||||
timestamp = datetime.now().strftime("%I:%M %p")
|
||||
new_dose_line = f"• {timestamp} - {dose}"
|
||||
|
||||
# Ensure widget is editable and read current content
|
||||
with contextlib.suppress(Exception):
|
||||
text_widget.configure(state="normal")
|
||||
current = text_widget.get("1.0", tk.END).strip()
|
||||
|
||||
# Replace placeholder or append
|
||||
if not current or current == "No doses recorded today":
|
||||
updated = new_dose_line
|
||||
else:
|
||||
updated = current + "\n" + new_dose_line
|
||||
|
||||
# Write back to the widget and sync the StringVar
|
||||
text_widget.delete("1.0", tk.END)
|
||||
text_widget.insert("1.0", var_content)
|
||||
text_widget.insert("1.0", updated)
|
||||
dose_var.set(updated)
|
||||
|
||||
return update_text_from_var
|
||||
# Clear the quick entry
|
||||
entry_var.set("")
|
||||
|
||||
var_to_text_callback = create_var_to_text_callback(
|
||||
dose_text, dose_string_var
|
||||
return punch_dose
|
||||
|
||||
punch_btn = ttk.Button(
|
||||
quick_frame,
|
||||
text=f"Take {medicine.display_name}",
|
||||
command=create_punch_callback(
|
||||
medicine_key, dose_entry_var, dose_text, dose_string_var
|
||||
),
|
||||
width=15,
|
||||
)
|
||||
dose_string_var.trace("w", var_to_text_callback)
|
||||
punch_btn.grid(row=0, column=0, padx=5)
|
||||
|
||||
# Quick dose buttons
|
||||
quick_doses = self.medicine_manager.get_quick_doses(medicine_key)
|
||||
for i, dose in enumerate(quick_doses[:3]): # Limit to 3 quick doses
|
||||
|
||||
def create_quick_callback(d, entry_var=dose_entry_var):
|
||||
return lambda: entry_var.set(d)
|
||||
|
||||
btn = ttk.Button(
|
||||
quick_frame,
|
||||
text=f"{dose}mg",
|
||||
command=create_quick_callback(dose),
|
||||
width=8,
|
||||
)
|
||||
btn.grid(row=0, column=i + 1, padx=2)
|
||||
|
||||
# Scrollbar for dose text
|
||||
dose_scroll = ttk.Scrollbar(
|
||||
|
||||
Reference in New Issue
Block a user