diff --git a/lib/libimhex/include/hex/api/content_registry/command_palette.hpp b/lib/libimhex/include/hex/api/content_registry/command_palette.hpp index 2d322f3ad..bada8ec76 100644 --- a/lib/libimhex/include/hex/api/content_registry/command_palette.hpp +++ b/lib/libimhex/include/hex/api/content_registry/command_palette.hpp @@ -26,6 +26,7 @@ EXPORT_MODULE namespace hex { std::function callback; }; + using ContentDisplayCallback = std::function; using DisplayCallback = std::function; using ExecuteCallback = std::function(std::string)>; using QueryCallback = std::function(std::string)>; @@ -48,6 +49,8 @@ EXPORT_MODULE namespace hex { const std::vector& getEntries(); const std::vector& getHandlers(); + std::optional& getDisplayedContent(); + } /** @@ -77,6 +80,12 @@ EXPORT_MODULE namespace hex { const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback); + + /** + * @brief Specify UI content that will be displayed inside the command palette + * @param displayCallback Display callback that will be called to display the content + */ + void setDisplayedContent(const impl::ContentDisplayCallback &displayCallback); } } \ No newline at end of file diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index 957b8f175..75c454b67 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -613,6 +613,11 @@ namespace hex { return *s_handlers; } + static AutoReset> s_displayedContent; + std::optional& getDisplayedContent() { + return *s_displayedContent; + } + } void add(Type type, const std::string &command, const UnlocalizedString &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) { @@ -627,6 +632,10 @@ namespace hex { impl::s_handlers->push_back(impl::Handler { type, command, queryCallback, displayCallback }); } + void setDisplayedContent(const impl::ContentDisplayCallback &displayCallback) { + impl::s_displayedContent = displayCallback; + } + } diff --git a/plugins/builtin/source/content/views/view_command_palette.cpp b/plugins/builtin/source/content/views/view_command_palette.cpp index 7f89cb3d7..7cd138772 100644 --- a/plugins/builtin/source/content/views/view_command_palette.cpp +++ b/plugins/builtin/source/content/views/view_command_palette.cpp @@ -20,7 +20,6 @@ namespace hex::plugin::builtin { EventSearchBoxClicked::subscribe([this](ImGuiMouseButton button) { if (button == ImGuiMouseButton_Left) { - RequestOpenPopup::post("hex.builtin.view.command_palette.name"_lang); m_commandPaletteOpen = true; m_justOpened = true; } @@ -28,14 +27,25 @@ namespace hex::plugin::builtin { } void ViewCommandPalette::drawAlwaysVisibleContent() { + if (m_justOpened) { + ImGui::OpenPopup("hex.builtin.view.command_palette.name"_lang); + ContentRegistry::CommandPalette::impl::getDisplayedContent().reset(); + } + // If the command palette is hidden, don't draw it if (!m_commandPaletteOpen) return; auto windowPos = ImHexApi::System::getMainWindowPosition(); auto windowSize = ImHexApi::System::getMainWindowSize(); + const auto &displayedContent = ContentRegistry::CommandPalette::impl::getDisplayedContent(); + ImGui::SetNextWindowPos(ImVec2(windowPos.x + windowSize.x * 0.5F, windowPos.y), ImGuiCond_Always, ImVec2(0.5F, 0.0F)); - ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize()); + if (!displayedContent.has_value()) + ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize()); + else + ImGui::SetNextWindowSizeConstraints(this->getMinSize(), ImVec2(FLT_MAX, FLT_MAX)); + if (ImGui::BeginPopup("hex.builtin.view.command_palette.name"_lang)) { ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead()); ImGui::BringWindowToFocusFront(ImGui::GetCurrentWindowRead()); @@ -118,33 +128,37 @@ namespace hex::plugin::builtin { ImGui::Separator(); // Draw the results - if (ImGui::BeginChild("##results", ImGui::GetContentRegionAvail(), ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { - u32 id = 1; - for (const auto &[displayResult, matchedCommand, callback] : m_lastResults) { - ImGui::PushID(id); - ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, false); - ON_SCOPE_EXIT { - ImGui::PopItemFlag(); - ImGui::PopID(); - id += 1; - }; + if (displayedContent.has_value()) { + (*displayedContent)(m_commandBuffer); + } else { + if (ImGui::BeginChild("##results", ImGui::GetContentRegionAvail(), ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { + u32 id = 1; + for (const auto &[displayResult, matchedCommand, callback] : m_lastResults) { + ImGui::PushID(id); + ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, false); + ON_SCOPE_EXIT { + ImGui::PopItemFlag(); + ImGui::PopID(); + id += 1; + }; - // Allow executing a command by clicking on it or selecting it with the keyboard and pressing enter - if (ImGui::Selectable(displayResult.c_str(), false, ImGuiSelectableFlags_NoAutoClosePopups)) { - if (auto result = callback(matchedCommand); result.has_value()) - m_commandBuffer = result.value(); + // Allow executing a command by clicking on it or selecting it with the keyboard and pressing enter + if (ImGui::Selectable(displayResult.c_str(), false, ImGuiSelectableFlags_NoAutoClosePopups)) { + if (auto result = callback(matchedCommand); result.has_value()) + m_commandBuffer = result.value(); - break; - } - if (ImGui::IsItemFocused() && (ImGui::IsKeyDown(ImGuiKey_Enter) || ImGui::IsKeyDown(ImGuiKey_KeypadEnter))) { - if (auto result = callback(matchedCommand); result.has_value()) - m_commandBuffer = result.value(); + break; + } + if (ImGui::IsItemFocused() && (ImGui::IsKeyDown(ImGuiKey_Enter) || ImGui::IsKeyDown(ImGuiKey_KeypadEnter))) { + if (auto result = callback(matchedCommand); result.has_value()) + m_commandBuffer = result.value(); - break; + break; + } } } + ImGui::EndChild(); } - ImGui::EndChild(); ImGui::EndPopup(); } else {