From c1359a71d6d3180c7e81b41d0ae66b20a236b43c Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 8 Jan 2023 16:06:26 +0100 Subject: [PATCH] feat: Added options to automatically expand or flatten the pattern tree --- lib/external/pattern_language | 2 +- plugins/builtin/include/ui/pattern_drawer.hpp | 14 ++++ plugins/builtin/romfs/lang/en_US.json | 4 + .../source/content/settings_entries.cpp | 19 +++++ .../content/views/view_pattern_data.cpp | 10 ++- plugins/builtin/source/ui/pattern_drawer.cpp | 84 +++++++++++-------- 6 files changed, 96 insertions(+), 37 deletions(-) diff --git a/lib/external/pattern_language b/lib/external/pattern_language index 98b503cef..58f1702be 160000 --- a/lib/external/pattern_language +++ b/lib/external/pattern_language @@ -1 +1 @@ -Subproject commit 98b503cefb80fba8f7b6b128f98d85c3fc15f14b +Subproject commit 58f1702be038aca08a01ddd61d41b1c724b43a31 diff --git a/plugins/builtin/include/ui/pattern_drawer.hpp b/plugins/builtin/include/ui/pattern_drawer.hpp index 615482d39..7681473ad 100644 --- a/plugins/builtin/include/ui/pattern_drawer.hpp +++ b/plugins/builtin/include/ui/pattern_drawer.hpp @@ -12,6 +12,14 @@ namespace hex::plugin::builtin::ui { void draw(const std::vector> &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 m_displayEnd; std::vector m_sortedPatterns; const pl::ptrn::Pattern *m_editingPattern = nullptr; + TreeStyle m_treeStyle = TreeStyle::Default; }; } \ No newline at end of file diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 95c1ec93d..c1d2216fe 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -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", diff --git a/plugins/builtin/source/content/settings_entries.cpp b/plugins/builtin/source/content/settings_entries.cpp index fb76f7da9..c3d6323bb 100644 --- a/plugins/builtin/source/content/settings_entries.cpp +++ b/plugins/builtin/source/content/settings_entries.cpp @@ -14,6 +14,8 @@ #include +#include + namespace { std::vector 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(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(setting); diff --git a/plugins/builtin/source/content/views/view_pattern_data.cpp b/plugins/builtin/source/content/views/view_pattern_data.cpp index 01bd27836..e2a9c4d64 100644 --- a/plugins/builtin/source/content/views/view_pattern_data.cpp +++ b/plugins/builtin/source/content/views/view_pattern_data.cpp @@ -1,5 +1,6 @@ -#include "content/views/view_pattern_data.hpp" +#include +#include #include #include @@ -19,6 +20,13 @@ namespace hex::plugin::builtin { EventManager::subscribe([this](auto *provider) { this->m_sortedPatterns[provider].clear(); }); + + EventManager::subscribe([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(patternStyle.get())); + }); } ViewPatternData::~ViewPatternData() { diff --git a/plugins/builtin/source/ui/pattern_drawer.cpp b/plugins/builtin/source/ui/pattern_drawer.cpp index 0ae1fcc23..12e6519fa 100644 --- a/plugins/builtin/source/ui/pattern_drawer.cpp +++ b/plugins/builtin/source/ui/pattern_drawer.cpp @@ -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(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); } }