c3c88c63d2
Build and Push Docker Image / build-and-push (push) Has been cancelled
- Introduced `ThemeManager` to handle application themes using `ttkthemes`. - Added `SettingsWindow` for user preferences including theme selection and UI settings. - Integrated theme selection into the main application with a menu for quick access. - Enhanced UI components with custom styles based on the selected theme. - Implemented tooltips for better user guidance across various UI elements. - Updated dependencies to include `ttkthemes` for improved visual appeal.
164 lines
5.4 KiB
Python
164 lines
5.4 KiB
Python
"""Tooltip system for enhanced user experience."""
|
|
|
|
import tkinter as tk
|
|
|
|
|
|
class ToolTip:
|
|
"""Create a tooltip for a given widget."""
|
|
|
|
def __init__(
|
|
self,
|
|
widget: tk.Widget,
|
|
text: str,
|
|
delay: int = 500,
|
|
wrap_length: int = 250,
|
|
) -> None:
|
|
self.widget = widget
|
|
self.text = text
|
|
self.delay = delay
|
|
self.wrap_length = wrap_length
|
|
self.tooltip: tk.Toplevel | None = None
|
|
self.id_after: str | None = None
|
|
|
|
# Bind events
|
|
self.widget.bind("<Enter>", self._on_enter)
|
|
self.widget.bind("<Leave>", self._on_leave)
|
|
self.widget.bind("<ButtonPress>", self._on_leave)
|
|
|
|
def _on_enter(self, event: tk.Event | None = None) -> None:
|
|
"""Mouse entered widget - schedule tooltip."""
|
|
self._cancel_scheduled()
|
|
self.id_after = self.widget.after(self.delay, self._show_tooltip)
|
|
|
|
def _on_leave(self, event: tk.Event | None = None) -> None:
|
|
"""Mouse left widget - hide tooltip."""
|
|
self._cancel_scheduled()
|
|
self._hide_tooltip()
|
|
|
|
def _cancel_scheduled(self) -> None:
|
|
"""Cancel any scheduled tooltip."""
|
|
if self.id_after:
|
|
self.widget.after_cancel(self.id_after)
|
|
self.id_after = None
|
|
|
|
def _show_tooltip(self) -> None:
|
|
"""Display the tooltip."""
|
|
if self.tooltip:
|
|
return
|
|
|
|
# Get widget position
|
|
x = self.widget.winfo_rootx() + 25
|
|
y = self.widget.winfo_rooty() + 25
|
|
|
|
# Create tooltip window
|
|
self.tooltip = tk.Toplevel(self.widget)
|
|
self.tooltip.wm_overrideredirect(True)
|
|
self.tooltip.wm_geometry(f"+{x}+{y}")
|
|
|
|
# Create tooltip content
|
|
label = tk.Label(
|
|
self.tooltip,
|
|
text=self.text,
|
|
justify="left",
|
|
background="#ffffe0",
|
|
foreground="#000000",
|
|
relief="solid",
|
|
borderwidth=1,
|
|
font=("TkDefaultFont", "9", "normal"),
|
|
wraplength=self.wrap_length,
|
|
padx=8,
|
|
pady=6,
|
|
)
|
|
label.pack()
|
|
|
|
# Make sure tooltip appears above other windows
|
|
self.tooltip.lift()
|
|
|
|
def _hide_tooltip(self) -> None:
|
|
"""Hide the tooltip."""
|
|
if self.tooltip:
|
|
self.tooltip.destroy()
|
|
self.tooltip = None
|
|
|
|
def update_text(self, new_text: str) -> None:
|
|
"""Update the tooltip text."""
|
|
self.text = new_text
|
|
|
|
|
|
class TooltipManager:
|
|
"""Manages tooltips for UI elements."""
|
|
|
|
def __init__(self, theme_manager) -> None:
|
|
self.theme_manager = theme_manager
|
|
self.tooltips: list[ToolTip] = []
|
|
|
|
def add_tooltip(
|
|
self,
|
|
widget: tk.Widget,
|
|
text: str,
|
|
delay: int = 500,
|
|
wrap_length: int = 250,
|
|
) -> ToolTip:
|
|
"""Add a tooltip to a widget."""
|
|
tooltip = ToolTip(widget, text, delay, wrap_length)
|
|
self.tooltips.append(tooltip)
|
|
return tooltip
|
|
|
|
def add_scale_tooltip(self, scale_widget: tk.Widget, pathology_name: str) -> None:
|
|
"""Add a specialized tooltip for pathology scales."""
|
|
text = (
|
|
f"Adjust your {pathology_name} level\\n"
|
|
"• Drag the slider to set your current level\\n"
|
|
"• Higher values typically indicate worse symptoms\\n"
|
|
"• Use the full range for accurate tracking"
|
|
)
|
|
self.add_tooltip(scale_widget, text, delay=800)
|
|
|
|
def add_medicine_tooltip(self, widget: tk.Widget, medicine_name: str) -> None:
|
|
"""Add a specialized tooltip for medicine checkboxes."""
|
|
text = (
|
|
f"Mark if you took {medicine_name} today\\n"
|
|
"• Check the box when you've taken this medication\\n"
|
|
"• This helps track your medication adherence\\n"
|
|
"• You can add dose details when editing entries"
|
|
)
|
|
self.add_tooltip(widget, text, delay=600)
|
|
|
|
def add_button_tooltip(self, widget: tk.Widget, action: str) -> None:
|
|
"""Add a tooltip for action buttons."""
|
|
tooltips_map = {
|
|
"save": (
|
|
"Save your current entry (Ctrl+S)\\nThis will add a new daily record"
|
|
),
|
|
"export": (
|
|
"Export your data to various formats\\n"
|
|
"Supports CSV, PDF, and image exports"
|
|
),
|
|
"refresh": (
|
|
"Reload data from file (F5)\\nUpdates the display with latest changes"
|
|
),
|
|
"settings": (
|
|
"Open application settings (F2)\\nCustomize themes and preferences"
|
|
),
|
|
"quit": (
|
|
"Exit the application (Ctrl+Q)\\nYour data will be automatically saved"
|
|
),
|
|
}
|
|
|
|
text = tooltips_map.get(action, f"Perform {action} action")
|
|
self.add_tooltip(widget, text, delay=400)
|
|
|
|
def add_menu_tooltip(self, widget: tk.Widget, menu_type: str) -> None:
|
|
"""Add tooltips for menu items."""
|
|
tooltips_map = {
|
|
"theme": (
|
|
"Quick theme selection\\nClick to instantly change the app's appearance"
|
|
),
|
|
"file": "File operations\\nExport data and manage files",
|
|
"tools": ("Data management tools\\nConfigure medicines and pathologies"),
|
|
"help": ("Get help and information\\nKeyboard shortcuts and about dialog"),
|
|
}
|
|
|
|
text = tooltips_map.get(menu_type, "Menu options")
|
|
self.add_tooltip(widget, text, delay=600)
|