mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 13:37:42 -05:00
impr: Rework setting change listeners
This commit is contained in:
@@ -279,6 +279,8 @@ namespace hex {
|
||||
Widgets::Widget* add(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedSubCategory, const UnlocalizedString &unlocalizedName, std::unique_ptr<Widgets::Widget> &&widget);
|
||||
|
||||
void printSettingReadError(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json::exception &e);
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value);
|
||||
}
|
||||
|
||||
template<std::derived_from<Widgets::Widget> T>
|
||||
@@ -293,6 +295,28 @@ namespace hex {
|
||||
|
||||
void setCategoryDescription(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedDescription);
|
||||
|
||||
class SettingsValue {
|
||||
public:
|
||||
SettingsValue(nlohmann::json value) : m_value(std::move(value)) {}
|
||||
|
||||
template<typename T>
|
||||
T get(std::common_type_t<T> defaultValue) const {
|
||||
try {
|
||||
auto result = m_value;
|
||||
if (result.is_number() && std::same_as<T, bool>)
|
||||
result = m_value.get<int>() != 0;
|
||||
if (m_value.is_null())
|
||||
result = defaultValue;
|
||||
|
||||
return result.get<T>();
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
private:
|
||||
nlohmann::json m_value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &defaultValue) {
|
||||
auto setting = impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue);
|
||||
@@ -314,8 +338,12 @@ namespace hex {
|
||||
template<typename T>
|
||||
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &value) {
|
||||
impl::getSetting(unlocalizedCategory, unlocalizedName, value) = value;
|
||||
impl::runOnChangeHandlers(unlocalizedCategory, unlocalizedName, value);
|
||||
}
|
||||
|
||||
using OnChangeCallback = std::function<void(const SettingsValue &)>;
|
||||
u64 onChange(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const OnChangeCallback &callback);
|
||||
|
||||
}
|
||||
|
||||
/* Command Palette Command Registry. Allows adding of new commands to the command palette */
|
||||
|
||||
@@ -215,7 +215,6 @@ namespace hex {
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow *);
|
||||
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
|
||||
EVENT_DEF(EventSettingsChanged);
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
EVENT_DEF(EventThemeChanged);
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/data_processor/node.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <jthread.hpp>
|
||||
|
||||
@@ -29,6 +30,13 @@ namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
struct OnChange {
|
||||
u32 id;
|
||||
OnChangeCallback callback;
|
||||
};
|
||||
|
||||
static AutoReset<std::map<std::string, std::map<std::string, std::vector<OnChange>>>> s_onChangeCallbacks;
|
||||
|
||||
static AutoReset<nlohmann::json> s_settings;
|
||||
const nlohmann::json& getSettingsData() {
|
||||
return s_settings;
|
||||
@@ -89,6 +97,14 @@ namespace hex {
|
||||
|
||||
if (!loaded)
|
||||
store();
|
||||
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
callback(getSetting(category, name, {}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void store() {
|
||||
@@ -160,6 +176,19 @@ namespace hex {
|
||||
hex::log::error("Failed to read setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
|
||||
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
|
||||
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
|
||||
for (const auto &[id, callback] : nameIt->second) {
|
||||
try {
|
||||
callback(value);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -169,6 +198,43 @@ namespace hex {
|
||||
category->unlocalizedDescription = unlocalizedDescription;
|
||||
}
|
||||
|
||||
u64 onChange(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const OnChangeCallback &callback) {
|
||||
static u64 id = 1;
|
||||
(*impl::s_onChangeCallbacks)[unlocalizedCategory][unlocalizedName].emplace_back(id, callback);
|
||||
|
||||
auto result = id;
|
||||
id += 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void removeOnChangeHandler(u64 id) {
|
||||
bool done = false;
|
||||
auto categoryIt = impl::s_onChangeCallbacks->begin();
|
||||
for (; categoryIt != impl::s_onChangeCallbacks->end(); ++categoryIt) {
|
||||
auto nameIt = categoryIt->second.begin();
|
||||
for (; nameIt != categoryIt->second.end(); ++nameIt) {
|
||||
done = std::erase_if(nameIt->second, [id](const impl::OnChange &entry) {
|
||||
return entry.id == id;
|
||||
}) > 0;
|
||||
|
||||
if (done) break;
|
||||
}
|
||||
|
||||
if (done) {
|
||||
if (nameIt->second.empty())
|
||||
categoryIt->second.erase(nameIt);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (done) {
|
||||
if (categoryIt->second.empty())
|
||||
impl::s_onChangeCallbacks->erase(categoryIt);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Widgets {
|
||||
|
||||
bool Checkbox::draw(const std::string &name) {
|
||||
|
||||
Reference in New Issue
Block a user