GComboBox.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include <LibGUI/GButton.h>
  2. #include <LibGUI/GComboBox.h>
  3. #include <LibGUI/GListView.h>
  4. #include <LibGUI/GScrollBar.h>
  5. #include <LibGUI/GTextEditor.h>
  6. #include <LibGUI/GWindow.h>
  7. GComboBox::GComboBox(GWidget* parent)
  8. : GWidget(parent)
  9. {
  10. m_editor = new GTextEditor(GTextEditor::Type::SingleLine, this);
  11. m_editor->on_change = [this] {
  12. if (on_change)
  13. on_change(m_editor->text());
  14. };
  15. m_editor->on_return_pressed = [this] {
  16. if (on_return_pressed)
  17. on_return_pressed();
  18. };
  19. m_open_button = new GButton(this);
  20. m_open_button->set_focusable(false);
  21. m_open_button->set_text("\xf7");
  22. m_open_button->on_click = [this](auto&) {
  23. if (m_list_window->is_visible())
  24. close();
  25. else
  26. open();
  27. };
  28. m_list_window = new GWindow(this);
  29. // FIXME: This is obviously not a tooltip window, but it's the closest thing to what we want atm.
  30. m_list_window->set_window_type(GWindowType::Tooltip);
  31. m_list_window->set_should_destroy_on_close(false);
  32. m_list_view = new GListView(nullptr);
  33. m_list_view->horizontal_scrollbar().set_visible(false);
  34. m_list_window->set_main_widget(m_list_view);
  35. m_list_view->on_selection = [this](auto& index) {
  36. ASSERT(model());
  37. auto new_value = model()->data(index).to_string();
  38. m_editor->set_text(new_value);
  39. m_editor->select_all();
  40. close();
  41. deferred_invoke([this](auto&) {
  42. if (on_change)
  43. on_change(m_editor->text());
  44. });
  45. };
  46. }
  47. GComboBox::~GComboBox()
  48. {
  49. }
  50. void GComboBox::resize_event(GResizeEvent& event)
  51. {
  52. int frame_thickness = m_editor->frame_thickness();
  53. int button_height = event.size().height() - frame_thickness * 2;
  54. int button_width = 15;
  55. m_open_button->set_relative_rect(width() - button_width - frame_thickness, frame_thickness, button_width, button_height);
  56. m_editor->set_relative_rect(0, 0, width(), height());
  57. }
  58. void GComboBox::set_model(NonnullRefPtr<GModel> model)
  59. {
  60. m_list_view->set_model(move(model));
  61. }
  62. void GComboBox::select_all()
  63. {
  64. m_editor->select_all();
  65. }
  66. void GComboBox::open()
  67. {
  68. if (!model())
  69. return;
  70. auto my_screen_rect = screen_relative_rect();
  71. int longest_item_width = 0;
  72. for (int i = 0; i < model()->row_count(); ++i) {
  73. auto index = model()->index(i);
  74. auto item_text = model()->data(index).to_string();
  75. longest_item_width = max(longest_item_width, m_list_view->font().width(item_text));
  76. }
  77. Size size {
  78. max(width(), longest_item_width + m_list_view->width_occupied_by_vertical_scrollbar() + m_list_view->frame_thickness() * 2 + m_list_view->horizontal_padding()),
  79. model()->row_count() * m_list_view->item_height() + m_list_view->frame_thickness() * 2
  80. };
  81. m_list_window->set_rect({ my_screen_rect.bottom_left(), size });
  82. m_list_window->show();
  83. }
  84. void GComboBox::close()
  85. {
  86. m_list_window->hide();
  87. m_editor->set_focus(true);
  88. }
  89. String GComboBox::text() const
  90. {
  91. return m_editor->text();
  92. }
  93. void GComboBox::set_text(const String& text)
  94. {
  95. m_editor->set_text(text);
  96. }
  97. void GComboBox::set_only_allow_values_from_model(bool b)
  98. {
  99. if (m_only_allow_values_from_model == b)
  100. return;
  101. m_editor->set_readonly(m_only_allow_values_from_model);
  102. }