mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 14:47:37 +03:00
Compare commits
2 Commits
cc483dc281
...
3ea0878189
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ea0878189 | ||
|
|
2b33d92a01 |
@ -233,7 +233,7 @@ void MyLibraryActivity::render() const {
|
||||
UITheme::drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, folderName);
|
||||
|
||||
UITheme::drawTabBar(renderer, Rect{0, metrics.topPadding + metrics.headerHeight, pageWidth, metrics.tabBarHeight},
|
||||
{{"Recent", currentTab == Tab::Recent}, {"Files", currentTab == Tab::Files}});
|
||||
{{"Recent", currentTab == Tab::Recent}, {"Files", currentTab == Tab::Files}}, false);
|
||||
|
||||
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.tabBarHeight + metrics.verticalSpacing;
|
||||
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2;
|
||||
|
||||
@ -110,12 +110,19 @@ void SettingsActivity::loop() {
|
||||
subActivity->loop();
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasChangedCategory = false;
|
||||
|
||||
// Handle actions with early return
|
||||
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
|
||||
toggleCurrentSetting();
|
||||
updateRequired = true;
|
||||
return;
|
||||
if (selectedSettingIndex == 0) {
|
||||
selectedCategoryIndex = (selectedCategoryIndex < categoryCount - 1) ? (selectedCategoryIndex + 1) : 0;
|
||||
hasChangedCategory = true;
|
||||
updateRequired = true;
|
||||
} else {
|
||||
toggleCurrentSetting();
|
||||
updateRequired = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
|
||||
@ -124,14 +131,13 @@ void SettingsActivity::loop() {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasChangedCategory = false;
|
||||
|
||||
// Handle navigation
|
||||
if (mappedInput.wasPressed(MappedInputManager::Button::Left)) {
|
||||
selectedSettingIndex = (selectedSettingIndex > 0) ? (selectedSettingIndex - 1) : (settingsCount - 1);
|
||||
selectedSettingIndex = (selectedSettingIndex > 0) ? (selectedSettingIndex - 1) : (settingsCount);
|
||||
updateRequired = true;
|
||||
} else if (mappedInput.wasPressed(MappedInputManager::Button::Right)) {
|
||||
selectedSettingIndex = (selectedSettingIndex < settingsCount - 1) ? (selectedSettingIndex + 1) : 0;
|
||||
selectedSettingIndex = (selectedSettingIndex < settingsCount) ? (selectedSettingIndex + 1) : 0;
|
||||
updateRequired = true;
|
||||
} else if (mappedInput.wasPressed(MappedInputManager::Button::Up)) {
|
||||
hasChangedCategory = true;
|
||||
@ -144,7 +150,7 @@ void SettingsActivity::loop() {
|
||||
}
|
||||
|
||||
if (hasChangedCategory) {
|
||||
selectedSettingIndex = 0;
|
||||
selectedSettingIndex = (selectedSettingIndex == 0) ? 0 : 1;
|
||||
switch (selectedCategoryIndex) {
|
||||
case 0: // Display
|
||||
settingsList = displaySettings;
|
||||
@ -167,11 +173,12 @@ void SettingsActivity::loop() {
|
||||
}
|
||||
|
||||
void SettingsActivity::toggleCurrentSetting() {
|
||||
if (selectedSettingIndex < 0 || selectedSettingIndex >= settingsCount) {
|
||||
int selectedSetting = selectedSettingIndex - 1;
|
||||
if (selectedSetting < 0 || selectedSetting >= settingsCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& setting = settingsList[selectedSettingIndex];
|
||||
const auto& setting = settingsList[selectedSetting];
|
||||
|
||||
if (setting.type == SettingType::TOGGLE && setting.valuePtr != nullptr) {
|
||||
// Toggle the boolean value using the member pointer
|
||||
@ -256,14 +263,14 @@ void SettingsActivity::render() const {
|
||||
tabs.push_back({categoryNames[i], selectedCategoryIndex == i});
|
||||
}
|
||||
UITheme::drawTabBar(renderer, Rect{0, metrics.topPadding + metrics.headerHeight, pageWidth, metrics.tabBarHeight},
|
||||
tabs);
|
||||
tabs, selectedSettingIndex == 0);
|
||||
|
||||
UITheme::drawList(
|
||||
renderer,
|
||||
Rect{0, metrics.topPadding + metrics.headerHeight + metrics.tabBarHeight + metrics.verticalSpacing, pageWidth,
|
||||
pageHeight - (metrics.topPadding + metrics.headerHeight + metrics.tabBarHeight + metrics.buttonHintsHeight +
|
||||
metrics.verticalSpacing * 2)},
|
||||
settingsCount, selectedSettingIndex, [this](int index) { return std::string(settingsList[index].name); }, false,
|
||||
settingsCount, selectedSettingIndex - 1, [this](int index) { return std::string(settingsList[index].name); }, false,
|
||||
nullptr, true,
|
||||
[this](int i) {
|
||||
const auto& setting = settingsList[i];
|
||||
@ -286,7 +293,7 @@ void SettingsActivity::render() const {
|
||||
metrics.versionTextY, CROSSPOINT_VERSION);
|
||||
|
||||
// Draw help text
|
||||
const auto labels = mappedInput.mapLabels("« Back", "Select", "Up", "Down");
|
||||
const auto labels = mappedInput.mapLabels("« Back", selectedSettingIndex == 0 ? "Tab >" : "Toggle", "Up", "Down");
|
||||
UITheme::drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
UITheme::drawSideButtonHints(renderer, "^", "v");
|
||||
|
||||
|
||||
@ -89,9 +89,9 @@ void UITheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* tit
|
||||
}
|
||||
}
|
||||
|
||||
void UITheme::drawTabBar(const GfxRenderer& renderer, const Rect rect, const std::vector<TabInfo>& tabs) {
|
||||
void UITheme::drawTabBar(const GfxRenderer& renderer, const Rect rect, const std::vector<TabInfo>& tabs, bool selected) {
|
||||
if (currentTheme != nullptr) {
|
||||
currentTheme->drawTabBar(renderer, rect, tabs);
|
||||
currentTheme->drawTabBar(renderer, rect, tabs, selected);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ class UITheme {
|
||||
const std::function<std::string(int index)>& rowIcon, bool hasValue,
|
||||
const std::function<std::string(int index)>& rowValue);
|
||||
static void drawHeader(const GfxRenderer& renderer, Rect rect, const char* title);
|
||||
static void drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs);
|
||||
static void drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs, bool selected);
|
||||
static void drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std::vector<RecentBookWithCover>& recentBooks,
|
||||
const int selectorIndex, bool& coverRendered, bool& coverBufferStored,
|
||||
bool& bufferRestored, std::function<bool()> storeCoverBuffer);
|
||||
|
||||
@ -191,7 +191,9 @@ void BaseTheme::drawList(const GfxRenderer& renderer, Rect rect, int itemCount,
|
||||
|
||||
// Draw selection
|
||||
int contentWidth = rect.width - BaseMetrics::values.sideButtonHintsWidth - 5;
|
||||
renderer.fillRect(0, rect.y + selectedIndex % pageItems * rowHeight - 2, contentWidth, rowHeight);
|
||||
if (selectedIndex >= 0) {
|
||||
renderer.fillRect(0, rect.y + selectedIndex % pageItems * rowHeight - 2, contentWidth, rowHeight);
|
||||
}
|
||||
// Draw all items
|
||||
const auto pageStartIndex = selectedIndex / pageItems * pageItems;
|
||||
for (int i = pageStartIndex; i < itemCount && i < pageStartIndex + pageItems; i++) {
|
||||
@ -232,7 +234,7 @@ void BaseTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t
|
||||
}
|
||||
}
|
||||
|
||||
void BaseTheme::drawTabBar(const GfxRenderer& renderer, const Rect rect, const std::vector<TabInfo>& tabs) {
|
||||
void BaseTheme::drawTabBar(const GfxRenderer& renderer, const Rect rect, const std::vector<TabInfo>& tabs, bool selected) {
|
||||
constexpr int underlineHeight = 2; // Height of selection underline
|
||||
constexpr int underlineGap = 4; // Gap between text and underline
|
||||
|
||||
@ -244,15 +246,19 @@ void BaseTheme::drawTabBar(const GfxRenderer& renderer, const Rect rect, const s
|
||||
const int textWidth =
|
||||
renderer.getTextWidth(UI_12_FONT_ID, tab.label, tab.selected ? EpdFontFamily::BOLD : EpdFontFamily::REGULAR);
|
||||
|
||||
// Draw tab label
|
||||
renderer.drawText(UI_12_FONT_ID, currentX, rect.y, tab.label, true,
|
||||
tab.selected ? EpdFontFamily::BOLD : EpdFontFamily::REGULAR);
|
||||
|
||||
// Draw underline for selected tab
|
||||
if (tab.selected) {
|
||||
renderer.fillRect(currentX, rect.y + lineHeight + underlineGap, textWidth, underlineHeight);
|
||||
if (selected) {
|
||||
renderer.fillRect(currentX - 3, rect.y, textWidth + 6, lineHeight + underlineGap);
|
||||
} else {
|
||||
renderer.fillRect(currentX, rect.y + lineHeight + underlineGap, textWidth, underlineHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw tab label
|
||||
renderer.drawText(UI_12_FONT_ID, currentX, rect.y, tab.label, !(tab.selected && selected),
|
||||
tab.selected ? EpdFontFamily::BOLD : EpdFontFamily::REGULAR);
|
||||
|
||||
currentX += textWidth + BaseMetrics::values.tabSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ class BaseTheme {
|
||||
const std::function<std::string(int index)>& rowValue);
|
||||
|
||||
virtual void drawHeader(const GfxRenderer& renderer, Rect rect, const char* title);
|
||||
virtual void drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs);
|
||||
virtual void drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs, bool selected);
|
||||
virtual void drawRecentBookCover(GfxRenderer& renderer, Rect rect,
|
||||
const std::vector<RecentBookWithCover>& recentBooks, const int selectorIndex,
|
||||
bool& coverRendered, bool& coverBufferStored, bool& bufferRestored,
|
||||
|
||||
@ -78,21 +78,30 @@ void LyraTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t
|
||||
}
|
||||
}
|
||||
|
||||
void LyraTheme::drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs) {
|
||||
void LyraTheme::drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs, bool selected) {
|
||||
int currentX = rect.x + LyraMetrics::values.contentSidePadding;
|
||||
|
||||
if (selected) {
|
||||
renderer.fillRectDither(rect.x, rect.y, rect.width, rect.height, COLOR_LIGHT_GRAY);
|
||||
}
|
||||
|
||||
for (const auto& tab : tabs) {
|
||||
const int textWidth = renderer.getTextWidth(UI_10_FONT_ID, tab.label, EpdFontFamily::REGULAR);
|
||||
|
||||
// Draw tab label
|
||||
renderer.drawText(UI_10_FONT_ID, currentX, rect.y + 6, tab.label, true, EpdFontFamily::REGULAR);
|
||||
|
||||
// Draw underline for selected tab
|
||||
if (tab.selected) {
|
||||
renderer.drawLine(currentX, rect.y + rect.height - 2, currentX + textWidth, rect.y + rect.height - 2, true);
|
||||
if (selected) {
|
||||
renderer.fillRoundedRect(currentX, rect.y + 1, textWidth + 2 * hPaddingInSelection, rect.height - 4,
|
||||
cornerRadius, COLOR_BLACK);
|
||||
} else {
|
||||
renderer.fillRectDither(currentX, rect.y, textWidth + 2 * hPaddingInSelection, rect.height - 3, COLOR_LIGHT_GRAY);
|
||||
renderer.drawLine(currentX, rect.y + rect.height - 3, currentX + textWidth + 2 * hPaddingInSelection, rect.y + rect.height - 3, 2, true);
|
||||
}
|
||||
}
|
||||
|
||||
currentX += textWidth + LyraMetrics::values.tabSpacing;
|
||||
renderer.drawText(UI_10_FONT_ID, currentX + hPaddingInSelection, rect.y + 6, tab.label, !(tab.selected && selected), EpdFontFamily::REGULAR);
|
||||
|
||||
|
||||
currentX += textWidth + LyraMetrics::values.tabSpacing + 2 * hPaddingInSelection;
|
||||
}
|
||||
|
||||
renderer.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1, true);
|
||||
@ -123,9 +132,11 @@ void LyraTheme::drawList(const GfxRenderer& renderer, Rect rect, int itemCount,
|
||||
int contentWidth =
|
||||
rect.width -
|
||||
(totalPages > 1 ? (LyraMetrics::values.scrollBarWidth + LyraMetrics::values.scrollBarRightOffset) : 1);
|
||||
renderer.fillRoundedRect(LyraMetrics::values.contentSidePadding, rect.y + selectedIndex % pageItems * rowHeight,
|
||||
if (selectedIndex >= 0) {
|
||||
renderer.fillRoundedRect(LyraMetrics::values.contentSidePadding, rect.y + selectedIndex % pageItems * rowHeight,
|
||||
contentWidth - LyraMetrics::values.contentSidePadding * 2, rowHeight, cornerRadius,
|
||||
COLOR_LIGHT_GRAY);
|
||||
}
|
||||
|
||||
// Draw all items
|
||||
const auto pageStartIndex = selectedIndex / pageItems * pageItems;
|
||||
@ -169,22 +180,26 @@ void LyraTheme::drawButtonHints(const GfxRenderer& renderer, const char* btn1, c
|
||||
|
||||
const int pageHeight = renderer.getScreenHeight();
|
||||
constexpr int buttonWidth = 80;
|
||||
constexpr int smallButtonHeight = 15;
|
||||
constexpr int buttonHeight = LyraMetrics::values.buttonHintsHeight;
|
||||
constexpr int buttonY = LyraMetrics::values.buttonHintsHeight; // Distance from bottom
|
||||
constexpr int textYOffset = 7; // Distance from top of button to text baseline
|
||||
constexpr int buttonPositions[] = {68, 156, 244, 332};
|
||||
constexpr int buttonPositions[] = {58, 146, 254, 342};
|
||||
const char* labels[] = {btn1, btn2, btn3, btn4};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// Only draw if the label is non-empty
|
||||
const int x = buttonPositions[i];
|
||||
renderer.fillRect(x, pageHeight - buttonY, buttonWidth, buttonHeight, false);
|
||||
if (labels[i] != nullptr && labels[i][0] != '\0') {
|
||||
const int x = buttonPositions[i];
|
||||
renderer.fillRect(x, pageHeight - buttonY, buttonWidth, buttonHeight, false);
|
||||
renderer.drawRoundedRect(x, pageHeight - buttonY, buttonWidth, buttonHeight, 1, cornerRadius, true, true, false,
|
||||
false, true);
|
||||
const int textWidth = renderer.getTextWidth(SMALL_FONT_ID, labels[i]);
|
||||
const int textX = x + (buttonWidth - 1 - textWidth) / 2;
|
||||
renderer.drawText(SMALL_FONT_ID, textX, pageHeight - buttonY + textYOffset, labels[i]);
|
||||
} else {
|
||||
renderer.drawRoundedRect(x, pageHeight - smallButtonHeight, buttonWidth, smallButtonHeight, 1, cornerRadius, true, true, false,
|
||||
false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,7 +209,7 @@ void LyraTheme::drawButtonHints(const GfxRenderer& renderer, const char* btn1, c
|
||||
void LyraTheme::drawSideButtonHints(const GfxRenderer& renderer, const char* topBtn, const char* bottomBtn) {
|
||||
const int screenWidth = renderer.getScreenWidth();
|
||||
constexpr int buttonWidth = LyraMetrics::values.sideButtonHintsWidth; // Width on screen (height when rotated)
|
||||
constexpr int buttonHeight = 80; // Height on screen (width when rotated)
|
||||
constexpr int buttonHeight = 78; // Height on screen (width when rotated)
|
||||
// Position for the button group - buttons share a border so they're adjacent
|
||||
|
||||
const char* labels[] = {topBtn, bottomBtn};
|
||||
|
||||
@ -16,7 +16,7 @@ constexpr ThemeMetrics values = {.batteryWidth = 16,
|
||||
.listRowHeight = 40,
|
||||
.menuRowHeight = 64,
|
||||
.menuSpacing = 8,
|
||||
.tabSpacing = 20,
|
||||
.tabSpacing = 8,
|
||||
.tabBarHeight = 40,
|
||||
.scrollBarWidth = 4,
|
||||
.scrollBarRightOffset = 5,
|
||||
@ -36,7 +36,7 @@ class LyraTheme : public BaseTheme {
|
||||
// void drawProgressBar(const GfxRenderer& renderer, Rect rect, size_t current, size_t total) override;
|
||||
void drawBattery(const GfxRenderer& renderer, Rect rect, bool showPercentage = true) override;
|
||||
void drawHeader(const GfxRenderer& renderer, Rect rect, const char* title) override;
|
||||
void drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs) override;
|
||||
void drawTabBar(const GfxRenderer& renderer, Rect rect, const std::vector<TabInfo>& tabs, bool selected) override;
|
||||
void drawList(const GfxRenderer& renderer, Rect rect, int itemCount, int selectedIndex,
|
||||
const std::function<std::string(int index)>& rowTitle, bool hasIcon,
|
||||
const std::function<std::string(int index)>& rowIcon, bool hasValue,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user