diff options
author | crupest <crupest@outlook.com> | 2021-03-13 16:05:21 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-03-13 16:05:21 +0800 |
commit | 49dfb2bc9f965b398aa12e711148696d28443eaf (patch) | |
tree | 7fffb9ad42988709809929802c8d08425eec8a42 | |
parent | e19d42f2f89ad6670e6b9a226bcf7abc12003bb5 (diff) | |
download | cru-49dfb2bc9f965b398aa12e711148696d28443eaf.tar.gz cru-49dfb2bc9f965b398aa12e711148696d28443eaf.tar.bz2 cru-49dfb2bc9f965b398aa12e711148696d28443eaf.zip |
feat: Scrollbar auto collapse.
-rw-r--r-- | include/cru/platform/gui/UiApplication.hpp | 5 | ||||
-rw-r--r-- | include/cru/ui/render/ScrollBar.hpp | 7 | ||||
-rw-r--r-- | src/ui/render/ScrollBar.cpp | 33 |
3 files changed, 43 insertions, 2 deletions
diff --git a/include/cru/platform/gui/UiApplication.hpp b/include/cru/platform/gui/UiApplication.hpp index ba85020a..5a5b0b13 100644 --- a/include/cru/platform/gui/UiApplication.hpp +++ b/include/cru/platform/gui/UiApplication.hpp @@ -79,6 +79,9 @@ class TimerAutoCanceler { } TimerAutoCanceler& operator=(TimerAutoCanceler&& other) { + if (&other == this) { + return *this; + } Reset(other.id_); other.id_ = 0; return *this; @@ -101,6 +104,8 @@ class TimerAutoCanceler { id_ = id; } + explicit operator bool() const { return id_; } + private: long long id_; }; diff --git a/include/cru/ui/render/ScrollBar.hpp b/include/cru/ui/render/ScrollBar.hpp index fc2910c4..7cfd2576 100644 --- a/include/cru/ui/render/ScrollBar.hpp +++ b/include/cru/ui/render/ScrollBar.hpp @@ -94,6 +94,11 @@ class ScrollBar : public Object { void SetCursor(); void RestoreCursor(); + void BeginAutoCollapseTimer(); + void StopAutoCollapseTimer(); + + void OnMouseLeave(); + protected: gsl::not_null<ScrollRenderObject*> render_object_; @@ -118,6 +123,8 @@ class ScrollBar : public Object { Event<Scroll> scroll_attempt_event_; std::optional<std::shared_ptr<platform::gui::ICursor>> old_cursor_; + + platform::gui::TimerAutoCanceler auto_collapse_timer_canceler_; }; class HorizontalScrollBar : public ScrollBar { diff --git a/src/ui/render/ScrollBar.cpp b/src/ui/render/ScrollBar.cpp index ee4b9e0d..02e079e9 100644 --- a/src/ui/render/ScrollBar.cpp +++ b/src/ui/render/ScrollBar.cpp @@ -14,14 +14,17 @@ #include <algorithm> #include <cassert> +#include <chrono> #include <gsl/pointers> #include <optional> #include <stdexcept> namespace cru::ui::render { +using namespace std::chrono_literals; constexpr float kScrollBarCollapseThumbWidth = 2; constexpr float kScrollBarCollapsedTriggerExpandAreaWidth = 5; constexpr float kScrollBarExpandWidth = 10; +constexpr auto kScrollBarAutoCollapseDelay = 1500ms; constexpr std::array<ScrollBarAreaKind, 5> kScrollBarAreaKindList{ ScrollBarAreaKind::UpArrow, ScrollBarAreaKind::DownArrow, @@ -131,6 +134,13 @@ void ScrollBar::InstallHandlers(controls::Control* control) { if (event.GetButton() == mouse_buttons::left && move_thumb_start_) { move_thumb_start_ = std::nullopt; + + auto hit_test_result = + ExpandedHitTest(event.GetPoint(this->render_object_)); + if (!hit_test_result) { + OnMouseLeave(); + } + control->ReleaseMouse(); event.SetHandled(); return true; @@ -159,8 +169,9 @@ void ScrollBar::InstallHandlers(controls::Control* control) { ExpandedHitTest(event.GetPoint(this->render_object_)); if (hit_test_result) { SetCursor(); + StopAutoCollapseTimer(); } else { - RestoreCursor(); + OnMouseLeave(); } } else { auto trigger_expand_area = @@ -182,7 +193,9 @@ void ScrollBar::InstallHandlers(controls::Control* control) { event_guard_ += control->MouseLeaveEvent()->Bubble()->PrependShortCircuitHandler( [this](event::MouseEventArgs&) { - if (IsExpanded() && !move_thumb_start_) RestoreCursor(); + if (IsExpanded() && !move_thumb_start_) { + OnMouseLeave(); + } return false; }); } @@ -267,6 +280,22 @@ void ScrollBar::RestoreCursor() { } } +void ScrollBar::BeginAutoCollapseTimer() { + if (!auto_collapse_timer_canceler_ && IsExpanded()) { + auto_collapse_timer_canceler_ = GetUiApplication()->SetTimeout( + kScrollBarAutoCollapseDelay, [this] { this->SetExpanded(false); }); + } +} + +void ScrollBar::StopAutoCollapseTimer() { + auto_collapse_timer_canceler_.Reset(); +} + +void ScrollBar::OnMouseLeave() { + RestoreCursor(); + BeginAutoCollapseTimer(); +} + std::optional<ScrollBarAreaKind> ScrollBar::ExpandedHitTest( const Point& point) { for (auto kind : kScrollBarAreaKindList) { |