Skip to content

Commit 05cad3a

Browse files
RFingAdamclaude
andcommitted
fix: cross-platform GUI fonts (v5.2 W4, #25)
"Arial" is not guaranteed on Linux and caused Tk font substitution + misaligned dialogs. Define FONT_FAMILY (Segoe UI / Helvetica Neue / DejaVu Sans by OS) first in config_template and route the legacy font constants (HEADER_FONT/LABEL_FONT/FONT_SM/MD/LG/XL) through it, then swap the 31 inline ("Arial",...)/("Segoe UI",...) literals across the GUI dialogs/tooltip/utils to (FONT_FAMILY,...). Closes #25. GUI modules import clean; full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 7eff493 commit 05cad3a

6 files changed

Lines changed: 73 additions & 56 deletions

File tree

plot_antenna/config_template.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,28 @@
6868
SUCCESS_COLOR = "#4CAF50"
6969
INFO_COLOR = "#4A90E2"
7070

71-
# GUI Fonts
72-
HEADER_FONT = ("Arial", 14, "bold")
73-
LABEL_FONT = ("Arial", 12)
74-
FONT_SM = ("Arial", 9)
75-
FONT_MD = ("Arial", 11)
76-
FONT_LG = ("Arial", 13)
77-
FONT_XL = ("Arial", 16, "bold")
71+
# Platform-aware font family (Linux/macOS/Windows) — defined first so every
72+
# font constant below uses a family that actually exists on the host. "Arial"
73+
# is not guaranteed on Linux and caused Tk substitution / misaligned dialogs.
74+
import sys as _sys
75+
76+
if _sys.platform == "win32":
77+
FONT_FAMILY = "Segoe UI"
78+
_MONO_FAMILY = "Consolas"
79+
elif _sys.platform == "darwin":
80+
FONT_FAMILY = "Helvetica Neue"
81+
_MONO_FAMILY = "Menlo"
82+
else: # Linux / other
83+
FONT_FAMILY = "DejaVu Sans"
84+
_MONO_FAMILY = "DejaVu Sans Mono"
85+
86+
# GUI Fonts (now cross-platform via FONT_FAMILY)
87+
HEADER_FONT = (FONT_FAMILY, 14, "bold")
88+
LABEL_FONT = (FONT_FAMILY, 12)
89+
FONT_SM = (FONT_FAMILY, 9)
90+
FONT_MD = (FONT_FAMILY, 11)
91+
FONT_LG = (FONT_FAMILY, 13)
92+
FONT_XL = (FONT_FAMILY, 16, "bold")
7893

7994
# Spacing Constants
8095
PAD_SM = 5
@@ -92,19 +107,7 @@
92107
DISABLED_FG_COLOR = "#A0A0A0" # WCAG AA compliant (5.6:1 on #2E2E2E)
93108
FOCUS_BORDER_COLOR = "#5A9CF5"
94109

95-
# Modern Fonts (platform-aware fallbacks for Linux/macOS/Windows)
96-
import sys as _sys
97-
98-
if _sys.platform == "win32":
99-
FONT_FAMILY = "Segoe UI"
100-
_MONO_FAMILY = "Consolas"
101-
elif _sys.platform == "darwin":
102-
FONT_FAMILY = "Helvetica Neue"
103-
_MONO_FAMILY = "Menlo"
104-
else: # Linux / other
105-
FONT_FAMILY = "DejaVu Sans"
106-
_MONO_FAMILY = "DejaVu Sans Mono"
107-
110+
# Modern Fonts (same platform-aware family)
108111
HEADER_BAR_FONT = (FONT_FAMILY, 16, "bold")
109112
HEADER_VERSION_FONT = (FONT_FAMILY, 9)
110113
SECTION_HEADER_FONT = (FONT_FAMILY, 11, "bold")

plot_antenna/gui/callbacks_mixin.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import numpy as np
2020
import matplotlib.pyplot as plt
2121

22-
from ..config import ACCENT_BLUE_COLOR, LIGHT_TEXT_COLOR
22+
from ..config import ACCENT_BLUE_COLOR, LIGHT_TEXT_COLOR, FONT_FAMILY
2323

2424
from ..file_utils import (
2525
read_passive_file,
@@ -368,7 +368,7 @@ def display_eff_gain_table(self, results):
368368

369369
row = 0
370370
for band_label, band_data in results:
371-
tk.Label(result_window, text=band_label, font=("Arial", 12, "bold")).grid(
371+
tk.Label(result_window, text=band_label, font=(FONT_FAMILY, 12, "bold")).grid(
372372
row=row, column=0, columnspan=7, pady=5
373373
)
374374
row += 1
@@ -383,7 +383,7 @@ def display_eff_gain_table(self, results):
383383
"Avg Eff(dB)",
384384
]
385385
for col, header in enumerate(headers):
386-
tk.Label(result_window, text=header, font=("Arial", 10, "bold")).grid(
386+
tk.Label(result_window, text=header, font=(FONT_FAMILY, 10, "bold")).grid(
387387
row=row, column=col, padx=10, pady=5
388388
)
389389
row += 1
@@ -441,20 +441,20 @@ def display_final_summary(self, results):
441441
summary_window.title("Final Summary")
442442

443443
tk.Label(
444-
summary_window, text="Final Summary of All Bands", font=("Arial", 12, "bold")
444+
summary_window, text="Final Summary of All Bands", font=(FONT_FAMILY, 12, "bold")
445445
).grid(row=0, column=0, columnspan=len(results) + 1, pady=10)
446446

447-
tk.Label(summary_window, text="Parameter", font=("Arial", 10, "bold")).grid(
447+
tk.Label(summary_window, text="Parameter", font=(FONT_FAMILY, 10, "bold")).grid(
448448
row=1, column=0, padx=10, pady=5
449449
)
450450
for col, (band_label, _) in enumerate(results, start=1):
451-
tk.Label(summary_window, text=band_label, font=("Arial", 10, "bold")).grid(
451+
tk.Label(summary_window, text=band_label, font=(FONT_FAMILY, 10, "bold")).grid(
452452
row=1, column=col, padx=10, pady=5
453453
)
454454

455455
parameters = ["Avg Eff(%)", "Avg Eff(dB)", "Min Gain(dBi)", "Max Gain(dBi)"]
456456
for row, param in enumerate(parameters, start=2):
457-
tk.Label(summary_window, text=param, font=("Arial", 10, "bold")).grid(
457+
tk.Label(summary_window, text=param, font=(FONT_FAMILY, 10, "bold")).grid(
458458
row=row, column=0, sticky="w", padx=10, pady=5
459459
)
460460

plot_antenna/gui/dialogs_mixin.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from typing import TYPE_CHECKING, Optional
1717

1818
from ..config import (
19+
FONT_FAMILY,
1920
DARK_BG_COLOR,
2021
LIGHT_TEXT_COLOR,
2122
ACCENT_BLUE_COLOR,
@@ -136,7 +137,7 @@ def show_about_dialog(self):
136137
name_label = tk.Label(
137138
header_frame,
138139
text="RFlect",
139-
font=("Arial", 28, "bold"),
140+
font=(FONT_FAMILY, 28, "bold"),
140141
bg=DARK_BG_COLOR,
141142
fg="#E63946", # Red color similar to smith_logo.png
142143
)
@@ -146,7 +147,7 @@ def show_about_dialog(self):
146147
version_label = tk.Label(
147148
about_window,
148149
text=f"Version {self.CURRENT_VERSION}",
149-
font=("Arial", 12),
150+
font=(FONT_FAMILY, 12),
150151
bg=DARK_BG_COLOR,
151152
fg=LIGHT_TEXT_COLOR,
152153
)
@@ -156,7 +157,7 @@ def show_about_dialog(self):
156157
desc_label = tk.Label(
157158
about_window,
158159
text="Antenna Measurement & Analysis Tool",
159-
font=("Arial", 10, "italic"),
160+
font=(FONT_FAMILY, 10, "italic"),
160161
bg=DARK_BG_COLOR,
161162
fg=LIGHT_TEXT_COLOR,
162163
)
@@ -181,7 +182,7 @@ def show_about_dialog(self):
181182
credits_label = tk.Label(
182183
credits_frame,
183184
text=credits_text,
184-
font=("Arial", 9),
185+
font=(FONT_FAMILY, 9),
185186
bg=DARK_BG_COLOR,
186187
fg=LIGHT_TEXT_COLOR,
187188
justify=tk.LEFT,
@@ -192,7 +193,7 @@ def show_about_dialog(self):
192193
license_label = tk.Label(
193194
about_window,
194195
text="Licensed under GNU General Public License v3.0",
195-
font=("Arial", 8),
196+
font=(FONT_FAMILY, 8),
196197
bg=DARK_BG_COLOR,
197198
fg=LIGHT_TEXT_COLOR,
198199
)
@@ -987,7 +988,7 @@ def _on_outer_destroy(event):
987988
text="(single freq)",
988989
bg=DARK_BG_COLOR,
989990
fg="#A0A0A0",
990-
font=("Arial", 9),
991+
font=(FONT_FAMILY, 9),
991992
).grid(row=4, column=3, sticky=tk.W)
992993

993994
# CSV file for per-frequency conducted power (batch processing)
@@ -1371,7 +1372,7 @@ def save_passive_settings():
13711372
title = tk.Label(
13721373
settings_window,
13731374
text="VSWR/Return Loss Settings",
1374-
font=("Arial", 12, "bold"),
1375+
font=(FONT_FAMILY, 12, "bold"),
13751376
bg=DARK_BG_COLOR,
13761377
fg=LIGHT_TEXT_COLOR,
13771378
)

plot_antenna/gui/tools_mixin.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import requests
2626

2727
from ..config import (
28+
FONT_FAMILY,
2829
ACCENT_BLUE_COLOR,
2930
DARK_BG_COLOR,
3031
LIGHT_TEXT_COLOR,
@@ -176,34 +177,42 @@ def generate_report_from_directory(self):
176177
report_dialog.grab_set()
177178

178179
# Title
179-
tk.Label(report_dialog, text="Report Generation", font=("Arial", 14, "bold")).pack(pady=10)
180+
tk.Label(report_dialog, text="Report Generation", font=(FONT_FAMILY, 14, "bold")).pack(
181+
pady=10
182+
)
180183

181184
# Report title
182-
tk.Label(report_dialog, text="Report Title:", font=("Arial", 10)).pack(anchor="w", padx=20)
185+
tk.Label(report_dialog, text="Report Title:", font=(FONT_FAMILY, 10)).pack(
186+
anchor="w", padx=20
187+
)
183188
title_var = tk.StringVar(value="Antenna Measurement Report")
184189
tk.Entry(report_dialog, textvariable=title_var, width=50).pack(padx=20, pady=5)
185190

186191
# Project name
187-
tk.Label(report_dialog, text="Project Name:", font=("Arial", 10)).pack(anchor="w", padx=20)
192+
tk.Label(report_dialog, text="Project Name:", font=(FONT_FAMILY, 10)).pack(
193+
anchor="w", padx=20
194+
)
188195
project_var = tk.StringVar()
189196
tk.Entry(report_dialog, textvariable=project_var, width=50).pack(padx=20, pady=5)
190197

191198
# Antenna type
192199
tk.Label(
193-
report_dialog, text="Antenna Type (e.g., Patch, Monopole, PIFA):", font=("Arial", 10)
200+
report_dialog,
201+
text="Antenna Type (e.g., Patch, Monopole, PIFA):",
202+
font=(FONT_FAMILY, 10),
194203
).pack(anchor="w", padx=20)
195204
antenna_var = tk.StringVar()
196205
tk.Entry(report_dialog, textvariable=antenna_var, width=50).pack(padx=20, pady=5)
197206

198207
# Frequency range
199208
tk.Label(
200-
report_dialog, text="Frequency Range (e.g., 2.4-2.5 GHz):", font=("Arial", 10)
209+
report_dialog, text="Frequency Range (e.g., 2.4-2.5 GHz):", font=(FONT_FAMILY, 10)
201210
).pack(anchor="w", padx=20)
202211
freq_var = tk.StringVar()
203212
tk.Entry(report_dialog, textvariable=freq_var, width=50).pack(padx=20, pady=5)
204213

205214
# Author
206-
tk.Label(report_dialog, text="Author/Engineer:", font=("Arial", 10)).pack(
215+
tk.Label(report_dialog, text="Author/Engineer:", font=(FONT_FAMILY, 10)).pack(
207216
anchor="w", padx=20
208217
)
209218
author_var = tk.StringVar()
@@ -872,41 +881,43 @@ def open_polarization_interactive(self):
872881
freq_dialog.grab_set()
873882

874883
# Frequency selection
875-
tk.Label(freq_dialog, text="Select Frequency (MHz):", font=("Arial", 11, "bold")).pack(
876-
pady=10
877-
)
884+
tk.Label(
885+
freq_dialog, text="Select Frequency (MHz):", font=(FONT_FAMILY, 11, "bold")
886+
).pack(pady=10)
878887
freq_var = tk.StringVar(value=str(freq_list[0]))
879-
freq_listbox = tk.Listbox(freq_dialog, height=6, font=("Arial", 10))
888+
freq_listbox = tk.Listbox(freq_dialog, height=6, font=(FONT_FAMILY, 10))
880889
for freq in freq_list:
881890
freq_listbox.insert(tk.END, f"{freq} MHz")
882891
freq_listbox.selection_set(0)
883892
freq_listbox.pack(pady=5)
884893

885894
# Plot options
886-
tk.Label(freq_dialog, text="Visualization Options:", font=("Arial", 11, "bold")).pack(
887-
pady=10
888-
)
895+
tk.Label(
896+
freq_dialog, text="Visualization Options:", font=(FONT_FAMILY, 11, "bold")
897+
).pack(pady=10)
889898
plot_2d_var = tk.BooleanVar(value=True)
890899
plot_3d_var = tk.BooleanVar(value=True)
891900

892901
tk.Checkbutton(
893902
freq_dialog,
894903
text="Show 2D Plots (Contour + Polar)",
895904
variable=plot_2d_var,
896-
font=("Arial", 10),
905+
font=(FONT_FAMILY, 10),
897906
).pack()
898907
tk.Checkbutton(
899908
freq_dialog,
900909
text="Show 3D Plots (Spherical)",
901910
variable=plot_3d_var,
902-
font=("Arial", 10),
911+
font=(FONT_FAMILY, 10),
903912
).pack()
904913

905914
# Export option
906-
tk.Label(freq_dialog, text="Export Options:", font=("Arial", 11, "bold")).pack(pady=10)
915+
tk.Label(freq_dialog, text="Export Options:", font=(FONT_FAMILY, 11, "bold")).pack(
916+
pady=10
917+
)
907918
export_var = tk.BooleanVar(value=False)
908919
tk.Checkbutton(
909-
freq_dialog, text="Export data to file", variable=export_var, font=("Arial", 10)
920+
freq_dialog, text="Export data to file", variable=export_var, font=(FONT_FAMILY, 10)
910921
).pack()
911922

912923
# Results container
@@ -930,10 +941,10 @@ def on_cancel():
930941
button_frame = tk.Frame(freq_dialog)
931942
button_frame.pack(pady=20)
932943
tk.Button(
933-
button_frame, text="OK", command=on_ok, width=10, font=("Arial", 10, "bold")
944+
button_frame, text="OK", command=on_ok, width=10, font=(FONT_FAMILY, 10, "bold")
934945
).pack(side=tk.LEFT, padx=5)
935946
tk.Button(
936-
button_frame, text="Cancel", command=on_cancel, width=10, font=("Arial", 10)
947+
button_frame, text="Cancel", command=on_cancel, width=10, font=(FONT_FAMILY, 10)
937948
).pack(side=tk.LEFT, padx=5)
938949

939950
# Wait for dialog to close

plot_antenna/gui/tooltip.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Lightweight tooltip widget for Tkinter."""
22

33
import tkinter as tk
4+
from ..config import FONT_FAMILY
45

56

67
class ToolTip:
@@ -42,7 +43,7 @@ def _show(self):
4243
fg="#DDDDDD",
4344
relief=tk.SOLID,
4445
borderwidth=1,
45-
font=("Segoe UI", 9),
46+
font=(FONT_FAMILY, 9),
4647
padx=8,
4748
pady=4,
4849
)

plot_antenna/gui/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ..file_utils import parse_2port_data
1212
import pandas as pd
1313
import numpy as np
14+
from ..config import FONT_FAMILY
1415

1516

1617
class DualOutput:
@@ -143,15 +144,15 @@ def display_parameter_table(results, param_name, parent):
143144
row = 0
144145
for band_label, band_data in results:
145146
# Band label
146-
tk.Label(parent, text=band_label, font=("Arial", 12, "bold")).grid(
147+
tk.Label(parent, text=band_label, font=(FONT_FAMILY, 12, "bold")).grid(
147148
row=row, column=0, columnspan=3, pady=10
148149
)
149150
row += 1
150151

151152
# Table headers for each band
152153
headers = ["File", f"Min {param_name}", f"Max {param_name}"]
153154
for col, header in enumerate(headers):
154-
tk.Label(parent, text=header, font=("Arial", 10, "bold")).grid(
155+
tk.Label(parent, text=header, font=(FONT_FAMILY, 10, "bold")).grid(
155156
row=row, column=col, padx=10, pady=5
156157
)
157158
row += 1

0 commit comments

Comments
 (0)