Revert sub-step custom colors — use default CTkLabel white text
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.
This commit is contained in:
+42
-105
@@ -638,150 +638,87 @@ class SubStepFrame(ctk.CTkFrame):
|
|||||||
"""Collapsible frame showing flash operation sub-steps with status.
|
"""Collapsible frame showing flash operation sub-steps with status.
|
||||||
|
|
||||||
Three sub-steps: Erase → Program → Verify.
|
Three sub-steps: Erase → Program → Verify.
|
||||||
Status dots match main Step style (CIRCLE_* / ACCENT_* colors).
|
Simple white-text dots and labels.
|
||||||
Collapsed by default, expands on workflow start.
|
Collapsed by default.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parent: ctk.CTkFrame) -> None:
|
def __init__(self, parent: ctk.CTkFrame) -> None:
|
||||||
"""Initialize the sub-step frame."""
|
|
||||||
super().__init__(parent, fg_color="transparent")
|
super().__init__(parent, fg_color="transparent")
|
||||||
self.grid_columnconfigure(0, weight=1)
|
|
||||||
|
|
||||||
# Collapse toggle — row 0
|
|
||||||
self._collapsed = True
|
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(
|
self._toggle_btn = ctk.CTkButton(
|
||||||
toggle_frame,
|
self, text="▶", width=22, height=22,
|
||||||
text="▶",
|
font=(FONT_SMALL[0], 9), command=self._toggle,
|
||||||
width=20,
|
|
||||||
height=20,
|
|
||||||
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(
|
self._header_label = ctk.CTkLabel(
|
||||||
toggle_frame,
|
self, text="Erase → Program → Verify",
|
||||||
text="Flash: Erase → Program → Verify",
|
font=FONT_SMALL,
|
||||||
font=FONT_BODY,
|
|
||||||
anchor="w",
|
|
||||||
)
|
)
|
||||||
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] = []
|
self._sub_items: list[dict] = []
|
||||||
sub_names = ["Erase ", "Program", "Verify "]
|
names = ["Erase ", "Program", "Verify "]
|
||||||
for i, name in enumerate(sub_names):
|
for i, name in enumerate(names):
|
||||||
item = self._build_sub_row(i + 1, name)
|
dot = ctk.CTkLabel(self, text="○", font=FONT_BODY, anchor="w")
|
||||||
item["dot"].grid_remove()
|
label = ctk.CTkLabel(self, text=name, font=FONT_BODY, anchor="w")
|
||||||
item["label"].grid_remove()
|
pct = ctk.CTkLabel(self, text="", font=FONT_BODY, anchor="e")
|
||||||
item["pct"].grid_remove()
|
dot.grid(row=i + 1, column=0, padx=(16, 2), pady=(2, 2), sticky="w")
|
||||||
self._sub_items.append(item)
|
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:
|
self.grid_columnconfigure(1, weight=1)
|
||||||
"""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}
|
|
||||||
|
|
||||||
def _toggle(self) -> None:
|
def _toggle(self) -> None:
|
||||||
"""Toggle collapse/expand."""
|
|
||||||
self._collapsed = not self._collapsed
|
self._collapsed = not self._collapsed
|
||||||
self._toggle_btn.configure(text="▶" if self._collapsed else "▼")
|
self._toggle_btn.configure(text="▶" if self._collapsed else "▼")
|
||||||
for item in self._sub_items:
|
for item in self._sub_items:
|
||||||
if self._collapsed:
|
if self._collapsed:
|
||||||
item["dot"].grid_remove()
|
item["dot"].grid_remove()
|
||||||
item["label"].master.grid_remove()
|
item["label"].grid_remove()
|
||||||
|
item["pct"].grid_remove()
|
||||||
else:
|
else:
|
||||||
item["dot"].grid()
|
item["dot"].grid()
|
||||||
item["label"].master.grid()
|
item["label"].grid()
|
||||||
|
item["pct"].grid()
|
||||||
|
|
||||||
def set_expanded(self, expanded: bool) -> None:
|
def set_expanded(self, expanded: bool) -> None:
|
||||||
"""Set expanded state."""
|
|
||||||
if expanded != self._collapsed:
|
if expanded != self._collapsed:
|
||||||
self._toggle()
|
self._toggle()
|
||||||
|
|
||||||
def set_phase(self, phase: str, pct: int = -1) -> None:
|
def set_phase(self, phase: str, pct: int = -1) -> None:
|
||||||
"""Update sub-step status.
|
idx = {"erase": 0, "program": 1, "verify": 2}.get(phase, -1)
|
||||||
|
|
||||||
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)
|
|
||||||
if idx < 0:
|
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
|
return
|
||||||
|
|
||||||
# Running with progress
|
|
||||||
pct_text = f"{pct}%" if pct >= 0 else ""
|
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):
|
for i, item in enumerate(self._sub_items):
|
||||||
if i < idx:
|
if i < idx:
|
||||||
item["dot"].configure(text="●", text_color=CIRCLE_COMPLETE)
|
item["dot"].configure(text="●")
|
||||||
item["label"].configure(text_color=SUCCESS_COLOR)
|
item["pct"].configure(text="OK")
|
||||||
item["pct"].configure(text="OK", text_color=SUCCESS_COLOR)
|
|
||||||
elif i == idx:
|
elif i == idx:
|
||||||
item["dot"].configure(text="◉", text_color=CIRCLE_RUNNING)
|
item["dot"].configure(text="◉")
|
||||||
item["label"].configure(text_color=ACCENT_RUNNING)
|
item["pct"].configure(text=pct_text)
|
||||||
item["pct"].configure(text=pct_text, text_color=ACCENT_RUNNING)
|
|
||||||
else:
|
else:
|
||||||
item["dot"].configure(text="○", text_color=CIRCLE_PENDING)
|
item["dot"].configure(text="○")
|
||||||
item["label"].configure(text_color=ACCENT_PENDING)
|
item["pct"].configure(text="")
|
||||||
item["pct"].configure(text="", text_color=ACCENT_PENDING)
|
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
"""Reset all sub-steps to pending state."""
|
for i in self._sub_items:
|
||||||
for item in self._sub_items:
|
i["dot"].configure(text="○")
|
||||||
item["dot"].configure(text="○", text_color=CIRCLE_PENDING)
|
i["pct"].configure(text="")
|
||||||
item["label"].configure(text_color=ACCENT_PENDING)
|
|
||||||
item["pct"].configure(text="", text_color=ACCENT_PENDING)
|
|
||||||
if not self._collapsed:
|
if not self._collapsed:
|
||||||
self._toggle()
|
self._toggle()
|
||||||
self._toggle()
|
self._toggle()
|
||||||
|
|||||||
Reference in New Issue
Block a user