diff --git a/src/IRCPanel.py b/src/IRCPanel.py index c78ee35..6a4c5f3 100644 --- a/src/IRCPanel.py +++ b/src/IRCPanel.py @@ -14,15 +14,18 @@ class IRCPanel(wx.Panel): self.parent = parent self.main_frame = main_frame self.messages = [] + self.theme = getattr(self.main_frame, "theme", None) + self.default_text_colour = self.theme["text"] if self.theme else wx.Colour(0, 0, 0) sizer = wx.BoxSizer(wx.VERTICAL) # Use a better font for chat with white theme self.text_ctrl = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2 | wx.TE_AUTO_URL) - # White theme colors - self.text_ctrl.SetBackgroundColour(wx.Colour(255, 255, 255)) # White background - self.text_ctrl.SetForegroundColour(wx.Colour(0, 0, 0)) # Black text + if self.theme: + self.text_ctrl.SetBackgroundColour(self.theme["content_bg"]) + self.text_ctrl.SetForegroundColour(self.theme["text"]) + self.SetBackgroundColour(self.theme["content_bg"]) # Load appropriate font self.font = self.load_system_font() @@ -143,7 +146,7 @@ class IRCPanel(wx.Panel): if message_color: attr.SetTextColour(message_color) else: - attr.SetTextColour(wx.Colour(0, 0, 0)) # Black text for white theme + attr.SetTextColour(self.default_text_colour) attr.SetFont(self.font) self.text_ctrl.SetDefaultStyle(attr) @@ -169,7 +172,7 @@ class IRCPanel(wx.Panel): self.add_message(message, f"* {username}", username_color, wx.Colour(128, 0, 128), italic=True) # Dark purple for actions else: message = f"{timestamp}<{username}> {content}" - self.add_message(message, f"<{username}>", username_color, wx.Colour(0, 0, 0)) # Black text + self.add_message(message, f"<{username}>", username_color, self.default_text_colour) except Exception as e: logger.error(f"Error adding formatted message: {e}") diff --git a/src/NotesDialog.py b/src/NotesDialog.py index 39af057..28eb524 100644 --- a/src/NotesDialog.py +++ b/src/NotesDialog.py @@ -19,6 +19,7 @@ class NotesDialog(wx.Frame): style=wx.DEFAULT_FRAME_STYLE) self.parent = parent + self.theme = getattr(parent, "theme", None) self.notes_data = notes_data or defaultdict(dict) self.current_note_key = None self.updating_title = False @@ -27,7 +28,7 @@ class NotesDialog(wx.Frame): self.last_save_time = time.time() self.auto_save_interval = 2 # seconds - reduced for immediate saving - self.SetBackgroundColour(wx.Colour(245, 245, 245)) + self.SetBackgroundColour(self.get_theme_colour("window_bg", wx.SystemSettings().GetColour(wx.SYS_COLOUR_WINDOW))) # Set icon if parent has one if parent: @@ -60,6 +61,11 @@ class NotesDialog(wx.Frame): def close_parent(self, pId): if self.GetParent().GetId() == pId: self.GetParent().Close() + + def get_theme_colour(self, key, fallback): + if self.theme and key in self.theme: + return self.theme[key] + return fallback def create_controls(self): # Create menu bar @@ -72,6 +78,7 @@ class NotesDialog(wx.Frame): # Left panel - notes list left_panel = wx.Panel(splitter) + left_panel.SetBackgroundColour(self.get_theme_colour("sidebar_bg", left_panel.GetBackgroundColour())) left_sizer = wx.BoxSizer(wx.VERTICAL) notes_label = wx.StaticText(left_panel, label="Your Notes:") @@ -101,6 +108,7 @@ class NotesDialog(wx.Frame): # Right panel - editor right_panel = wx.Panel(splitter) + right_panel.SetBackgroundColour(self.get_theme_colour("content_bg", right_panel.GetBackgroundColour())) right_sizer = wx.BoxSizer(wx.VERTICAL) title_label = wx.StaticText(right_panel, label="Note Title:") @@ -226,6 +234,7 @@ class NotesDialog(wx.Frame): def setup_editor_toolbar(self, parent): self.toolbar = wx.Panel(parent) + self.toolbar.SetBackgroundColour(self.get_theme_colour("control_bg", self.toolbar.GetBackgroundColour())) toolbar_sizer = wx.BoxSizer(wx.HORIZONTAL) # Text formatting buttons diff --git a/src/main.py b/src/main.py index 44b5b4d..1b5a09e 100644 --- a/src/main.py +++ b/src/main.py @@ -43,8 +43,9 @@ class IRCFrame(wx.Frame): def __init__(self): super().__init__(None, title="wxIRC", size=(1200, 700)) - # Apply white theme - self.apply_white_theme() + # Determine platform theme once + self.theme = self.build_theme() + self.apply_theme() # Show privacy notice first self.show_privacy_notice() @@ -121,18 +122,69 @@ class IRCFrame(wx.Frame): self.Bind(wx.EVT_MENU, self.on_find_previous, id=1002) self.Bind(wx.EVT_MENU, self.on_quick_escape, id=1003) - def apply_white_theme(self): - """Apply white theme to the application""" + def build_theme(self): + """Build a small theme descriptor that respects the host platform.""" try: - # Set system colors for white theme - self.SetBackgroundColour(wx.Colour(255, 255, 255)) - self.SetForegroundColour(wx.Colour(0, 0, 0)) - - # Set system settings for light theme sys_settings = wx.SystemSettings() + system_window = sys_settings.GetColour(wx.SYS_COLOUR_WINDOW) + system_text = sys_settings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) + system_face = sys_settings.GetColour(wx.SYS_COLOUR_BTNFACE) + is_windows = wx.Platform == "__WXMSW__" + if is_windows: + window_bg = wx.Colour(255, 255, 255) + control_bg = wx.Colour(240, 240, 240) + text = wx.Colour(0, 0, 0) + else: + window_bg = system_window + control_bg = system_face + text = system_text + + sidebar_delta = 15 if self._is_light_colour(window_bg) else -20 + sidebar_bg = self._adjust_colour(control_bg if control_bg.IsOk() else window_bg, sidebar_delta) + + return { + "window_bg": window_bg, + "content_bg": window_bg, + "text": text, + "sidebar_bg": sidebar_bg, + "control_bg": control_bg if control_bg.IsOk() else window_bg, + "force_light": is_windows, + } except Exception as e: - logger.error(f"Error applying white theme: {e}") + logger.error(f"Error building theme: {e}") + # Fallback to a simple light theme + return { + "window_bg": wx.Colour(255, 255, 255), + "content_bg": wx.Colour(255, 255, 255), + "text": wx.Colour(0, 0, 0), + "sidebar_bg": wx.Colour(240, 240, 240), + "control_bg": wx.Colour(240, 240, 240), + "force_light": True, + } + + def _is_light_colour(self, colour): + """Simple luminance check to know if a colour is light.""" + luminance = 0.299 * colour.Red() + 0.587 * colour.Green() + 0.114 * colour.Blue() + return luminance >= 128 + + def _adjust_colour(self, colour, delta): + """Lighten or darken a colour by delta.""" + def clamp(value): + return max(0, min(255, value)) + return wx.Colour( + clamp(colour.Red() + delta), + clamp(colour.Green() + delta), + clamp(colour.Blue() + delta), + ) + + def apply_theme(self): + """Apply the detected theme.""" + try: + self.SetBackgroundColour(self.theme["window_bg"]) + self.SetForegroundColour(self.theme["text"]) + except Exception as e: + logger.error(f"Error applying theme: {e}") def show_privacy_notice(self): """Show privacy notice dialog at startup""" @@ -199,12 +251,12 @@ class IRCFrame(wx.Frame): def setup_ui(self): """Setup UI components with white theme""" panel = wx.Panel(self) - panel.SetBackgroundColour(wx.Colour(255, 255, 255)) # White background + panel.SetBackgroundColour(self.theme["window_bg"]) main_sizer = wx.BoxSizer(wx.HORIZONTAL) # Left sidebar - light gray for contrast left_panel = wx.Panel(panel) - left_panel.SetBackgroundColour(wx.Colour(240, 240, 240)) # Light gray + left_panel.SetBackgroundColour(self.theme["sidebar_bg"]) left_sizer = wx.BoxSizer(wx.VERTICAL) conn_box = wx.StaticBox(left_panel, label="Connection") @@ -270,7 +322,7 @@ class IRCFrame(wx.Frame): # Center - Notebook self.notebook = wx.Notebook(panel) - self.notebook.SetBackgroundColour(wx.Colour(255, 255, 255)) + self.notebook.SetBackgroundColour(self.theme["content_bg"]) # Server panel server_panel = IRCPanel(self.notebook, self) @@ -280,7 +332,7 @@ class IRCFrame(wx.Frame): # Right sidebar - Users - light gray for contrast right_panel = wx.Panel(panel) - right_panel.SetBackgroundColour(wx.Colour(240, 240, 240)) # Light gray + right_panel.SetBackgroundColour(self.theme["sidebar_bg"]) right_sizer = wx.BoxSizer(wx.VERTICAL) users_box = wx.StaticBox(right_panel, label="Users")