1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 11:28:12 +00:00

LibGUI: Add a AutoScroll timer to AbstractScrollableWidget

This commit adds a timer to AbstractScrollableWidget that can be used
when implementing automatic scrolling. By overriding
on_automatic_scrolling_timer_fired() we can calculate the scrolling
delta when dragging objects, and redraw as needed. A helper function,
automatic_scroll_delta_from_position() gives us a delta that
we can use to calculate speed and direction. By default
m_autoscroll_threshold is 20 pixels from the edge, and gives a linear
change in scroll delta.
This commit is contained in:
Marcus Nilsson 2021-09-16 19:00:09 +02:00 committed by Andreas Kling
parent 522119ab95
commit eec411c508
2 changed files with 47 additions and 0 deletions

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/Timer.h>
#include <LibGUI/AbstractScrollableWidget.h>
#include <LibGUI/Scrollbar.h>
@ -28,6 +29,12 @@ AbstractScrollableWidget::AbstractScrollableWidget()
m_corner_widget = add<Widget>();
m_corner_widget->set_fill_with_background_color(true);
m_automatic_scrolling_timer = add<Core::Timer>();
m_automatic_scrolling_timer->set_interval(50);
m_automatic_scrolling_timer->on_timeout = [this] {
on_automatic_scrolling_timer_fired();
};
}
AbstractScrollableWidget::~AbstractScrollableWidget()
@ -214,6 +221,38 @@ void AbstractScrollableWidget::scroll_to_bottom()
scroll_into_view({ 0, content_height(), 0, 0 }, Orientation::Vertical);
}
void AbstractScrollableWidget::set_automatic_scrolling_timer(bool active)
{
if (active == m_active_scrolling_enabled)
return;
m_active_scrolling_enabled = active;
if (active) {
on_automatic_scrolling_timer_fired();
m_automatic_scrolling_timer->start();
} else {
m_automatic_scrolling_timer->stop();
}
}
Gfx::IntPoint AbstractScrollableWidget::automatic_scroll_delta_from_position(const Gfx::IntPoint& pos) const
{
Gfx::IntPoint delta { 0, 0 };
if (pos.y() < m_autoscroll_threshold)
delta.set_y(clamp(-(m_autoscroll_threshold - pos.y()), -m_autoscroll_threshold, 0));
else if (pos.y() > height() - m_autoscroll_threshold)
delta.set_y(clamp(m_autoscroll_threshold - (height() - pos.y()), 0, m_autoscroll_threshold));
if (pos.x() < m_autoscroll_threshold)
delta.set_x(clamp(-(m_autoscroll_threshold - pos.x()), -m_autoscroll_threshold, 0));
else if (pos.x() > width() - m_autoscroll_threshold)
delta.set_x(clamp(m_autoscroll_threshold - (width() - pos.x()), 0, m_autoscroll_threshold));
return delta;
}
Gfx::IntRect AbstractScrollableWidget::widget_inner_rect() const
{
auto rect = frame_inner_rect();