1
0
mirror of synced 2025-01-07 12:11:37 +01:00

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.
This commit is contained in:
paxcut 2024-11-29 09:20:28 -07:00 committed by GitHub
parent bcb69b9855
commit 9de3dd89c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 79 additions and 36 deletions

View File

@ -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
)

View File

@ -0,0 +1,24 @@
#pragma once
#include <string>
#include <map>
#include "hex/api/content_registry.hpp"
namespace hex::ui {
class VisualizerDrawer {
std::string m_lastVisualizerError;
public:
VisualizerDrawer()=default;
void drawVisualizer(const std::map<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers, const std::vector<pl::core::Token::Literal> &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();
}
};
}

View File

@ -0,0 +1,34 @@
#include "hex/ui/visualizer_drawer.hpp"
#include "imgui.h"
namespace hex::ui {
void VisualizerDrawer::drawVisualizer(
const std::map<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers,
const std::vector<pl::core::Token::Literal> &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());
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <hex/ui/view.hpp>
#include <hex/ui/visualizer_drawer.hpp>
#include <hex/api/content_registry.hpp>
#include <hex/api/task_manager.hpp>
@ -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;

View File

@ -1,4 +1,5 @@
#include "content/views/view_data_inspector.hpp"
#include "ui/pattern_drawer.hpp"
#include <hex/api/achievement_manager.hpp>
#include <hex/providers/provider.hpp>
@ -7,6 +8,8 @@
#include <fonts/codicons_font.h>
#include <hex/ui/imgui_imhex_extensions.h>
#include <hex/ui/visualizer_drawer.hpp>
#include <pl/pattern_language.hpp>
#include <pl/patterns/pattern.hpp>
@ -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;
};

View File

@ -2,6 +2,7 @@
#include <hex/api/task_manager.hpp>
#include <hex/api/content_registry.hpp>
#include <hex/ui/visualizer_drawer.hpp>
#include <pl/patterns/pattern.hpp>
#include <pl/pattern_visitor.hpp>
@ -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<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers, const std::vector<pl::core::Token::Literal> &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<pl::ptrn::Pattern*> m_visualizedPatterns;
std::string m_lastVisualizerError;
std::string m_filterText;
Filter m_filter;

View File

@ -339,32 +339,6 @@ namespace hex::ui {
ImGui::TextUnformatted(pattern.getComment().c_str());
}
void PatternDrawer::drawVisualizer(const std::map<std::string, ContentRegistry::PatternLanguage::impl::Visualizer> &visualizers, const std::vector<pl::core::Token::Literal> &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();