mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-11-15 15:02:52 +01:00
189 lines
6.9 KiB
C++
189 lines
6.9 KiB
C++
#include <json.hpp>
|
|
#include <gui/theme_manager.h>
|
|
#include <imgui_internal.h>
|
|
#include <spdlog/spdlog.h>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
|
|
bool ThemeManager::loadThemesFromDir(std::string path) {
|
|
if (!std::filesystem::is_directory(path)) {
|
|
spdlog::error("Theme directory doesn't exist: {0}", path);
|
|
return false;
|
|
}
|
|
themes.clear();
|
|
for (const auto & file : std::filesystem::directory_iterator(path)) {
|
|
std::string _path = file.path().generic_string();
|
|
if (file.path().extension().generic_string() != ".json") {
|
|
continue;
|
|
}
|
|
loadTheme(_path);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ThemeManager::loadTheme(std::string path) {
|
|
if (!std::filesystem::is_regular_file(path)) {
|
|
spdlog::error("Theme file doesn't exist: {0}", path);
|
|
return false;
|
|
}
|
|
|
|
// Load defaults in theme
|
|
Theme thm;
|
|
thm.author = "--";
|
|
|
|
// Load JSON
|
|
std::ifstream file(path.c_str());
|
|
json data;
|
|
file >> data;
|
|
file.close();
|
|
|
|
// Load theme name
|
|
if (!data.contains("name")) {
|
|
spdlog::error("Theme {0} is missing the name parameter", path);
|
|
return false;
|
|
}
|
|
if (!data["name"].is_string()) {
|
|
spdlog::error("Theme {0} contains invalid name field. Expected string", path);
|
|
return false;
|
|
}
|
|
std::string name = data["name"];
|
|
|
|
// Load theme author if available
|
|
if (data.contains("author")) {
|
|
if (!data["author"].is_string()) {
|
|
spdlog::error("Theme {0} contains invalid author field. Expected string", path);
|
|
return false;
|
|
}
|
|
thm.author = data["author"];
|
|
}
|
|
|
|
// Iterate through all parameters and check their contents
|
|
std::map<std::string, std::string> params = data;
|
|
for (auto const& [param, val] : params) {
|
|
if (param == "name" || param == "author") { continue; }
|
|
|
|
bool isValid = false;
|
|
|
|
// If param is a color, check that it's a valid RGBA hex value
|
|
if (IMGUI_COL_IDS.find(param) != IMGUI_COL_IDS.end()) {
|
|
if (val[0] != '#' || !std::all_of(val.begin() + 1, val.end(), ::isxdigit) || val.length() != 9) {
|
|
spdlog::error("Theme {0} contains invalid {1} field. Expected hex RGBA color", path, param);
|
|
return false;
|
|
}
|
|
isValid = true;
|
|
}
|
|
|
|
if (!isValid) {
|
|
spdlog::error("Theme {0} contains unknown {1} field.", path, param);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
thm.data = data;
|
|
themes[name] = thm;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ThemeManager::applyTheme(std::string name) {
|
|
if (themes.find(name) == themes.end()) {
|
|
spdlog::error("Unknown theme: {0}", name);
|
|
return false;
|
|
}
|
|
|
|
ImGui::StyleColorsDark();
|
|
|
|
auto& style = ImGui::GetStyle();
|
|
|
|
style.WindowRounding = 0.0f;
|
|
style.ChildRounding = 0.0f;
|
|
style.FrameRounding = 0.0f;
|
|
style.GrabRounding = 0.0f;
|
|
style.PopupRounding = 0.0f;
|
|
style.ScrollbarRounding = 0.0f;
|
|
|
|
ImVec4* colors = style.Colors;
|
|
Theme thm = themes[name];
|
|
|
|
uint8_t ret[4];
|
|
std::map<std::string, std::string> params = thm.data;
|
|
for (auto const& [param, val] : params) {
|
|
if (param == "name" || param == "author") { continue; }
|
|
|
|
// If param is a color, check that it's a valid RGBA hex value
|
|
if (IMGUI_COL_IDS.find(param) != IMGUI_COL_IDS.end()) {
|
|
decodeRGBA(val, ret);
|
|
colors[IMGUI_COL_IDS[param]] = ImVec4((float)ret[0]/255.0f, (float)ret[1]/255.0f, (float)ret[2]/255.0f, (float)ret[3]/255.0f);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ThemeManager::decodeRGBA(std::string str, uint8_t out[4]) {
|
|
if (str[0] != '#' || !std::all_of(str.begin() + 1, str.end(), ::isxdigit) || str.length() != 9) {
|
|
return false;
|
|
}
|
|
out[0] = std::stoi(str.substr(1, 2), NULL, 16);
|
|
out[1] = std::stoi(str.substr(3, 2), NULL, 16);
|
|
out[2] = std::stoi(str.substr(5, 2), NULL, 16);
|
|
out[3] = std::stoi(str.substr(7, 2), NULL, 16);
|
|
return true;
|
|
}
|
|
|
|
std::map<std::string, int> ThemeManager::IMGUI_COL_IDS = {
|
|
{"Text", ImGuiCol_Text},
|
|
{"TextDisabled", ImGuiCol_TextDisabled},
|
|
{"WindowBg", ImGuiCol_WindowBg},
|
|
{"ChildBg", ImGuiCol_ChildBg},
|
|
{"PopupBg", ImGuiCol_PopupBg},
|
|
{"Border", ImGuiCol_Border},
|
|
{"BorderShadow", ImGuiCol_BorderShadow},
|
|
{"FrameBg", ImGuiCol_FrameBg},
|
|
{"FrameBgHovered", ImGuiCol_FrameBgHovered},
|
|
{"FrameBgActive", ImGuiCol_FrameBgActive},
|
|
{"TitleBg", ImGuiCol_TitleBg},
|
|
{"TitleBgActive", ImGuiCol_TitleBgActive},
|
|
{"TitleBgCollapsed", ImGuiCol_TitleBgCollapsed},
|
|
{"MenuBarBg", ImGuiCol_MenuBarBg},
|
|
{"ScrollbarBg", ImGuiCol_ScrollbarBg},
|
|
{"ScrollbarGrab", ImGuiCol_ScrollbarGrab},
|
|
{"ScrollbarGrabHovered", ImGuiCol_ScrollbarGrabHovered},
|
|
{"ScrollbarGrabActive", ImGuiCol_ScrollbarGrabActive},
|
|
{"CheckMark", ImGuiCol_CheckMark},
|
|
{"SliderGrab", ImGuiCol_SliderGrab},
|
|
{"SliderGrabActive", ImGuiCol_SliderGrabActive},
|
|
{"Button", ImGuiCol_Button},
|
|
{"ButtonHovered", ImGuiCol_ButtonHovered},
|
|
{"ButtonActive", ImGuiCol_ButtonActive},
|
|
{"Header", ImGuiCol_Header},
|
|
{"HeaderHovered", ImGuiCol_HeaderHovered},
|
|
{"HeaderActive", ImGuiCol_HeaderActive},
|
|
{"Separator", ImGuiCol_Separator},
|
|
{"SeparatorHovered", ImGuiCol_SeparatorHovered},
|
|
{"SeparatorActive", ImGuiCol_SeparatorActive},
|
|
{"ResizeGrip", ImGuiCol_ResizeGrip},
|
|
{"ResizeGripHovered", ImGuiCol_ResizeGripHovered},
|
|
{"ResizeGripActive", ImGuiCol_ResizeGripActive},
|
|
{"Tab", ImGuiCol_Tab},
|
|
{"TabHovered", ImGuiCol_TabHovered},
|
|
{"TabActive", ImGuiCol_TabActive},
|
|
{"TabUnfocused", ImGuiCol_TabUnfocused},
|
|
{"TabUnfocusedActive", ImGuiCol_TabUnfocusedActive},
|
|
{"PlotLines", ImGuiCol_PlotLines},
|
|
{"PlotLinesHovered", ImGuiCol_PlotLinesHovered},
|
|
{"PlotHistogram", ImGuiCol_PlotHistogram},
|
|
{"PlotHistogramHovered", ImGuiCol_PlotHistogramHovered},
|
|
{"TableHeaderBg", ImGuiCol_TableHeaderBg},
|
|
{"TableBorderStrong", ImGuiCol_TableBorderStrong},
|
|
{"TableBorderLight", ImGuiCol_TableBorderLight},
|
|
{"TableRowBg", ImGuiCol_TableRowBg},
|
|
{"TableRowBgAlt", ImGuiCol_TableRowBgAlt},
|
|
{"TextSelectedBg", ImGuiCol_TextSelectedBg},
|
|
{"DragDropTarget", ImGuiCol_DragDropTarget},
|
|
{"NavHighlight", ImGuiCol_NavHighlight},
|
|
{"NavWindowingHighlight", ImGuiCol_NavWindowingHighlight},
|
|
{"NavWindowingDimBg", ImGuiCol_NavWindowingDimBg},
|
|
{"ModalWindowDimBg", ImGuiCol_ModalWindowDimBg}
|
|
}; |