feat: Allow jumping from hex editor to patterns and from patterns to source line

This commit is contained in:
WerWolv 2024-01-31 11:26:22 +01:00
parent 6393bfda37
commit 80953a2286
10 changed files with 63 additions and 12 deletions

@ -1 +1 @@
Subproject commit 76c73d3a3ba90bb356907861c74deb2cafdd69ae
Subproject commit 31c32e965521d97bfcdca325af37e5243b9825f7

View file

@ -36,6 +36,7 @@ namespace hex {
class View;
}
namespace pl::ptrn { class Pattern; }
namespace hex {
@ -274,7 +275,9 @@ namespace hex {
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
EVENT_DEF(RequestOpenWindow, std::string);
EVENT_DEF(RequestSelectionChange, Region);
EVENT_DEF(RequestHexEditorSelectionChange, Region);
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
EVENT_DEF(RequestRemoveBookmark, u64);
EVENT_DEF(RequestSetPatternLanguageCode, std::string);

View file

@ -191,7 +191,7 @@ namespace hex {
}
void setSelection(const ProviderRegion &region) {
RequestSelectionChange::post(region);
RequestHexEditorSelectionChange::post(region);
}
void setSelection(u64 address, size_t size, prv::Provider *provider) {

View file

@ -766,6 +766,7 @@
"hex.builtin.view.hex_editor.menu.edit.fill": "Fill...",
"hex.builtin.view.hex_editor.menu.edit.insert": "Insert...",
"hex.builtin.view.hex_editor.menu.edit.jump_to": "Jump to",
"hex.builtin.view.hex_editor.menu.edit.jump_to.curr_pattern": "Current Pattern",
"hex.builtin.view.hex_editor.menu.edit.open_in_new_provider": "Open selection view...",
"hex.builtin.view.hex_editor.menu.edit.paste": "Paste",
"hex.builtin.view.hex_editor.menu.edit.paste_all": "Paste all",

View file

@ -458,7 +458,7 @@ namespace hex::plugin::builtin {
}
ViewHexEditor::~ViewHexEditor() {
RequestSelectionChange::unsubscribe(this);
RequestHexEditorSelectionChange::unsubscribe(this);
EventProviderChanged::unsubscribe(this);
EventProviderOpened::unsubscribe(this);
EventHighlightingChanged::unsubscribe(this);
@ -800,7 +800,7 @@ namespace hex::plugin::builtin {
}
void ViewHexEditor::registerEvents() {
RequestSelectionChange::subscribe(this, [this](Region region) {
RequestHexEditorSelectionChange::subscribe(this, [this](Region region) {
auto provider = ImHexApi::Provider::get();
if (region == Region::Invalid()) {
@ -1136,6 +1136,13 @@ namespace hex::plugin::builtin {
if (ImGui::MenuItem(hex::format("0x{:08X}", bigEndianValue).c_str(), "hex.ui.common.big_endian"_lang, false, canJumpTo(bigEndianValue))) {
ImHexApi::HexEditor::setSelection(bigEndianValue, 1);
}
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.jump_to.curr_pattern"_lang, "", false, selection.has_value() && ContentRegistry::PatternLanguage::getRuntime().getCreatedPatternCount() > 0)) {
auto patterns = ContentRegistry::PatternLanguage::getRuntime().getPatternsAtAddress(selection->getStartAddress());
if (!patterns.empty())
RequestJumpToPattern::post(patterns.front());
}
},
[] { return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid() && ImHexApi::HexEditor::getSelection()->getSize() <= sizeof(u64); });

View file

@ -30,10 +30,18 @@ namespace hex::plugin::builtin {
(*m_patternDrawer)->reset();
});
RequestJumpToPattern::subscribe(this, [this](const pl::ptrn::Pattern *pattern) {
(*m_patternDrawer)->jumpToPattern(pattern);
});
m_patternDrawer.setOnCreateCallback([this](prv::Provider *, auto &drawer) {
drawer = std::make_unique<ui::PatternDrawer>();
drawer->setSelectionCallback([](Region region){ ImHexApi::HexEditor::setSelection(region); });
drawer->setSelectionCallback([](const pl::ptrn::Pattern *pattern) {
ImHexApi::HexEditor::setSelection(Region { pattern->getOffset(), pattern->getSize() });
RequestPatternEditorSelectionChange::post(pattern->getLine(), 0);
});
drawer->setTreeStyle(m_treeStyle);
drawer->enableRowColoring(m_rowColoring);
});

View file

@ -192,6 +192,7 @@ namespace hex::plugin::builtin {
}
ViewPatternEditor::~ViewPatternEditor() {
RequestPatternEditorSelectionChange::unsubscribe(this);
RequestSetPatternLanguageCode::unsubscribe(this);
RequestRunPatternCode::unsubscribe(this);
EventFileLoaded::unsubscribe(this);
@ -1111,8 +1112,8 @@ namespace hex::plugin::builtin {
m_sectionWindowDrawer[patternProvider] = [this, id, patternProvider, dataProvider, hexEditor, patternDrawer = std::make_shared<ui::PatternDrawer>(), &runtime] mutable {
hexEditor.setProvider(dataProvider.get());
hexEditor.draw(480_scaled);
patternDrawer->setSelectionCallback([&](const auto &region) {
hexEditor.setSelection(region);
patternDrawer->setSelectionCallback([&](const pl::ptrn::Pattern *pattern) {
hexEditor.setSelection(Region { pattern->getOffset(), pattern->getSize() });
});
const auto &patterns = [&, this] -> const auto& {
@ -1627,6 +1628,11 @@ namespace hex::plugin::builtin {
}
void ViewPatternEditor::registerEvents() {
RequestPatternEditorSelectionChange::subscribe(this, [this](u32 line, u32 column) {
const TextEditor::Coordinates coords = { int(line) - 1, int(column) };
m_textEditor.SetCursorPosition(coords);
});
RequestLoadPatternLanguageFile::subscribe(this, [this](const std::fs::path &path) {
this->loadPatternFile(path, ImHexApi::Provider::get());
});

View file

@ -31,10 +31,12 @@ namespace hex::ui {
};
void setTreeStyle(TreeStyle style) { m_treeStyle = style; }
void setSelectionCallback(std::function<void(Region)> callback) { m_selectionCallback = std::move(callback); }
void setSelectionCallback(std::function<void(const pl::ptrn::Pattern *)> callback) { m_selectionCallback = std::move(callback); }
void enableRowColoring(bool enabled) { m_rowColoring = enabled; }
void reset();
void jumpToPattern(const pl::ptrn::Pattern *pattern) { m_jumpToPattern = pattern; }
private:
void draw(pl::ptrn::Pattern& pattern);
@ -100,6 +102,7 @@ namespace hex::ui {
TreeStyle m_treeStyle = TreeStyle::Default;
bool m_rowColoring = false;
pl::ptrn::Pattern *m_currVisualizedPattern = nullptr;
const pl::ptrn::Pattern *m_jumpToPattern = nullptr;
std::set<pl::ptrn::Pattern*> m_visualizedPatterns;
std::string m_lastVisualizerError;
@ -115,7 +118,7 @@ namespace hex::ui {
TaskHolder m_favoritesUpdateTask;
std::function<void(Region)> m_selectionCallback = [](Region) { };
std::function<void(const pl::ptrn::Pattern *)> m_selectionCallback = [](const pl::ptrn::Pattern *) { };
pl::gen::fmt::FormatterArray m_formatters;
};

View file

@ -1032,7 +1032,7 @@ namespace hex::ui {
this->setSelection(selectionStart.value_or(address), endAddress);
this->scrollToSelection();
}
else if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
else if (ImGui::IsMouseDown(ImGuiMouseButton_Left) || (ImGui::IsMouseDown(ImGuiMouseButton_Right) && (address < m_selectionStart || address > m_selectionEnd))) {
if (ImGui::GetIO().KeyShift)
this->setSelection(selectionStart.value_or(address), endAddress);
else

View file

@ -342,6 +342,26 @@ namespace hex::ui {
bool PatternDrawer::createTreeNode(const pl::ptrn::Pattern& pattern, bool leaf) {
drawFavoriteColumn(pattern);
bool shouldOpen = false;
if (m_jumpToPattern != nullptr) {
if (m_jumpToPattern == &pattern) {
ImGui::SetScrollHereY();
m_jumpToPattern = nullptr;
}
else {
auto parent = m_jumpToPattern->getParent();
while (parent != nullptr) {
if (&pattern == parent) {
ImGui::SetScrollHereY();
shouldOpen = true;
break;
}
parent = parent->getParent();
}
}
}
if (pattern.isSealed() || leaf) {
ImGui::Indent();
highlightWhenSelected(pattern, [&]{ ImGui::TextUnformatted(this->getDisplayName(pattern).c_str()); });
@ -350,6 +370,9 @@ namespace hex::ui {
}
return highlightWhenSelected(pattern, [&]{
if (shouldOpen)
ImGui::SetNextItemOpen(true, ImGuiCond_Always);
switch (m_treeStyle) {
using enum TreeStyle;
default:
@ -368,7 +391,7 @@ namespace hex::ui {
ImGui::PushID(pattern.getVariableName().c_str());
if (ImGui::Selectable("##PatternLine", false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
m_selectionCallback(Region { pattern.getOffset(), pattern.getSize() });
m_selectionCallback(&pattern);
if (m_editingPattern != &pattern) {
this->resetEditing();