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:
parent
bcb69b9855
commit
9de3dd89c5
@ -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
|
||||
)
|
||||
|
24
lib/libimhex/include/hex/ui/visualizer_drawer.hpp
Normal file
24
lib/libimhex/include/hex/ui/visualizer_drawer.hpp
Normal 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();
|
||||
}
|
||||
};
|
||||
}
|
34
lib/libimhex/source/ui/visualizer_drawer.cpp
Normal file
34
lib/libimhex/source/ui/visualizer_drawer.cpp
Normal 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());
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user