Skip to content

Commit

Permalink
Theme selection in option menu (daid#2088)
Browse files Browse the repository at this point in the history
* Theme selection

* Remove dependency from canvas to preference manager, tradoff by static member

* Forgotten occurrence in main

* Change font when changing theme
  • Loading branch information
Tsht committed Oct 12, 2024
1 parent ac7459c commit ca51919
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 30 deletions.
3 changes: 1 addition & 2 deletions src/gui/gui2_canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
#include "gui2_element.h"
#include "theme.h"


GuiCanvas::GuiCanvas(RenderLayer* renderLayer)
: Renderable(renderLayer), click_element(nullptr), focus_element(nullptr)
{
enable_debug_rendering = false;
theme = GuiTheme::getTheme("default");
theme = GuiTheme::getCurrentTheme();
}

//due to a suspected compiler bug this deconstructor needs to be explicitly defined
Expand Down
25 changes: 23 additions & 2 deletions src/gui/theme.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "gui/theme.h"
#include "resources.h"
#include <io/keyValueTreeLoader.h>
#include <graphics/freetypefont.h>
#include <logging.h>


static std::unordered_map<string, sp::Font*> fonts;
std::unordered_map<string, GuiTheme*> GuiTheme::themes;
string GuiTheme::current_theme = "default";

static glm::u8vec4 toColor(const string& s)
{
Expand Down Expand Up @@ -44,7 +46,7 @@ const GuiThemeStyle* GuiTheme::getStyle(const string& element)
int n = element.rfind(".");
if (n == -1)
{
LOG(Warning, "Cannot find", element, "in theme", name);
LOG(Warning, "Cannot find ", element, " in theme ", name);
return getStyle("fallback");
}
return getStyle(element.substr(0, n));
Expand All @@ -60,10 +62,24 @@ GuiTheme* GuiTheme::getTheme(const string& name)
LOG(Error, "Default theme not found. Most likely crashing now.");
return nullptr;
}
LOG(Warning, "Theme", name, "not found. Falling back to [default] theme.");
LOG(Warning, "Theme ", name, " not found. Falling back to [default] theme.");
return getTheme("default");
}

void GuiTheme::setCurrentTheme(const string &theme_name)
{
if(themes.find(theme_name) != themes.end())
{
LOG(INFO, "Set theme to : ", theme_name);
GuiTheme::current_theme = theme_name;
}
}

GuiTheme* GuiTheme::getCurrentTheme()
{
return GuiTheme::getTheme(GuiTheme::current_theme);
}

bool GuiTheme::loadTheme(const string& name, const string& resource_name)
{
GuiTheme* theme = new GuiTheme(name);
Expand Down Expand Up @@ -133,6 +149,11 @@ GuiTheme::GuiTheme(const string& name)
fallback_state.color = {255, 255, 255, 255};
fallback_state.size = 12;
fallback_state.font = nullptr;
std::vector<string> fonts = findResources("gui/fonts/*.ttf");
if(fonts.size() > 0)
{
fallback_state.font = getFont(fonts[0]);
}
fallback_state.texture = "";
GuiThemeStyle fallback;
for(unsigned int n=0; n<int(GuiElement::State::COUNT); n++)
Expand Down
4 changes: 4 additions & 0 deletions src/gui/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class GuiTheme
const GuiThemeStyle* getStyle(const string& element);

static GuiTheme* getTheme(const string& name);
//Will return default theme if not found
static GuiTheme* getCurrentTheme();
static void setCurrentTheme(const string &name);
static bool loadTheme(const string& name, const string& resource_name);
private:
GuiTheme(const string& name);
Expand All @@ -55,6 +58,7 @@ class GuiTheme
std::unordered_map<string, GuiThemeStyle> styles;

static std::unordered_map<string, GuiTheme*> themes;
static string current_theme;
};

#endif//GUI_THEME_H
23 changes: 17 additions & 6 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,22 @@ int main(int argc, char** argv)
#endif
}

if (!GuiTheme::loadTheme("default", PreferencesManager::get("guitheme", "gui/default.theme.txt")))
//For now there is only one named theme : default.
string theme_name = PreferencesManager::get("guitheme", "default");
if (!GuiTheme::loadTheme(theme_name, "gui/" + theme_name +".theme.txt"))
{
LOG(ERROR, "Failed to load default theme, exiting.");
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Failed to load gui theme, resources missing?", nullptr);
return 1;
LOG(ERROR, "Failed to load "+ theme_name + " theme, trying default. Resources missing or contains errors ? Check gui/" + theme_name + ".theme.txt");
if (!GuiTheme::loadTheme("default", "gui/default.theme.txt"))
{
LOG(ERROR, "Failed to load default theme, exiting. Check gui/default.theme.txt"); //Yes, we may try to load twice default theme but this should be a rare error case which always finish in exit
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Failed to load gui theme, resources missing or contains errors ? Check gui/default.theme.txt", nullptr);
return 1;
}
GuiTheme::setCurrentTheme("default");
}
else
{
GuiTheme::setCurrentTheme(theme_name);
}

if (PreferencesManager::get("headless") == "")
Expand Down Expand Up @@ -337,8 +348,8 @@ int main(int argc, char** argv)
soundManager->setMusicVolume(PreferencesManager::get("music_volume", "50").toFloat());
soundManager->setMasterSoundVolume(PreferencesManager::get("sound_volume", "50").toFloat());

main_font = GuiTheme::getTheme("default")->getStyle("base")->states[0].font;
bold_font = GuiTheme::getTheme("default")->getStyle("bold")->states[0].font;
main_font = GuiTheme::getCurrentTheme()->getStyle("base")->states[0].font;
bold_font = GuiTheme::getCurrentTheme()->getStyle("bold")->states[0].font;
if (!main_font || !bold_font)
{
LOG(ERROR, "Missing font or bold font.");
Expand Down
98 changes: 78 additions & 20 deletions src/menus/optionsMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "soundManager.h"
#include "windowManager.h"

#include "gui/theme.h"
#include "gui/gui2_overlay.h"
#include "gui/gui2_button.h"
#include "gui/gui2_togglebutton.h"
Expand Down Expand Up @@ -104,36 +105,93 @@ OptionsMenu::OptionsMenu()
}))->setSize(GuiElement::GuiSizeMax, 50);

//Select the language
(new GuiLabel(interface_page, "LANGUAGE_OPTIONS_LABEL", tr("Language (applies on back)"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50)->layout.margin.top = 20;

std::vector<string> languages = findResources("locale/main.*.po");

for(string &language : languages)
{
//strip extension
language = language.substr(language.find(".") + 1, language.rfind("."));
}
std::sort(languages.begin(), languages.end());
(new GuiLabel(interface_page, "LANGUAGE_OPTIONS_LABEL", tr("Language (applies on back)"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50)->layout.margin.top = 20;

std::vector<string> languages = findResources("locale/main.*.po");

for(string &language : languages)
{
//strip extension
language = language.substr(language.find(".") + 1, language.rfind("."));
}
std::sort(languages.begin(), languages.end());

int default_index = 0;
auto default_elem = std::find(languages.begin(), languages.end(), PreferencesManager::get("language", "en"));
if(default_elem != languages.end())
{
default_index = static_cast<int>(default_elem - languages.begin());
int default_index = 0;
auto default_elem = std::find(languages.begin(), languages.end(), PreferencesManager::get("language", "en"));
if(default_elem != languages.end())
{
default_index = static_cast<int>(default_elem - languages.begin());
}

(new GuiSelector(interface_page, "LANGUAGE_SELECTOR", [](int index, string value)
{
i18n::reset();
i18n::load("locale/main." + value + ".po");
PreferencesManager::set("language", value);
keys.init(); // Reinit keyboard shortcut labels
}))->setOptions(languages)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50);
}

(new GuiSelector(interface_page, "LANGUAGE_SELECTOR", [](int index, string value)
//Gui theme selection
{
i18n::reset();
i18n::load("locale/main." + value + ".po");
PreferencesManager::set("language", value);
keys.init(); // Reinit keyboard shortcut labels
}))->setOptions(languages)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50);
(new GuiLabel(interface_page, "GUI_THEME_OPTIONS_LABEL", tr("Interface Theme"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50)->layout.margin.top = 20;

std::vector<string> themes = findResources("gui/*.theme.txt");

auto iter = themes.begin();
while(iter != themes.end())
{
//strip extension
*iter = iter->substr(iter->find("/")+1, iter->find("."));
if (!GuiTheme::loadTheme(*iter, "gui/" + *iter +".theme.txt"))
{
LOG(ERROR, "Failed to load theme : ", *iter);
iter = themes.erase(iter);
}
else if (!GuiTheme::getTheme(*iter)->getStyle("base")->states[0].font
|| !GuiTheme::getTheme(*iter)->getStyle("bold")->states[0].font)
{
LOG(ERROR, "Missing base font or bold font for theme : ", *iter);
iter = themes.erase(iter);
}
else
{
++iter;
}
}

std::sort(themes.begin(), themes.end());
if(0 == themes.size())
{
LOG(ERROR, "Failed to load any theme, exiting");
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Failed to load any theme, resources missing ? Should be gui/*.theme.txt. and not contain errors.", nullptr);
exit(1);
}

int default_index = 0;
auto default_elem = std::find(themes.begin(), themes.end(), PreferencesManager::get("guitheme", "default"));
if(default_elem != themes.end())
{
default_index = static_cast<int>(default_elem - themes.begin());
}

(new GuiSelector(interface_page, "GUI_THEME_SELECTOR", [](int index, string theme_name)
{
GuiTheme::setCurrentTheme(theme_name);
main_font = GuiTheme::getCurrentTheme()->getStyle("base")->states[0].font;
bold_font = GuiTheme::getCurrentTheme()->getStyle("bold")->states[0].font;
//Render default font is applied on back only
PreferencesManager::set("guitheme", theme_name);
}))->setOptions(themes)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50);
}

// Bottom GUI.
// Back button.
(new GuiButton(this, "BACK", tr("button", "Back"), [this]()
{
//Apply potentially modified font now, in order not to have some half rendered panel with one font and another
sp::RenderTarget::setDefaultFont(main_font);
// Close this menu, stop the music, and return to the main menu.
destroy();
soundManager->stopMusic();
Expand Down

0 comments on commit ca51919

Please sign in to comment.