Implement filtering for TreeSearch

This commit is contained in:
Alexander Montag 2024-09-25 16:54:33 +00:00
parent b4974bffd2
commit 18a6bbeae6
3 changed files with 47 additions and 10 deletions

View File

@ -533,8 +533,10 @@ void TaskTree::_notification(int p_what) {
tree->connect("multi_selected", callable_mp(this, &TaskTree::_on_item_selected).unbind(3), CONNECT_DEFERRED);
tree->connect("item_activated", callable_mp(this, &TaskTree::_on_item_activated));
tree->connect("item_collapsed", callable_mp(this, &TaskTree::_on_item_collapsed));
// TODO: Simplify these signals into one (candidate names: changed, updated, update_requested):
tree_search->search_panel->connect("text_changed", callable_mp(this, &TaskTree::_update_tree).unbind(1));
tree_search->search_panel->connect("visibility_changed", callable_mp(this, &TaskTree::_update_tree));
tree_search->search_panel->connect("filter_toggled", callable_mp(this, &TaskTree::_update_tree));
} break;
case NOTIFICATION_THEME_CHANGED: {
_do_update_theme_item_cache();

View File

@ -93,6 +93,10 @@ void TreeSearchPanel::_emit_text_submitted(const String &p_text) {
this->emit_signal("text_submitted");
}
void TreeSearchPanel::_emit_filter_toggled() {
this->emit_signal("filter_toggled");
}
void TreeSearchPanel::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
@ -100,6 +104,7 @@ void TreeSearchPanel::_notification(int p_what) {
line_edit_search->connect("text_changed", callable_mp(this, &TreeSearchPanel::_emit_text_changed));
_initialize_close_callbacks();
line_edit_search->connect("text_submitted", callable_mp(this, &TreeSearchPanel::_emit_text_submitted));
check_button_filter_highlight->connect("pressed", callable_mp(this, &TreeSearchPanel::_emit_filter_toggled));
break;
}
}
@ -108,6 +113,7 @@ void TreeSearchPanel::_notification(int p_what) {
void TreeSearchPanel::_bind_methods() {
ADD_SIGNAL(MethodInfo("text_changed"));
ADD_SIGNAL(MethodInfo("text_submitted"));
ADD_SIGNAL(MethodInfo("filter_toggled"));
}
TreeSearchPanel::TreeSearchPanel() {
@ -140,10 +146,26 @@ void TreeSearchPanel::show_and_focus() {
/* ------- TreeSearch ------- */
void TreeSearch::_filter_tree(TreeItem *p_tree_item, const String &p_search_mask) {
for (int i = 0; i < ordered_tree_items.size(); i++) {
void TreeSearch::_filter_tree(const String &p_search_mask) {
if (matching_entries.size() == 0) {
return;
}
for (int i = 0; i < ordered_tree_items.size(); i++) {
TreeItem *cur_item = ordered_tree_items[i];
if (number_matches.has(cur_item)){
continue;
}
TreeItem *first_counting_ancestor = cur_item;
while (first_counting_ancestor && !number_matches.has(first_counting_ancestor)) {
first_counting_ancestor = first_counting_ancestor->get_parent();
}
if (!first_counting_ancestor || first_counting_ancestor == tree_reference->get_root() || !_vector_has_bsearch(matching_entries, first_counting_ancestor)) {
cur_item->set_visible(false);
}
}
PRINT_LINE("filter tree not yet implemented!", p_search_mask);
}
void TreeSearch::_highlight_tree(const String &p_search_mask) {
@ -366,8 +388,7 @@ void TreeSearch::_select_first_match() {
}
for (int i = 0; i < ordered_tree_items.size(); i++) {
TreeItem *item = ordered_tree_items[i];
int match_idx = matching_entries.bsearch(item, true);
if (match_idx < 0 || match_idx >= matching_entries.size() || matching_entries[match_idx] != item) {
if (!_vector_has_bsearch(matching_entries, item)){
continue;
}
String debug_string = "[";
@ -397,8 +418,7 @@ void TreeSearch::_select_next_match() {
// find the best fitting entry.
for (int i = 0; i < ordered_tree_items.size(); i++) {
TreeItem *item = ordered_tree_items[i];
int match_idx = matching_entries.bsearch(item, true);
if (match_idx < 0 || match_idx >= matching_entries.size() || selected_idx >= i || matching_entries[match_idx] != item) {
if (!_vector_has_bsearch(matching_entries, item)){
continue;
}
@ -408,6 +428,14 @@ void TreeSearch::_select_next_match() {
_select_first_match(); // wrap around.
}
template <typename T>
inline bool TreeSearch::_vector_has_bsearch(Vector<T *> p_vec, T *element) {
int idx = p_vec.bsearch(element, true);
bool in_array = idx >= 0 && idx < p_vec.size();
return in_array && p_vec[idx] == element;
}
void TreeSearch::on_item_edited(TreeItem *item) {
if (item->get_cell_mode(0) != TreeItem::CELL_MODE_CUSTOM) {
return;
@ -446,7 +474,7 @@ void TreeSearch::update_search(Tree *p_tree) {
}
}
if (search_mode == TreeSearchMode::FILTER) {
_filter_tree(tree_root, search_mask);
_filter_tree(search_mask);
}
}

View File

@ -56,6 +56,7 @@ private:
void _on_draw_highlight(TreeItem *item, Rect2 rect);
void _emit_text_changed(const String &text);
void _emit_text_submitted(const String &p_text);
void _emit_filter_toggled();
void _notification(int p_what);
protected:
@ -90,12 +91,14 @@ private:
HashMap<TreeItem *, int> number_matches;
HashMap<TreeItem *, Callable> callable_cache;
void _filter_tree(TreeItem *tree_item, const String &search_mask);
void _filter_tree(const String &p_search_mask);
void _highlight_tree(const String &p_search_mask);
void _draw_highlight_item(TreeItem *tree_item, Rect2 rect, String search_mask, Callable parent_draw_method);
void _update_matching_entries(const String &search_mask);
void _update_ordered_tree_items(TreeItem *tree_item);
void _update_number_matches();
Vector<TreeItem *> _find_matching_entries(TreeItem *tree_item, const String &search_mask, Vector<TreeItem *> &buffer);
StringSearchIndices _substring_bounds(const String &searchable, const String &search_mask) const;
@ -103,6 +106,8 @@ private:
void _select_first_match();
void _select_next_match();
template<typename T>
bool _vector_has_bsearch(Vector<T*> p_vec, T* element);
protected:
static void _bind_methods() {}
@ -117,4 +122,6 @@ public:
};
#endif // TREE_SEARCH_H
#endif // ! TOOLS_ENABLED
#endif // ! TOOLS_ENABLED