Toggle Controls
Three toggle controls — ButtonToggle, PillToggle, and SegmentToggle — each with animated state transitions, Settings/Theme/Style layering, and a single onToggled callback.
Three Toggle Styles
Each toggle inherits its geometry from a Settings type and its colors from a Theme type. The active app theme is applied automatically via Themeable. Use applySettings(), applyTheme(), or applyStyle() to customize, and onToggled() to react to state changes.
| Class | Visual style | Manifest | Variant template |
|---|---|---|---|
ml::ButtonToggle | Rectangular button, label swaps on toggle | ButtonToggleManifest | ButtonToggleWith<M> |
ml::PillToggle | iOS-style oval with animated sliding thumb | PillToggleManifest | PillToggleWith<M> |
ml::SegmentToggle | Two-segment pill with animated pill indicator | SegmentToggleManifest | SegmentToggleWith<M> |
All three share the same state API: setOn(bool), toggle(), isOn(), setEnabled(bool), isEnabled(), and onToggled(std::function<void(bool)>).
ButtonToggle
A rectangular button that changes its label and colors when toggled on or off. Inherits ButtonSettings (geometry, labels, icons) and ButtonTheme (colors).
ml::ButtonToggle toggle;
toggle.setOffLabel("Muted");
toggle.setOnLabel("Live");
toggle.setPosition({200.f, 100.f});
toggle.onToggled([](bool on) {
setStreamActive(on);
});
addComponent(toggle);
The toggle state can be driven programmatically too:
toggle.setOn(true); // force on
toggle.toggle(); // flip current state
bool on = toggle.isOn(); // query state
toggle.setEnabled(false); // disable interactions
bool en = toggle.isEnabled();
Use applySettings(), applyTheme(), or applyStyle() to bulk-configure the toggle. Any type that derives from ButtonSettings works with applySettings(), and any type that derives from ButtonTheme works with applyTheme(). applyStyle() requires both.
| Flag | State | Meaning |
|---|---|---|
Flag::ON | State::ON | Toggle is currently active |
Flag::DISABLED | State::DISABLED | Interactions are suppressed |
| — | State::IDLE | Default, not hovered |
| — | State::HOVERED | Mouse is over the button |
PillToggle
An iOS-style oval pill switch. The circular thumb slides left (off) or right (on) with a smooth animation driven internally by an sf::Clock. Inherits PillSettings (layout, labels, animation speed) and PillTheme (colors).
ml::PillToggle darkMode;
darkMode.setRightLabel("Dark mode"); // label drawn to the right of the pill
darkMode.setPosition({200.f, 100.f});
darkMode.onToggled([](bool on) {
ThemeManager::apply(on ? DarkTheme{} : LightTheme{});
});
addComponent(darkMode);
// Both names work — match whichever convention you prefer
darkMode.setCharacterSize(14); // SFML-style alias
darkMode.setFontSize(14); // Settings-style name
unsigned sz = darkMode.getCharacterSize(); // or getFontSize()
The only thing the active app theme updates on a PillToggle is the PillTheme layer — geometry and labels are untouched. If you need to override colors without a full style, call applyTheme(MyPillTheme{}).
SegmentToggle
A two-option segmented control drawn as a rounded rectangle split into two halves. The active segment is highlighted by an animated pill indicator. Inherits SegmentSettings (geometry, labels) and SegmentTheme (colors).
ml::SegmentToggle themeSwitch;
themeSwitch.setOffLabel("Light"); // left segment
themeSwitch.setOnLabel("Dark"); // right segment
themeSwitch.setPosition({200.f, 100.f});
themeSwitch.onToggled([](bool on) {
applyTheme(on);
});
addComponent(themeSwitch);
struct MySegmentStyle : public ml::SegmentSettings,
public ml::SegmentTheme
{
MySegmentStyle() {
// SegmentSettings fields
width = 180.f;
height = 34.f;
cornerRadius = 8.f;
// SegmentTheme fields
// (colors come from theme defaults)
}
};
themeSwitch.applyStyle(MySegmentStyle{});
// Or apply layers separately:
themeSwitch.applySettings(MySegmentStyle{}); // geometry only
themeSwitch.applyTheme(MySegmentStyle{}); // colors only
Like PillToggle, the active theme only touches the SegmentTheme layer automatically. Call applySettings() explicitly whenever you need to update geometry.