aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-03-13 16:05:21 +0800
committercrupest <crupest@outlook.com>2021-03-13 16:05:21 +0800
commit49dfb2bc9f965b398aa12e711148696d28443eaf (patch)
tree7fffb9ad42988709809929802c8d08425eec8a42
parente19d42f2f89ad6670e6b9a226bcf7abc12003bb5 (diff)
downloadcru-49dfb2bc9f965b398aa12e711148696d28443eaf.tar.gz
cru-49dfb2bc9f965b398aa12e711148696d28443eaf.tar.bz2
cru-49dfb2bc9f965b398aa12e711148696d28443eaf.zip
feat: Scrollbar auto collapse.
-rw-r--r--include/cru/platform/gui/UiApplication.hpp5
-rw-r--r--include/cru/ui/render/ScrollBar.hpp7
-rw-r--r--src/ui/render/ScrollBar.cpp33
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) {