impr: Make pattern data filter behave more intuitively
This commit is contained in:
parent
ceeda6de3b
commit
6a9e07729f
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
@ -1 +1 @@
|
||||
Subproject commit 0947102c05757c28c94553d40945ced478355f01
|
||||
Subproject commit 7e43939feac350489d59d97e9d09bf61d463f6fe
|
@ -24,7 +24,7 @@ namespace hex::ui {
|
||||
|
||||
void draw(const std::vector<std::shared_ptr<pl::ptrn::Pattern>> &patterns, const pl::PatternLanguage *runtime = nullptr, float height = 0.0F);
|
||||
|
||||
enum class TreeStyle {
|
||||
enum class TreeStyle : u8 {
|
||||
Default = 0,
|
||||
AutoExpanded = 1,
|
||||
Flattened = 2
|
||||
@ -82,18 +82,19 @@ namespace hex::ui {
|
||||
void closeTreeNode(bool inlined) const;
|
||||
|
||||
bool sortPatterns(const ImGuiTableSortSpecs* sortSpecs, const pl::ptrn::Pattern * left, const pl::ptrn::Pattern * right) const;
|
||||
bool isEditingPattern(const pl::ptrn::Pattern& pattern) const;
|
||||
[[nodiscard]] bool isEditingPattern(const pl::ptrn::Pattern& pattern) const;
|
||||
void resetEditing();
|
||||
bool matchesFilter(const std::vector<std::string> &filterPath, const std::vector<std::string> &patternPath, bool fullMatch) const;
|
||||
void traversePatternTree(pl::ptrn::Pattern &pattern, std::vector<std::string> &patternPath, const std::function<void(pl::ptrn::Pattern&)> &callback);
|
||||
std::string getDisplayName(const pl::ptrn::Pattern& pattern) const;
|
||||
[[nodiscard]] std::string getDisplayName(const pl::ptrn::Pattern& pattern) const;
|
||||
|
||||
struct Filter {
|
||||
std::vector<std::string> path;
|
||||
std::optional<pl::core::Token::Literal> value;
|
||||
};
|
||||
|
||||
std::optional<Filter> parseRValueFilter(const std::string &filter) const;
|
||||
[[nodiscard]] static bool matchesFilter(const std::vector<std::string> &filterPath, const std::vector<std::string> &patternPath, bool fullMatch);
|
||||
[[nodiscard]] static std::optional<Filter> parseRValueFilter(const std::string &filter);
|
||||
void updateFilter();
|
||||
|
||||
private:
|
||||
std::map<const pl::ptrn::Pattern*, u64> m_displayEnd;
|
||||
@ -113,11 +114,13 @@ namespace hex::ui {
|
||||
|
||||
std::string m_filterText;
|
||||
Filter m_filter;
|
||||
std::vector<pl::ptrn::Pattern*> m_filteredPatterns;
|
||||
|
||||
std::vector<std::string> m_currPatternPath;
|
||||
std::map<std::vector<std::string>, std::unique_ptr<pl::ptrn::Pattern>> m_favorites;
|
||||
std::map<std::string, std::vector<std::unique_ptr<pl::ptrn::Pattern>>> m_groups;
|
||||
bool m_showFavoriteStars = false;
|
||||
bool m_favoritesUpdated = false;
|
||||
bool m_filtersUpdated = false;
|
||||
bool m_showSpecName = false;
|
||||
|
||||
TaskHolder m_favoritesUpdateTask;
|
||||
|
@ -151,7 +151,7 @@ namespace hex::ui {
|
||||
|
||||
}
|
||||
|
||||
std::optional<PatternDrawer::Filter> PatternDrawer::parseRValueFilter(const std::string &filter) const {
|
||||
std::optional<PatternDrawer::Filter> PatternDrawer::parseRValueFilter(const std::string &filter) {
|
||||
Filter result;
|
||||
|
||||
if (filter.empty()) {
|
||||
@ -192,6 +192,17 @@ namespace hex::ui {
|
||||
return result;
|
||||
}
|
||||
|
||||
void PatternDrawer::updateFilter() {
|
||||
m_filteredPatterns.clear();
|
||||
std::vector<std::string> treePath;
|
||||
for (auto &pattern : m_sortedPatterns) {
|
||||
traversePatternTree(*pattern, treePath, [this, &treePath](auto &pattern){
|
||||
if (matchesFilter(m_filter.path, treePath, false))
|
||||
m_filteredPatterns.push_back(&pattern);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool PatternDrawer::isEditingPattern(const pl::ptrn::Pattern& pattern) const {
|
||||
return m_editingPattern == &pattern && m_editingPatternOffset == pattern.getOffset();
|
||||
}
|
||||
@ -201,18 +212,28 @@ namespace hex::ui {
|
||||
m_editingPatternOffset = 0x00;
|
||||
}
|
||||
|
||||
bool PatternDrawer::matchesFilter(const std::vector<std::string> &filterPath, const std::vector<std::string> &patternPath, bool fullMatch) const {
|
||||
bool PatternDrawer::matchesFilter(const std::vector<std::string> &filterPath, const std::vector<std::string> &patternPath, bool fullMatch) {
|
||||
if (fullMatch) {
|
||||
if (patternPath.size() != filterPath.size())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (patternPath.size() <= filterPath.size()) {
|
||||
for (ssize_t i = patternPath.size() - 1; i >= 0; i--) {
|
||||
const auto &filter = filterPath[i];
|
||||
if (filterPath.size() > patternPath.size())
|
||||
return false;
|
||||
|
||||
if (patternPath[i] != filter && !filter.empty() && filter != "*") {
|
||||
return false;
|
||||
auto commonSize = std::min(filterPath.size(), patternPath.size());
|
||||
for (size_t i = patternPath.size() - commonSize; i < patternPath.size(); i += 1) {
|
||||
const auto &filter = filterPath[i - (patternPath.size() - commonSize)];
|
||||
if (filter.empty())
|
||||
return false;
|
||||
|
||||
if (filter != "*") {
|
||||
if (i == (patternPath.size() - 1)) {
|
||||
if (!patternPath[i].starts_with(filter))
|
||||
return false;
|
||||
} else {
|
||||
if (patternPath[i] != filter)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -887,21 +908,7 @@ namespace hex::ui {
|
||||
m_currPatternPath.push_back(pattern.getVariableName());
|
||||
ON_SCOPE_EXIT { m_currPatternPath.pop_back(); };
|
||||
|
||||
if (matchesFilter(m_filter.path, m_currPatternPath, false)) {
|
||||
if (m_filter.value.has_value()) {
|
||||
auto patternValue = pattern.getValue();
|
||||
if (patternValue == m_filter.value) {
|
||||
pattern.accept(*this);
|
||||
} else if (!matchesFilter(m_filter.path, m_currPatternPath, true)) {
|
||||
pattern.accept(*this);
|
||||
} else if (patternValue.isPattern() && m_filter.value->isString()) {
|
||||
if (patternValue.toString(true) == m_filter.value->toString(false))
|
||||
pattern.accept(*this);
|
||||
}
|
||||
} else {
|
||||
pattern.accept(*this);
|
||||
}
|
||||
}
|
||||
pattern.accept(*this);
|
||||
}
|
||||
|
||||
void PatternDrawer::drawArray(pl::ptrn::Pattern& pattern, pl::ptrn::IIterable &iterable, bool isInlined) {
|
||||
@ -1128,9 +1135,10 @@ namespace hex::ui {
|
||||
this->resetEditing();
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeightWithSpacing() * 9.5);
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeightWithSpacing() * 8.5F);
|
||||
if (ImGuiExt::InputTextIcon("##Search", ICON_VS_FILTER, m_filterText)) {
|
||||
m_filter = parseRValueFilter(m_filterText).value_or(Filter{ });
|
||||
updateFilter();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
@ -1172,7 +1180,7 @@ namespace hex::ui {
|
||||
const auto &extension = formatter->getFileExtension();
|
||||
|
||||
if (ImGui::MenuItem(name.c_str())) {
|
||||
fs::openFileBrowser(fs::DialogMode::Save, { { name.c_str(), extension.c_str() } }, [&](const std::fs::path &path) {
|
||||
fs::openFileBrowser(fs::DialogMode::Save, { { name, extension } }, [&](const std::fs::path &path) {
|
||||
auto result = formatter->format(*runtime);
|
||||
|
||||
wolv::io::File output(path, wolv::io::File::Mode::Create);
|
||||
@ -1183,10 +1191,10 @@ namespace hex::ui {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (!m_favoritesUpdated) {
|
||||
m_favoritesUpdated = true;
|
||||
if (!m_filtersUpdated && !patterns.empty()) {
|
||||
m_filtersUpdated = true;
|
||||
|
||||
if (!patterns.empty() && !m_favoritesUpdateTask.isRunning()) {
|
||||
if (!m_favoritesUpdateTask.isRunning()) {
|
||||
m_favoritesUpdateTask = TaskManager::createTask("hex.ui.pattern_drawer.updating"_lang, TaskManager::NoProgress, [this, patterns](auto &task) {
|
||||
size_t updatedFavorites = 0;
|
||||
|
||||
@ -1217,7 +1225,7 @@ namespace hex::ui {
|
||||
task.interrupt();
|
||||
task.update();
|
||||
|
||||
if (this->matchesFilter(patternPath, path, true)) {
|
||||
if (matchesFilter(patternPath, path, true)) {
|
||||
favoritePattern = currPattern.clone();
|
||||
updatedFavorites += 1;
|
||||
|
||||
@ -1235,6 +1243,8 @@ namespace hex::ui {
|
||||
});
|
||||
}
|
||||
|
||||
updateFilter();
|
||||
|
||||
}
|
||||
|
||||
if (beginPatternTable(patterns, m_sortedPatterns, height)) {
|
||||
@ -1299,7 +1309,7 @@ namespace hex::ui {
|
||||
|
||||
m_showFavoriteStars = true;
|
||||
|
||||
for (auto &pattern : m_sortedPatterns) {
|
||||
for (auto &pattern : m_filter.path.empty() ? m_sortedPatterns : m_filteredPatterns) {
|
||||
ImGui::PushID(id);
|
||||
this->draw(*pattern);
|
||||
ImGui::PopID();
|
||||
@ -1326,6 +1336,7 @@ namespace hex::ui {
|
||||
m_visualizedPatterns.clear();
|
||||
m_currVisualizedPattern = nullptr;
|
||||
m_sortedPatterns.clear();
|
||||
m_filteredPatterns.clear();
|
||||
m_lastVisualizerError.clear();
|
||||
m_currPatternPath.clear();
|
||||
|
||||
@ -1340,6 +1351,6 @@ namespace hex::ui {
|
||||
|
||||
m_groups.clear();
|
||||
|
||||
m_favoritesUpdated = false;
|
||||
m_filtersUpdated = false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user