feat: Allow statusbar clock to be on the left (#2359)

This commit is contained in:
Husam Younis
2026-06-25 00:23:23 +03:00
committed by GitHub
parent 6e8dbd7f23
commit 7271c00d35
5 changed files with 53 additions and 28 deletions
+3 -1
View File
@@ -65,6 +65,8 @@ class CrossPointSettings {
XTC_STATUS_BAR_MODE_COUNT XTC_STATUS_BAR_MODE_COUNT
}; };
enum STATUS_BAR_CLOCK_MODE { STATUS_BAR_CLOCK_HIDE = 0, STATUS_BAR_CLOCK_RIGHT = 1, STATUS_BAR_CLOCK_LEFT = 2 };
enum ORIENTATION { enum ORIENTATION {
PORTRAIT = 0, // 480x800 logical coordinates (current default) PORTRAIT = 0, // 480x800 logical coordinates (current default)
LANDSCAPE_CW = 1, // 800x480 logical coordinates, rotated 180° (swap top/bottom) LANDSCAPE_CW = 1, // 800x480 logical coordinates, rotated 180° (swap top/bottom)
@@ -188,7 +190,7 @@ class CrossPointSettings {
uint8_t statusBarBattery = 1; uint8_t statusBarBattery = 1;
uint8_t xtcStatusBarMode = XTC_STATUS_BAR_HIDE; uint8_t xtcStatusBarMode = XTC_STATUS_BAR_HIDE;
// Clock display in status bar (X3 only, requires DS3231 RTC) // Clock display in status bar (X3 only, requires DS3231 RTC)
uint8_t statusBarClock = 0; uint8_t statusBarClock = STATUS_BAR_CLOCK_HIDE;
// Clock UTC offset in quarter-hour steps, biased by 48 so it fits in uint8_t. // Clock UTC offset in quarter-hour steps, biased by 48 so it fits in uint8_t.
// Value 48 = UTC+0, 0 = UTC-12:00, 104 = UTC+14:00. // Value 48 = UTC+0, 0 = UTC-12:00, 104 = UTC+14:00.
// Quarter-hour granularity supports oddball zones like Nepal (+5:45) and Chatham (+12:45). // Quarter-hour granularity supports oddball zones like Nepal (+5:45) and Chatham (+12:45).
+3 -2
View File
@@ -244,8 +244,9 @@ inline std::vector<SettingInfo> getSettingsList(const SdCardFontRegistry* regist
StrId::STR_CUSTOMISE_STATUS_BAR), StrId::STR_CUSTOMISE_STATUS_BAR),
// Clock entries (web settings only; device UI uses ClockOffsetActivity for the offset). // Clock entries (web settings only; device UI uses ClockOffsetActivity for the offset).
// Range 0..104 = quarter-hour steps from UTC-12:00 to UTC+14:00, biased by 48. // Range 0..104 = quarter-hour steps from UTC-12:00 to UTC+14:00, biased by 48.
SettingInfo::Toggle(StrId::STR_CLOCK, &CrossPointSettings::statusBarClock, "statusBarClock", SettingInfo::Enum(StrId::STR_CLOCK, &CrossPointSettings::statusBarClock,
StrId::STR_CUSTOMISE_STATUS_BAR), {StrId::STR_HIDE, StrId::STR_DIR_LEFT, StrId::STR_DIR_RIGHT}, "statusBarClock",
StrId::STR_CUSTOMISE_STATUS_BAR),
SettingInfo::Value(StrId::STR_CLOCK_UTC_OFFSET, &CrossPointSettings::clockUtcOffsetQ, {0, 104, 1}, SettingInfo::Value(StrId::STR_CLOCK_UTC_OFFSET, &CrossPointSettings::clockUtcOffsetQ, {0, 104, 1},
"clockUtcOffsetQ", StrId::STR_CUSTOMISE_STATUS_BAR), "clockUtcOffsetQ", StrId::STR_CUSTOMISE_STATUS_BAR),
SettingInfo::Enum(StrId::STR_CLOCK_FORMAT, &CrossPointSettings::clockFormat, SettingInfo::Enum(StrId::STR_CLOCK_FORMAT, &CrossPointSettings::clockFormat,
@@ -77,6 +77,9 @@ const StrId titleNames[TITLE_ITEMS] = {StrId::STR_BOOK, StrId::STR_CHAPTER, StrI
constexpr int XTC_STATUS_BAR_ITEMS = 3; constexpr int XTC_STATUS_BAR_ITEMS = 3;
const StrId xtcStatusBarNames[XTC_STATUS_BAR_ITEMS] = {StrId::STR_HIDE, StrId::STR_BOTTOM, StrId::STR_TOP}; const StrId xtcStatusBarNames[XTC_STATUS_BAR_ITEMS] = {StrId::STR_HIDE, StrId::STR_BOTTOM, StrId::STR_TOP};
constexpr int STATUS_BAR_CLOCK_ITEMS = 3;
const StrId statusBarClockNames[STATUS_BAR_CLOCK_ITEMS] = {StrId::STR_HIDE, StrId::STR_DIR_RIGHT, StrId::STR_DIR_LEFT};
const int verticalPreviewPadding = 50; const int verticalPreviewPadding = 50;
const int verticalPreviewTextPadding = 40; const int verticalPreviewTextPadding = 40;
} // namespace } // namespace
@@ -112,6 +115,10 @@ void StatusBarSettingsActivity::onEnter() {
SETTINGS.clockFormat = 0; SETTINGS.clockFormat = 0;
} }
if (SETTINGS.statusBarClock >= STATUS_BAR_CLOCK_ITEMS) {
SETTINGS.statusBarClock = CrossPointSettings::STATUS_BAR_CLOCK_MODE::STATUS_BAR_CLOCK_HIDE;
}
requestUpdate(); requestUpdate();
} }
@@ -176,7 +183,7 @@ void StatusBarSettingsActivity::handleSelection() {
SETTINGS.xtcStatusBarMode = (SETTINGS.xtcStatusBarMode + 1) % XTC_STATUS_BAR_ITEMS; SETTINGS.xtcStatusBarMode = (SETTINGS.xtcStatusBarMode + 1) % XTC_STATUS_BAR_ITEMS;
break; break;
case ITEM_CLOCK: case ITEM_CLOCK:
SETTINGS.statusBarClock = (SETTINGS.statusBarClock + 1) % 2; SETTINGS.statusBarClock = (SETTINGS.statusBarClock + 1) % STATUS_BAR_CLOCK_ITEMS;
break; break;
case ITEM_CLOCK_FORMAT: case ITEM_CLOCK_FORMAT:
SETTINGS.clockFormat = (SETTINGS.clockFormat + 1) % CLOCK_FORMAT_ITEMS; SETTINGS.clockFormat = (SETTINGS.clockFormat + 1) % CLOCK_FORMAT_ITEMS;
@@ -225,7 +232,7 @@ void StatusBarSettingsActivity::render(RenderLock&&) {
case ITEM_XTC_STATUS_BAR: case ITEM_XTC_STATUS_BAR:
return I18N.get(xtcStatusBarNames[SETTINGS.xtcStatusBarMode]); return I18N.get(xtcStatusBarNames[SETTINGS.xtcStatusBarMode]);
case ITEM_CLOCK: case ITEM_CLOCK:
return SETTINGS.statusBarClock ? tr(STR_SHOW) : tr(STR_HIDE); return I18N.get(statusBarClockNames[SETTINGS.statusBarClock]);
case ITEM_CLOCK_FORMAT: { case ITEM_CLOCK_FORMAT: {
const uint8_t fmt = SETTINGS.clockFormat < CLOCK_FORMAT_ITEMS ? SETTINGS.clockFormat : 0; const uint8_t fmt = SETTINGS.clockFormat < CLOCK_FORMAT_ITEMS ? SETTINGS.clockFormat : 0;
return std::string(I18N.get(clockFormatNames[fmt])); return std::string(I18N.get(clockFormatNames[fmt]));
+4 -3
View File
@@ -131,9 +131,10 @@ int UITheme::getStatusBarHeight() {
const ThemeMetrics& metrics = UITheme::getInstance().getMetrics(); const ThemeMetrics& metrics = UITheme::getInstance().getMetrics();
// Add status bar margin // Add status bar margin
const bool showStatusBar = SETTINGS.statusBarChapterPageCount || SETTINGS.statusBarBookProgressPercentage || const bool showStatusBar =
SETTINGS.statusBarTitle != CrossPointSettings::STATUS_BAR_TITLE::HIDE_TITLE || SETTINGS.statusBarChapterPageCount || SETTINGS.statusBarBookProgressPercentage ||
SETTINGS.statusBarBattery; SETTINGS.statusBarTitle != CrossPointSettings::STATUS_BAR_TITLE::HIDE_TITLE || SETTINGS.statusBarBattery ||
SETTINGS.statusBarClock != CrossPointSettings::STATUS_BAR_CLOCK_MODE::STATUS_BAR_CLOCK_HIDE;
const bool showProgressBar = const bool showProgressBar =
SETTINGS.statusBarProgressBar != CrossPointSettings::STATUS_BAR_PROGRESS_BAR::HIDE_PROGRESS; SETTINGS.statusBarProgressBar != CrossPointSettings::STATUS_BAR_PROGRESS_BAR::HIDE_PROGRESS;
return (showStatusBar ? (metrics.statusBarVerticalMargin) : 0) + return (showStatusBar ? (metrics.statusBarVerticalMargin) : 0) +
+34 -20
View File
@@ -759,7 +759,11 @@ void BaseTheme::drawStatusBar(GfxRenderer& renderer, const float bookProgress, c
// Draw Progress Text // Draw Progress Text
const auto screenHeight = renderer.getScreenHeight(); const auto screenHeight = renderer.getScreenHeight();
auto textY = screenHeight - UITheme::getInstance().getStatusBarHeight() - orientedMarginBottom - paddingBottom - 4; auto textY = screenHeight - UITheme::getInstance().getStatusBarHeight() - orientedMarginBottom - paddingBottom - 4;
int progressTextWidth = 0;
const int leftClusterX = metrics.statusBarHorizontalMargin + orientedMarginLeft + 1;
const int rightClusterX = renderer.getScreenWidth() - metrics.statusBarHorizontalMargin - orientedMarginRight;
int leftClusterWidth = 0;
int rightClusterWidth = 0;
if (SETTINGS.statusBarBookProgressPercentage || SETTINGS.statusBarChapterPageCount) { if (SETTINGS.statusBarBookProgressPercentage || SETTINGS.statusBarChapterPageCount) {
// Right aligned text for progress counter // Right aligned text for progress counter
@@ -773,11 +777,10 @@ void BaseTheme::drawStatusBar(GfxRenderer& renderer, const float bookProgress, c
snprintf(progressStr, sizeof(progressStr), "%d/%d", currentPage, pageCount); snprintf(progressStr, sizeof(progressStr), "%d/%d", currentPage, pageCount);
} }
progressTextWidth = renderer.getTextWidth(SMALL_FONT_ID, progressStr); int progressTextWidth = renderer.getTextWidth(SMALL_FONT_ID, progressStr);
renderer.drawText( renderer.drawText(SMALL_FONT_ID, rightClusterX - progressTextWidth, textY, progressStr);
SMALL_FONT_ID,
renderer.getScreenWidth() - metrics.statusBarHorizontalMargin - orientedMarginRight - progressTextWidth, textY, rightClusterWidth += progressTextWidth;
progressStr);
} }
// Draw Progress Bar // Draw Progress Bar
@@ -801,34 +804,46 @@ void BaseTheme::drawStatusBar(GfxRenderer& renderer, const float bookProgress, c
} }
// Draw Bookmark // Draw Bookmark
const int leftClusterX = metrics.statusBarHorizontalMargin + orientedMarginLeft + 1; if (showStatusBarTextLane && isPageBookmarked) {
const bool showBookmarkIcon = showStatusBarTextLane && isPageBookmarked;
const int bookmarkReserveWidth = showBookmarkIcon ? (bookmarkStatusIconWidth + bookmarkStatusIconGap) : 0;
if (showBookmarkIcon) {
const int bookmarkY = textY + 5; const int bookmarkY = textY + 5;
drawBookmarkStatusIcon(renderer, leftClusterX, bookmarkY); drawBookmarkStatusIcon(renderer, leftClusterX, bookmarkY);
leftClusterWidth += bookmarkStatusIconWidth + bookmarkStatusIconGap;
} }
// Draw Battery // Draw Battery
const bool showBatteryPercentage = const bool showBatteryPercentage =
SETTINGS.hideBatteryPercentage == CrossPointSettings::HIDE_BATTERY_PERCENTAGE::HIDE_NEVER; SETTINGS.hideBatteryPercentage == CrossPointSettings::HIDE_BATTERY_PERCENTAGE::HIDE_NEVER;
int leftClusterWidth = bookmarkReserveWidth;
if (SETTINGS.statusBarBattery) { if (SETTINGS.statusBarBattery) {
GUI.drawBatteryLeft(renderer, GUI.drawBatteryLeft(renderer,
Rect{leftClusterX + bookmarkReserveWidth, textY, metrics.batteryWidth, metrics.batteryHeight}, Rect{leftClusterX + leftClusterWidth, textY, metrics.batteryWidth, metrics.batteryHeight},
showBatteryPercentage); showBatteryPercentage);
leftClusterWidth += showBatteryPercentage ? 50 : 20; int batteryWidth = metrics.batteryWidth;
if (showBatteryPercentage) {
const uint16_t percentage = powerManager.getBatteryPercentage();
// width of icon + spacing + text for layout purposes
batteryWidth +=
batteryPercentSpacing + renderer.getTextWidth(SMALL_FONT_ID, (std::to_string(percentage) + "%").c_str());
}
leftClusterWidth += batteryWidth;
} }
// Draw Clock (X3 only — DS3231 RTC) // Draw Clock (X3 only — DS3231 RTC)
int clockTextWidth = 0;
if (SETTINGS.statusBarClock && halClock.isAvailable()) { if (SETTINGS.statusBarClock && halClock.isAvailable()) {
char timeBuf[9]; char timeBuf[9];
if (halClock.formatTime(timeBuf, sizeof(timeBuf), SETTINGS.clockUtcOffsetQ, SETTINGS.clockFormat == 1)) { if (halClock.formatTime(timeBuf, sizeof(timeBuf), SETTINGS.clockUtcOffsetQ, SETTINGS.clockFormat == 1)) {
clockTextWidth = renderer.getTextWidth(SMALL_FONT_ID, timeBuf); int clockTextWidth = renderer.getTextWidth(SMALL_FONT_ID, timeBuf);
// Position to the left of the progress text (with a small gap) int clockX = 0;
const int clockX = renderer.getScreenWidth() - metrics.statusBarHorizontalMargin - orientedMarginRight - // Position to the left or right of the progress text (with a small gap)
progressTextWidth - (progressTextWidth > 0 ? 10 : 0) - clockTextWidth; if (SETTINGS.statusBarClock == CrossPointSettings::STATUS_BAR_CLOCK_LEFT) {
clockX = leftClusterX + leftClusterWidth + (leftClusterWidth > 0 ? 10 : 0);
leftClusterWidth += clockTextWidth + 10;
} else if (SETTINGS.statusBarClock == CrossPointSettings::STATUS_BAR_CLOCK_RIGHT) {
clockX = rightClusterX - rightClusterWidth - (rightClusterWidth > 0 ? 10 : 0) - clockTextWidth;
rightClusterWidth += clockTextWidth + 10;
}
renderer.drawText(SMALL_FONT_ID, clockX, textY, timeBuf); renderer.drawText(SMALL_FONT_ID, clockX, textY, timeBuf);
} }
} }
@@ -842,8 +857,7 @@ void BaseTheme::drawStatusBar(GfxRenderer& renderer, const float bookProgress, c
renderer.getScreenWidth() - (metrics.statusBarHorizontalMargin * 2) - orientedMarginLeft - orientedMarginRight; renderer.getScreenWidth() - (metrics.statusBarHorizontalMargin * 2) - orientedMarginLeft - orientedMarginRight;
const int titleMarginLeft = leftClusterWidth + 30; const int titleMarginLeft = leftClusterWidth + 30;
const int clockReserve = clockTextWidth > 0 ? (clockTextWidth + 10) : 0; const int titleMarginRight = rightClusterWidth + 30;
const int titleMarginRight = progressTextWidth + clockReserve + 30;
// Attempt to center title on the screen, but if title is too wide then later we will center it within the // Attempt to center title on the screen, but if title is too wide then later we will center it within the
// available space. // available space.