Merge pull request #167 from jpirnay/feat-btn-overview
feat: Add a button overview activity
This commit is contained in:
@@ -555,6 +555,11 @@ STR_CAPTIVE_PORTAL_HINT_2: "visit the URL below to authorize, then press OK."
|
|||||||
STR_CAPTIVE_PORTAL_DONE: "I'm authorized"
|
STR_CAPTIVE_PORTAL_DONE: "I'm authorized"
|
||||||
STR_MENU_BTN_ACTIONS: "Button Actions"
|
STR_MENU_BTN_ACTIONS: "Button Actions"
|
||||||
STR_MENU_BTN_PHYSICAL: "Physical Buttons"
|
STR_MENU_BTN_PHYSICAL: "Physical Buttons"
|
||||||
|
STR_BTN_ACTIONS_OVERVIEW: "Button Actions Overview"
|
||||||
|
STR_BTN_OVERVIEW_HEADER_BUTTON: "Button"
|
||||||
|
STR_BTN_OVERVIEW_HEADER_SHORT: "Short"
|
||||||
|
STR_BTN_OVERVIEW_HEADER_DOUBLE: "Double"
|
||||||
|
STR_BTN_OVERVIEW_HEADER_LONG: "Long"
|
||||||
STR_BTN_SHORT_PRESS: "Short Press"
|
STR_BTN_SHORT_PRESS: "Short Press"
|
||||||
STR_BTN_DOUBLE_PRESS: "Double Press"
|
STR_BTN_DOUBLE_PRESS: "Double Press"
|
||||||
STR_BTN_LONG_PRESS: "Long Press"
|
STR_BTN_LONG_PRESS: "Long Press"
|
||||||
@@ -566,16 +571,16 @@ STR_BTN_PAGE_BACK: "Page Back Button"
|
|||||||
STR_BTN_PAGE_FORWARD: "Page Forward Button"
|
STR_BTN_PAGE_FORWARD: "Page Forward Button"
|
||||||
STR_BTN_POWER: "Power Button"
|
STR_BTN_POWER: "Power Button"
|
||||||
STR_BTN_ACT_DEFAULT: "Default"
|
STR_BTN_ACT_DEFAULT: "Default"
|
||||||
STR_BTN_DEF_IGNORE: "Default (ignore)"
|
STR_BTN_DEF_IGNORE: "Ignore"
|
||||||
STR_BTN_DEF_EXIT_READER: "Default (exit reader)"
|
STR_BTN_DEF_EXIT_READER: "Exit Reader"
|
||||||
STR_BTN_DEF_GO_HOME: "Default (go home)"
|
STR_BTN_DEF_GO_HOME: "Go Home"
|
||||||
STR_BTN_DEF_READER_MENU: "Default (reader menu)"
|
STR_BTN_DEF_READER_MENU: "Reader Menu"
|
||||||
STR_BTN_DEF_KOREADER_SYNC: "Default (KOReader sync)"
|
STR_BTN_DEF_KOREADER_SYNC: "KOReader Sync"
|
||||||
STR_BTN_DEF_PREV_PAGE: "Default (previous page)"
|
STR_BTN_DEF_PREV_PAGE: "Previous Page"
|
||||||
STR_BTN_DEF_NEXT_PAGE: "Default (next page)"
|
STR_BTN_DEF_NEXT_PAGE: "Next Page"
|
||||||
STR_BTN_DEF_CHAPTER_BACK: "Default (chapter back)"
|
STR_BTN_DEF_CHAPTER_BACK: "Chapter Back"
|
||||||
STR_BTN_DEF_CHAPTER_FORWARD: "Default (chapter forward)"
|
STR_BTN_DEF_CHAPTER_FORWARD: "Chapter Forward"
|
||||||
STR_BTN_DEF_SLEEP: "Default (sleep)"
|
STR_BTN_DEF_SLEEP: "Sleep"
|
||||||
STR_BTN_ACT_PAGE_FORWARD: "Next Page"
|
STR_BTN_ACT_PAGE_FORWARD: "Next Page"
|
||||||
STR_BTN_ACT_PAGE_BACK: "Previous Page"
|
STR_BTN_ACT_PAGE_BACK: "Previous Page"
|
||||||
STR_BTN_ACT_PAGE_FORWARD_10: "Skip 10 Pages Forward"
|
STR_BTN_ACT_PAGE_FORWARD_10: "Skip 10 Pages Forward"
|
||||||
|
|||||||
@@ -372,7 +372,6 @@ STR_CAPTIVE_PORTAL_DETECTED: "Anmeldung erforderlich"
|
|||||||
STR_CAPTIVE_PORTAL_HINT_1: "Netzwerk erfordert Anmeldung. Authorisieren Sie dieses Gerät,"
|
STR_CAPTIVE_PORTAL_HINT_1: "Netzwerk erfordert Anmeldung. Authorisieren Sie dieses Gerät,"
|
||||||
STR_CAPTIVE_PORTAL_HINT_2: "indem Sie die URL auf einem anderen Gerät öffnen und fahren dann fort."
|
STR_CAPTIVE_PORTAL_HINT_2: "indem Sie die URL auf einem anderen Gerät öffnen und fahren dann fort."
|
||||||
STR_CAPTIVE_PORTAL_DONE: "Erledigt"
|
STR_CAPTIVE_PORTAL_DONE: "Erledigt"
|
||||||
|
|
||||||
STR_READER_TOOLS: "Werkzeuge"
|
STR_READER_TOOLS: "Werkzeuge"
|
||||||
STR_READER_NAVIGATION: "Navigation"
|
STR_READER_NAVIGATION: "Navigation"
|
||||||
STR_READER_APPEARANCE: "Darstellung"
|
STR_READER_APPEARANCE: "Darstellung"
|
||||||
|
|||||||
@@ -557,16 +557,16 @@ STR_BTN_PAGE_BACK: "Gumb stran Nazaj"
|
|||||||
STR_BTN_PAGE_FORWARD: "Gumb stran Naprej"
|
STR_BTN_PAGE_FORWARD: "Gumb stran Naprej"
|
||||||
STR_BTN_POWER: "Gumb za vklop"
|
STR_BTN_POWER: "Gumb za vklop"
|
||||||
STR_BTN_ACT_DEFAULT: "Privzeto"
|
STR_BTN_ACT_DEFAULT: "Privzeto"
|
||||||
STR_BTN_DEF_IGNORE: "Privzeto (prezri)"
|
STR_BTN_DEF_IGNORE: "prezri"
|
||||||
STR_BTN_DEF_EXIT_READER: "Privzeto (izhod iz bralnika)"
|
STR_BTN_DEF_EXIT_READER: "izhod iz bralnika"
|
||||||
STR_BTN_DEF_GO_HOME: "Privzeto (pojdi domov)"
|
STR_BTN_DEF_GO_HOME: "pojdi domov"
|
||||||
STR_BTN_DEF_READER_MENU: "Privzeto (meni bralnika)"
|
STR_BTN_DEF_READER_MENU: "meni bralnika"
|
||||||
STR_BTN_DEF_KOREADER_SYNC: "Privzeto (KOReader sinhronizacija)"
|
STR_BTN_DEF_KOREADER_SYNC: "KOReader sinhronizacija"
|
||||||
STR_BTN_DEF_PREV_PAGE: "Privzeto (prejšnja stran)"
|
STR_BTN_DEF_PREV_PAGE: "prejšnja stran"
|
||||||
STR_BTN_DEF_NEXT_PAGE: "Privzeto (naslednja stran)"
|
STR_BTN_DEF_NEXT_PAGE: "naslednja stran"
|
||||||
STR_BTN_DEF_CHAPTER_BACK: "Privzeto (poglavje nazaj)"
|
STR_BTN_DEF_CHAPTER_BACK: "poglavje nazaj"
|
||||||
STR_BTN_DEF_CHAPTER_FORWARD: "Privzeto (poglavje naprej)"
|
STR_BTN_DEF_CHAPTER_FORWARD: "poglavje naprej"
|
||||||
STR_BTN_DEF_SLEEP: "Privzeto (spanje)"
|
STR_BTN_DEF_SLEEP: "spanje"
|
||||||
STR_BTN_ACT_PAGE_FORWARD: "Naslednja stran"
|
STR_BTN_ACT_PAGE_FORWARD: "Naslednja stran"
|
||||||
STR_BTN_ACT_PAGE_BACK: "Prejšnja stran"
|
STR_BTN_ACT_PAGE_BACK: "Prejšnja stran"
|
||||||
STR_BTN_ACT_PAGE_FORWARD_10: "Preskoči 10 strani naprej"
|
STR_BTN_ACT_PAGE_FORWARD_10: "Preskoči 10 strani naprej"
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
#include "ButtonActionsOverviewActivity.h"
|
||||||
|
|
||||||
|
#include <GfxRenderer.h>
|
||||||
|
#include <I18n.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "MappedInputManager.h"
|
||||||
|
#include "SettingInfo.h"
|
||||||
|
#include "SettingsList.h"
|
||||||
|
#include "components/UITheme.h"
|
||||||
|
#include "fontIds.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct ButtonRow {
|
||||||
|
StrId submenu; // e.g. STR_BTN_BACK — identifies which logical button
|
||||||
|
StrId labelStrId; // e.g. STR_BTN_BACK — display label for the row
|
||||||
|
};
|
||||||
|
|
||||||
|
// Order matches the on-screen rendering order — power → confirm.
|
||||||
|
constexpr std::array<ButtonRow, 7> kButtonRows = {{
|
||||||
|
{StrId::STR_BTN_POWER, StrId::STR_BTN_POWER},
|
||||||
|
{StrId::STR_BTN_BACK, StrId::STR_BTN_BACK},
|
||||||
|
{StrId::STR_BTN_LEFT, StrId::STR_BTN_LEFT},
|
||||||
|
{StrId::STR_BTN_RIGHT, StrId::STR_BTN_RIGHT},
|
||||||
|
{StrId::STR_BTN_PAGE_BACK, StrId::STR_BTN_PAGE_BACK},
|
||||||
|
{StrId::STR_BTN_PAGE_FORWARD, StrId::STR_BTN_PAGE_FORWARD},
|
||||||
|
{StrId::STR_BTN_CONFIRM, StrId::STR_BTN_CONFIRM},
|
||||||
|
}};
|
||||||
|
|
||||||
|
// Find the SettingInfo for a given (button submenu, press kind) pair in the shared settings list.
|
||||||
|
const SettingInfo* findEntry(StrId submenu, StrId pressKind) {
|
||||||
|
for (const auto& s : getSettingsList()) {
|
||||||
|
if (s.submenu == submenu && s.nameId == pressKind && s.category == StrId::STR_CAT_CONTROLS) {
|
||||||
|
return &s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cellValue(StrId submenu, StrId pressKind) {
|
||||||
|
const SettingInfo* s = findEntry(submenu, pressKind);
|
||||||
|
if (!s) return {};
|
||||||
|
return s->getDisplayValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void ButtonActionsOverviewActivity::onEnter() {
|
||||||
|
Activity::onEnter();
|
||||||
|
|
||||||
|
// Force landscape so the four-column table has room for full action labels.
|
||||||
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
renderer.setOrientation(GfxRenderer::Orientation::LandscapeClockwise);
|
||||||
|
}
|
||||||
|
|
||||||
|
requestUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonActionsOverviewActivity::onExit() {
|
||||||
|
// Restore portrait — matches the rest of the settings UI.
|
||||||
|
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
||||||
|
|
||||||
|
Activity::onExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonActionsOverviewActivity::loop() {
|
||||||
|
if (mappedInput.wasPressed(MappedInputManager::Button::Back) ||
|
||||||
|
mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonActionsOverviewActivity::render(RenderLock&&) {
|
||||||
|
renderer.clearScreen();
|
||||||
|
|
||||||
|
const auto& metrics = UITheme::getInstance().getMetrics();
|
||||||
|
const Rect contentRect = UITheme::getContentRect(renderer, /*hasBottomHints=*/true, /*hasSideHints=*/false);
|
||||||
|
|
||||||
|
GUI.drawHeader(renderer,
|
||||||
|
Rect{contentRect.x, contentRect.y + metrics.topPadding, contentRect.width, metrics.headerHeight},
|
||||||
|
tr(STR_BTN_ACTIONS_OVERVIEW), CROSSPOINT_VERSION);
|
||||||
|
|
||||||
|
const int fontId = UI_10_FONT_ID;
|
||||||
|
const int lineH = renderer.getLineHeight(fontId);
|
||||||
|
const int rowStep = lineH + 4;
|
||||||
|
const int padX = metrics.verticalSpacing * 2;
|
||||||
|
|
||||||
|
// 4-column layout: button label, short, double, long.
|
||||||
|
// Button column gets a fixed share, the three action columns share the remainder evenly.
|
||||||
|
const int innerLeft = contentRect.x + padX;
|
||||||
|
const int innerWidth = contentRect.width - padX * 2;
|
||||||
|
const int colButtonWidth = innerWidth * 28 / 100;
|
||||||
|
const int colActionWidth = (innerWidth - colButtonWidth) / 3;
|
||||||
|
|
||||||
|
const int colX[4] = {
|
||||||
|
innerLeft,
|
||||||
|
innerLeft + colButtonWidth,
|
||||||
|
innerLeft + colButtonWidth + colActionWidth,
|
||||||
|
innerLeft + colButtonWidth + colActionWidth * 2,
|
||||||
|
};
|
||||||
|
const int colW[4] = {
|
||||||
|
colButtonWidth - 2,
|
||||||
|
colActionWidth - 2,
|
||||||
|
colActionWidth - 2,
|
||||||
|
innerLeft + innerWidth - colX[3] - 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
int y = contentRect.y + metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
|
||||||
|
|
||||||
|
// Header row (bold)
|
||||||
|
const char* headers[4] = {
|
||||||
|
tr(STR_BTN_OVERVIEW_HEADER_BUTTON),
|
||||||
|
tr(STR_BTN_OVERVIEW_HEADER_SHORT),
|
||||||
|
tr(STR_BTN_OVERVIEW_HEADER_DOUBLE),
|
||||||
|
tr(STR_BTN_OVERVIEW_HEADER_LONG),
|
||||||
|
};
|
||||||
|
for (int c = 0; c < 4; c++) {
|
||||||
|
const std::string clipped = renderer.truncatedText(fontId, headers[c], colW[c], EpdFontFamily::BOLD);
|
||||||
|
renderer.drawText(fontId, colX[c], y, clipped.c_str(), true, EpdFontFamily::BOLD);
|
||||||
|
}
|
||||||
|
y += lineH + 2;
|
||||||
|
|
||||||
|
// Underline below header
|
||||||
|
const int underlineX[4] = {innerLeft, innerLeft + innerWidth, innerLeft + innerWidth, innerLeft};
|
||||||
|
const int underlineY[4] = {y, y, y + 1, y + 1};
|
||||||
|
renderer.fillPolygon(underlineX, underlineY, 4, true);
|
||||||
|
y += 4;
|
||||||
|
|
||||||
|
// Data rows
|
||||||
|
for (const auto& row : kButtonRows) {
|
||||||
|
const std::string label = I18N.get(row.labelStrId);
|
||||||
|
const std::string clippedLabel = renderer.truncatedText(fontId, label.c_str(), colW[0], EpdFontFamily::BOLD);
|
||||||
|
renderer.drawText(fontId, colX[0], y, clippedLabel.c_str(), true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
|
const std::string vShort = cellValue(row.submenu, StrId::STR_BTN_SHORT_PRESS);
|
||||||
|
const std::string vDouble = cellValue(row.submenu, StrId::STR_BTN_DOUBLE_PRESS);
|
||||||
|
const std::string vLong = cellValue(row.submenu, StrId::STR_BTN_LONG_PRESS);
|
||||||
|
|
||||||
|
renderer.drawText(fontId, colX[1], y, renderer.truncatedText(fontId, vShort.c_str(), colW[1]).c_str());
|
||||||
|
renderer.drawText(fontId, colX[2], y, renderer.truncatedText(fontId, vDouble.c_str(), colW[2]).c_str());
|
||||||
|
renderer.drawText(fontId, colX[3], y, renderer.truncatedText(fontId, vLong.c_str(), colW[3]).c_str());
|
||||||
|
|
||||||
|
y += rowStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", "");
|
||||||
|
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
|
|
||||||
|
renderer.displayBuffer();
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "activities/Activity.h"
|
||||||
|
|
||||||
|
class ButtonActionsOverviewActivity final : public Activity {
|
||||||
|
public:
|
||||||
|
explicit ButtonActionsOverviewActivity(GfxRenderer& renderer, MappedInputManager& mappedInput)
|
||||||
|
: Activity("ButtonActionsOverview", renderer, mappedInput) {}
|
||||||
|
|
||||||
|
void onEnter() override;
|
||||||
|
void onExit() override;
|
||||||
|
void loop() override;
|
||||||
|
void render(RenderLock&&) override;
|
||||||
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "SettingActionDispatch.h"
|
#include "SettingActionDispatch.h"
|
||||||
|
|
||||||
|
#include "ButtonActionsOverviewActivity.h"
|
||||||
#include "ButtonRemapActivity.h"
|
#include "ButtonRemapActivity.h"
|
||||||
#include "ClearCacheActivity.h"
|
#include "ClearCacheActivity.h"
|
||||||
#include "ClockSettingsActivity.h"
|
#include "ClockSettingsActivity.h"
|
||||||
@@ -20,6 +21,8 @@ std::unique_ptr<Activity> createActivityForAction(SettingAction action, GfxRende
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case SettingAction::RemapFrontButtons:
|
case SettingAction::RemapFrontButtons:
|
||||||
return std::make_unique<ButtonRemapActivity>(renderer, mappedInput);
|
return std::make_unique<ButtonRemapActivity>(renderer, mappedInput);
|
||||||
|
case SettingAction::ButtonActionsOverview:
|
||||||
|
return std::make_unique<ButtonActionsOverviewActivity>(renderer, mappedInput);
|
||||||
case SettingAction::CustomiseStatusBar:
|
case SettingAction::CustomiseStatusBar:
|
||||||
return std::make_unique<StatusBarSettingsActivity>(renderer, mappedInput);
|
return std::make_unique<StatusBarSettingsActivity>(renderer, mappedInput);
|
||||||
case SettingAction::DownloadFonts:
|
case SettingAction::DownloadFonts:
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ enum class SettingType { TOGGLE, ENUM, ACTION, VALUE, STRING };
|
|||||||
enum class SettingAction {
|
enum class SettingAction {
|
||||||
None,
|
None,
|
||||||
RemapFrontButtons,
|
RemapFrontButtons,
|
||||||
|
ButtonActionsOverview,
|
||||||
CustomiseStatusBar,
|
CustomiseStatusBar,
|
||||||
DownloadFonts,
|
DownloadFonts,
|
||||||
ClockSettings,
|
ClockSettings,
|
||||||
|
|||||||
@@ -119,6 +119,12 @@ void SettingsActivity::onEnter() {
|
|||||||
SettingInfo::Action(StrId::STR_REMAP_FRONT_BUTTONS, SettingAction::RemapFrontButtons));
|
SettingInfo::Action(StrId::STR_REMAP_FRONT_BUTTONS, SettingAction::RemapFrontButtons));
|
||||||
controlsSettings.insert(controlsSettings.begin(), SettingInfo::Separator(StrId::STR_MENU_BTN_PHYSICAL));
|
controlsSettings.insert(controlsSettings.begin(), SettingInfo::Separator(StrId::STR_MENU_BTN_PHYSICAL));
|
||||||
|
|
||||||
|
// Button Actions overview lives at the end of the Button Actions section (same subcategory as
|
||||||
|
// the per-button submenus, so no new separator is inserted).
|
||||||
|
addToMoved(controlsSettings, lastControlsSub,
|
||||||
|
std::move(SettingInfo::Action(StrId::STR_BTN_ACTIONS_OVERVIEW, SettingAction::ButtonActionsOverview)
|
||||||
|
.withSubcategory(StrId::STR_MENU_BTN_ACTIONS)));
|
||||||
|
|
||||||
addToMoved(readerSettings, lastReaderSub,
|
addToMoved(readerSettings, lastReaderSub,
|
||||||
SettingInfo::Action(StrId::STR_CUSTOMISE_STATUS_BAR, SettingAction::CustomiseStatusBar));
|
SettingInfo::Action(StrId::STR_CUSTOMISE_STATUS_BAR, SettingAction::CustomiseStatusBar));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user