From ef320b74b07b325fd5fdf28e3817a1ccdcb52232 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Tue, 7 Nov 2023 15:31:54 +0100 Subject: [PATCH] impr: Handle showing popups when closing unsaved providers better --- lib/libimhex/include/hex/api/imhex_api.hpp | 2 +- lib/libimhex/source/api/imhex_api.cpp | 10 +-- .../content/popups/popup_unsaved_changes.hpp | 66 +++++++++++++++++++ .../content/providers/view_provider.hpp | 2 +- plugins/builtin/romfs/lang/de_DE.json | 2 +- plugins/builtin/romfs/lang/en_US.json | 2 +- plugins/builtin/romfs/lang/es_ES.json | 2 +- plugins/builtin/romfs/lang/ja_JP.json | 2 +- plugins/builtin/romfs/lang/ko_KR.json | 2 +- plugins/builtin/romfs/lang/zh_CN.json | 2 +- plugins/builtin/romfs/lang/zh_TW.json | 2 +- plugins/builtin/source/content/events.cpp | 21 ++++-- 12 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 plugins/builtin/include/content/popups/popup_unsaved_changes.hpp diff --git a/lib/libimhex/include/hex/api/imhex_api.hpp b/lib/libimhex/include/hex/api/imhex_api.hpp index 33bbed253..1c32def76 100644 --- a/lib/libimhex/include/hex/api/imhex_api.hpp +++ b/lib/libimhex/include/hex/api/imhex_api.hpp @@ -239,7 +239,7 @@ namespace hex { namespace impl { void resetClosingProvider(); - prv::Provider* getClosingProvider(); + const std::vector& getClosingProviders(); } diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp index 2082b18e3..258d8cba9 100644 --- a/lib/libimhex/source/api/imhex_api.cpp +++ b/lib/libimhex/source/api/imhex_api.cpp @@ -224,13 +224,13 @@ namespace hex { namespace impl { - static prv::Provider *s_closingProvider = nullptr; + static std::vector s_closingProviders; void resetClosingProvider() { - s_closingProvider = nullptr; + s_closingProviders.clear(); } - prv::Provider* getClosingProvider() { - return s_closingProvider; + const std::vector& getClosingProviders() { + return s_closingProviders; } } @@ -302,7 +302,7 @@ namespace hex { return; if (!noQuestions) { - impl::s_closingProvider = provider; + impl::s_closingProviders.push_back(provider); bool shouldClose = true; EventManager::post(provider, &shouldClose); diff --git a/plugins/builtin/include/content/popups/popup_unsaved_changes.hpp b/plugins/builtin/include/content/popups/popup_unsaved_changes.hpp new file mode 100644 index 000000000..c5f7b5a00 --- /dev/null +++ b/plugins/builtin/include/content/popups/popup_unsaved_changes.hpp @@ -0,0 +1,66 @@ +#include + +#include + +#include +#include + +namespace hex::plugin::builtin { + + class PopupUnsavedChanges : public Popup { + public: + PopupUnsavedChanges(std::string message, std::function yesFunction, std::function noFunction) + : hex::Popup("hex.builtin.common.question", false), + m_message(std::move(message)), + m_yesFunction(std::move(yesFunction)), m_noFunction(std::move(noFunction)) { } + + void drawContent() override { + ImGui::TextFormattedWrapped("{}", this->m_message.c_str()); + ImGui::NewLine(); + + if (ImGui::BeginTable("##unsaved_providers", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 4))) { + for (const auto &provider : ImHexApi::Provider::impl::getClosingProviders()) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(provider->getName().c_str()); + } + ImGui::EndTable(); + } + + ImGui::NewLine(); + ImGui::Separator(); + + auto width = ImGui::GetWindowWidth(); + ImGui::SetCursorPosX(width / 9); + if (ImGui::Button("hex.builtin.common.yes"_lang, ImVec2(width / 3, 0))) { + this->m_yesFunction(); + this->close(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(width / 9 * 5); + if (ImGui::Button("hex.builtin.common.no"_lang, ImVec2(width / 3, 0))) { + this->m_noFunction(); + this->close(); + } + + ImGui::SetWindowPos((ImHexApi::System::getMainWindowSize() - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing); + } + + [[nodiscard]] ImGuiWindowFlags getFlags() const override { + return ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; + } + + [[nodiscard]] ImVec2 getMinSize() const override { + return scaled({ 400, 100 }); + } + + [[nodiscard]] ImVec2 getMaxSize() const override { + return scaled({ 600, 300 }); + } + + private: + std::string m_message; + std::function m_yesFunction, m_noFunction; + }; + +} \ No newline at end of file diff --git a/plugins/builtin/include/content/providers/view_provider.hpp b/plugins/builtin/include/content/providers/view_provider.hpp index 5d9ae8b38..06adda94f 100644 --- a/plugins/builtin/include/content/providers/view_provider.hpp +++ b/plugins/builtin/include/content/providers/view_provider.hpp @@ -12,7 +12,7 @@ namespace hex::plugin::builtin { explicit ViewProvider() { EventManager::subscribe(this, [this](prv::Provider *provider, bool*) { if (this->m_provider == provider) - ImHexApi::Provider::remove(this, true); + ImHexApi::Provider::remove(this, false); }); } ~ViewProvider() override { diff --git a/plugins/builtin/romfs/lang/de_DE.json b/plugins/builtin/romfs/lang/de_DE.json index dc46eb10d..924f638b9 100644 --- a/plugins/builtin/romfs/lang/de_DE.json +++ b/plugins/builtin/romfs/lang/de_DE.json @@ -447,7 +447,7 @@ "hex.builtin.pl_visualizer.coordinates.query": "Adresse finden", "hex.builtin.pl_visualizer.coordinates.querying": "Adresse abfragen...", "hex.builtin.pl_visualizer.coordinates.querying_no_address": "Keine Adresse gefunden", - "hex.builtin.popup.close_provider.desc": "Es wurden ungespeicherte Änderungen an diesem Provider vorgenommen.\nBist du sicher, dass du ihn schliessen willst?", + "hex.builtin.popup.close_provider.desc": "Es wurden ungespeicherte Änderungen an einem oder mehreren Provider vorgenommen.\nBist du sicher, dass du diese schliessen willst?", "hex.builtin.popup.close_provider.title": "Provider schliessen?", "hex.builtin.popup.docs_question.title": "Dokumentationsabfrage", "hex.builtin.popup.docs_question.no_answer": "Die Dokumentation enthielt keine Antwort auf diese Frage", diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 6b1c68e4e..3ecfbf689 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -454,7 +454,7 @@ "hex.builtin.pl_visualizer.coordinates.query": "Find address", "hex.builtin.pl_visualizer.coordinates.querying": "Querying address...", "hex.builtin.pl_visualizer.coordinates.querying_no_address": "No address found", - "hex.builtin.popup.close_provider.desc": "There are unsaved changes made to this Provider\nthat haven't been saved to a Project yet.\n\nAre you sure you want to close it?", + "hex.builtin.popup.close_provider.desc": "There are unsaved changes made to one or more Providers\nthat haven't been saved to a Project yet.\n\nAre you sure you want to close them?", "hex.builtin.popup.close_provider.title": "Close Provider?", "hex.builtin.popup.docs_question.title": "Documentation query", "hex.builtin.popup.docs_question.no_answer": "The documentation didn't have an answer for this question", diff --git a/plugins/builtin/romfs/lang/es_ES.json b/plugins/builtin/romfs/lang/es_ES.json index c77424e95..18c8f8fea 100644 --- a/plugins/builtin/romfs/lang/es_ES.json +++ b/plugins/builtin/romfs/lang/es_ES.json @@ -447,7 +447,7 @@ "hex.builtin.pl_visualizer.coordinates.query": "", "hex.builtin.pl_visualizer.coordinates.querying": "", "hex.builtin.pl_visualizer.coordinates.querying_no_address": "", - "hex.builtin.popup.close_provider.desc": "Hay cambios sin guardar en este Proveedor.\nque aún no han sido guardados en un Proyecto.\n\n¿Está seguro de que quiera cerrarlo?", + "hex.builtin.popup.close_provider.desc": "", "hex.builtin.popup.close_provider.title": "¿Cerrar Proveedor?", "hex.builtin.popup.docs_question.title": "Búsqueda de Documentación", "hex.builtin.popup.docs_question.no_answer": "La documentación no tuvo una respuesta esta pregunta", diff --git a/plugins/builtin/romfs/lang/ja_JP.json b/plugins/builtin/romfs/lang/ja_JP.json index e04f630fa..01e610ec0 100644 --- a/plugins/builtin/romfs/lang/ja_JP.json +++ b/plugins/builtin/romfs/lang/ja_JP.json @@ -447,7 +447,7 @@ "hex.builtin.pl_visualizer.coordinates.query": "", "hex.builtin.pl_visualizer.coordinates.querying": "", "hex.builtin.pl_visualizer.coordinates.querying_no_address": "", - "hex.builtin.popup.close_provider.desc": "変更がプロジェクトとして保存されていません。\nファイルを閉じてもよろしいですか?", + "hex.builtin.popup.close_provider.desc": "", "hex.builtin.popup.close_provider.title": "タブを閉じますか?", "hex.builtin.popup.docs_question.title": "", "hex.builtin.popup.docs_question.no_answer": "", diff --git a/plugins/builtin/romfs/lang/ko_KR.json b/plugins/builtin/romfs/lang/ko_KR.json index d6102aaa9..1b9bdafd7 100644 --- a/plugins/builtin/romfs/lang/ko_KR.json +++ b/plugins/builtin/romfs/lang/ko_KR.json @@ -447,7 +447,7 @@ "hex.builtin.pl_visualizer.coordinates.query": "주소 찾기", "hex.builtin.pl_visualizer.coordinates.querying": "주소 쿼리 중...", "hex.builtin.pl_visualizer.coordinates.querying_no_address": "찾은 주소가 없습니다", - "hex.builtin.popup.close_provider.desc": "이 공급자에 대해 아직 프로젝트에\n저장되지 않은 변경 사항이 있습니다.\n\n정말 종료하시겠습니까?", + "hex.builtin.popup.close_provider.desc": "", "hex.builtin.popup.close_provider.title": "공급자를 종료하시겠습니까?", "hex.builtin.popup.docs_question.title": "설명서 쿼리", "hex.builtin.popup.docs_question.no_answer": "설명서에 이 질문에 대한 답변이 없습니다", diff --git a/plugins/builtin/romfs/lang/zh_CN.json b/plugins/builtin/romfs/lang/zh_CN.json index 4b7727e38..994523272 100644 --- a/plugins/builtin/romfs/lang/zh_CN.json +++ b/plugins/builtin/romfs/lang/zh_CN.json @@ -447,7 +447,7 @@ "hex.builtin.pl_visualizer.coordinates.query": "查找地址", "hex.builtin.pl_visualizer.coordinates.querying": "正在查找地址...", "hex.builtin.pl_visualizer.coordinates.querying_no_address": "找不到地址", - "hex.builtin.popup.close_provider.desc": "有对此提供器做出的未保存的更改。\n你确定要关闭吗?", + "hex.builtin.popup.close_provider.desc": "", "hex.builtin.popup.close_provider.title": "关闭提供器?", "hex.builtin.popup.docs_question.title": "查找文档", "hex.builtin.popup.docs_question.no_answer": "文档中没有这个问题的答案", diff --git a/plugins/builtin/romfs/lang/zh_TW.json b/plugins/builtin/romfs/lang/zh_TW.json index 05af9de76..414f79371 100644 --- a/plugins/builtin/romfs/lang/zh_TW.json +++ b/plugins/builtin/romfs/lang/zh_TW.json @@ -447,7 +447,7 @@ "hex.builtin.pl_visualizer.coordinates.query": "查詢地址", "hex.builtin.pl_visualizer.coordinates.querying": "正在查詢地址...", "hex.builtin.pl_visualizer.coordinates.querying_no_address": "找不到地址", - "hex.builtin.popup.close_provider.desc": "您對此提供者有未儲存的更動。\n您確定要關閉嗎?", + "hex.builtin.popup.close_provider.desc": "", "hex.builtin.popup.close_provider.title": "關閉提供者?", "hex.builtin.popup.docs_question.title": "說明文件查詢", "hex.builtin.popup.docs_question.no_answer": "說明文件回答不了此問題", diff --git a/plugins/builtin/source/content/events.cpp b/plugins/builtin/source/content/events.cpp index be29734f8..60fe196d4 100644 --- a/plugins/builtin/source/content/events.cpp +++ b/plugins/builtin/source/content/events.cpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace hex::plugin::builtin { @@ -36,13 +37,15 @@ namespace hex::plugin::builtin { void registerEventHandlers() { + static bool imhexClosing = false; EventManager::subscribe([](GLFWwindow *window) { - if (ImHexApi::Provider::isDirty()) { + if (ImHexApi::Provider::isDirty() && !imhexClosing) { glfwSetWindowShouldClose(window, GLFW_FALSE); PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang, - []{ - ImHexApi::Provider::resetDirty(); - ImHexApi::System::closeImHex(); + [] { + imhexClosing = true; + for (const auto &provider : auto(ImHexApi::Provider::getProviders())) + ImHexApi::Provider::remove(provider); }, [] { } ); @@ -59,11 +62,15 @@ namespace hex::plugin::builtin { EventManager::subscribe([](hex::prv::Provider *provider, bool *shouldClose) { if (provider->isDirty()) { *shouldClose = false; - PopupQuestion::open("hex.builtin.popup.close_provider.desc"_lang, + PopupUnsavedChanges::open("hex.builtin.popup.close_provider.desc"_lang, []{ - ImHexApi::Provider::remove(ImHexApi::Provider::impl::getClosingProvider(), true); + for (auto &provider : ImHexApi::Provider::impl::getClosingProviders()) + ImHexApi::Provider::remove(provider, true); }, - [] { } + [] { + ImHexApi::Provider::impl::resetClosingProvider(); + imhexClosing = false; + } ); } });