#include #include #include #include #include #include namespace hex::plugin::builtin { ViewPatternData::ViewPatternData() : View::Window("hex.builtin.view.pattern_data.name", ICON_VS_DATABASE) { // Handle tree style setting changes ContentRegistry::Settings::onChange("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_tree_style", [this](const ContentRegistry::Settings::SettingsValue &value) { m_treeStyle = ui::PatternDrawer::TreeStyle(value.get(0)); for (auto &drawer : m_patternDrawer.all()) drawer->setTreeStyle(m_treeStyle); }); ContentRegistry::Settings::onChange("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_data_row_bg", [this](const ContentRegistry::Settings::SettingsValue &value) { m_rowColoring = bool(value.get(false)); for (auto &drawer : m_patternDrawer.all()) drawer->enableRowColoring(m_rowColoring); }); EventPatternEvaluating::subscribe(this, [this]{ (*m_patternDrawer)->reset(); }); EventPatternExecuted::subscribe(this, [this](auto){ (*m_patternDrawer)->reset(); }); RequestJumpToPattern::subscribe(this, [this](const pl::ptrn::Pattern *pattern) { (*m_patternDrawer)->jumpToPattern(pattern); }); ImHexApi::HexEditor::addHoverHighlightProvider([this](const prv::Provider *, u64 address, const u8 *, size_t size) { return m_hoveredPatternRegion.overlaps(Region { address, size }); }); m_patternDrawer.setOnCreateCallback([this](const prv::Provider *provider, auto &drawer) { drawer = std::make_unique(); drawer->setSelectionCallback([](const pl::ptrn::Pattern *pattern) { ImHexApi::HexEditor::setSelection(Region { pattern->getOffset(), pattern->getSize() }); RequestPatternEditorSelectionChange::post(pattern->getLine(), 0); }); drawer->setHoverCallback([this](const pl::ptrn::Pattern *pattern) { if (pattern == nullptr) m_hoveredPatternRegion = Region::Invalid(); else m_hoveredPatternRegion = { pattern->getOffset(), pattern->getSize() }; }); drawer->setTreeStyle(m_treeStyle); drawer->enableRowColoring(m_rowColoring); drawer->enablePatternEditing(provider->isWritable()); }); } ViewPatternData::~ViewPatternData() { EventPatternEvaluating::unsubscribe(this); EventPatternExecuted::unsubscribe(this); } void ViewPatternData::drawContent() { // Draw the pattern tree if the provider is valid if (ImHexApi::Provider::isValid()) { // Make sure the runtime has finished evaluating and produced valid patterns auto &runtime = ContentRegistry::PatternLanguage::getRuntime(); const auto height = std::max(ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().FramePadding.y * 2, ImGui::GetTextLineHeightWithSpacing() * 5); if (*m_patternDrawer != nullptr) { if (!runtime.arePatternsValid()) { (*m_patternDrawer)->draw({ }, nullptr, height); } else { // If the runtime has finished evaluating, draw the patterns if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) { (*m_patternDrawer)->draw(runtime.getPatterns(), &runtime, height); } } } } } }