143 lines
4.8 KiB
C++
143 lines
4.8 KiB
C++
#include "UITheme.h"
|
|
|
|
#include <FsHelpers.h>
|
|
#include <GfxRenderer.h>
|
|
#include <Logging.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "MappedInputManager.h"
|
|
#include "RecentBooksStore.h"
|
|
#include "components/themes/BaseTheme.h"
|
|
#include "components/themes/lyra/Lyra3CoversTheme.h"
|
|
#include "components/themes/lyra/LyraTheme.h"
|
|
|
|
namespace {
|
|
constexpr int SKIP_PAGE_MS = 700;
|
|
} // namespace
|
|
|
|
UITheme UITheme::instance;
|
|
|
|
UITheme::UITheme() {
|
|
auto themeType = static_cast<CrossPointSettings::UI_THEME>(SETTINGS.uiTheme);
|
|
setTheme(themeType);
|
|
}
|
|
|
|
void UITheme::reload() {
|
|
auto themeType = static_cast<CrossPointSettings::UI_THEME>(SETTINGS.uiTheme);
|
|
setTheme(themeType);
|
|
}
|
|
|
|
void UITheme::setTheme(CrossPointSettings::UI_THEME type) {
|
|
switch (type) {
|
|
case CrossPointSettings::UI_THEME::CLASSIC:
|
|
LOG_DBG("UI", "Using Classic theme");
|
|
currentTheme = std::make_unique<BaseTheme>();
|
|
currentMetrics = &BaseMetrics::values;
|
|
break;
|
|
case CrossPointSettings::UI_THEME::LYRA:
|
|
LOG_DBG("UI", "Using Lyra theme");
|
|
currentTheme = std::make_unique<LyraTheme>();
|
|
currentMetrics = &LyraMetrics::values;
|
|
break;
|
|
case CrossPointSettings::UI_THEME::LYRA_3_COVERS:
|
|
LOG_DBG("UI", "Using Lyra 3 Covers theme");
|
|
currentTheme = std::make_unique<Lyra3CoversTheme>();
|
|
currentMetrics = &Lyra3CoversMetrics::values;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int UITheme::getNumberOfItemsPerPage(const GfxRenderer& renderer, bool hasHeader, bool hasTabBar, bool hasButtonHints,
|
|
bool hasSubtitle) {
|
|
const ThemeMetrics& metrics = UITheme::getInstance().getMetrics();
|
|
const Rect contentRect = getContentRect(renderer, hasButtonHints, /*hasSideHints=*/false);
|
|
int reservedHeight = metrics.topPadding;
|
|
if (hasHeader) {
|
|
reservedHeight += metrics.headerHeight + metrics.verticalSpacing;
|
|
}
|
|
if (hasTabBar) {
|
|
reservedHeight += metrics.tabBarHeight;
|
|
}
|
|
if (hasButtonHints) {
|
|
reservedHeight += metrics.verticalSpacing;
|
|
}
|
|
const int availableHeight = contentRect.height - reservedHeight;
|
|
int rowHeight = hasSubtitle ? metrics.listWithSubtitleRowHeight : metrics.listRowHeight;
|
|
return availableHeight / rowHeight;
|
|
}
|
|
|
|
Rect UITheme::getContentRect(const GfxRenderer& renderer, bool hasBottomHints, bool hasSideHints) {
|
|
const ThemeMetrics& metrics = UITheme::getInstance().getMetrics();
|
|
const int bh = hasBottomHints ? metrics.buttonHintsHeight : 0;
|
|
const int sw = hasSideHints ? metrics.sideButtonHintsWidth : 0;
|
|
|
|
int top = 0, right = 0, bottom = 0, left = 0;
|
|
switch (renderer.getOrientation()) {
|
|
case GfxRenderer::Portrait:
|
|
bottom = bh;
|
|
right = sw;
|
|
break;
|
|
case GfxRenderer::PortraitInverted:
|
|
top = bh;
|
|
left = sw;
|
|
break;
|
|
case GfxRenderer::LandscapeClockwise:
|
|
left = bh;
|
|
bottom = sw;
|
|
break;
|
|
case GfxRenderer::LandscapeCounterClockwise:
|
|
right = bh;
|
|
top = sw;
|
|
break;
|
|
}
|
|
|
|
const int w = renderer.getScreenWidth();
|
|
const int h = renderer.getScreenHeight();
|
|
return Rect{left, top, w - left - right, h - top - bottom};
|
|
}
|
|
|
|
std::string UITheme::getCoverThumbPath(std::string coverBmpPath, int coverHeight) {
|
|
size_t pos = coverBmpPath.find("[HEIGHT]", 0);
|
|
if (pos != std::string::npos) {
|
|
coverBmpPath.replace(pos, 8, std::to_string(coverHeight));
|
|
}
|
|
return coverBmpPath;
|
|
}
|
|
|
|
UIIcon UITheme::getFileIcon(const std::string& filename) {
|
|
if (filename.back() == '/') {
|
|
return Folder;
|
|
}
|
|
if (FsHelpers::hasEpubExtension(filename) || FsHelpers::hasXtcExtension(filename)) {
|
|
return Book;
|
|
}
|
|
if (FsHelpers::hasTxtExtension(filename) || FsHelpers::hasMarkdownExtension(filename)) {
|
|
return Text;
|
|
}
|
|
if (FsHelpers::hasBmpExtension(filename)) {
|
|
return Image;
|
|
}
|
|
return File;
|
|
}
|
|
|
|
int UITheme::getStatusBarHeight() {
|
|
const ThemeMetrics& metrics = UITheme::getInstance().getMetrics();
|
|
|
|
// Add status bar margin
|
|
const bool showStatusBar = SETTINGS.statusBarChapterPageCount || SETTINGS.statusBarBookProgressPercentage ||
|
|
SETTINGS.statusBarTitle != CrossPointSettings::STATUS_BAR_TITLE::HIDE_TITLE ||
|
|
SETTINGS.statusBarBattery || (SETTINGS.useClock && SETTINGS.statusBarClock);
|
|
const bool showProgressBar =
|
|
SETTINGS.statusBarProgressBar != CrossPointSettings::STATUS_BAR_PROGRESS_BAR::HIDE_PROGRESS;
|
|
return (showStatusBar ? (metrics.statusBarVerticalMargin) : 0) +
|
|
(showProgressBar ? (((SETTINGS.statusBarProgressBarThickness + 1) * 2) + metrics.progressBarMarginTop) : 0);
|
|
}
|
|
|
|
int UITheme::getProgressBarHeight() {
|
|
const ThemeMetrics& metrics = UITheme::getInstance().getMetrics();
|
|
const bool showProgressBar =
|
|
SETTINGS.statusBarProgressBar != CrossPointSettings::STATUS_BAR_PROGRESS_BAR::HIDE_PROGRESS;
|
|
return (showProgressBar ? (((SETTINGS.statusBarProgressBarThickness + 1) * 2) + metrics.progressBarMarginTop) : 0);
|
|
}
|