windows fixes
This commit is contained in:
178
main.py
178
main.py
@@ -518,13 +518,15 @@ class IRCPanel(wx.Panel):
|
||||
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
# Use a better font for chat
|
||||
# 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)
|
||||
self.text_ctrl.SetBackgroundColour(wx.Colour(30, 30, 30))
|
||||
self.text_ctrl.SetForegroundColour(wx.Colour(220, 220, 220))
|
||||
|
||||
# Load Fira Code font
|
||||
self.font = self.load_fira_code_font()
|
||||
# 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
|
||||
|
||||
# Load appropriate font
|
||||
self.font = self.load_system_font()
|
||||
self.text_ctrl.SetFont(self.font)
|
||||
|
||||
sizer.Add(self.text_ctrl, 1, wx.EXPAND | wx.ALL, 0)
|
||||
@@ -560,39 +562,46 @@ class IRCPanel(wx.Panel):
|
||||
self.SetAcceleratorTable(accel_tbl)
|
||||
self.Bind(wx.EVT_MENU, self.on_search, id=wx.ID_FIND)
|
||||
|
||||
def load_fira_code_font(self):
|
||||
"""Load Fira Code font from resources"""
|
||||
def load_system_font(self):
|
||||
"""Load appropriate system font with high DPI support"""
|
||||
try:
|
||||
# Try to use Fira Code if available
|
||||
font_path = get_resource_path("FiraCode-Regular.ttf")
|
||||
# Get system DPI scale factor
|
||||
dc = wx.ClientDC(self)
|
||||
dpi_scale = dc.GetPPI().GetWidth() / 96.0 # 96 is standard DPI
|
||||
|
||||
if os.path.exists(font_path):
|
||||
# On wxPython 4.1+, we can try to add the font to the font manager
|
||||
try:
|
||||
font_collection = wx.private.FontCollection()
|
||||
if font_collection.AddFont(font_path):
|
||||
font = wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL,
|
||||
False, "Fira Code")
|
||||
if font.IsOk():
|
||||
logger.info("Successfully loaded Fira Code font")
|
||||
return font
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Fallback: try to create font by name
|
||||
font = wx.Font(wx.FontInfo(10).Family(wx.FONTFAMILY_TELETYPE).FaceName("Fira Code"))
|
||||
if font.IsOk():
|
||||
logger.info("Using Fira Code font via FaceName")
|
||||
return font
|
||||
# Calculate base font size based on DPI
|
||||
base_size = 10
|
||||
if dpi_scale > 1.5:
|
||||
font_size = int(base_size * 1.5) # 150% scaling
|
||||
elif dpi_scale > 1.25:
|
||||
font_size = int(base_size * 1.25) # 125% scaling
|
||||
else:
|
||||
logger.warning("FiraCode-Regular.ttf not found in resources")
|
||||
font_size = base_size
|
||||
|
||||
# Try system fonts in order of preference
|
||||
font_families = [
|
||||
(wx.FONTFAMILY_TELETYPE, "Consolas"),
|
||||
(wx.FONTFAMILY_TELETYPE, "Courier New"),
|
||||
(wx.FONTFAMILY_TELETYPE, "Monaco"),
|
||||
(wx.FONTFAMILY_TELETYPE, "DejaVu Sans Mono"),
|
||||
(wx.FONTFAMILY_TELETYPE, "Liberation Mono"),
|
||||
]
|
||||
|
||||
for family, face_name in font_families:
|
||||
font = wx.Font(font_size, family, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, face_name)
|
||||
if font.IsOk():
|
||||
logger.info(f"Using font: {face_name} at {font_size}pt")
|
||||
return font
|
||||
|
||||
# Fallback to default monospace
|
||||
font = wx.Font(font_size, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
|
||||
logger.info("Using system monospace font as fallback")
|
||||
return font
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error loading Fira Code font: {e}")
|
||||
|
||||
# Fall back to system monospace font
|
||||
font = wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
|
||||
logger.info("Using system monospace font as fallback")
|
||||
return font
|
||||
logger.error(f"Error loading system font: {e}")
|
||||
# Ultimate fallback
|
||||
return wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
|
||||
|
||||
def set_target(self, target):
|
||||
self.target = target
|
||||
@@ -635,7 +644,7 @@ class IRCPanel(wx.Panel):
|
||||
if message_color:
|
||||
attr.SetTextColour(message_color)
|
||||
else:
|
||||
attr.SetTextColour(wx.Colour(220, 220, 220))
|
||||
attr.SetTextColour(wx.Colour(0, 0, 0)) # Black text for white theme
|
||||
|
||||
attr.SetFont(self.font)
|
||||
self.text_ctrl.SetDefaultStyle(attr)
|
||||
@@ -658,10 +667,10 @@ class IRCPanel(wx.Panel):
|
||||
try:
|
||||
if is_action:
|
||||
message = f"{timestamp}* {username} {content}"
|
||||
self.add_message(message, f"* {username}", username_color, wx.Colour(255, 150, 255), italic=True)
|
||||
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(220, 220, 220))
|
||||
self.add_message(message, f"<{username}>", username_color, wx.Colour(0, 0, 0)) # Black text
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding formatted message: {e}")
|
||||
|
||||
@@ -669,7 +678,7 @@ class IRCPanel(wx.Panel):
|
||||
"""Add system message without username coloring"""
|
||||
try:
|
||||
if color is None:
|
||||
color = wx.Colour(180, 180, 255)
|
||||
color = wx.Colour(0, 0, 128) # Dark blue for system messages
|
||||
self.add_message(message, None, None, color, bold, False, False)
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding system message: {e}")
|
||||
@@ -868,6 +877,9 @@ class IRCFrame(wx.Frame):
|
||||
def __init__(self):
|
||||
super().__init__(None, title="wxIRC", size=(1200, 700))
|
||||
|
||||
# Apply white theme
|
||||
self.apply_white_theme()
|
||||
|
||||
# Show privacy notice first
|
||||
self.show_privacy_notice()
|
||||
|
||||
@@ -891,21 +903,21 @@ class IRCFrame(wx.Frame):
|
||||
self.away = False
|
||||
self.timestamps = True
|
||||
|
||||
# User color mapping
|
||||
# User color mapping - darker colors for white theme
|
||||
self.user_colors = {}
|
||||
self.available_colors = [
|
||||
wx.Colour(255, 150, 150), # Light red
|
||||
wx.Colour(150, 255, 150), # Light green
|
||||
wx.Colour(150, 200, 255), # Light blue
|
||||
wx.Colour(255, 255, 150), # Light yellow
|
||||
wx.Colour(255, 150, 255), # Light magenta
|
||||
wx.Colour(150, 255, 255), # Light cyan
|
||||
wx.Colour(255, 200, 150), # Light orange
|
||||
wx.Colour(200, 150, 255), # Light purple
|
||||
wx.Colour(255, 200, 200), # Pink
|
||||
wx.Colour(200, 255, 200), # Mint
|
||||
wx.Colour(200, 200, 255), # Lavender
|
||||
wx.Colour(255, 255, 200), # Cream
|
||||
wx.Colour(178, 34, 34), # Firebrick red
|
||||
wx.Colour(0, 100, 0), # Dark green
|
||||
wx.Colour(0, 0, 139), # Dark blue
|
||||
wx.Colour(139, 69, 19), # Saddle brown
|
||||
wx.Colour(139, 0, 139), # Dark magenta
|
||||
wx.Colour(0, 139, 139), # Dark cyan
|
||||
wx.Colour(210, 105, 30), # Chocolate
|
||||
wx.Colour(75, 0, 130), # Indigo
|
||||
wx.Colour(178, 34, 34), # Firebrick
|
||||
wx.Colour(0, 128, 128), # Teal
|
||||
wx.Colour(72, 61, 139), # Dark slate blue
|
||||
wx.Colour(139, 0, 0), # Dark red
|
||||
]
|
||||
self.color_index = 0
|
||||
|
||||
@@ -939,6 +951,19 @@ 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"""
|
||||
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()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error applying white theme: {e}")
|
||||
|
||||
def show_privacy_notice(self):
|
||||
"""Show privacy notice dialog at startup"""
|
||||
dlg = PrivacyNoticeDialog(self)
|
||||
@@ -1002,13 +1027,14 @@ class IRCFrame(wx.Frame):
|
||||
return None
|
||||
|
||||
def setup_ui(self):
|
||||
"""Setup UI components"""
|
||||
"""Setup UI components with white theme"""
|
||||
panel = wx.Panel(self)
|
||||
panel.SetBackgroundColour(wx.Colour(255, 255, 255)) # White background
|
||||
main_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
# Left sidebar
|
||||
# Left sidebar - light gray for contrast
|
||||
left_panel = wx.Panel(panel)
|
||||
left_panel.SetBackgroundColour(wx.Colour(45, 45, 45))
|
||||
left_panel.SetBackgroundColour(wx.Colour(240, 240, 240)) # Light gray
|
||||
left_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
conn_box = wx.StaticBox(left_panel, label="Connection")
|
||||
@@ -1068,6 +1094,7 @@ class IRCFrame(wx.Frame):
|
||||
|
||||
# Center - Notebook
|
||||
self.notebook = wx.Notebook(panel)
|
||||
self.notebook.SetBackgroundColour(wx.Colour(255, 255, 255))
|
||||
|
||||
# Server panel
|
||||
server_panel = IRCPanel(self.notebook, self)
|
||||
@@ -1075,9 +1102,9 @@ class IRCFrame(wx.Frame):
|
||||
self.notebook.AddPage(server_panel, "Server")
|
||||
self.channels["SERVER"] = server_panel
|
||||
|
||||
# Right sidebar - Users
|
||||
# Right sidebar - Users - light gray for contrast
|
||||
right_panel = wx.Panel(panel)
|
||||
right_panel.SetBackgroundColour(wx.Colour(45, 45, 45))
|
||||
right_panel.SetBackgroundColour(wx.Colour(240, 240, 240)) # Light gray
|
||||
right_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
users_box = wx.StaticBox(right_panel, label="Users")
|
||||
@@ -1232,7 +1259,7 @@ class IRCFrame(wx.Frame):
|
||||
if hasattr(event, 'arguments') and event.arguments:
|
||||
event_info += f" - {' '.join(event.arguments)}"
|
||||
|
||||
self.log_server(event_info, wx.Colour(180, 180, 255), italic=True)
|
||||
self.log_server(event_info, wx.Colour(0, 0, 128), italic=True) # Dark blue for raw events
|
||||
except Exception as e:
|
||||
logger.error(f"Error in all_events handler: {e}")
|
||||
|
||||
@@ -1259,19 +1286,19 @@ class IRCFrame(wx.Frame):
|
||||
try:
|
||||
self.port = int(self.port_ctrl.GetValue())
|
||||
except ValueError:
|
||||
self.safe_ui_update(self.log_server, "Invalid port number", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, "Invalid port number", wx.Colour(255, 0, 0))
|
||||
self.is_connecting = False
|
||||
return
|
||||
|
||||
self.nick = self.nick_ctrl.GetValue()
|
||||
|
||||
if not self.server or not self.nick:
|
||||
self.safe_ui_update(self.log_server, "Server and nick are required", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, "Server and nick are required", wx.Colour(255, 0, 0))
|
||||
self.is_connecting = False
|
||||
return
|
||||
|
||||
self.safe_ui_update(self.connect_btn.Enable, False)
|
||||
self.safe_ui_update(self.log_server, f"Connecting to {self.server}:{self.port} as {self.nick}...", wx.Colour(150, 150, 255))
|
||||
self.safe_ui_update(self.log_server, f"Connecting to {self.server}:{self.port} as {self.nick}...", wx.Colour(0, 0, 128))
|
||||
|
||||
def connect_thread():
|
||||
try:
|
||||
@@ -1320,7 +1347,7 @@ class IRCFrame(wx.Frame):
|
||||
self.reactor.process_forever()
|
||||
except Exception as e:
|
||||
logger.error(f"Reactor loop error: {e}")
|
||||
self.safe_ui_update(self.log_server, f"Connection error: {e}", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, f"Connection error: {e}", wx.Colour(255, 0, 0))
|
||||
self.safe_ui_update(self.on_disconnect_cleanup)
|
||||
|
||||
def on_connect_success(self):
|
||||
@@ -1334,7 +1361,7 @@ class IRCFrame(wx.Frame):
|
||||
def on_connect_failed(self, error_msg):
|
||||
"""Handle connection failure"""
|
||||
self.is_connecting = False
|
||||
self.log_server(error_msg, wx.Colour(255, 100, 100))
|
||||
self.log_server(error_msg, wx.Colour(255, 0, 0))
|
||||
self.connect_btn.Enable(True)
|
||||
self.SetStatusText("Connection failed")
|
||||
logger.error(f"Connection failed: {error_msg}")
|
||||
@@ -1376,7 +1403,7 @@ class IRCFrame(wx.Frame):
|
||||
self.safe_ui_update(self.connect_btn.SetLabel, "Connect")
|
||||
self.safe_ui_update(self.connect_btn.Enable, True)
|
||||
self.safe_ui_update(self.SetStatusText, "Disconnected")
|
||||
self.safe_ui_update(self.log_server, "Disconnected from server", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, "Disconnected from server", wx.Colour(255, 0, 0))
|
||||
|
||||
def on_join_channel(self, event):
|
||||
try:
|
||||
@@ -1388,7 +1415,7 @@ class IRCFrame(wx.Frame):
|
||||
self.channel_input.Clear()
|
||||
except Exception as e:
|
||||
logger.error(f"Error joining channel: {e}")
|
||||
self.safe_ui_update(self.log_server, f"Error joining channel: {e}", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, f"Error joining channel: {e}", wx.Colour(255, 0, 0))
|
||||
|
||||
def on_channel_select(self, event):
|
||||
try:
|
||||
@@ -1505,7 +1532,7 @@ class IRCFrame(wx.Frame):
|
||||
self.channels[target].add_formatted_message(timestamp, self.nick, message, user_color)
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending message: {e}")
|
||||
self.safe_ui_update(self.log_server, f"Error sending message: {e}", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, f"Error sending message: {e}", wx.Colour(255, 0, 0))
|
||||
|
||||
def handle_command(self, target, message):
|
||||
try:
|
||||
@@ -1528,7 +1555,7 @@ Available commands:
|
||||
/quit [message] - Disconnect from server
|
||||
/help - Show this help
|
||||
"""
|
||||
self.log_server(help_text, wx.Colour(200, 255, 200))
|
||||
self.log_server(help_text, wx.Colour(0, 100, 0)) # Dark green for help
|
||||
elif cmd == "me":
|
||||
if self.is_connected():
|
||||
self.connection.action(target, args)
|
||||
@@ -1568,10 +1595,10 @@ Available commands:
|
||||
self.away = bool(args)
|
||||
self.safe_ui_update(self.away_item.Check, self.away)
|
||||
else:
|
||||
self.safe_ui_update(self.log_server, f"Unknown command: {cmd}. Use /help for available commands.", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, f"Unknown command: {cmd}. Use /help for available commands.", wx.Colour(255, 0, 0))
|
||||
except Exception as e:
|
||||
logger.error(f"Error handling command: {e}")
|
||||
self.safe_ui_update(self.log_server, f"Error executing command: {e}", wx.Colour(255, 100, 100))
|
||||
self.safe_ui_update(self.log_server, f"Error executing command: {e}", wx.Colour(255, 0, 0))
|
||||
|
||||
def part_channel(self, channel):
|
||||
try:
|
||||
@@ -1767,13 +1794,14 @@ COMMANDS (type /help in chat for full list):
|
||||
/nick newname - Change nickname
|
||||
/away [message] - Set away status
|
||||
"""
|
||||
self.log_server(help_text, wx.Colour(200, 255, 200), bold=True)
|
||||
self.log_server(help_text, wx.Colour(0, 100, 0), bold=True) # Dark green for help
|
||||
|
||||
|
||||
# IRC Event Handlers - All use thread-safe UI updates
|
||||
def on_welcome(self, connection, event):
|
||||
try:
|
||||
self.log_server("Connected to server!", wx.Colour(100, 255, 100), bold=True)
|
||||
self.log_server(f"Welcome message: {' '.join(event.arguments)}", wx.Colour(150, 255, 150))
|
||||
self.log_server("Connected to server!", wx.Colour(0, 128, 0), bold=True) # Dark green
|
||||
self.log_server(f"Welcome message: {' '.join(event.arguments)}", wx.Colour(0, 100, 0))
|
||||
|
||||
# Auto-join channels
|
||||
for channel in self.auto_join_channels:
|
||||
@@ -1792,7 +1820,7 @@ COMMANDS (type /help in chat for full list):
|
||||
|
||||
if nick == self.nick:
|
||||
self.safe_ui_update(self.add_channel, channel)
|
||||
self.log_server(f"Joined channel {channel}", wx.Colour(100, 255, 100))
|
||||
self.log_server(f"Joined channel {channel}", wx.Colour(0, 128, 0)) # Dark green
|
||||
|
||||
self.log_channel_message(channel, nick, f"→ {nick} joined", is_system=True)
|
||||
|
||||
@@ -1900,7 +1928,7 @@ COMMANDS (type /help in chat for full list):
|
||||
|
||||
if old_nick == self.nick:
|
||||
self.nick = new_nick
|
||||
self.log_server(f"You are now known as {new_nick}", wx.Colour(150, 200, 255), bold=True)
|
||||
self.log_server(f"You are now known as {new_nick}", wx.Colour(0, 0, 128), bold=True) # Dark blue
|
||||
|
||||
for channel in self.channel_users:
|
||||
if old_nick in self.channel_users[channel]:
|
||||
@@ -1928,13 +1956,13 @@ COMMANDS (type /help in chat for full list):
|
||||
nick = event.source.nick if hasattr(event.source, 'nick') else str(event.source)
|
||||
message = event.arguments[0]
|
||||
|
||||
self.log_server(f"-{nick}- {message}", wx.Colour(255, 150, 255), italic=True)
|
||||
self.log_server(f"-{nick}- {message}", wx.Colour(128, 0, 128), italic=True) # Dark purple for notices
|
||||
except Exception as e:
|
||||
logger.error(f"Error in notice handler: {e}")
|
||||
|
||||
def on_disconnect(self, connection, event):
|
||||
try:
|
||||
self.log_server("Disconnected from server", wx.Colour(255, 100, 100), bold=True)
|
||||
self.log_server("Disconnected from server", wx.Colour(255, 0, 0), bold=True) # Red for disconnect
|
||||
self.safe_ui_update(self.on_disconnect_cleanup)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in disconnect handler: {e}")
|
||||
|
||||
Reference in New Issue
Block a user