v1.9.1: PNG Material Design icons — 28 icons, dark/light theme, HiDPI, graceful Unicode fallback

- 56 PNG icons (28 unique × 2 color variants) from Material Design Icons (round style, 96×96px)
- core/icons.py: ctk_icon(), make_icon_button(), reconfigure_icon_button() with CTkImage cache
- Updated 15 GUI files: app.py, sidebar.py, server_dialog.py, all tabs
- build.py: auto-include assets/icons/ in PyInstaller bundle, patch rollover at 99→minor+1
- tools/download_icons.py: icon download script
- Automatic dark↔light theme switching via CTkImage dual-image support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-03-03 07:27:49 -05:00
parent 9b0e4c76a3
commit 1e729fcf3a
76 changed files with 397 additions and 148 deletions

View File

@@ -10,7 +10,7 @@ import threading
import customtkinter as ctk
from core.remote_desktop import RemoteDesktopLauncher
from core.i18n import t
from core.icons import icon_text
from core.icons import icon_text, make_icon_button, reconfigure_icon_button
from core.logger import log
@@ -33,15 +33,15 @@ class LaunchTab(ctk.CTkFrame):
# ── Toolbar (shown when RDP connected) ──
self._toolbar = ctk.CTkFrame(self, height=36, fg_color="transparent")
self._disconnect_btn = ctk.CTkButton(
self._toolbar, text=icon_text("delete", t("rdp_disconnect")),
self._disconnect_btn = make_icon_button(
self._toolbar, "delete", t("rdp_disconnect"),
width=120, height=30, fg_color="#ef4444", hover_color="#dc2626",
command=self._disconnect,
)
self._disconnect_btn.pack(side="left", padx=(8, 4))
self._fullscreen_btn = ctk.CTkButton(
self._toolbar, text=icon_text("launch", t("rdp_fullscreen")),
self._fullscreen_btn = make_icon_button(
self._toolbar, "launch", t("rdp_fullscreen"),
width=130, height=30, fg_color="#6b7280", hover_color="#4b5563",
command=self._toggle_fullscreen,
)
@@ -135,8 +135,9 @@ class LaunchTab(ctk.CTkFrame):
).pack(fill="x", padx=15, pady=(3, 12))
# Connect button
self._connect_btn = ctk.CTkButton(
self._settings_panel, text=icon_text("execute", t("launch_connect")),
self._connect_btn = make_icon_button(
self._settings_panel, "execute", t("launch_connect"),
icon_size=20,
font=ctk.CTkFont(size=18, weight="bold"),
width=220, height=50,
command=self._on_connect,
@@ -374,9 +375,7 @@ class LaunchTab(ctk.CTkFrame):
if self._is_fullscreen:
# Exit fullscreen — reattach
self._is_fullscreen = False
self._fullscreen_btn.configure(
text=icon_text("launch", t("rdp_fullscreen")),
)
reconfigure_icon_button(self._fullscreen_btn, "launch", t("rdp_fullscreen"))
self._rdp_frame.update_idletasks()
parent_hwnd = self._rdp_frame.winfo_id()
w = self._rdp_frame.winfo_width()
@@ -385,9 +384,7 @@ class LaunchTab(ctk.CTkFrame):
else:
# Go fullscreen — detach, then maximize after event loop settles
self._is_fullscreen = True
self._fullscreen_btn.configure(
text=icon_text("back", t("rdp_exit_fullscreen")),
)
reconfigure_icon_button(self._fullscreen_btn, "back", t("rdp_exit_fullscreen"))
self._embedded_rdp.detach()
self.after(300, self._maximize_detached)