From 9ea2131adffe83559b160d9a17b1fbe2dffb25fe Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 10 Feb 2019 06:51:01 +0100 Subject: [PATCH] LibGUI: Support dragging the GScrollBar scrubber. This was pleasantly easy to implement with the global mouse tracking. :^) --- LibGUI/GScrollBar.cpp | 45 +++++++++++++++++++++++++++++++++++++------ LibGUI/GScrollBar.h | 12 +++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/LibGUI/GScrollBar.cpp b/LibGUI/GScrollBar.cpp index c2b585c140..bc5f77abde 100644 --- a/LibGUI/GScrollBar.cpp +++ b/LibGUI/GScrollBar.cpp @@ -55,23 +55,28 @@ Rect GScrollBar::down_button_rect() const return { 0, height() - button_size(), button_size(), button_size() }; } -Rect GScrollBar::pgup_rect() const +Rect GScrollBar::upper_gutter_rect() const { return { 0, button_size(), button_size(), scrubber_rect().top() - button_size() }; } -Rect GScrollBar::pgdn_rect() const +Rect GScrollBar::lower_gutter_rect() const { auto scrubber_rect = this->scrubber_rect(); return { 0, scrubber_rect.bottom(), button_size(), height() - button_size() - scrubber_rect.bottom() }; } +int GScrollBar::scrubbable_range_in_pixels() const +{ + return height() - button_size() * 3; +} + Rect GScrollBar::scrubber_rect() const { int range_size = m_max - m_min; if (range_size == 0) return { 0, button_size(), button_size(), height() - button_size() * 2 }; - float available_y = height() - button_size() * 3; + float available_y = scrubbable_range_in_pixels(); float y_step = available_y / range_size; float y = button_size() + (y_step * m_value); return { 0, (int)y, button_size(), button_size() }; @@ -115,7 +120,7 @@ void GScrollBar::paint_event(GPaintEvent&) Painter painter(*this); - painter.fill_rect(rect(), Color::MidGray); + painter.fill_rect(rect(), Color(164, 164, 164)); painter.draw_rect(up_button_rect(), Color::DarkGray, true); painter.fill_rect_with_gradient(up_button_rect().shrunken(2, 2), Color::LightGray, Color::White); @@ -141,12 +146,40 @@ void GScrollBar::mousedown_event(GMouseEvent& event) set_value(value() + m_step); return; } - if (pgup_rect().contains(event.position())) { + if (upper_gutter_rect().contains(event.position())) { set_value(value() - m_big_step); return; } - if (pgdn_rect().contains(event.position())) { + if (lower_gutter_rect().contains(event.position())) { set_value(value() + m_big_step); return; } + if (scrubber_rect().contains(event.position())) { + m_scrubbing = true; + m_scrub_start_value = value(); + m_scrub_origin = event.position(); + set_global_cursor_tracking(true); + return; + } +} + +void GScrollBar::mouseup_event(GMouseEvent& event) +{ + if (event.button() != GMouseButton::Left) + return; + if (!m_scrubbing) + return; + m_scrubbing = false; + set_global_cursor_tracking(false); +} + +void GScrollBar::mousemove_event(GMouseEvent& event) +{ + if (!m_scrubbing) + return; + float delta = event.y() - m_scrub_origin.y(); + float scrubbable_range = scrubbable_range_in_pixels(); + float value_steps_per_scrubbed_pixel = (m_max - m_min) / scrubbable_range; + float new_value = m_scrub_start_value + (value_steps_per_scrubbed_pixel * delta); + set_value(new_value); } diff --git a/LibGUI/GScrollBar.h b/LibGUI/GScrollBar.h index 48f1199bb1..4fd458afd3 100644 --- a/LibGUI/GScrollBar.h +++ b/LibGUI/GScrollBar.h @@ -24,19 +24,25 @@ public: private: virtual void paint_event(GPaintEvent&) override; virtual void mousedown_event(GMouseEvent&) override; + virtual void mouseup_event(GMouseEvent&) override; + virtual void mousemove_event(GMouseEvent&) override; virtual const char* class_name() const override { return "GScrollBar"; } int button_size() const { return 16; } Rect up_button_rect() const; Rect down_button_rect() const; - Rect pgup_rect() const; - Rect pgdn_rect() const; + Rect upper_gutter_rect() const; + Rect lower_gutter_rect() const; Rect scrubber_rect() const; + int scrubbable_range_in_pixels() const; int m_min { 0 }; int m_max { 0 }; int m_value { 0 }; int m_step { 1 }; int m_big_step { 5 }; -}; + bool m_scrubbing { false }; + int m_scrub_start_value { 0 }; + Point m_scrub_origin; +};