diff --git a/Userland/Libraries/LibGUI/AbstractScrollableWidget.cpp b/Userland/Libraries/LibGUI/AbstractScrollableWidget.cpp index c0d7730b48..5466f5f3fc 100644 --- a/Userland/Libraries/LibGUI/AbstractScrollableWidget.cpp +++ b/Userland/Libraries/LibGUI/AbstractScrollableWidget.cpp @@ -106,6 +106,7 @@ void AbstractScrollableWidget::custom_layout() void AbstractScrollableWidget::resize_event(ResizeEvent& event) { Frame::resize_event(event); + update_scrollbar_visibility(); update_scrollbar_ranges(); } @@ -125,26 +126,22 @@ Gfx::IntSize AbstractScrollableWidget::excess_size() const return { excess_width, excess_height }; } +void AbstractScrollableWidget::set_should_hide_unnecessary_scrollbars(bool should_hide_unnecessary_scrollbars) +{ + if (m_should_hide_unnecessary_scrollbars == should_hide_unnecessary_scrollbars) + return; + + m_should_hide_unnecessary_scrollbars = should_hide_unnecessary_scrollbars; + if (should_hide_unnecessary_scrollbars) + update_scrollbar_ranges(); + else { + m_horizontal_scrollbar->set_visible(true); + m_vertical_scrollbar->set_visible(true); + } +} + void AbstractScrollableWidget::update_scrollbar_ranges() { - if (should_hide_unnecessary_scrollbars()) { - if (excess_size().height() - height_occupied_by_horizontal_scrollbar() <= 0 && excess_size().width() - width_occupied_by_vertical_scrollbar() <= 0) { - m_horizontal_scrollbar->set_visible(false); - m_vertical_scrollbar->set_visible(false); - } else { - auto vertical_initial_visibility = m_vertical_scrollbar->is_visible(); - auto horizontal_initial_visibility = m_horizontal_scrollbar->is_visible(); - - m_vertical_scrollbar->set_visible(excess_size().height() > 0); - m_horizontal_scrollbar->set_visible(excess_size().width() > 0); - - if (m_vertical_scrollbar->is_visible() != vertical_initial_visibility) - m_horizontal_scrollbar->set_visible(excess_size().width() > 0); - if (m_horizontal_scrollbar->is_visible() != horizontal_initial_visibility) - m_vertical_scrollbar->set_visible(excess_size().height() > 0); - } - } - m_horizontal_scrollbar->set_range(0, excess_size().width()); m_horizontal_scrollbar->set_page_step(visible_content_rect().width() - m_horizontal_scrollbar->step()); @@ -152,6 +149,29 @@ void AbstractScrollableWidget::update_scrollbar_ranges() m_vertical_scrollbar->set_page_step(visible_content_rect().height() - m_vertical_scrollbar->step()); } +void AbstractScrollableWidget::update_scrollbar_visibility() +{ + if (should_hide_unnecessary_scrollbars()) { + // If there has not been a min_size set, the content_size can be used as a substitute + auto effective_min_content_size = m_min_content_size; + if (m_min_content_size == Gfx::IntSize {}) + effective_min_content_size = m_content_size; + int horizontal_buffer = rect().width() - 2 * frame_thickness() - effective_min_content_size.width(); + int vertical_buffer = rect().height() - 2 * frame_thickness() - effective_min_content_size.height(); + bool horizontal_scrollbar_should_be_visible = false, vertical_scrollbar_should_be_visible = false; + vertical_scrollbar_should_be_visible = vertical_buffer < 0; + if (vertical_scrollbar_should_be_visible) + horizontal_buffer -= m_vertical_scrollbar->width(); + horizontal_scrollbar_should_be_visible = horizontal_buffer < 0; + if (horizontal_scrollbar_should_be_visible) + vertical_buffer -= m_horizontal_scrollbar->height(); + vertical_scrollbar_should_be_visible = vertical_buffer < 0; + + m_horizontal_scrollbar->set_visible(horizontal_scrollbar_should_be_visible); + m_vertical_scrollbar->set_visible(vertical_scrollbar_should_be_visible); + } +} + void AbstractScrollableWidget::set_content_size(Gfx::IntSize const& size) { if (m_content_size == size) @@ -160,6 +180,14 @@ void AbstractScrollableWidget::set_content_size(Gfx::IntSize const& size) update_scrollbar_ranges(); } +void AbstractScrollableWidget::set_min_content_size(Gfx::IntSize const& min_size) +{ + if (m_min_content_size == min_size) + return; + m_min_content_size = min_size; + update_scrollbar_ranges(); +} + void AbstractScrollableWidget::set_size_occupied_by_fixed_elements(Gfx::IntSize const& size) { if (m_size_occupied_by_fixed_elements == size) diff --git a/Userland/Libraries/LibGUI/AbstractScrollableWidget.h b/Userland/Libraries/LibGUI/AbstractScrollableWidget.h index 54a79b7db7..88030ef5f6 100644 --- a/Userland/Libraries/LibGUI/AbstractScrollableWidget.h +++ b/Userland/Libraries/LibGUI/AbstractScrollableWidget.h @@ -21,6 +21,7 @@ public: Gfx::IntSize content_size() const { return m_content_size; } int content_width() const { return m_content_size.width(); } int content_height() const { return m_content_size.height(); } + Gfx::IntSize min_content_size() const { return m_min_content_size; } Gfx::IntRect visible_content_rect() const; @@ -60,7 +61,7 @@ public: virtual Margins content_margins() const override; - void set_should_hide_unnecessary_scrollbars(bool b) { m_should_hide_unnecessary_scrollbars = b; } + void set_should_hide_unnecessary_scrollbars(bool); bool should_hide_unnecessary_scrollbars() const { return m_should_hide_unnecessary_scrollbars; } Gfx::IntPoint to_content_position(Gfx::IntPoint const& widget_position) const; @@ -76,9 +77,12 @@ protected: virtual void mousewheel_event(MouseEvent&) override; virtual void did_scroll() { } void set_content_size(Gfx::IntSize const&); + void set_min_content_size(Gfx::IntSize const&); void set_size_occupied_by_fixed_elements(Gfx::IntSize const&); virtual void on_automatic_scrolling_timer_fired() {}; int autoscroll_threshold() const { return m_autoscroll_threshold; } + void update_scrollbar_visibility(); + void update_scrollbar_ranges(); private: class AbstractScrollableWidgetScrollbar final : public Scrollbar { @@ -100,13 +104,13 @@ private: }; friend class ScrollableWidgetScrollbar; - void update_scrollbar_ranges(); void handle_wheel_event(MouseEvent&, Widget&); RefPtr m_vertical_scrollbar; RefPtr m_horizontal_scrollbar; RefPtr m_corner_widget; Gfx::IntSize m_content_size; + Gfx::IntSize m_min_content_size; Gfx::IntSize m_size_occupied_by_fixed_elements; bool m_scrollbars_enabled { true }; bool m_should_hide_unnecessary_scrollbars { false };