Refactor submenu creation logic

This commit is contained in:
jpirnay
2026-04-24 12:44:08 +02:00
parent 7533ed1a9c
commit 0c080f5600
8 changed files with 102 additions and 30 deletions
+47
View File
@@ -1,7 +1,9 @@
#pragma once
#include <I18n.h>
#include <algorithm>
#include <cassert>
#include <iterator>
#include <string>
#include <vector>
@@ -88,6 +90,13 @@ struct SettingInfo {
stringSetter(accessorCtx, v);
}
struct SubmenuData {
StrId id = StrId::STR_NONE_OPT;
std::vector<SettingInfo> items;
};
static void prepareSubmenus(std::vector<SettingInfo>& items, std::vector<SubmenuData>& submenuData);
SettingInfo& withObfuscated() {
obfuscated = true;
return *this;
@@ -237,3 +246,41 @@ struct SettingInfo {
// not the SettingInfo itself.
void toggleValue() const;
};
inline void SettingInfo::prepareSubmenus(std::vector<SettingInfo>& items,
std::vector<SettingInfo::SubmenuData>& submenuData) {
if (items.empty()) return;
std::vector<SettingInfo> preparedItems;
std::vector<SubmenuData> preparedSubmenus;
preparedItems.reserve(items.size());
for (auto& item : items) {
if (item.submenu == StrId::STR_NONE_OPT) {
preparedItems.push_back(std::move(item));
continue;
}
auto it = std::find_if(preparedSubmenus.begin(), preparedSubmenus.end(),
[&item](const SubmenuData& d) { return d.id == item.submenu; });
if (it == preparedSubmenus.end()) {
preparedItems.push_back(SettingInfo::SubmenuEntry(item.submenu));
preparedSubmenus.push_back({item.submenu, {}});
it = preparedSubmenus.end() - 1;
}
it->items.push_back(std::move(item));
}
items.swap(preparedItems);
for (auto& submenu : preparedSubmenus) {
auto it = std::find_if(submenuData.begin(), submenuData.end(),
[&submenu](const SubmenuData& d) { return d.id == submenu.id; });
if (it == submenuData.end()) {
submenuData.push_back(std::move(submenu));
} else {
it->items.insert(it->items.end(), std::make_move_iterator(submenu.items.begin()),
std::make_move_iterator(submenu.items.end()));
}
}
}
+14 -23
View File
@@ -41,33 +41,19 @@ void SettingsActivity::onEnter() {
StrId lastControlsSub = StrId::STR_NONE_OPT;
StrId lastSystemSub = StrId::STR_NONE_OPT;
// Shared placement logic — locates submenu target or inserts separator.
// Returns the vector the caller should push into (either `vec` or a submenu's items).
auto locateTarget = [this](std::vector<SettingInfo>& vec, StrId& lastSub,
const SettingInfo& s) -> std::vector<SettingInfo>* {
if (s.submenu != StrId::STR_NONE_OPT) {
auto it = std::find_if(submenuData.begin(), submenuData.end(),
[&s](const SubmenuData& d) { return d.id == s.submenu; });
if (it == submenuData.end()) {
vec.push_back(SettingInfo::SubmenuEntry(s.submenu));
submenuData.push_back({s.submenu, {}});
it = submenuData.end() - 1;
}
return &it->items;
}
auto addTo = [](std::vector<SettingInfo>& vec, StrId& lastSub, const SettingInfo& s) {
if (s.subcategory != StrId::STR_NONE_OPT && s.subcategory != lastSub) {
vec.push_back(SettingInfo::Separator(s.subcategory));
lastSub = s.subcategory;
}
return &vec;
vec.push_back(s);
};
auto addTo = [&locateTarget](std::vector<SettingInfo>& vec, StrId& lastSub, const SettingInfo& s) {
locateTarget(vec, lastSub, s)->push_back(s);
};
auto addToMoved = [&locateTarget](std::vector<SettingInfo>& vec, StrId& lastSub, SettingInfo&& s) {
auto* target = locateTarget(vec, lastSub, s);
target->push_back(std::move(s));
auto addToMoved = [](std::vector<SettingInfo>& vec, StrId& lastSub, SettingInfo&& s) {
if (s.subcategory != StrId::STR_NONE_OPT && s.subcategory != lastSub) {
vec.push_back(SettingInfo::Separator(s.subcategory));
lastSub = s.subcategory;
}
vec.push_back(std::move(s));
};
for (const auto& setting : getSettingsList()) {
@@ -122,6 +108,11 @@ void SettingsActivity::onEnter() {
std::move(SettingInfo::Action(StrId::STR_SYSTEM_INFO, SettingAction::SystemInfo)
.withSubcategory(StrId::STR_MENU_SYS_SYSTEM)));
SettingInfo::prepareSubmenus(displaySettings, submenuData);
SettingInfo::prepareSubmenus(readerSettings, submenuData);
SettingInfo::prepareSubmenus(controlsSettings, submenuData);
SettingInfo::prepareSubmenus(systemSettings, submenuData);
// Reset selection to first category
selectedCategoryIndex = 0;
selectedSettingIndex = 0;
@@ -226,7 +217,7 @@ void SettingsActivity::toggleCurrentSetting() {
if (setting.action == SettingAction::Submenu) {
auto it = std::find_if(submenuData.begin(), submenuData.end(),
[&setting](const SubmenuData& d) { return d.id == setting.nameId; });
[&setting](const SettingInfo::SubmenuData& d) { return d.id == setting.nameId; });
if (it != submenuData.end()) {
startActivityForResult(
std::make_unique<SettingsSubmenuActivity>(renderer, mappedInput, setting.nameId, it->items), resultHandler);
+1 -5
View File
@@ -24,11 +24,7 @@ class SettingsActivity final : public Activity {
static constexpr int categoryCount = 4;
static const StrId categoryNames[categoryCount];
struct SubmenuData {
StrId id;
std::vector<SettingInfo> items;
};
std::vector<SubmenuData> submenuData;
std::vector<SettingInfo::SubmenuData> submenuData;
void enterCategory(int categoryIndex);
void toggleCurrentSetting();
@@ -9,6 +9,12 @@
#include "components/UITheme.h"
#include "fontIds.h"
void SettingsSubmenuActivity::onEnter() {
Activity::onEnter();
initMenuList();
requestUpdate();
}
void SettingsSubmenuActivity::onActionSelected(int index) {
const auto& setting = menuItems[index];
auto resultHandler = [this](const ActivityResult&) { SETTINGS.saveToFile(); };
@@ -12,6 +12,7 @@ class SettingsSubmenuActivity final : public MenuListActivity {
StrId titleId;
// MenuListActivity overrides
void onEnter() override;
void onActionSelected(int index) override;
void onSettingToggled(int index) override;