diff --git a/CMakeLists.txt b/CMakeLists.txt index 298dcaca9..69f46ddaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,7 @@ add_executable(imhex ${application_type} source/views/view_bookmarks.cpp source/views/view_patches.cpp source/views/view_command_palette.cpp + source/views/view_settings.cpp ${imhex_icon} ) diff --git a/include/views/view_settings.hpp b/include/views/view_settings.hpp new file mode 100644 index 000000000..65cf61ec9 --- /dev/null +++ b/include/views/view_settings.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "views/view.hpp" + +#include +#include + +namespace hex { + + class ViewSettings : public View { + public: + explicit ViewSettings(); + ~ViewSettings() override; + + void drawContent() override; + void drawMenu() override; + + bool hasViewMenuItemEntry() override { return false; } + private: + bool m_settingsWindowOpen = false; + }; + +} \ No newline at end of file diff --git a/plugins/libimhex/CMakeLists.txt b/plugins/libimhex/CMakeLists.txt index ed39d5c54..bdea2a4a6 100644 --- a/plugins/libimhex/CMakeLists.txt +++ b/plugins/libimhex/CMakeLists.txt @@ -12,6 +12,7 @@ endif() add_library(libimhex STATIC source/helpers/event.cpp source/helpers/utils.cpp + source/helpers/content_registry.cpp source/providers/provider.cpp diff --git a/plugins/libimhex/include/helpers/content_registry.hpp b/plugins/libimhex/include/helpers/content_registry.hpp new file mode 100644 index 000000000..f8c443354 --- /dev/null +++ b/plugins/libimhex/include/helpers/content_registry.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include + +namespace hex { + + class ContentRegistry { + public: + ContentRegistry() = delete; + + struct Settings { + Settings() = delete; + + struct Entry { + std::string name; + std::function callback; + }; + + static void load(); + static void store(); + + static void add(std::string_view category, std::string_view name, s64 defaultValue, const std::function &callback); + static void add(std::string_view category, std::string_view name, std::string_view defaultValue, const std::function &callback); + + static std::map>& getEntries(); + static nlohmann::json& getSettingsData(); + }; + }; + +} \ No newline at end of file diff --git a/plugins/libimhex/include/helpers/event.hpp b/plugins/libimhex/include/helpers/event.hpp index 791748723..528f7a07d 100644 --- a/plugins/libimhex/include/helpers/event.hpp +++ b/plugins/libimhex/include/helpers/event.hpp @@ -19,7 +19,9 @@ namespace hex { AppendPatternLanguageCode, ProjectFileStore, - ProjectFileLoad + ProjectFileLoad, + + SettingsChanged }; struct EventHandler { diff --git a/plugins/libimhex/include/helpers/shared_data.hpp b/plugins/libimhex/include/helpers/shared_data.hpp index 38f049356..a7fcd2061 100644 --- a/plugins/libimhex/include/helpers/shared_data.hpp +++ b/plugins/libimhex/include/helpers/shared_data.hpp @@ -1,10 +1,14 @@ #pragma once +#include #include #include #include +#include + #include +#include namespace hex { class SharedData; } @@ -31,18 +35,34 @@ namespace hex { friend void hex::plugin::internal::initializePlugin(SharedData &sharedData); friend class Window; + template + T& getVariable(std::string variableName) { + return std::any_cast((*this->sharedVariables)[variableName]); + } + + template + void setVariable(std::string variableName, T value) { + (*this->sharedVariables)[variableName] = value; + } + private: void initializeData() { static std::vector eventHandlersStorage; static std::vector> deferredCallsStorage; static prv::Provider *currentProviderStorage; + static std::map> settingsEntriesStorage; + static std::map sharedVariablesStorage; static ImVec2 windowPosStorage, windowSizeStorage; + static nlohmann::json settingsJsonStorage; this->imguiContext = ImGui::GetCurrentContext(); this->eventHandlers = &eventHandlersStorage; this->deferredCalls = &deferredCallsStorage; this->currentProvider = ¤tProviderStorage; + this->settingsEntries = &settingsEntriesStorage; + this->sharedVariables = &sharedVariablesStorage; + this->settingsJson = &settingsJsonStorage; this->windowPos = &windowPosStorage; this->windowSize = &windowSizeStorage; @@ -53,6 +73,9 @@ namespace hex { this->eventHandlers = other.eventHandlers; this->deferredCalls = other.deferredCalls; this->currentProvider = other.currentProvider; + this->settingsEntries = other.settingsEntries; + this->sharedVariables = other.sharedVariables; + this->settingsJson = other.settingsJson; this->windowPos = other.windowPos; this->windowSize = other.windowSize; @@ -63,9 +86,14 @@ namespace hex { std::vector *eventHandlers; std::vector> *deferredCalls; prv::Provider **currentProvider; + std::map> *settingsEntries; + nlohmann::json *settingsJson; ImVec2 *windowPos; ImVec2 *windowSize; + + private: + std::map *sharedVariables; }; } \ No newline at end of file diff --git a/plugins/libimhex/source/helpers/content_registry.cpp b/plugins/libimhex/source/helpers/content_registry.cpp new file mode 100644 index 000000000..a0a23ada0 --- /dev/null +++ b/plugins/libimhex/source/helpers/content_registry.cpp @@ -0,0 +1,50 @@ +#include + +#include + +#include +#include + +namespace hex { + + /* Settings */ + + void ContentRegistry::Settings::load() { + std::ifstream settingsFile(std::filesystem::path(mainArgv[0]).parent_path() / "settings.json"); + + if (settingsFile.good()) + settingsFile >> getSettingsData(); + } + + void ContentRegistry::Settings::store() { + std::ofstream settingsFile(std::filesystem::path(mainArgv[0]).parent_path() / "settings.json", std::ios::trunc); + settingsFile << getSettingsData(); + } + + void ContentRegistry::Settings::add(std::string_view category, std::string_view name, s64 defaultValue, const std::function &callback) { + ContentRegistry::Settings::getEntries()[category.data()].emplace_back(Entry{ name.data(), callback }); + + auto &json = (*SharedData::get().settingsJson); + + if (!json.contains(category.data())) + json[category.data()] = nlohmann::json::object(); + if (!json[category.data()].contains(name.data())) + json[category.data()][name.data()] = defaultValue; + } + + void ContentRegistry::Settings::add(std::string_view category, std::string_view name, std::string_view defaultValue, const std::function &callback) { + ContentRegistry::Settings::getEntries()[category.data()].emplace_back(Entry{ name.data(), callback }); + + (*SharedData::get().settingsJson)[category.data()] = nlohmann::json::object(); + (*SharedData::get().settingsJson)[category.data()][name.data()] = defaultValue; + } + + std::map>& ContentRegistry::Settings::getEntries() { + return *SharedData::get().settingsEntries; + } + + nlohmann::json& ContentRegistry::Settings::getSettingsData() { + return *SharedData::get().settingsJson; + } + +} \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 4dfe584eb..ff054a6ed 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -15,6 +15,7 @@ #include "views/view_bookmarks.hpp" #include "views/view_patches.hpp" #include "views/view_command_palette.hpp" +#include "views/view_settings.hpp" #include "providers/provider.hpp" @@ -46,6 +47,7 @@ int main(int argc, char **argv) { window.addView(); window.addView(); window.addView(); + window.addView(); if (argc > 1) hex::View::postEvent(hex::Events::FileDropped, argv[1]); diff --git a/source/views/view_settings.cpp b/source/views/view_settings.cpp new file mode 100644 index 000000000..c9729908a --- /dev/null +++ b/source/views/view_settings.cpp @@ -0,0 +1,47 @@ +#include "views/view_settings.hpp" + +#include "helpers/content_registry.hpp" + +namespace hex { + + ViewSettings::ViewSettings() : View("Settings") { + this->getWindowOpenState() = true; + } + + ViewSettings::~ViewSettings() { + + } + + void ViewSettings::drawContent() { + + ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX)); + + if (ImGui::BeginPopupModal("Preferences", &this->m_settingsWindowOpen, ImGuiWindowFlags_AlwaysAutoResize)) { + for (auto &[category, entries] : ContentRegistry::Settings::getEntries()) { + ImGui::TextUnformatted(category.c_str()); + ImGui::Separator(); + for (auto &[name, callback] : entries) { + ImGui::TextUnformatted(name.c_str()); + ImGui::SameLine(); + if (callback(ContentRegistry::Settings::getSettingsData()[category][name])) + View::postEvent(Events::SettingsChanged, nullptr); + ImGui::NewLine(); + } + ImGui::NewLine(); + } + ImGui::EndPopup(); + } + + } + + void ViewSettings::drawMenu() { + if (ImGui::BeginMenu("Help")) { + if (ImGui::MenuItem("Preferences")) { + View::doLater([]{ ImGui::OpenPopup("Preferences"); }); + this->m_settingsWindowOpen = true; + } + ImGui::EndMenu(); + } + } + +} \ No newline at end of file diff --git a/source/window.cpp b/source/window.cpp index cbdfdda51..34beb1ec5 100644 --- a/source/window.cpp +++ b/source/window.cpp @@ -12,6 +12,7 @@ #include "imgui_freetype.h" #include "helpers/plugin_handler.hpp" +#include "helpers/content_registry.hpp" #include #include @@ -49,6 +50,8 @@ namespace hex { Window::Window() { SharedData::get().initializeData(); + ContentRegistry::Settings::load(); + View::postEvent(Events::SettingsChanged, nullptr); this->initGLFW(); this->initImGui(); @@ -59,6 +62,7 @@ namespace hex { this->deinitImGui(); this->deinitGLFW(); this->deinitPlugins(); + ContentRegistry::Settings::store(); for (auto &view : this->m_views) delete view;