refactor: Improve dose entry handling in UIManager for better synchronization and user experience
This commit is contained in:
+66
-64
@@ -1,3 +1,4 @@
|
|||||||
|
import contextlib
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@@ -1446,60 +1447,10 @@ class UIManager:
|
|||||||
quick_frame = ttk.Frame(entry_frame)
|
quick_frame = ttk.Frame(entry_frame)
|
||||||
quick_frame.grid(row=0, column=1, padx=10, pady=5, sticky="w")
|
quick_frame.grid(row=0, column=1, padx=10, pady=5, sticky="w")
|
||||||
|
|
||||||
# Create the dose StringVar that will be used for saving
|
# Create the dose StringVar; we'll keep it in sync with the text widget
|
||||||
dose_string_var = tk.StringVar(value=str(dose_str))
|
dose_string_var = tk.StringVar(value="")
|
||||||
vars_dict[f"{medicine_key}_doses"] = dose_string_var
|
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
|
# Dose history section
|
||||||
history_frame = ttk.LabelFrame(
|
history_frame = ttk.LabelFrame(
|
||||||
tab_frame, text="Dose History (HH:MM: dose)", padding="10"
|
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
|
# Populate with existing doses using the proper formatting method
|
||||||
self._populate_dose_history(dose_text, dose_str)
|
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
|
# Bind text widget to update string var - fixed closure issue
|
||||||
def create_update_callback(text_widget, dose_var):
|
def create_update_callback(text_widget, dose_var):
|
||||||
@@ -1534,21 +1491,66 @@ class UIManager:
|
|||||||
dose_text.bind("<KeyRelease>", update_callback)
|
dose_text.bind("<KeyRelease>", update_callback)
|
||||||
dose_text.bind("<FocusOut>", update_callback)
|
dose_text.bind("<FocusOut>", update_callback)
|
||||||
|
|
||||||
# Also update text widget when StringVar changes (for punch button)
|
# Do not mirror StringVar back to Text automatically to avoid overwriting
|
||||||
def create_var_to_text_callback(text_widget, string_var):
|
# user edits or formatted history; we keep var in sync from Text only.
|
||||||
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:
|
|
||||||
text_widget.delete("1.0", tk.END)
|
|
||||||
text_widget.insert("1.0", var_content)
|
|
||||||
|
|
||||||
return update_text_from_var
|
# 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
|
||||||
|
|
||||||
var_to_text_callback = create_var_to_text_callback(
|
# Format timestamp for display (12-hour format with AM/PM)
|
||||||
dose_text, dose_string_var
|
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", updated)
|
||||||
|
dose_var.set(updated)
|
||||||
|
|
||||||
|
# Clear the quick entry
|
||||||
|
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_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
|
# Scrollbar for dose text
|
||||||
dose_scroll = ttk.Scrollbar(
|
dose_scroll = ttk.Scrollbar(
|
||||||
|
|||||||
Reference in New Issue
Block a user