aboutsummaryrefslogtreecommitdiff
path: root/include/cru/ui/render/ScrollRenderObject.h
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-02-08 16:53:51 +0800
committercrupest <crupest@outlook.com>2022-02-08 16:53:51 +0800
commit74bb9cd27242b9320f99ff4d2b50c3051576cc14 (patch)
tree744bac5799c593d1d6f81e7b09581bea626f2cde /include/cru/ui/render/ScrollRenderObject.h
parentb90c398de829d1ba5329651d75bae82f5e4085fe (diff)
downloadcru-74bb9cd27242b9320f99ff4d2b50c3051576cc14.tar.gz
cru-74bb9cd27242b9320f99ff4d2b50c3051576cc14.tar.bz2
cru-74bb9cd27242b9320f99ff4d2b50c3051576cc14.zip
...
Diffstat (limited to 'include/cru/ui/render/ScrollRenderObject.h')
-rw-r--r--include/cru/ui/render/ScrollRenderObject.h98
1 files changed, 98 insertions, 0 deletions
diff --git a/include/cru/ui/render/ScrollRenderObject.h b/include/cru/ui/render/ScrollRenderObject.h
new file mode 100644
index 00000000..bb282953
--- /dev/null
+++ b/include/cru/ui/render/ScrollRenderObject.h
@@ -0,0 +1,98 @@
+#pragma once
+#include "RenderObject.h"
+
+#include "cru/common/Event.h"
+#include "cru/platform/graphics/util/Painter.h"
+#include "cru/ui/Base.h"
+#include "cru/ui/render/ScrollBar.h"
+
+#include <memory>
+#include <optional>
+
+namespace cru::ui::render {
+// Measure logic:
+// Measure child with unspecified min and max size.
+// If parent's preferred size is specified, then it is used as measure result.
+// Or child's size is coerced into requirement and then used as result.
+// If no child, then use the preferred size if set or min size if set or 0.
+// Layout logic:
+// If child is smaller than content area, layout at lefttop.
+// Or layout by scroll state.
+class CRU_UI_API ScrollRenderObject : public RenderObject {
+ public:
+ ScrollRenderObject();
+
+ CRU_DELETE_COPY(ScrollRenderObject)
+ CRU_DELETE_MOVE(ScrollRenderObject)
+
+ ~ScrollRenderObject() override = default;
+
+ RenderObject* HitTest(const Point& point) override;
+
+ // Return the coerced scroll offset.
+ Point GetScrollOffset();
+ float GetScrollOffset(Direction direction) {
+ return direction == Direction::Horizontal ? GetScrollOffset().x
+ : GetScrollOffset().y;
+ }
+ void SetScrollOffset(const Point& offset);
+ void SetScrollOffset(std::optional<float> x, std::optional<float> y);
+ void SetScrollOffset(Direction direction, std::optional<float> value) {
+ if (direction == Direction::Horizontal) {
+ SetScrollOffset(value, std::nullopt);
+ } else {
+ SetScrollOffset(std::nullopt, value);
+ }
+ }
+
+ void ApplyScroll(const Scroll& scroll);
+
+ Point GetRawScrollOffset() const { return scroll_offset_; }
+
+ // Return the viewable area rect.
+ // Lefttop is scroll offset. Size is content size.
+ // If size exceeds view area, left and top is more important when calculate
+ // new scroll offset.
+ Rect GetViewRect() {
+ return Rect{GetScrollOffset(), GetContentRect().GetSize()};
+ }
+
+ // Rect lefttop relative to content rect.
+ // Param margin is just for convenience and it will just add to the rect.
+ void ScrollToContain(const Rect& rect, const Thickness& margin = Thickness{});
+
+ std::u16string_view GetName() const override { return u"ScrollRenderObject"; }
+
+ bool IsMouseWheelScrollEnabled() const { return is_mouse_wheel_enabled_; }
+ void SetMouseWheelScrollEnabled(bool enable);
+
+ bool HorizontalCanScrollUp();
+ bool HorizontalCanScrollDown();
+ bool VerticalCanScrollUp();
+ bool VerticalCanScrollDown();
+
+ protected:
+ void OnDrawCore(platform::graphics::IPainter* painter) override;
+
+ // Logic:
+ // If available size is bigger than child's preferred size, then child's
+ // preferred size is taken.
+ // If not, all available size is taken while forming a scroll area.
+ Size OnMeasureContent(const MeasureRequirement& requirement,
+ const MeasureSize& preferred_size) override;
+ void OnLayoutContent(const Rect& content_rect) override;
+
+ void OnAttachedControlChanged(controls::Control* control) override;
+
+ void InstallMouseWheelHandler(controls::Control* control);
+
+ private:
+ Point scroll_offset_;
+
+ std::unique_ptr<ScrollBarDelegate> scroll_bar_delegate_;
+
+ bool is_mouse_wheel_enabled_ = true;
+
+ EventRevokerListGuard guard_;
+};
+} // namespace cru::ui::render