Implement filtering for TreeSearch
This commit is contained in:
parent
b4974bffd2
commit
18a6bbeae6
|
@ -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("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_activated", callable_mp(this, &TaskTree::_on_item_activated));
|
||||||
tree->connect("item_collapsed", callable_mp(this, &TaskTree::_on_item_collapsed));
|
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("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("visibility_changed", callable_mp(this, &TaskTree::_update_tree));
|
||||||
|
tree_search->search_panel->connect("filter_toggled", callable_mp(this, &TaskTree::_update_tree));
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_THEME_CHANGED: {
|
case NOTIFICATION_THEME_CHANGED: {
|
||||||
_do_update_theme_item_cache();
|
_do_update_theme_item_cache();
|
||||||
|
|
|
@ -93,6 +93,10 @@ void TreeSearchPanel::_emit_text_submitted(const String &p_text) {
|
||||||
this->emit_signal("text_submitted");
|
this->emit_signal("text_submitted");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TreeSearchPanel::_emit_filter_toggled() {
|
||||||
|
this->emit_signal("filter_toggled");
|
||||||
|
}
|
||||||
|
|
||||||
void TreeSearchPanel::_notification(int p_what) {
|
void TreeSearchPanel::_notification(int p_what) {
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case NOTIFICATION_READY: {
|
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));
|
line_edit_search->connect("text_changed", callable_mp(this, &TreeSearchPanel::_emit_text_changed));
|
||||||
_initialize_close_callbacks();
|
_initialize_close_callbacks();
|
||||||
line_edit_search->connect("text_submitted", callable_mp(this, &TreeSearchPanel::_emit_text_submitted));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,6 +113,7 @@ void TreeSearchPanel::_notification(int p_what) {
|
||||||
void TreeSearchPanel::_bind_methods() {
|
void TreeSearchPanel::_bind_methods() {
|
||||||
ADD_SIGNAL(MethodInfo("text_changed"));
|
ADD_SIGNAL(MethodInfo("text_changed"));
|
||||||
ADD_SIGNAL(MethodInfo("text_submitted"));
|
ADD_SIGNAL(MethodInfo("text_submitted"));
|
||||||
|
ADD_SIGNAL(MethodInfo("filter_toggled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeSearchPanel::TreeSearchPanel() {
|
TreeSearchPanel::TreeSearchPanel() {
|
||||||
|
@ -140,10 +146,26 @@ void TreeSearchPanel::show_and_focus() {
|
||||||
|
|
||||||
/* ------- TreeSearch ------- */
|
/* ------- TreeSearch ------- */
|
||||||
|
|
||||||
void TreeSearch::_filter_tree(TreeItem *p_tree_item, const String &p_search_mask) {
|
void TreeSearch::_filter_tree(const String &p_search_mask) {
|
||||||
for (int i = 0; i < ordered_tree_items.size(); i++) {
|
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) {
|
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++) {
|
for (int i = 0; i < ordered_tree_items.size(); i++) {
|
||||||
TreeItem *item = ordered_tree_items[i];
|
TreeItem *item = ordered_tree_items[i];
|
||||||
int match_idx = matching_entries.bsearch(item, true);
|
if (!_vector_has_bsearch(matching_entries, item)){
|
||||||
if (match_idx < 0 || match_idx >= matching_entries.size() || matching_entries[match_idx] != item) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String debug_string = "[";
|
String debug_string = "[";
|
||||||
|
@ -397,8 +418,7 @@ void TreeSearch::_select_next_match() {
|
||||||
// find the best fitting entry.
|
// find the best fitting entry.
|
||||||
for (int i = 0; i < ordered_tree_items.size(); i++) {
|
for (int i = 0; i < ordered_tree_items.size(); i++) {
|
||||||
TreeItem *item = ordered_tree_items[i];
|
TreeItem *item = ordered_tree_items[i];
|
||||||
int match_idx = matching_entries.bsearch(item, true);
|
if (!_vector_has_bsearch(matching_entries, item)){
|
||||||
if (match_idx < 0 || match_idx >= matching_entries.size() || selected_idx >= i || matching_entries[match_idx] != item) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +428,14 @@ void TreeSearch::_select_next_match() {
|
||||||
_select_first_match(); // wrap around.
|
_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) {
|
void TreeSearch::on_item_edited(TreeItem *item) {
|
||||||
if (item->get_cell_mode(0) != TreeItem::CELL_MODE_CUSTOM) {
|
if (item->get_cell_mode(0) != TreeItem::CELL_MODE_CUSTOM) {
|
||||||
return;
|
return;
|
||||||
|
@ -446,7 +474,7 @@ void TreeSearch::update_search(Tree *p_tree) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (search_mode == TreeSearchMode::FILTER) {
|
if (search_mode == TreeSearchMode::FILTER) {
|
||||||
_filter_tree(tree_root, search_mask);
|
_filter_tree(search_mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ private:
|
||||||
void _on_draw_highlight(TreeItem *item, Rect2 rect);
|
void _on_draw_highlight(TreeItem *item, Rect2 rect);
|
||||||
void _emit_text_changed(const String &text);
|
void _emit_text_changed(const String &text);
|
||||||
void _emit_text_submitted(const String &p_text);
|
void _emit_text_submitted(const String &p_text);
|
||||||
|
void _emit_filter_toggled();
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -90,12 +91,14 @@ private:
|
||||||
HashMap<TreeItem *, int> number_matches;
|
HashMap<TreeItem *, int> number_matches;
|
||||||
HashMap<TreeItem *, Callable> callable_cache;
|
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 _highlight_tree(const String &p_search_mask);
|
||||||
void _draw_highlight_item(TreeItem *tree_item, Rect2 rect, String search_mask, Callable parent_draw_method);
|
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_matching_entries(const String &search_mask);
|
||||||
void _update_ordered_tree_items(TreeItem *tree_item);
|
void _update_ordered_tree_items(TreeItem *tree_item);
|
||||||
void _update_number_matches();
|
void _update_number_matches();
|
||||||
|
|
||||||
|
|
||||||
Vector<TreeItem *> _find_matching_entries(TreeItem *tree_item, const String &search_mask, Vector<TreeItem *> &buffer);
|
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;
|
StringSearchIndices _substring_bounds(const String &searchable, const String &search_mask) const;
|
||||||
|
|
||||||
|
@ -103,6 +106,8 @@ private:
|
||||||
void _select_first_match();
|
void _select_first_match();
|
||||||
void _select_next_match();
|
void _select_next_match();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool _vector_has_bsearch(Vector<T*> p_vec, T* element);
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods() {}
|
static void _bind_methods() {}
|
||||||
|
|
||||||
|
@ -117,4 +122,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TREE_SEARCH_H
|
#endif // TREE_SEARCH_H
|
||||||
#endif // ! TOOLS_ENABLED
|
#endif // ! TOOLS_ENABLED
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue