diff --git a/src/activities/reader/EpubReaderMenuActivity.cpp b/src/activities/reader/EpubReaderMenuActivity.cpp index c82f6510..15641b46 100644 --- a/src/activities/reader/EpubReaderMenuActivity.cpp +++ b/src/activities/reader/EpubReaderMenuActivity.cpp @@ -25,6 +25,11 @@ EpubReaderMenuActivity::EpubReaderMenuActivity(GfxRenderer& renderer, MappedInpu totalPages(totalPages), bookProgressPercent(bookProgressPercent) {} +std::string EpubReaderMenuActivity::MenuItem::getTitle() const { + const auto t = I18N.get(labelId); + return isSeparator ? UITheme::makeSeparatorTitle(t) : t; +} + std::vector EpubReaderMenuActivity::buildMenuItems(bool hasFootnotes) { std::vector items; items.reserve(18); @@ -63,11 +68,7 @@ std::vector EpubReaderMenuActivity::buildMenuI void EpubReaderMenuActivity::onEnter() { Activity::onEnter(); const auto pred = UITheme::makeSelectablePredicate( - static_cast(menuItems.size()), [this](int i) { - const auto& item = menuItems[i]; - const auto t = I18N.get(item.labelId); - return item.isSeparator ? UITheme::makeSeparatorTitle(t) : t; - }); + static_cast(menuItems.size()), [this](int i) { return menuItems[i].getTitle(); }); buttonNavigator.setSelectablePredicate(pred, static_cast(menuItems.size())); if (!pred(selectedIndex)) { selectedIndex = buttonNavigator.nextIndex(selectedIndex); @@ -187,11 +188,7 @@ void EpubReaderMenuActivity::render(RenderLock&&) { GUI.drawList( renderer, Rect{contentRect.x, startY, contentRect.width, listHeight}, static_cast(menuItems.size()), selectedIndex, - [this](int index) { - const auto& item = menuItems[index]; - const auto title = I18N.get(item.labelId); - return item.isSeparator ? UITheme::makeSeparatorTitle(title) : title; - }, + [this](int index) { return menuItems[index].getTitle(); }, nullptr, nullptr, [this](int index) { const auto& item = menuItems[index]; diff --git a/src/activities/reader/EpubReaderMenuActivity.h b/src/activities/reader/EpubReaderMenuActivity.h index 216caae2..a0617dab 100644 --- a/src/activities/reader/EpubReaderMenuActivity.h +++ b/src/activities/reader/EpubReaderMenuActivity.h @@ -46,6 +46,7 @@ class EpubReaderMenuActivity final : public Activity { StrId labelId; bool isSeparator = false; static MenuItem separator(StrId label) { return {MenuAction::NONE, label, true}; } + [[nodiscard]] std::string getTitle() const; }; static std::vector buildMenuItems(bool hasFootnotes); diff --git a/src/activities/settings/ClockSettingsActivity.cpp b/src/activities/settings/ClockSettingsActivity.cpp index 1e6a9b1c..4b01adfe 100644 --- a/src/activities/settings/ClockSettingsActivity.cpp +++ b/src/activities/settings/ClockSettingsActivity.cpp @@ -19,6 +19,11 @@ const StrId timeZoneNames[CrossPointSettings::TIMEZONE_COUNT] = { StrId::STR_TZ_EST, StrId::STR_TZ_CST, StrId::STR_TZ_MST, StrId::STR_TZ_PST}; } // namespace +std::string ClockSettingsActivity::MenuItem::getTitle() const { + const auto t = I18N.get(labelId); + return isSeparator ? UITheme::makeSeparatorTitle(t) : t; +} + std::vector ClockSettingsActivity::buildMenuItems() { std::vector items; items.reserve(7); @@ -38,10 +43,7 @@ std::vector ClockSettingsActivity::buildMenuIte void ClockSettingsActivity::onEnter() { Activity::onEnter(); const auto pred = UITheme::makeSelectablePredicate( - static_cast(menuItems.size()), [this](int i) { - const auto t = I18N.get(menuItems[i].labelId); - return menuItems[i].isSeparator ? UITheme::makeSeparatorTitle(t) : t; - }); + static_cast(menuItems.size()), [this](int i) { return menuItems[i].getTitle(); }); buttonNavigator.setSelectablePredicate(pred, static_cast(menuItems.size())); if (!pred(selectedIndex)) { selectedIndex = buttonNavigator.nextIndex(selectedIndex); @@ -124,10 +126,7 @@ void ClockSettingsActivity::render(RenderLock&&) { GUI.drawList( renderer, Rect{0, contentTop, pageWidth, contentHeight}, static_cast(menuItems.size()), selectedIndex, - [this](int index) { - const auto title = I18N.get(menuItems[index].labelId); - return menuItems[index].isSeparator ? UITheme::makeSeparatorTitle(title) : title; - }, + [this](int index) { return menuItems[index].getTitle(); }, nullptr, nullptr, [this](int index) { const auto action = menuItems[index].action; diff --git a/src/activities/settings/ClockSettingsActivity.h b/src/activities/settings/ClockSettingsActivity.h index a5c02136..54a4196b 100644 --- a/src/activities/settings/ClockSettingsActivity.h +++ b/src/activities/settings/ClockSettingsActivity.h @@ -15,6 +15,7 @@ class ClockSettingsActivity final : public Activity { StrId labelId; bool isSeparator = false; static MenuItem separator(StrId label) { return {Action::NONE, label, true}; } + [[nodiscard]] std::string getTitle() const; }; ButtonNavigator buttonNavigator; diff --git a/src/components/UITheme.h b/src/components/UITheme.h index 4cacca79..041b1338 100644 --- a/src/components/UITheme.h +++ b/src/components/UITheme.h @@ -36,22 +36,19 @@ class UITheme { // struct MenuItem { // Action action; StrId labelId; bool isSeparator = false; // static MenuItem separator(StrId label) { return {Action::NONE, label, true}; } + // std::string getTitle() const; // implemented in .cpp: makeSeparatorTitle when isSeparator // }; // const std::vector items = buildMenuItems(); // // In buildMenuItems, use MenuItem::separator(StrId) for section headers. // - // // Title getter — used by both drawList and makeSelectablePredicate: - // auto titleGetter = [&](int i) { - // const auto t = I18N.get(items[i].labelId); - // return items[i].isSeparator ? UITheme::makeSeparatorTitle(t) : t; - // }; - // // // onEnter: wire navigation so separators are skipped: - // const auto pred = UITheme::makeSelectablePredicate(items.size(), titleGetter); + // const auto pred = UITheme::makeSelectablePredicate(items.size(), + // [this](int i) { return items[i].getTitle(); }); // buttonNavigator.setSelectablePredicate(pred, items.size()); // // // render: pass the same getter to drawList; separator rows are drawn automatically: - // GUI.drawList(renderer, rect, items.size(), selectedIndex, titleGetter, ...); + // GUI.drawList(renderer, rect, items.size(), selectedIndex, + // [this](int i) { return items[i].getTitle(); }, ...); static std::function makeSelectablePredicate(int total, std::function titleGetter); // Returns the drawable content Rect accounting for screen orientation and visible button hints.