fix: set default theme to original crosspoint ui + add small font + battery icon

This commit is contained in:
Brackyt 2026-01-25 17:43:10 +01:00
parent ad2bea2122
commit 1fab1f9ec5
6 changed files with 285 additions and 707 deletions

View File

@ -440,4 +440,73 @@ public:
}
};
// --- BatteryIcon ---
class BatteryIcon : public UIElement {
Expression valueExpr;
Expression colorExpr;
public:
BatteryIcon(const std::string &id) : UIElement(id) {
valueExpr = Expression::parse("0");
colorExpr = Expression::parse("0x00"); // Black by default
}
ElementType getType() const override { return ElementType::BatteryIcon; }
void setValue(const std::string &expr) {
valueExpr = Expression::parse(expr);
markDirty();
}
void setColor(const std::string &expr) {
colorExpr = Expression::parse(expr);
markDirty();
}
void draw(const GfxRenderer &renderer, const ThemeContext &context) override {
if (!isVisible(context))
return;
std::string valStr = context.evaluatestring(valueExpr);
int percentage = valStr.empty() ? 0 : std::stoi(valStr);
std::string colStr = context.evaluatestring(colorExpr);
uint8_t color = Color::parse(colStr).value;
bool black = (color == 0x00);
constexpr int batteryWidth = 15;
constexpr int batteryHeight = 12;
int x = absX;
int y = absY;
if (absW > batteryWidth)
x += (absW - batteryWidth) / 2;
if (absH > batteryHeight)
y += (absH - batteryHeight) / 2;
renderer.drawLine(x + 1, y, x + batteryWidth - 3, y, black);
renderer.drawLine(x + 1, y + batteryHeight - 1, x + batteryWidth - 3,
y + batteryHeight - 1, black);
renderer.drawLine(x, y + 1, x, y + batteryHeight - 2, black);
renderer.drawLine(x + batteryWidth - 2, y + 1, x + batteryWidth - 2,
y + batteryHeight - 2, black);
renderer.drawPixel(x + batteryWidth - 1, y + 3, black);
renderer.drawPixel(x + batteryWidth - 1, y + batteryHeight - 4, black);
renderer.drawLine(x + batteryWidth - 0, y + 4, x + batteryWidth - 0,
y + batteryHeight - 5, black);
if (percentage > 0) {
int filledWidth = percentage * (batteryWidth - 5) / 100 + 1;
if (filledWidth > batteryWidth - 5) {
filledWidth = batteryWidth - 5;
}
renderer.fillRect(x + 2, y + 2, filledWidth, batteryHeight - 4, black);
}
markClean();
}
};
} // namespace ThemeEngine

View File

@ -1,13 +1,23 @@
#pragma once
constexpr const char *DEFAULT_THEME_INI = R"(
// Default theme - matches the original CrossPoint Reader look
// This is embedded in the firmware as a fallback
namespace ThemeEngine {
// Use static function for C++14 ODR compatibility
static const char *getDefaultThemeIni() {
static const char *theme = R"INI(
; ============================================
; Default Theme for CrossPoint Reader
; DEFAULT THEME - Original CrossPoint Reader
; ============================================
; Screen: 480x800
; Layout: Centered book card + vertical menu list
[Global]
FontUI12 = UI_12
FontUI10 = UI_10
NavBookCount = 1
; ============================================
; HOME SCREEN
@ -17,429 +27,252 @@ FontUI10 = UI_10
Type = Container
X = 0
Y = 0
Width = 100%
Height = 100%
Color = white
Width = 480
Height = 800
BgColor = white
; --- Status Bar ---
[StatusBar]
; --- Battery (top right) ---
[BatteryWrapper]
Parent = Home
Type = Container
X = 0
Y = 10
Width = 100%
Height = 24
[BatteryContainer]
Parent = StatusBar
Type = Container
X = 400
Y = 3
Width = 28
Height = 18
Y = 10
Width = 80
Height = 20
[BatteryIcon]
Parent = BatteryContainer
Type = Icon
Src = battery
Parent = BatteryWrapper
Type = BatteryIcon
X = 0
Y = 0
Width = 28
Height = 18
Y = 5
Width = 15
Height = 20
Value = {BatteryPercent}
Color = black
; Fill bar inside the battery (positioned inside the battery outline)
[BatteryFill]
Parent = BatteryContainer
Type = ProgressBar
X = 2
Y = 4
Width = 20
Height = 10
Value = {BatteryPercent}
Max = 100
FgColor = black
BgColor = white
ShowBorder = false
[BatteryLabel]
Parent = StatusBar
[BatteryText]
Parent = BatteryWrapper
Type = Label
Font = UI_10
Font = Small
Text = {BatteryPercent}%
X = 432
Y = 3
Width = 48
Height = 18
X = 22
Y = 0
Width = 50
Height = 20
Align = Left
Visible = {ShowBatteryPercent}
; --- Recent Books Section ---
[RecentBooksSection]
; --- Book Card (centered) ---
; Original: 240x400 at (120, 30)
[BookCard]
Parent = Home
Type = Container
X = 0
X = 120
Y = 30
Width = 100%
Height = 280
Visible = {HasRecentBooks}
Width = 240
Height = 400
Border = true
BgColor = {IsBookSelected ? "black" : "white"}
Visible = {HasBook}
[RecentBooksList]
Parent = RecentBooksSection
Type = List
Source = RecentBooks
ItemTemplate = RecentBookItem
X = 10
Y = 0
Width = 460
Height = 280
Direction = Horizontal
ItemWidth = 149
ItemHeight = 270
Spacing = 8
; --- Recent Book Item Template ---
; Based on mockup: 74.5px at 240px scale = 149px at 480px
[RecentBookItem]
; Bookmark ribbon decoration (when no cover)
[BookmarkRibbon]
Parent = BookCard
Type = Container
Width = 149
Height = 270
Padding = 8
BgColor = {Item.Selected ? "0xD9" : "white"}
BorderRadius = 12
X = 200
Y = 5
Width = 30
Height = 60
BgColor = {IsBookSelected ? "white" : "black"}
Visible = {!HasCover}
[BookCoverImage]
Parent = RecentBookItem
Type = Bitmap
X = 0
Y = 0
Width = 133
Height = 190
Src = {Item.Image}
[BookmarkNotch]
Parent = BookmarkRibbon
Type = Container
X = 10
Y = 45
Width = 10
Height = 15
BgColor = {IsBookSelected ? "black" : "white"}
[BookProgressBadge]
Parent = RecentBookItem
Type = Badge
X = 4
Y = 224
Text = {Item.Progress}%
Font = UI_10
BgColor = black
FgColor = white
PaddingH = 6
PaddingV = 3
[BookTitleLabel]
Parent = RecentBookItem
Type = Label
Font = UI_10
Text = {Item.Title}
X = 0
Y = 196
Width = 133
Height = 22
Ellipsis = true
; --- No Recent Books State ---
[EmptyBooksMessage]
Parent = Home
; Title centered in card
[BookTitle]
Parent = BookCard
Type = Label
Font = UI_12
Text = No recent books
Centered = true
X = 0
Y = 100
Width = 480
Height = 30
Visible = {!HasRecentBooks}
Text = {BookTitle}
X = 20
Y = 150
Width = 200
Height = 60
Color = {IsBookSelected ? "white" : "black"}
Align = center
Ellipsis = true
[EmptyBooksSub]
Parent = Home
[BookAuthor]
Parent = BookCard
Type = Label
Font = UI_10
Text = Open a book to start reading
Centered = true
X = 0
Y = 130
Width = 480
Height = 30
Visible = {!HasRecentBooks}
Text = {BookAuthor}
X = 20
Y = 210
Width = 200
Height = 25
Color = {IsBookSelected ? "white" : "black"}
Align = center
Ellipsis = true
; --- Main Menu (2-column grid) ---
[MainMenuList]
; "Continue Reading" at bottom of card
[ContinueLabel]
Parent = BookCard
Type = Label
Font = UI_10
Text = Continue Reading
X = 20
Y = 365
Width = 200
Height = 25
Color = {IsBookSelected ? "white" : "black"}
Align = center
; --- No Book Message ---
[NoBookCard]
Parent = Home
Type = Container
X = 120
Y = 30
Width = 240
Height = 400
Border = true
Visible = {!HasBook}
[NoBookTitle]
Parent = NoBookCard
Type = Label
Font = UI_12
Text = No open book
X = 20
Y = 175
Width = 200
Height = 25
Align = center
[NoBookSubtitle]
Parent = NoBookCard
Type = Label
Font = UI_10
Text = Start reading below
X = 20
Y = 205
Width = 200
Height = 25
Align = center
; --- Menu List ---
; Original: margin=20, tileWidth=440, tileHeight=45, spacing=8
; menuStartY = 30 + 400 + 15 = 445
[MenuList]
Parent = Home
Type = List
Source = MainMenu
ItemTemplate = MainMenuItem
X = 15
Y = 330
Width = 450
Height = 350
Columns = 2
ItemHeight = 70
Spacing = 20
ItemTemplate = MenuItem
X = 20
Y = 445
Width = 440
Height = 280
Direction = Vertical
ItemHeight = 45
Spacing = 8
; --- Menu Item Template ---
[MainMenuItem]
Type = HStack
Width = 210
Height = 65
Spacing = 12
CenterVertical = true
Padding = 16
BgColor = {Item.Selected ? "0xD9" : "white"}
BorderRadius = 12
[MenuItemIcon]
Parent = MainMenuItem
Type = Icon
Src = {Item.Icon}
Width = 36
Height = 36
Color = black
[MenuItem]
Type = Container
Width = 440
Height = 45
BgColor = {Item.Selected ? "black" : "white"}
Border = true
[MenuItemLabel]
Parent = MainMenuItem
Parent = MenuItem
Type = Label
Font = UI_12
Font = UI_10
Text = {Item.Title}
Width = 150
Height = 40
Color = black
X = 0
Y = 0
Width = 440
Height = 45
Color = {Item.Selected ? "white" : "black"}
Align = center
; --- Bottom Navigation Bar ---
; Positioned at the very bottom of screen, buttons align with physical buttons
[NavBar]
; --- Button Hints (bottom) ---
; Original: 4 buttons at [25, 130, 245, 350], width=106, height=40
; Y = pageHeight - 40 = 760
[HintBtn2]
Parent = Home
Type = Container
X = 0
Y = 776
Width = 100%
Height = 24
; Left button group (OK and Back) - aligned with left physical buttons
[NavLeftGroup]
Parent = NavBar
Type = HStack
X = 120
Y = 0
Width = 168
Height = 24
Spacing = 8
[NavBtnBack]
Parent = NavLeftGroup
Type = Container
Width = 80
Height = 8
Border = true
BorderRadius = 8
[NavBtnOK]
Parent = NavLeftGroup
Type = Container
Width = 80
Height = 24
Border = true
BorderRadius = 8
[NavBtnOKIcon]
Parent = NavBtnOK
Type = Icon
Src = check
X = 30
Y = 6
Width = 20
Height = 12
; Right button group (Up and Down) - aligned with right physical buttons
[NavRightGroup]
Parent = NavBar
Type = HStack
X = 292
Y = 0
Width = 168
Height = 24
Spacing = 8
[NavBtnUp]
Parent = NavRightGroup
Type = Container
Width = 80
Height = 24
Border = true
BorderRadius = 8
[NavBtnUpIcon]
Parent = NavBtnUp
Type = Icon
Src = up
X = 30
Y = 6
Width = 20
Height = 12
[NavBtnDown]
Parent = NavRightGroup
Type = Container
Width = 80
Height = 24
Border = true
BorderRadius = 8
[NavBtnDownIcon]
Parent = NavBtnDown
Type = Icon
Src = down
X = 30
Y = 6
Width = 20
Height = 12
; ============================================
; SETTINGS SCREEN
; ============================================
[Settings]
Type = Container
X = 0
Y = 0
Width = 100%
Height = 100%
Color = white
[SettingsTitle]
Parent = Settings
Type = Label
Font = UI_12
Text = Settings
X = 15
Y = 15
Width = 200
Height = 30
[SettingsTabBar]
Parent = Settings
Type = TabBar
X = 0
Y = 50
Width = 100%
X = 130
Y = 760
Width = 106
Height = 40
Selected = {SelectedTab}
IndicatorHeight = 3
ShowIndicator = true
BgColor = white
Border = true
[TabReading]
Parent = SettingsTabBar
[HintBtn2Label]
Parent = HintBtn2
Type = Label
Font = UI_10
Text = Reading
Centered = true
Height = 35
[TabControls]
Parent = SettingsTabBar
Type = Label
Font = UI_10
Text = Controls
Centered = true
Height = 35
[TabDisplay]
Parent = SettingsTabBar
Type = Label
Font = UI_10
Text = Display
Centered = true
Height = 35
[TabSystem]
Parent = SettingsTabBar
Type = Label
Font = UI_10
Text = System
Centered = true
Height = 35
[SettingsList]
Parent = Settings
Type = List
Source = SettingsItems
ItemTemplate = SettingsItem
Text = Confirm
X = 0
Y = 95
Width = 450
Height = 650
ItemHeight = 50
Spacing = 0
Y = 0
Width = 106
Height = 40
Align = center
[SettingsScrollIndicator]
Parent = Settings
Type = ScrollIndicator
X = 460
Y = 100
Width = 15
Height = 640
Position = {ScrollPosition}
Total = {TotalItems}
VisibleCount = {VisibleItems}
TrackWidth = 4
; --- Settings Item Template ---
[SettingsItem]
[HintBtn3]
Parent = Home
Type = Container
Width = 450
Height = 48
Border = false
X = 245
Y = 760
Width = 106
Height = 40
BgColor = white
Border = true
[SettingsItemBg]
Parent = SettingsItem
Type = Rectangle
[HintBtn3Label]
Parent = HintBtn3
Type = Label
Font = UI_10
Text = Up
X = 0
Y = 0
Width = 450
Height = 45
Fill = {Item.Selected}
Color = black
Width = 106
Height = 40
Align = center
[SettingsItemLabel]
Parent = SettingsItem
[HintBtn4]
Parent = Home
Type = Container
X = 350
Y = 760
Width = 106
Height = 40
BgColor = white
Border = true
[HintBtn4Label]
Parent = HintBtn4
Type = Label
Font = UI_10
Text = {Item.Title}
X = 15
Text = Down
X = 0
Y = 0
Width = 250
Height = 45
Color = {Item.Selected ? white : black}
Width = 106
Height = 40
Align = center
[SettingsItemValue]
Parent = SettingsItem
Type = Label
Font = UI_10
Text = {Item.Value}
X = 270
Y = 0
Width = 120
Height = 45
Align = Right
Color = {Item.Selected ? white : black}
)INI";
return theme;
}
[SettingsItemToggle]
Parent = SettingsItem
Type = Toggle
X = 390
Y = 8
Width = 50
Height = 30
Value = {Item.ToggleValue}
Visible = {Item.HasToggle}
[SettingsItemDivider]
Parent = SettingsItem
Type = Divider
X = 15
Y = 46
Width = 420
Height = 1
Horizontal = true
Color = 0x80
)";
} // namespace ThemeEngine

View File

@ -153,6 +153,7 @@ public:
Toggle,
TabBar,
Icon,
BatteryIcon,
ScrollIndicator
};

View File

@ -63,6 +63,8 @@ UIElement *ThemeManager::createElement(const std::string &id,
return new Icon(id);
if (type == "ScrollIndicator")
return new ScrollIndicator(id);
if (type == "BatteryIcon")
return new BatteryIcon(id);
return nullptr;
}
@ -115,6 +117,8 @@ void ThemeManager::applyProperties(
static_cast<Divider *>(elem)->setColorExpr(val);
} else if (elemType == UIElement::ElementType::Icon) {
static_cast<Icon *>(elem)->setColorExpr(val);
} else if (elemType == UIElement::ElementType::BatteryIcon) {
static_cast<BatteryIcon *>(elem)->setColor(val);
}
}
@ -273,6 +277,8 @@ void ThemeManager::applyProperties(
static_cast<ProgressBar *>(elem)->setValue(val);
} else if (elemType == UIElement::ElementType::Toggle) {
static_cast<Toggle *>(elem)->setValue(val);
} else if (elemType == UIElement::ElementType::BatteryIcon) {
static_cast<BatteryIcon *>(elem)->setValue(val);
}
} else if (key == "Max") {
if (elemType == UIElement::ElementType::ProgressBar) {

View File

@ -1,332 +0,0 @@
; ============================================
; Default Theme for CrossPoint Reader
; ============================================
;
; ELEMENT TYPES:
; Container - Basic container for grouping elements
; HStack - Horizontal stack layout
; VStack - Vertical stack layout
; Grid - Grid layout with columns
; Rectangle - Rectangle (filled or outlined)
; Label - Text display
; Bitmap - Image display (BMP files)
; Icon - Built-in icons or small images
; List - Repeating items (vertical, horizontal, or grid)
; Badge - Small text overlay/tag
; Toggle - On/off switch
; TabBar - Tab selection bar
; ProgressBar - Progress indicator
; Divider - Horizontal/vertical line
; ScrollIndicator - Scroll position indicator
;
; BUILT-IN ICONS:
; heart, book, books, folder, files, settings, gear,
; transfer, send, library, device, battery, check,
; back, left, up, down
;
; EXPRESSIONS:
; {Variable} - Variable substitution
; {!Variable} - Boolean negation
; {A && B} - Boolean AND
; {A || B} - Boolean OR
; {A == B} - Equality
; {A != B} - Inequality
; {A < B}, {A > B} - Comparisons
; {Cond ? True : False} - Ternary
;
; DIMENSIONS:
; 100 - Absolute pixels
; 50% - Percentage of parent
;
; COLORS:
; 0x00, black - Black
; 0xFF, white - White
[Global]
FontUI12 = UI_12
FontUI10 = UI_10
; ============================================
; HOME SCREEN
; ============================================
[Home]
Type = Container
X = 0
Y = 0
Width = 100%
Height = 100%
Color = white
; --- Status Bar ---
[StatusBar]
Parent = Home
Type = Container
X = 0
Y = 10
Width = 100%
Height = 24
[BatteryContainer]
Parent = StatusBar
Type = Container
X = 400
Y = 3
Width = 28
Height = 18
[BatteryIcon]
Parent = BatteryContainer
Type = Icon
Src = battery
X = 0
Y = 0
Width = 28
Height = 18
Color = black
; Fill bar inside the battery (positioned inside the battery outline)
[BatteryFill]
Parent = BatteryContainer
Type = ProgressBar
X = 2
Y = 4
Width = 20
Height = 10
Value = {BatteryPercent}
Max = 100
FgColor = black
BgColor = white
ShowBorder = false
[BatteryLabel]
Parent = StatusBar
Type = Label
Font = UI_10
Text = {BatteryPercent}%
X = 432
Y = 3
Width = 48
Height = 18
; --- Recent Books Section ---
[RecentBooksSection]
Parent = Home
Type = Container
X = 0
Y = 30
Width = 100%
Height = 280
Visible = {HasRecentBooks}
[RecentBooksList]
Parent = RecentBooksSection
Type = List
Source = RecentBooks
ItemTemplate = RecentBookItem
X = 10
Y = 0
Width = 460
Height = 280
Direction = Horizontal
ItemWidth = 149
ItemHeight = 270
Spacing = 8
; --- Recent Book Item Template ---
; Based on mockup: 74.5px at 240px scale = 149px at 480px
[RecentBookItem]
Type = Container
Width = 149
Height = 270
Padding = 8
BgColor = {Item.Selected ? "0xD9" : "white"}
BorderRadius = 12
[BookCoverImage]
Parent = RecentBookItem
Type = Bitmap
X = 0
Y = 0
Width = 133
Height = 190
Src = {Item.Image}
[BookProgressBadge]
Parent = RecentBookItem
Type = Badge
X = 4
Y = 224
Text = {Item.Progress}%
Font = UI_10
BgColor = black
FgColor = white
PaddingH = 6
PaddingV = 3
[BookTitleLabel]
Parent = RecentBookItem
Type = Label
Font = UI_10
Text = {Item.Title}
X = 0
Y = 196
Width = 133
Height = 22
Ellipsis = true
; --- No Recent Books State ---
[EmptyBooksMessage]
Parent = Home
Type = Label
Font = UI_12
Text = No recent books
Centered = true
X = 0
Y = 100
Width = 480
Height = 30
Visible = {!HasRecentBooks}
[EmptyBooksSub]
Parent = Home
Type = Label
Font = UI_10
Text = Open a book to start reading
Centered = true
X = 0
Y = 130
Width = 480
Height = 30
Visible = {!HasRecentBooks}
; --- Main Menu (2-column grid) ---
[MainMenuList]
Parent = Home
Type = List
Source = MainMenu
ItemTemplate = MainMenuItem
X = 15
Y = 330
Width = 450
Height = 350
Columns = 2
ItemHeight = 70
Spacing = 20
; --- Menu Item Template ---
[MainMenuItem]
Type = HStack
Width = 210
Height = 65
Spacing = 12
CenterVertical = true
Padding = 16
BgColor = {Item.Selected ? "0xD9" : "white"}
BorderRadius = 12
[MenuItemIcon]
Parent = MainMenuItem
Type = Icon
Src = {Item.Icon}
Width = 36
Height = 36
Color = black
[MenuItemLabel]
Parent = MainMenuItem
Type = Label
Font = UI_12
Text = {Item.Title}
Width = 150
Height = 40
Color = black
; --- Bottom Navigation Bar ---
; Positioned at the very bottom of screen, buttons align with physical buttons
[NavBar]
Parent = Home
Type = Container
X = 0
Y = 776
Width = 100%
Height = 24
; Left button group (OK and Back) - aligned with left physical buttons
[NavLeftGroup]
Parent = NavBar
Type = HStack
X = 120
Y = 0
Width = 168
Height = 24
Spacing = 8
[NavBtnBack]
Parent = NavLeftGroup
Type = Container
Width = 80
Height = 8
Border = true
BorderRadius = 8
[NavBtnOK]
Parent = NavLeftGroup
Type = Container
Width = 80
Height = 24
Border = true
BorderRadius = 8
[NavBtnOKIcon]
Parent = NavBtnOK
Type = Icon
Src = check
X = 30
Y = 6
Width = 20
Height = 12
; Right button group (Up and Down) - aligned with right physical buttons
[NavRightGroup]
Parent = NavBar
Type = HStack
X = 292
Y = 0
Width = 168
Height = 24
Spacing = 8
[NavBtnUp]
Parent = NavRightGroup
Type = Container
Width = 80
Height = 24
Border = true
BorderRadius = 8
[NavBtnUpIcon]
Parent = NavBtnUp
Type = Icon
Src = up
X = 30
Y = 6
Width = 20
Height = 12
[NavBtnDown]
Parent = NavRightGroup
Type = Container
Width = 80
Height = 24
Border = true
BorderRadius = 8
[NavBtnDownIcon]
Parent = NavBtnDown
Type = Icon
Src = down
X = 30
Y = 6
Width = 20
Height = 12

View File

@ -344,6 +344,7 @@ void setup() {
ThemeEngine::ThemeManager::get().begin();
ThemeEngine::ThemeManager::get().registerFont("UI_12", UI_12_FONT_ID);
ThemeEngine::ThemeManager::get().registerFont("UI_10", UI_10_FONT_ID);
ThemeEngine::ThemeManager::get().registerFont("Small", SMALL_FONT_ID);
ThemeEngine::ThemeManager::get().loadTheme(SETTINGS.themeName);
exitActivity();