mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-12-25 02:18:30 +01:00
Added persistant menu open/close
This commit is contained in:
parent
ed83abaeef
commit
1dbdf48e9a
@ -119,16 +119,31 @@ int sdrpp_main(int argc, char *argv[]) {
|
|||||||
defConfig["fullWaterfallUpdate"] = false;
|
defConfig["fullWaterfallUpdate"] = false;
|
||||||
defConfig["max"] = 0.0;
|
defConfig["max"] = 0.0;
|
||||||
defConfig["maximized"] = false;
|
defConfig["maximized"] = false;
|
||||||
defConfig["menuOrder"] = {
|
|
||||||
"Source",
|
// Menu
|
||||||
"Radio",
|
defConfig["menuElements"] = json::array();
|
||||||
"Recorder",
|
|
||||||
"Sinks",
|
defConfig["menuElements"][0]["name"] = "Source";
|
||||||
"Audio",
|
defConfig["menuElements"][0]["open"] = true;
|
||||||
"Scripting",
|
|
||||||
"Band Plan",
|
defConfig["menuElements"][1]["name"] = "Radio";
|
||||||
"Display"
|
defConfig["menuElements"][1]["open"] = true;
|
||||||
};
|
|
||||||
|
defConfig["menuElements"][2]["name"] = "Recorder";
|
||||||
|
defConfig["menuElements"][2]["open"] = true;
|
||||||
|
|
||||||
|
defConfig["menuElements"][3]["name"] = "Sinks";
|
||||||
|
defConfig["menuElements"][3]["open"] = true;
|
||||||
|
|
||||||
|
defConfig["menuElements"][4]["name"] = "Scripting";
|
||||||
|
defConfig["menuElements"][4]["open"] = false;
|
||||||
|
|
||||||
|
defConfig["menuElements"][5]["name"] = "Band Plan";
|
||||||
|
defConfig["menuElements"][5]["open"] = true;
|
||||||
|
|
||||||
|
defConfig["menuElements"][6]["name"] = "Display";
|
||||||
|
defConfig["menuElements"][6]["open"] = true;
|
||||||
|
|
||||||
defConfig["menuWidth"] = 300;
|
defConfig["menuWidth"] = 300;
|
||||||
defConfig["min"] = -120.0;
|
defConfig["min"] = -120.0;
|
||||||
|
|
||||||
@ -169,14 +184,24 @@ int sdrpp_main(int argc, char *argv[]) {
|
|||||||
core::configManager.load(defConfig);
|
core::configManager.load(defConfig);
|
||||||
core::configManager.enableAutoSave();
|
core::configManager.enableAutoSave();
|
||||||
|
|
||||||
// Fix config
|
|
||||||
core::configManager.aquire();
|
core::configManager.aquire();
|
||||||
|
// Fix missing elements in config
|
||||||
for (auto const& item : defConfig.items()) {
|
for (auto const& item : defConfig.items()) {
|
||||||
if (!core::configManager.conf.contains(item.key())) {
|
if (!core::configManager.conf.contains(item.key())) {
|
||||||
spdlog::warn("Missing key in config {0}, repairing", item.key());
|
spdlog::warn("Missing key in config {0}, repairing", item.key());
|
||||||
core::configManager.conf[item.key()] = defConfig[item.key()];
|
core::configManager.conf[item.key()] = defConfig[item.key()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove unused elements
|
||||||
|
auto items = core::configManager.conf.items();
|
||||||
|
for (auto const& item : items) {
|
||||||
|
if (!defConfig.contains(item.key())) {
|
||||||
|
spdlog::warn("Unused key in config {0}, repairing", item.key());
|
||||||
|
core::configManager.conf.erase(item.key());
|
||||||
|
}
|
||||||
|
}
|
||||||
core::configManager.release(true);
|
core::configManager.release(true);
|
||||||
|
|
||||||
// Setup window
|
// Setup window
|
||||||
|
@ -112,11 +112,24 @@ void windowInit() {
|
|||||||
credits::init();
|
credits::init();
|
||||||
|
|
||||||
core::configManager.aquire();
|
core::configManager.aquire();
|
||||||
gui::menu.order = core::configManager.conf["menuOrder"].get<std::vector<std::string>>();
|
json menuElements = core::configManager.conf["menuElements"];
|
||||||
std::string modulesDir = core::configManager.conf["modulesDirectory"];
|
std::string modulesDir = core::configManager.conf["modulesDirectory"];
|
||||||
std::string resourcesDir = core::configManager.conf["resourcesDirectory"];
|
std::string resourcesDir = core::configManager.conf["resourcesDirectory"];
|
||||||
core::configManager.release();
|
core::configManager.release();
|
||||||
|
|
||||||
|
// Load menu elements
|
||||||
|
gui::menu.order.clear();
|
||||||
|
for (auto& elem : menuElements) {
|
||||||
|
if (!elem.contains("name")) { spdlog::error("Menu element is missing name key"); continue; }
|
||||||
|
if (!elem["name"].is_string()) { spdlog::error("Menu element name isn't a string"); continue; }
|
||||||
|
if (!elem.contains("open")) { spdlog::error("Menu element is missing open key"); continue; }
|
||||||
|
if (!elem["open"].is_boolean()) { spdlog::error("Menu element name isn't a string"); continue; }
|
||||||
|
Menu::MenuOption_t opt;
|
||||||
|
opt.name = elem["name"];
|
||||||
|
opt.open = elem["open"];
|
||||||
|
gui::menu.order.push_back(opt);
|
||||||
|
}
|
||||||
|
|
||||||
gui::menu.registerEntry("Source", sourecmenu::draw, NULL);
|
gui::menu.registerEntry("Source", sourecmenu::draw, NULL);
|
||||||
gui::menu.registerEntry("Sinks", sinkmenu::draw, NULL);
|
gui::menu.registerEntry("Sinks", sinkmenu::draw, NULL);
|
||||||
gui::menu.registerEntry("Scripting", scriptingmenu::draw, NULL);
|
gui::menu.registerEntry("Scripting", scriptingmenu::draw, NULL);
|
||||||
@ -541,7 +554,16 @@ void drawWindow() {
|
|||||||
ImGui::BeginChild("Left Column");
|
ImGui::BeginChild("Left Column");
|
||||||
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
|
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
|
||||||
|
|
||||||
gui::menu.draw();
|
if (gui::menu.draw()) {
|
||||||
|
core::configManager.aquire();
|
||||||
|
json arr = json::array();
|
||||||
|
for (int i = 0; i < gui::menu.order.size(); i++) {
|
||||||
|
arr[i]["name"] = gui::menu.order[i].name;
|
||||||
|
arr[i]["open"] = gui::menu.order[i].open;
|
||||||
|
}
|
||||||
|
core::configManager.conf["menuElements"] = arr;
|
||||||
|
core::configManager.release(true);
|
||||||
|
}
|
||||||
|
|
||||||
if(ImGui::CollapsingHeader("Debug")) {
|
if(ImGui::CollapsingHeader("Debug")) {
|
||||||
ImGui::Text("Frame time: %.3f ms/frame", 1000.0 / ImGui::GetIO().Framerate);
|
ImGui::Text("Frame time: %.3f ms/frame", 1000.0 / ImGui::GetIO().Framerate);
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
using nlohmann::json;
|
|
||||||
|
|
||||||
bool ThemeManager::loadThemesFromDir(std::string path) {
|
bool ThemeManager::loadThemesFromDir(std::string path) {
|
||||||
if (!std::filesystem::is_directory(path)) {
|
if (!std::filesystem::is_directory(path)) {
|
||||||
spdlog::error("Theme directory doesn't exist: {0}", path);
|
spdlog::error("Theme directory doesn't exist: {0}", path);
|
||||||
@ -31,6 +29,7 @@ bool ThemeManager::loadTheme(std::string path) {
|
|||||||
|
|
||||||
// Load defaults in theme
|
// Load defaults in theme
|
||||||
Theme thm;
|
Theme thm;
|
||||||
|
thm.author = "--";
|
||||||
|
|
||||||
// Load JSON
|
// Load JSON
|
||||||
std::ifstream file(path.c_str());
|
std::ifstream file(path.c_str());
|
||||||
@ -38,61 +37,50 @@ bool ThemeManager::loadTheme(std::string path) {
|
|||||||
file >> data;
|
file >> data;
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// Load theme
|
// Load theme name
|
||||||
uint8_t val[4];
|
if (!data.contains("name")) {
|
||||||
if (data.contains("Text")) { if (decodeRGBA(data["Text"], val)) { thm.Text = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
spdlog::error("Theme {0} is missing the name parameter", path);
|
||||||
if (data.contains("TextDisabled")) { if (decodeRGBA(data["TextDisabled"], val)) { thm.TextDisabled = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
return false;
|
||||||
if (data.contains("WindowBg")) { if (decodeRGBA(data["WindowBg"], val)) { thm.WindowBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("ChildBg")) { if (decodeRGBA(data["ChildBg"], val)) { thm.ChildBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
if (!data["name"].is_string()) {
|
||||||
if (data.contains("PopupBg")) { if (decodeRGBA(data["PopupBg"], val)) { thm.PopupBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
spdlog::error("Theme {0} contains invalid name field. Expected string", path);
|
||||||
if (data.contains("Border")) { if (decodeRGBA(data["Border"], val)) { thm.Border = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
return false;
|
||||||
if (data.contains("BorderShadow")) { if (decodeRGBA(data["BorderShadow"], val)) { thm.BorderShadow = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("FrameBg")) { if (decodeRGBA(data["FrameBg"], val)) { thm.FrameBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
std::string name = data["name"];
|
||||||
if (data.contains("FrameBgHovered")) { if (decodeRGBA(data["FrameBgHovered"], val)) { thm.FrameBgHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("FrameBgActive")) { if (decodeRGBA(data["FrameBgActive"], val)) { thm.FrameBgActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
// Load theme author if available
|
||||||
if (data.contains("TitleBg")) { if (decodeRGBA(data["TitleBg"], val)) { thm.TitleBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
if (data.contains("author")) {
|
||||||
if (data.contains("TitleBgActive")) { if (decodeRGBA(data["TitleBgActive"], val)) { thm.TitleBgActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
if (!data["author"].is_string()) {
|
||||||
if (data.contains("TitleBgCollapsed")) { if (decodeRGBA(data["TitleBgCollapsed"], val)) { thm.TitleBgCollapsed = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
spdlog::error("Theme {0} contains invalid author field. Expected string", path);
|
||||||
if (data.contains("MenuBarBg")) { if (decodeRGBA(data["MenuBarBg"], val)) { thm.MenuBarBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
return false;
|
||||||
if (data.contains("ScrollbarBg")) { if (decodeRGBA(data["ScrollbarBg"], val)) { thm.ScrollbarBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("ScrollbarGrab")) { if (decodeRGBA(data["ScrollbarGrab"], val)) { thm.ScrollbarGrab = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
thm.author = data["author"];
|
||||||
if (data.contains("ScrollbarGrabHovered")) { if (decodeRGBA(data["ScrollbarGrabHovered"], val)) { thm.ScrollbarGrabHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("ScrollbarGrabActive")) { if (decodeRGBA(data["ScrollbarGrabActive"], val)) { thm.ScrollbarGrabActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("CheckMark")) { if (decodeRGBA(data["CheckMark"], val)) { thm.CheckMark = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
// Iterate through all parameters and check their contents
|
||||||
if (data.contains("SliderGrab")) { if (decodeRGBA(data["SliderGrab"], val)) { thm.SliderGrab = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
std::map<std::string, std::string> params = data;
|
||||||
if (data.contains("TeSliderGrabActivext")) { if (decodeRGBA(data["SliderGrabActive"], val)) { thm.SliderGrabActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
for (auto const& [param, val] : params) {
|
||||||
if (data.contains("Button")) { if (decodeRGBA(data["Button"], val)) { thm.Button = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
if (param == "name" || param == "author") { continue; }
|
||||||
if (data.contains("ButtonHovered")) { if (decodeRGBA(data["ButtonHovered"], val)) { thm.ButtonHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("ButtonActive")) { if (decodeRGBA(data["ButtonActive"], val)) { thm.ButtonActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
bool isValid = false;
|
||||||
if (data.contains("Header")) { if (decodeRGBA(data["Header"], val)) { thm.Header = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("HeaderHovered")) { if (decodeRGBA(data["HeaderHovered"], val)) { thm.HeaderHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
// If param is a color, check that it's a valid RGBA hex value
|
||||||
if (data.contains("HeaderActive")) { if (decodeRGBA(data["HeaderActive"], val)) { thm.HeaderActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
if (IMGUI_COL_IDS.find(param) != IMGUI_COL_IDS.end()) {
|
||||||
if (data.contains("Separator")) { if (decodeRGBA(data["Separator"], val)) { thm.Separator = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
if (val[0] != '#' || !std::all_of(val.begin() + 1, val.end(), ::isxdigit) || val.length() != 9) {
|
||||||
if (data.contains("SeparatorHovered")) { if (decodeRGBA(data["SeparatorHovered"], val)) { thm.SeparatorHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
spdlog::error("Theme {0} contains invalid {1} field. Expected hex RGBA color", path, param);
|
||||||
if (data.contains("SeparatorActive")) { if (decodeRGBA(data["SeparatorActive"], val)) { thm.SeparatorActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
return false;
|
||||||
if (data.contains("ResizeGrip")) { if (decodeRGBA(data["ResizeGrip"], val)) { thm.ResizeGrip = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("ResizeGripHovered")) { if (decodeRGBA(data["ResizeGripHovered"], val)) { thm.ResizeGripHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
isValid = true;
|
||||||
if (data.contains("ResizeGripActive")) { if (decodeRGBA(data["ResizeGripActive"], val)) { thm.ResizeGripActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("Tab")) { if (decodeRGBA(data["Tab"], val)) { thm.Tab = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("TabHovered")) { if (decodeRGBA(data["TabHovered"], val)) { thm.TabHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
if (!isValid) {
|
||||||
if (data.contains("TabActive")) { if (decodeRGBA(data["TabActive"], val)) { thm.TabActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
spdlog::error("Theme {0} contains unknown {1} field.", path, param);
|
||||||
if (data.contains("TabUnfocused")) { if (decodeRGBA(data["TabUnfocused"], val)) { thm.TabUnfocused = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
return false;
|
||||||
if (data.contains("TabUnfocusedActive")) { if (decodeRGBA(data["TabUnfocusedActive"], val)) { thm.TabUnfocusedActive = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("PlotLines")) { if (decodeRGBA(data["PlotLines"], val)) { thm.PlotLines = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
}
|
||||||
if (data.contains("PlotLinesHovered")) { if (decodeRGBA(data["PlotLinesHovered"], val)) { thm.PlotLinesHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("PlotHistogram")) { if (decodeRGBA(data["PlotHistogram"], val)) { thm.PlotHistogram = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
thm.data = data;
|
||||||
if (data.contains("PlotHistogramHovered")) { if (decodeRGBA(data["PlotHistogramHovered"], val)) { thm.PlotHistogramHovered = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
themes[name] = thm;
|
||||||
if (data.contains("TableHeaderBg")) { if (decodeRGBA(data["TableHeaderBg"], val)) { thm.TableHeaderBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("TableBorderStrong")) { if (decodeRGBA(data["TableBorderStrong"], val)) { thm.TableBorderStrong = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("TableBorderLight")) { if (decodeRGBA(data["TableBorderLight"], val)) { thm.TableBorderLight = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("TableRowBg")) { if (decodeRGBA(data["TableRowBg"], val)) { thm.TableRowBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("TableRowBgAlt")) { if (decodeRGBA(data["TableRowBgAlt"], val)) { thm.TableRowBgAlt = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("TextSelectedBg")) { if (decodeRGBA(data["TextSelectedBg"], val)) { thm.TextSelectedBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("DragDropTarget")) { if (decodeRGBA(data["DragDropTarget"], val)) { thm.DragDropTarget = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("NavHighlight")) { if (decodeRGBA(data["NavHighlight"], val)) { thm.NavHighlight = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("NavWindowingHighlight")) { if (decodeRGBA(data["NavWindowingHighlight"], val)) { thm.NavWindowingHighlight = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("NavWindowingDimBg")) { if (decodeRGBA(data["NavWindowingDimBg"], val)) { thm.NavWindowingDimBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
if (data.contains("ModalWindowDimBg")) { if (decodeRGBA(data["ModalWindowDimBg"], val)) { thm.ModalWindowDimBg = ImVec4((float)val[0]/255.0f, (float)val[1]/255.0f, (float)val[2]/255.0f, (float)val[3]/255.0f); } }
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -103,62 +91,32 @@ bool ThemeManager::applyTheme(std::string name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
auto& style = ImGui::GetStyle();
|
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;
|
ImVec4* colors = style.Colors;
|
||||||
Theme thm = themes[name];
|
Theme thm = themes[name];
|
||||||
colors[ImGuiCol_Text] = thm.Text;
|
|
||||||
colors[ImGuiCol_TextDisabled] = thm.TextDisabled;
|
uint8_t ret[4];
|
||||||
colors[ImGuiCol_WindowBg] = thm.WindowBg;
|
std::map<std::string, std::string> params = thm.data;
|
||||||
colors[ImGuiCol_ChildBg] = thm.ChildBg;
|
for (auto const& [param, val] : params) {
|
||||||
colors[ImGuiCol_PopupBg] = thm.PopupBg;
|
if (param == "name" || param == "author") { continue; }
|
||||||
colors[ImGuiCol_Border] = thm.Border;
|
|
||||||
colors[ImGuiCol_BorderShadow] = thm.BorderShadow;
|
// If param is a color, check that it's a valid RGBA hex value
|
||||||
colors[ImGuiCol_FrameBg] = thm.FrameBg;
|
if (IMGUI_COL_IDS.find(param) != IMGUI_COL_IDS.end()) {
|
||||||
colors[ImGuiCol_FrameBgHovered] = thm.FrameBgHovered;
|
decodeRGBA(val, ret);
|
||||||
colors[ImGuiCol_FrameBgActive] = thm.FrameBgActive;
|
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);
|
||||||
colors[ImGuiCol_TitleBg] = thm.TitleBg;
|
continue;
|
||||||
colors[ImGuiCol_TitleBgActive] = thm.TitleBgActive;
|
}
|
||||||
colors[ImGuiCol_TitleBgCollapsed] = thm.TitleBgCollapsed;
|
}
|
||||||
colors[ImGuiCol_MenuBarBg] = thm.MenuBarBg;
|
|
||||||
colors[ImGuiCol_ScrollbarBg] = thm.ScrollbarBg;
|
|
||||||
colors[ImGuiCol_ScrollbarGrab] = thm.ScrollbarGrab;
|
|
||||||
colors[ImGuiCol_ScrollbarGrabHovered] = thm.ScrollbarGrabHovered;
|
|
||||||
colors[ImGuiCol_ScrollbarGrabActive] = thm.ScrollbarGrabActive;
|
|
||||||
colors[ImGuiCol_CheckMark] = thm.CheckMark;
|
|
||||||
colors[ImGuiCol_SliderGrab] = thm.SliderGrab;
|
|
||||||
colors[ImGuiCol_SliderGrabActive] = thm.SliderGrabActive;
|
|
||||||
colors[ImGuiCol_Button] = thm.Button;
|
|
||||||
colors[ImGuiCol_ButtonHovered] = thm.ButtonHovered;
|
|
||||||
colors[ImGuiCol_ButtonActive] = thm.ButtonActive;
|
|
||||||
colors[ImGuiCol_Header] = thm.Header;
|
|
||||||
colors[ImGuiCol_HeaderHovered] = thm.HeaderHovered;
|
|
||||||
colors[ImGuiCol_HeaderActive] = thm.HeaderActive;
|
|
||||||
colors[ImGuiCol_Separator] = thm.Separator;
|
|
||||||
colors[ImGuiCol_SeparatorHovered] = thm.SeparatorHovered;
|
|
||||||
colors[ImGuiCol_SeparatorActive] = thm.SeparatorActive;
|
|
||||||
colors[ImGuiCol_ResizeGrip] = thm.ResizeGrip;
|
|
||||||
colors[ImGuiCol_ResizeGripHovered] = thm.ResizeGripHovered;
|
|
||||||
colors[ImGuiCol_ResizeGripActive] = thm.ResizeGripActive;
|
|
||||||
colors[ImGuiCol_Tab] = thm.Tab;
|
|
||||||
colors[ImGuiCol_TabHovered] = thm.TabHovered;
|
|
||||||
colors[ImGuiCol_TabActive] = thm.TabActive;
|
|
||||||
colors[ImGuiCol_TabUnfocused] = thm.TabUnfocused;
|
|
||||||
colors[ImGuiCol_TabUnfocusedActive] = thm.TabUnfocusedActive;
|
|
||||||
colors[ImGuiCol_PlotLines] = thm.PlotLines;
|
|
||||||
colors[ImGuiCol_PlotLinesHovered] = thm.PlotLinesHovered;
|
|
||||||
colors[ImGuiCol_PlotHistogram] = thm.PlotHistogram;
|
|
||||||
colors[ImGuiCol_PlotHistogramHovered] = thm.PlotHistogramHovered;
|
|
||||||
colors[ImGuiCol_TableHeaderBg] = thm.TableHeaderBg;
|
|
||||||
colors[ImGuiCol_TableBorderStrong] = thm.TableBorderStrong;
|
|
||||||
colors[ImGuiCol_TableBorderLight] = thm.TableBorderLight;
|
|
||||||
colors[ImGuiCol_TableRowBg] = thm.TableRowBg;
|
|
||||||
colors[ImGuiCol_TableRowBgAlt] = thm.TableRowBgAlt;
|
|
||||||
colors[ImGuiCol_TextSelectedBg] = thm.TextSelectedBg;
|
|
||||||
colors[ImGuiCol_DragDropTarget] = thm.DragDropTarget;
|
|
||||||
colors[ImGuiCol_NavHighlight] = thm.NavHighlight;
|
|
||||||
colors[ImGuiCol_NavWindowingHighlight] = thm.NavWindowingHighlight;
|
|
||||||
colors[ImGuiCol_NavWindowingDimBg] = thm.NavWindowingDimBg;
|
|
||||||
colors[ImGuiCol_ModalWindowDimBg] = thm.ModalWindowDimBg;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -173,3 +131,59 @@ bool ThemeManager::decodeRGBA(std::string str, uint8_t out[4]) {
|
|||||||
out[3] = std::stoi(str.substr(7, 2), NULL, 16);
|
out[3] = std::stoi(str.substr(7, 2), NULL, 16);
|
||||||
return true;
|
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}
|
||||||
|
};
|
@ -3,62 +3,13 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
struct Theme {
|
struct Theme {
|
||||||
std::string author;
|
std::string author;
|
||||||
ImVec4 Text;
|
json data;
|
||||||
ImVec4 TextDisabled;
|
|
||||||
ImVec4 WindowBg;
|
|
||||||
ImVec4 ChildBg;
|
|
||||||
ImVec4 PopupBg;
|
|
||||||
ImVec4 Border;
|
|
||||||
ImVec4 BorderShadow;
|
|
||||||
ImVec4 FrameBg;
|
|
||||||
ImVec4 FrameBgHovered;
|
|
||||||
ImVec4 FrameBgActive;
|
|
||||||
ImVec4 TitleBg;
|
|
||||||
ImVec4 TitleBgActive;
|
|
||||||
ImVec4 TitleBgCollapsed;
|
|
||||||
ImVec4 MenuBarBg;
|
|
||||||
ImVec4 ScrollbarBg;
|
|
||||||
ImVec4 ScrollbarGrab;
|
|
||||||
ImVec4 ScrollbarGrabHovered;
|
|
||||||
ImVec4 ScrollbarGrabActive;
|
|
||||||
ImVec4 CheckMark;
|
|
||||||
ImVec4 SliderGrab;
|
|
||||||
ImVec4 SliderGrabActive;
|
|
||||||
ImVec4 Button;
|
|
||||||
ImVec4 ButtonHovered;
|
|
||||||
ImVec4 ButtonActive;
|
|
||||||
ImVec4 Header;
|
|
||||||
ImVec4 HeaderHovered;
|
|
||||||
ImVec4 HeaderActive;
|
|
||||||
ImVec4 Separator;
|
|
||||||
ImVec4 SeparatorHovered;
|
|
||||||
ImVec4 SeparatorActive;
|
|
||||||
ImVec4 ResizeGrip;
|
|
||||||
ImVec4 ResizeGripHovered;
|
|
||||||
ImVec4 ResizeGripActive;
|
|
||||||
ImVec4 Tab;
|
|
||||||
ImVec4 TabHovered;
|
|
||||||
ImVec4 TabActive;
|
|
||||||
ImVec4 TabUnfocused;
|
|
||||||
ImVec4 TabUnfocusedActive;
|
|
||||||
ImVec4 PlotLines;
|
|
||||||
ImVec4 PlotLinesHovered;
|
|
||||||
ImVec4 PlotHistogram;
|
|
||||||
ImVec4 PlotHistogramHovered;
|
|
||||||
ImVec4 TableHeaderBg;
|
|
||||||
ImVec4 TableBorderStrong;
|
|
||||||
ImVec4 TableBorderLight;
|
|
||||||
ImVec4 TableRowBg;
|
|
||||||
ImVec4 TableRowBgAlt;
|
|
||||||
ImVec4 TextSelectedBg;
|
|
||||||
ImVec4 DragDropTarget;
|
|
||||||
ImVec4 NavHighlight;
|
|
||||||
ImVec4 NavWindowingHighlight;
|
|
||||||
ImVec4 NavWindowingDimBg;
|
|
||||||
ImVec4 ModalWindowDimBg;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThemeManager {
|
class ThemeManager {
|
||||||
@ -72,6 +23,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
static bool decodeRGBA(std::string str, uint8_t out[4]);
|
static bool decodeRGBA(std::string str, uint8_t out[4]);
|
||||||
|
|
||||||
|
static std::map<std::string, int> IMGUI_COL_IDS;
|
||||||
|
|
||||||
std::map<std::string, Theme> themes;
|
std::map<std::string, Theme> themes;
|
||||||
|
|
||||||
};
|
};
|
@ -13,7 +13,10 @@ void Menu::registerEntry(std::string name, void (*drawHandler)(void* ctx), void*
|
|||||||
item.inst = inst;
|
item.inst = inst;
|
||||||
items[name] = item;
|
items[name] = item;
|
||||||
if (!isInOrderList(name)) {
|
if (!isInOrderList(name)) {
|
||||||
order.push_back(name);
|
MenuOption_t opt;
|
||||||
|
opt.name = name;
|
||||||
|
opt.open = true;
|
||||||
|
order.push_back(opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,35 +24,40 @@ void Menu::removeEntry(std::string name) {
|
|||||||
items.erase(name);
|
items.erase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::draw() {
|
bool Menu::draw() {
|
||||||
MenuItem_t item;
|
bool changed = false;
|
||||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||||
for (std::string name : order) {
|
for (MenuOption_t& opt : order) {
|
||||||
if (items.find(name) == items.end()) {
|
if (items.find(opt.name) == items.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
item = items[name];
|
MenuItem_t& item = items[opt.name];
|
||||||
|
|
||||||
ImRect orginalRect = window->WorkRect;
|
ImRect orginalRect = window->WorkRect;
|
||||||
if (item.inst != NULL) {
|
if (item.inst != NULL) {
|
||||||
|
|
||||||
window->WorkRect = ImRect(orginalRect.Min, ImVec2(orginalRect.Max.x - ImGui::GetTextLineHeight() - 6, orginalRect.Max.y));
|
window->WorkRect = ImRect(orginalRect.Min, ImVec2(orginalRect.Max.x - ImGui::GetTextLineHeight() - 6, orginalRect.Max.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader(name.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
|
if (ImGui::CollapsingHeader(opt.name.c_str(), opt.open ? ImGuiTreeNodeFlags_DefaultOpen : 0)) {
|
||||||
if (item.inst != NULL) {
|
if (item.inst != NULL) {
|
||||||
window->WorkRect = orginalRect;
|
window->WorkRect = orginalRect;
|
||||||
ImVec2 pos = ImGui::GetCursorPos();
|
ImVec2 pos = ImGui::GetCursorPos();
|
||||||
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
||||||
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
||||||
bool enabled = item.inst->isEnabled();
|
bool enabled = item.inst->isEnabled();
|
||||||
if (ImGui::Checkbox(("##_menu_checkbox_" + name).c_str(), &enabled)) {
|
if (ImGui::Checkbox(("##_menu_checkbox_" + opt.name).c_str(), &enabled)) {
|
||||||
enabled ? item.inst->enable() : item.inst->disable();
|
enabled ? item.inst->enable() : item.inst->disable();
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPos(pos);
|
ImGui::SetCursorPos(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the state changed
|
||||||
|
if (!opt.open) {
|
||||||
|
opt.open = true;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
item.drawHandler(item.ctx);
|
item.drawHandler(item.ctx);
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
}
|
}
|
||||||
@ -59,17 +67,27 @@ void Menu::draw() {
|
|||||||
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
|
||||||
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
|
||||||
bool enabled = item.inst->isEnabled();
|
bool enabled = item.inst->isEnabled();
|
||||||
if (ImGui::Checkbox(("##_menu_checkbox_" + name).c_str(), &enabled)) {
|
if (ImGui::Checkbox(("##_menu_checkbox_" + opt.name).c_str(), &enabled)) {
|
||||||
enabled ? item.inst->enable() : item.inst->disable();
|
enabled ? item.inst->enable() : item.inst->disable();
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPos(pos);
|
ImGui::SetCursorPos(pos);
|
||||||
|
|
||||||
|
if (opt.open) {
|
||||||
|
opt.open = false;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (opt.open) {
|
||||||
|
opt.open = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::isInOrderList(std::string name) {
|
bool Menu::isInOrderList(std::string name) {
|
||||||
for (std::string _name : order) {
|
for (MenuOption_t opt : order) {
|
||||||
if (_name == name) {
|
if (opt.name == name) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,11 @@ class Menu {
|
|||||||
public:
|
public:
|
||||||
Menu();
|
Menu();
|
||||||
|
|
||||||
|
struct MenuOption_t {
|
||||||
|
std::string name;
|
||||||
|
bool open;
|
||||||
|
};
|
||||||
|
|
||||||
struct MenuItem_t {
|
struct MenuItem_t {
|
||||||
void (*drawHandler)(void* ctx);
|
void (*drawHandler)(void* ctx);
|
||||||
void* ctx;
|
void* ctx;
|
||||||
@ -16,9 +21,9 @@ public:
|
|||||||
|
|
||||||
void registerEntry(std::string name, void (*drawHandler)(void* ctx), void* ctx = NULL, ModuleManager::Instance* inst = NULL);
|
void registerEntry(std::string name, void (*drawHandler)(void* ctx), void* ctx = NULL, ModuleManager::Instance* inst = NULL);
|
||||||
void removeEntry(std::string name);
|
void removeEntry(std::string name);
|
||||||
void draw();
|
bool draw();
|
||||||
|
|
||||||
std::vector<std::string> order;
|
std::vector<MenuOption_t> order;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isInOrderList(std::string name);
|
bool isInOrderList(std::string name);
|
||||||
|
Loading…
Reference in New Issue
Block a user