Files
Crosspoint/src/activities/MenuListActivity.h
T
2026-04-24 14:17:50 +02:00

114 lines
4.3 KiB
C++

#pragma once
#include <vector>
#include "Activity.h"
#include "settings/SettingInfo.h"
#include "util/ButtonNavigator.h"
struct Rect;
// Base class for activities that display a scrollable list of SettingInfo items.
// Provides common navigation, toggle/cycle logic, and drawList rendering.
//
// Subclasses populate `menuItems` (typically in the constructor or onEnter()),
// then rely on the default loop()/onEnter() or override selectively.
//
// === Minimal example ===
//
// class MyMenuActivity final : public MenuListActivity {
// public:
// explicit MyMenuActivity(GfxRenderer& r, MappedInputManager& m)
// : MenuListActivity("MyMenu", r, m) {
// // Separator header
// menuItems.push_back(SettingInfo::Separator(StrId::STR_MY_SECTION));
//
// // Toggle bound to a CrossPointSettings field
// menuItems.push_back(SettingInfo::Toggle(StrId::STR_MY_TOGGLE, &CrossPointSettings::myFlag));
//
// // Enum bound to a CrossPointSettings field
// menuItems.push_back(SettingInfo::Enum(StrId::STR_MY_ENUM, &CrossPointSettings::myEnum,
// {StrId::STR_OPTION_A, StrId::STR_OPTION_B, StrId::STR_OPTION_C}));
//
// // DynamicEnum with local state (getter/setter lambdas)
// menuItems.push_back(SettingInfo::DynamicEnum(StrId::STR_MY_DYNAMIC,
// {StrId::STR_LOW, StrId::STR_HIGH},
// [this]() -> uint8_t { return localValue; },
// [this](uint8_t v) { localValue = v; }));
//
// // Action item (handled in onActionSelected)
// menuItems.push_back(SettingInfo::Action(StrId::STR_DO_SOMETHING, SettingAction::None));
// }
//
// // render(): draw header/footer around the list
// void render(RenderLock&&) override {
// renderer.clearScreen();
// const Rect r = UITheme::getContentRect(renderer, true, false);
// drawMenuList(r); // <-- draws the item list
// GUI.drawButtonHints(renderer, ...);
// renderer.displayBuffer();
// }
//
// private:
// uint8_t localValue = 0;
//
// // Called when an ACTION item is confirmed
// void onActionSelected(int index) override {
// if (menuItems[index].nameId == StrId::STR_DO_SOMETHING) { /* ... */ }
// }
//
// // Called after a TOGGLE/ENUM/VALUE is cycled
// void onSettingToggled(int) override { SETTINGS.saveToFile(); }
// };
//
// The base class provides:
// onEnter() — wires up the selectable-predicate (skips separators) and requestUpdate().
// loop() — handles Back (→ onBackPressed), Confirm (→ toggleCurrentItem), and nav.
// drawMenuList(rect) — calls GUI.drawList with SettingInfo-based title/value lambdas.
// getItemValueString(i) — override for custom per-item value display.
// onBackPressed() — override to customise Back behaviour (default: finish()).
//
class MenuListActivity : public Activity {
protected:
std::vector<SettingInfo> menuItems;
std::vector<SettingInfo::SubmenuData> submenuData;
int selectedIndex = 0;
ButtonNavigator buttonNavigator;
bool submenusPrepared = false;
// Call after building/rebuilding menuItems to wire up the selectable predicate.
void initMenuList();
// Process SettingInfo items marked with withSubmenu() into submenu placeholders.
void prepareSubmenus();
void openSubmenu(const SettingInfo& submenuEntry);
// Handle up/down navigation via buttonNavigator. Call from loop() if overriding.
void handleNavigation();
// Toggle/cycle the currently selected item. For ACTION items, delegates to onActionSelected().
virtual void toggleCurrentItem();
// Draw the list into the given rect using GUI.drawList().
void drawMenuList(const Rect& rect);
// Override to provide custom value display for specific items.
// Default returns SettingInfo::getDisplayValue().
[[nodiscard]] virtual std::string getItemValueString(int index) const;
// Called when an ACTION-type item is confirmed. Override to handle actions.
virtual void onActionSelected(int index) {}
// Called when Back is pressed. Default calls finish().
virtual void onBackPressed() { finish(); }
// Called after a TOGGLE/ENUM/VALUE item has been toggled.
// Override to persist changes or trigger side-effects.
virtual void onSettingToggled(int /*index*/) {}
public:
using Activity::Activity;
void onEnter() override;
void loop() override;
};