diff options
author | crupest <crupest@outlook.com> | 2020-03-01 22:08:15 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-03-01 22:08:15 +0800 |
commit | 6e0e0e18cbeff6487160c84d71997575f6cccebd (patch) | |
tree | 9b4c552234dfc4f9b5129dd96b25dba3518e4581 /include/cru/ui/render/layout_render_object.hpp | |
parent | 8fc4e33b97372d93b1bcc4b598e5c8e2f15652d8 (diff) | |
download | cru-6e0e0e18cbeff6487160c84d71997575f6cccebd.tar.gz cru-6e0e0e18cbeff6487160c84d71997575f6cccebd.tar.bz2 cru-6e0e0e18cbeff6487160c84d71997575f6cccebd.zip |
Add stack layout.
Diffstat (limited to 'include/cru/ui/render/layout_render_object.hpp')
-rw-r--r-- | include/cru/ui/render/layout_render_object.hpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/include/cru/ui/render/layout_render_object.hpp b/include/cru/ui/render/layout_render_object.hpp new file mode 100644 index 00000000..db6daba9 --- /dev/null +++ b/include/cru/ui/render/layout_render_object.hpp @@ -0,0 +1,91 @@ +#pragma once +#include "render_object.hpp" + +#include "cru/platform/graph/util/painter.hpp" + +#include <cassert> +#include <functional> + +namespace cru::ui::render { +template <typename TChildLayoutData> +class LayoutRenderObject : public RenderObject { + public: + using ChildLayoutData = TChildLayoutData; + + protected: + LayoutRenderObject() : RenderObject(ChildMode::Multiple) {} + + public: + CRU_DELETE_COPY(LayoutRenderObject) + CRU_DELETE_MOVE(LayoutRenderObject) + + ~LayoutRenderObject() override = default; + + ChildLayoutData* GetChildLayoutData(int position) { + assert(position >= 0 && + position < static_cast<int>(child_layout_data_.size())); + return &child_layout_data_[position]; + } + + void Draw(platform::graph::IPainter* painter) override; + + RenderObject* HitTest(const Point& point) override; + + protected: + void OnAddChild(RenderObject* new_child, int position) override; + void OnRemoveChild(RenderObject* removed_child, int position) override; + + private: + std::vector<ChildLayoutData> child_layout_data_{}; +}; + +template <typename TChildLayoutData> +void LayoutRenderObject<TChildLayoutData>::Draw( + platform::graph::IPainter* painter) { + for (const auto child : GetChildren()) { + auto offset = child->GetOffset(); + platform::graph::util::WithTransform( + painter, platform::Matrix::Translation(offset.x, offset.y), + [child](auto p) { child->Draw(p); }); + } +} + +template <typename TChildLayoutData> +RenderObject* LayoutRenderObject<TChildLayoutData>::HitTest( + const Point& point) { + const auto& children = GetChildren(); + for (auto i = children.crbegin(); i != children.crend(); ++i) { + auto offset = (*i)->GetOffset(); + Point p{point.x - offset.x, point.y - offset.y}; + const auto result = (*i)->HitTest(p); + if (result != nullptr) { + return result; + } + } + + const auto margin = GetMargin(); + const auto size = GetSize(); + return Rect{margin.left, margin.top, + std::max(size.width - margin.GetHorizontalTotal(), 0.0f), + std::max(size.height - margin.GetVerticalTotal(), 0.0f)} + .IsPointInside(point) + ? this + : nullptr; +} // namespace cru::ui::render + +template <typename TChildLayoutData> +void LayoutRenderObject<TChildLayoutData>::OnAddChild(RenderObject* new_child, + int position) { + CRU_UNUSED(new_child) + + child_layout_data_.emplace(child_layout_data_.cbegin() + position); +} + +template <typename TChildLayoutData> +void LayoutRenderObject<TChildLayoutData>::OnRemoveChild( + RenderObject* removed_child, int position) { + CRU_UNUSED(removed_child) + + child_layout_data_.erase(child_layout_data_.cbegin() + position); +} +} // namespace cru::ui::render |