feat(theme): make MOX idle accent independently themable (follows #3763)#3768
Conversation
Follow-up to #3763, mirroring the waterfall LIVE chip (#3761). #3763 gave the idle MOX button a distinct amber accent so it reads as the primary transmit control, but with hardcoded hex literals duplicated across its two styling sites. This tokenizes that accent behind dedicated color.tx.mox.* tokens so it is editable in the Theme Editor: color.tx.mox.border / .text — idle amber border + text color.tx.mox.border.hover / .text.hover — hover variants Both MOX styling sites (construction and the moxChanged return-to-idle branch) now share a single kMoxIdleStyle template via ThemeManager::applyStyleSheet(), which also removes the duplicated-literal drift risk the #3763 review flagged. The active-TX red branch is converted from setStyleSheet() to applyStyleSheet() too — its template stays byte-identical literal hex, but routing it through the tracked path fixes a latent bug: a Theme Editor recolor mid-transmit would otherwise re-resolve the stale idle template over the active red (the TUNE button already uses applyStyleSheet for both states for this reason). Seed defaults and both preset JSONs carry the same literal values the buttons used before, so the rendered appearance is unchanged; only the editability is new. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Reviewed the diff against ThemeManager::applyStyleSheet / reapplyAllTrackedStyleSheets and the seed/preset token sources. This is clean and well-scoped — appearance-only, no transmit/keying path touched. Thanks @ten9876, nice follow-up to #3763.
A few things I verified rather than took on faith:
-
Live-recolor mechanism is correct.
applyStyleSheetrecords the most-recently-applied template per widget andthemeChangedre-resolves it (ThemeManager.cpp:318,:1789). So the idle branch (tokenizedkMoxIdleStyle) recolors live, and the active-TX branch re-registers a token-free literal template — a Theme Editor recolor mid-transmit re-resolves that literal and stays red rather than stomping the idle amber over it. The latent-bug framing in the description is accurate, and routing the red branch throughapplyStyleSheetis the right fix (matches the TUNE button precedent). -
No visual regression. The active-red template is byte-identical to the prior literal (and, like the pre-existing
tuneChangedred branch, intentionally omits the hover/disabled rules — consistent with how that sibling already behaves). Idle defaults inseedBuiltinDefaultsand both preset JSONs match the old hardcoded hex, and the JSON nesting (tx.mox.*undercolor) mirrors the already-workingwaterfall.livetoken, so{{color.tx.mox.border}}resolves as expected. -
De-duplication is real — both idle styling sites now share
kMoxIdleStyle, removing the drift risk the #3763 review flagged.
No AppSettings/RAII/null-pointer/lifetime concerns: applyStyleSheet guards null and auto-deregisters on widget destroyed(). Nothing outside stated scope.
One optional thought (non-blocking): the active-red #cc2222/#ff4444 is still literal and now visually diverges from the themable idle accent — if a future theme recolors MOX amber, the TX-active red won't track it. That's arguably fine (red = transmitting is a safety-signal convention you may want fixed), but if symmetry is desired later, the same tokenization pattern would extend cleanly. Not needed for this PR.
LGTM.
🤖 aethersdr-agent · cost: $2.3042 · model: claude-opus-4-8
Summary
Follow-up to #3763, mirroring the waterfall LIVE chip (#3761). #3763 gave the idle MOX button a distinct amber accent so it reads as the primary transmit control — but with hardcoded hex literals duplicated across its two styling sites. This tokenizes that accent behind dedicated
color.tx.mox.*tokens so it becomes editable in the Theme Editor:color.tx.mox.border#d08020color.tx.mox.text#f0c890color.tx.mox.border.hover#e09030color.tx.mox.text.hover#ffd8a0What changed
moxChangedreturn-to-idle branch) now share a singlekMoxIdleStyletemplate viaThemeManager::applyStyleSheet(), which also removes the duplicated-literal drift risk the fix: give the idle MOX button a distinct accent color so it reads as the transmit button #3763 review flagged.setStyleSheet()toapplyStyleSheet()as well. Its template stays byte-identical literal hex, but routing it through the tracked path fixes a latent bug: a Theme Editor recolor mid-transmit would otherwise re-resolve the stale idle template over the active red. (The TUNE button already usesapplyStyleSheetfor both states for exactly this reason.)ThemeManager::seedBuiltinDefaults) and both preset JSONs carry the same literal values the buttons used before. The buttons don't respond to theme today (hardcoded hex), so seeding both presets identically preserves the rendered appearance exactly — only the editability is new.Background / hover-background / disabled colors stay literal (structural, shared with the neutral TUNE/ATU/MEM
btnStyle); only the amber accent that defines MOX's identity is tokenized — the same focused scope as #3761.Constitution
Test plan
cmake --build build --target AetherSDR)json.load)color.tx.mox.borderin the Theme Editor moves only the MOX accent (and updates live, including while transmitting)Refs #3663. Follows #3763, #3761.
🤖 Generated with Claude Code