LibGUI: Make GUI::ScrollBar inherit from AbstractSlider
This commit is contained in:
parent
cb67264f61
commit
1215d2a642
Notes:
sideshowbarker
2024-07-19 00:22:38 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/1215d2a6429
6 changed files with 33 additions and 89 deletions
|
@ -282,8 +282,10 @@ int main(int argc, char** argv)
|
|||
vert_slider_group_box.set_title("Vertical sliders");
|
||||
|
||||
auto& vslider1 = vert_slider_group_box.add<GUI::VerticalSlider>();
|
||||
vslider1.set_max(100);
|
||||
vslider1.set_tooltip("Fixed");
|
||||
auto& vslider2 = vert_slider_group_box.add<GUI::VerticalSlider>();
|
||||
vslider1.set_max(100);
|
||||
vslider2.set_enabled(false);
|
||||
vslider2.set_tooltip("Disabled");
|
||||
auto& vslider3 = vert_slider_group_box.add<GUI::VerticalSlider>();
|
||||
|
@ -304,9 +306,11 @@ int main(int argc, char** argv)
|
|||
horizontal_slider_container2.set_layout<GUI::HorizontalBoxLayout>();
|
||||
horizontal_slider_container2.layout()->set_margins({ 4, 4, 4, 4 });
|
||||
|
||||
[[maybe_unused]] auto& slider1 = horizontal_slider_container.add<GUI::HorizontalSlider>();
|
||||
auto& slider1 = horizontal_slider_container.add<GUI::HorizontalSlider>();
|
||||
slider1.set_max(100);
|
||||
auto& slider2 = horizontal_slider_container.add<GUI::HorizontalSlider>();
|
||||
slider2.set_enabled(false);
|
||||
slider2.set_max(100);
|
||||
slider2.set_value(50);
|
||||
auto& slider3 = horizontal_slider_container.add<GUI::HorizontalSlider>();
|
||||
slider3.set_max(5);
|
||||
|
|
|
@ -63,7 +63,7 @@ private:
|
|||
|
||||
int m_value { 0 };
|
||||
int m_min { 0 };
|
||||
int m_max { 100 };
|
||||
int m_max { 0 };
|
||||
int m_step { 1 };
|
||||
int m_page_step { 10 };
|
||||
Orientation m_orientation { Orientation::Horizontal };
|
||||
|
|
|
@ -87,7 +87,7 @@ static Gfx::CharacterBitmap* s_left_arrow_bitmap;
|
|||
static Gfx::CharacterBitmap* s_right_arrow_bitmap;
|
||||
|
||||
ScrollBar::ScrollBar(Orientation orientation)
|
||||
: m_orientation(orientation)
|
||||
: AbstractSlider(orientation)
|
||||
{
|
||||
m_automatic_scrolling_timer = add<Core::Timer>();
|
||||
if (!s_up_arrow_bitmap)
|
||||
|
@ -99,7 +99,7 @@ ScrollBar::ScrollBar(Orientation orientation)
|
|||
if (!s_right_arrow_bitmap)
|
||||
s_right_arrow_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_right_arrow_bitmap_data, 9, 9).leak_ref();
|
||||
|
||||
if (m_orientation == Orientation::Vertical) {
|
||||
if (orientation == Orientation::Vertical) {
|
||||
set_fixed_width(16);
|
||||
} else {
|
||||
set_fixed_height(16);
|
||||
|
@ -109,48 +109,12 @@ ScrollBar::ScrollBar(Orientation orientation)
|
|||
m_automatic_scrolling_timer->on_timeout = [this] {
|
||||
on_automatic_scrolling_timer_fired();
|
||||
};
|
||||
|
||||
REGISTER_INT_PROPERTY("min", min, set_min);
|
||||
REGISTER_INT_PROPERTY("max", max, set_max);
|
||||
REGISTER_INT_PROPERTY("step", step, set_step);
|
||||
REGISTER_INT_PROPERTY("big_step", big_step, set_big_step);
|
||||
}
|
||||
|
||||
ScrollBar::~ScrollBar()
|
||||
{
|
||||
}
|
||||
|
||||
void ScrollBar::set_range(int min, int max, int page)
|
||||
{
|
||||
ASSERT(min <= max);
|
||||
if (page < 0)
|
||||
page = 0;
|
||||
if (m_min == min && m_max == max && m_page == page)
|
||||
return;
|
||||
|
||||
m_min = min;
|
||||
m_max = max;
|
||||
m_page = page;
|
||||
|
||||
int old_value = m_value;
|
||||
m_value = clamp(m_value, m_min, m_max);
|
||||
if (on_change && m_value != old_value)
|
||||
on_change(m_value);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void ScrollBar::set_value(int value)
|
||||
{
|
||||
value = clamp(value, m_min, m_max);
|
||||
if (value == m_value)
|
||||
return;
|
||||
m_value = value;
|
||||
if (on_change)
|
||||
on_change(value);
|
||||
update();
|
||||
}
|
||||
|
||||
Gfx::IntRect ScrollBar::decrement_button_rect() const
|
||||
{
|
||||
return { 0, 0, button_width(), button_height() };
|
||||
|
@ -191,19 +155,19 @@ int ScrollBar::scrubbable_range_in_pixels() const
|
|||
|
||||
bool ScrollBar::has_scrubber() const
|
||||
{
|
||||
return m_max != m_min;
|
||||
return max() != min();
|
||||
}
|
||||
|
||||
int ScrollBar::unclamped_scrubber_size() const
|
||||
{
|
||||
int pixel_range = length(orientation()) - button_size() * 2;
|
||||
int value_range = m_max - m_min;
|
||||
int value_range = max() - min();
|
||||
|
||||
int scrubber_size = 0;
|
||||
if (value_range > 0) {
|
||||
// Scrubber size should be proportional to the visible portion
|
||||
// (page) in relation to the content (value range + page)
|
||||
scrubber_size = (m_page * pixel_range) / (value_range + m_page);
|
||||
scrubber_size = (page_step() * pixel_range) / (value_range + page_step());
|
||||
}
|
||||
return scrubber_size;
|
||||
}
|
||||
|
@ -218,15 +182,15 @@ Gfx::IntRect ScrollBar::scrubber_rect() const
|
|||
if (!has_scrubber() || length(orientation()) <= (button_size() * 2) + visible_scrubber_size())
|
||||
return {};
|
||||
float x_or_y;
|
||||
if (m_value == m_min)
|
||||
if (value() == min())
|
||||
x_or_y = button_size();
|
||||
else if (m_value == m_max)
|
||||
else if (value() == max())
|
||||
x_or_y = (length(orientation()) - button_size() - visible_scrubber_size()) + 1;
|
||||
else {
|
||||
float range_size = m_max - m_min;
|
||||
float range_size = max() - min();
|
||||
float available = scrubbable_range_in_pixels();
|
||||
float step = available / range_size;
|
||||
x_or_y = (button_size() + (step * m_value));
|
||||
x_or_y = (button_size() + (step * value()));
|
||||
}
|
||||
|
||||
if (orientation() == Orientation::Vertical)
|
||||
|
@ -271,11 +235,11 @@ void ScrollBar::paint_event(PaintEvent& event)
|
|||
void ScrollBar::on_automatic_scrolling_timer_fired()
|
||||
{
|
||||
if (m_pressed_component == Component::DecrementButton && component_at_position(m_last_mouse_position) == Component::DecrementButton) {
|
||||
set_value(value() - m_step);
|
||||
set_value(value() - step());
|
||||
return;
|
||||
}
|
||||
if (m_pressed_component == Component::IncrementButton && component_at_position(m_last_mouse_position) == Component::IncrementButton) {
|
||||
set_value(value() + m_step);
|
||||
set_value(value() + step());
|
||||
return;
|
||||
}
|
||||
if (m_pressed_component == Component::Gutter && component_at_position(m_last_mouse_position) == Component::Gutter) {
|
||||
|
@ -336,7 +300,7 @@ void ScrollBar::mousewheel_event(MouseEvent& event)
|
|||
{
|
||||
if (!is_scrollable())
|
||||
return;
|
||||
set_value(value() + event.wheel_delta() * m_step);
|
||||
set_value(value() + event.wheel_delta() * step());
|
||||
Widget::mousewheel_event(event);
|
||||
}
|
||||
|
||||
|
@ -358,7 +322,7 @@ void ScrollBar::set_automatic_scrolling_active(bool active, Component pressed_co
|
|||
|
||||
void ScrollBar::scroll_by_page(const Gfx::IntPoint& click_position)
|
||||
{
|
||||
float range_size = m_max - m_min;
|
||||
float range_size = max() - min();
|
||||
float available = scrubbable_range_in_pixels();
|
||||
float rel_scrubber_size = unclamped_scrubber_size() / available;
|
||||
float page_increment = range_size * rel_scrubber_size;
|
||||
|
@ -371,12 +335,12 @@ void ScrollBar::scroll_by_page(const Gfx::IntPoint& click_position)
|
|||
|
||||
void ScrollBar::scroll_to_position(const Gfx::IntPoint& click_position)
|
||||
{
|
||||
float range_size = m_max - m_min;
|
||||
float range_size = max() - min();
|
||||
float available = scrubbable_range_in_pixels();
|
||||
|
||||
float x_or_y = ::max(0, click_position.primary_offset_for_orientation(orientation()) - button_width() - button_width() / 2);
|
||||
float rel_x_or_y = x_or_y / available;
|
||||
set_value(m_min + rel_x_or_y * range_size);
|
||||
set_value(min() + rel_x_or_y * range_size);
|
||||
}
|
||||
|
||||
ScrollBar::Component ScrollBar::component_at_position(const Gfx::IntPoint& position)
|
||||
|
@ -405,7 +369,7 @@ void ScrollBar::mousemove_event(MouseEvent& event)
|
|||
return;
|
||||
float delta = orientation() == Orientation::Vertical ? (event.y() - m_scrub_origin.y()) : (event.x() - m_scrub_origin.x());
|
||||
float scrubbable_range = scrubbable_range_in_pixels();
|
||||
float value_steps_per_scrubbed_pixel = (m_max - m_min) / scrubbable_range;
|
||||
float value_steps_per_scrubbed_pixel = (max() - min()) / scrubbable_range;
|
||||
float new_value = m_scrub_start_value + (value_steps_per_scrubbed_pixel * delta);
|
||||
set_value(new_value);
|
||||
}
|
||||
|
|
|
@ -27,38 +27,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
#include <LibGUI/AbstractSlider.h>
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class ScrollBar final : public Widget {
|
||||
C_OBJECT(ScrollBar)
|
||||
class ScrollBar final : public AbstractSlider {
|
||||
C_OBJECT(ScrollBar);
|
||||
|
||||
public:
|
||||
virtual ~ScrollBar() override;
|
||||
|
||||
Gfx::Orientation orientation() const { return m_orientation; }
|
||||
|
||||
bool is_scrollable() const { return max() != min(); }
|
||||
|
||||
int value() const { return m_value; }
|
||||
int min() const { return m_min; }
|
||||
int max() const { return m_max; }
|
||||
int page() const { return m_page; }
|
||||
int step() const { return m_step; }
|
||||
int big_step() const { return m_big_step; }
|
||||
|
||||
void set_min(int min) { set_range(min, max(), page()); }
|
||||
void set_max(int max) { set_range(min(), max, page()); }
|
||||
void set_page(int page) { set_range(min(), max(), page); }
|
||||
void set_range(int min, int max) { set_range(min, max, page()); }
|
||||
void set_range(int min, int max, int page);
|
||||
void set_value(int value);
|
||||
void set_step(int step) { m_step = step; }
|
||||
void set_big_step(int big_step) { m_big_step = big_step; }
|
||||
bool has_scrubber() const;
|
||||
|
||||
Function<void(int)> on_change;
|
||||
|
||||
enum Component {
|
||||
None,
|
||||
DecrementButton,
|
||||
|
@ -98,17 +80,9 @@ private:
|
|||
|
||||
Component component_at_position(const Gfx::IntPoint&);
|
||||
|
||||
int m_min { 0 };
|
||||
int m_max { 0 };
|
||||
int m_page { 0 };
|
||||
int m_value { 0 };
|
||||
int m_step { 1 };
|
||||
int m_big_step { 5 };
|
||||
|
||||
int m_scrub_start_value { 0 };
|
||||
Gfx::IntPoint m_scrub_origin;
|
||||
|
||||
Gfx::Orientation m_orientation { Gfx::Orientation::Vertical };
|
||||
Component m_hovered_component { Component::None };
|
||||
Component m_pressed_component { Component::None };
|
||||
Gfx::IntPoint m_last_mouse_position;
|
||||
|
|
|
@ -40,7 +40,7 @@ ScrollableWidget::ScrollableWidget()
|
|||
|
||||
m_horizontal_scrollbar = add<ScrollBar>(Orientation::Horizontal);
|
||||
m_horizontal_scrollbar->set_step(4);
|
||||
m_horizontal_scrollbar->set_big_step(30);
|
||||
m_horizontal_scrollbar->set_page_step(30);
|
||||
m_horizontal_scrollbar->on_change = [this](int) {
|
||||
did_scroll();
|
||||
update();
|
||||
|
@ -111,18 +111,20 @@ void ScrollableWidget::update_scrollbar_ranges()
|
|||
auto available_size = this->available_size();
|
||||
|
||||
int excess_height = max(0, m_content_size.height() - available_size.height());
|
||||
m_vertical_scrollbar->set_range(0, excess_height, available_size.height());
|
||||
m_vertical_scrollbar->set_range(0, excess_height);
|
||||
m_vertical_scrollbar->set_page_step(available_size.height());
|
||||
|
||||
if (should_hide_unnecessary_scrollbars())
|
||||
m_vertical_scrollbar->set_visible(excess_height > 0);
|
||||
|
||||
int excess_width = max(0, m_content_size.width() - available_size.width());
|
||||
m_horizontal_scrollbar->set_range(0, excess_width, available_size.width());
|
||||
m_horizontal_scrollbar->set_range(0, excess_width);
|
||||
m_horizontal_scrollbar->set_page_step(available_size.width());
|
||||
|
||||
if (should_hide_unnecessary_scrollbars())
|
||||
m_horizontal_scrollbar->set_visible(excess_width > 0);
|
||||
|
||||
m_vertical_scrollbar->set_big_step(visible_content_rect().height() - m_vertical_scrollbar->step());
|
||||
m_vertical_scrollbar->set_page_step(visible_content_rect().height() - m_vertical_scrollbar->step());
|
||||
}
|
||||
|
||||
void ScrollableWidget::set_content_size(const Gfx::IntSize& size)
|
||||
|
|
|
@ -459,7 +459,7 @@ void TerminalWidget::relayout(const Gfx::IntSize& size)
|
|||
size.height() - frame_thickness() * 2,
|
||||
};
|
||||
m_scrollbar->set_relative_rect(scrollbar_rect);
|
||||
m_scrollbar->set_page(new_rows);
|
||||
m_scrollbar->set_page_step(new_rows);
|
||||
}
|
||||
|
||||
Gfx::IntSize TerminalWidget::compute_base_size() const
|
||||
|
|
Loading…
Add table
Reference in a new issue