Procházet zdrojové kódy

LibGUI: Standardize automatic scrolling in TextEditor+GlyphMapWidget

Both widgets now make use of their base class's scrolling timer and
now always accept drag selection updates on mousemove_event().

This guarantees much snappier feeling selections when actively moving
the mouse.
thankyouverycool před 2 roky
rodič
revize
804baa42f9

+ 32 - 14
Userland/Libraries/LibGUI/GlyphMapWidget.cpp

@@ -54,19 +54,6 @@ GlyphMapWidget::GlyphMapWidget()
     horizontal_scrollbar().set_visible(false);
     did_change_font();
     set_active_glyph('A');
-
-    m_automatic_selection_scroll_timer = add<Core::Timer>(20, [this] {
-        if (!m_in_drag_select) {
-            m_automatic_selection_scroll_timer->stop();
-            return;
-        }
-        auto glyph = glyph_at_position_clamped(m_last_mousemove_position);
-        m_selection.extend_to(glyph);
-        set_active_glyph(glyph, ShouldResetSelection::No);
-        scroll_to_glyph(glyph);
-        update();
-    });
-    m_automatic_selection_scroll_timer->stop();
 }
 
 void GlyphMapWidget::resize_event(ResizeEvent& event)
@@ -233,7 +220,6 @@ void GlyphMapWidget::mousedown_event(MouseEvent& event)
         if (event.shift())
             m_selection.extend_to(glyph);
         m_in_drag_select = true;
-        m_automatic_selection_scroll_timer->start();
         set_active_glyph(glyph, event.shift() ? ShouldResetSelection::No : ShouldResetSelection::Yes);
     }
 }
@@ -257,6 +243,27 @@ void GlyphMapWidget::mouseup_event(GUI::MouseEvent& event)
 void GlyphMapWidget::mousemove_event(GUI::MouseEvent& event)
 {
     m_last_mousemove_position = event.position();
+    if (m_in_drag_select) {
+        auto constrained = event.position().constrained(widget_inner_rect());
+        auto glyph = glyph_at_position_clamped(constrained);
+        m_selection.extend_to(glyph);
+        set_active_glyph(glyph, ShouldResetSelection::No);
+        scroll_to_glyph(glyph);
+        update();
+    }
+}
+
+void GlyphMapWidget::automatic_scrolling_timer_did_fire()
+{
+    if (!m_in_drag_select) {
+        set_automatic_scrolling_timer_active(false);
+        return;
+    }
+    auto glyph = glyph_at_position_clamped(m_last_mousemove_position);
+    m_selection.extend_to(glyph);
+    set_active_glyph(glyph, ShouldResetSelection::No);
+    scroll_to_glyph(glyph);
+    update();
 }
 
 void GlyphMapWidget::doubleclick_event(MouseEvent& event)
@@ -569,6 +576,17 @@ ErrorOr<void> GlyphMapWidget::set_font(Gfx::Font const& font)
     return {};
 }
 
+void GlyphMapWidget::enter_event(Core::Event&)
+{
+    set_automatic_scrolling_timer_active(false);
+}
+
+void GlyphMapWidget::leave_event(Core::Event&)
+{
+    if (m_in_drag_select)
+        set_automatic_scrolling_timer_active(true);
+}
+
 Optional<UISize> GlyphMapWidget::calculated_min_size() const
 {
     auto scrollbar = vertical_scrollbar().effective_min_size().height().as_int();

+ 3 - 2
Userland/Libraries/LibGUI/GlyphMapWidget.h

@@ -8,7 +8,6 @@
 
 #pragma once
 
-#include <LibCore/Timer.h>
 #include <LibGUI/AbstractScrollableWidget.h>
 #include <LibGUI/TextRange.h>
 #include <LibGfx/Font/BitmapFont.h>
@@ -92,6 +91,9 @@ private:
     virtual void resize_event(ResizeEvent&) override;
     virtual void did_change_font() override;
     virtual void context_menu_event(ContextMenuEvent&) override;
+    virtual void enter_event(Core::Event&) override;
+    virtual void leave_event(Core::Event&) override;
+    virtual void automatic_scrolling_timer_did_fire() override;
     virtual Optional<UISize> calculated_min_size() const override;
 
     Gfx::IntRect get_outer_rect(int glyph) const;
@@ -115,7 +117,6 @@ private:
     bool m_show_system_emoji { false };
     HashTable<u32> m_modified_glyphs;
     Unicode::CodePointRange m_active_range { 0x0000, 0x10FFFF };
-    RefPtr<Core::Timer> m_automatic_selection_scroll_timer;
     Gfx::IntPoint m_last_mousemove_position;
 };
 

+ 7 - 10
Userland/Libraries/LibGUI/TextEditor.cpp

@@ -69,10 +69,6 @@ TextEditor::TextEditor(Type type)
     }
     vertical_scrollbar().set_step(line_height());
     m_cursor = { 0, 0 };
-    m_automatic_selection_scroll_timer = add<Core::Timer>(100, [this] {
-        automatic_selection_scroll_timer_fired();
-    });
-    m_automatic_selection_scroll_timer->stop();
     create_actions();
     set_editing_engine(make<RegularEditingEngine>());
 }
@@ -309,8 +305,9 @@ void TextEditor::mouseup_event(MouseEvent& event)
 void TextEditor::mousemove_event(MouseEvent& event)
 {
     m_last_mousemove_position = event.position();
-    if (m_in_drag_select && (rect().contains(event.position()) || !m_automatic_selection_scroll_timer->is_active())) {
-        set_cursor(text_position_at(event.position()));
+    if (m_in_drag_select) {
+        auto constrained = event.position().constrained(widget_inner_rect());
+        set_cursor(text_position_at(constrained));
         m_selection.set_end(m_cursor);
         did_update_selection();
         update();
@@ -332,10 +329,10 @@ void TextEditor::select_current_line()
     did_update_selection();
 }
 
-void TextEditor::automatic_selection_scroll_timer_fired()
+void TextEditor::automatic_scrolling_timer_did_fire()
 {
     if (!m_in_drag_select) {
-        m_automatic_selection_scroll_timer->stop();
+        set_automatic_scrolling_timer_active(false);
         return;
     }
     set_cursor(text_position_at(m_last_mousemove_position));
@@ -1736,13 +1733,13 @@ void TextEditor::hide_autocomplete()
 
 void TextEditor::enter_event(Core::Event&)
 {
-    m_automatic_selection_scroll_timer->stop();
+    set_automatic_scrolling_timer_active(false);
 }
 
 void TextEditor::leave_event(Core::Event&)
 {
     if (m_in_drag_select)
-        m_automatic_selection_scroll_timer->start();
+        set_automatic_scrolling_timer_active(true);
 }
 
 void TextEditor::did_change(AllowCallback allow_callback)

+ 3 - 4
Userland/Libraries/LibGUI/TextEditor.h

@@ -300,6 +300,9 @@ private:
     // ^Clipboard::ClipboardClient
     virtual void clipboard_content_did_change(DeprecatedString const& mime_type) override;
 
+    // ^GUI::AbstractScrollableWidget
+    virtual void automatic_scrolling_timer_did_fire() override;
+
     void create_actions();
     void paint_ruler(Painter&);
     void update_content_size();
@@ -354,8 +357,6 @@ private:
     size_t visual_line_containing(size_t line_index, size_t column) const;
     void recompute_visual_lines(size_t line_index);
 
-    void automatic_selection_scroll_timer_fired();
-
     template<class T, class... Args>
     inline void execute(Args&&... args)
     {
@@ -430,8 +431,6 @@ private:
     OwnPtr<AutocompleteBox> m_autocomplete_box;
     bool m_should_keep_autocomplete_box { false };
     size_t m_automatic_autocomplete_delay_ms { 800 };
-
-    RefPtr<Core::Timer> m_automatic_selection_scroll_timer;
     RefPtr<Core::Timer> m_autocomplete_timer;
 
     OwnPtr<EditingEngine> m_editing_engine;