From 35bd6e600c65f1c1fb69710fb6c6742722d10514 Mon Sep 17 00:00:00 2001 From: Jeremy Shen Date: Wed, 10 Jun 2026 13:54:06 +0800 Subject: [PATCH] =?UTF-8?q?Revert=20sub-step=20custom=20colors=20=E2=80=94?= =?UTF-8?q?=20use=20default=20CTkLabel=20white=20text?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SubStepFrame now uses default CustomTkinter label colors (white in dark mode, black in light mode) instead of manually set CIRCLE_*/ACCENT_* colors that were unreadable on dark backgrounds. Simplified grid layout — no nested sub-frames. --- src/gui/widgets.py | 147 +++++++++++++-------------------------------- 1 file changed, 42 insertions(+), 105 deletions(-) diff --git a/src/gui/widgets.py b/src/gui/widgets.py index 460604b..3d812d2 100644 --- a/src/gui/widgets.py +++ b/src/gui/widgets.py @@ -638,150 +638,87 @@ class SubStepFrame(ctk.CTkFrame): """Collapsible frame showing flash operation sub-steps with status. Three sub-steps: Erase → Program → Verify. - Status dots match main Step style (CIRCLE_* / ACCENT_* colors). - Collapsed by default, expands on workflow start. + Simple white-text dots and labels. + Collapsed by default. """ def __init__(self, parent: ctk.CTkFrame) -> None: - """Initialize the sub-step frame.""" super().__init__(parent, fg_color="transparent") - self.grid_columnconfigure(0, weight=1) - # Collapse toggle — row 0 self._collapsed = True - toggle_frame = ctk.CTkFrame(self, fg_color="transparent") - toggle_frame.grid(row=0, column=0, sticky="ew", padx=(PADDING, PADDING), pady=(2, 0)) - toggle_frame.grid_columnconfigure(1, weight=1) - self._toggle_btn = ctk.CTkButton( - toggle_frame, - text="▶", - width=20, - height=20, - font=(FONT_SMALL[0], 9), - command=self._toggle, + self, text="▶", width=22, height=22, + font=(FONT_SMALL[0], 9), command=self._toggle, ) - self._toggle_btn.grid(row=0, column=0, padx=(0, 4)) + self._toggle_btn.grid(row=0, column=0, padx=(4, 4), pady=(2, 2), sticky="w") self._header_label = ctk.CTkLabel( - toggle_frame, - text="Flash: Erase → Program → Verify", - font=FONT_BODY, - anchor="w", + self, text="Erase → Program → Verify", + font=FONT_SMALL, ) - self._header_label.grid(row=0, column=1, sticky="w") + self._header_label.grid(row=0, column=1, padx=(0, 4), pady=(2, 2), sticky="w") - # Sub-items (hidden initially) self._sub_items: list[dict] = [] - sub_names = ["Erase ", "Program", "Verify "] - for i, name in enumerate(sub_names): - item = self._build_sub_row(i + 1, name) - item["dot"].grid_remove() - item["label"].grid_remove() - item["pct"].grid_remove() - self._sub_items.append(item) + names = ["Erase ", "Program", "Verify "] + for i, name in enumerate(names): + dot = ctk.CTkLabel(self, text="○", font=FONT_BODY, anchor="w") + label = ctk.CTkLabel(self, text=name, font=FONT_BODY, anchor="w") + pct = ctk.CTkLabel(self, text="", font=FONT_BODY, anchor="e") + dot.grid(row=i + 1, column=0, padx=(16, 2), pady=(2, 2), sticky="w") + label.grid(row=i + 1, column=1, padx=(2, 4), pady=(2, 2), sticky="w") + pct.grid(row=i + 1, column=2, padx=(4, 8), pady=(2, 2), sticky="e") + dot.grid_remove() + label.grid_remove() + pct.grid_remove() + self._sub_items.append({"dot": dot, "label": label, "pct": pct}) - def _build_sub_row(self, row: int, name: str) -> dict: - """Build one sub-item row with dot, label, and percentage label.""" - dot = ctk.CTkLabel( - self, text="○", - width=28, - font=(FONT_BODY[0], FONT_BODY[1]), - text_color=CIRCLE_PENDING, - anchor="center", - ) - dot.grid(row=row, column=0, padx=(PADDING + 20, 4), pady=(3, 3), sticky="w") - - sub_frame = ctk.CTkFrame(self, fg_color="transparent") - sub_frame.grid(row=row, column=0, sticky="ew", padx=(PADDING + 52, PADDING), pady=(3, 3)) - sub_frame.grid_columnconfigure(0, weight=1) - - label = ctk.CTkLabel( - sub_frame, text=name, - font=FONT_BODY, - text_color=ACCENT_PENDING, - anchor="w", - ) - label.grid(row=0, column=0, sticky="w") - - pct = ctk.CTkLabel( - sub_frame, text="", - font=FONT_BODY, - text_color=ACCENT_PENDING, - anchor="e", - ) - pct.grid(row=0, column=1, sticky="e", padx=(8, 0)) - - return {"dot": dot, "label": label, "pct": pct, "name": name} + self.grid_columnconfigure(1, weight=1) def _toggle(self) -> None: - """Toggle collapse/expand.""" self._collapsed = not self._collapsed self._toggle_btn.configure(text="▶" if self._collapsed else "▼") for item in self._sub_items: if self._collapsed: item["dot"].grid_remove() - item["label"].master.grid_remove() + item["label"].grid_remove() + item["pct"].grid_remove() else: item["dot"].grid() - item["label"].master.grid() + item["label"].grid() + item["pct"].grid() def set_expanded(self, expanded: bool) -> None: - """Set expanded state.""" if expanded != self._collapsed: self._toggle() def set_phase(self, phase: str, pct: int = -1) -> None: - """Update sub-step status. - - Args: - phase: 'erase', 'program', 'verify', 'done', 'error'. - pct: Progress 0-100, -1 means running (no specific %). - """ - phase_map = {"erase": 0, "program": 1, "verify": 2} - - if phase == "done": - for item in self._sub_items: - item["dot"].configure(text="●", text_color=CIRCLE_COMPLETE) - item["label"].configure(text_color=SUCCESS_COLOR) - item["pct"].configure(text="OK", text_color=SUCCESS_COLOR) - return - - if phase == "error": - for item in self._sub_items: - item["dot"].configure(text="✗", text_color=CIRCLE_ERROR) - item["label"].configure(text_color=DANGER_COLOR) - item["pct"].configure(text="", text_color=DANGER_COLOR) - return - - idx = phase_map.get(phase, -1) + idx = {"erase": 0, "program": 1, "verify": 2}.get(phase, -1) if idx < 0: + if phase == "done": + for i in self._sub_items: + i["dot"].configure(text="●") + i["pct"].configure(text="OK") + elif phase == "error": + for i in self._sub_items: + i["dot"].configure(text="✗") return - # Running with progress pct_text = f"{pct}%" if pct >= 0 else "" - running_text = f" {pct_text}" if pct_text else "" - for i, item in enumerate(self._sub_items): if i < idx: - item["dot"].configure(text="●", text_color=CIRCLE_COMPLETE) - item["label"].configure(text_color=SUCCESS_COLOR) - item["pct"].configure(text="OK", text_color=SUCCESS_COLOR) + item["dot"].configure(text="●") + item["pct"].configure(text="OK") elif i == idx: - item["dot"].configure(text="◉", text_color=CIRCLE_RUNNING) - item["label"].configure(text_color=ACCENT_RUNNING) - item["pct"].configure(text=pct_text, text_color=ACCENT_RUNNING) + item["dot"].configure(text="◉") + item["pct"].configure(text=pct_text) else: - item["dot"].configure(text="○", text_color=CIRCLE_PENDING) - item["label"].configure(text_color=ACCENT_PENDING) - item["pct"].configure(text="", text_color=ACCENT_PENDING) + item["dot"].configure(text="○") + item["pct"].configure(text="") def reset(self) -> None: - """Reset all sub-steps to pending state.""" - for item in self._sub_items: - item["dot"].configure(text="○", text_color=CIRCLE_PENDING) - item["label"].configure(text_color=ACCENT_PENDING) - item["pct"].configure(text="", text_color=ACCENT_PENDING) + for i in self._sub_items: + i["dot"].configure(text="○") + i["pct"].configure(text="") if not self._collapsed: self._toggle() self._toggle()