From d333013a54a3c46a21698a6f0b7b30278380733b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 10 Feb 2019 12:26:58 +0100 Subject: [PATCH] LibGUI: Support horizontal GScrollBars as well. --- LibGUI/GScrollBar.cpp | 86 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/LibGUI/GScrollBar.cpp b/LibGUI/GScrollBar.cpp index d508805b832..6c5ea1d82f1 100644 --- a/LibGUI/GScrollBar.cpp +++ b/LibGUI/GScrollBar.cpp @@ -27,8 +27,35 @@ static const char* s_down_arrow_bitmap_data = { " " }; + +static const char* s_left_arrow_bitmap_data = { + " " + " # " + " ## " + " ###### " + " ####### " + " ###### " + " ## " + " # " + " " +}; + +static const char* s_right_arrow_bitmap_data = { + " " + " # " + " ## " + " ###### " + " ####### " + " ###### " + " ## " + " # " + " " +}; + static CharacterBitmap* s_up_arrow_bitmap; static CharacterBitmap* s_down_arrow_bitmap; +static CharacterBitmap* s_left_arrow_bitmap; +static CharacterBitmap* s_right_arrow_bitmap; GScrollBar::GScrollBar(Orientation orientation, GWidget* parent) : GWidget(parent) @@ -38,6 +65,10 @@ GScrollBar::GScrollBar(Orientation orientation, GWidget* parent) s_up_arrow_bitmap = CharacterBitmap::create_from_ascii(s_up_arrow_bitmap_data, 9, 9).leak_ref(); if (!s_down_arrow_bitmap) s_down_arrow_bitmap = CharacterBitmap::create_from_ascii(s_down_arrow_bitmap_data, 9, 9).leak_ref(); + if (!s_left_arrow_bitmap) + s_left_arrow_bitmap = CharacterBitmap::create_from_ascii(s_left_arrow_bitmap_data, 9, 9).leak_ref(); + if (!s_right_arrow_bitmap) + s_right_arrow_bitmap = CharacterBitmap::create_from_ascii(s_right_arrow_bitmap_data, 9, 9).leak_ref(); if (m_orientation == Orientation::Vertical) { set_preferred_size({ 15, 0 }); @@ -91,23 +122,35 @@ Rect GScrollBar::up_button_rect() const Rect GScrollBar::down_button_rect() const { - return { 0, height() - button_size(), button_size(), button_size() }; + if (orientation() == Orientation::Vertical) + return { 0, height() - button_size(), button_size(), button_size() }; + else + return { width() - button_size(), 0, button_size(), button_size() }; } Rect GScrollBar::upper_gutter_rect() const { - return { 0, button_size(), button_size(), scrubber_rect().top() - button_size() }; + if (orientation() == Orientation::Vertical) + return { 0, button_size(), button_size(), scrubber_rect().top() - button_size() }; + else + return { button_size(), 0, scrubber_rect().x() - button_size(), button_size() }; } 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() }; + if (orientation() == Orientation::Vertical) + return { 0, scrubber_rect.bottom() + 1, button_size(), height() - button_size() - scrubber_rect.bottom() - 1}; + else + return { scrubber_rect.right() + 1, 0, width() - button_size() - scrubber_rect.right() - 1, button_size() }; } int GScrollBar::scrubbable_range_in_pixels() const { - return height() - button_size() * 3; + if (orientation() == Orientation::Vertical) + return height() - button_size() * 3; + else + return width() - button_size() * 3; } bool GScrollBar::has_scrubber() const @@ -117,13 +160,24 @@ bool GScrollBar::has_scrubber() const 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 = 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() }; + if (!has_scrubber()) + return { }; + float x_or_y; + if (m_value == m_min) + x_or_y = button_size(); + else if (m_value == m_max) + x_or_y = (orientation() == Orientation::Vertical ? height() : width()) - (button_size() * 2); + else { + float range_size = m_max - m_min; + float available = scrubbable_range_in_pixels(); + float step = available / range_size; + x_or_y = (button_size() + (step * m_value)); + } + + if (orientation() == Orientation::Vertical) + return { 0, (int)x_or_y, button_size(), button_size() }; + else + return { (int)x_or_y, 0, button_size(), button_size() }; } void GScrollBar::paint_event(GPaintEvent&) @@ -133,10 +187,10 @@ void GScrollBar::paint_event(GPaintEvent&) painter.fill_rect(rect(), Color(164, 164, 164)); GStyle::the().paint_button(painter, up_button_rect(), false); - painter.draw_bitmap(up_button_rect().location().translated(3, 3), *s_up_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); + painter.draw_bitmap(up_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_up_arrow_bitmap : *s_left_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); GStyle::the().paint_button(painter, down_button_rect(), false); - painter.draw_bitmap(down_button_rect().location().translated(3, 3), *s_down_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); + painter.draw_bitmap(down_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_down_arrow_bitmap : *s_right_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); if (has_scrubber()) GStyle::the().paint_button(painter, scrubber_rect(), m_scrubbing); @@ -154,11 +208,11 @@ void GScrollBar::mousedown_event(GMouseEvent& event) set_value(value() + m_step); return; } - if (upper_gutter_rect().contains(event.position())) { + if (has_scrubber() && upper_gutter_rect().contains(event.position())) { set_value(value() - m_big_step); return; } - if (lower_gutter_rect().contains(event.position())) { + if (has_scrubber() && lower_gutter_rect().contains(event.position())) { set_value(value() + m_big_step); return; } @@ -187,7 +241,7 @@ void GScrollBar::mousemove_event(GMouseEvent& event) { if (!m_scrubbing) return; - float delta = event.y() - m_scrub_origin.y(); + 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 new_value = m_scrub_start_value + (value_steps_per_scrubbed_pixel * delta);