From 9de3dd89c5f7b3d19af6667c68ff8ae912b8eaca Mon Sep 17 00:00:00 2001 From: paxcut <53811119+paxcut@users.noreply.github.com> Date: Fri, 29 Nov 2024 09:20:28 -0700 Subject: [PATCH] feat: Added support for inline visualizers in custom data inspectors (#1966) ### Problem description This PR aims at making inline visualizers work on the data inspector so that more rgb encodings can be added as custom pattern language inspector rows. This was never setup to work because the inline visualizer rendering function was a private member function. ### Implementation description In order to be accessible from the inspector class the rendering function was made public. ### Additional things Missing still is the tooltip to make it behave like other color entries. --- lib/libimhex/CMakeLists.txt | 1 + .../include/hex/ui/visualizer_drawer.hpp | 24 ++++++++++++ lib/libimhex/source/ui/visualizer_drawer.cpp | 34 +++++++++++++++++ .../content/views/view_data_inspector.hpp | 2 + .../content/views/view_data_inspector.cpp | 12 +++++- plugins/ui/include/ui/pattern_drawer.hpp | 4 +- plugins/ui/source/ui/pattern_drawer.cpp | 38 +++---------------- 7 files changed, 79 insertions(+), 36 deletions(-) create mode 100644 lib/libimhex/include/hex/ui/visualizer_drawer.hpp create mode 100644 lib/libimhex/source/ui/visualizer_drawer.cpp diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index abcd9677f..ef335ed32 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -49,6 +49,7 @@ set(LIBIMHEX_SOURCES source/ui/view.cpp source/ui/popup.cpp source/ui/toast.cpp + source/ui/visualizer_drawer.cpp source/subcommands/subcommands.cpp ) diff --git a/lib/libimhex/include/hex/ui/visualizer_drawer.hpp b/lib/libimhex/include/hex/ui/visualizer_drawer.hpp new file mode 100644 index 000000000..75b212185 --- /dev/null +++ b/lib/libimhex/include/hex/ui/visualizer_drawer.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include "hex/api/content_registry.hpp" + +namespace hex::ui { + + class VisualizerDrawer { + std::string m_lastVisualizerError; + public: + VisualizerDrawer()=default; + void drawVisualizer(const std::map &visualizers, const std::vector &arguments, pl::ptrn::Pattern &pattern, bool reset); + const std::string& getLastVisualizerError() const { + return m_lastVisualizerError; + } + void setLastVisualizerError(const std::string &error) { + m_lastVisualizerError = error; + } + void clearLastVisualizerError() { + m_lastVisualizerError.clear(); + } + }; +} \ No newline at end of file diff --git a/lib/libimhex/source/ui/visualizer_drawer.cpp b/lib/libimhex/source/ui/visualizer_drawer.cpp new file mode 100644 index 000000000..f0f3fb63c --- /dev/null +++ b/lib/libimhex/source/ui/visualizer_drawer.cpp @@ -0,0 +1,34 @@ + +#include "hex/ui/visualizer_drawer.hpp" +#include "imgui.h" + +namespace hex::ui { + void VisualizerDrawer::drawVisualizer( + const std::map &visualizers, + const std::vector &arguments, pl::ptrn::Pattern &pattern, bool reset) { + auto visualizerName = arguments.front().toString(true); + + if (auto entry = visualizers.find(visualizerName); entry != visualizers.end()) { + const auto &[name, visualizer] = *entry; + + auto paramCount = arguments.size() - 1; + auto [minParams, maxParams] = visualizer.parameterCount; + + if (paramCount >= minParams && paramCount <= maxParams) { + try { + visualizer.callback(pattern, reset, {arguments.begin() + 1, arguments.end()}); + } catch (std::exception &e) { + m_lastVisualizerError = e.what(); + } + } else { + ImGui::TextUnformatted("hex.ui.pattern_drawer.visualizer.invalid_parameter_count"_lang); + } + } else { + ImGui::TextUnformatted("hex.ui.pattern_drawer.visualizer.unknown"_lang); + } + + if (!m_lastVisualizerError.empty()) + ImGui::TextUnformatted(m_lastVisualizerError.c_str()); + } + +} \ No newline at end of file diff --git a/plugins/builtin/include/content/views/view_data_inspector.hpp b/plugins/builtin/include/content/views/view_data_inspector.hpp index 29c00b3f4..ea925f1d4 100644 --- a/plugins/builtin/include/content/views/view_data_inspector.hpp +++ b/plugins/builtin/include/content/views/view_data_inspector.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -56,6 +57,7 @@ namespace hex::plugin::builtin { ContentRegistry::DataInspector::NumberDisplayStyle m_numberDisplayStyle = ContentRegistry::DataInspector::NumberDisplayStyle::Decimal; bool m_invert = false; + ui::VisualizerDrawer m_visualizerDrawer; u64 m_startAddress = 0; size_t m_validBytes = 0; prv::Provider *m_selectedProvider = nullptr; diff --git a/plugins/builtin/source/content/views/view_data_inspector.cpp b/plugins/builtin/source/content/views/view_data_inspector.cpp index 7380f9d41..1cd64eb90 100644 --- a/plugins/builtin/source/content/views/view_data_inspector.cpp +++ b/plugins/builtin/source/content/views/view_data_inspector.cpp @@ -1,4 +1,5 @@ #include "content/views/view_data_inspector.hpp" +#include "ui/pattern_drawer.hpp" #include #include @@ -7,6 +8,8 @@ #include #include +#include + #include #include @@ -198,8 +201,13 @@ namespace hex::plugin::builtin { try { // Set up the display function using the pattern's formatter - auto displayFunction = [value = pattern->getFormattedValue()] { - ImGui::TextUnformatted(value.c_str()); + auto displayFunction = [pattern,value = pattern->getFormattedValue()] { + auto drawer = ui::VisualizerDrawer(); + if (const auto &inlineVisualizeArgs = pattern->getAttributeArguments("hex::inline_visualize"); !inlineVisualizeArgs.empty()) { + drawer.drawVisualizer(ContentRegistry::PatternLanguage::impl::getInlineVisualizers(), inlineVisualizeArgs, *pattern, true); + } else { + ImGui::TextUnformatted(value.c_str()); + } return value; }; diff --git a/plugins/ui/include/ui/pattern_drawer.hpp b/plugins/ui/include/ui/pattern_drawer.hpp index c4dc352ad..87df29dc9 100644 --- a/plugins/ui/include/ui/pattern_drawer.hpp +++ b/plugins/ui/include/ui/pattern_drawer.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -71,7 +72,6 @@ namespace hex::ui { void makeSelectable(const pl::ptrn::Pattern &pattern); void drawValueColumn(pl::ptrn::Pattern& pattern); - void drawVisualizer(const std::map &visualizers, const std::vector &arguments, pl::ptrn::Pattern &pattern, bool reset); void drawFavoriteColumn(const pl::ptrn::Pattern& pattern); bool drawNameColumn(const pl::ptrn::Pattern &pattern, bool leaf = false); void drawColorColumn(const pl::ptrn::Pattern& pattern); @@ -103,6 +103,7 @@ namespace hex::ui { const pl::ptrn::Pattern *m_editingPattern = nullptr; u64 m_editingPatternOffset = 0; + hex::ui::VisualizerDrawer m_visualizerDrawer; TreeStyle m_treeStyle = TreeStyle::Default; bool m_rowColoring = false; @@ -111,7 +112,6 @@ namespace hex::ui { const pl::ptrn::Pattern *m_jumpToPattern = nullptr; std::set m_visualizedPatterns; - std::string m_lastVisualizerError; std::string m_filterText; Filter m_filter; diff --git a/plugins/ui/source/ui/pattern_drawer.cpp b/plugins/ui/source/ui/pattern_drawer.cpp index 06a10de12..b79494b5c 100644 --- a/plugins/ui/source/ui/pattern_drawer.cpp +++ b/plugins/ui/source/ui/pattern_drawer.cpp @@ -339,32 +339,6 @@ namespace hex::ui { ImGui::TextUnformatted(pattern.getComment().c_str()); } - void PatternDrawer::drawVisualizer(const std::map &visualizers, const std::vector &arguments, pl::ptrn::Pattern &pattern, bool reset) { - auto visualizerName = arguments.front().toString(true); - - if (auto entry = visualizers.find(visualizerName); entry != visualizers.end()) { - const auto &[name, visualizer] = *entry; - - auto paramCount = arguments.size() - 1; - auto [minParams, maxParams] = visualizer.parameterCount; - - if (paramCount >= minParams && paramCount <= maxParams) { - try { - visualizer.callback(pattern, reset, { arguments.begin() + 1, arguments.end() }); - } catch (std::exception &e) { - m_lastVisualizerError = e.what(); - } - } else { - ImGui::TextUnformatted("hex.ui.pattern_drawer.visualizer.invalid_parameter_count"_lang); - } - } else { - ImGui::TextUnformatted("hex.ui.pattern_drawer.visualizer.unknown"_lang); - } - - if (!m_lastVisualizerError.empty()) - ImGui::TextUnformatted(m_lastVisualizerError.c_str()); - } - void PatternDrawer::drawValueColumn(pl::ptrn::Pattern& pattern) { ImGui::TableNextColumn(); @@ -384,11 +358,11 @@ namespace hex::ui { if (ImGui::Button(hex::format(" {} {}", ICON_VS_EYE_WATCH, value).c_str(), ImVec2(width, ImGui::GetTextLineHeight()))) { auto previousPattern = m_currVisualizedPattern; m_currVisualizedPattern = &pattern; - - if (!m_lastVisualizerError.empty() || m_currVisualizedPattern != previousPattern) + auto lastVisualizerError = m_visualizerDrawer.getLastVisualizerError(); + if (!lastVisualizerError.empty() || m_currVisualizedPattern != previousPattern) shouldReset = true; - m_lastVisualizerError.clear(); + m_visualizerDrawer.clearLastVisualizerError(); ImGui::OpenPopup("Visualizer"); } @@ -398,14 +372,14 @@ namespace hex::ui { if (ImGui::BeginPopup("Visualizer")) { if (m_currVisualizedPattern == &pattern) { - drawVisualizer(ContentRegistry::PatternLanguage::impl::getVisualizers(), visualizeArgs, pattern, !m_visualizedPatterns.contains(&pattern) || shouldReset); + m_visualizerDrawer.drawVisualizer(ContentRegistry::PatternLanguage::impl::getVisualizers(), visualizeArgs, pattern, !m_visualizedPatterns.contains(&pattern) || shouldReset); m_visualizedPatterns.insert(&pattern); } ImGui::EndPopup(); } } else if (const auto &inlineVisualizeArgs = pattern.getAttributeArguments("hex::inline_visualize"); !inlineVisualizeArgs.empty()) { - drawVisualizer(ContentRegistry::PatternLanguage::impl::getInlineVisualizers(), inlineVisualizeArgs, pattern, true); + m_visualizerDrawer.drawVisualizer(ContentRegistry::PatternLanguage::impl::getInlineVisualizers(), inlineVisualizeArgs, pattern, true); } else { ImGuiExt::TextFormatted("{}", value); } @@ -1464,7 +1438,7 @@ namespace hex::ui { m_currVisualizedPattern = nullptr; m_sortedPatterns.clear(); m_filteredPatterns.clear(); - m_lastVisualizerError.clear(); + m_visualizerDrawer.clearLastVisualizerError(); m_currPatternPath.clear(); m_favoritesUpdateTask.interrupt();