From eb06929e222dbebe499412a0e5406e958187fe86 Mon Sep 17 00:00:00 2001 From: jostephd Date: Sun, 23 Dec 2018 16:42:37 +0000 Subject: [PATCH] Recruit Unit: Add search functionality (#3787) --- data/gui/window/unit_recruit.cfg | 46 +++++++++++++--------- src/gui/dialogs/unit_recruit.cpp | 65 +++++++++++++++++++++++++++++++- src/gui/dialogs/unit_recruit.hpp | 4 ++ 3 files changed, 97 insertions(+), 18 deletions(-) diff --git a/data/gui/window/unit_recruit.cfg b/data/gui/window/unit_recruit.cfg index 59275b62390d..d5a373052dd3 100644 --- a/data/gui/window/unit_recruit.cfg +++ b/data/gui/window/unit_recruit.cfg @@ -132,23 +132,6 @@ [/helptip] [grid] - [row] - grow_factor = 0 - - [column] - grow_factor = 1 - border = "all" - border_size = 5 - horizontal_alignment = "left" - - [label] - definition = "title" - label = _ "Recruit Unit" - [/label] - - [/column] - - [/row] [row] grow_factor = 1 @@ -159,6 +142,35 @@ [grid] + [row] + + [column] + grow_factor = 1 + border = "all" + border_size = 5 + horizontal_alignment = "left" + + [label] + definition = "title" + label = _ "Recruit Unit" + [/label] + + [/column] + + [column] + border = "all" + border_size = 5 + horizontal_alignment = "left" + + [text_box] + id = "filter_box" + definition = "default" + {FITER_TEXT_BOX_HINT} + [/text_box] + + [/column] + [/row] + [row] [column] grow_factor = 0 diff --git a/src/gui/dialogs/unit_recruit.cpp b/src/gui/dialogs/unit_recruit.cpp index 59f98e0bdfbf..b975f523074f 100644 --- a/src/gui/dialogs/unit_recruit.cpp +++ b/src/gui/dialogs/unit_recruit.cpp @@ -21,6 +21,8 @@ #include "gui/widgets/listbox.hpp" #include "gui/widgets/unit_preview_pane.hpp" #include "gui/widgets/settings.hpp" +#include "gui/widgets/text_box.hpp" +#include "gui/widgets/text_box_base.hpp" #include "gui/widgets/window.hpp" #include "gettext.hpp" #include "help/help.hpp" @@ -55,13 +57,74 @@ static std::string can_afford_unit(const std::string& text, const bool can_affor return can_afford ? text : "" + text + ""; } +namespace +{ + +bool ci_search(const std::string& a, const std::string& b) +{ + return std::search(a.begin(), a.end(), + b.begin(), b.end(), + chars_equal_insensitive) != a.end(); +} + +} // end unnamed namespace + +// Compare unit_create::filter_text_change +void unit_recruit::filter_text_changed(text_box_base* textbox, const std::string& text) +{ + window& window = *textbox->get_window(); + + listbox& list = find_widget(&window, "recruit_list", false); + + const std::vector words = utils::split(text, ' '); + + if(words == last_words_) + return; + last_words_ = words; + + boost::dynamic_bitset<> show_items; + show_items.resize(list.get_item_count(), true); + + if(!text.empty()) { + for(unsigned int i = 0; i < list.get_item_count(); i++) { + assert(i < recruit_list_.size()); + const unit_type* type = recruit_list_[i]; + if(!type) continue; + + bool found = false; + for(const auto & word : words) + { + // Search for the name in the local language. + // In debug mode, also search for the type id. + found = + (game_config::debug && ci_search(type->id(), word)) || + ci_search(type->type_name(), word); + + if(!found) { + // one word doesn't match, we don't reach words.end() + break; + } + } + + show_items[i] = found; + } + } + + list.set_row_shown(show_items); +} + void unit_recruit::pre_show(window& window) { + text_box* filter = find_widget(&window, "filter_box", false, true); + filter->set_text_changed_callback( + std::bind(&unit_recruit::filter_text_changed, this, _1, _2)); + listbox& list = find_widget(&window, "recruit_list", false); connect_signal_notify_modified(list, std::bind(&unit_recruit::list_item_clicked, this, std::ref(window))); - window.keyboard_capture(&list); + window.keyboard_capture(filter); + window.add_to_keyboard_chain(&list); connect_signal_mouse_left_click( find_widget