import tkinter as tk from tkinter import ttk class ThemeManager: """Manager for application theme configuration (defaulting to light theme).""" def __init__(self, root): """ Initialize the theme manager and apply the light theme. Args: root: The Tkinter root window (needed for background config). """ self.root = root self.style = ttk.Style() self.apply_theme() # Directly apply light theme def apply_theme(self): """Applies the light theme.""" self._apply_light_theme() # Ensure the root window background matches the theme try: bg_color = self.style.lookup('.', 'background') self.root.configure(background=bg_color) except tk.TclError: # Fallback if style lookup fails self.root.configure(background='SystemButtonFace') def _apply_light_theme(self): """Configure a standard light theme using system defaults where possible.""" try: # Use a standard theme, preferring OS native look available_themes = self.style.theme_names() # Windows preference order preferred_themes = ['vista', 'xpnative', 'clam', 'alt', 'default'] chosen_theme = 'default' for theme in preferred_themes: if theme in available_themes: try: self.style.theme_use(theme) chosen_theme = theme # print(f"Using theme: {chosen_theme}") # Debug break except tk.TclError: continue # Reset most styles to theme defaults by configuring with empty strings # or removing specific configure calls if they were only for dark theme. # Explicitly set base theme colors for light mode self.style.configure('.', background='SystemButtonFace', foreground='SystemWindowText') self.style.configure('TFrame', background='SystemButtonFace') # Explicitly set foreground AND background for visibility self.style.configure('TLabel', foreground='SystemWindowText', background='SystemButtonFace') # Explicitly set foreground AND background for visibility self.style.configure('TButton', foreground='SystemWindowText', background='SystemButtonFace', padding=5) # Reset button border color explicitly if needed, or remove if SystemButtonFace is desired self.style.configure('TButton', bordercolor='SystemGrayText') # Example: Use a visible border self.style.map('TButton', background=[('active', 'SystemButtonHighlight'), ('pressed', '!focus', 'SystemButtonFace'), ('focus', 'SystemButtonHighlight')]) # Example map # Keep Danger button distinct self.style.configure('Danger.TButton', foreground='black', background='#cc3333', bordercolor='#aa2222', padding=5) # Enhanced danger button self.style.map('Danger.TButton', background=[('active', '#dd4444'), ('pressed', '#bb2222')], foreground=[('active', 'black'), ('pressed', 'black')]) # TEntry: Use defaults. Let's ensure its colors are sensible too. self.style.configure('TEntry', foreground='SystemWindowText', fieldbackground='SystemWindow', insertcolor='SystemWindowText', bordercolor='SystemGrayText') # self.style.map('TEntry') # Reset map - might not be needed if configure is explicit self.style.configure('TLabelframe', background='SystemButtonFace', bordercolor='SystemGrayText') # Ensure label frame labels are also visible self.style.configure('TLabelframe.Label', background='SystemButtonFace', foreground='SystemWindowText') # TNotebook adjustments (if needed, often inherit well) self.style.configure('TNotebook', background='SystemButtonFace', bordercolor='SystemGrayText', tabmargins=[2, 5, 2, 0]) self.style.configure('TNotebook.Tab', foreground='SystemWindowText', background='SystemButtonFace', padding=[10, 5]) self.style.map('TNotebook.Tab', background=[('selected', 'SystemButtonHighlight')]) # Example map # Progressbar and Scrollbar adjustments self.style.configure('Horizontal.TProgressbar', background='SystemHighlight', troughcolor='SystemButtonFace', bordercolor='SystemGrayText') self.style.configure('TScrollbar', troughcolor='SystemButtonFace', background='SystemScrollbar', bordercolor='SystemGrayText', arrowcolor='SystemWindowText') # self.style.map('TScrollbar') # Reset map except Exception as e: print(f"Error applying light theme: {e}") def get_scrolledtext_colors(self): """Returns appropriate background/foreground colors for ScrolledText (light theme defaults).""" # Always return light theme defaults now try: default_bg = self.root.option_get('background', 'Text') default_fg = self.root.option_get('foreground', 'Text') insert_bg = self.root.option_get('insertBackground', 'Text') if not default_bg: default_bg = 'SystemWindow' # Tk default color name if not default_fg: default_fg = 'SystemWindowText' if not insert_bg: insert_bg = default_fg # Cursor color often matches text return {'bg': default_bg, 'fg': default_fg, 'insertbackground': insert_bg} except tk.TclError: # Fallback if options can't be retrieved return {'bg': 'white', 'fg': 'black', 'insertbackground': 'black'}