GScrollableWidget.cpp 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include <LibGUI/GScrollableWidget.h>
  2. #include <LibGUI/GScrollBar.h>
  3. GScrollableWidget::GScrollableWidget(GWidget* parent)
  4. : GWidget(parent)
  5. {
  6. m_vertical_scrollbar = new GScrollBar(Orientation::Vertical, this);
  7. m_vertical_scrollbar->set_step(4);
  8. m_vertical_scrollbar->on_change = [this] (int) {
  9. update();
  10. };
  11. m_horizontal_scrollbar = new GScrollBar(Orientation::Horizontal, this);
  12. m_horizontal_scrollbar->set_step(4);
  13. m_horizontal_scrollbar->set_big_step(30);
  14. m_horizontal_scrollbar->on_change = [this] (int) {
  15. update();
  16. };
  17. m_corner_widget = new GWidget(this);
  18. m_corner_widget->set_fill_with_background_color(true);
  19. }
  20. GScrollableWidget::~GScrollableWidget()
  21. {
  22. }
  23. void GScrollableWidget::resize_event(GResizeEvent& event)
  24. {
  25. update_scrollbar_ranges();
  26. m_vertical_scrollbar->set_relative_rect(event.size().width() - m_vertical_scrollbar->preferred_size().width(), 0, m_vertical_scrollbar->preferred_size().width(), event.size().height() - m_horizontal_scrollbar->preferred_size().height());
  27. m_horizontal_scrollbar->set_relative_rect(0, event.size().height() - m_horizontal_scrollbar->preferred_size().height(), event.size().width() - m_vertical_scrollbar->preferred_size().width(), m_horizontal_scrollbar->preferred_size().height());
  28. m_corner_widget->set_visible(m_vertical_scrollbar->is_visible() && m_horizontal_scrollbar->is_visible());
  29. if (m_corner_widget->is_visible()) {
  30. Rect corner_rect { m_horizontal_scrollbar->rect().right() + 1, m_vertical_scrollbar->rect().bottom() + 1, m_horizontal_scrollbar->height(), m_vertical_scrollbar->width() };
  31. m_corner_widget->set_relative_rect(corner_rect);
  32. }
  33. }
  34. void GScrollableWidget::update_scrollbar_ranges()
  35. {
  36. int available_height = height() - m_size_occupied_by_fixed_elements.height() - m_horizontal_scrollbar->height();
  37. int excess_height = max(0, m_content_size.height() - available_height);
  38. m_vertical_scrollbar->set_range(0, excess_height);
  39. int available_width = width() - m_size_occupied_by_fixed_elements.width() - m_vertical_scrollbar->width();
  40. int excess_width = max(0, m_content_size.width() - available_width);
  41. m_horizontal_scrollbar->set_range(0, excess_width);
  42. m_vertical_scrollbar->set_big_step(visible_content_rect().height() - m_vertical_scrollbar->step());
  43. }
  44. void GScrollableWidget::set_content_size(const Size& size)
  45. {
  46. if (m_content_size == size)
  47. return;
  48. m_content_size = size;
  49. update_scrollbar_ranges();
  50. }
  51. void GScrollableWidget::set_size_occupied_by_fixed_elements(const Size& size)
  52. {
  53. if (m_size_occupied_by_fixed_elements == size)
  54. return;
  55. m_size_occupied_by_fixed_elements = size;
  56. update_scrollbar_ranges();
  57. }
  58. Rect GScrollableWidget::visible_content_rect() const
  59. {
  60. return {
  61. m_horizontal_scrollbar->value(),
  62. m_vertical_scrollbar->value(),
  63. width() - m_vertical_scrollbar->width(),
  64. height() - m_size_occupied_by_fixed_elements.height() - m_horizontal_scrollbar->height()
  65. };
  66. }
  67. void GScrollableWidget::scroll_into_view(const Rect& rect, Orientation orientation)
  68. {
  69. auto visible_content_rect = this->visible_content_rect();
  70. if (visible_content_rect.contains(rect))
  71. return;
  72. if (orientation == Orientation::Vertical) {
  73. if (rect.top() < visible_content_rect.top())
  74. m_vertical_scrollbar->set_value(rect.top());
  75. else if (rect.bottom() > visible_content_rect.bottom())
  76. m_vertical_scrollbar->set_value(rect.bottom() - visible_content_rect.height());
  77. } else {
  78. if (rect.left() < visible_content_rect.left())
  79. m_horizontal_scrollbar->set_value(rect.left());
  80. else if (rect.right() > visible_content_rect.right())
  81. m_horizontal_scrollbar->set_value(rect.right() - visible_content_rect.width());
  82. }
  83. }