From b425de18cc564b740ec0bef19b5a4df19bcdceb3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 13 Jul 2019 10:27:19 +0200 Subject: [PATCH] LibGUI: Add an auto-repeat interval to GAbstractButton. Use this in GSpinBox to implement auto-increment / auto-decrement while you are pressing down the respective buttons. :^) --- Libraries/LibGUI/GAbstractButton.cpp | 20 ++++++++++++++++++-- Libraries/LibGUI/GAbstractButton.h | 7 +++++++ Libraries/LibGUI/GCheckBox.h | 4 ++++ Libraries/LibGUI/GRadioButton.h | 4 ++++ Libraries/LibGUI/GSpinBox.cpp | 2 ++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Libraries/LibGUI/GAbstractButton.cpp b/Libraries/LibGUI/GAbstractButton.cpp index 61aaacfed3..22fc7e14c0 100644 --- a/Libraries/LibGUI/GAbstractButton.cpp +++ b/Libraries/LibGUI/GAbstractButton.cpp @@ -2,7 +2,7 @@ #include GAbstractButton::GAbstractButton(GWidget* parent) - : GWidget(parent) + : GAbstractButton({}, parent) { } @@ -10,6 +10,9 @@ GAbstractButton::GAbstractButton(const StringView& text, GWidget* parent) : GWidget(parent) , m_text(text) { + m_auto_repeat_timer.on_timeout = [this] { + click(); + }; } GAbstractButton::~GAbstractButton() @@ -65,6 +68,12 @@ void GAbstractButton::mousemove_event(GMouseEvent& event) bool being_pressed = is_over; if (being_pressed != m_being_pressed) { m_being_pressed = being_pressed; + if (m_auto_repeat_interval) { + if (!m_being_pressed) + m_auto_repeat_timer.stop(); + else + m_auto_repeat_timer.start(m_auto_repeat_interval); + } update(); } } @@ -81,6 +90,11 @@ void GAbstractButton::mousedown_event(GMouseEvent& event) if (is_enabled()) { m_being_pressed = true; update(); + + if (m_auto_repeat_interval) { + click(); + m_auto_repeat_timer.start(m_auto_repeat_interval); + } } } GWidget::mousedown_event(event); @@ -92,11 +106,13 @@ void GAbstractButton::mouseup_event(GMouseEvent& event) dbgprintf("GAbstractButton::mouse_up_event: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button()); #endif if (event.button() == GMouseButton::Left) { + bool was_auto_repeating = m_auto_repeat_timer.is_active(); + m_auto_repeat_timer.stop(); if (is_enabled()) { bool was_being_pressed = m_being_pressed; m_being_pressed = false; update(); - if (was_being_pressed) + if (was_being_pressed && !was_auto_repeating) click(); } } diff --git a/Libraries/LibGUI/GAbstractButton.h b/Libraries/LibGUI/GAbstractButton.h index 9618422682..386bfc4960 100644 --- a/Libraries/LibGUI/GAbstractButton.h +++ b/Libraries/LibGUI/GAbstractButton.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -32,6 +33,9 @@ public: virtual bool supports_keyboard_activation() const override { return true; } virtual bool is_uncheckable() const { return true; } + int auto_repeat_interval() const { return m_auto_repeat_interval; } + void set_auto_repeat_interval(int interval) { m_auto_repeat_interval = interval; } + protected: explicit GAbstractButton(GWidget* parent); GAbstractButton(const StringView&, GWidget* parent); @@ -55,6 +59,9 @@ private: bool m_hovered { false }; bool m_being_pressed { false }; bool m_exclusive { false }; + + int m_auto_repeat_interval { 0 }; + CTimer m_auto_repeat_timer; }; template<> diff --git a/Libraries/LibGUI/GCheckBox.h b/Libraries/LibGUI/GCheckBox.h index 8235b577ba..ec6864e4b1 100644 --- a/Libraries/LibGUI/GCheckBox.h +++ b/Libraries/LibGUI/GCheckBox.h @@ -15,5 +15,9 @@ public: virtual const char* class_name() const override { return "GCheckBox"; } private: + // These don't make sense for a check box, so hide them. + using GAbstractButton::auto_repeat_interval; + using GAbstractButton::set_auto_repeat_interval; + virtual void paint_event(GPaintEvent&) override; }; diff --git a/Libraries/LibGUI/GRadioButton.h b/Libraries/LibGUI/GRadioButton.h index 44c0cfe97b..5378e66047 100644 --- a/Libraries/LibGUI/GRadioButton.h +++ b/Libraries/LibGUI/GRadioButton.h @@ -15,6 +15,10 @@ protected: virtual void paint_event(GPaintEvent&) override; private: + // These don't make sense for a radio button, so hide them. + using GAbstractButton::auto_repeat_interval; + using GAbstractButton::set_auto_repeat_interval; + virtual bool is_radio_button() const final { return true; } template diff --git a/Libraries/LibGUI/GSpinBox.cpp b/Libraries/LibGUI/GSpinBox.cpp index d37ffafcf4..3fae9bf10c 100644 --- a/Libraries/LibGUI/GSpinBox.cpp +++ b/Libraries/LibGUI/GSpinBox.cpp @@ -19,10 +19,12 @@ GSpinBox::GSpinBox(GWidget* parent) m_increment_button->set_focusable(false); m_increment_button->set_text("\xf6"); m_increment_button->on_click = [this](GButton&) { set_value(m_value + 1); }; + m_increment_button->set_auto_repeat_interval(150); m_decrement_button = new GButton(this); m_decrement_button->set_focusable(false); m_decrement_button->set_text("\xf7"); m_decrement_button->on_click = [this](GButton&) { set_value(m_value - 1); }; + m_decrement_button->set_auto_repeat_interval(150); } GSpinBox::~GSpinBox()