mirror of https://github.com/WerWolv/ImHex.git
feat: Allow jumping from hex editor to patterns and from patterns to source line
This commit is contained in:
parent
6393bfda37
commit
80953a2286
|
@ -1 +1 @@
|
|||
Subproject commit 76c73d3a3ba90bb356907861c74deb2cafdd69ae
|
||||
Subproject commit 31c32e965521d97bfcdca325af37e5243b9825f7
|
|
@ -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);
|
||||
|
|
|
@ -191,7 +191,7 @@ namespace hex {
|
|||
}
|
||||
|
||||
void setSelection(const ProviderRegion ®ion) {
|
||||
RequestSelectionChange::post(region);
|
||||
RequestHexEditorSelectionChange::post(region);
|
||||
}
|
||||
|
||||
void setSelection(u64 address, size_t size, prv::Provider *provider) {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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); });
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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 ®ion) {
|
||||
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());
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue