CharacterSearchWidget.cpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "CharacterSearchWidget.h"
  7. #include "SearchCharacters.h"
  8. #include <Applications/CharacterMap/CharacterSearchWindowGML.h>
  9. struct SearchResult {
  10. u32 code_point;
  11. String code_point_string;
  12. String display_text;
  13. };
  14. class CharacterSearchModel final : public GUI::Model {
  15. public:
  16. CharacterSearchModel() { }
  17. int row_count(GUI::ModelIndex const&) const override { return m_data.size(); }
  18. int column_count(GUI::ModelIndex const&) const override { return 2; }
  19. GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override
  20. {
  21. auto& result = m_data.at(index.row());
  22. if (role == GUI::ModelRole::Display) {
  23. if (index.column() == 0)
  24. return result.code_point_string;
  25. return result.display_text;
  26. }
  27. if (role == GUI::ModelRole::Custom)
  28. return result.code_point;
  29. return {};
  30. }
  31. void clear()
  32. {
  33. m_data.clear();
  34. invalidate();
  35. }
  36. void add_result(SearchResult result)
  37. {
  38. m_data.append(move(result));
  39. invalidate();
  40. }
  41. private:
  42. Vector<SearchResult> m_data;
  43. };
  44. CharacterSearchWidget::CharacterSearchWidget()
  45. {
  46. load_from_gml(character_search_window_gml);
  47. m_search_input = find_descendant_of_type_named<GUI::TextBox>("search_input");
  48. m_search_button = find_descendant_of_type_named<GUI::Button>("search_button");
  49. m_results_table = find_descendant_of_type_named<GUI::TableView>("results_table");
  50. m_search_input->on_return_pressed = [this] { search(); };
  51. m_search_button->on_click = [this](auto) { search(); };
  52. m_results_table->horizontal_scrollbar().set_visible(false);
  53. m_results_table->set_column_headers_visible(false);
  54. m_results_table->set_model(adopt_ref(*new CharacterSearchModel()));
  55. m_results_table->on_activation = [&](GUI::ModelIndex const& index) {
  56. auto& model = static_cast<CharacterSearchModel&>(*m_results_table->model());
  57. auto code_point = model.data(index, GUI::ModelRole::Custom).as_u32();
  58. if (on_character_selected)
  59. on_character_selected(code_point);
  60. };
  61. }
  62. CharacterSearchWidget::~CharacterSearchWidget()
  63. {
  64. }
  65. void CharacterSearchWidget::search()
  66. {
  67. // TODO: Sort the results nicely. They're sorted by code-point for now, which is easy, but not the most useful.
  68. // Sorting intelligently in a style similar to Assistant would be nicer.
  69. auto& model = static_cast<CharacterSearchModel&>(*m_results_table->model());
  70. model.clear();
  71. auto query = m_search_input->text();
  72. if (query.is_empty())
  73. return;
  74. for_each_character_containing(query, [&](auto code_point, auto& display_name) {
  75. StringBuilder builder;
  76. builder.append_code_point(code_point);
  77. model.add_result({ code_point, builder.build(), display_name });
  78. });
  79. }