Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

theme: Adds very basic theme support. #112

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ add_executable(${PROJECT_NAME}
Sources/sntpClient.cpp
Sources/subAppRouter.cpp
Sources/subsystems.cpp
Sources/theme.cpp
Sources/timing.cpp
Sources/timeMenu.cpp
Sources/videoMenu.cpp
3 changes: 2 additions & 1 deletion Includes/config.hpp
Original file line number Diff line number Diff line change
@@ -133,7 +133,7 @@ void from_json(nlohmann::json const& j, homescreenConfig& o);

class Settings {
public:
Settings() = default;
std::string activeThemeDirectory{ "default" };
#ifdef NXDK
netConfig net;
sntpConfig sntp;
@@ -154,6 +154,7 @@ class Config {

void setChanged();
void storeToDisk();

Settings settings;
nlohmann::json menu;
};
3 changes: 2 additions & 1 deletion Includes/renderer.hpp
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
#define RENDERER_H

#include <SDL.h>
#include <string>
#include <vector>

int min(int lhs, int rhs);
@@ -13,7 +14,7 @@ class Renderer {
~Renderer();

int init();
int init(const char* bg);
int init(std::string const& backgroundImagePath);
int clear();
void flip();

58 changes: 58 additions & 0 deletions Includes/theme.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef NEVOLUTIONX_THEME_H
#define NEVOLUTIONX_THEME_H

#include <string>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type"
#include "../3rdparty/json.hpp"
#pragma clang diagnostic pop


class Theme {
public:
struct MenuTheme {
std::string font;
// TODO: Actually support this in Font.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: font not Font

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure I was referring to the Font class, so I think the capitalization is correct. Making it "font" would be ambiguous with the member var just above.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also sounds good

unsigned int fontColor;
};

struct ImageSet {
std::string image480p;
std::string image720p;
};

explicit Theme(std::string themeDirectory);

void setTitle(std::string const& val) { title = val; }
std::string const& getTitle() const { return title; }

void setBackground(ImageSet const& val) { background = val; }
ImageSet const& getBackground() const { return background; }

void setMenu(MenuTheme const& val) { menu = val; }
MenuTheme const& getMenu() const { return menu; }

std::string getAbsolutePath(std::string const& subpath) const {
return rootPath + subpath;
}

private:
void load();

std::string rootPath;
std::string title{ "??MISSING??" };
ImageSet background;
MenuTheme menu;
};

void to_json(nlohmann::json& j, Theme const& o);
void from_json(nlohmann::json const& j, Theme& o);

void to_json(nlohmann::json& j, Theme::MenuTheme const& o);
void from_json(nlohmann::json const& j, Theme::MenuTheme& o);

void to_json(nlohmann::json& j, Theme::ImageSet const& o);
void from_json(nlohmann::json const& j, Theme::ImageSet& o);

#endif // NEVOLUTIONX_THEME_H
14 changes: 10 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ SRCS += \
$(SRCDIR)/sntpClient.cpp \
$(SRCDIR)/subAppRouter.cpp \
$(SRCDIR)/subsystems.cpp \
$(SRCDIR)/theme.cpp \
$(SRCDIR)/timeMenu.cpp \
$(SRCDIR)/timing.cpp \
$(SRCDIR)/videoMenu.cpp \
@@ -46,12 +47,17 @@ CFLAGS += -O2
CXXFLAGS += -O2
endif

new_all: copy_resources all

include $(NXDK_DIR)/Makefile

copy_resources: $(OUTPUT_DIR)/config.json
@cp $(RESOURCEDIR)/480.png $(RESOURCEDIR)/720.png $(RESOURCEDIR)/vegur.ttf $(OUTPUT_DIR)
RESOURCES = \
$(OUTPUT_DIR)/config.json \
$(patsubst $(CURDIR)/Resources/%,$(OUTPUT_DIR)/%,$(wildcard $(CURDIR)/Resources/NeXThemes/*))
TARGET += $(RESOURCES)
$(GEN_XISO): $(RESOURCES)

$(OUTPUT_DIR)/NeXThemes/%: $(CURDIR)/Resources/NeXThemes/%
$(VE)mkdir -p '$(dir $@)'
$(VE)cp -r '$<' '$@'

$(OUTPUT_DIR)/config.json: $(CURDIR)/sampleconfig.json
@mkdir -p $(OUTPUT_DIR)
File renamed without changes
File renamed without changes
11 changes: 11 additions & 0 deletions Resources/NeXThemes/default/theme.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"title": "Default",
"background": {
"480": "480.png",
"720": "720.png"
},
"menu": {
"font": "vegur.ttf",
"font_color": "FFFFFF"
}
}
File renamed without changes.
8 changes: 6 additions & 2 deletions Sources/config.cpp
Original file line number Diff line number Diff line change
@@ -212,16 +212,20 @@ void from_json(nlohmann::json const& j, homescreenConfig& o) {
}

void to_json(nlohmann::json& j, Settings const& o) {
j = nlohmann::json{ { "ftp", nlohmann::json(o.ftp) },
j = nlohmann::json{ { "active_theme_directory", o.activeThemeDirectory },
{ "ftp", nlohmann::json(o.ftp) },
{ "mount", nlohmann::json(o.mount) },
#ifdef NXDK
{ "network", nlohmann::json(o.net) },
#endif
{ "logging", nlohmann::json(o.logging) },
{ "homescreenConfig", nlohmann::json(o.homescreen) } };
{ "homescreen", nlohmann::json(o.homescreen) } };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: specific reason why this was changed? Listing it as config may make it easier for outside devs to understand.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been a long time, but looking a few lines down at line 246 it's specifically looking for "homescreen" when reading the config file, so I think saving the config would always cause the default values to be used.

It also strikes me as more consistent to use "homescreen" in the same way that "logging", etc... is used rather than "loggingConfig".

Copy link

@MasonT8198 MasonT8198 Mar 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: Sounds Good, voice to text is really losing today

}

void from_json(nlohmann::json const& j, Settings& o) {
if (j.contains("active_theme_directory")) {
o.activeThemeDirectory = j["active_theme_directory"];
}
if (j.contains("ftp")) {
o.ftp = j["ftp"].get<ftpConfig>();
}
7 changes: 2 additions & 5 deletions Sources/renderer.cpp
Original file line number Diff line number Diff line change
@@ -59,15 +59,12 @@ int Renderer::init() {
return 0;
}

int Renderer::init(const char* bgpath) {
int Renderer::init(std::string const& backgroundImagePath) {
int ret = init();
if (ret != 0) {
return ret;
}
char* bgname = (char*)malloc(strlen(bgpath) + 10);
sprintf(bgname, "%s%d.png", bgpath, height);
SDL_Surface* bgsurf = IMG_Load(bgname);
free(bgname);
SDL_Surface* bgsurf = IMG_Load(backgroundImagePath.c_str());
if (bgsurf == nullptr) {
InfoLog::outputLine(InfoLog::ERROR, "Creating background surface failed.\n");
return 3;
74 changes: 74 additions & 0 deletions Sources/theme.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "theme.hpp"
#include <fstream>
#include <utility>

#define THEME_JSON_FILE_NAME "theme.json"

Theme::Theme(std::string themeDirectory) : rootPath(std::move(themeDirectory)) {
if (rootPath.back() != '\\') {
rootPath += "\\";
}
load();
}

void Theme::load() {
std::string themeFilePath = rootPath + THEME_JSON_FILE_NAME;

std::ifstream themeFile(themeFilePath);
nlohmann::json json;
// FIXME: Once nxdk supports C++ Exceptions, this needs to be put in a try-catch block!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is supported now is it not?

themeFile >> json;
from_json(json, *this);

themeFile.close();
}

void to_json(nlohmann::json& j, Theme::MenuTheme const& o) {
char fontColor[16] = { 0 };
snprintf(fontColor, 15, "%X", o.fontColor);

j = nlohmann::json{ { "font", nlohmann::json(o.font) },
{ "font_color", nlohmann::json(fontColor) } };
}

void from_json(nlohmann::json const& j, Theme::MenuTheme& o) {
if (j.contains("font")) {
o.font = j["font"];
}
if (j.contains("font_color")) {
std::string const& colorString = j["font_color"];
sscanf(colorString.c_str(), "%X", &o.fontColor);
}
}

void to_json(nlohmann::json& j, Theme::ImageSet const& o) {
j = nlohmann::json{ { "480", nlohmann::json(o.image480p) },
{ "720", nlohmann::json(o.image720p) } };
}

void from_json(nlohmann::json const& j, Theme::ImageSet& o) {
if (j.contains("480")) {
o.image480p = j["480"];
}
if (j.contains("720")) {
o.image720p = j["720"];
}
}

void to_json(nlohmann::json& j, Theme const& o) {
j = nlohmann::json{ { "title", o.getTitle() },
{ "menu", nlohmann::json(o.getMenu()) },
{ "background", nlohmann::json(o.getBackground()) } };
}

void from_json(nlohmann::json const& j, Theme& o) {
if (j.contains("title")) {
o.setTitle(j["title"]);
}
if (j.contains("menu")) {
o.setMenu(j["menu"].get<Theme::MenuTheme>());
}
if (j.contains("background")) {
o.setBackground(j["background"].get<Theme::ImageSet>());
}
}
16 changes: 13 additions & 3 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
#include "sntpClient.hpp"
#include "subAppRouter.hpp"
#include "subsystems.hpp"
#include "theme.hpp"
#include "timeMenu.hpp"
#include "timing.hpp"

@@ -29,6 +30,12 @@
#define HOME "." SEPARATOR
#endif

static void initWithBackground(Renderer& r, Theme const& theme) {
auto const& imageSet = theme.getBackground();
std::string const& path = (r.getHeight() >= 720) ? imageSet.image720p
: imageSet.image480p;
r.init(theme.getAbsolutePath(path));
}

int main(void) {
#ifdef NXDK
@@ -45,6 +52,10 @@ int main(void) {
return init;
}

std::string themePath = "A:\\NeXThemes\\" + config.settings.activeThemeDirectory;
InfoLog::outputLine(InfoLog::INFO, "Loading theme from %s", themePath.c_str());
Theme activeTheme(themePath);

NetworkManager networkManager(config);
#ifdef NXDK
if (config.settings.net.getEnabled()) {
@@ -73,11 +84,10 @@ int main(void) {

// Create render system
Renderer r;
r.init(HOME);
initWithBackground(r, activeTheme);

// Load font
// FIXME: Font path should be read from theme
Font f(r, HOME "vegur.ttf");
Font f(r, activeTheme.getAbsolutePath(activeTheme.getMenu().font).c_str());

SubAppRouter& router = *SubAppRouter::getInstance();

1 change: 1 addition & 0 deletions sampleconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"settings":
{
"active_theme_directory": "default",
"network":
{
"enable": true,