Added theme system

This commit is contained in:
Ryzerth 2021-06-23 21:45:38 +02:00
parent 94fae2135d
commit 26079dba0a
21 changed files with 466 additions and 234 deletions

View File

@ -19,6 +19,7 @@
#include <duktape/duktape.h> #include <duktape/duktape.h>
#include <duktape/duk_console.h> #include <duktape/duk_console.h>
#include <filesystem> #include <filesystem>
#include <gui/menus/theme.h>
#define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_IMAGE_RESIZE_IMPLEMENTATION
#include <stb_image_resize.h> #include <stb_image_resize.h>
@ -166,6 +167,9 @@ int sdrpp_main(int argc, char *argv[]) {
defConfig["moduleInstances"]["SDRplay Source"] = "sdrplay_source"; defConfig["moduleInstances"]["SDRplay Source"] = "sdrplay_source";
defConfig["moduleInstances"]["Audio Sink"] = "audio_sink"; defConfig["moduleInstances"]["Audio Sink"] = "audio_sink";
// Themes
defConfig["theme"] = "Dark";
defConfig["modules"] = json::array(); defConfig["modules"] = json::array();
defConfig["offset"] = 0.0; defConfig["offset"] = 0.0;
defConfig["showMenu"] = true; defConfig["showMenu"] = true;
@ -322,7 +326,8 @@ int sdrpp_main(int argc, char *argv[]) {
} }
} }
if (!style::setDarkStyle(resDir)) { return -1; } if (!style::loadFonts(resDir)) { return -1; }
thememenu::init(resDir);
LoadingScreen::setWindow(core::window); LoadingScreen::setWindow(core::window);
@ -405,8 +410,8 @@ int sdrpp_main(int argc, char *argv[]) {
int display_w, display_h; int display_w, display_h;
glfwGetFramebufferSize(core::window, &display_w, &display_h); glfwGetFramebufferSize(core::window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h); glViewport(0, 0, display_w, display_h);
glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f); //glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f);
//glClearColor(0.9f, 0.9f, 0.9f, 1.0f); glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

View File

@ -9,7 +9,7 @@ namespace sdrpp_credits {
"Benjamin Kyd", "Benjamin Kyd",
"Benjamin Vernoux", "Benjamin Vernoux",
"Cropinghigh", "Cropinghigh",
"Fred F4EED" "Fred F4EED",
"Howard0su", "Howard0su",
"Joshua Kimsey", "Joshua Kimsey",
"Martin Hauke", "Martin Hauke",

View File

@ -7,6 +7,7 @@
#include <gui/icons.h> #include <gui/icons.h>
#include <gui/style.h> #include <gui/style.h>
#include <credits.h> #include <credits.h>
#include <gui/gui.h>
namespace LoadingScreen { namespace LoadingScreen {
GLFWwindow* _win; GLFWwindow* _win;
@ -76,7 +77,7 @@ namespace LoadingScreen {
int display_w, display_h; int display_w, display_h;
glfwGetFramebufferSize(_win, &display_w, &display_h); glfwGetFramebufferSize(_win, &display_w, &display_h);
glViewport(0, 0, display_w, display_h); glViewport(0, 0, display_w, display_h);
glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f); glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

View File

@ -4,5 +4,6 @@ namespace gui {
MainWindow mainWindow; MainWindow mainWindow;
ImGui::WaterFall waterfall; ImGui::WaterFall waterfall;
FrequencySelect freqSelect; FrequencySelect freqSelect;
ThemeManager themeManager;
Menu menu; Menu menu;
}; };

View File

@ -5,12 +5,13 @@
#include <gui/dialogs/loading_screen.h> #include <gui/dialogs/loading_screen.h>
#include <module.h> #include <module.h>
#include <gui/main_window.h> #include <gui/main_window.h>
#include <gui/theme_manager.h>
namespace gui { namespace gui {
SDRPP_EXPORT ImGui::WaterFall waterfall; SDRPP_EXPORT ImGui::WaterFall waterfall;
SDRPP_EXPORT FrequencySelect freqSelect; SDRPP_EXPORT FrequencySelect freqSelect;
SDRPP_EXPORT Menu menu; SDRPP_EXPORT Menu menu;
SDRPP_EXPORT ThemeManager themeManager;
SDRPP_EXPORT MainWindow mainWindow; SDRPP_EXPORT MainWindow mainWindow;
void selectSource(std::string name); void selectSource(std::string name);

View File

@ -25,6 +25,7 @@
#include <gui/menus/scripting.h> #include <gui/menus/scripting.h>
#include <gui/menus/vfo_color.h> #include <gui/menus/vfo_color.h>
#include <gui/menus/module_manager.h> #include <gui/menus/module_manager.h>
#include <gui/menus/theme.h>
#include <gui/dialogs/credits.h> #include <gui/dialogs/credits.h>
#include <filesystem> #include <filesystem>
#include <signal_path/source.h> #include <signal_path/source.h>
@ -68,6 +69,7 @@ void MainWindow::init() {
gui::menu.registerEntry("Scripting", scriptingmenu::draw, NULL); gui::menu.registerEntry("Scripting", scriptingmenu::draw, NULL);
gui::menu.registerEntry("Band Plan", bandplanmenu::draw, NULL); gui::menu.registerEntry("Band Plan", bandplanmenu::draw, NULL);
gui::menu.registerEntry("Display", displaymenu::draw, NULL); gui::menu.registerEntry("Display", displaymenu::draw, NULL);
gui::menu.registerEntry("Theme", thememenu::draw, NULL);
gui::menu.registerEntry("VFO Color", vfo_color_menu::draw, NULL); gui::menu.registerEntry("VFO Color", vfo_color_menu::draw, NULL);
gui::menu.registerEntry("Module Manager", module_manager_menu::draw, NULL); gui::menu.registerEntry("Module Manager", module_manager_menu::draw, NULL);
@ -423,7 +425,7 @@ void MainWindow::draw() {
} }
// Left Column // Left Column
lockWaterfallControls = false;
if (showMenu) { if (showMenu) {
ImGui::Columns(3, "WindowColumns", false); ImGui::Columns(3, "WindowColumns", false);
ImGui::SetColumnWidth(0, menuWidth); ImGui::SetColumnWidth(0, menuWidth);
@ -490,45 +492,47 @@ void MainWindow::draw() {
ImGui::EndChild(); ImGui::EndChild();
// Handle arrow keys if (!lockWaterfallControls) {
if (vfo != NULL && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) { // Handle arrow keys
if (ImGui::IsKeyPressed(GLFW_KEY_LEFT) && !gui::freqSelect.digitHovered) { if (vfo != NULL && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) {
double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset - vfo->snapInterval; if (ImGui::IsKeyPressed(GLFW_KEY_LEFT) && !gui::freqSelect.digitHovered) {
nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval; double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset - vfo->snapInterval;
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq); nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
}
if (ImGui::IsKeyPressed(GLFW_KEY_RIGHT) && !gui::freqSelect.digitHovered) {
double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + vfo->snapInterval;
nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
}
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
if (vfo != NULL) {
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
}
core::configManager.release(true);
} }
if (ImGui::IsKeyPressed(GLFW_KEY_RIGHT) && !gui::freqSelect.digitHovered) {
double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + vfo->snapInterval;
nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
}
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
if (vfo != NULL) {
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
}
core::configManager.release(true);
}
// Handle scrollwheel // Handle scrollwheel
int wheel = ImGui::GetIO().MouseWheel; int wheel = ImGui::GetIO().MouseWheel;
if (wheel != 0 && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) { if (wheel != 0 && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) {
double nfreq; double nfreq;
if (vfo != NULL) { if (vfo != NULL) {
nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + (vfo->snapInterval * wheel); nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + (vfo->snapInterval * wheel);
nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval; nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
}
else {
nfreq = gui::waterfall.getCenterFrequency() - (gui::waterfall.getViewBandwidth() * wheel / 20.0);
}
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
gui::freqSelect.setFrequency(nfreq);
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
if (vfo != NULL) {
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
}
core::configManager.release(true);
} }
else {
nfreq = gui::waterfall.getCenterFrequency() - (gui::waterfall.getViewBandwidth() * wheel / 20.0);
}
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
gui::freqSelect.setFrequency(nfreq);
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
if (vfo != NULL) {
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
}
core::configManager.release(true);
} }
ImGui::NextColumn(); ImGui::NextColumn();

View File

@ -22,6 +22,8 @@ public:
// TODO: Replace with it's own class // TODO: Replace with it's own class
void setVFO(double freq); void setVFO(double freq);
bool lockWaterfallControls = false;
private: private:
static void fftHandler(dsp::complex_t* samples, int count, void* ctx); static void fftHandler(dsp::complex_t* samples, int count, void* ctx);
static void vfoAddedHandler(VFOManager::VFO* vfo, void* ctx); static void vfoAddedHandler(VFOManager::VFO* vfo, void* ctx);

View File

@ -0,0 +1,47 @@
#include <gui/menus/theme.h>
#include <gui/gui.h>
#include <options.h>
#include <core.h>>
namespace thememenu {
int themeId;
std::vector<std::string> themeNames;
std::string themeNamesTxt;
void init(std::string resDir) {
// TODO: Not hardcode theme directory
gui::themeManager.loadThemesFromDir(resDir + "/themes/");
core::configManager.aquire();
std::string selectedThemeName = core::configManager.conf["theme"];
core::configManager.release();
// Select theme by name, if not available, apply Dark theme
themeNames = gui::themeManager.getThemeNames();
auto it = std::find(themeNames.begin(), themeNames.end(), selectedThemeName);
if (it == themeNames.end()) {
it = std::find(themeNames.begin(), themeNames.end(), "Dark");
selectedThemeName = "Dark";
}
gui::themeManager.applyTheme(selectedThemeName);
themeId = std::distance(themeNames.begin(), it);
themeNamesTxt = "";
for (auto name : themeNames) {
themeNamesTxt += name;
themeNamesTxt += '\0';
}
}
void draw(void* ctx) {
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::Text("Theme");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::Combo("##theme_select_combo", &themeId, themeNamesTxt.c_str())) {
gui::themeManager.applyTheme(themeNames[themeId]);
core::configManager.aquire();
core::configManager.conf["theme"] = themeNames[themeId];
core::configManager.release(true);
}
}
}

View File

@ -0,0 +1,7 @@
#pragma once
#include <string>
namespace thememenu {
void init(std::string resDir);
void draw(void* ctx);
}

View File

@ -11,107 +11,32 @@ namespace style {
ImFont* bigFont; ImFont* bigFont;
ImFont* hugeFont; ImFont* hugeFont;
bool setDefaultStyle(std::string resDir) { bool loadFonts(std::string resDir) {
if (!std::filesystem::is_directory(resDir)) { if (!std::filesystem::is_directory(resDir)) {
spdlog::error("Inavlid resource directory: {0}", resDir); spdlog::error("Inavlid resource directory: {0}", resDir);
return false; return false;
} }
ImGui::GetStyle().WindowRounding = 0.0f;
ImGui::GetStyle().ChildRounding = 0.0f;
ImGui::GetStyle().FrameRounding = 0.0f;
ImGui::GetStyle().GrabRounding = 0.0f;
ImGui::GetStyle().PopupRounding = 0.0f;
ImGui::GetStyle().ScrollbarRounding = 0.0f;
baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 16.0f); baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 16.0f);
bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 45.0f); bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 45.0f);
hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 128.0f); hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 128.0f);
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
return true;
}
void testtt() {
ImGui::StyleColorsLight();
}
bool setDarkStyle(std::string resDir) {
if (!std::filesystem::is_directory(resDir)) {
spdlog::error("Inavlid resource directory: {0}", resDir);
return false;
}
ImGui::GetStyle().WindowRounding = 0.0f;
ImGui::GetStyle().ChildRounding = 0.0f;
ImGui::GetStyle().FrameRounding = 0.0f;
ImGui::GetStyle().GrabRounding = 0.0f;
ImGui::GetStyle().PopupRounding = 0.0f;
ImGui::GetStyle().ScrollbarRounding = 0.0f;
baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 16.0f);
bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 45.0f);
hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 128.0f);
ImGui::StyleColorsDark();
auto& style = ImGui::GetStyle();
ImVec4* colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
colors[ImGuiCol_ChildBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f);
colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.29f, 0.29f, 0.29f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.45f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f);
colors[ImGuiCol_Header] = ImVec4(0.63f, 0.63f, 0.70f, 0.31f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.63f, 0.63f, 0.70f, 0.40f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.63f, 0.63f, 0.70f, 0.31f);
colors[ImGuiCol_Separator] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.72f, 0.72f, 0.72f, 0.78f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.91f, 0.91f, 0.91f, 0.25f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.81f, 0.81f, 0.81f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.46f, 0.46f, 0.46f, 0.95f);
colors[ImGuiCol_PlotLines] = ImVec4(0.4f, 0.9f, 1.0f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.73f, 0.60f, 0.15f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.87f, 0.87f, 0.87f, 0.35f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
return true; return true;
} }
void beginDisabled() { void beginDisabled() {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.44f, 0.44f, 0.44f, 0.15f)); auto& style = ImGui::GetStyle();
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.20f, 0.21f, 0.22f, 0.30f)); ImVec4* colors = style.Colors;
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.00f, 1.00f, 1.00f, 0.65f)); ImVec4 btnCol = colors[ImGuiCol_Button];
ImVec4 frameCol = colors[ImGuiCol_Button];
ImVec4 textCol = colors[ImGuiCol_Button];
btnCol.w = 0.15f;
frameCol.w = 0.30f;
textCol.w = 0.65f;
ImGui::PushStyleColor(ImGuiCol_Button, btnCol);
ImGui::PushStyleColor(ImGuiCol_FrameBg, frameCol);
ImGui::PushStyleColor(ImGuiCol_Text, textCol);
} }
void endDisabled() { void endDisabled() {

View File

@ -8,7 +8,7 @@ namespace style {
extern ImFont* hugeFont; extern ImFont* hugeFont;
bool setDefaultStyle(std::string resDir); bool setDefaultStyle(std::string resDir);
bool setDarkStyle(std::string resDir); bool loadFonts(std::string resDir);
void beginDisabled(); void beginDisabled();
void endDisabled(); void endDisabled();
void testtt(); void testtt();

View File

@ -6,6 +6,22 @@
#include <fstream> #include <fstream>
bool ThemeManager::loadThemesFromDir(std::string path) { bool ThemeManager::loadThemesFromDir(std::string path) {
// TEST JUST TO DUMP THE ORIGINAL THEME
auto& style = ImGui::GetStyle();
ImVec4* colors = style.Colors;
printf("\n\n");
for (auto [name, id] : IMGUI_COL_IDS) {
ImVec4 col = colors[id];
uint8_t r = 255 - (col.x * 255.0f);
uint8_t g = 255 - (col.y * 255.0f);
uint8_t b = 255 - (col.z * 255.0f);
uint8_t a = col.w * 255.0f;
printf("\"%s\": \"#%02X%02X%02X%02X\",\n", name.c_str(), r, g, b, a);
}
printf("\n\n");
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);
return false; return false;
@ -48,6 +64,11 @@ bool ThemeManager::loadTheme(std::string path) {
} }
std::string name = data["name"]; std::string name = data["name"];
if (themes.find(name) != themes.end()) {
spdlog::error("A theme named '{0}' already exists", name);
return false;
}
// Load theme author if available // Load theme author if available
if (data.contains("author")) { if (data.contains("author")) {
if (!data["author"].is_string()) { if (!data["author"].is_string()) {
@ -62,6 +83,15 @@ bool ThemeManager::loadTheme(std::string path) {
for (auto const& [param, val] : params) { for (auto const& [param, val] : params) {
if (param == "name" || param == "author") { continue; } if (param == "name" || param == "author") { continue; }
// Exception for non-imgu colors
if (param == "WaterfallBackground" || param == "ClearColor") {
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;
}
continue;
}
bool isValid = false; bool isValid = false;
// If param is a color, check that it's a valid RGBA hex value // If param is a color, check that it's a valid RGBA hex value
@ -110,6 +140,18 @@ bool ThemeManager::applyTheme(std::string name) {
for (auto const& [param, val] : params) { for (auto const& [param, val] : params) {
if (param == "name" || param == "author") { continue; } if (param == "name" || param == "author") { continue; }
if (param == "WaterfallBackground") {
decodeRGBA(val, ret);
waterfallBg = ImVec4((float)ret[0]/255.0f, (float)ret[1]/255.0f, (float)ret[2]/255.0f, (float)ret[3]/255.0f);
continue;
}
if (param == "ClearColor") {
decodeRGBA(val, ret);
clearColor = ImVec4((float)ret[0]/255.0f, (float)ret[1]/255.0f, (float)ret[2]/255.0f, (float)ret[3]/255.0f);
continue;
}
// If param is a color, check that it's a valid RGBA hex value // 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 (IMGUI_COL_IDS.find(param) != IMGUI_COL_IDS.end()) {
decodeRGBA(val, ret); decodeRGBA(val, ret);
@ -132,6 +174,12 @@ bool ThemeManager::decodeRGBA(std::string str, uint8_t out[4]) {
return true; return true;
} }
std::vector<std::string> ThemeManager::getThemeNames() {
std::vector<std::string> names;
for (auto [name, theme] : themes) { names.push_back(name); }
return names;
}
std::map<std::string, int> ThemeManager::IMGUI_COL_IDS = { std::map<std::string, int> ThemeManager::IMGUI_COL_IDS = {
{"Text", ImGuiCol_Text}, {"Text", ImGuiCol_Text},
{"TextDisabled", ImGuiCol_TextDisabled}, {"TextDisabled", ImGuiCol_TextDisabled},

View File

@ -20,6 +20,9 @@ public:
std::vector<std::string> getThemeNames(); std::vector<std::string> getThemeNames();
ImVec4 waterfallBg = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);;
ImVec4 clearColor = ImVec4(0.0666f, 0.0666f, 0.0666f, 1.0f);
private: private:
static bool decodeRGBA(std::string str, uint8_t out[4]); static bool decodeRGBA(std::string str, uint8_t out[4]);

View File

@ -1,6 +1,7 @@
#include <gui/widgets/frequency_select.h> #include <gui/widgets/frequency_select.h>
#include <config.h> #include <config.h>
#include <gui/style.h> #include <gui/style.h>
#include <gui/gui.h>
#include <glfw_window.h> #include <glfw_window.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@ -142,72 +143,73 @@ void FrequencySelect::draw() {
} }
} }
ImVec2 mousePos = ImGui::GetMousePos(); if (!gui::mainWindow.lockWaterfallControls) {
bool leftClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); ImVec2 mousePos = ImGui::GetMousePos();
bool rightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right); bool leftClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
int mw = ImGui::GetIO().MouseWheel; bool rightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right);
bool onDigit = false; int mw = ImGui::GetIO().MouseWheel;
bool hovered = false; bool onDigit = false;
bool hovered = false;
for (int i = 0; i < 12; i++) { for (int i = 0; i < 12; i++) {
onDigit = false; onDigit = false;
if (isInArea(mousePos, digitTopMins[i], digitTopMaxs[i])) { if (isInArea(mousePos, digitTopMins[i], digitTopMaxs[i])) {
window->DrawList->AddRectFilled(digitTopMins[i], digitTopMaxs[i], IM_COL32(255, 0, 0, 75)); window->DrawList->AddRectFilled(digitTopMins[i], digitTopMaxs[i], IM_COL32(255, 0, 0, 75));
if (leftClick) { if (leftClick) {
incrementDigit(i); incrementDigit(i);
}
onDigit = true;
}
if (isInArea(mousePos, digitBottomMins[i], digitBottomMaxs[i])) {
window->DrawList->AddRectFilled(digitBottomMins[i], digitBottomMaxs[i], IM_COL32(0, 0, 255, 75));
if (leftClick) {
decrementDigit(i);
}
onDigit = true;
}
if (onDigit) {
hovered = true;
if (rightClick || (ImGui::IsKeyPressed(GLFW_KEY_DELETE) || ImGui::IsKeyPressed(GLFW_KEY_ENTER) || ImGui::IsKeyPressed(GLFW_KEY_KP_ENTER))) {
for (int j = i; j < 12; j++) {
digits[j] = 0;
} }
frequencyChanged = true; onDigit = true;
} }
if (ImGui::IsKeyPressed(GLFW_KEY_UP)) { if (isInArea(mousePos, digitBottomMins[i], digitBottomMaxs[i])) {
incrementDigit(i); window->DrawList->AddRectFilled(digitBottomMins[i], digitBottomMaxs[i], IM_COL32(0, 0, 255, 75));
if (leftClick) {
decrementDigit(i);
}
onDigit = true;
} }
if (ImGui::IsKeyPressed(GLFW_KEY_DOWN)) { if (onDigit) {
decrementDigit(i); hovered = true;
} if (rightClick || (ImGui::IsKeyPressed(GLFW_KEY_DELETE) || ImGui::IsKeyPressed(GLFW_KEY_ENTER) || ImGui::IsKeyPressed(GLFW_KEY_KP_ENTER))) {
if ((ImGui::IsKeyPressed(GLFW_KEY_LEFT) || ImGui::IsKeyPressed(GLFW_KEY_BACKSPACE)) && i > 0) { for (int j = i; j < 12; j++) {
moveCursorToDigit(i - 1); digits[j] = 0;
} }
if (ImGui::IsKeyPressed(GLFW_KEY_RIGHT) && i < 11) {
moveCursorToDigit(i + 1);
}
auto chars = ImGui::GetIO().InputQueueCharacters;
// For each keyboard characters, type it
for (int j = 0; j < chars.Size; j++) {
if (chars[j] >= '0' && chars[j] <= '9') {
digits[i + j] = chars[j] - '0';
if ((i + j) < 11) { moveCursorToDigit(i + j + 1); }
frequencyChanged = true; frequencyChanged = true;
} }
} if (ImGui::IsKeyPressed(GLFW_KEY_UP)) {
incrementDigit(i);
}
if (ImGui::IsKeyPressed(GLFW_KEY_DOWN)) {
decrementDigit(i);
}
if ((ImGui::IsKeyPressed(GLFW_KEY_LEFT) || ImGui::IsKeyPressed(GLFW_KEY_BACKSPACE)) && i > 0) {
moveCursorToDigit(i - 1);
}
if (ImGui::IsKeyPressed(GLFW_KEY_RIGHT) && i < 11) {
moveCursorToDigit(i + 1);
}
if (mw != 0) { auto chars = ImGui::GetIO().InputQueueCharacters;
int count = abs(mw);
for (int j = 0; j < count; j++) { // For each keyboard characters, type it
mw > 0 ? incrementDigit(i) : decrementDigit(i); for (int j = 0; j < chars.Size; j++) {
if (chars[j] >= '0' && chars[j] <= '9') {
digits[i + j] = chars[j] - '0';
if ((i + j) < 11) { moveCursorToDigit(i + j + 1); }
frequencyChanged = true;
}
}
if (mw != 0) {
int count = abs(mw);
for (int j = 0; j < count; j++) {
mw > 0 ? incrementDigit(i) : decrementDigit(i);
}
} }
} }
} }
digitHovered = hovered;
} }
digitHovered = hovered;
uint64_t freq = 0; uint64_t freq = 0;
for (int i = 0; i < 12; i++) { for (int i = 0; i < 12; i++) {
freq += digits[i] * pow(10, 11 - i); freq += digits[i] * pow(10, 11 - i);

View File

@ -17,6 +17,8 @@ namespace ImGui {
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), 26); ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), 26);
ImRect bb(min, min + size); ImRect bb(min, min + size);
ImU32 text = ImGui::GetColorU32(ImGuiCol_Text);
float lineHeight = size.y; float lineHeight = size.y;
ItemSize(size, style.FramePadding.y); ItemSize(size, style.FramePadding.y);
@ -30,14 +32,14 @@ namespace ImGui {
char buf[32]; char buf[32];
window->DrawList->AddRectFilled(min + ImVec2(0, 1), min + ImVec2(roundf((float)val * ratio), 10), IM_COL32(0, 136, 255, 255)); window->DrawList->AddRectFilled(min + ImVec2(0, 1), min + ImVec2(roundf((float)val * ratio), 10), IM_COL32(0, 136, 255, 255));
window->DrawList->AddLine(min, min + ImVec2(0, 9), IM_COL32(255, 255, 255, 255)); window->DrawList->AddLine(min, min + ImVec2(0, 9), text);
window->DrawList->AddLine(min + ImVec2(0, 9), min + ImVec2(size.x + 1, 9), IM_COL32(255, 255, 255, 255)); window->DrawList->AddLine(min + ImVec2(0, 9), min + ImVec2(size.x + 1, 9), text);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
window->DrawList->AddLine(min + ImVec2(roundf((float)i * it), 9), min + ImVec2(roundf((float)i * it), 14), IM_COL32(255, 255, 255, 255)); window->DrawList->AddLine(min + ImVec2(roundf((float)i * it), 9), min + ImVec2(roundf((float)i * it), 14), text);
sprintf(buf, "%d", i * 10); sprintf(buf, "%d", i * 10);
ImVec2 sz = ImGui::CalcTextSize(buf); ImVec2 sz = ImGui::CalcTextSize(buf);
window->DrawList->AddText(min + ImVec2(roundf(((float)i * it) - (sz.x/2.0)) + 1, 16), IM_COL32(255, 255, 255, 255), buf); window->DrawList->AddText(min + ImVec2(roundf(((float)i * it) - (sz.x/2.0)) + 1, 16), text, buf);
} }
} }
} }

View File

@ -29,8 +29,8 @@ namespace ImGui {
float zeroDb = roundf(((-val_min) / (val_max - val_min)) * size.x); float zeroDb = roundf(((-val_min) / (val_max - val_min)) * size.x);
window->DrawList->AddRectFilled(min, min + ImVec2(zeroDb, lineHeight), IM_COL32( 0, 255, 0, 127 )); window->DrawList->AddRectFilled(min, min + ImVec2(zeroDb, lineHeight), IM_COL32( 9, 136, 9, 255 ));
window->DrawList->AddRectFilled(min + ImVec2(zeroDb, 0), min + ImVec2(size.x, lineHeight), IM_COL32( 255, 0, 0, 127 )); window->DrawList->AddRectFilled(min + ImVec2(zeroDb, 0), min + ImVec2(size.x, lineHeight), IM_COL32( 136, 9, 9, 255 ));
float end = roundf(((avg - val_min) / (val_max - val_min)) * size.x); float end = roundf(((avg - val_min) / (val_max - val_min)) * size.x);
float endP = roundf(((peak - val_min) / (val_max - val_min)) * size.x); float endP = roundf(((peak - val_min) / (val_max - val_min)) * size.x);

View File

@ -131,6 +131,7 @@ namespace ImGui {
ImU32 trace = ImGui::GetColorU32(ImGuiCol_PlotLines); ImU32 trace = ImGui::GetColorU32(ImGuiCol_PlotLines);
ImU32 shadow = ImGui::GetColorU32(ImGuiCol_PlotLines, 0.2); ImU32 shadow = ImGui::GetColorU32(ImGuiCol_PlotLines, 0.2);
ImU32 text = ImGui::GetColorU32(ImGuiCol_Text);
// Vertical scale // Vertical scale
for (float line = startLine; line > fftMin; line -= vRange) { for (float line = startLine; line > fftMin; line -= vRange) {
@ -140,7 +141,7 @@ namespace ImGui {
IM_COL32(50, 50, 50, 255), 1.0); IM_COL32(50, 50, 50, 255), 1.0);
sprintf(buf, "%d", (int)line); sprintf(buf, "%d", (int)line);
ImVec2 txtSz = ImGui::CalcTextSize(buf); ImVec2 txtSz = ImGui::CalcTextSize(buf);
window->DrawList->AddText(ImVec2(widgetPos.x + 40 - txtSz.x, roundf(yPos - (txtSz.y / 2.0))), IM_COL32( 255, 255, 255, 255 ), buf); window->DrawList->AddText(ImVec2(widgetPos.x + 40 - txtSz.x, roundf(yPos - (txtSz.y / 2.0))), text, buf);
} }
// Horizontal scale // Horizontal scale
@ -153,10 +154,10 @@ namespace ImGui {
IM_COL32(50, 50, 50, 255), 1.0); IM_COL32(50, 50, 50, 255), 1.0);
window->DrawList->AddLine(ImVec2(roundf(xPos), widgetPos.y + fftHeight + 10), window->DrawList->AddLine(ImVec2(roundf(xPos), widgetPos.y + fftHeight + 10),
ImVec2(roundf(xPos), widgetPos.y + fftHeight + 17), ImVec2(roundf(xPos), widgetPos.y + fftHeight + 17),
IM_COL32(255, 255, 255, 255), 1.0); text, 1.0);
printAndScale(freq, buf); printAndScale(freq, buf);
ImVec2 txtSz = ImGui::CalcTextSize(buf); ImVec2 txtSz = ImGui::CalcTextSize(buf);
window->DrawList->AddText(ImVec2(roundf(xPos - (txtSz.x / 2.0)), widgetPos.y + fftHeight + 10 + txtSz.y), IM_COL32( 255, 255, 255, 255 ), buf); window->DrawList->AddText(ImVec2(roundf(xPos - (txtSz.x / 2.0)), widgetPos.y + fftHeight + 10 + txtSz.y), text, buf);
} }
// Data // Data
@ -176,11 +177,11 @@ namespace ImGui {
// X Axis // X Axis
window->DrawList->AddLine(ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 10), window->DrawList->AddLine(ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 10),
ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 10), ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 10),
IM_COL32(255, 255, 255, 255), 1.0); text, 1.0);
// Y Axis // Y Axis
window->DrawList->AddLine(ImVec2(widgetPos.x + 50, widgetPos.y + 9), window->DrawList->AddLine(ImVec2(widgetPos.x + 50, widgetPos.y + 9),
ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 9), ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 9),
IM_COL32(255, 255, 255, 255), 1.0); text, 1.0);
} }
@ -193,7 +194,7 @@ namespace ImGui {
window->DrawList->AddImage((void*)(intptr_t)textureId, wfMin, wfMax); window->DrawList->AddImage((void*)(intptr_t)textureId, wfMin, wfMax);
ImVec2 mPos = ImGui::GetMousePos(); ImVec2 mPos = ImGui::GetMousePos();
if (IS_IN_AREA(mPos, wfMin, wfMax)) { if (IS_IN_AREA(mPos, wfMin, wfMax) && !gui::mainWindow.lockWaterfallControls) {
for (auto const& [name, vfo] : vfos) { for (auto const& [name, vfo] : vfos) {
window->DrawList->AddRectFilled(vfo->wfRectMin, vfo->wfRectMax, vfo->color); window->DrawList->AddRectFilled(vfo->wfRectMin, vfo->wfRectMax, vfo->color);
window->DrawList->AddLine(vfo->wfLineMin, vfo->wfLineMax, (name == selectedVFO) ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255)); window->DrawList->AddLine(vfo->wfLineMin, vfo->wfLineMax, (name == selectedVFO) ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255));
@ -701,11 +702,13 @@ namespace ImGui {
onResize(); onResize();
} }
window->DrawList->AddRectFilled(widgetPos, widgetEndPos, IM_COL32( 0, 0, 0, 255 )); //window->DrawList->AddRectFilled(widgetPos, widgetEndPos, IM_COL32( 0, 0, 0, 255 ));
ImU32 bg = ImGui::ColorConvertFloat4ToU32(gui::themeManager.waterfallBg);
window->DrawList->AddRectFilled(widgetPos, widgetEndPos, bg);
window->DrawList->AddRect(widgetPos, widgetEndPos, IM_COL32( 50, 50, 50, 255 )); window->DrawList->AddRect(widgetPos, widgetEndPos, IM_COL32( 50, 50, 50, 255 ));
window->DrawList->AddLine(ImVec2(widgetPos.x, widgetPos.y + fftHeight + 50), ImVec2(widgetPos.x + widgetSize.x, widgetPos.y + fftHeight + 50), IM_COL32(50, 50, 50, 255), 1.0); window->DrawList->AddLine(ImVec2(widgetPos.x, widgetPos.y + fftHeight + 50), ImVec2(widgetPos.x + widgetSize.x, widgetPos.y + fftHeight + 50), IM_COL32(50, 50, 50, 255), 1.0);
processInputs(); if (!gui::mainWindow.lockWaterfallControls) { processInputs(); }
updateAllVFOs(true); updateAllVFOs(true);
@ -724,28 +727,30 @@ namespace ImGui {
} }
// Handle fft resize // Handle fft resize
ImVec2 winSize = ImGui::GetWindowSize(); if (!gui::mainWindow.lockWaterfallControls) {
ImVec2 mousePos = ImGui::GetMousePos(); ImVec2 winSize = ImGui::GetWindowSize();
mousePos.x -= widgetPos.x; ImVec2 mousePos = ImGui::GetMousePos();
mousePos.y -= widgetPos.y; mousePos.x -= widgetPos.x;
bool click = ImGui::IsMouseClicked(ImGuiMouseButton_Left); mousePos.y -= widgetPos.y;
bool down = ImGui::IsMouseDown(ImGuiMouseButton_Left); bool click = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
if (draggingFW) { bool down = ImGui::IsMouseDown(ImGuiMouseButton_Left);
newFFTAreaHeight = mousePos.y; if (draggingFW) {
newFFTAreaHeight = std::clamp<float>(newFFTAreaHeight, 150, widgetSize.y - 50); newFFTAreaHeight = mousePos.y;
ImGui::GetForegroundDrawList()->AddLine(ImVec2(widgetPos.x, newFFTAreaHeight + widgetPos.y), ImVec2(widgetEndPos.x, newFFTAreaHeight + widgetPos.y), newFFTAreaHeight = std::clamp<float>(newFFTAreaHeight, 150, widgetSize.y - 50);
ImGui::GetColorU32(ImGuiCol_SeparatorActive)); ImGui::GetForegroundDrawList()->AddLine(ImVec2(widgetPos.x, newFFTAreaHeight + widgetPos.y), ImVec2(widgetEndPos.x, newFFTAreaHeight + widgetPos.y),
} ImGui::GetColorU32(ImGuiCol_SeparatorActive));
if (mousePos.y >= newFFTAreaHeight - 2 && mousePos.y <= newFFTAreaHeight + 2 && mousePos.x > 0 && mousePos.x < widgetSize.x) { }
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS); if (mousePos.y >= newFFTAreaHeight - 2 && mousePos.y <= newFFTAreaHeight + 2 && mousePos.x > 0 && mousePos.x < widgetSize.x) {
if (click) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
draggingFW = true; if (click) {
draggingFW = true;
}
}
if(!down && draggingFW) {
draggingFW = false;
FFTAreaHeight = newFFTAreaHeight;
onResize();
} }
}
if(!down && draggingFW) {
draggingFW = false;
FFTAreaHeight = newFFTAreaHeight;
onResize();
} }
buf_mtx.unlock(); buf_mtx.unlock();
@ -1128,14 +1133,16 @@ namespace ImGui {
window->DrawList->AddLine(lineMin, lineMax, selected ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255)); window->DrawList->AddLine(lineMin, lineMax, selected ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255));
} }
ImVec2 mousePos = ImGui::GetMousePos(); if (!gui::mainWindow.lockWaterfallControls) {
if (reference != REF_LOWER && !bandwidthLocked) { ImVec2 mousePos = ImGui::GetMousePos();
if (IS_IN_AREA(mousePos, lbwSelMin, lbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } if (reference != REF_LOWER && !bandwidthLocked) {
else if (IS_IN_AREA(mousePos, wfLbwSelMin, wfLbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } if (IS_IN_AREA(mousePos, lbwSelMin, lbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); }
} else if (IS_IN_AREA(mousePos, wfLbwSelMin, wfLbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); }
if (reference != REF_UPPER && !bandwidthLocked) { }
if (IS_IN_AREA(mousePos, rbwSelMin, rbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } if (reference != REF_UPPER && !bandwidthLocked) {
else if (IS_IN_AREA(mousePos, wfRbwSelMin, wfRbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } if (IS_IN_AREA(mousePos, rbwSelMin, rbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); }
else if (IS_IN_AREA(mousePos, wfRbwSelMin, wfRbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); }
}
} }
}; };

View File

@ -5,9 +5,11 @@
#include <gui/style.h> #include <gui/style.h>
#include <core.h> #include <core.h>
#include <thread> #include <thread>
#include <options.h>
#include <radio_interface.h> #include <radio_interface.h>
#include <signal_path/signal_path.h> #include <signal_path/signal_path.h>
#include <vector> #include <vector>
#include <gui/tuner.h>
SDRPP_MOD_INFO { SDRPP_MOD_INFO {
/* Name: */ "frequency_manager", /* Name: */ "frequency_manager",
@ -24,6 +26,8 @@ struct FrequencyBookmark {
bool selected; bool selected;
}; };
ConfigManager config;
class FrequencyManagerModule : public ModuleManager::Instance { class FrequencyManagerModule : public ModuleManager::Instance {
public: public:
FrequencyManagerModule(std::string name) { FrequencyManagerModule(std::string name) {
@ -78,12 +82,20 @@ private:
gui::waterfall.centerFreqMoved = true; gui::waterfall.centerFreqMoved = true;
} }
else { else {
tuner::tune(tuner::TUNER_MODE_NORMAL, vfoName, bm.frequency);
if (core::modComManager.interfaceExists(vfoName)) {
if (core::modComManager.getModuleName(vfoName) == "radio") {
int mode = bm.mode;
core::modComManager.callInterface(vfoName, RADIO_IFACE_CMD_SET_MODE, &mode, NULL);
// TODO: Set bandwidth as well
}
}
} }
} }
bool bookmarkEditDialog() { bool bookmarkEditDialog() {
bool open = true; bool open = true;
gui::mainWindow.lockWaterfallControls = true;
std::string id = "Edit##freq_manager_edit_popup_" + name; std::string id = "Edit##freq_manager_edit_popup_" + name;
ImGui::OpenPopup(id.c_str()); ImGui::OpenPopup(id.c_str());
@ -131,7 +143,13 @@ private:
if (strlen(nameBuf) == 0) { style::beginDisabled(); } if (strlen(nameBuf) == 0) { style::beginDisabled(); }
if (ImGui::Button("Apply")) { if (ImGui::Button("Apply")) {
open = false; open = false;
// If editing, delete the original one
if (editOpen) {
bookmarks.erase(firstEeditedBookmarkName);
}
bookmarks[nameBuf] = editedBookmark; bookmarks[nameBuf] = editedBookmark;
} }
if (strlen(nameBuf) == 0) { style::endDisabled(); } if (strlen(nameBuf) == 0) { style::endDisabled(); }
ImGui::SameLine(); ImGui::SameLine();
@ -143,6 +161,32 @@ private:
return open; return open;
} }
void loadByName(std::string listName) {
if (std::find(listNames.begin(), listNames.end(), listName) == listNames.end()) { return; }
bookmarks.clear();
config.aquire();
for (auto [bmName, bm] : config.conf["lists"][listName].items()) {
FrequencyBookmark fbm;
fbm.frequency = bm["frequency"];
fbm.bandwidth = bm["bandwidth"];
fbm.mode = bm["mode"];
fbm.selected = false;
bookmarks[bmName] = fbm;
}
config.release();
}
void saveByName(std::string listName) {
config.aquire();
config.conf["lists"][listName] = json::object();
for (auto [bmName, bm] : bookmarks) {
config.conf["lists"][listName][bmName]["frequency"] = bm.frequency;
config.conf["lists"][listName][bmName]["bandwidth"] = bm.bandwidth;
config.conf["lists"][listName][bmName]["mode"] = bm.mode;
}
config.release(true);
}
static void menuHandler(void* ctx) { static void menuHandler(void* ctx) {
FrequencyManagerModule* _this = (FrequencyManagerModule*)ctx; FrequencyManagerModule* _this = (FrequencyManagerModule*)ctx;
float menuWidth = ImGui::GetContentRegionAvailWidth(); float menuWidth = ImGui::GetContentRegionAvailWidth();
@ -211,13 +255,14 @@ private:
_this->editOpen = true; _this->editOpen = true;
_this->editedBookmark = _this->bookmarks[selectedNames[0]]; _this->editedBookmark = _this->bookmarks[selectedNames[0]];
_this->editedBookmarkName = selectedNames[0]; _this->editedBookmarkName = selectedNames[0];
_this->firstEeditedBookmarkName = selectedNames[0];
} }
if (selectedNames.size() != 1) { style::endDisabled(); } if (selectedNames.size() != 1) { style::endDisabled(); }
ImGui::EndTable(); ImGui::EndTable();
// Bookmark list // Bookmark list
ImGui::BeginTable(("freq_manager_bkm_table"+_this->name).c_str(), 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, 300)); ImGui::BeginTable(("freq_manager_bkm_table"+_this->name).c_str(), 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, 200));
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Bookmark", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Bookmark", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
@ -235,8 +280,6 @@ private:
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
ImGui::Text(freqToStr(bm.frequency).c_str()); ImGui::Text(freqToStr(bm.frequency).c_str());
ImVec2 max = ImGui::GetCursorPos(); ImVec2 max = ImGui::GetCursorPos();
} }
ImGui::EndTable(); ImGui::EndTable();
@ -249,6 +292,10 @@ private:
} }
if (selectedNames.size() != 1) { style::endDisabled(); } if (selectedNames.size() != 1) { style::endDisabled(); }
if (_this->createOpen) {
_this->createOpen = _this->bookmarkEditDialog();
}
if (_this->editOpen) { if (_this->editOpen) {
_this->editOpen = _this->bookmarkEditDialog(); _this->editOpen = _this->bookmarkEditDialog();
} }
@ -256,19 +303,30 @@ private:
std::string name; std::string name;
bool enabled = true; bool enabled = true;
bool createOpen = false;
bool editOpen = false; bool editOpen = false;
std::map<std::string, FrequencyBookmark> bookmarks; std::map<std::string, FrequencyBookmark> bookmarks;
std::string editedBookmarkName = ""; std::string editedBookmarkName = "";
std::string firstEeditedBookmarkName = "";
FrequencyBookmark editedBookmark; FrequencyBookmark editedBookmark;
std::vector<std::string> listNames;
std::string selectedListName;
int selectedListId = 0;
int testN = 0; int testN = 0;
}; };
MOD_EXPORT void _INIT_() { MOD_EXPORT void _INIT_() {
// Nothing here (testing) json def = json({});
def["selectedList"] = "General";
def["lists"]["General"] = json::array();
config.setPath(options::opts.root + "/frequency_manager_config.json");
config.load(def);
config.enableAutoSave();
} }
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) { MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {

View File

@ -2,7 +2,8 @@
enum { enum {
RADIO_IFACE_CMD_GET_MODE, RADIO_IFACE_CMD_GET_MODE,
RADIO_IFACE_CMD_SET_MODE RADIO_IFACE_CMD_SET_MODE,
RADIO_IFACE_CMD_SET_BANDWIDTH,
}; };
enum { enum {

59
root/res/themes/dark.json Normal file
View File

@ -0,0 +1,59 @@
{
"name": "Dark",
"author": "Ryzerth",
"Border": "#6D6D7F7F",
"BorderShadow": "#00000000",
"Button": "#70707066",
"ButtonActive": "#70707066",
"ButtonHovered": "#70707072",
"CheckMark": "#3D84E0FF",
"ChildBg": "#FFFFFF00",
"DragDropTarget": "#FFFF00E5",
"FrameBg": "#33353889",
"FrameBgActive": "#33353889",
"FrameBgHovered": "#33353889",
"Header": "#A0A0B24F",
"HeaderActive": "#A0A0B24F",
"HeaderHovered": "#A0A0B266",
"MenuBarBg": "#232323FF",
"ModalWindowDimBg": "#CCCCCC59",
"NavHighlight": "#999999FF",
"NavWindowingDimBg": "#CCCCCC33",
"NavWindowingHighlight": "#FFFFFFB2",
"PlotHistogram": "#BA9926FF",
"PlotHistogramHovered": "#FF9900FF",
"PlotLines": "#66E5FFFF",
"PlotLinesHovered": "#FF6D59FF",
"PopupBg": "#141414EF",
"ResizeGrip": "#E8E8E83F",
"ResizeGripActive": "#757575F2",
"ResizeGripHovered": "#CECECEAA",
"ScrollbarBg": "#05050587",
"ScrollbarGrab": "#4F4F4FFF",
"ScrollbarGrabActive": "#828282FF",
"ScrollbarGrabHovered": "#686868FF",
"Separator": "#6D6D7F7F",
"SeparatorActive": "#828282FF",
"SeparatorHovered": "#B7B7B7C6",
"SliderGrab": "#3D84E0FF",
"SliderGrabActive": "#4296F9FF",
"Tab": "#2D5993DB",
"TabActive": "#3268ADFF",
"TabHovered": "#4296F9CC",
"TabUnfocused": "#111A25F7",
"TabUnfocusedActive": "#22426CFF",
"TableBorderLight": "#3A3A3FFF",
"TableBorderStrong": "#4F4F59FF",
"TableHeaderBg": "#303033FF",
"TableRowBg": "#00000000",
"TableRowBgAlt": "#FFFFFF0F",
"Text": "#FFFFFFFF",
"TextDisabled": "#7F7F7FFF",
"TextSelectedBg": "#DDDDDD59",
"TitleBg": "#0A0A0AFF",
"TitleBgActive": "#494949FF",
"TitleBgCollapsed": "#00000082",
"WindowBg": "#0F0F0FEF",
"ClearColor": "#111111FF",
"WaterfallBackground": "#000000FF"
}

View File

@ -0,0 +1,59 @@
{
"name": "Light",
"author": "Ryzerth",
"Border": "#91917F7F",
"BorderShadow": "#FFFFFF00",
"Button": "#8E8E8E66",
"ButtonActive": "#8E8E8E66",
"ButtonHovered": "#8E8E8E72",
"CheckMark": "#C17A1EFF",
"ChildBg": "#00000000",
"DragDropTarget": "#0000FFE5",
"FrameBg": "#ACA7A389",
"FrameBgActive": "#ACA7A389",
"FrameBgHovered": "#ACA7A389",
"Header": "#5E5E4C4F",
"HeaderActive": "#5E5E4C4F",
"HeaderHovered": "#5E5E4C66",
"MenuBarBg": "#DBDBDBFF",
"ModalWindowDimBg": "#33333359",
"NavHighlight": "#666666FF",
"NavWindowingDimBg": "#33333333",
"NavWindowingHighlight": "#000000B2",
"PlotHistogram": "#4466D8FF",
"PlotHistogramHovered": "#0066FFFF",
"PlotLines": "#991900FF",
"PlotLinesHovered": "#0091A5FF",
"PopupBg": "#EAEAEAEF",
"ResizeGrip": "#1616163F",
"ResizeGripActive": "#898989F2",
"ResizeGripHovered": "#303030AA",
"ScrollbarBg": "#F9F9F987",
"ScrollbarGrab": "#AFAFAFFF",
"ScrollbarGrabActive": "#7C7C7CFF",
"ScrollbarGrabHovered": "#969696FF",
"Separator": "#91917F7F",
"SeparatorActive": "#7C7C7CFF",
"SeparatorHovered": "#474747C6",
"SliderGrab": "#C17A1EFF",
"SliderGrabActive": "#BC6805FF",
"Tab": "#D1A56BDB",
"TabActive": "#CC9651FF",
"TabHovered": "#BC6805CC",
"TabUnfocused": "#EDE4D9F7",
"TabUnfocusedActive": "#DCBC92FF",
"TableBorderLight": "#C4C4BFFF",
"TableBorderStrong": "#AFAFA5FF",
"TableHeaderBg": "#CECECCFF",
"TableRowBg": "#FFFFFF00",
"TableRowBgAlt": "#0000000F",
"Text": "#000000FF",
"TextDisabled": "#7F7F7FFF",
"TextSelectedBg": "#21212159",
"TitleBg": "#F4F4F4FF",
"TitleBgActive": "#B5B5B5FF",
"TitleBgCollapsed": "#FFFFFF82",
"WindowBg": "#EFEFEFEF",
"ClearColor": "#E6E6E6FF",
"WaterfallBackground": "#FFFFFFFF"
}