From a449478e395c486a4e9896d5134dcbb82c31c6e5 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sat, 24 Jun 2023 16:40:34 +0200 Subject: [PATCH] patterns: Make updating favorites and pattern tooltips not lag out ImHex --- lib/external/pattern_language | 2 +- plugins/builtin/include/ui/pattern_drawer.hpp | 7 +- plugins/builtin/romfs/lang/en_US.json | 1 + plugins/builtin/source/ui/pattern_drawer.cpp | 79 +++++++++++++------ 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/lib/external/pattern_language b/lib/external/pattern_language index b18b2e60e..57dc02b9d 160000 --- a/lib/external/pattern_language +++ b/lib/external/pattern_language @@ -1 +1 @@ -Subproject commit b18b2e60e5c4cd6550c1d5e73fdc7e3b238dcd36 +Subproject commit 57dc02b9d338650aaebc3627eeef6c2d7dd95738 diff --git a/plugins/builtin/include/ui/pattern_drawer.hpp b/plugins/builtin/include/ui/pattern_drawer.hpp index 665f42526..b2351cd6b 100644 --- a/plugins/builtin/include/ui/pattern_drawer.hpp +++ b/plugins/builtin/include/ui/pattern_drawer.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -68,8 +70,8 @@ namespace hex::plugin::builtin::ui { bool isEditingPattern(const pl::ptrn::Pattern& pattern) const; void resetEditing(); - bool matchesFilter(const std::vector &filterPath, bool fullMatch); - void traversePatternTree(pl::ptrn::Pattern &pattern, const std::function &callback); + bool matchesFilter(const std::vector &filterPath, const std::vector &patternPath, bool fullMatch); + void traversePatternTree(pl::ptrn::Pattern &pattern, std::vector &patternPath, const std::function &callback); private: std::map m_displayEnd; @@ -90,6 +92,7 @@ namespace hex::plugin::builtin::ui { std::map, std::unique_ptr> m_favorites; bool m_showFavoriteStars = false; bool m_favoritesUpdated = false; + TaskHolder m_favoritesUpdateTask; std::function m_selectionCallback = [](Region) { }; diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index b2b57a0ec..30da7922b 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -379,6 +379,7 @@ "hex.builtin.pattern_drawer.tree_style.auto_expanded": "Auto Expanded Tree", "hex.builtin.pattern_drawer.tree_style.flattened": "Flattened", "hex.builtin.pattern_drawer.type": "Type", + "hex.builtin.pattern_drawer.updating": "Updating Favorites...", "hex.builtin.pattern_drawer.value": "Value", "hex.builtin.pattern_drawer.var_name": "Name", "hex.builtin.pattern_drawer.visualizer.unknown": "Unknown visualizer", diff --git a/plugins/builtin/source/ui/pattern_drawer.cpp b/plugins/builtin/source/ui/pattern_drawer.cpp index 1d7c7f495..9a703c2a8 100644 --- a/plugins/builtin/source/ui/pattern_drawer.cpp +++ b/plugins/builtin/source/ui/pattern_drawer.cpp @@ -183,17 +183,17 @@ namespace hex::plugin::builtin::ui { this->m_editingPatternOffset = 0x00; } - bool PatternDrawer::matchesFilter(const std::vector &filterPath, bool fullMatch) { + bool PatternDrawer::matchesFilter(const std::vector &filterPath, const std::vector &patternPath, bool fullMatch) { if (fullMatch) { - if (this->m_currPatternPath.size() != filterPath.size()) + if (patternPath.size() != filterPath.size()) return false; } - if (this->m_currPatternPath.size() <= filterPath.size()) { - for (ssize_t i = this->m_currPatternPath.size() - 1; i >= 0; i--) { + if (patternPath.size() <= filterPath.size()) { + for (ssize_t i = patternPath.size() - 1; i >= 0; i--) { const auto &filter = filterPath[i]; - if (this->m_currPatternPath[i] != filter && !filter.empty() && filter != "*") { + if (patternPath[i] != filter && !filter.empty() && filter != "*") { return false; } } @@ -790,7 +790,7 @@ namespace hex::plugin::builtin::ui { this->m_currPatternPath.push_back(pattern.getVariableName()); ON_SCOPE_EXIT { this->m_currPatternPath.pop_back(); }; - if (matchesFilter(this->m_filter, false)) + if (matchesFilter(this->m_filter, this->m_currPatternPath, false)) pattern.accept(*this); } @@ -994,14 +994,14 @@ namespace hex::plugin::builtin::ui { return false; } - void PatternDrawer::traversePatternTree(pl::ptrn::Pattern &pattern, const std::function &callback) { - this->m_currPatternPath.push_back(pattern.getVariableName()); - ON_SCOPE_EXIT { this->m_currPatternPath.pop_back(); }; + void PatternDrawer::traversePatternTree(pl::ptrn::Pattern &pattern, std::vector &patternPath, const std::function &callback) { + patternPath.push_back(pattern.getVariableName()); + ON_SCOPE_EXIT { patternPath.pop_back(); }; callback(pattern); if (auto iterable = dynamic_cast(&pattern); iterable != nullptr) { iterable->forEachEntry(0, iterable->getEntryCount(), [&](u64, pl::ptrn::Pattern *entry) { - traversePatternTree(*entry, callback); + traversePatternTree(*entry, patternPath, callback); }); } } @@ -1081,22 +1081,39 @@ namespace hex::plugin::builtin::ui { if (!this->m_favoritesUpdated) { this->m_favoritesUpdated = true; - for (auto &pattern : patterns) { - traversePatternTree(*pattern, [this](pl::ptrn::Pattern &pattern){ - for (auto &[path, favoritePattern] : this->m_favorites) { - if (this->matchesFilter(path, true)) { - favoritePattern = pattern.clone(); - break; - } + if (!this->m_favorites.empty() && !patterns.empty() && !this->m_favoritesUpdateTask.isRunning()) { + this->m_favoritesUpdateTask = TaskManager::createTask("hex.builtin.pattern_drawer.updating"_lang, TaskManager::NoProgress, [this, patterns](auto &task) { + size_t updatedFavorites = 0; + for (auto &pattern : patterns) { + if (updatedFavorites == this->m_favorites.size()) + task.interrupt(); + task.update(); + + std::vector patternPath; + traversePatternTree(*pattern, patternPath, [&, this](pl::ptrn::Pattern &pattern) { + for (auto &[path, favoritePattern] : this->m_favorites) { + if (updatedFavorites == this->m_favorites.size()) + task.interrupt(); + task.update(); + + if (this->matchesFilter(patternPath, path, true)) { + favoritePattern = pattern.clone(); + updatedFavorites += 1; + + break; + } + } + }); } + + std::erase_if(this->m_favorites, [](const auto &entry) { + const auto &[path, favoritePattern] = entry; + + return favoritePattern == nullptr; + }); }); } - std::erase_if(this->m_favorites, [](const auto &entry) { - const auto &[path, favoritePattern] = entry; - - return favoritePattern == nullptr; - }); } if (beginPatternTable(patterns, this->m_sortedPatterns, height)) { @@ -1108,10 +1125,20 @@ namespace hex::plugin::builtin::ui { ImGui::TableNextColumn(); ImGui::PushID(1); if (ImGui::TreeNodeEx("hex.builtin.pattern_drawer.favorites"_lang, ImGuiTreeNodeFlags_SpanFullWidth)) { - for (auto &[path, pattern] : this->m_favorites) { - ImGui::PushID(pattern->getDisplayName().c_str()); - this->draw(*pattern); - ImGui::PopID(); + if (!this->m_favoritesUpdateTask.isRunning()) { + for (auto &[path, pattern] : this->m_favorites) { + if (pattern == nullptr) + continue; + + ImGui::PushID(pattern->getDisplayName().c_str()); + this->draw(*pattern); + ImGui::PopID(); + } + } else { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TableNextColumn(); + ImGui::TextSpinner("hex.builtin.pattern_drawer.updating"_lang); } ImGui::TreePop();