sys: Replace the terrible event manager with a much better one

This commit is contained in:
WerWolv 2021-03-27 11:36:36 +01:00
parent 688ca01b1b
commit d805d976a6
27 changed files with 206 additions and 227 deletions

View File

@ -48,7 +48,7 @@
#include <stdint.h> // uint8_t, etc.
#include <hex/helpers/utils.hpp>
#include <hex/views/view.hpp>
#include <hex/api/event.hpp>
#include <string>
@ -223,7 +223,7 @@ struct MemoryEditor
{
if (DataPreviewAddr != DataPreviewAddrOld || DataPreviewAddrEnd != DataPreviewAddrEndOld) {
hex::Region selectionRegion = { std::min(DataPreviewAddr, DataPreviewAddrEnd), std::max(DataPreviewAddr, DataPreviewAddrEnd) - std::min(DataPreviewAddr, DataPreviewAddrEnd) };
hex::View::postEvent(hex::Events::RegionSelected, selectionRegion);
hex::EventManager::post<hex::EventRegionSelected>(selectionRegion);
}
DataPreviewAddrOld = DataPreviewAddr;

View File

@ -55,13 +55,6 @@ namespace hex {
static nlohmann::json& getSettingsData();
};
/* Events Registry. Allows to define new events that can be used by other plugins later on subscribe to */
struct Events {
Events() = delete;
static auto get(std::string_view name);
};
/* Command Palette Command Registry. Allows adding of new commands to the command palette */
struct CommandPaletteCommands {
CommandPaletteCommands() = delete;

View File

@ -2,48 +2,114 @@
#include <hex.hpp>
#include <any>
#include <list>
#include <map>
#include <string_view>
#include <functional>
#include <vector>
#include <hex/api/imhex_api.hpp>
#define EVENT_DEF(event_name, ...) \
struct event_name final : public hex::Event<__VA_ARGS__> { \
constexpr static auto id = [] { return hex::EventId(); }(); \
event_name(Callback func) noexcept : Event(func) { } \
};
class GLFWwindow;
namespace hex {
enum class Events : u32 {
FileLoaded,
DataChanged,
PatternChanged,
FileDropped,
WindowClosing,
RegionSelected,
class EventId {
public:
constexpr EventId(const char *func = __builtin_FUNCTION(), u32 line = __builtin_LINE()) {
this->m_hash = line ^ 123456789;
for (auto c : std::string_view(func)) {
this->m_hash = (this->m_hash >> 5) | (this->m_hash << 27);
this->m_hash ^= c;
}
}
SelectionChangeRequest,
constexpr bool operator ==(const EventId &rhs) const = default;
AddBookmark,
AppendPatternLanguageCode,
ProjectFileStore,
ProjectFileLoad,
SettingsChanged,
OpenWindow,
CloseImHex,
/* This is not a real event but a flag to show all events after this one are plugin ones */
Events_BuiltinEnd
private:
u32 m_hash;
};
struct EventHandler {
void *owner;
Events eventType;
std::function<std::any(const std::any&)> callback;
struct EventBase {
EventBase() noexcept = default;
};
template<typename ... Params>
struct Event : public EventBase {
using Callback = std::function<void(Params...)>;
explicit Event(Callback func) noexcept : m_func(func) {}
void operator()(Params... params) const noexcept {
this->m_func(params...);
}
private:
Callback m_func;
};
class EventManager {
public:
static std::vector<std::any> post(Events eventType, const std::any &userData);
static void subscribe(Events eventType, void *owner, std::function<std::any(const std::any&)> callback);
static void unsubscribe(Events eventType, void *sender);
using EventList = std::list<std::pair<EventId, EventBase*>>;
template<typename E>
[[nodiscard]] static EventList::iterator subscribe(typename E::Callback function) {
return s_events.insert(s_events.end(), std::make_pair(E::id, new E(function)));
}
template<typename E>
static void subscribe(void *token, typename E::Callback function) {
s_tokenStore.insert(std::make_pair(token, subscribe<E>(function)));
}
static void unsubscribe(EventList::iterator iter) noexcept {
s_events.remove(*iter);
}
template<typename E>
static void unsubscribe(void *token) noexcept {
auto iter = std::find_if(s_tokenStore.begin(), s_tokenStore.end(), [&](auto &item){
return item.first == token && item.second->first == E::id;
});
if (iter != s_tokenStore.end()) {
s_events.remove(*iter->second);
}
}
template<typename E>
static void post(auto ... args) noexcept {
for (const auto &[id, event] : s_events) {
if (id == E::id)
(*reinterpret_cast<E *>(event))(args...);
}
}
private:
static std::map<void*, EventList::iterator> s_tokenStore;
static EventList s_events;
};
/* Default Events */
EVENT_DEF(EventFileLoaded, std::string);
EVENT_DEF(EventDataChanged);
EVENT_DEF(EventPatternChanged);
EVENT_DEF(EventFileDropped, std::string);
EVENT_DEF(EventWindowClosing, GLFWwindow*);
EVENT_DEF(EventRegionSelected, Region);
EVENT_DEF(EventProjectFileStore);
EVENT_DEF(EventProjectFileLoad);
EVENT_DEF(EventSettingsChanged);
EVENT_DEF(RequestOpenWindow, std::string);
EVENT_DEF(RequestSelectionChange, Region);
EVENT_DEF(RequestAddBookmark, ImHexApi::Bookmarks::Entry);
EVENT_DEF(RequestAppendPatternLanguageCode, std::string);
EVENT_DEF(RequestCloseImHex);
}

View File

@ -9,7 +9,6 @@
#include <hex/api/content_registry.hpp>
#include <hex/api/imhex_api.hpp>
#include <hex/api/event.hpp>
#include <hex/views/view.hpp>
#include <imgui.h>
@ -47,13 +46,10 @@ namespace hex {
}
public:
static std::vector<EventHandler> eventHandlers;
static std::vector<std::function<void()>> deferredCalls;
static prv::Provider *currentProvider;
static std::map<std::string, std::vector<ContentRegistry::Settings::Entry>> settingsEntries;
static nlohmann::json settingsJson;
static std::map<std::string, Events> customEvents;
static u32 customEventsLastId;
static std::vector<ContentRegistry::CommandPaletteCommands::Entry> commandPaletteCommands;
static std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> patternLanguageFunctions;
static std::vector<View*> views;

View File

@ -154,8 +154,7 @@ namespace hex::lang {
ImGui::TreeNodeEx(this->getVariableName().c_str(), ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_AllowItemOverlap);
ImGui::TableNextColumn();
if (ImGui::Selectable(("##PatternDataLine"s + std::to_string(this->getOffset())).c_str(), false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap)) {
Region selectRegion = { this->getOffset(), this->getSize() };
View::postEvent(Events::SelectionChangeRequest, selectRegion);
EventManager::post<RequestSelectionChange>(Region { this->getOffset(), this->getSize() });
}
this->drawCommentTooltip();
ImGui::SameLine();
@ -743,8 +742,7 @@ namespace hex::lang {
this->drawCommentTooltip();
ImGui::TableNextColumn();
if (ImGui::Selectable(("##PatternDataLine"s + std::to_string(this->getOffset())).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
Region selectRegion = { this->getOffset(), this->getSize() };
View::postEvent(Events::SelectionChangeRequest, selectRegion);
EventManager::post<RequestSelectionChange>(Region { this->getOffset(), this->getSize() });
}
ImGui::SameLine();
ImGui::Text("%s", this->getVariableName().c_str());

View File

@ -40,8 +40,6 @@ namespace hex {
static void doLater(std::function<void()> &&function);
static std::vector<std::function<void()>>& getDeferedCalls();
static std::vector<std::any> postEvent(Events eventType, const std::any &userData = { });
static void drawCommonInterfaces();
static void showErrorPopup(std::string_view errorMessage);
@ -55,11 +53,6 @@ namespace hex {
std::string_view getUnlocalizedName() const;
protected:
void subscribeEvent(Events eventType, const std::function<std::any(const std::any&)> &callback);
void subscribeEvent(Events eventType, const std::function<void(const std::any&)> &callback);
void unsubscribeEvent(Events eventType);
void discardNavigationRequests();
void confirmButtons(const char *textLeft, const char *textRight, const std::function<void()> &leftButtonFn, const std::function<void()> &rightButtonFn);

View File

@ -133,21 +133,6 @@ namespace hex {
}
/* Events */
auto ContentRegistry::Events::get(std::string_view name) {
auto &customEvents = SharedData::customEvents;
auto &lastId = SharedData::customEventsLastId;
if (!customEvents.contains(name.data())) {
customEvents[name.data()] = static_cast<hex::Events>(lastId);
lastId++;
}
return customEvents[name.data()];
}
/* Command Palette Commands */
void ContentRegistry::CommandPaletteCommands::add(ContentRegistry::CommandPaletteCommands::Type type, std::string_view command, std::string_view unlocalizedDescription, const std::function<std::string(std::string)> &displayCallback, const std::function<void(std::string)> &executeCallback) {
@ -225,7 +210,7 @@ namespace hex {
void ContentRegistry::Language::addLocalizations(std::string_view languageCode, const LanguageDefinition &definition) {
getLanguageDefinitions()[languageCode.data()].push_back(definition);
EventManager::post(hex::Events::SettingsChanged, {});
EventManager::post<EventSettingsChanged>();
}
std::map<std::string, std::string>& ContentRegistry::Language::getLanguages() {

View File

@ -1,30 +1,8 @@
#include <hex/api/event.hpp>
#include <hex/helpers/shared_data.hpp>
namespace hex {
std::vector<std::any> EventManager::post(Events eventType, const std::any &userData) {
std::vector<std::any> results;
for (auto &handler : SharedData::eventHandlers)
if (eventType == handler.eventType)
results.push_back(handler.callback(userData));
return results;
}
void EventManager::subscribe(Events eventType, void *owner, std::function<std::any(const std::any&)> callback) {
for (auto &handler : SharedData::eventHandlers)
if (eventType == handler.eventType && owner == handler.owner)
return;
SharedData::eventHandlers.push_back(EventHandler { owner, eventType, callback });
}
void EventManager::unsubscribe(Events eventType, void *sender) {
std::erase_if(SharedData::eventHandlers, [&eventType, &sender](EventHandler handler) {
return eventType == handler.eventType && sender == handler.owner;
});
}
std::map<void*, EventManager::EventList::iterator> EventManager::s_tokenStore;
EventManager::EventList EventManager::s_events;
}

View File

@ -18,7 +18,7 @@ namespace hex {
entry.color = color;
EventManager::post(Events::AddBookmark, entry);
EventManager::post<RequestAddBookmark>(entry);
}
void ImHexApi::Bookmarks::add(u64 addr, size_t size, std::string_view name, std::string_view comment, u32 color) {

View File

@ -2,13 +2,10 @@
namespace hex {
std::vector<EventHandler> SharedData::eventHandlers;
std::vector<std::function<void()>> SharedData::deferredCalls;
prv::Provider *SharedData::currentProvider;
std::map<std::string, std::vector<ContentRegistry::Settings::Entry>> SharedData::settingsEntries;
nlohmann::json SharedData::settingsJson;
std::map<std::string, Events> SharedData::customEvents;
u32 SharedData::customEventsLastId;
std::vector<ContentRegistry::CommandPaletteCommands::Entry> SharedData::commandPaletteCommands;
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> SharedData::patternLanguageFunctions;
std::vector<View*> SharedData::views;

View File

@ -24,10 +24,6 @@ namespace hex {
return SharedData::deferredCalls;
}
std::vector<std::any> View::postEvent(Events eventType, const std::any &userData) {
return EventManager::post(eventType, userData);
}
void View::openFileBrowser(std::string_view title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::string)> &callback) {
NFD::Init();
@ -93,18 +89,6 @@ namespace hex {
return this->m_unlocalizedViewName;
}
void View::subscribeEvent(Events eventType, const std::function<std::any(const std::any&)> &callback) {
EventManager::subscribe(eventType, this, callback);
}
void View::subscribeEvent(Events eventType, const std::function<void(const std::any&)> &callback) {
EventManager::subscribe(eventType, this, [callback](auto userData) -> std::any { callback(userData); return { }; });
}
void View::unsubscribeEvent(Events eventType) {
EventManager::unsubscribe(eventType, this);
}
void View::discardNavigationRequests() {
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows))
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard;

View File

@ -163,7 +163,7 @@ namespace hex {
code += "};\n";
View::postEvent(Events::AppendPatternLanguageCode, code.c_str());
EventManager::post<RequestAppendPatternLanguageCode>(code);
Py_RETURN_NONE;
}

View File

@ -53,7 +53,7 @@ int main(int argc, char **argv) {
ContentRegistry::Views::add<ViewYara>();
if (argc > 1)
View::postEvent(Events::FileDropped, const_cast<const char*>(argv[1]));
EventManager::post<EventFileDropped>(argv[1]);
window.loop();

View File

@ -8,8 +8,7 @@
namespace hex {
ViewBookmarks::ViewBookmarks() : View("hex.view.bookmarks.name") {
View::subscribeEvent(Events::AddBookmark, [](auto userData) {
auto bookmark = std::any_cast<ImHexApi::Bookmarks::Entry>(userData);
EventManager::subscribe<RequestAddBookmark>(this, [](ImHexApi::Bookmarks::Entry bookmark) {
bookmark.comment.resize(0xF'FFFF);
if (bookmark.name.empty()) {
@ -29,18 +28,19 @@ namespace hex {
ProjectFile::markDirty();
});
View::subscribeEvent(Events::ProjectFileLoad, [](auto) {
EventManager::subscribe<EventProjectFileLoad>(this, []{
SharedData::bookmarkEntries = ProjectFile::getBookmarks();
});
View::subscribeEvent(Events::ProjectFileStore, [](auto) {
EventManager::subscribe<EventProjectFileStore>(this, []{
ProjectFile::setBookmarks(SharedData::bookmarkEntries);
});
}
ViewBookmarks::~ViewBookmarks() {
View::unsubscribeEvent(Events::AddBookmark);
View::unsubscribeEvent(Events::ProjectFileLoad);
View::unsubscribeEvent(Events::ProjectFileStore);
EventManager::unsubscribe<RequestAddBookmark>(this);
EventManager::unsubscribe<EventProjectFileLoad>(this);
EventManager::unsubscribe<EventProjectFileStore>(this);
}
void ViewBookmarks::drawContent() {
@ -90,7 +90,7 @@ namespace hex {
ImGui::TextColored(ImColor(0xFF9BC64D), "%s", bytesString.c_str());
}
if (ImGui::Button("hex.view.bookmarks.button.jump"_lang))
View::postEvent(Events::SelectionChangeRequest, region);
EventManager::post<RequestSelectionChange>(region);
ImGui::SameLine(0, 15);
if (ImGui::Button("hex.view.bookmarks.button.remove"_lang))

View File

@ -11,9 +11,7 @@ namespace hex {
using NumberDisplayStyle = ContentRegistry::DataInspector::NumberDisplayStyle;
ViewDataInspector::ViewDataInspector() : View("hex.view.data_inspector.name") {
View::subscribeEvent(Events::RegionSelected, [this](auto userData) {
auto region = std::any_cast<Region>(userData);
EventManager::subscribe<EventRegionSelected>(this, [this](Region region) {
auto provider = SharedData::currentProvider;
if (provider == nullptr) {
@ -34,7 +32,7 @@ namespace hex {
}
ViewDataInspector::~ViewDataInspector() {
View::unsubscribeEvent(Events::RegionSelected);
EventManager::unsubscribe<EventRegionSelected>(this);
}
void ViewDataInspector::drawContent() {

View File

@ -17,7 +17,7 @@ namespace hex {
io.link_detach_with_modifier_click.modifier = &always;
}
View::subscribeEvent(Events::SettingsChanged, [](auto) {
EventManager::subscribe<EventSettingsChanged>(this, [] {
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
if (theme.is_number()) {
@ -38,7 +38,7 @@ namespace hex {
}
});
View::subscribeEvent(Events::FileLoaded, [this](auto) {
EventManager::subscribe<EventFileLoaded>(this, [this](const std::string &path){
for (auto &node : this->m_nodes) {
node->setCurrentOverlay(nullptr);
}
@ -50,6 +50,9 @@ namespace hex {
for (auto &node : this->m_nodes)
delete node;
EventManager::unsubscribe<EventSettingsChanged>(this);
EventManager::unsubscribe<EventFileLoaded>(this);
imnodes::PopAttributeFlag();
imnodes::PopAttributeFlag();
imnodes::Shutdown();

View File

@ -13,13 +13,11 @@ using namespace std::literals::string_literals;
namespace hex {
ViewDisassembler::ViewDisassembler() : View("hex.view.disassembler.name") {
View::subscribeEvent(Events::DataChanged, [this](auto){
EventManager::subscribe<EventDataChanged>(this, [this]() {
this->disassemble();
});
View::subscribeEvent(Events::RegionSelected, [this](auto userData) {
auto region = std::any_cast<Region>(userData);
EventManager::subscribe<EventRegionSelected>(this, [this](Region region) {
if (this->m_shouldMatchSelection) {
this->m_codeRegion[0] = region.address;
this->m_codeRegion[1] = region.address + region.size - 1;
@ -28,8 +26,8 @@ namespace hex {
}
ViewDisassembler::~ViewDisassembler() {
View::unsubscribeEvent(Events::DataChanged);
View::unsubscribeEvent(Events::RegionSelected);
EventManager::unsubscribe<EventDataChanged>(this);
EventManager::unsubscribe<EventRegionSelected>(this);
}
void ViewDisassembler::disassemble() {
@ -273,8 +271,7 @@ namespace hex {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::Selectable(("##DisassemblyLine"s + std::to_string(i)).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
Region selectRegion = { this->m_disassembly[i].offset, this->m_disassembly[i].size };
View::postEvent(Events::SelectionChangeRequest, selectRegion);
EventManager::post<RequestSelectionChange>(Region { this->m_disassembly[i].offset, this->m_disassembly[i].size });
}
ImGui::SameLine();
ImGui::Text("0x%llx", this->m_disassembly[i].address);

View File

@ -10,13 +10,11 @@
namespace hex {
ViewHashes::ViewHashes() : View("hex.view.hashes.name") {
View::subscribeEvent(Events::DataChanged, [this](auto) {
EventManager::subscribe<EventDataChanged>(this, [this]() {
this->m_shouldInvalidate = true;
});
View::subscribeEvent(Events::RegionSelected, [this](auto userData) {
auto region = std::any_cast<const Region>(userData);
EventManager::subscribe<EventRegionSelected>(this, [this](Region region) {
if (this->m_shouldMatchSelection) {
this->m_hashRegion[0] = region.address;
this->m_hashRegion[1] = region.address + region.size - 1;
@ -26,8 +24,8 @@ namespace hex {
}
ViewHashes::~ViewHashes() {
View::unsubscribeEvent(Events::DataChanged);
View::unsubscribeEvent(Events::RegionSelected);
EventManager::unsubscribe<EventDataChanged>(this);
EventManager::unsubscribe<EventRegionSelected>(this);
}

View File

@ -39,7 +39,7 @@ namespace hex {
return;
provider->write(off, &d, sizeof(ImU8));
View::postEvent(Events::DataChanged);
EventManager::post<EventDataChanged>();
ProjectFile::markDirty();
};
@ -124,16 +124,11 @@ namespace hex {
return { std::string(decoded), advance, color };
};
View::subscribeEvent(Events::FileDropped, [this](auto userData) {
auto filePath = std::any_cast<const char*>(userData);
if (filePath != nullptr)
this->openFile(filePath);
EventManager::subscribe<EventFileDropped>(this, [this](const std::string &filePath) {
this->openFile(filePath);
});
View::subscribeEvent(Events::SelectionChangeRequest, [this](auto userData) {
const Region &region = std::any_cast<Region>(userData);
EventManager::subscribe<RequestSelectionChange>(this, [this](Region region) {
auto provider = SharedData::currentProvider;
auto page = provider->getPageOfAddress(region.address);
if (!page.has_value())
@ -141,39 +136,37 @@ namespace hex {
provider->setCurrentPage(page.value());
this->m_memoryEditor.GotoAddrAndHighlight(region.address, region.address + region.size - 1);
View::postEvent(Events::RegionSelected, region);
EventManager::post<EventRegionSelected>(region);
});
View::subscribeEvent(Events::ProjectFileLoad, [this](auto) {
EventManager::subscribe<EventProjectFileLoad>(this, [this]() {
this->openFile(ProjectFile::getFilePath());
});
View::subscribeEvent(Events::WindowClosing, [this](auto userData) {
auto window = std::any_cast<GLFWwindow*>(userData);
EventManager::subscribe<EventWindowClosing>(this, [](GLFWwindow *window) {
if (ProjectFile::hasUnsavedChanges()) {
glfwSetWindowShouldClose(window, GLFW_FALSE);
View::doLater([] { ImGui::OpenPopup("hex.view.hexeditor.save_changes.title"_lang); });
}
});
View::subscribeEvent(Events::PatternChanged, [this](auto) {
EventManager::subscribe<EventPatternChanged>(this, [this]() {
this->m_highlightedBytes.clear();
for (const auto &pattern : this->m_patternData)
this->m_highlightedBytes.merge(pattern->getHighlightedAddresses());
});
View::subscribeEvent(Events::OpenWindow, [this](auto name) {
if (std::any_cast<const char*>(name) == std::string("Open File")) {
EventManager::subscribe<RequestOpenWindow>(this, [this](std::string name) {
if (name == "Open File") {
View::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
this->openFile(path);
this->getWindowOpenState() = true;
});
} else if (std::any_cast<const char*>(name) == std::string("Open Project")) {
} else if (name == "Open Project") {
View::openFileBrowser("hex.view.hexeditor.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
ProjectFile::load(path);
View::postEvent(Events::ProjectFileLoad);
EventManager::post<EventProjectFileLoad>();
this->getWindowOpenState() = true;
});
}
@ -181,7 +174,12 @@ namespace hex {
}
ViewHexEditor::~ViewHexEditor() {
EventManager::unsubscribe<EventFileDropped>(this);
EventManager::unsubscribe<RequestSelectionChange>(this);
EventManager::unsubscribe<EventProjectFileLoad>(this);
EventManager::unsubscribe<EventWindowClosing>(this);
EventManager::unsubscribe<EventPatternChanged>(this);
EventManager::unsubscribe<RequestOpenWindow>(this);
}
void ViewHexEditor::drawContent() {
@ -211,8 +209,7 @@ namespace hex {
if (ImGui::ArrowButton("prevPage", ImGuiDir_Left)) {
provider->setCurrentPage(provider->getCurrentPage() - 1);
Region dataPreview = { std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd), 1 };
View::postEvent(Events::RegionSelected, dataPreview);
EventManager::post<EventRegionSelected>(Region { std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd), 1 });
}
ImGui::SameLine();
@ -220,8 +217,7 @@ namespace hex {
if (ImGui::ArrowButton("nextPage", ImGuiDir_Right)) {
provider->setCurrentPage(provider->getCurrentPage() + 1);
Region dataPreview = { std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd), 1 };
View::postEvent(Events::RegionSelected, dataPreview);
EventManager::post<EventRegionSelected>(Region { std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd), 1 });
}
}
ImGui::End();
@ -269,7 +265,12 @@ namespace hex {
ImGui::TextUnformatted("hex.view.hexeditor.save_changes.desc"_lang);
ImGui::NewLine();
confirmButtons("hex.common.yes"_lang, "hex.common.no"_lang, [] { View::postEvent(Events::CloseImHex); }, [] { ImGui::CloseCurrentPopup(); });
confirmButtons("hex.common.yes"_lang, "hex.common.no"_lang, [] {
EventManager::post<RequestCloseImHex>();
},
[] {
ImGui::CloseCurrentPopup();
});
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
ImGui::CloseCurrentPopup();
@ -364,13 +365,13 @@ namespace hex {
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.open_project"_lang, "")) {
View::openFileBrowser("hex.view.hexeditor.menu.file.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
ProjectFile::load(path);
View::postEvent(Events::ProjectFileLoad);
EventManager::post<EventProjectFileLoad>();
this->getWindowOpenState() = true;
});
}
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.save_project"_lang, "", false, provider != nullptr && provider->isWritable())) {
View::postEvent(Events::ProjectFileStore);
EventManager::post<EventProjectFileStore>();
if (ProjectFile::getProjectFilePath() == "") {
View::openFileBrowser("hex.view.hexeditor.save_project"_lang, DialogMode::Save, { { "Project File", "hexproj" } }, [](auto path) {
@ -560,9 +561,9 @@ namespace hex {
this->getWindowOpenState() = true;
View::postEvent(Events::FileLoaded, path);
View::postEvent(Events::DataChanged);
View::postEvent(Events::PatternChanged);
EventManager::post<EventFileLoaded>(path);
EventManager::post<EventDataChanged>();
EventManager::post<EventPatternChanged>();
}
bool ViewHexEditor::saveToFile(std::string path, const std::vector<u8>& data) {

View File

@ -19,7 +19,7 @@
namespace hex {
ViewInformation::ViewInformation() : View("hex.view.information.name") {
View::subscribeEvent(Events::DataChanged, [this](auto) {
EventManager::subscribe<EventDataChanged>(this, [this]() {
this->m_dataValid = false;
this->m_highestBlockEntropy = 0;
this->m_blockEntropy.clear();
@ -33,7 +33,7 @@ namespace hex {
}
ViewInformation::~ViewInformation() {
View::unsubscribeEvent(Events::DataChanged);
EventManager::unsubscribe<EventDataChanged>(this);
}
static float calculateEntropy(std::array<ImU64, 256> &valueCounts, size_t numBytes) {
@ -209,7 +209,7 @@ namespace hex {
ImPlot::PlotLine("##entropy_line", this->m_blockEntropy.data(), this->m_blockEntropy.size());
if (ImGui::IsItemClicked())
View::postEvent(Events::SelectionChangeRequest, Region{ u64(ImPlot::GetPlotMousePos().x) * this->m_blockSize, 1 });
EventManager::post<RequestSelectionChange>( Region{ u64(ImPlot::GetPlotMousePos().x) * this->m_blockSize, 1 });
ImPlot::EndPlot();
}

View File

@ -12,13 +12,13 @@ using namespace std::literals::string_literals;
namespace hex {
ViewPatches::ViewPatches() : View("hex.view.patches.name") {
View::subscribeEvent(Events::ProjectFileStore, [](auto) {
EventManager::subscribe<EventProjectFileStore>(this, []{
auto provider = SharedData::currentProvider;
if (provider != nullptr)
ProjectFile::setPatches(provider->getPatches());
});
View::subscribeEvent(Events::ProjectFileLoad, [](auto) {
EventManager::subscribe<EventProjectFileLoad>(this, []{
auto provider = SharedData::currentProvider;
if (provider != nullptr)
provider->getPatches() = ProjectFile::getPatches();
@ -26,8 +26,8 @@ namespace hex {
}
ViewPatches::~ViewPatches() {
View::unsubscribeEvent(Events::ProjectFileStore);
View::unsubscribeEvent(Events::ProjectFileLoad);
EventManager::unsubscribe<EventProjectFileStore>(this);
EventManager::unsubscribe<EventProjectFileLoad>(this);
}
void ViewPatches::drawContent() {
@ -52,8 +52,7 @@ namespace hex {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::Selectable(("##patchLine" + std::to_string(index)).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
Region selectRegion = { address, 1 };
View::postEvent(Events::SelectionChangeRequest, selectRegion);
EventManager::post<RequestSelectionChange>(Region { address, 1 });
}
if (ImGui::IsMouseReleased(1) && ImGui::IsItemHovered()) {
ImGui::OpenPopup("PatchContextMenu");

View File

@ -82,23 +82,21 @@ namespace hex {
this->m_textEditor.SetLanguageDefinition(PatternLanguage());
this->m_textEditor.SetShowWhitespaces(false);
View::subscribeEvent(Events::ProjectFileStore, [this](auto) {
EventManager::subscribe<EventProjectFileStore>(this, [this]() {
ProjectFile::setPattern(this->m_textEditor.GetText());
});
View::subscribeEvent(Events::ProjectFileLoad, [this](auto) {
EventManager::subscribe<EventProjectFileLoad>(this, [this]() {
this->m_textEditor.SetText(ProjectFile::getPattern());
this->parsePattern(this->m_textEditor.GetText().data());
});
View::subscribeEvent(Events::AppendPatternLanguageCode, [this](auto userData) {
auto code = std::any_cast<const char*>(userData);
EventManager::subscribe<RequestAppendPatternLanguageCode>(this, [this](std::string code) {
this->m_textEditor.InsertText("\n");
this->m_textEditor.InsertText(code);
});
View::subscribeEvent(Events::FileLoaded, [this](auto) {
EventManager::subscribe<EventFileLoaded>(this, [this](const std::string &path) {
if (this->m_textEditor.GetText().find_first_not_of(" \f\n\r\t\v") != std::string::npos)
return;
@ -179,7 +177,7 @@ namespace hex {
/* Settings */
{
View::subscribeEvent(Events::SettingsChanged, [this](auto) {
EventManager::subscribe<EventSettingsChanged>(this, [this]() {
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
if (theme.is_number()) {
@ -204,8 +202,11 @@ namespace hex {
ViewPattern::~ViewPattern() {
delete this->m_patternLanguageRuntime;
View::unsubscribeEvent(Events::ProjectFileStore);
View::unsubscribeEvent(Events::ProjectFileLoad);
EventManager::unsubscribe<EventProjectFileStore>(this);
EventManager::unsubscribe<EventProjectFileLoad>(this);
EventManager::unsubscribe<RequestAppendPatternLanguageCode>(this);
EventManager::unsubscribe<EventFileLoaded>(this);
EventManager::unsubscribe<EventSettingsChanged>(this);
}
void ViewPattern::drawMenu() {
@ -354,7 +355,7 @@ namespace hex {
this->clearPatternData();
this->m_textEditor.SetErrorMarkers({ });
this->m_console.clear();
View::postEvent(Events::PatternChanged);
EventManager::post<EventPatternChanged>();
std::thread([this, buffer = std::string(buffer)] {
auto result = this->m_patternLanguageRuntime->executeString(SharedData::currentProvider, buffer);
@ -368,7 +369,9 @@ namespace hex {
if (result.has_value()) {
this->m_patternData = std::move(result.value());
View::doLater([]{ View::postEvent(Events::PatternChanged); });
View::doLater([]{
EventManager::post<EventPatternChanged>();
});
}
this->m_evaluatorRunning = false;

View File

@ -8,13 +8,13 @@ namespace hex {
ViewPatternData::ViewPatternData(std::vector<lang::PatternData*> &patternData)
: View("hex.view.pattern_data.name"), m_patternData(patternData) {
this->subscribeEvent(Events::PatternChanged, [this](auto data) {
EventManager::subscribe<EventPatternChanged>(this, [this]() {
this->m_sortedPatternData.clear();
});
}
ViewPatternData::~ViewPatternData() {
this->unsubscribeEvent(Events::PatternChanged);
EventManager::unsubscribe<EventPatternChanged>(this);
}
static bool beginPatternDataTable(prv::Provider* &provider, const std::vector<lang::PatternData*> &patterns, std::vector<lang::PatternData*> &sortedPatterns) {

View File

@ -5,8 +5,8 @@
namespace hex {
ViewSettings::ViewSettings() : View("hex.view.settings.name") {
View::subscribeEvent(Events::OpenWindow, [this](auto name) {
if (std::any_cast<const char*>(name) == std::string("hex.view.settings.name")) {
EventManager::subscribe<RequestOpenWindow>(this, [this](const std::string &name) {
if (name == "hex.view.settings.name") {
View::doLater([]{ ImGui::OpenPopup("hex.view.settings.name"_lang); });
this->getWindowOpenState() = true;
}
@ -14,7 +14,7 @@ namespace hex {
}
ViewSettings::~ViewSettings() {
View::unsubscribeEvent(Events::OpenWindow);
EventManager::unsubscribe<RequestOpenWindow>(this);
}
void ViewSettings::drawContent() {
@ -27,7 +27,7 @@ namespace hex {
ImGui::Separator();
for (auto &[name, callback] : entries) {
if (callback(LangEntry(name), ContentRegistry::Settings::getSettingsData()[category][name]))
View::postEvent(Events::SettingsChanged);
EventManager::post<EventSettingsChanged>();
}
ImGui::NewLine();
}

View File

@ -14,7 +14,7 @@ using namespace std::literals::string_literals;
namespace hex {
ViewStrings::ViewStrings() : View("hex.view.strings.name") {
View::subscribeEvent(Events::DataChanged, [this](auto){
EventManager::subscribe<EventDataChanged>(this, [this]() {
this->m_foundStrings.clear();
});
@ -22,7 +22,7 @@ namespace hex {
}
ViewStrings::~ViewStrings() {
View::unsubscribeEvent(Events::DataChanged);
EventManager::unsubscribe<EventDataChanged>(this);
}
@ -161,8 +161,7 @@ namespace hex {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::Selectable(("##StringLine"s + std::to_string(i)).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
Region selectRegion = { foundString.offset, foundString.size };
View::postEvent(Events::SelectionChangeRequest, selectRegion);
EventManager::post<RequestSelectionChange>(Region { foundString.offset, foundString.size });
}
ImGui::PushID(i + 1);
createStringContextMenu(foundString);

View File

@ -81,8 +81,7 @@ namespace hex {
ImGui::TableNextColumn();
ImGui::PushID(i);
if (ImGui::Selectable("match", false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap)) {
Region selectRegion = { u64(address), size_t(size) };
View::postEvent(Events::SelectionChangeRequest, selectRegion);
EventManager::post<RequestSelectionChange>(Region { u64(address), size_t(size) });
}
ImGui::PopID();
ImGui::SameLine();

View File

@ -62,7 +62,7 @@ namespace hex {
this->initGLFW();
this->initImGui();
EventManager::subscribe(Events::SettingsChanged, this, [this](auto) -> std::any {
EventManager::subscribe<EventSettingsChanged>(this, [this]() {
{
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
@ -102,13 +102,9 @@ namespace hex {
if (targetFps.is_number())
this->m_targetFps = targetFps;
}
return { };
});
EventManager::subscribe(Events::FileLoaded, this, [this](auto userData) -> std::any {
auto path = std::any_cast<std::string>(userData);
EventManager::subscribe<EventFileLoaded>(this, [this](const std::string &path){
this->m_recentFiles.push_front(path);
{
@ -136,20 +132,16 @@ namespace hex {
ContentRegistry::Settings::write("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files", recentFilesVector);
}
return { };
});
EventManager::subscribe(Events::CloseImHex, this, [this](auto) -> std::any {
EventManager::subscribe<RequestCloseImHex>(this, [this]() {
glfwSetWindowShouldClose(this->m_window, true);
return { };
});
this->initPlugins();
ContentRegistry::Settings::load();
View::postEvent(Events::SettingsChanged);
EventManager::post<EventSettingsChanged>();
for (const auto &path : ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files"))
this->m_recentFiles.push_back(path);
@ -168,9 +160,9 @@ namespace hex {
this->deinitPlugins();
EventManager::unsubscribe(Events::SettingsChanged, this);
EventManager::unsubscribe(Events::FileLoaded, this);
EventManager::unsubscribe(Events::CloseImHex, this);
EventManager::unsubscribe<EventSettingsChanged>(this);
EventManager::unsubscribe<EventFileLoaded>(this);
EventManager::unsubscribe<RequestCloseImHex>(this);
}
void Window::loop() {
@ -417,9 +409,9 @@ namespace hex {
ImGui::TextUnformatted("hex.welcome.header.start"_lang);
{
if (ImGui::BulletHyperlink("hex.welcome.start.open_file"_lang))
EventManager::post(Events::OpenWindow, "Open File");
EventManager::post<RequestOpenWindow>("Open File");
if (ImGui::BulletHyperlink("hex.welcome.start.open_project"_lang))
EventManager::post(Events::OpenWindow, "Open Project");
EventManager::post<RequestOpenWindow>("Open Project");
}
ImGui::TableNextRow(ImGuiTableRowFlags_None, rowHeight);
@ -429,7 +421,7 @@ namespace hex {
if (!this->m_recentFiles.empty()) {
for (auto &path : this->m_recentFiles) {
if (ImGui::BulletHyperlink(std::filesystem::path(path).filename().string().c_str())) {
EventManager::post(Events::FileDropped, path.c_str());
EventManager::post<EventFileDropped>(path);
break;
}
}
@ -495,7 +487,7 @@ namespace hex {
ImGui::TextUnformatted("hex.welcome.header.customize"_lang);
{
if (ImGui::DescriptionButton("hex.welcome.customize.settings.title"_lang, "hex.welcome.customize.settings.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
EventManager::post(Events::OpenWindow, "hex.view.settings.title");
EventManager::post<RequestOpenWindow>("hex.view.settings.title");
}
ImGui::TableNextRow(ImGuiTableRowFlags_None, rowHeight);
ImGui::TableNextColumn();
@ -638,11 +630,11 @@ namespace hex {
if (count != 1)
return;
View::postEvent(Events::FileDropped, paths[0]);
EventManager::post<EventFileDropped>(paths[0]);
});
glfwSetWindowCloseCallback(this->m_window, [](GLFWwindow *window) {
View::postEvent(Events::WindowClosing, window);
EventManager::post<EventWindowClosing>(window);
});