adds bezel compensation settings
This commit is contained in:
parent
c2a966a6ea
commit
80c9e7a1d6
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
1) Ability to clear all books and clear individual books from Recents.
|
1) Ability to clear all books and clear individual books from Recents.
|
||||||
2) Bookmarks
|
2) Bookmarks
|
||||||
|
2a) crosspoint logo on firmware flashing screen
|
||||||
3) ability to add/remove books from lists on device.
|
3) ability to add/remove books from lists on device.
|
||||||
4) quick menu
|
4) quick menu
|
||||||
5) hide "system folders" from files view
|
5) hide "system folders" from files view
|
||||||
|
|||||||
@ -621,15 +621,20 @@ void GfxRenderer::drawButtonHints(const int fontId, const char* btn1, const char
|
|||||||
const int pageHeight = getScreenHeight();
|
const int pageHeight = getScreenHeight();
|
||||||
constexpr int buttonWidth = 106;
|
constexpr int buttonWidth = 106;
|
||||||
constexpr int buttonHeight = 40;
|
constexpr int buttonHeight = 40;
|
||||||
constexpr int buttonY = 40; // Distance from bottom
|
constexpr int baseButtonY = 40; // Base distance from bottom
|
||||||
constexpr int textYOffset = 7; // Distance from top of button to text baseline
|
constexpr int textYOffset = 7; // Distance from top of button to text baseline
|
||||||
constexpr int buttonPositions[] = {25, 130, 245, 350};
|
constexpr int baseButtonPositions[] = {25, 130, 245, 350};
|
||||||
const char* labels[] = {btn1, btn2, btn3, btn4};
|
const char* labels[] = {btn1, btn2, btn3, btn4};
|
||||||
|
|
||||||
|
// Apply bezel compensation (in portrait mode, bottom bezel affects Y position)
|
||||||
|
const int bezelBottom = getBezelOffsetBottom();
|
||||||
|
const int bezelLeft = getBezelOffsetLeft();
|
||||||
|
const int buttonY = baseButtonY + bezelBottom;
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
// Only draw if the label is non-empty
|
// Only draw if the label is non-empty
|
||||||
if (labels[i] != nullptr && labels[i][0] != '\0') {
|
if (labels[i] != nullptr && labels[i][0] != '\0') {
|
||||||
const int x = buttonPositions[i];
|
const int x = baseButtonPositions[i] + bezelLeft;
|
||||||
fillRect(x, pageHeight - buttonY, buttonWidth, buttonHeight, false);
|
fillRect(x, pageHeight - buttonY, buttonWidth, buttonHeight, false);
|
||||||
drawRect(x, pageHeight - buttonY, buttonWidth, buttonHeight);
|
drawRect(x, pageHeight - buttonY, buttonWidth, buttonHeight);
|
||||||
const int textWidth = getTextWidth(fontId, labels[i]);
|
const int textWidth = getTextWidth(fontId, labels[i]);
|
||||||
@ -648,9 +653,14 @@ void GfxRenderer::drawSideButtonHints(const int fontId, const char* topBtn, cons
|
|||||||
const int screenWidth = getScreenWidth();
|
const int screenWidth = getScreenWidth();
|
||||||
constexpr int buttonWidth = 40; // Width on screen (height when rotated)
|
constexpr int buttonWidth = 40; // Width on screen (height when rotated)
|
||||||
constexpr int buttonHeight = 80; // Height on screen (width when rotated)
|
constexpr int buttonHeight = 80; // Height on screen (width when rotated)
|
||||||
constexpr int buttonX = 5; // Distance from right edge
|
constexpr int baseButtonX = 5; // Base distance from right edge
|
||||||
// Position for the button group - buttons share a border so they're adjacent
|
// Position for the button group - buttons share a border so they're adjacent
|
||||||
constexpr int topButtonY = 345; // Top button position
|
constexpr int baseTopButtonY = 345; // Base top button position
|
||||||
|
|
||||||
|
// Apply bezel compensation (in portrait mode)
|
||||||
|
const int bezelRight = getBezelOffsetRight();
|
||||||
|
const int buttonX = baseButtonX + bezelRight;
|
||||||
|
const int topButtonY = baseTopButtonY; // Y position doesn't need adjustment for side buttons
|
||||||
|
|
||||||
const char* labels[] = {topBtn, bottomBtn};
|
const char* labels[] = {topBtn, bottomBtn};
|
||||||
|
|
||||||
@ -979,31 +989,107 @@ void GfxRenderer::renderChar(const EpdFontFamily& fontFamily, const uint32_t cp,
|
|||||||
*x += glyph->advanceX;
|
*x += glyph->advanceX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to map physical bezel edge to logical edge based on orientation
|
||||||
|
// bezelEdge: 0=physical bottom, 1=physical top, 2=physical left, 3=physical right (in portrait)
|
||||||
|
// Returns: 0=logical bottom, 1=logical top, 2=logical left, 3=logical right
|
||||||
|
int mapPhysicalToLogicalEdge(int bezelEdge, GfxRenderer::Orientation orientation) {
|
||||||
|
switch (orientation) {
|
||||||
|
case GfxRenderer::Portrait:
|
||||||
|
return bezelEdge;
|
||||||
|
case GfxRenderer::LandscapeClockwise:
|
||||||
|
switch (bezelEdge) {
|
||||||
|
case 0: return 2; // Physical bottom -> logical left
|
||||||
|
case 1: return 3; // Physical top -> logical right
|
||||||
|
case 2: return 1; // Physical left -> logical top
|
||||||
|
case 3: return 0; // Physical right -> logical bottom
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GfxRenderer::PortraitInverted:
|
||||||
|
switch (bezelEdge) {
|
||||||
|
case 0: return 1; // Physical bottom -> logical top
|
||||||
|
case 1: return 0; // Physical top -> logical bottom
|
||||||
|
case 2: return 3; // Physical left -> logical right
|
||||||
|
case 3: return 2; // Physical right -> logical left
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GfxRenderer::LandscapeCounterClockwise:
|
||||||
|
switch (bezelEdge) {
|
||||||
|
case 0: return 3; // Physical bottom -> logical right
|
||||||
|
case 1: return 2; // Physical top -> logical left
|
||||||
|
case 2: return 0; // Physical left -> logical bottom
|
||||||
|
case 3: return 1; // Physical right -> logical top
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return bezelEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getViewableMarginTop() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return BASE_VIEWABLE_MARGIN_TOP + (logicalEdge == 1 ? bezelCompensation : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getViewableMarginRight() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return BASE_VIEWABLE_MARGIN_RIGHT + (logicalEdge == 3 ? bezelCompensation : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getViewableMarginBottom() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return BASE_VIEWABLE_MARGIN_BOTTOM + (logicalEdge == 0 ? bezelCompensation : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getViewableMarginLeft() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return BASE_VIEWABLE_MARGIN_LEFT + (logicalEdge == 2 ? bezelCompensation : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getBezelOffsetTop() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return (logicalEdge == 1) ? bezelCompensation : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getBezelOffsetRight() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return (logicalEdge == 3) ? bezelCompensation : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getBezelOffsetBottom() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return (logicalEdge == 0) ? bezelCompensation : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GfxRenderer::getBezelOffsetLeft() const {
|
||||||
|
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||||
|
return (logicalEdge == 2) ? bezelCompensation : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void GfxRenderer::getOrientedViewableTRBL(int* outTop, int* outRight, int* outBottom, int* outLeft) const {
|
void GfxRenderer::getOrientedViewableTRBL(int* outTop, int* outRight, int* outBottom, int* outLeft) const {
|
||||||
|
// Get base margins rotated for current orientation, with bezel compensation applied
|
||||||
switch (orientation) {
|
switch (orientation) {
|
||||||
case Portrait:
|
case Portrait:
|
||||||
*outTop = VIEWABLE_MARGIN_TOP;
|
*outTop = getViewableMarginTop();
|
||||||
*outRight = VIEWABLE_MARGIN_RIGHT;
|
*outRight = getViewableMarginRight();
|
||||||
*outBottom = VIEWABLE_MARGIN_BOTTOM;
|
*outBottom = getViewableMarginBottom();
|
||||||
*outLeft = VIEWABLE_MARGIN_LEFT;
|
*outLeft = getViewableMarginLeft();
|
||||||
break;
|
break;
|
||||||
case LandscapeClockwise:
|
case LandscapeClockwise:
|
||||||
*outTop = VIEWABLE_MARGIN_LEFT;
|
*outTop = BASE_VIEWABLE_MARGIN_LEFT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 1 ? bezelCompensation : 0);
|
||||||
*outRight = VIEWABLE_MARGIN_TOP;
|
*outRight = BASE_VIEWABLE_MARGIN_TOP + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 3 ? bezelCompensation : 0);
|
||||||
*outBottom = VIEWABLE_MARGIN_RIGHT;
|
*outBottom = BASE_VIEWABLE_MARGIN_RIGHT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 0 ? bezelCompensation : 0);
|
||||||
*outLeft = VIEWABLE_MARGIN_BOTTOM;
|
*outLeft = BASE_VIEWABLE_MARGIN_BOTTOM + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 2 ? bezelCompensation : 0);
|
||||||
break;
|
break;
|
||||||
case PortraitInverted:
|
case PortraitInverted:
|
||||||
*outTop = VIEWABLE_MARGIN_BOTTOM;
|
*outTop = BASE_VIEWABLE_MARGIN_BOTTOM + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 1 ? bezelCompensation : 0);
|
||||||
*outRight = VIEWABLE_MARGIN_LEFT;
|
*outRight = BASE_VIEWABLE_MARGIN_LEFT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 3 ? bezelCompensation : 0);
|
||||||
*outBottom = VIEWABLE_MARGIN_TOP;
|
*outBottom = BASE_VIEWABLE_MARGIN_TOP + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 0 ? bezelCompensation : 0);
|
||||||
*outLeft = VIEWABLE_MARGIN_RIGHT;
|
*outLeft = BASE_VIEWABLE_MARGIN_RIGHT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 2 ? bezelCompensation : 0);
|
||||||
break;
|
break;
|
||||||
case LandscapeCounterClockwise:
|
case LandscapeCounterClockwise:
|
||||||
*outTop = VIEWABLE_MARGIN_RIGHT;
|
*outTop = BASE_VIEWABLE_MARGIN_RIGHT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 1 ? bezelCompensation : 0);
|
||||||
*outRight = VIEWABLE_MARGIN_BOTTOM;
|
*outRight = BASE_VIEWABLE_MARGIN_BOTTOM + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 3 ? bezelCompensation : 0);
|
||||||
*outBottom = VIEWABLE_MARGIN_LEFT;
|
*outBottom = BASE_VIEWABLE_MARGIN_LEFT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 0 ? bezelCompensation : 0);
|
||||||
*outLeft = VIEWABLE_MARGIN_TOP;
|
*outLeft = BASE_VIEWABLE_MARGIN_TOP + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 2 ? bezelCompensation : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,9 +28,17 @@ class GfxRenderer {
|
|||||||
static_assert(BW_BUFFER_CHUNK_SIZE * BW_BUFFER_NUM_CHUNKS == EInkDisplay::BUFFER_SIZE,
|
static_assert(BW_BUFFER_CHUNK_SIZE * BW_BUFFER_NUM_CHUNKS == EInkDisplay::BUFFER_SIZE,
|
||||||
"BW buffer chunking does not line up with display buffer size");
|
"BW buffer chunking does not line up with display buffer size");
|
||||||
|
|
||||||
|
// Base viewable margins (hardware-specific, before bezel compensation)
|
||||||
|
static constexpr int BASE_VIEWABLE_MARGIN_TOP = 9;
|
||||||
|
static constexpr int BASE_VIEWABLE_MARGIN_RIGHT = 3;
|
||||||
|
static constexpr int BASE_VIEWABLE_MARGIN_BOTTOM = 3;
|
||||||
|
static constexpr int BASE_VIEWABLE_MARGIN_LEFT = 3;
|
||||||
|
|
||||||
EInkDisplay& einkDisplay;
|
EInkDisplay& einkDisplay;
|
||||||
RenderMode renderMode;
|
RenderMode renderMode;
|
||||||
Orientation orientation;
|
Orientation orientation;
|
||||||
|
int bezelCompensation = 0; // Pixels to add for bezel defect compensation
|
||||||
|
int bezelEdge = 0; // Which physical edge (0=bottom, 1=top, 2=left, 3=right in portrait)
|
||||||
uint8_t* bwBufferChunks[BW_BUFFER_NUM_CHUNKS] = {nullptr};
|
uint8_t* bwBufferChunks[BW_BUFFER_NUM_CHUNKS] = {nullptr};
|
||||||
std::map<int, EpdFontFamily> fontMap;
|
std::map<int, EpdFontFamily> fontMap;
|
||||||
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState,
|
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState,
|
||||||
@ -42,10 +50,24 @@ class GfxRenderer {
|
|||||||
explicit GfxRenderer(EInkDisplay& einkDisplay) : einkDisplay(einkDisplay), renderMode(BW), orientation(Portrait) {}
|
explicit GfxRenderer(EInkDisplay& einkDisplay) : einkDisplay(einkDisplay), renderMode(BW), orientation(Portrait) {}
|
||||||
~GfxRenderer() { freeBwBufferChunks(); }
|
~GfxRenderer() { freeBwBufferChunks(); }
|
||||||
|
|
||||||
static constexpr int VIEWABLE_MARGIN_TOP = 9;
|
// Viewable margins (includes bezel compensation applied to the configured edge)
|
||||||
static constexpr int VIEWABLE_MARGIN_RIGHT = 3;
|
int getViewableMarginTop() const;
|
||||||
static constexpr int VIEWABLE_MARGIN_BOTTOM = 3;
|
int getViewableMarginRight() const;
|
||||||
static constexpr int VIEWABLE_MARGIN_LEFT = 3;
|
int getViewableMarginBottom() const;
|
||||||
|
int getViewableMarginLeft() const;
|
||||||
|
|
||||||
|
// Bezel compensation configuration
|
||||||
|
void setBezelCompensation(int amount, int edge) {
|
||||||
|
bezelCompensation = amount;
|
||||||
|
bezelEdge = edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get bezel offset for each logical edge (0 if not the compensated edge)
|
||||||
|
// Use these to add bezel compensation to hardcoded margins in UI screens
|
||||||
|
int getBezelOffsetTop() const;
|
||||||
|
int getBezelOffsetRight() const;
|
||||||
|
int getBezelOffsetBottom() const;
|
||||||
|
int getBezelOffsetLeft() const;
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
void insertFont(int fontId, EpdFontFamily font);
|
void insertFont(int fontId, EpdFontFamily font);
|
||||||
|
|||||||
@ -23,7 +23,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) {
|
|||||||
namespace {
|
namespace {
|
||||||
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
||||||
// Increment this when adding new persisted settings fields
|
// Increment this when adding new persisted settings fields
|
||||||
constexpr uint8_t SETTINGS_COUNT = 27; // 26 + displayContrast
|
constexpr uint8_t SETTINGS_COUNT = 29; // 28 + bezelCompensationEdge
|
||||||
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -68,6 +68,10 @@ bool CrossPointSettings::saveToFile() const {
|
|||||||
serialization::writePod(outputFile, sleepScreenCoverFilter);
|
serialization::writePod(outputFile, sleepScreenCoverFilter);
|
||||||
// System-wide display contrast
|
// System-wide display contrast
|
||||||
serialization::writePod(outputFile, displayContrast);
|
serialization::writePod(outputFile, displayContrast);
|
||||||
|
// Bezel compensation for physical screen edge defects
|
||||||
|
serialization::writePod(outputFile, bezelCompensation);
|
||||||
|
// Which physical edge needs bezel compensation
|
||||||
|
serialization::writePod(outputFile, bezelCompensationEdge);
|
||||||
// New fields added at end for backward compatibility
|
// New fields added at end for backward compatibility
|
||||||
outputFile.close();
|
outputFile.close();
|
||||||
|
|
||||||
@ -172,6 +176,12 @@ bool CrossPointSettings::loadFromFile() {
|
|||||||
// System-wide display contrast (0 = normal, 1 = high)
|
// System-wide display contrast (0 = normal, 1 = high)
|
||||||
serialization::readPod(inputFile, displayContrast);
|
serialization::readPod(inputFile, displayContrast);
|
||||||
if (++settingsRead >= fileSettingsCount) break;
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
|
// Bezel compensation for physical screen edge defects (0-10px)
|
||||||
|
serialization::readPod(inputFile, bezelCompensation);
|
||||||
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
|
// Which physical edge needs bezel compensation
|
||||||
|
readAndValidate(inputFile, bezelCompensationEdge, BEZEL_EDGE_COUNT);
|
||||||
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
// New fields added at end for backward compatibility
|
// New fields added at end for backward compatibility
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
|
|||||||
@ -91,6 +91,10 @@ class CrossPointSettings {
|
|||||||
// Hide battery percentage
|
// Hide battery percentage
|
||||||
enum HIDE_BATTERY_PERCENTAGE { HIDE_NEVER = 0, HIDE_READER = 1, HIDE_ALWAYS = 2, HIDE_BATTERY_PERCENTAGE_COUNT };
|
enum HIDE_BATTERY_PERCENTAGE { HIDE_NEVER = 0, HIDE_READER = 1, HIDE_ALWAYS = 2, HIDE_BATTERY_PERCENTAGE_COUNT };
|
||||||
|
|
||||||
|
// Bezel compensation edge (which physical edge has the defect)
|
||||||
|
// These refer to physical edges in portrait orientation
|
||||||
|
enum BEZEL_EDGE { BEZEL_BOTTOM = 0, BEZEL_TOP = 1, BEZEL_LEFT = 2, BEZEL_RIGHT = 3, BEZEL_EDGE_COUNT };
|
||||||
|
|
||||||
// Sleep screen settings
|
// Sleep screen settings
|
||||||
uint8_t sleepScreen = DARK;
|
uint8_t sleepScreen = DARK;
|
||||||
// Sleep screen cover mode settings
|
// Sleep screen cover mode settings
|
||||||
@ -135,6 +139,11 @@ class CrossPointSettings {
|
|||||||
uint8_t longPressChapterSkip = 1;
|
uint8_t longPressChapterSkip = 1;
|
||||||
// System-wide display contrast (0 = normal, 1 = high)
|
// System-wide display contrast (0 = normal, 1 = high)
|
||||||
uint8_t displayContrast = 0;
|
uint8_t displayContrast = 0;
|
||||||
|
// Bezel compensation - extra margin for physical screen edge defects (0-10px)
|
||||||
|
// Applied to the physical edge specified by bezelCompensationEdge, rotates with orientation
|
||||||
|
uint8_t bezelCompensation = 0;
|
||||||
|
// Which physical edge needs compensation (in portrait orientation)
|
||||||
|
uint8_t bezelCompensationEdge = BEZEL_BOTTOM;
|
||||||
|
|
||||||
// Pinned list name (empty = none pinned)
|
// Pinned list name (empty = none pinned)
|
||||||
char pinnedListName[64] = "";
|
char pinnedListName[64] = "";
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Battery.h"
|
#include "Battery.h"
|
||||||
|
#include "CrossPointSettings.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
|
|
||||||
void ScreenComponents::drawBattery(const GfxRenderer& renderer, const int left, const int top,
|
void ScreenComponents::drawBattery(const GfxRenderer& renderer, const int left, const int top,
|
||||||
|
|||||||
@ -11,10 +11,15 @@ void BootActivity::onEnter() {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int centerY = (pageHeight - bezelTop - bezelBottom) / 2 + bezelTop;
|
||||||
|
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
renderer.drawImage(CrossLarge, (pageWidth - 128) / 2, (pageHeight - 128) / 2, 128, 128);
|
renderer.drawImage(CrossLarge, (pageWidth - 128) / 2, centerY - 64, 128, 128);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 70, "CrossPoint", true, EpdFontFamily::BOLD);
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "BOOTING");
|
renderer.drawCenteredText(SMALL_FONT_ID, centerY + 95, "BOOTING");
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, CROSSPOINT_VERSION);
|
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30 - bezelBottom, CROSSPOINT_VERSION);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,10 +139,15 @@ void SleepActivity::renderDefaultSleepScreen() const {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int centerY = (pageHeight - bezelTop - bezelBottom) / 2 + bezelTop;
|
||||||
|
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
renderer.drawImage(CrossLarge, (pageWidth - 128) / 2, (pageHeight - 128) / 2, 128, 128);
|
renderer.drawImage(CrossLarge, (pageWidth - 128) / 2, centerY - 64, 128, 128);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 70, "CrossPoint", true, EpdFontFamily::BOLD);
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "SLEEPING");
|
renderer.drawCenteredText(SMALL_FONT_ID, centerY + 95, "SLEEPING");
|
||||||
|
|
||||||
// Make sleep screen dark unless light is selected in settings
|
// Make sleep screen dark unless light is selected in settings
|
||||||
if (SETTINGS.sleepScreen != CrossPointSettings::SLEEP_SCREEN_MODE::LIGHT) {
|
if (SETTINGS.sleepScreen != CrossPointSettings::SLEEP_SCREEN_MODE::LIGHT) {
|
||||||
|
|||||||
@ -172,10 +172,17 @@ void OpdsBookBrowserActivity::render() const {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "OPDS Browser", true, EpdFontFamily::BOLD);
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int centerY = (pageHeight - bezelTop - bezelBottom) / 2 + bezelTop;
|
||||||
|
|
||||||
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "OPDS Browser", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
if (state == BrowserState::CHECK_WIFI) {
|
if (state == BrowserState::CHECK_WIFI) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, statusMessage.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, statusMessage.c_str());
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
@ -183,7 +190,7 @@ void OpdsBookBrowserActivity::render() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == BrowserState::LOADING) {
|
if (state == BrowserState::LOADING) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, statusMessage.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, statusMessage.c_str());
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
@ -191,8 +198,8 @@ void OpdsBookBrowserActivity::render() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == BrowserState::ERROR) {
|
if (state == BrowserState::ERROR) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, "Error:");
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 20, "Error:");
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, errorMessage.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 10, errorMessage.c_str());
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "Retry", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "Retry", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
@ -200,13 +207,13 @@ void OpdsBookBrowserActivity::render() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == BrowserState::DOWNLOADING) {
|
if (state == BrowserState::DOWNLOADING) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 40, "Downloading...");
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 40, "Downloading...");
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 10, statusMessage.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 10, statusMessage.c_str());
|
||||||
if (downloadTotal > 0) {
|
if (downloadTotal > 0) {
|
||||||
const int barWidth = pageWidth - 100;
|
const int barWidth = pageWidth - 100 - bezelLeft - bezelRight;
|
||||||
constexpr int barHeight = 20;
|
constexpr int barHeight = 20;
|
||||||
constexpr int barX = 50;
|
const int barX = 50 + bezelLeft;
|
||||||
const int barY = pageHeight / 2 + 20;
|
const int barY = centerY + 20;
|
||||||
ScreenComponents::drawProgressBar(renderer, barX, barY, barWidth, barHeight, downloadProgress, downloadTotal);
|
ScreenComponents::drawProgressBar(renderer, barX, barY, barWidth, barHeight, downloadProgress, downloadTotal);
|
||||||
}
|
}
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
@ -223,13 +230,13 @@ void OpdsBookBrowserActivity::render() const {
|
|||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
|
|
||||||
if (entries.empty()) {
|
if (entries.empty()) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, "No entries found");
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, "No entries found");
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto pageStartIndex = selectorIndex / PAGE_ITEMS * PAGE_ITEMS;
|
const auto pageStartIndex = selectorIndex / PAGE_ITEMS * PAGE_ITEMS;
|
||||||
renderer.fillRect(0, 60 + (selectorIndex % PAGE_ITEMS) * 30 - 2, pageWidth - 1, 30);
|
renderer.fillRect(bezelLeft, 60 + bezelTop + (selectorIndex % PAGE_ITEMS) * 30 - 2, pageWidth - 1 - bezelLeft - bezelRight, 30);
|
||||||
|
|
||||||
for (size_t i = pageStartIndex; i < entries.size() && i < static_cast<size_t>(pageStartIndex + PAGE_ITEMS); i++) {
|
for (size_t i = pageStartIndex; i < entries.size() && i < static_cast<size_t>(pageStartIndex + PAGE_ITEMS); i++) {
|
||||||
const auto& entry = entries[i];
|
const auto& entry = entries[i];
|
||||||
@ -246,8 +253,8 @@ void OpdsBookBrowserActivity::render() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto item = renderer.truncatedText(UI_10_FONT_ID, displayText.c_str(), renderer.getScreenWidth() - 40);
|
auto item = renderer.truncatedText(UI_10_FONT_ID, displayText.c_str(), renderer.getScreenWidth() - 40 - bezelLeft - bezelRight);
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, 60 + (i % PAGE_ITEMS) * 30, item.c_str(),
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, 60 + bezelTop + (i % PAGE_ITEMS) * 30, item.c_str(),
|
||||||
i != static_cast<size_t>(selectorIndex));
|
i != static_cast<size_t>(selectorIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -343,9 +343,12 @@ void HomeActivity::render() {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
constexpr int margin = 20;
|
// Base margins plus bezel compensation
|
||||||
constexpr int bottomMargin = 60;
|
const int margin = 20 + renderer.getBezelOffsetLeft();
|
||||||
constexpr int bookY = 30;
|
const int rightMargin = 20 + renderer.getBezelOffsetRight();
|
||||||
|
const int bottomMargin = 60 + renderer.getBezelOffsetBottom();
|
||||||
|
const int topMargin = renderer.getBezelOffsetTop();
|
||||||
|
const int bookY = 30 + topMargin;
|
||||||
constexpr int elementSpacing = 15;
|
constexpr int elementSpacing = 15;
|
||||||
|
|
||||||
// --- Calculate layout from bottom up ---
|
// --- Calculate layout from bottom up ---
|
||||||
@ -366,7 +369,7 @@ void HomeActivity::render() {
|
|||||||
fullWidthItems.insert(fullWidthItems.begin(), "OPDS Browser");
|
fullWidthItems.insert(fullWidthItems.begin(), "OPDS Browser");
|
||||||
}
|
}
|
||||||
|
|
||||||
const int menuTileWidth = pageWidth - 2 * margin;
|
const int menuTileWidth = pageWidth - margin - rightMargin;
|
||||||
constexpr int menuTileHeight = 45;
|
constexpr int menuTileHeight = 45;
|
||||||
constexpr int menuSpacing = 8;
|
constexpr int menuSpacing = 8;
|
||||||
const int halfTileWidth = (menuTileWidth - menuSpacing) / 2; // Account for spacing between halves
|
const int halfTileWidth = (menuTileWidth - menuSpacing) / 2; // Account for spacing between halves
|
||||||
@ -375,10 +378,10 @@ void HomeActivity::render() {
|
|||||||
menuTileHeight + static_cast<int>(fullWidthItems.size()) * (menuTileHeight + menuSpacing);
|
menuTileHeight + static_cast<int>(fullWidthItems.size()) * (menuTileHeight + menuSpacing);
|
||||||
|
|
||||||
// Anchor menu to bottom of screen
|
// Anchor menu to bottom of screen
|
||||||
const int menuStartY = pageHeight - bottomMargin - totalMenuHeight - margin;
|
const int menuStartY = pageHeight - bottomMargin - totalMenuHeight;
|
||||||
|
|
||||||
// Calculate book card dimensions - larger, filling available space
|
// Calculate book card dimensions - larger, filling available space
|
||||||
const int bookWidth = pageWidth - 2 * margin;
|
const int bookWidth = pageWidth - margin - rightMargin;
|
||||||
// Card extends to just above menu
|
// Card extends to just above menu
|
||||||
const int bookCardBottomY = menuStartY - elementSpacing;
|
const int bookCardBottomY = menuStartY - elementSpacing;
|
||||||
const int bookHeight = bookCardBottomY - bookY;
|
const int bookHeight = bookCardBottomY - bookY;
|
||||||
@ -721,7 +724,7 @@ void HomeActivity::render() {
|
|||||||
for (size_t i = 0; i < fullWidthItems.size(); ++i) {
|
for (size_t i = 0; i < fullWidthItems.size(); ++i) {
|
||||||
// Index offset: base + 2 (for Lists and My Library) + i
|
// Index offset: base + 2 (for Lists and My Library) + i
|
||||||
const int overallIndex = baseMenuIndex + 2 + static_cast<int>(i);
|
const int overallIndex = baseMenuIndex + 2 + static_cast<int>(i);
|
||||||
constexpr int tileX = margin;
|
const int tileX = margin;
|
||||||
const int tileY = firstRowY + menuTileHeight + menuSpacing + static_cast<int>(i) * (menuTileHeight + menuSpacing);
|
const int tileY = firstRowY + menuTileHeight + menuSpacing + static_cast<int>(i) * (menuTileHeight + menuSpacing);
|
||||||
const bool selected = selectorIndex == overallIndex;
|
const bool selected = selectorIndex == overallIndex;
|
||||||
|
|
||||||
|
|||||||
@ -12,15 +12,15 @@
|
|||||||
#include "util/StringUtils.h"
|
#include "util/StringUtils.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Layout constants (matching MyLibraryActivity's Recent tab)
|
// Base layout constants (bezel offsets added at render time)
|
||||||
constexpr int HEADER_Y = 15;
|
constexpr int BASE_HEADER_Y = 15;
|
||||||
constexpr int CONTENT_START_Y = 60;
|
constexpr int BASE_CONTENT_START_Y = 60;
|
||||||
constexpr int LINE_HEIGHT = 65; // Two-line items (title + author)
|
constexpr int LINE_HEIGHT = 65; // Two-line items (title + author)
|
||||||
constexpr int LEFT_MARGIN = 20;
|
constexpr int BASE_LEFT_MARGIN = 20;
|
||||||
constexpr int RIGHT_MARGIN = 40;
|
constexpr int BASE_RIGHT_MARGIN = 40;
|
||||||
constexpr int MICRO_THUMB_WIDTH = 45;
|
constexpr int MICRO_THUMB_WIDTH = 45;
|
||||||
constexpr int MICRO_THUMB_HEIGHT = 60;
|
constexpr int MICRO_THUMB_HEIGHT = 60;
|
||||||
constexpr int THUMB_RIGHT_MARGIN = 50;
|
constexpr int BASE_THUMB_RIGHT_MARGIN = 50;
|
||||||
|
|
||||||
// Timing thresholds
|
// Timing thresholds
|
||||||
constexpr int SKIP_PAGE_MS = 700;
|
constexpr int SKIP_PAGE_MS = 700;
|
||||||
@ -41,7 +41,9 @@ std::string getMicroThumbPathForBook(const std::string& bookPath) {
|
|||||||
int ListViewActivity::getPageItems() const {
|
int ListViewActivity::getPageItems() const {
|
||||||
const int screenHeight = renderer.getScreenHeight();
|
const int screenHeight = renderer.getScreenHeight();
|
||||||
const int bottomBarHeight = 60;
|
const int bottomBarHeight = 60;
|
||||||
const int availableHeight = screenHeight - CONTENT_START_Y - bottomBarHeight;
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int availableHeight = screenHeight - (BASE_CONTENT_START_Y + bezelTop) - bottomBarHeight - bezelBottom;
|
||||||
int items = availableHeight / LINE_HEIGHT;
|
int items = availableHeight / LINE_HEIGHT;
|
||||||
if (items < 1) {
|
if (items < 1) {
|
||||||
items = 1;
|
items = 1;
|
||||||
@ -172,6 +174,16 @@ void ListViewActivity::render() const {
|
|||||||
const int pageItems = getPageItems();
|
const int pageItems = getPageItems();
|
||||||
const int bookCount = static_cast<int>(bookList.books.size());
|
const int bookCount = static_cast<int>(bookList.books.size());
|
||||||
|
|
||||||
|
// Calculate bezel-adjusted margins
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int HEADER_Y = BASE_HEADER_Y + bezelTop;
|
||||||
|
const int CONTENT_START_Y = BASE_CONTENT_START_Y + bezelTop;
|
||||||
|
const int LEFT_MARGIN = BASE_LEFT_MARGIN + bezelLeft;
|
||||||
|
const int RIGHT_MARGIN = BASE_RIGHT_MARGIN + bezelRight;
|
||||||
|
const int THUMB_RIGHT_MARGIN = BASE_THUMB_RIGHT_MARGIN + bezelRight;
|
||||||
|
|
||||||
// Draw header with list name
|
// Draw header with list name
|
||||||
auto truncatedTitle = renderer.truncatedText(UI_12_FONT_ID, listName.c_str(), pageWidth - LEFT_MARGIN - RIGHT_MARGIN);
|
auto truncatedTitle = renderer.truncatedText(UI_12_FONT_ID, listName.c_str(), pageWidth - LEFT_MARGIN - RIGHT_MARGIN);
|
||||||
renderer.drawText(UI_12_FONT_ID, LEFT_MARGIN, HEADER_Y, truncatedTitle.c_str(), true, EpdFontFamily::BOLD);
|
renderer.drawText(UI_12_FONT_ID, LEFT_MARGIN, HEADER_Y, truncatedTitle.c_str(), true, EpdFontFamily::BOLD);
|
||||||
@ -190,7 +202,7 @@ void ListViewActivity::render() const {
|
|||||||
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
||||||
|
|
||||||
// Draw selection highlight
|
// Draw selection highlight
|
||||||
renderer.fillRect(0, CONTENT_START_Y + (selectorIndex % pageItems) * LINE_HEIGHT - 2, pageWidth - RIGHT_MARGIN,
|
renderer.fillRect(bezelLeft, CONTENT_START_Y + (selectorIndex % pageItems) * LINE_HEIGHT - 2, pageWidth - RIGHT_MARGIN - bezelLeft,
|
||||||
LINE_HEIGHT);
|
LINE_HEIGHT);
|
||||||
|
|
||||||
// Calculate available text width
|
// Calculate available text width
|
||||||
|
|||||||
@ -31,16 +31,16 @@ void MyLibraryActivity::clearThumbExistsCache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Layout constants
|
// Base layout constants (bezel offsets added at render time)
|
||||||
constexpr int TAB_BAR_Y = 15;
|
constexpr int BASE_TAB_BAR_Y = 15;
|
||||||
constexpr int CONTENT_START_Y = 60;
|
constexpr int BASE_CONTENT_START_Y = 60;
|
||||||
constexpr int LINE_HEIGHT = 30;
|
constexpr int LINE_HEIGHT = 30;
|
||||||
constexpr int RECENTS_LINE_HEIGHT = 65; // Increased for two-line items
|
constexpr int RECENTS_LINE_HEIGHT = 65; // Increased for two-line items
|
||||||
constexpr int LEFT_MARGIN = 20;
|
constexpr int BASE_LEFT_MARGIN = 20;
|
||||||
constexpr int RIGHT_MARGIN = 40; // Extra space for scroll indicator
|
constexpr int BASE_RIGHT_MARGIN = 40; // Extra space for scroll indicator
|
||||||
constexpr int MICRO_THUMB_WIDTH = 45;
|
constexpr int MICRO_THUMB_WIDTH = 45;
|
||||||
constexpr int MICRO_THUMB_HEIGHT = 60;
|
constexpr int MICRO_THUMB_HEIGHT = 60;
|
||||||
constexpr int THUMB_RIGHT_MARGIN = 50; // Space from right edge for thumbnail
|
constexpr int BASE_THUMB_RIGHT_MARGIN = 50; // Space from right edge for thumbnail
|
||||||
|
|
||||||
// Helper function to get the micro-thumb path for a book based on its file path
|
// Helper function to get the micro-thumb path for a book based on its file path
|
||||||
std::string getMicroThumbPathForBook(const std::string& bookPath) {
|
std::string getMicroThumbPathForBook(const std::string& bookPath) {
|
||||||
@ -74,7 +74,9 @@ void sortFileList(std::vector<std::string>& strs) {
|
|||||||
int MyLibraryActivity::getPageItems() const {
|
int MyLibraryActivity::getPageItems() const {
|
||||||
const int screenHeight = renderer.getScreenHeight();
|
const int screenHeight = renderer.getScreenHeight();
|
||||||
const int bottomBarHeight = 60; // Space for button hints
|
const int bottomBarHeight = 60; // Space for button hints
|
||||||
const int availableHeight = screenHeight - CONTENT_START_Y - bottomBarHeight;
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int availableHeight = screenHeight - (BASE_CONTENT_START_Y + bezelTop) - bottomBarHeight - bezelBottom;
|
||||||
// Recent tab uses taller items (title + author), Lists and Files use single-line items
|
// Recent tab uses taller items (title + author), Lists and Files use single-line items
|
||||||
const int lineHeight = (currentTab == Tab::Recent) ? RECENTS_LINE_HEIGHT : LINE_HEIGHT;
|
const int lineHeight = (currentTab == Tab::Recent) ? RECENTS_LINE_HEIGHT : LINE_HEIGHT;
|
||||||
int items = availableHeight / lineHeight;
|
int items = availableHeight / lineHeight;
|
||||||
@ -700,6 +702,12 @@ void MyLibraryActivity::render() const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate bezel-adjusted margins
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int TAB_BAR_Y = BASE_TAB_BAR_Y + bezelTop;
|
||||||
|
const int CONTENT_START_Y = BASE_CONTENT_START_Y + bezelTop;
|
||||||
|
|
||||||
// Normal state - draw library view
|
// Normal state - draw library view
|
||||||
// Draw tab bar
|
// Draw tab bar
|
||||||
std::vector<TabInfo> tabs = {{"Recent", currentTab == Tab::Recent},
|
std::vector<TabInfo> tabs = {{"Recent", currentTab == Tab::Recent},
|
||||||
@ -718,7 +726,7 @@ void MyLibraryActivity::render() const {
|
|||||||
|
|
||||||
// Draw scroll indicator
|
// Draw scroll indicator
|
||||||
const int screenHeight = renderer.getScreenHeight();
|
const int screenHeight = renderer.getScreenHeight();
|
||||||
const int contentHeight = screenHeight - CONTENT_START_Y - 60; // 60 for bottom bar
|
const int contentHeight = screenHeight - CONTENT_START_Y - 60 - bezelBottom; // 60 for bottom bar
|
||||||
ScreenComponents::drawScrollIndicator(renderer, getCurrentPage(), getTotalPages(), CONTENT_START_Y, contentHeight);
|
ScreenComponents::drawScrollIndicator(renderer, getCurrentPage(), getTotalPages(), CONTENT_START_Y, contentHeight);
|
||||||
|
|
||||||
// Draw side button hints (up/down navigation on right side)
|
// Draw side button hints (up/down navigation on right side)
|
||||||
@ -737,6 +745,15 @@ void MyLibraryActivity::renderRecentTab() const {
|
|||||||
const int pageItems = getPageItems();
|
const int pageItems = getPageItems();
|
||||||
const int bookCount = static_cast<int>(recentBooks.size());
|
const int bookCount = static_cast<int>(recentBooks.size());
|
||||||
|
|
||||||
|
// Calculate bezel-adjusted margins
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int CONTENT_START_Y = BASE_CONTENT_START_Y + bezelTop;
|
||||||
|
const int LEFT_MARGIN = BASE_LEFT_MARGIN + bezelLeft;
|
||||||
|
const int RIGHT_MARGIN = BASE_RIGHT_MARGIN + bezelRight;
|
||||||
|
const int THUMB_RIGHT_MARGIN = BASE_THUMB_RIGHT_MARGIN + bezelRight;
|
||||||
|
|
||||||
if (bookCount == 0) {
|
if (bookCount == 0) {
|
||||||
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y, "No recent books");
|
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y, "No recent books");
|
||||||
return;
|
return;
|
||||||
@ -745,8 +762,8 @@ void MyLibraryActivity::renderRecentTab() const {
|
|||||||
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
||||||
|
|
||||||
// Draw selection highlight
|
// Draw selection highlight
|
||||||
renderer.fillRect(0, CONTENT_START_Y + (selectorIndex % pageItems) * RECENTS_LINE_HEIGHT - 2,
|
renderer.fillRect(bezelLeft, CONTENT_START_Y + (selectorIndex % pageItems) * RECENTS_LINE_HEIGHT - 2,
|
||||||
pageWidth - RIGHT_MARGIN, RECENTS_LINE_HEIGHT);
|
pageWidth - RIGHT_MARGIN - bezelLeft, RECENTS_LINE_HEIGHT);
|
||||||
|
|
||||||
// Calculate available text width (leaving space for thumbnail on the right)
|
// Calculate available text width (leaving space for thumbnail on the right)
|
||||||
const int textMaxWidth = pageWidth - LEFT_MARGIN - RIGHT_MARGIN - MICRO_THUMB_WIDTH - 10;
|
const int textMaxWidth = pageWidth - LEFT_MARGIN - RIGHT_MARGIN - MICRO_THUMB_WIDTH - 10;
|
||||||
@ -897,6 +914,14 @@ void MyLibraryActivity::renderListsTab() const {
|
|||||||
const int pageItems = getPageItems();
|
const int pageItems = getPageItems();
|
||||||
const int listCount = static_cast<int>(lists.size());
|
const int listCount = static_cast<int>(lists.size());
|
||||||
|
|
||||||
|
// Calculate bezel-adjusted margins
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int CONTENT_START_Y = BASE_CONTENT_START_Y + bezelTop;
|
||||||
|
const int LEFT_MARGIN = BASE_LEFT_MARGIN + bezelLeft;
|
||||||
|
const int RIGHT_MARGIN = BASE_RIGHT_MARGIN + bezelRight;
|
||||||
|
|
||||||
if (listCount == 0) {
|
if (listCount == 0) {
|
||||||
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y, "No lists found");
|
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y, "No lists found");
|
||||||
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y + LINE_HEIGHT, "Create lists in Companion App");
|
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y + LINE_HEIGHT, "Create lists in Companion App");
|
||||||
@ -906,7 +931,7 @@ void MyLibraryActivity::renderListsTab() const {
|
|||||||
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
||||||
|
|
||||||
// Draw selection highlight
|
// Draw selection highlight
|
||||||
renderer.fillRect(0, CONTENT_START_Y + (selectorIndex % pageItems) * LINE_HEIGHT - 2, pageWidth - RIGHT_MARGIN,
|
renderer.fillRect(bezelLeft, CONTENT_START_Y + (selectorIndex % pageItems) * LINE_HEIGHT - 2, pageWidth - RIGHT_MARGIN - bezelLeft,
|
||||||
LINE_HEIGHT);
|
LINE_HEIGHT);
|
||||||
|
|
||||||
// Draw items
|
// Draw items
|
||||||
@ -927,6 +952,14 @@ void MyLibraryActivity::renderFilesTab() const {
|
|||||||
const int pageItems = getPageItems();
|
const int pageItems = getPageItems();
|
||||||
const int fileCount = static_cast<int>(files.size());
|
const int fileCount = static_cast<int>(files.size());
|
||||||
|
|
||||||
|
// Calculate bezel-adjusted margins
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int CONTENT_START_Y = BASE_CONTENT_START_Y + bezelTop;
|
||||||
|
const int LEFT_MARGIN = BASE_LEFT_MARGIN + bezelLeft;
|
||||||
|
const int RIGHT_MARGIN = BASE_RIGHT_MARGIN + bezelRight;
|
||||||
|
|
||||||
if (fileCount == 0) {
|
if (fileCount == 0) {
|
||||||
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y, "No books found");
|
renderer.drawText(UI_10_FONT_ID, LEFT_MARGIN, CONTENT_START_Y, "No books found");
|
||||||
return;
|
return;
|
||||||
@ -935,7 +968,7 @@ void MyLibraryActivity::renderFilesTab() const {
|
|||||||
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
||||||
|
|
||||||
// Draw selection highlight
|
// Draw selection highlight
|
||||||
renderer.fillRect(0, CONTENT_START_Y + (selectorIndex % pageItems) * LINE_HEIGHT - 2, pageWidth - RIGHT_MARGIN,
|
renderer.fillRect(bezelLeft, CONTENT_START_Y + (selectorIndex % pageItems) * LINE_HEIGHT - 2, pageWidth - RIGHT_MARGIN - bezelLeft,
|
||||||
LINE_HEIGHT);
|
LINE_HEIGHT);
|
||||||
|
|
||||||
// Draw items
|
// Draw items
|
||||||
@ -950,12 +983,17 @@ void MyLibraryActivity::renderActionMenu() const {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 20, "Book Actions", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 20 + bezelTop, "Book Actions", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
// Show filename
|
// Show filename
|
||||||
const int filenameY = 70;
|
const int filenameY = 70 + bezelTop;
|
||||||
auto truncatedName = renderer.truncatedText(UI_10_FONT_ID, actionTargetName.c_str(), pageWidth - 40);
|
auto truncatedName = renderer.truncatedText(UI_10_FONT_ID, actionTargetName.c_str(), pageWidth - 40 - bezelLeft - bezelRight);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, filenameY, truncatedName.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, filenameY, truncatedName.c_str());
|
||||||
|
|
||||||
// Menu options - 4 for Recent tab, 2 for Files tab
|
// Menu options - 4 for Recent tab, 2 for Files tab
|
||||||
|
|||||||
@ -211,10 +211,13 @@ void CalibreConnectActivity::render() const {
|
|||||||
|
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int centerY = (pageHeight - bezelTop - bezelBottom) / 2 + bezelTop;
|
||||||
if (state == CalibreConnectState::SERVER_STARTING) {
|
if (state == CalibreConnectState::SERVER_STARTING) {
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Starting Calibre...", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, centerY - 20, "Starting Calibre...", true, EpdFontFamily::BOLD);
|
||||||
} else if (state == CalibreConnectState::ERROR) {
|
} else if (state == CalibreConnectState::ERROR) {
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Calibre setup failed", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, centerY - 20, "Calibre setup failed", true, EpdFontFamily::BOLD);
|
||||||
}
|
}
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
}
|
}
|
||||||
@ -224,7 +227,8 @@ void CalibreConnectActivity::renderServerRunning() const {
|
|||||||
constexpr int SMALL_SPACING = 20;
|
constexpr int SMALL_SPACING = 20;
|
||||||
constexpr int SECTION_SPACING = 40;
|
constexpr int SECTION_SPACING = 40;
|
||||||
constexpr int TOP_PADDING = 14;
|
constexpr int TOP_PADDING = 14;
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Connect to Calibre", true, EpdFontFamily::BOLD);
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "Connect to Calibre", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
int y = 55 + TOP_PADDING;
|
int y = 55 + TOP_PADDING;
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, y, "Network", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, y, "Network", true, EpdFontFamily::BOLD);
|
||||||
|
|||||||
@ -460,7 +460,10 @@ void CrossPointWebServerActivity::render() const {
|
|||||||
} else if (state == WebServerActivityState::AP_STARTING) {
|
} else if (state == WebServerActivityState::AP_STARTING) {
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Starting Hotspot...", true, EpdFontFamily::BOLD);
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int centerY = (pageHeight - bezelTop - bezelBottom) / 2 + bezelTop;
|
||||||
|
renderer.drawCenteredText(UI_12_FONT_ID, centerY - 20, "Starting Hotspot...", true, EpdFontFamily::BOLD);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,15 +105,21 @@ void NetworkModeSelectionActivity::render() const {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
|
||||||
// Draw header
|
// Draw header
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "File Transfer", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
// Draw subtitle
|
// Draw subtitle
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 50, "How would you like to connect?");
|
renderer.drawCenteredText(UI_10_FONT_ID, 50 + bezelTop, "How would you like to connect?");
|
||||||
|
|
||||||
// Draw menu items centered on screen
|
// Draw menu items centered on screen
|
||||||
constexpr int itemHeight = 50; // Height for each menu item (including description)
|
constexpr int itemHeight = 50; // Height for each menu item (including description)
|
||||||
const int startY = (pageHeight - (MENU_ITEM_COUNT * itemHeight)) / 2 + 10;
|
const int startY = (pageHeight - bezelTop - bezelBottom - (MENU_ITEM_COUNT * itemHeight)) / 2 + bezelTop + 10;
|
||||||
|
|
||||||
for (int i = 0; i < MENU_ITEM_COUNT; i++) {
|
for (int i = 0; i < MENU_ITEM_COUNT; i++) {
|
||||||
const int itemY = startY + i * itemHeight;
|
const int itemY = startY + i * itemHeight;
|
||||||
@ -121,13 +127,13 @@ void NetworkModeSelectionActivity::render() const {
|
|||||||
|
|
||||||
// Draw selection highlight (black fill) for selected item
|
// Draw selection highlight (black fill) for selected item
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
renderer.fillRect(20, itemY - 2, pageWidth - 40, itemHeight - 6);
|
renderer.fillRect(20 + bezelLeft, itemY - 2, pageWidth - 40 - bezelLeft - bezelRight, itemHeight - 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text: black=false (white text) when selected (on black background)
|
// Draw text: black=false (white text) when selected (on black background)
|
||||||
// black=true (black text) when not selected (on white background)
|
// black=true (black text) when not selected (on white background)
|
||||||
renderer.drawText(UI_10_FONT_ID, 30, itemY, MENU_ITEMS[i], /*black=*/!isSelected);
|
renderer.drawText(UI_10_FONT_ID, 30 + bezelLeft, itemY, MENU_ITEMS[i], /*black=*/!isSelected);
|
||||||
renderer.drawText(SMALL_FONT_ID, 30, itemY + 22, MENU_DESCRIPTIONS[i], /*black=*/!isSelected);
|
renderer.drawText(SMALL_FONT_ID, 30 + bezelLeft, itemY + 22, MENU_DESCRIPTIONS[i], /*black=*/!isSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw help text at bottom
|
// Draw help text at bottom
|
||||||
|
|||||||
@ -513,8 +513,14 @@ void WifiSelectionActivity::renderNetworkList() const {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
|
||||||
// Draw header
|
// Draw header
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "WiFi Networks", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "WiFi Networks", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
if (networks.empty()) {
|
if (networks.empty()) {
|
||||||
// No networks found or scan failed
|
// No networks found or scan failed
|
||||||
@ -524,9 +530,9 @@ void WifiSelectionActivity::renderNetworkList() const {
|
|||||||
renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Press OK to scan again");
|
renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Press OK to scan again");
|
||||||
} else {
|
} else {
|
||||||
// Calculate how many networks we can display
|
// Calculate how many networks we can display
|
||||||
constexpr int startY = 60;
|
const int startY = 60 + bezelTop;
|
||||||
constexpr int lineHeight = 25;
|
constexpr int lineHeight = 25;
|
||||||
const int maxVisibleNetworks = (pageHeight - startY - 40) / lineHeight;
|
const int maxVisibleNetworks = (pageHeight - startY - 40 - bezelBottom) / lineHeight;
|
||||||
|
|
||||||
// Calculate scroll offset to keep selected item visible
|
// Calculate scroll offset to keep selected item visible
|
||||||
int scrollOffset = 0;
|
int scrollOffset = 0;
|
||||||
@ -542,7 +548,7 @@ void WifiSelectionActivity::renderNetworkList() const {
|
|||||||
|
|
||||||
// Draw selection indicator
|
// Draw selection indicator
|
||||||
if (static_cast<int>(i) == selectedNetworkIndex) {
|
if (static_cast<int>(i) == selectedNetworkIndex) {
|
||||||
renderer.drawText(UI_10_FONT_ID, 5, networkY, ">");
|
renderer.drawText(UI_10_FONT_ID, 5 + bezelLeft, networkY, ">");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw network name (truncate if too long)
|
// Draw network name (truncate if too long)
|
||||||
@ -550,42 +556,42 @@ void WifiSelectionActivity::renderNetworkList() const {
|
|||||||
if (displayName.length() > 16) {
|
if (displayName.length() > 16) {
|
||||||
displayName.replace(13, displayName.length() - 13, "...");
|
displayName.replace(13, displayName.length() - 13, "...");
|
||||||
}
|
}
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, networkY, displayName.c_str());
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, networkY, displayName.c_str());
|
||||||
|
|
||||||
// Draw signal strength indicator
|
// Draw signal strength indicator
|
||||||
std::string signalStr = getSignalStrengthIndicator(network.rssi);
|
std::string signalStr = getSignalStrengthIndicator(network.rssi);
|
||||||
renderer.drawText(UI_10_FONT_ID, pageWidth - 90, networkY, signalStr.c_str());
|
renderer.drawText(UI_10_FONT_ID, pageWidth - 90 - bezelRight, networkY, signalStr.c_str());
|
||||||
|
|
||||||
// Draw saved indicator (checkmark) for networks with saved passwords
|
// Draw saved indicator (checkmark) for networks with saved passwords
|
||||||
if (network.hasSavedPassword) {
|
if (network.hasSavedPassword) {
|
||||||
renderer.drawText(UI_10_FONT_ID, pageWidth - 50, networkY, "+");
|
renderer.drawText(UI_10_FONT_ID, pageWidth - 50 - bezelRight, networkY, "+");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw lock icon for encrypted networks
|
// Draw lock icon for encrypted networks
|
||||||
if (network.isEncrypted) {
|
if (network.isEncrypted) {
|
||||||
renderer.drawText(UI_10_FONT_ID, pageWidth - 30, networkY, "*");
|
renderer.drawText(UI_10_FONT_ID, pageWidth - 30 - bezelRight, networkY, "*");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw scroll indicators if needed
|
// Draw scroll indicators if needed
|
||||||
if (scrollOffset > 0) {
|
if (scrollOffset > 0) {
|
||||||
renderer.drawText(SMALL_FONT_ID, pageWidth - 15, startY - 10, "^");
|
renderer.drawText(SMALL_FONT_ID, pageWidth - 15 - bezelRight, startY - 10, "^");
|
||||||
}
|
}
|
||||||
if (scrollOffset + maxVisibleNetworks < static_cast<int>(networks.size())) {
|
if (scrollOffset + maxVisibleNetworks < static_cast<int>(networks.size())) {
|
||||||
renderer.drawText(SMALL_FONT_ID, pageWidth - 15, startY + maxVisibleNetworks * lineHeight, "v");
|
renderer.drawText(SMALL_FONT_ID, pageWidth - 15 - bezelRight, startY + maxVisibleNetworks * lineHeight, "v");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show network count
|
// Show network count
|
||||||
char countStr[32];
|
char countStr[32];
|
||||||
snprintf(countStr, sizeof(countStr), "%zu networks found", networks.size());
|
snprintf(countStr, sizeof(countStr), "%zu networks found", networks.size());
|
||||||
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 90, countStr);
|
renderer.drawText(SMALL_FONT_ID, 20 + bezelLeft, pageHeight - 90 - bezelBottom, countStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show MAC address above the network count and legend
|
// Show MAC address above the network count and legend
|
||||||
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 105, cachedMacAddress.c_str());
|
renderer.drawText(SMALL_FONT_ID, 20 + bezelLeft, pageHeight - 105 - bezelBottom, cachedMacAddress.c_str());
|
||||||
|
|
||||||
// Draw help text
|
// Draw help text
|
||||||
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Encrypted | + = Saved");
|
renderer.drawText(SMALL_FONT_ID, 20 + bezelLeft, pageHeight - 75 - bezelBottom, "* = Encrypted | + = Saved");
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "Connect", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "Connect", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -166,28 +166,33 @@ void EpubReaderChapterSelectionActivity::renderScreen() {
|
|||||||
const int pageItems = getPageItems();
|
const int pageItems = getPageItems();
|
||||||
const int totalItems = getTotalItems();
|
const int totalItems = getTotalItems();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
|
||||||
const std::string title =
|
const std::string title =
|
||||||
renderer.truncatedText(UI_12_FONT_ID, epub->getTitle().c_str(), pageWidth - 40, EpdFontFamily::BOLD);
|
renderer.truncatedText(UI_12_FONT_ID, epub->getTitle().c_str(), pageWidth - 40 - bezelLeft - bezelRight, EpdFontFamily::BOLD);
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, title.c_str(), true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, title.c_str(), true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
const auto pageStartIndex = selectorIndex / pageItems * pageItems;
|
||||||
renderer.fillRect(0, 60 + (selectorIndex % pageItems) * 30 - 2, pageWidth - 1, 30);
|
renderer.fillRect(bezelLeft, 60 + bezelTop + (selectorIndex % pageItems) * 30 - 2, pageWidth - 1 - bezelLeft - bezelRight, 30);
|
||||||
|
|
||||||
for (int itemIndex = pageStartIndex; itemIndex < totalItems && itemIndex < pageStartIndex + pageItems; itemIndex++) {
|
for (int itemIndex = pageStartIndex; itemIndex < totalItems && itemIndex < pageStartIndex + pageItems; itemIndex++) {
|
||||||
const int displayY = 60 + (itemIndex % pageItems) * 30;
|
const int displayY = 60 + bezelTop + (itemIndex % pageItems) * 30;
|
||||||
const bool isSelected = (itemIndex == selectorIndex);
|
const bool isSelected = (itemIndex == selectorIndex);
|
||||||
|
|
||||||
if (isSyncItem(itemIndex)) {
|
if (isSyncItem(itemIndex)) {
|
||||||
// Draw sync option (at top or bottom)
|
// Draw sync option (at top or bottom)
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, displayY, ">> Sync Progress", !isSelected);
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, displayY, ">> Sync Progress", !isSelected);
|
||||||
} else {
|
} else {
|
||||||
// Draw TOC item (account for top sync offset)
|
// Draw TOC item (account for top sync offset)
|
||||||
const int tocIndex = tocIndexFromItemIndex(itemIndex);
|
const int tocIndex = tocIndexFromItemIndex(itemIndex);
|
||||||
auto item = epub->getTocItem(tocIndex);
|
auto item = epub->getTocItem(tocIndex);
|
||||||
const int indentSize = 20 + (item.level - 1) * 15;
|
const int indentSize = 20 + bezelLeft + (item.level - 1) * 15;
|
||||||
const std::string chapterName =
|
const std::string chapterName =
|
||||||
renderer.truncatedText(UI_10_FONT_ID, item.title.c_str(), pageWidth - 40 - indentSize);
|
renderer.truncatedText(UI_10_FONT_ID, item.title.c_str(), pageWidth - 40 - bezelLeft - bezelRight - indentSize + 20 + bezelLeft);
|
||||||
renderer.drawText(UI_10_FONT_ID, indentSize, 60 + (tocIndex % pageItems) * 30, chapterName.c_str(),
|
renderer.drawText(UI_10_FONT_ID, indentSize, 60 + bezelTop + (tocIndex % pageItems) * 30, chapterName.c_str(),
|
||||||
tocIndex != selectorIndex);
|
tocIndex != selectorIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -153,21 +153,26 @@ void CalibreSettingsActivity::render() {
|
|||||||
|
|
||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
|
||||||
// Draw header
|
// Draw header
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "OPDS Browser", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "OPDS Browser", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
// Draw info text about Calibre
|
// Draw info text about Calibre
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 40, "For Calibre, add /opds to your URL");
|
renderer.drawCenteredText(UI_10_FONT_ID, 40 + bezelTop, "For Calibre, add /opds to your URL");
|
||||||
|
|
||||||
// Draw selection highlight
|
// Draw selection highlight
|
||||||
renderer.fillRect(0, 70 + selectedIndex * 30 - 2, pageWidth - 1, 30);
|
renderer.fillRect(bezelLeft, 70 + bezelTop + selectedIndex * 30 - 2, pageWidth - 1 - bezelLeft - bezelRight, 30);
|
||||||
|
|
||||||
// Draw menu items
|
// Draw menu items
|
||||||
for (int i = 0; i < MENU_ITEMS; i++) {
|
for (int i = 0; i < MENU_ITEMS; i++) {
|
||||||
const int settingY = 70 + i * 30;
|
const int settingY = 70 + bezelTop + i * 30;
|
||||||
const bool isSelected = (i == selectedIndex);
|
const bool isSelected = (i == selectedIndex);
|
||||||
|
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, settingY, menuNames[i], !isSelected);
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, settingY, menuNames[i], !isSelected);
|
||||||
|
|
||||||
// Draw status for each setting
|
// Draw status for each setting
|
||||||
const char* status = "[Not Set]";
|
const char* status = "[Not Set]";
|
||||||
@ -179,7 +184,7 @@ void CalibreSettingsActivity::render() {
|
|||||||
status = (strlen(SETTINGS.opdsPassword) > 0) ? "[Set]" : "[Not Set]";
|
status = (strlen(SETTINGS.opdsPassword) > 0) ? "[Set]" : "[Not Set]";
|
||||||
}
|
}
|
||||||
const auto width = renderer.getTextWidth(UI_10_FONT_ID, status);
|
const auto width = renderer.getTextWidth(UI_10_FONT_ID, status);
|
||||||
renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - width, settingY, status, !isSelected);
|
renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - bezelRight - width, settingY, status, !isSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw button hints
|
// Draw button hints
|
||||||
|
|||||||
@ -124,6 +124,11 @@ void CategorySettingsActivity::toggleCurrentSetting() {
|
|||||||
} else if (setting.type == SettingType::ENUM && setting.valuePtr != nullptr) {
|
} else if (setting.type == SettingType::ENUM && setting.valuePtr != nullptr) {
|
||||||
const uint8_t currentValue = SETTINGS.*(setting.valuePtr);
|
const uint8_t currentValue = SETTINGS.*(setting.valuePtr);
|
||||||
SETTINGS.*(setting.valuePtr) = (currentValue + 1) % static_cast<uint8_t>(setting.enumValues.size());
|
SETTINGS.*(setting.valuePtr) = (currentValue + 1) % static_cast<uint8_t>(setting.enumValues.size());
|
||||||
|
|
||||||
|
// Handle side effects for specific settings
|
||||||
|
if (setting.valuePtr == &CrossPointSettings::bezelCompensationEdge) {
|
||||||
|
renderer.setBezelCompensation(SETTINGS.bezelCompensation, SETTINGS.bezelCompensationEdge);
|
||||||
|
}
|
||||||
} else if (setting.type == SettingType::VALUE && setting.valuePtr != nullptr) {
|
} else if (setting.type == SettingType::VALUE && setting.valuePtr != nullptr) {
|
||||||
const int8_t currentValue = SETTINGS.*(setting.valuePtr);
|
const int8_t currentValue = SETTINGS.*(setting.valuePtr);
|
||||||
if (currentValue + setting.valueRange.step > setting.valueRange.max) {
|
if (currentValue + setting.valueRange.step > setting.valueRange.max) {
|
||||||
@ -131,6 +136,11 @@ void CategorySettingsActivity::toggleCurrentSetting() {
|
|||||||
} else {
|
} else {
|
||||||
SETTINGS.*(setting.valuePtr) = currentValue + setting.valueRange.step;
|
SETTINGS.*(setting.valuePtr) = currentValue + setting.valueRange.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle side effects for specific settings
|
||||||
|
if (setting.valuePtr == &CrossPointSettings::bezelCompensation) {
|
||||||
|
renderer.setBezelCompensation(SETTINGS.bezelCompensation, SETTINGS.bezelCompensationEdge);
|
||||||
|
}
|
||||||
} else if (setting.type == SettingType::ACTION) {
|
} else if (setting.type == SettingType::ACTION) {
|
||||||
if (strcmp(setting.name, "Calibre Settings") == 0) {
|
if (strcmp(setting.name, "Calibre Settings") == 0) {
|
||||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||||
@ -182,10 +192,16 @@ void CategorySettingsActivity::render() const {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, categoryName, true, EpdFontFamily::BOLD);
|
// Bezel compensation offsets
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
|
||||||
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, categoryName, true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
// Draw selection highlight
|
// Draw selection highlight
|
||||||
renderer.fillRect(0, 60 + selectedSettingIndex * 30 - 2, pageWidth - 1, 30);
|
renderer.fillRect(bezelLeft, 60 + bezelTop + selectedSettingIndex * 30 - 2, pageWidth - 1 - bezelLeft - bezelRight, 30);
|
||||||
|
|
||||||
// Draw only visible settings
|
// Draw only visible settings
|
||||||
int visibleIndex = 0;
|
int visibleIndex = 0;
|
||||||
@ -194,11 +210,11 @@ void CategorySettingsActivity::render() const {
|
|||||||
continue; // Skip hidden settings
|
continue; // Skip hidden settings
|
||||||
}
|
}
|
||||||
|
|
||||||
const int settingY = 60 + visibleIndex * 30; // 30 pixels between settings
|
const int settingY = 60 + bezelTop + visibleIndex * 30; // 30 pixels between settings
|
||||||
const bool isSelected = (visibleIndex == selectedSettingIndex);
|
const bool isSelected = (visibleIndex == selectedSettingIndex);
|
||||||
|
|
||||||
// Draw setting name
|
// Draw setting name
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, settingY, settingsList[i].name, !isSelected);
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, settingY, settingsList[i].name, !isSelected);
|
||||||
|
|
||||||
// Draw value based on setting type
|
// Draw value based on setting type
|
||||||
std::string valueText;
|
std::string valueText;
|
||||||
@ -215,14 +231,14 @@ void CategorySettingsActivity::render() const {
|
|||||||
}
|
}
|
||||||
if (!valueText.empty()) {
|
if (!valueText.empty()) {
|
||||||
const auto width = renderer.getTextWidth(UI_10_FONT_ID, valueText.c_str());
|
const auto width = renderer.getTextWidth(UI_10_FONT_ID, valueText.c_str());
|
||||||
renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - width, settingY, valueText.c_str(), !isSelected);
|
renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - bezelRight - width, settingY, valueText.c_str(), !isSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
visibleIndex++;
|
visibleIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.drawText(SMALL_FONT_ID, pageWidth - 20 - renderer.getTextWidth(SMALL_FONT_ID, CROSSPOINT_VERSION),
|
renderer.drawText(SMALL_FONT_ID, pageWidth - 20 - bezelRight - renderer.getTextWidth(SMALL_FONT_ID, CROSSPOINT_VERSION),
|
||||||
pageHeight - 60, CROSSPOINT_VERSION);
|
pageHeight - 60 - bezelBottom, CROSSPOINT_VERSION);
|
||||||
|
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "Toggle", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "Toggle", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
|
|||||||
@ -58,15 +58,20 @@ void ClearCacheActivity::displayTaskLoop() {
|
|||||||
void ClearCacheActivity::render() {
|
void ClearCacheActivity::render() {
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int centerY = (pageHeight - bezelTop - bezelBottom) / 2 + bezelTop;
|
||||||
|
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Clear Cache", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "Clear Cache", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
if (state == WARNING) {
|
if (state == WARNING) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 60, "This will clear all cached book data.", true);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 60, "This will clear all cached book data.", true);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 30, "All reading progress will be lost!", true,
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 30, "All reading progress will be lost!", true,
|
||||||
EpdFontFamily::BOLD);
|
EpdFontFamily::BOLD);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, "Books will need to be re-indexed", true);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 10, "Books will need to be re-indexed", true);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 30, "when opened again.", true);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 30, "when opened again.", true);
|
||||||
|
|
||||||
const auto labels = mappedInput.mapLabels("« Cancel", "Clear", "", "");
|
const auto labels = mappedInput.mapLabels("« Cancel", "Clear", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
@ -75,18 +80,18 @@ void ClearCacheActivity::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == CLEARING) {
|
if (state == CLEARING) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, "Clearing cache...", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, "Clearing cache...", true, EpdFontFamily::BOLD);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == SUCCESS) {
|
if (state == SUCCESS) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, "Cache Cleared", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 20, "Cache Cleared", true, EpdFontFamily::BOLD);
|
||||||
String resultText = String(clearedCount) + " items removed";
|
String resultText = String(clearedCount) + " items removed";
|
||||||
if (failedCount > 0) {
|
if (failedCount > 0) {
|
||||||
resultText += ", " + String(failedCount) + " failed";
|
resultText += ", " + String(failedCount) + " failed";
|
||||||
}
|
}
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, resultText.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 10, resultText.c_str());
|
||||||
|
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
@ -95,8 +100,8 @@ void ClearCacheActivity::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == FAILED) {
|
if (state == FAILED) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, "Failed to clear cache", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 20, "Failed to clear cache", true, EpdFontFamily::BOLD);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, "Check serial output for details");
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 10, "Check serial output for details");
|
||||||
|
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
|
|||||||
@ -126,20 +126,28 @@ void OtaUpdateActivity::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int centerY = (pageHeight - bezelTop - bezelBottom) / 2 + bezelTop;
|
||||||
|
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Update", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "Update", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
if (state == CHECKING_FOR_UPDATE) {
|
if (state == CHECKING_FOR_UPDATE) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Checking for update...", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, "Checking for update...", true, EpdFontFamily::BOLD);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == WAITING_CONFIRMATION) {
|
if (state == WAITING_CONFIRMATION) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 200, "New update available!", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 100, "New update available!", true, EpdFontFamily::BOLD);
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, 250, "Current Version: " CROSSPOINT_VERSION);
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, centerY - 50, "Current Version: " CROSSPOINT_VERSION);
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, 270, ("New Version: " + updater.getLatestVersion()).c_str());
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, centerY - 30, ("New Version: " + updater.getLatestVersion()).c_str());
|
||||||
|
|
||||||
const auto labels = mappedInput.mapLabels("Cancel", "Update", "", "");
|
const auto labels = mappedInput.mapLabels("Cancel", "Update", "", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
@ -148,33 +156,33 @@ void OtaUpdateActivity::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == UPDATE_IN_PROGRESS) {
|
if (state == UPDATE_IN_PROGRESS) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 310, "Updating...", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY - 40, "Updating...", true, EpdFontFamily::BOLD);
|
||||||
renderer.drawRect(20, 350, pageWidth - 40, 50);
|
renderer.drawRect(20 + bezelLeft, centerY, pageWidth - 40 - bezelLeft - bezelRight, 50);
|
||||||
renderer.fillRect(24, 354, static_cast<int>(updaterProgress * static_cast<float>(pageWidth - 44)), 42);
|
renderer.fillRect(24 + bezelLeft, centerY + 4, static_cast<int>(updaterProgress * static_cast<float>(pageWidth - 44 - bezelLeft - bezelRight)), 42);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 420,
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 70,
|
||||||
(std::to_string(static_cast<int>(updaterProgress * 100)) + "%").c_str());
|
(std::to_string(static_cast<int>(updaterProgress * 100)) + "%").c_str());
|
||||||
renderer.drawCenteredText(
|
renderer.drawCenteredText(
|
||||||
UI_10_FONT_ID, 440,
|
UI_10_FONT_ID, centerY + 90,
|
||||||
(std::to_string(updater.processedSize) + " / " + std::to_string(updater.totalSize)).c_str());
|
(std::to_string(updater.processedSize) + " / " + std::to_string(updater.totalSize)).c_str());
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == NO_UPDATE) {
|
if (state == NO_UPDATE) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "No update available", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, "No update available", true, EpdFontFamily::BOLD);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == FAILED) {
|
if (state == FAILED) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update failed", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, "Update failed", true, EpdFontFamily::BOLD);
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == FINISHED) {
|
if (state == FINISHED) {
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update complete", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY, "Update complete", true, EpdFontFamily::BOLD);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, 350, "Press and hold power button to turn back on");
|
renderer.drawCenteredText(UI_10_FONT_ID, centerY + 50, "Press and hold power button to turn back on");
|
||||||
renderer.displayBuffer();
|
renderer.displayBuffer();
|
||||||
state = SHUTTING_DOWN;
|
state = SHUTTING_DOWN;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -12,7 +12,10 @@
|
|||||||
const char* SettingsActivity::categoryNames[categoryCount] = {"Display", "Reader", "Controls", "System"};
|
const char* SettingsActivity::categoryNames[categoryCount] = {"Display", "Reader", "Controls", "System"};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr int displaySettingsCount = 7;
|
// Visibility condition for bezel edge setting (only show when compensation > 0)
|
||||||
|
bool isBezelCompensationEnabled() { return SETTINGS.bezelCompensation > 0; }
|
||||||
|
|
||||||
|
constexpr int displaySettingsCount = 9;
|
||||||
const SettingInfo displaySettings[displaySettingsCount] = {
|
const SettingInfo displaySettings[displaySettingsCount] = {
|
||||||
// Should match with SLEEP_SCREEN_MODE
|
// Should match with SLEEP_SCREEN_MODE
|
||||||
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
||||||
@ -24,7 +27,10 @@ const SettingInfo displaySettings[displaySettingsCount] = {
|
|||||||
{"None", "No Progress", "Full w/ Percentage", "Full w/ Progress Bar", "Progress Bar"}),
|
{"None", "No Progress", "Full w/ Percentage", "Full w/ Progress Bar", "Progress Bar"}),
|
||||||
SettingInfo::Enum("Hide Battery %", &CrossPointSettings::hideBatteryPercentage, {"Never", "In Reader", "Always"}),
|
SettingInfo::Enum("Hide Battery %", &CrossPointSettings::hideBatteryPercentage, {"Never", "In Reader", "Always"}),
|
||||||
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
||||||
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"})};
|
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}),
|
||||||
|
SettingInfo::Value("Bezel Compensation", &CrossPointSettings::bezelCompensation, {0, 10, 1}),
|
||||||
|
SettingInfo::Enum("Bezel Edge", &CrossPointSettings::bezelCompensationEdge,
|
||||||
|
{"Bottom", "Top", "Left", "Right"}, isBezelCompensationEnabled)};
|
||||||
|
|
||||||
// Helper to get custom font names as a vector
|
// Helper to get custom font names as a vector
|
||||||
std::vector<std::string> getCustomFontNamesVector() {
|
std::vector<std::string> getCustomFontNamesVector() {
|
||||||
@ -213,23 +219,29 @@ void SettingsActivity::render() const {
|
|||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|
||||||
|
// Bezel compensation offsets
|
||||||
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelLeft = renderer.getBezelOffsetLeft();
|
||||||
|
const int bezelRight = renderer.getBezelOffsetRight();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
|
||||||
// Draw header
|
// Draw header
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Settings", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, 15 + bezelTop, "Settings", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
// Draw selection
|
// Draw selection
|
||||||
renderer.fillRect(0, 60 + selectedCategoryIndex * 30 - 2, pageWidth - 1, 30);
|
renderer.fillRect(bezelLeft, 60 + bezelTop + selectedCategoryIndex * 30 - 2, pageWidth - 1 - bezelLeft - bezelRight, 30);
|
||||||
|
|
||||||
// Draw all categories
|
// Draw all categories
|
||||||
for (int i = 0; i < categoryCount; i++) {
|
for (int i = 0; i < categoryCount; i++) {
|
||||||
const int categoryY = 60 + i * 30; // 30 pixels between categories
|
const int categoryY = 60 + bezelTop + i * 30; // 30 pixels between categories
|
||||||
|
|
||||||
// Draw category name
|
// Draw category name
|
||||||
renderer.drawText(UI_10_FONT_ID, 20, categoryY, categoryNames[i], i != selectedCategoryIndex);
|
renderer.drawText(UI_10_FONT_ID, 20 + bezelLeft, categoryY, categoryNames[i], i != selectedCategoryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw version text above button hints
|
// Draw version text above button hints
|
||||||
renderer.drawText(SMALL_FONT_ID, pageWidth - 20 - renderer.getTextWidth(SMALL_FONT_ID, CROSSPOINT_VERSION),
|
renderer.drawText(SMALL_FONT_ID, pageWidth - 20 - bezelRight - renderer.getTextWidth(SMALL_FONT_ID, CROSSPOINT_VERSION),
|
||||||
pageHeight - 60, CROSSPOINT_VERSION);
|
pageHeight - 60 - bezelBottom, CROSSPOINT_VERSION);
|
||||||
|
|
||||||
// Draw help text
|
// Draw help text
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "Select", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "Select", "", "");
|
||||||
|
|||||||
@ -8,7 +8,9 @@ void FullScreenMessageActivity::onEnter() {
|
|||||||
Activity::onEnter();
|
Activity::onEnter();
|
||||||
|
|
||||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||||
const auto top = (renderer.getScreenHeight() - height) / 2;
|
const int bezelTop = renderer.getBezelOffsetTop();
|
||||||
|
const int bezelBottom = renderer.getBezelOffsetBottom();
|
||||||
|
const auto top = (renderer.getScreenHeight() - bezelTop - bezelBottom - height) / 2 + bezelTop;
|
||||||
|
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, top, text.c_str(), true, style);
|
renderer.drawCenteredText(UI_10_FONT_ID, top, text.c_str(), true, style);
|
||||||
|
|||||||
@ -475,6 +475,8 @@ void setup() {
|
|||||||
SETTINGS.loadFromFile();
|
SETTINGS.loadFromFile();
|
||||||
// Apply high contrast mode from settings
|
// Apply high contrast mode from settings
|
||||||
setHighContrastMode(SETTINGS.displayContrast == 1);
|
setHighContrastMode(SETTINGS.displayContrast == 1);
|
||||||
|
// Apply bezel compensation from settings
|
||||||
|
renderer.setBezelCompensation(SETTINGS.bezelCompensation, SETTINGS.bezelCompensationEdge);
|
||||||
|
|
||||||
if (isWakeupByPowerButton()) {
|
if (isWakeupByPowerButton()) {
|
||||||
// For normal wakeups, verify power button press duration
|
// For normal wakeups, verify power button press duration
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user