diff --git a/include/views/view.hpp b/include/views/view.hpp index 789e2dcee..4c502e10b 100644 --- a/include/views/view.hpp +++ b/include/views/view.hpp @@ -7,6 +7,7 @@ #include "event.hpp" #include +#include #include @@ -14,7 +15,7 @@ namespace hex { class View { public: - View() { } + View(std::string viewName) : m_viewName(viewName) { } virtual ~View() { } virtual void createView() = 0; @@ -29,6 +30,14 @@ namespace hex { View::s_eventManager.post(eventType, userData); } + bool& getWindowOpenState() { + return this->m_windowOpen; + } + + const std::string getName() const { + return this->m_viewName; + } + protected: void subscribeEvent(Events eventType, std::function callback) { View::s_eventManager.subscribe(eventType, this, callback); @@ -42,7 +51,12 @@ namespace hex { View::s_deferedCalls.push_back(function); } + + private: + std::string m_viewName; + bool m_windowOpen = false; + static inline EventManager s_eventManager; static inline std::vector> s_deferedCalls; }; diff --git a/include/views/view_data_inspector.hpp b/include/views/view_data_inspector.hpp index 5b43dca6e..ea9c8e37e 100644 --- a/include/views/view_data_inspector.hpp +++ b/include/views/view_data_inspector.hpp @@ -51,7 +51,6 @@ namespace hex { private: prv::Provider* &m_dataProvider; - bool m_windowOpen = true; bool m_shouldInvalidate = true; std::endian m_endianess = std::endian::native; diff --git a/include/views/view_disassembler.hpp b/include/views/view_disassembler.hpp index a8b271475..3c8b396b2 100644 --- a/include/views/view_disassembler.hpp +++ b/include/views/view_disassembler.hpp @@ -31,8 +31,6 @@ namespace hex { private: prv::Provider* &m_dataProvider; - bool m_windowOpen = true; - bool m_shouldInvalidate = false; u64 m_baseAddress = 0; diff --git a/include/views/view_hashes.hpp b/include/views/view_hashes.hpp index 975fd65dc..cfa0db89d 100644 --- a/include/views/view_hashes.hpp +++ b/include/views/view_hashes.hpp @@ -18,7 +18,6 @@ namespace hex { private: prv::Provider* &m_dataProvider; - bool m_windowOpen = true; bool m_shouldInvalidate = true; int m_currHashFunction = 0; diff --git a/include/views/view_information.hpp b/include/views/view_information.hpp index a4a7d166b..0ef6c6760 100644 --- a/include/views/view_information.hpp +++ b/include/views/view_information.hpp @@ -21,7 +21,6 @@ namespace hex { private: prv::Provider* &m_dataProvider; - bool m_windowOpen = true; bool m_dataValid = false; u32 m_blockSize = 0; diff --git a/include/views/view_pattern.hpp b/include/views/view_pattern.hpp index d873150fb..1429f6877 100644 --- a/include/views/view_pattern.hpp +++ b/include/views/view_pattern.hpp @@ -28,7 +28,6 @@ namespace hex { std::vector &m_patternData; prv::Provider* &m_dataProvider; std::filesystem::path m_possiblePatternFile; - bool m_windowOpen = true; TextEditor m_textEditor; imgui_addons::ImGuiFileBrowser m_fileBrowser; diff --git a/include/views/view_pattern_data.hpp b/include/views/view_pattern_data.hpp index 5b839660b..11fa29f67 100644 --- a/include/views/view_pattern_data.hpp +++ b/include/views/view_pattern_data.hpp @@ -23,10 +23,10 @@ namespace hex { void createMenu() override; private: + prv::Provider* &m_dataProvider; std::vector &m_patternData; std::vector m_sortedPatternData; - bool m_windowOpen = true; }; } \ No newline at end of file diff --git a/include/views/view_strings.hpp b/include/views/view_strings.hpp index da2963b3d..e40f592dc 100644 --- a/include/views/view_strings.hpp +++ b/include/views/view_strings.hpp @@ -25,7 +25,6 @@ namespace hex { private: prv::Provider* &m_dataProvider; - bool m_windowOpen = true; bool m_shouldInvalidate = false; std::vector m_foundStrings; diff --git a/include/views/view_tools.hpp b/include/views/view_tools.hpp index d263be7b8..e5e133a89 100644 --- a/include/views/view_tools.hpp +++ b/include/views/view_tools.hpp @@ -21,8 +21,6 @@ namespace hex { void createMenu() override; private: - bool m_windowOpen = true; - char *m_mangledBuffer = nullptr; char *m_demangledName = nullptr; diff --git a/include/window.hpp b/include/window.hpp index 188fda918..0fbe9af0f 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -7,6 +7,7 @@ #include "views/view.hpp" struct GLFWwindow; +struct ImGuiSettingsHandler; namespace hex { @@ -24,8 +25,10 @@ namespace hex { return static_cast(this->m_views.back()); } - public: - float m_globalScale = 1.0f, m_fontScale = 1.0f; + friend void *ImHexSettingsHandler_ReadOpenFn(ImGuiContext *ctx, ImGuiSettingsHandler *, const char *); + friend void ImHexSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler *handler, void *, const char* line); + friend void ImHexSettingsHandler_ApplyAll(ImGuiContext *ctx, ImGuiSettingsHandler *handler); + friend void ImHexSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buf); private: void frameBegin(); @@ -38,6 +41,8 @@ namespace hex { GLFWwindow* m_window; std::vector m_views; + + float m_globalScale = 1.0f, m_fontScale = 1.0f; bool m_fpsVisible = false; bool m_demoWindowOpen = false; diff --git a/libs/ImGui/include/imgui_memory_editor.h b/libs/ImGui/include/imgui_memory_editor.h index ca573b693..86d7e0e0b 100644 --- a/libs/ImGui/include/imgui_memory_editor.h +++ b/libs/ImGui/include/imgui_memory_editor.h @@ -75,7 +75,6 @@ struct MemoryEditor }; // Settings - bool Open; // = true // set to false when DrawWindow() was closed. ignore if not using DrawWindow(). bool ReadOnly; // = false // disable any editing. int Cols; // = 16 // number of columns to display. bool OptShowOptions; // = true // display options button/context menu. when disabled, options will be locked unless you provide your own UI for them. @@ -106,7 +105,6 @@ struct MemoryEditor MemoryEditor() { // Settings - Open = true; ReadOnly = false; Cols = 16; OptShowOptions = true; @@ -181,13 +179,12 @@ struct MemoryEditor } // Standalone Memory Editor window - void DrawWindow(const char* title, void* mem_data, size_t mem_size, size_t base_display_addr = 0x0000) + void DrawWindow(const char* title, bool *p_open, void* mem_data, size_t mem_size, size_t base_display_addr = 0x0000) { Sizes s; CalcSizes(s, mem_size, base_display_addr); - ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(s.WindowWidth, FLT_MAX)); - if (ImGui::Begin(title, &Open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse)) + if (ImGui::Begin(title, p_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse)) { DrawContents(mem_data, mem_size, base_display_addr); if (ContentsWidthChanged) diff --git a/source/views/view_data_inspector.cpp b/source/views/view_data_inspector.cpp index fec0f6b53..da1fe5137 100644 --- a/source/views/view_data_inspector.cpp +++ b/source/views/view_data_inspector.cpp @@ -9,7 +9,7 @@ extern int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const namespace hex { - ViewDataInspector::ViewDataInspector(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) { + ViewDataInspector::ViewDataInspector(prv::Provider* &dataProvider) : View("Data Inspector"), m_dataProvider(dataProvider) { View::subscribeEvent(Events::ByteSelected, [this](const void* userData){ size_t offset = *static_cast(userData); @@ -26,9 +26,6 @@ namespace hex { } void ViewDataInspector::createView() { - if (!this->m_windowOpen) - return; - if (this->m_shouldInvalidate) { this->m_shouldInvalidate = false; @@ -108,7 +105,7 @@ namespace hex { } - if (ImGui::Begin("Data Inspector", &this->m_windowOpen, ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Data Inspector", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { if (ImGui::BeginChild("##scrolling", ImVec2(0, ImGui::GetWindowHeight() - 60))) { if (ImGui::BeginTable("##datainspector", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody)) { @@ -155,10 +152,7 @@ namespace hex { } void ViewDataInspector::createMenu() { - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Data Preview View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } + } } \ No newline at end of file diff --git a/source/views/view_disassembler.cpp b/source/views/view_disassembler.cpp index 9cafbd5ea..82c863e5a 100644 --- a/source/views/view_disassembler.cpp +++ b/source/views/view_disassembler.cpp @@ -9,7 +9,7 @@ using namespace std::literals::string_literals; namespace hex { - ViewDisassembler::ViewDisassembler(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) { + ViewDisassembler::ViewDisassembler(prv::Provider* &dataProvider) : View("Disassembler"), m_dataProvider(dataProvider) { View::subscribeEvent(Events::DataChanged, [this](const void*){ this->m_shouldInvalidate = true; }); @@ -20,9 +20,6 @@ namespace hex { } void ViewDisassembler::createView() { - if (!this->m_windowOpen) - return; - if (this->m_shouldInvalidate) { this->m_disassembly.clear(); @@ -85,7 +82,7 @@ namespace hex { } - if (ImGui::Begin("Disassembler", &this->m_windowOpen, ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Disassembler", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { constexpr static const char * const ArchitectureNames[] = { "ARM32", "ARM64", "MIPS", "x86", "PowerPC", "Sparc", "SystemZ", "XCore", "68K", "TMS320C64x", "680X", "Ethereum" }; @@ -277,10 +274,7 @@ namespace hex { } void ViewDisassembler::createMenu() { - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Disassembler View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } + } } \ No newline at end of file diff --git a/source/views/view_hashes.cpp b/source/views/view_hashes.cpp index 9440ffb88..2b65b3498 100644 --- a/source/views/view_hashes.cpp +++ b/source/views/view_hashes.cpp @@ -10,7 +10,7 @@ namespace hex { - ViewHashes::ViewHashes(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) { + ViewHashes::ViewHashes(prv::Provider* &dataProvider) : View("Hashes"), m_dataProvider(dataProvider) { View::subscribeEvent(Events::DataChanged, [this](const void*){ this->m_shouldInvalidate = true; }); @@ -27,10 +27,7 @@ namespace hex { } void ViewHashes::createView() { - if (!this->m_windowOpen) - return; - - if (ImGui::Begin("Hashing", &this->m_windowOpen, ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Hashing", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav); ImGui::NewLine(); @@ -204,10 +201,7 @@ namespace hex { } void ViewHashes::createMenu() { - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Hash View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } + } } \ No newline at end of file diff --git a/source/views/view_help.cpp b/source/views/view_help.cpp index 61284b18c..5a9529725 100644 --- a/source/views/view_help.cpp +++ b/source/views/view_help.cpp @@ -2,8 +2,8 @@ namespace hex { - ViewHelp::ViewHelp() { - + ViewHelp::ViewHelp() : View("Help") { + this->getWindowOpenState() = true; } ViewHelp::~ViewHelp() { diff --git a/source/views/view_hexeditor.cpp b/source/views/view_hexeditor.cpp index e239f99c1..a858a3e1f 100644 --- a/source/views/view_hexeditor.cpp +++ b/source/views/view_hexeditor.cpp @@ -8,7 +8,7 @@ namespace hex { ViewHexEditor::ViewHexEditor(prv::Provider* &dataProvider, std::vector &patternData) - : View(), m_dataProvider(dataProvider), m_patternData(patternData) { + : View("Hex Editor"), m_dataProvider(dataProvider), m_patternData(patternData) { this->m_memoryEditor.ReadFn = [](const ImU8 *data, size_t off) -> ImU8 { ViewHexEditor *_this = (ViewHexEditor *) data; @@ -79,12 +79,9 @@ namespace hex { } void ViewHexEditor::createView() { - if (!this->m_memoryEditor.Open) - return; - size_t dataSize = (this->m_dataProvider == nullptr || !this->m_dataProvider->isReadable()) ? 0x00 : this->m_dataProvider->getSize(); - this->m_memoryEditor.DrawWindow("Hex Editor", this, dataSize, dataSize == 0 ? 0x00 : this->m_dataProvider->getBaseAddress()); + this->m_memoryEditor.DrawWindow("Hex Editor", &this->getWindowOpenState(), this, dataSize, dataSize == 0 ? 0x00 : this->m_dataProvider->getBaseAddress()); if (dataSize != 0x00) { ImGui::Begin("Hex Editor"); @@ -423,11 +420,6 @@ R"( ImGui::EndMenu(); } - - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Hex View", "", &this->m_memoryEditor.Open); - ImGui::EndMenu(); - } } bool ViewHexEditor::handleShortcut(int key, int mods) { diff --git a/source/views/view_information.cpp b/source/views/view_information.cpp index 2ae572543..755f8d460 100644 --- a/source/views/view_information.cpp +++ b/source/views/view_information.cpp @@ -15,7 +15,7 @@ namespace hex { ViewInformation::ViewInformation(prv::Provider* &dataProvider) - : View(), m_dataProvider(dataProvider) { + : View("Information"), m_dataProvider(dataProvider) { View::subscribeEvent(Events::DataChanged, [this](const void*) { this->m_dataValid = false; this->m_highestBlockEntropy = 0; @@ -47,10 +47,7 @@ namespace hex { } void ViewInformation::createView() { - if (!this->m_windowOpen) - return; - - if (ImGui::Begin("Data Information", &this->m_windowOpen, ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Data Information", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav); if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { @@ -192,10 +189,7 @@ namespace hex { } void ViewInformation::createMenu() { - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Data Information View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } + } } \ No newline at end of file diff --git a/source/views/view_pattern.cpp b/source/views/view_pattern.cpp index 92e5c6d87..7a8604f16 100644 --- a/source/views/view_pattern.cpp +++ b/source/views/view_pattern.cpp @@ -69,7 +69,7 @@ namespace hex { ViewPattern::ViewPattern(prv::Provider* &dataProvider, std::vector &patternData) - : View(), m_dataProvider(dataProvider), m_patternData(patternData) { + : View("Pattern"), m_dataProvider(dataProvider), m_patternData(patternData) { this->m_textEditor.SetLanguageDefinition(PatternLanguage()); this->m_textEditor.SetShowWhitespaces(false); @@ -148,18 +148,10 @@ namespace hex { } ImGui::EndMenu(); } - - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Pattern View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } } void ViewPattern::createView() { - if (!this->m_windowOpen) - return; - - if (ImGui::Begin("Pattern", &this->m_windowOpen, ImGuiWindowFlags_None | ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Pattern", &this->getWindowOpenState(), ImGuiWindowFlags_None | ImGuiWindowFlags_NoCollapse)) { if (this->m_dataProvider != nullptr && this->m_dataProvider->isAvailable()) { this->m_textEditor.Render("Pattern"); diff --git a/source/views/view_pattern_data.cpp b/source/views/view_pattern_data.cpp index 955dae5db..16d33e684 100644 --- a/source/views/view_pattern_data.cpp +++ b/source/views/view_pattern_data.cpp @@ -6,7 +6,7 @@ namespace hex { ViewPatternData::ViewPatternData(prv::Provider* &dataProvider, std::vector &patternData) - : View(), m_dataProvider(dataProvider), m_patternData(patternData) { + : View("Pattern Data"), m_dataProvider(dataProvider), m_patternData(patternData) { this->subscribeEvent(Events::PatternChanged, [this](auto data) { this->m_sortedPatternData.clear(); @@ -49,10 +49,7 @@ namespace hex { } void ViewPatternData::createView() { - if (!this->m_windowOpen) - return; - - if (ImGui::Begin("Pattern Data", &this->m_windowOpen, ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Pattern Data", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { if (beginPatternDataTable(this->m_dataProvider, this->m_patternData, this->m_sortedPatternData)) { @@ -73,10 +70,7 @@ namespace hex { } void ViewPatternData::createMenu() { - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Data View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } + } } \ No newline at end of file diff --git a/source/views/view_strings.cpp b/source/views/view_strings.cpp index c2d707e2e..3ccaacd14 100644 --- a/source/views/view_strings.cpp +++ b/source/views/view_strings.cpp @@ -9,7 +9,7 @@ using namespace std::literals::string_literals; namespace hex { - ViewStrings::ViewStrings(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) { + ViewStrings::ViewStrings(prv::Provider* &dataProvider) : View("Strings"), m_dataProvider(dataProvider) { View::subscribeEvent(Events::DataChanged, [this](const void*){ this->m_foundStrings.clear(); }); @@ -24,15 +24,11 @@ namespace hex { } void ViewStrings::createView() { - if (!this->m_windowOpen) - return; - if (this->m_shouldInvalidate) { this->m_shouldInvalidate = false; this->m_foundStrings.clear(); - std::vector buffer(1024, 0x00); u32 foundCharacters = 0; for (u64 offset = 0; offset < this->m_dataProvider->getSize(); offset += buffer.size()) { @@ -62,7 +58,7 @@ namespace hex { } - if (ImGui::Begin("Strings", &this->m_windowOpen, ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Strings", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { if (ImGui::InputInt("Minimum length", &this->m_minimumLength, 1, 0)) this->m_shouldInvalidate = true; @@ -147,10 +143,7 @@ namespace hex { } void ViewStrings::createMenu() { - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Strings View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } + } } \ No newline at end of file diff --git a/source/views/view_tools.cpp b/source/views/view_tools.cpp index 91e3975d5..955c2ba84 100644 --- a/source/views/view_tools.cpp +++ b/source/views/view_tools.cpp @@ -8,7 +8,7 @@ namespace hex { - ViewTools::ViewTools() { + ViewTools::ViewTools() : View("Tools") { this->m_mangledBuffer = new char[0xF'FFFF]; this->m_demangledName = static_cast(malloc(8)); @@ -136,10 +136,7 @@ namespace hex { } void ViewTools::createView() { - if (!this->m_windowOpen) - return; - - if (ImGui::Begin("Tools", &this->m_windowOpen, ImGuiWindowFlags_NoCollapse)) { + if (ImGui::Begin("Tools", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { this->drawDemangler(); this->drawASCIITable(); @@ -151,10 +148,7 @@ namespace hex { } void ViewTools::createMenu() { - if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Tools View", "", &this->m_windowOpen); - ImGui::EndMenu(); - } + } } \ No newline at end of file diff --git a/source/window.cpp b/source/window.cpp index fafac882b..629e3bea1 100644 --- a/source/window.cpp +++ b/source/window.cpp @@ -12,42 +12,51 @@ namespace hex { - namespace { + constexpr auto MenuBarItems = { "File", "Edit", "View", "Help" }; - void *ImHexSettingsHandler_ReadOpenFn(ImGuiContext *ctx, ImGuiSettingsHandler *, const char *) { - return ctx; // Unused, but the return value has to be non-null - } - - void ImHexSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler *handler, void *, const char* line) { - auto *window = reinterpret_cast(handler->UserData); - - float scale; - if (sscanf(line, "Scale=%f", &scale) == 1) { window->m_globalScale = scale; } - else if (sscanf(line, "FontScale=%f", &scale) == 1) { window->m_fontScale = scale; } - } - - void ImHexSettingsHandler_ApplyAll(ImGuiContext *ctx, ImGuiSettingsHandler *handler) { - auto *window = reinterpret_cast(handler->UserData); - auto &style = ImGui::GetStyle(); - auto &io = ImGui::GetIO(); - - if (window->m_globalScale != 0.0f) - style.ScaleAllSizes(window->m_globalScale); - if (window->m_fontScale != 0.0f) - io.FontGlobalScale = window->m_fontScale; - } - - void ImHexSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buf) { - auto *window = reinterpret_cast(handler->UserData); - - buf->reserve(buf->size() + 0x20); // Ballpark reserve - - buf->appendf("[%s][General]\n", handler->TypeName); - buf->appendf("Scale=%.1f\n", window->m_globalScale); - buf->appendf("FontScale=%.1f\n", window->m_fontScale); - buf->append("\n"); + void *ImHexSettingsHandler_ReadOpenFn(ImGuiContext *ctx, ImGuiSettingsHandler *, const char *) { + return ctx; // Unused, but the return value has to be non-null + } + + void ImHexSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler *handler, void *, const char* line) { + auto *window = reinterpret_cast(handler->UserData); + + float scale; + if (sscanf(line, "Scale=%f", &scale) == 1) { window->m_globalScale = scale; } + else if (sscanf(line, "FontScale=%f", &scale) == 1) { window->m_fontScale = scale; } + else { + for (auto &view : window->m_views) { + std::string format = view->getName() + "=%d"; + sscanf(line, format.c_str(), &view->getWindowOpenState()); + } + } + } + + void ImHexSettingsHandler_ApplyAll(ImGuiContext *ctx, ImGuiSettingsHandler *handler) { + auto *window = reinterpret_cast(handler->UserData); + auto &style = ImGui::GetStyle(); + auto &io = ImGui::GetIO(); + + if (window->m_globalScale != 0.0f) + style.ScaleAllSizes(window->m_globalScale); + if (window->m_fontScale != 0.0f) + io.FontGlobalScale = window->m_fontScale; + } + + void ImHexSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buf) { + auto *window = reinterpret_cast(handler->UserData); + + buf->reserve(buf->size() + 0x20); // Ballpark reserve + + buf->appendf("[%s][General]\n", handler->TypeName); + buf->appendf("Scale=%.1f\n", window->m_globalScale); + buf->appendf("FontScale=%.1f\n", window->m_fontScale); + + for (auto &view : window->m_views) { + buf->appendf("%s=%d\n", view->getName().c_str(), view->getWindowOpenState()); } + buf->append("\n"); } Window::Window() { @@ -72,6 +81,10 @@ namespace hex { View::getDeferedCalls().clear(); for (auto &view : this->m_views) { + if (!view->getWindowOpenState()) + continue; + + ImGui::SetNextWindowSizeConstraints(ImVec2(480, 720), ImVec2(FLT_MAX, FLT_MAX)); view->createView(); } @@ -102,54 +115,65 @@ namespace hex { windowFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; windowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; - ImGui::Begin("DockSpace", nullptr, windowFlags); - ImGui::PopStyleVar(2); - ImGui::DockSpace(ImGui::GetID("MainDock"), ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None); + if (ImGui::Begin("DockSpace", nullptr, windowFlags)) { + ImGui::PopStyleVar(2); + ImGui::DockSpace(ImGui::GetID("MainDock"), ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None); - ImGui::BeginMenuBar(); + if (ImGui::BeginMenuBar()) { - for (auto &view : this->m_views) - view->createMenu(); + for (auto menu : MenuBarItems) + if (ImGui::BeginMenu(menu)) ImGui::EndMenu(); - if (ImGui::BeginMenu("View")) { - ImGui::Separator(); - ImGui::MenuItem("Display FPS", "", &this->m_fpsVisible); - #ifdef DEBUG - ImGui::MenuItem("Demo View", "", &this->m_demoWindowOpen); - #endif - ImGui::EndMenu(); - } + if (ImGui::BeginMenu("View")) { + for (auto &view : this->m_views) + ImGui::MenuItem((view->getName() + " View").c_str(), "", &view->getWindowOpenState()); + ImGui::EndMenu(); + } - if (this->m_fpsVisible) { - char buffer[0x20]; - snprintf(buffer, 0x20, "%.1f FPS", ImGui::GetIO().Framerate); + for (auto &view : this->m_views) { + view->createMenu(); + } - ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetFontSize() * strlen(buffer) + 20); - ImGui::TextUnformatted(buffer); - } + if (ImGui::BeginMenu("View")) { + ImGui::Separator(); + ImGui::MenuItem("Display FPS", "", &this->m_fpsVisible); + #ifdef DEBUG + ImGui::MenuItem("Demo View", "", &this->m_demoWindowOpen); + #endif + ImGui::EndMenu(); + } + if (this->m_fpsVisible) { + char buffer[0x20]; + snprintf(buffer, 0x20, "%.1f FPS", ImGui::GetIO().Framerate); - ImGui::EndMenuBar(); + ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetFontSize() * strlen(buffer) + 20); + ImGui::TextUnformatted(buffer); + } - ImGui::End(); - - if (auto &[key, mods] = Window::s_currShortcut; key != -1) { - for (auto &view : this->m_views) { - if (view->handleShortcut(key, mods)) - break; + ImGui::EndMenuBar(); + } + + if (auto &[key, mods] = Window::s_currShortcut; key != -1) { + for (auto &view : this->m_views) { + if (view->handleShortcut(key, mods)) + break; + } + + Window::s_currShortcut = { -1, -1 }; } - Window::s_currShortcut = { -1, -1 }; } + ImGui::End(); } void Window::frameEnd() { ImGui::Render(); - int display_w, display_h; - glfwGetFramebufferSize(this->m_window, &display_w, &display_h); - glViewport(0, 0, display_w, display_h); + int displayWidth, displayHeight; + glfwGetFramebufferSize(this->m_window, &displayWidth, &displayHeight); + glViewport(0, 0, displayWidth, displayHeight); glClearColor(0.45f, 0.55f, 0.60f, 1.00f); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); @@ -180,6 +204,7 @@ namespace hex { this->m_window = glfwCreateWindow(1280, 720, "ImHex", nullptr, nullptr); + if (this->m_window == nullptr) throw std::runtime_error("Failed to create window!");