feat: Added options to automatically expand or flatten the pattern tree
This commit is contained in:
parent
b1a26d02c1
commit
c1359a71d6
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
@ -1 +1 @@
|
||||
Subproject commit 98b503cefb80fba8f7b6b128f98d85c3fc15f14b
|
||||
Subproject commit 58f1702be038aca08a01ddd61d41b1c724b43a31
|
@ -12,6 +12,14 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
void draw(const std::vector<std::shared_ptr<pl::ptrn::Pattern>> &patterns, float height = 0.0F);
|
||||
|
||||
enum class TreeStyle {
|
||||
Default = 0,
|
||||
AutoExpanded = 1,
|
||||
Flattened = 2
|
||||
};
|
||||
|
||||
void setTreeStyle(TreeStyle style) { this->m_treeStyle = style; }
|
||||
|
||||
private:
|
||||
void draw(pl::ptrn::Pattern& pattern);
|
||||
|
||||
@ -41,12 +49,18 @@ namespace hex::plugin::builtin::ui {
|
||||
void drawArray(pl::ptrn::Pattern& pattern, pl::ptrn::Iteratable &iteratable, bool isInlined);
|
||||
u64& getDisplayEnd(const pl::ptrn::Pattern& pattern);
|
||||
void makeSelectable(const pl::ptrn::Pattern &pattern);
|
||||
|
||||
void createLeafNode(const pl::ptrn::Pattern& pattern);
|
||||
bool createTreeNode(const pl::ptrn::Pattern& pattern);
|
||||
void createDefaultEntry(pl::ptrn::Pattern &pattern);
|
||||
void closeTreeNode(bool inlined);
|
||||
|
||||
|
||||
private:
|
||||
std::map<const pl::ptrn::Pattern*, u64> m_displayEnd;
|
||||
std::vector<pl::ptrn::Pattern*> m_sortedPatterns;
|
||||
|
||||
const pl::ptrn::Pattern *m_editingPattern = nullptr;
|
||||
TreeStyle m_treeStyle = TreeStyle::Default;
|
||||
};
|
||||
}
|
@ -377,6 +377,10 @@
|
||||
"hex.builtin.setting.interface.fps.unlocked": "Unlocked",
|
||||
"hex.builtin.setting.interface.language": "Language",
|
||||
"hex.builtin.setting.interface.multi_windows": "Enable Multi Window support",
|
||||
"hex.builtin.setting.interface.pattern_tree_style": "Pattern Tree Style",
|
||||
"hex.builtin.setting.interface.pattern_tree_style.tree": "Tree",
|
||||
"hex.builtin.setting.interface.pattern_tree_style.auto_expanded": "Auto Expanded Tree",
|
||||
"hex.builtin.setting.interface.pattern_tree_style.flattened": "Flattened",
|
||||
"hex.builtin.setting.interface.scaling": "Scaling",
|
||||
"hex.builtin.setting.interface.scaling.native": "Native",
|
||||
"hex.builtin.setting.interface.scaling.x0_5": "x0.5",
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <ui/pattern_drawer.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<std::fs::path> userFolders;
|
||||
@ -231,6 +233,23 @@ namespace hex::plugin::builtin {
|
||||
return false;
|
||||
}, true);
|
||||
|
||||
ContentRegistry::Settings::add("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_tree_style", 0, [](auto name, nlohmann::json &setting) {
|
||||
static int selection = static_cast<int>(setting);
|
||||
|
||||
const char *style[] = {
|
||||
"hex.builtin.setting.interface.pattern_tree_style.tree"_lang,
|
||||
"hex.builtin.setting.interface.pattern_tree_style.auto_expanded"_lang,
|
||||
"hex.builtin.setting.interface.pattern_tree_style.flattened"_lang,
|
||||
};
|
||||
|
||||
if (ImGui::Combo(name.data(), &selection, style, IM_ARRAYSIZE(style))) {
|
||||
setting = selection;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
ContentRegistry::Settings::add("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.highlight_color", 0x60C08080, [](auto name, nlohmann::json &setting) {
|
||||
static auto color = static_cast<color_t>(setting);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "content/views/view_pattern_data.hpp"
|
||||
#include <content/views/view_pattern_data.hpp>
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
@ -19,6 +20,13 @@ namespace hex::plugin::builtin {
|
||||
EventManager::subscribe<EventProviderClosed>([this](auto *provider) {
|
||||
this->m_sortedPatterns[provider].clear();
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventSettingsChanged>([this]() {
|
||||
auto patternStyle = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_tree_style");
|
||||
|
||||
if (patternStyle.is_number())
|
||||
this->m_patternDrawer.setTreeStyle(static_cast<ui::PatternDrawer::TreeStyle>(patternStyle.get<int>()));
|
||||
});
|
||||
}
|
||||
|
||||
ViewPatternData::~ViewPatternData() {
|
||||
|
@ -74,25 +74,6 @@ namespace hex::plugin::builtin::ui {
|
||||
return highlightWhenSelected(pattern.getOffset(), pattern.getSize(), callback);
|
||||
}
|
||||
|
||||
void createLeafNode(const pl::ptrn::Pattern& pattern) {
|
||||
ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_Leaf |
|
||||
ImGuiTreeNodeFlags_NoTreePushOnOpen |
|
||||
ImGuiTreeNodeFlags_SpanFullWidth |
|
||||
ImGuiTreeNodeFlags_AllowItemOverlap);
|
||||
}
|
||||
|
||||
bool createTreeNode(const pl::ptrn::Pattern& pattern) {
|
||||
if (pattern.isSealed()) {
|
||||
ImGui::Indent();
|
||||
highlightWhenSelected(pattern, [&]{ ImGui::TextUnformatted(pattern.getDisplayName().c_str()); });
|
||||
ImGui::Unindent();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return highlightWhenSelected(pattern, [&]{ return ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_SpanFullWidth);});
|
||||
}
|
||||
}
|
||||
|
||||
void drawTypenameColumn(const pl::ptrn::Pattern& pattern, const std::string& pattern_name) {
|
||||
ImGui::TextFormattedColored(ImColor(0xFFD69C56), pattern_name);
|
||||
ImGui::SameLine();
|
||||
@ -158,6 +139,36 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
}
|
||||
|
||||
void PatternDrawer::createLeafNode(const pl::ptrn::Pattern& pattern) {
|
||||
ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_Leaf |
|
||||
ImGuiTreeNodeFlags_NoTreePushOnOpen |
|
||||
ImGuiTreeNodeFlags_SpanFullWidth |
|
||||
ImGuiTreeNodeFlags_AllowItemOverlap);
|
||||
}
|
||||
|
||||
bool PatternDrawer::createTreeNode(const pl::ptrn::Pattern& pattern) {
|
||||
if (pattern.isSealed()) {
|
||||
ImGui::Indent();
|
||||
highlightWhenSelected(pattern, [&]{ ImGui::TextUnformatted(pattern.getDisplayName().c_str()); });
|
||||
ImGui::Unindent();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return highlightWhenSelected(pattern, [&]{
|
||||
switch (this->m_treeStyle) {
|
||||
using enum TreeStyle;
|
||||
default:
|
||||
case Default:
|
||||
return ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
case AutoExpanded:
|
||||
return ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
case Flattened:
|
||||
return ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void PatternDrawer::makeSelectable(const pl::ptrn::Pattern &pattern) {
|
||||
ImGui::PushID(static_cast<int>(pattern.getOffset()));
|
||||
ImGui::PushID(pattern.getVariableName().c_str());
|
||||
@ -191,6 +202,11 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
|
||||
void PatternDrawer::closeTreeNode(bool inlined) {
|
||||
if (!inlined && this->m_treeStyle != TreeStyle::Flattened)
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
|
||||
void PatternDrawer::visit(pl::ptrn::PatternArrayDynamic& pattern) {
|
||||
drawArray(pattern, pattern, pattern.isInlined());
|
||||
@ -232,7 +248,7 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
void PatternDrawer::visit(pl::ptrn::PatternBitfield& pattern) {
|
||||
bool open = true;
|
||||
if (!pattern.isInlined()) {
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@ -257,8 +273,7 @@ namespace hex::plugin::builtin::ui {
|
||||
id += 1;
|
||||
});
|
||||
|
||||
if (!pattern.isInlined())
|
||||
ImGui::TreePop();
|
||||
closeTreeNode(pattern.isInlined());
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,7 +393,7 @@ namespace hex::plugin::builtin::ui {
|
||||
void PatternDrawer::visit(pl::ptrn::PatternPointer& pattern) {
|
||||
bool open = true;
|
||||
|
||||
if (!pattern.isInlined()) {
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@ -396,8 +411,7 @@ namespace hex::plugin::builtin::ui {
|
||||
if (open) {
|
||||
pattern.getPointedAtPattern()->accept(*this);
|
||||
|
||||
if (!pattern.isInlined())
|
||||
ImGui::TreePop();
|
||||
closeTreeNode(pattern.isInlined());
|
||||
}
|
||||
}
|
||||
|
||||
@ -450,7 +464,7 @@ namespace hex::plugin::builtin::ui {
|
||||
void PatternDrawer::visit(pl::ptrn::PatternStruct& pattern) {
|
||||
bool open = true;
|
||||
|
||||
if (!pattern.isInlined()) {
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@ -494,15 +508,14 @@ namespace hex::plugin::builtin::ui {
|
||||
id += 1;
|
||||
});
|
||||
|
||||
if (!pattern.isInlined())
|
||||
ImGui::TreePop();
|
||||
closeTreeNode(pattern.isInlined());
|
||||
}
|
||||
}
|
||||
|
||||
void PatternDrawer::visit(pl::ptrn::PatternUnion& pattern) {
|
||||
bool open = true;
|
||||
|
||||
if (!pattern.isInlined()) {
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@ -546,8 +559,7 @@ namespace hex::plugin::builtin::ui {
|
||||
id += 1;
|
||||
});
|
||||
|
||||
if (!pattern.isInlined())
|
||||
ImGui::TreePop();
|
||||
closeTreeNode(pattern.isInlined());
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,7 +609,7 @@ namespace hex::plugin::builtin::ui {
|
||||
return;
|
||||
|
||||
bool open = true;
|
||||
if (!isInlined) {
|
||||
if (!isInlined && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@ -661,7 +673,10 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{ return ImGui::TreeNodeEx(hex::format("[{} ... {}]", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth); });
|
||||
chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{
|
||||
return ImGui::TreeNodeEx(hex::format("{0}[{1} ... {2}]", this->m_treeStyle == TreeStyle::Flattened ? pattern.getDisplayName().c_str() : "", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
});
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
drawColorColumn(pattern);
|
||||
ImGui::TextFormatted("0x{0:08X} : 0x{1:08X}", startOffset, startOffset + chunkSize - (pattern.getSize() == 0 ? 0 : 1));
|
||||
@ -698,8 +713,7 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
}
|
||||
|
||||
if (!isInlined)
|
||||
ImGui::TreePop();
|
||||
closeTreeNode(isInlined);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user