@@ -60,7 +60,6 @@ STR_CALIBRE_INSTRUCTION_4: "\"Keep this screen open while sending\""
|
|||||||
STR_CAT_DISPLAY: "Display"
|
STR_CAT_DISPLAY: "Display"
|
||||||
STR_CAT_READER: "Reader"
|
STR_CAT_READER: "Reader"
|
||||||
STR_CAT_CONTROLS: "Controls"
|
STR_CAT_CONTROLS: "Controls"
|
||||||
STR_CAT_NETWORK: "Network"
|
|
||||||
STR_CAT_SYSTEM: "System"
|
STR_CAT_SYSTEM: "System"
|
||||||
STR_SLEEP_SCREEN: "Sleep Screen"
|
STR_SLEEP_SCREEN: "Sleep Screen"
|
||||||
STR_SLEEP_COVER_MODE: "Sleep Screen Cover Mode"
|
STR_SLEEP_COVER_MODE: "Sleep Screen Cover Mode"
|
||||||
@@ -469,10 +468,4 @@ STR_WEATHER_MOON_INFO: "Moon"
|
|||||||
STR_WEATHER_SUN_INFO: "Sun"
|
STR_WEATHER_SUN_INFO: "Sun"
|
||||||
STR_READER_TOOLS: "Tools"
|
STR_READER_TOOLS: "Tools"
|
||||||
STR_READER_NAVIGATION: "Navigation"
|
STR_READER_NAVIGATION: "Navigation"
|
||||||
STR_READER_APPEARANCE: "Appearance"
|
STR_READER_APPEARANCE: "Appearance"
|
||||||
STR_SETTINGS_MENU_SYSTEM: "System"
|
|
||||||
STR_SETTINGS_MENU_TOOLS: "Tools"
|
|
||||||
STR_SETTINGS_MENU_NETWORK: "Network"
|
|
||||||
STR_SETTINGS_MENU_SETTINGS: "Behaviour"
|
|
||||||
STR_SETTINGS_MENU_SOURCES: "Online Sources"
|
|
||||||
STR_SETTINGS_MENU_SYNC: "Synchronisation"
|
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "MappedInputManager.h"
|
#include "MappedInputManager.h"
|
||||||
#include "components/UITheme.h"
|
#include "components/UITheme.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
#include "util/MenuItemHelpers.h"
|
|
||||||
|
|
||||||
EpubReaderMenuActivity::EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
|
EpubReaderMenuActivity::EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
|
||||||
const std::string& title, const int currentPage, const int totalPages,
|
const std::string& title, const int currentPage, const int totalPages,
|
||||||
@@ -30,7 +29,7 @@ std::vector<EpubReaderMenuActivity::MenuItem> EpubReaderMenuActivity::buildMenuI
|
|||||||
std::vector<MenuItem> items;
|
std::vector<MenuItem> items;
|
||||||
items.reserve(18);
|
items.reserve(18);
|
||||||
// Navigation
|
// Navigation
|
||||||
items.push_back(makeSeparatorMenuItem<MenuItem>(StrId::STR_READER_NAVIGATION));
|
items.push_back({MenuAction::NONE, StrId::STR_READER_NAVIGATION, true});
|
||||||
items.push_back({MenuAction::SELECT_CHAPTER, StrId::STR_SELECT_CHAPTER});
|
items.push_back({MenuAction::SELECT_CHAPTER, StrId::STR_SELECT_CHAPTER});
|
||||||
items.push_back({MenuAction::GO_TO_PERCENT, StrId::STR_GO_TO_PERCENT});
|
items.push_back({MenuAction::GO_TO_PERCENT, StrId::STR_GO_TO_PERCENT});
|
||||||
if (hasFootnotes) {
|
if (hasFootnotes) {
|
||||||
@@ -39,7 +38,7 @@ std::vector<EpubReaderMenuActivity::MenuItem> EpubReaderMenuActivity::buildMenuI
|
|||||||
items.push_back({MenuAction::AUTO_PAGE_TURN, StrId::STR_AUTO_TURN_PAGES_PER_MIN});
|
items.push_back({MenuAction::AUTO_PAGE_TURN, StrId::STR_AUTO_TURN_PAGES_PER_MIN});
|
||||||
|
|
||||||
// Appearance
|
// Appearance
|
||||||
items.push_back(makeSeparatorMenuItem<MenuItem>(StrId::STR_READER_APPEARANCE));
|
items.push_back({MenuAction::NONE, StrId::STR_READER_APPEARANCE, true});
|
||||||
items.push_back({MenuAction::EMBEDDED_STYLE, StrId::STR_EMBEDDED_STYLE});
|
items.push_back({MenuAction::EMBEDDED_STYLE, StrId::STR_EMBEDDED_STYLE});
|
||||||
items.push_back({MenuAction::IMAGE_RENDERING, StrId::STR_IMAGES});
|
items.push_back({MenuAction::IMAGE_RENDERING, StrId::STR_IMAGES});
|
||||||
items.push_back({MenuAction::TEXT_DARKNESS, StrId::STR_TEXT_DARKNESS});
|
items.push_back({MenuAction::TEXT_DARKNESS, StrId::STR_TEXT_DARKNESS});
|
||||||
@@ -47,13 +46,13 @@ std::vector<EpubReaderMenuActivity::MenuItem> EpubReaderMenuActivity::buildMenuI
|
|||||||
|
|
||||||
// Synchronisation (only if credentials are set, to avoid confusion)
|
// Synchronisation (only if credentials are set, to avoid confusion)
|
||||||
if (KOREADER_STORE.hasCredentials()) {
|
if (KOREADER_STORE.hasCredentials()) {
|
||||||
items.push_back(makeSeparatorMenuItem<MenuItem>(StrId::STR_KOREADER_SYNC));
|
items.push_back({MenuAction::NONE, StrId::STR_KOREADER_SYNC, true});
|
||||||
items.push_back({MenuAction::PULL_REMOTE, StrId::STR_PULL_PROGRESS_FROM_OTHER_DEVICES});
|
items.push_back({MenuAction::PULL_REMOTE, StrId::STR_PULL_PROGRESS_FROM_OTHER_DEVICES});
|
||||||
items.push_back({MenuAction::PUSH_LOCAL, StrId::STR_PUSH_PROGRESS_FROM_THIS_DEVICE});
|
items.push_back({MenuAction::PUSH_LOCAL, StrId::STR_PUSH_PROGRESS_FROM_THIS_DEVICE});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
items.push_back(makeSeparatorMenuItem<MenuItem>(StrId::STR_READER_TOOLS));
|
items.push_back({MenuAction::NONE, StrId::STR_READER_TOOLS, true});
|
||||||
items.push_back({MenuAction::SCREENSHOT, StrId::STR_SCREENSHOT_BUTTON});
|
items.push_back({MenuAction::SCREENSHOT, StrId::STR_SCREENSHOT_BUTTON});
|
||||||
items.push_back({MenuAction::DISPLAY_QR, StrId::STR_DISPLAY_QR});
|
items.push_back({MenuAction::DISPLAY_QR, StrId::STR_DISPLAY_QR});
|
||||||
items.push_back({MenuAction::DELETE_CACHE, StrId::STR_DELETE_CACHE});
|
items.push_back({MenuAction::DELETE_CACHE, StrId::STR_DELETE_CACHE});
|
||||||
@@ -62,7 +61,9 @@ std::vector<EpubReaderMenuActivity::MenuItem> EpubReaderMenuActivity::buildMenuI
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::function<bool(int)> EpubReaderMenuActivity::buildSelectablePredicate() const {
|
std::function<bool(int)> EpubReaderMenuActivity::buildSelectablePredicate() const {
|
||||||
return makeSelectablePredicate(menuItems);
|
return [this](int index) {
|
||||||
|
return index >= 0 && index < static_cast<int>(menuItems.size()) && !menuItems[index].isSeparator;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpubReaderMenuActivity::onEnter() {
|
void EpubReaderMenuActivity::onEnter() {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include <Epub.h>
|
#include <Epub.h>
|
||||||
#include <I18n.h>
|
#include <I18n.h>
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -30,12 +29,6 @@ class EpubReaderMenuActivity final : public Activity {
|
|||||||
DELETE_CACHE
|
DELETE_CACHE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MenuItem {
|
|
||||||
MenuAction action;
|
|
||||||
StrId labelId;
|
|
||||||
bool isSeparator = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& title,
|
explicit EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& title,
|
||||||
const int currentPage, const int totalPages, const int bookProgressPercent,
|
const int currentPage, const int totalPages, const int bookProgressPercent,
|
||||||
const uint8_t currentOrientation, const bool hasFootnotes,
|
const uint8_t currentOrientation, const bool hasFootnotes,
|
||||||
@@ -47,10 +40,17 @@ class EpubReaderMenuActivity final : public Activity {
|
|||||||
void loop() override;
|
void loop() override;
|
||||||
void render(RenderLock&&) override;
|
void render(RenderLock&&) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct MenuItem {
|
||||||
|
MenuAction action;
|
||||||
|
StrId labelId;
|
||||||
|
bool isSeparator = false;
|
||||||
|
};
|
||||||
|
|
||||||
static std::vector<MenuItem> buildMenuItems(bool hasFootnotes);
|
static std::vector<MenuItem> buildMenuItems(bool hasFootnotes);
|
||||||
|
|
||||||
std::function<bool(int)> buildSelectablePredicate() const;
|
std::function<bool(int)> buildSelectablePredicate() const;
|
||||||
|
|
||||||
private:
|
|
||||||
// Fixed menu layout
|
// Fixed menu layout
|
||||||
const std::vector<MenuItem> menuItems;
|
const std::vector<MenuItem> menuItems;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "SyncTimeActivity.h"
|
#include "SyncTimeActivity.h"
|
||||||
#include "components/UITheme.h"
|
#include "components/UITheme.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
#include "util/MenuItemHelpers.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const StrId timeZoneNames[CrossPointSettings::TIMEZONE_COUNT] = {
|
const StrId timeZoneNames[CrossPointSettings::TIMEZONE_COUNT] = {
|
||||||
@@ -24,20 +23,22 @@ std::vector<ClockSettingsActivity::MenuItem> ClockSettingsActivity::buildMenuIte
|
|||||||
std::vector<MenuItem> items;
|
std::vector<MenuItem> items;
|
||||||
items.reserve(7);
|
items.reserve(7);
|
||||||
// Settings
|
// Settings
|
||||||
items.push_back(makeSeparatorMenuItem<MenuItem>(StrId::STR_SETTINGS_TITLE));
|
items.push_back({Action::NONE, StrId::STR_SETTINGS_TITLE, true});
|
||||||
items.push_back({Action::USE_CLOCK, StrId::STR_USE_CLOCK});
|
items.push_back({Action::USE_CLOCK, StrId::STR_USE_CLOCK});
|
||||||
items.push_back({Action::CLOCK_FORMAT, StrId::STR_CLOCK_FORMAT});
|
items.push_back({Action::CLOCK_FORMAT, StrId::STR_CLOCK_FORMAT});
|
||||||
items.push_back({Action::TIMEZONE, StrId::STR_TIMEZONE});
|
items.push_back({Action::TIMEZONE, StrId::STR_TIMEZONE});
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
items.push_back(makeSeparatorMenuItem<MenuItem>(StrId::STR_READER_TOOLS));
|
items.push_back({Action::NONE, StrId::STR_READER_TOOLS, true});
|
||||||
items.push_back({Action::DETECT_TIMEZONE, StrId::STR_DETECT_TIMEZONE});
|
items.push_back({Action::DETECT_TIMEZONE, StrId::STR_DETECT_TIMEZONE});
|
||||||
items.push_back({Action::SYNC_TIME, StrId::STR_SYNC_TIME});
|
items.push_back({Action::SYNC_TIME, StrId::STR_SYNC_TIME});
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<bool(int)> ClockSettingsActivity::buildSelectablePredicate() const {
|
std::function<bool(int)> ClockSettingsActivity::buildSelectablePredicate() const {
|
||||||
return makeSelectablePredicate(menuItems);
|
return [this](int index) {
|
||||||
|
return index >= 0 && index < static_cast<int>(menuItems.size()) && !menuItems[index].isSeparator;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClockSettingsActivity::onEnter() {
|
void ClockSettingsActivity::onEnter() {
|
||||||
@@ -123,7 +124,8 @@ void ClockSettingsActivity::render(RenderLock&&) {
|
|||||||
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2;
|
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2;
|
||||||
|
|
||||||
GUI.drawList(
|
GUI.drawList(
|
||||||
renderer, Rect{0, contentTop, pageWidth, contentHeight}, static_cast<int>(menuItems.size()), selectedIndex,
|
renderer, Rect{0, contentTop, pageWidth, contentHeight}, static_cast<int>(menuItems.size()),
|
||||||
|
selectedIndex,
|
||||||
[this](int index) {
|
[this](int index) {
|
||||||
const auto title = I18N.get(menuItems[index].labelId);
|
const auto title = I18N.get(menuItems[index].labelId);
|
||||||
return menuItems[index].isSeparator ? UITheme::makeSeparatorTitle(title) : title;
|
return menuItems[index].isSeparator ? UITheme::makeSeparatorTitle(title) : title;
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <I18n.h>
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <I18n.h>
|
||||||
|
|
||||||
#include "activities/Activity.h"
|
#include "activities/Activity.h"
|
||||||
#include "util/ButtonNavigator.h"
|
#include "util/ButtonNavigator.h"
|
||||||
|
|
||||||
class ClockSettingsActivity final : public Activity {
|
class ClockSettingsActivity final : public Activity {
|
||||||
enum class Action { USE_CLOCK, CLOCK_FORMAT, TIMEZONE, SYNC_TIME, DETECT_TIMEZONE, NONE };
|
enum class Action {
|
||||||
|
USE_CLOCK,
|
||||||
|
CLOCK_FORMAT,
|
||||||
|
TIMEZONE,
|
||||||
|
SYNC_TIME,
|
||||||
|
DETECT_TIMEZONE,
|
||||||
|
NONE
|
||||||
|
};
|
||||||
|
|
||||||
struct MenuItem {
|
struct MenuItem {
|
||||||
Action action;
|
Action action;
|
||||||
|
|||||||
@@ -22,11 +22,9 @@
|
|||||||
#include "activities/weather/WeatherSettingsActivity.h"
|
#include "activities/weather/WeatherSettingsActivity.h"
|
||||||
#include "components/UITheme.h"
|
#include "components/UITheme.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
#include "util/MenuItemHelpers.h"
|
|
||||||
|
|
||||||
const StrId SettingsActivity::categoryNames[categoryCount] = {StrId::STR_CAT_DISPLAY, StrId::STR_CAT_READER,
|
const StrId SettingsActivity::categoryNames[categoryCount] = {StrId::STR_CAT_DISPLAY, StrId::STR_CAT_READER,
|
||||||
StrId::STR_CAT_CONTROLS, StrId::STR_CAT_NETWORK,
|
StrId::STR_CAT_CONTROLS, StrId::STR_CAT_SYSTEM};
|
||||||
StrId::STR_CAT_SYSTEM};
|
|
||||||
|
|
||||||
void SettingsActivity::onEnter() {
|
void SettingsActivity::onEnter() {
|
||||||
Activity::onEnter();
|
Activity::onEnter();
|
||||||
@@ -35,9 +33,7 @@ void SettingsActivity::onEnter() {
|
|||||||
displaySettings.clear();
|
displaySettings.clear();
|
||||||
readerSettings.clear();
|
readerSettings.clear();
|
||||||
controlsSettings.clear();
|
controlsSettings.clear();
|
||||||
networkSettings.clear();
|
|
||||||
systemSettings.clear();
|
systemSettings.clear();
|
||||||
systemSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SETTINGS));
|
|
||||||
|
|
||||||
for (const auto& setting : getSettingsList()) {
|
for (const auto& setting : getSettingsList()) {
|
||||||
if (setting.category == StrId::STR_NONE_OPT) continue;
|
if (setting.category == StrId::STR_NONE_OPT) continue;
|
||||||
@@ -54,8 +50,6 @@ void SettingsActivity::onEnter() {
|
|||||||
controlsSettings.push_back(setting);
|
controlsSettings.push_back(setting);
|
||||||
} else if (setting.category == StrId::STR_CAT_SYSTEM) {
|
} else if (setting.category == StrId::STR_CAT_SYSTEM) {
|
||||||
systemSettings.push_back(setting);
|
systemSettings.push_back(setting);
|
||||||
} else if (setting.category == StrId::STR_CAT_NETWORK) {
|
|
||||||
networkSettings.push_back(setting);
|
|
||||||
}
|
}
|
||||||
// Web-only categories (KOReader Sync, OPDS Browser) are skipped for device UI
|
// Web-only categories (KOReader Sync, OPDS Browser) are skipped for device UI
|
||||||
}
|
}
|
||||||
@@ -63,26 +57,15 @@ void SettingsActivity::onEnter() {
|
|||||||
// Append device-only ACTION items
|
// Append device-only ACTION items
|
||||||
controlsSettings.insert(controlsSettings.begin(),
|
controlsSettings.insert(controlsSettings.begin(),
|
||||||
SettingInfo::Action(StrId::STR_REMAP_FRONT_BUTTONS, SettingAction::RemapFrontButtons));
|
SettingInfo::Action(StrId::STR_REMAP_FRONT_BUTTONS, SettingAction::RemapFrontButtons));
|
||||||
|
|
||||||
networkSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_NETWORK));
|
|
||||||
networkSettings.push_back(SettingInfo::Action(StrId::STR_WIFI_NETWORKS, SettingAction::Network));
|
|
||||||
networkSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SOURCES));
|
|
||||||
networkSettings.push_back(SettingInfo::Action(StrId::STR_OPDS_BROWSER, SettingAction::OPDSBrowser));
|
|
||||||
networkSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SYNC));
|
|
||||||
networkSettings.push_back(SettingInfo::Action(StrId::STR_KOREADER_SYNC, SettingAction::KOReaderSync));
|
|
||||||
|
|
||||||
// System settings with actions
|
|
||||||
systemSettings.push_back(SettingInfo::Action(StrId::STR_LANGUAGE, SettingAction::Language));
|
|
||||||
|
|
||||||
systemSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_TOOLS));
|
|
||||||
systemSettings.push_back(SettingInfo::Action(StrId::STR_CLOCK_SETTINGS, SettingAction::ClockSettings));
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_CLOCK_SETTINGS, SettingAction::ClockSettings));
|
||||||
systemSettings.push_back(SettingInfo::Action(StrId::STR_WEATHER_SETTINGS, SettingAction::Weather));
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_WIFI_NETWORKS, SettingAction::Network));
|
||||||
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_KOREADER_SYNC, SettingAction::KOReaderSync));
|
||||||
systemSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SYSTEM));
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_OPDS_BROWSER, SettingAction::OPDSBrowser));
|
||||||
systemSettings.push_back(SettingInfo::Action(StrId::STR_CLEAR_READING_CACHE, SettingAction::ClearCache));
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_CLEAR_READING_CACHE, SettingAction::ClearCache));
|
||||||
systemSettings.push_back(SettingInfo::Action(StrId::STR_CHECK_UPDATES, SettingAction::CheckForUpdates));
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_CHECK_UPDATES, SettingAction::CheckForUpdates));
|
||||||
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_LANGUAGE, SettingAction::Language));
|
||||||
systemSettings.push_back(SettingInfo::Action(StrId::STR_SYSTEM_INFO, SettingAction::SystemInfo));
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_SYSTEM_INFO, SettingAction::SystemInfo));
|
||||||
|
systemSettings.push_back(SettingInfo::Action(StrId::STR_WEATHER_SETTINGS, SettingAction::Weather));
|
||||||
readerSettings.push_back(SettingInfo::Action(StrId::STR_CUSTOMISE_STATUS_BAR, SettingAction::CustomiseStatusBar));
|
readerSettings.push_back(SettingInfo::Action(StrId::STR_CUSTOMISE_STATUS_BAR, SettingAction::CustomiseStatusBar));
|
||||||
|
|
||||||
// Reset selection to first category
|
// Reset selection to first category
|
||||||
@@ -92,16 +75,11 @@ void SettingsActivity::onEnter() {
|
|||||||
// Initialize with first category (Display)
|
// Initialize with first category (Display)
|
||||||
currentSettings = &displaySettings;
|
currentSettings = &displaySettings;
|
||||||
settingsCount = static_cast<int>(displaySettings.size());
|
settingsCount = static_cast<int>(displaySettings.size());
|
||||||
buttonNavigator.setSelectablePredicate(makeSelectablePredicate(*currentSettings, 1, true), settingsCount + 1);
|
|
||||||
|
|
||||||
// Trigger first update
|
// Trigger first update
|
||||||
requestUpdate();
|
requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<bool(int)> SettingsActivity::buildSelectablePredicate() const {
|
|
||||||
return makeSelectablePredicate(*currentSettings, 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsActivity::onExit() {
|
void SettingsActivity::onExit() {
|
||||||
Activity::onExit();
|
Activity::onExit();
|
||||||
|
|
||||||
@@ -137,12 +115,12 @@ void SettingsActivity::loop() {
|
|||||||
|
|
||||||
// Handle navigation
|
// Handle navigation
|
||||||
buttonNavigator.onNextRelease([this] {
|
buttonNavigator.onNextRelease([this] {
|
||||||
selectedSettingIndex = buttonNavigator.nextIndex(selectedSettingIndex);
|
selectedSettingIndex = ButtonNavigator::nextIndex(selectedSettingIndex, settingsCount + 1);
|
||||||
requestUpdate();
|
requestUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
buttonNavigator.onPreviousRelease([this] {
|
buttonNavigator.onPreviousRelease([this] {
|
||||||
selectedSettingIndex = buttonNavigator.previousIndex(selectedSettingIndex);
|
selectedSettingIndex = ButtonNavigator::previousIndex(selectedSettingIndex, settingsCount + 1);
|
||||||
requestUpdate();
|
requestUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -171,14 +149,10 @@ void SettingsActivity::loop() {
|
|||||||
currentSettings = &controlsSettings;
|
currentSettings = &controlsSettings;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
currentSettings = &networkSettings;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
currentSettings = &systemSettings;
|
currentSettings = &systemSettings;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
settingsCount = static_cast<int>(currentSettings->size());
|
settingsCount = static_cast<int>(currentSettings->size());
|
||||||
buttonNavigator.setSelectablePredicate(makeSelectablePredicate(*currentSettings, 1, true), settingsCount + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,9 +163,6 @@ void SettingsActivity::toggleCurrentSetting() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto& setting = (*currentSettings)[selectedSetting];
|
const auto& setting = (*currentSettings)[selectedSetting];
|
||||||
if (setting.isSeparator) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setting.type == SettingType::TOGGLE && setting.valuePtr != nullptr) {
|
if (setting.type == SettingType::TOGGLE && setting.valuePtr != nullptr) {
|
||||||
// Toggle the boolean value using the member pointer
|
// Toggle the boolean value using the member pointer
|
||||||
@@ -288,11 +259,7 @@ void SettingsActivity::render(RenderLock&&) {
|
|||||||
contentRect.height -
|
contentRect.height -
|
||||||
(metrics.topPadding + metrics.headerHeight + metrics.tabBarHeight + metrics.verticalSpacing * 2)},
|
(metrics.topPadding + metrics.headerHeight + metrics.tabBarHeight + metrics.verticalSpacing * 2)},
|
||||||
settingsCount, selectedSettingIndex - 1,
|
settingsCount, selectedSettingIndex - 1,
|
||||||
[&settings](int index) {
|
[&settings](int index) { return std::string(I18N.get(settings[index].nameId)); }, nullptr, nullptr,
|
||||||
const auto title = I18N.get(settings[index].nameId);
|
|
||||||
return settings[index].isSeparator ? UITheme::makeSeparatorTitle(title) : title;
|
|
||||||
},
|
|
||||||
nullptr, nullptr,
|
|
||||||
[&settings](int i) {
|
[&settings](int i) {
|
||||||
const auto& setting = settings[i];
|
const auto& setting = settings[i];
|
||||||
std::string valueText = "";
|
std::string valueText = "";
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ enum class SettingAction {
|
|||||||
|
|
||||||
struct SettingInfo {
|
struct SettingInfo {
|
||||||
StrId nameId;
|
StrId nameId;
|
||||||
bool isSeparator = false;
|
|
||||||
SettingType type;
|
SettingType type;
|
||||||
uint8_t CrossPointSettings::* valuePtr = nullptr;
|
uint8_t CrossPointSettings::* valuePtr = nullptr;
|
||||||
std::vector<StrId> enumValues;
|
std::vector<StrId> enumValues;
|
||||||
@@ -85,21 +84,11 @@ struct SettingInfo {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SettingInfo Action(StrId nameId, SettingAction action, bool isSeparator = false) {
|
static SettingInfo Action(StrId nameId, SettingAction action) {
|
||||||
SettingInfo s;
|
SettingInfo s;
|
||||||
s.nameId = nameId;
|
s.nameId = nameId;
|
||||||
s.type = SettingType::ACTION;
|
s.type = SettingType::ACTION;
|
||||||
s.action = action;
|
s.action = action;
|
||||||
s.isSeparator = isSeparator;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SettingInfo Separator(StrId nameId) {
|
|
||||||
SettingInfo s;
|
|
||||||
s.nameId = nameId;
|
|
||||||
s.type = SettingType::ACTION;
|
|
||||||
s.action = SettingAction::None;
|
|
||||||
s.isSeparator = true;
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,16 +155,14 @@ class SettingsActivity final : public Activity {
|
|||||||
std::vector<SettingInfo> displaySettings;
|
std::vector<SettingInfo> displaySettings;
|
||||||
std::vector<SettingInfo> readerSettings;
|
std::vector<SettingInfo> readerSettings;
|
||||||
std::vector<SettingInfo> controlsSettings;
|
std::vector<SettingInfo> controlsSettings;
|
||||||
std::vector<SettingInfo> networkSettings;
|
|
||||||
std::vector<SettingInfo> systemSettings;
|
std::vector<SettingInfo> systemSettings;
|
||||||
const std::vector<SettingInfo>* currentSettings = nullptr;
|
const std::vector<SettingInfo>* currentSettings = nullptr;
|
||||||
|
|
||||||
static constexpr int categoryCount = 5;
|
static constexpr int categoryCount = 4;
|
||||||
static const StrId categoryNames[categoryCount];
|
static const StrId categoryNames[categoryCount];
|
||||||
|
|
||||||
void enterCategory(int categoryIndex);
|
void enterCategory(int categoryIndex);
|
||||||
void toggleCurrentSetting();
|
void toggleCurrentSetting();
|
||||||
std::function<bool(int)> buildSelectablePredicate() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput)
|
explicit SettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput)
|
||||||
|
|||||||
@@ -98,11 +98,17 @@ Rect UITheme::getContentRect(const GfxRenderer& renderer, bool hasBottomHints, b
|
|||||||
return Rect{left, top, w - left - right, h - top - bottom};
|
return Rect{left, top, w - left - right, h - top - bottom};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UITheme::makeSeparatorTitle(const std::string& title) { return std::string("__") + title; }
|
std::string UITheme::makeSeparatorTitle(const std::string& title) {
|
||||||
|
return std::string("__") + title;
|
||||||
|
}
|
||||||
|
|
||||||
std::string UITheme::makeSeparatorTitle(StrId labelId) { return std::string("__") + I18N.get(labelId); }
|
std::string UITheme::makeSeparatorTitle(StrId labelId) {
|
||||||
|
return std::string("__") + I18N.get(labelId);
|
||||||
|
}
|
||||||
|
|
||||||
bool UITheme::isSeparatorTitle(const std::string& title) { return title.rfind("__", 0) == 0; }
|
bool UITheme::isSeparatorTitle(const std::string& title) {
|
||||||
|
return title.rfind("__", 0) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::string UITheme::stripSeparatorTitle(const std::string& title) {
|
std::string UITheme::stripSeparatorTitle(const std::string& title) {
|
||||||
return isSeparatorTitle(title) ? title.substr(2) : title;
|
return isSeparatorTitle(title) ? title.substr(2) : title;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <I18n.h>
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include <I18n.h>
|
||||||
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "components/themes/BaseTheme.h"
|
#include "components/themes/BaseTheme.h"
|
||||||
|
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ class ButtonNavigator final {
|
|||||||
[[nodiscard]] static int nextIndex(int currentIndex, const std::vector<bool>& selectable);
|
[[nodiscard]] static int nextIndex(int currentIndex, const std::vector<bool>& selectable);
|
||||||
[[nodiscard]] static int previousIndex(int currentIndex, const std::vector<bool>& selectable);
|
[[nodiscard]] static int previousIndex(int currentIndex, const std::vector<bool>& selectable);
|
||||||
[[nodiscard]] static int nextIndex(int currentIndex, int totalItems,
|
[[nodiscard]] static int nextIndex(int currentIndex, int totalItems,
|
||||||
const std::function<bool(int index)>& isSelectable);
|
const std::function<bool(int index)>& isSelectable);
|
||||||
[[nodiscard]] static int previousIndex(int currentIndex, int totalItems,
|
[[nodiscard]] static int previousIndex(int currentIndex, int totalItems,
|
||||||
const std::function<bool(int index)>& isSelectable);
|
const std::function<bool(int index)>& isSelectable);
|
||||||
|
|
||||||
[[nodiscard]] int nextIndex(int currentIndex) const;
|
[[nodiscard]] int nextIndex(int currentIndex) const;
|
||||||
[[nodiscard]] int previousIndex(int currentIndex) const;
|
[[nodiscard]] int previousIndex(int currentIndex) const;
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <I18n.h>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// Generic helper for constructing separator rows in menu item vectors.
|
|
||||||
// The item type must have an `action`, an `isSeparator`, and either a `labelId` or `nameId` member.
|
|
||||||
template <typename ItemType>
|
|
||||||
inline ItemType makeSeparatorMenuItem(StrId labelId) {
|
|
||||||
ItemType item{};
|
|
||||||
if constexpr (std::is_member_object_pointer_v<decltype(&ItemType::action)>) {
|
|
||||||
item.action = static_cast<decltype(item.action)>(0);
|
|
||||||
}
|
|
||||||
if constexpr (std::is_member_object_pointer_v<decltype(&ItemType::labelId)>) {
|
|
||||||
item.labelId = labelId;
|
|
||||||
} else if constexpr (std::is_member_object_pointer_v<decltype(&ItemType::nameId)>) {
|
|
||||||
item.nameId = labelId;
|
|
||||||
} else {
|
|
||||||
static_assert(sizeof(ItemType) == 0,
|
|
||||||
"makeSeparatorMenuItem requires ItemType with labelId or nameId member");
|
|
||||||
}
|
|
||||||
item.isSeparator = true;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic helper for creating a selectable predicate for menu lists.
|
|
||||||
// The item type must have an `isSeparator` member.
|
|
||||||
template <typename ItemType>
|
|
||||||
inline std::function<bool(int)> makeSelectablePredicate(const std::vector<ItemType>& items) {
|
|
||||||
return
|
|
||||||
[&items](int index) { return index >= 0 && index < static_cast<int>(items.size()) && !items[index].isSeparator; };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ItemType>
|
|
||||||
inline std::function<bool(int)> makeSelectablePredicate(const std::vector<ItemType>& items, int indexOffset,
|
|
||||||
bool firstIndexSelectable) {
|
|
||||||
return [&items, indexOffset, firstIndexSelectable](int index) {
|
|
||||||
if (firstIndexSelectable && index == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int itemIndex = index - indexOffset;
|
|
||||||
return itemIndex >= 0 && itemIndex < static_cast<int>(items.size()) && !items[itemIndex].isSeparator;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user