Przeglądaj źródła

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. :^)
Andreas Kling 6 lat temu
rodzic
commit
b425de18cc

+ 18 - 2
Libraries/LibGUI/GAbstractButton.cpp

@@ -2,7 +2,7 @@
 #include <LibGUI/GPainter.h>
 
 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();
         }
     }

+ 7 - 0
Libraries/LibGUI/GAbstractButton.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <LibCore/CTimer.h>
 #include <LibGUI/GWidget.h>
 #include <SharedGraphics/TextAlignment.h>
 
@@ -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<>

+ 4 - 0
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;
 };

+ 4 - 0
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<typename Callback>

+ 2 - 0
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()