fix(instrument-ui): distinguish Disabled from Off, add hover cue to mode toggles, close review minors

Adds a hairline outline for Disabled chrome buttons, resolves Hover on the four
mode-selector single-buttons, re-measures the control-surface doc's 1.2 layout
table post-reflow, and adds a structural test pinning every enable/mode toggle
to a derived segment.
This commit is contained in:
2026-08-03 13:43:38 -04:00
parent 450559f155
commit 73c69f689c
8 changed files with 108 additions and 33 deletions
+22 -2
View File
@@ -226,15 +226,35 @@ void ReaSamplerEditor::paintChrome(LICE_IBitmap* bmp, const FaceLayout& fl, bool
: (active ? InteractionState::Active
: (hov ? InteractionState::Hover : InteractionState::Rest));
fillSurface(bmp, toKitBox(r), Role::BgCell, st);
// Disabled's wash over bg/cell is barely a shade off Rest's — the third state needs
// its own mark, not just a slightly-quieter fill, so it draws the one outline this
// control ever gets. See PLAN.md's Off-vs-Disabled ruling: Off is live and
// clickable, Disabled is not, and the two must not read as the same thing.
if (disabled) {
LICE_DrawRect(bmp, r.x, r.y, r.width - 1, r.height - 1,
toLice(roleColor(Role::LineHairline)), 1.0f, 0);
}
kitTextCentered(bmp, r, label, kToolbarFont,
active && !disabled ? Role::BgBase
: (hov ? Role::TextPrimary : Role::TextDim));
};
drawChromeToggle(cr.loop, "Loop", HoverKind::kLoop, marks.hasLoop,
!loopControlsLive());
// The channel button is a MODE selector like the deck's Stage|Spline buttons — always
// "on", so InteractionState::Active would otherwise swallow every hover. Filled by
// accent/primary rather than bg/cell so Hover's mix-toward-accent/hot actually moves the
// surface instead of nudging bg/cell by a few percent (roleColorState's Active case
// always answers accent/primary regardless of the role passed in, so Rest is unreachable
// here and this is purely which color Hover mixes FROM).
const auto drawModeChromeToggle = [&](const Rect& r, const char* label, HoverKind hk) {
const bool hov = isHovered(hk, -1);
const InteractionState st = hov ? InteractionState::Hover : InteractionState::Active;
fillSurface(bmp, toKitBox(r), Role::AccentPrimary, st);
kitTextCentered(bmp, r, label, kToolbarFont, Role::BgBase);
};
const bool isStereo = (channelMode_ == ChannelMode::Stereo);
drawChromeToggle(cr.channel, isStereo ? "Stereo" : "Mono", HoverKind::kChannel,
/*active=*/true, /*disabled=*/false);
drawModeChromeToggle(cr.channel, isStereo ? "Stereo" : "Mono", HoverKind::kChannel);
}
// The strip row: the full 128-key piano with the root lit. The loaded capture responds