#pragma once #include "SingleChildRenderObject.h" #include "ScrollBar.h" #include "cru/common/Event.h" #include #include 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 SingleChildRenderObject { 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 x, std::optional y); void SetScrollOffset(Direction direction, std::optional 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{}); String 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(); void Draw(platform::graphics::IPainter* painter) override; protected: // 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* old_control, controls::Control* new_control) override; void InstallMouseWheelHandler(controls::Control* control); private: Point scroll_offset_; std::unique_ptr scroll_bar_delegate_; bool is_mouse_wheel_enabled_ = true; EventRevokerListGuard guard_; }; } // namespace cru::ui::render