aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-07-25 23:57:16 +0800
committercrupest <crupest@outlook.com>2020-07-25 23:57:16 +0800
commit23bf673f9582d7bc99eb6440be1df0cf5c43b725 (patch)
treed4715f526d14d2f3367358e5ba7d987b92df7fd7
parent83736f1208a613d2457147c2df3f493228bab3cb (diff)
downloadcru-23bf673f9582d7bc99eb6440be1df0cf5c43b725.tar.gz
cru-23bf673f9582d7bc99eb6440be1df0cf5c43b725.tar.bz2
cru-23bf673f9582d7bc99eb6440be1df0cf5c43b725.zip
Implement ScrollRenderObject::ScrollToContain .
-rw-r--r--include/cru/platform/GraphBase.hpp6
-rw-r--r--include/cru/ui/render/ScrollRenderObject.hpp12
-rw-r--r--src/ui/render/ScrollRenderObject.cpp43
3 files changed, 57 insertions, 4 deletions
diff --git a/include/cru/platform/GraphBase.hpp b/include/cru/platform/GraphBase.hpp
index 28dab1e6..e476e3cd 100644
--- a/include/cru/platform/GraphBase.hpp
+++ b/include/cru/platform/GraphBase.hpp
@@ -161,6 +161,12 @@ struct Rect final {
constexpr Size GetSize() const { return Size(width, height); }
+ constexpr Rect Expand(const Thickness& thickness) const {
+ return Rect(left - thickness.left, top - thickness.top,
+ width + thickness.GetHorizontalTotal(),
+ height + thickness.GetVerticalTotal());
+ }
+
constexpr Rect Shrink(const Thickness& thickness) const {
return Rect(left + thickness.left, top + thickness.top,
width - thickness.GetHorizontalTotal(),
diff --git a/include/cru/ui/render/ScrollRenderObject.hpp b/include/cru/ui/render/ScrollRenderObject.hpp
index 45fa3993..9b0cbf9a 100644
--- a/include/cru/ui/render/ScrollRenderObject.hpp
+++ b/include/cru/ui/render/ScrollRenderObject.hpp
@@ -3,6 +3,8 @@
#include "cru/platform/graph/util/Painter.hpp"
+#include <optional>
+
namespace cru::ui::render {
// Measure logic:
// Measure child with unspecified min and max size.
@@ -26,9 +28,19 @@ class ScrollRenderObject : public RenderObject {
// Return the coerced scroll offset.
Point GetScrollOffset();
void SetScrollOffset(const Point& offset);
+ void SetScrollOffset(std::optional<float> x, std::optional<float> y);
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{});
protected:
diff --git a/src/ui/render/ScrollRenderObject.cpp b/src/ui/render/ScrollRenderObject.cpp
index 533a269a..08ce744b 100644
--- a/src/ui/render/ScrollRenderObject.cpp
+++ b/src/ui/render/ScrollRenderObject.cpp
@@ -67,12 +67,47 @@ void ScrollRenderObject::SetScrollOffset(const Point& offset) {
InvalidateLayout();
}
+void ScrollRenderObject::SetScrollOffset(std::optional<float> x,
+ std::optional<float> y) {
+ bool dirty = false;
+
+ if (x.has_value()) {
+ dirty = true;
+ scroll_offset_.x = *x;
+ }
+
+ if (y.has_value()) {
+ dirty = true;
+ scroll_offset_.y = *y;
+ }
+
+ if (dirty) InvalidateLayout();
+}
+
void ScrollRenderObject::ScrollToContain(const Rect& rect,
const Thickness& margin) {
- // TODO: Implement this.
- CRU_UNUSED(rect);
- CRU_UNUSED(margin);
- throw std::runtime_error("Not implemented.");
+ std::optional<float> new_scroll_x;
+ std::optional<float> new_scroll_y;
+
+ Rect real_rect = rect.Expand(margin);
+
+ Rect view_rect = GetViewRect();
+
+ // horizontal
+ if (real_rect.left < view_rect.left) {
+ new_scroll_x = real_rect.left;
+ } else if (real_rect.GetRight() > view_rect.GetRight()) {
+ new_scroll_x = real_rect.GetRight() - view_rect.width;
+ }
+
+ // vertical
+ if (real_rect.top < view_rect.top) {
+ new_scroll_y = real_rect.top;
+ } else if (real_rect.GetBottom() > view_rect.GetBottom()) {
+ new_scroll_y = real_rect.GetBottom() - view_rect.height;
+ }
+
+ SetScrollOffset(new_scroll_x, new_scroll_y);
}
Size ScrollRenderObject::OnMeasureContent(const MeasureRequirement& requirement,