diff options
author | 杨宇千 <crupest@outlook.com> | 2019-09-16 21:45:01 +0800 |
---|---|---|
committer | 杨宇千 <crupest@outlook.com> | 2019-09-16 21:45:01 +0800 |
commit | f1da8e06253748887ae769845a6e605d56d5789b (patch) | |
tree | 3a2a92cc52f77b4b2e77b5a802ed477525253bc2 | |
parent | 574e69fb379cd54fc3034fe45a155e770435b97d (diff) | |
download | cru-f1da8e06253748887ae769845a6e605d56d5789b.tar.gz cru-f1da8e06253748887ae769845a6e605d56d5789b.tar.bz2 cru-f1da8e06253748887ae769845a6e605d56d5789b.zip |
...
-rw-r--r-- | include/cru/ui/render/border_render_object.hpp | 2 | ||||
-rw-r--r-- | include/cru/ui/render/flex_layout_render_object.hpp | 2 | ||||
-rw-r--r-- | include/cru/ui/render/render_object.hpp | 37 | ||||
-rw-r--r-- | include/cru/ui/render/window_render_object.hpp | 7 | ||||
-rw-r--r-- | src/ui/render/border_render_object.cpp | 9 | ||||
-rw-r--r-- | src/ui/render/flex_layout_render_object.cpp | 4 | ||||
-rw-r--r-- | src/ui/render/render_object.cpp | 13 | ||||
-rw-r--r-- | src/ui/render/text_render_object.cpp | 2 | ||||
-rw-r--r-- | src/ui/render/window_render_object.cpp | 35 |
9 files changed, 99 insertions, 12 deletions
diff --git a/include/cru/ui/render/border_render_object.hpp b/include/cru/ui/render/border_render_object.hpp index 5c147df5..22e8ab58 100644 --- a/include/cru/ui/render/border_render_object.hpp +++ b/include/cru/ui/render/border_render_object.hpp @@ -77,8 +77,6 @@ class BorderRenderObject : public RenderObject { RenderObject* HitTest(const Point& point) override; protected: - void OnAddChild(RenderObject* new_child, int position) override; - void OnSizeChanged(const Size& old_size, const Size& new_size) override; void OnMeasureCore(const Size& available_size) override; diff --git a/include/cru/ui/render/flex_layout_render_object.hpp b/include/cru/ui/render/flex_layout_render_object.hpp index 1234b920..68ffc89e 100644 --- a/include/cru/ui/render/flex_layout_render_object.hpp +++ b/include/cru/ui/render/flex_layout_render_object.hpp @@ -41,7 +41,7 @@ struct FlexChildLayoutData { class FlexLayoutRenderObject : public RenderObject { public: - FlexLayoutRenderObject() = default; + FlexLayoutRenderObject(); FlexLayoutRenderObject(const FlexLayoutRenderObject& other) = delete; FlexLayoutRenderObject& operator=(const FlexLayoutRenderObject& other) = delete; diff --git a/include/cru/ui/render/render_object.hpp b/include/cru/ui/render/render_object.hpp index dca254cc..8ea7ca79 100644 --- a/include/cru/ui/render/render_object.hpp +++ b/include/cru/ui/render/render_object.hpp @@ -15,6 +15,18 @@ class Painter; } namespace cru::ui::render { +struct IRenderHost : Interface { + // Mark the layout as invalid, and arrange a re-layout later. + // Note this method might be called more than one times in a message cycle. So + // implementation should merge multiple request into once. + virtual void InvalidateLayout() = 0; + + // Mark the paint as invalid, and arrange a re-paint later. + // Note this method might be called more than one times in a message cycle. So + // implementation should merge multiple request into once. + virtual void InvalidatePaint() = 0; +}; + class RenderObject : public Object { protected: RenderObject() = default; @@ -29,6 +41,9 @@ class RenderObject : public Object { Control* GetAttachedControl() const { return control_; } void SetAttachedControl(Control* new_control) { control_ = new_control; } + IRenderHost* GetRenderHost() const { return render_host_; } + void SetRenderHost(IRenderHost* render_host) { render_host_ = render_host; } + RenderObject* GetParent() const { return parent_; } const std::vector<RenderObject*>& GetChildren() const { return children_; } @@ -63,10 +78,29 @@ class RenderObject : public Object { virtual RenderObject* HitTest(const Point& point) = 0; protected: + enum class ChildMode { + None, + Single, + Multiple, + }; + + void SetChildMode(ChildMode mode) { child_mode_ = mode; } + + void InvalidateLayout() const { + if (render_host_ != nullptr) render_host_->InvalidateLayout(); + } + + void InvalidatePaint() const { + if (render_host_ != nullptr) render_host_->InvalidatePaint(); + } + + protected: virtual void OnParentChanged(RenderObject* old_parent, RenderObject* new_parent); + // default is to invalidate both layout and paint virtual void OnAddChild(RenderObject* new_child, int position); + // default is to invalidate both layout and paint virtual void OnRemoveChild(RenderObject* removed_child, int position); virtual void OnSizeChanged(const Size& old_size, const Size& new_size); @@ -83,10 +117,13 @@ class RenderObject : public Object { private: Control* control_ = nullptr; + IRenderHost* render_host_ = nullptr; RenderObject* parent_ = nullptr; std::vector<RenderObject*> children_{}; + ChildMode child_mode_ = ChildMode::None; + Point offset_{}; Size size_{}; diff --git a/include/cru/ui/render/window_render_object.hpp b/include/cru/ui/render/window_render_object.hpp index dfeae487..e73a6bfe 100644 --- a/include/cru/ui/render/window_render_object.hpp +++ b/include/cru/ui/render/window_render_object.hpp @@ -1,6 +1,8 @@ #pragma once #include "render_object.hpp" +#include <memory> + namespace cru::ui { class Window; } @@ -8,7 +10,7 @@ class Window; namespace cru::ui::render { class WindowRenderObject : public RenderObject { public: - WindowRenderObject(Window* window) : window_(window) {} + WindowRenderObject(Window* window); WindowRenderObject(const WindowRenderObject& other) = delete; WindowRenderObject(WindowRenderObject&& other) = delete; WindowRenderObject& operator=(const WindowRenderObject& other) = delete; @@ -23,6 +25,7 @@ class WindowRenderObject : public RenderObject { protected: void OnAddChild(RenderObject* new_child, int position) override; + void OnRemoveChild(RenderObject* new_child, int position) override; Size OnMeasureContent(const Size& available_size) override; void OnLayoutContent(const Rect& content_rect) override; @@ -34,5 +37,7 @@ class WindowRenderObject : public RenderObject { private: Window* window_; + + std::unique_ptr<IRenderHost> render_host_; }; } // namespace cru::ui::render diff --git a/src/ui/render/border_render_object.cpp b/src/ui/render/border_render_object.cpp index 68e74740..6af76b32 100644 --- a/src/ui/render/border_render_object.cpp +++ b/src/ui/render/border_render_object.cpp @@ -9,7 +9,10 @@ #include <cassert> namespace cru::ui::render { -BorderRenderObject::BorderRenderObject() { RecreateGeometry(); } +BorderRenderObject::BorderRenderObject() { + SetChildMode(ChildMode::Single); + RecreateGeometry(); +} BorderRenderObject::~BorderRenderObject() {} @@ -61,10 +64,6 @@ RenderObject* BorderRenderObject::HitTest(const Point& point) { } } -void BorderRenderObject::OnAddChild(RenderObject* new_child, int position) { - assert(GetChildren().size() == 1); -} - void BorderRenderObject::OnSizeChanged(const Size& old_size, const Size& new_size) { RecreateGeometry(); diff --git a/src/ui/render/flex_layout_render_object.cpp b/src/ui/render/flex_layout_render_object.cpp index c4bdd874..416f39bd 100644 --- a/src/ui/render/flex_layout_render_object.cpp +++ b/src/ui/render/flex_layout_render_object.cpp @@ -7,6 +7,10 @@ #include <functional> namespace cru::ui::render { +FlexLayoutRenderObject::FlexLayoutRenderObject() { + SetChildMode(ChildMode::Multiple); +} + FlexChildLayoutData* FlexLayoutRenderObject::GetChildLayoutData(int position) { assert(position >= 0 && position < child_layout_data_.size()); // Position out of bound. diff --git a/src/ui/render/render_object.cpp b/src/ui/render/render_object.cpp index a083403b..dcd2f0b9 100644 --- a/src/ui/render/render_object.cpp +++ b/src/ui/render/render_object.cpp @@ -7,6 +7,9 @@ namespace cru::ui::render { void RenderObject::AddChild(RenderObject* render_object, const int position) { + assert(child_mode_ == ChildMode::None); + assert(child_mode_ == ChildMode::Single && children_.size() > 0); + assert(render_object->GetParent() == nullptr); // Render object already has a parent. assert(position >= 0); // Position index is less than 0. @@ -41,9 +44,15 @@ void RenderObject::Layout(const Rect& rect) { void RenderObject::OnParentChanged(RenderObject* old_parent, RenderObject* new_parent) {} -void RenderObject::OnAddChild(RenderObject* new_child, int position) {} +void RenderObject::OnAddChild(RenderObject* new_child, int position) { + InvalidateLayout(); + InvalidatePaint(); +} -void RenderObject::OnRemoveChild(RenderObject* removed_child, int position) {} +void RenderObject::OnRemoveChild(RenderObject* removed_child, int position) { + InvalidateLayout(); + InvalidatePaint(); +} void RenderObject::OnSizeChanged(const Size& old_size, const Size& new_size) {} diff --git a/src/ui/render/text_render_object.cpp b/src/ui/render/text_render_object.cpp index 64a34b6c..49d7bcb4 100644 --- a/src/ui/render/text_render_object.cpp +++ b/src/ui/render/text_render_object.cpp @@ -16,6 +16,8 @@ TextRenderObject::TextRenderObject( assert(font); assert(selection_brush); + SetChildMode(ChildMode::None); + brush.swap(brush_); font.swap(font_); selection_brush.swap(selection_brush_); diff --git a/src/ui/render/window_render_object.cpp b/src/ui/render/window_render_object.cpp index 18faeee8..e61dd286 100644 --- a/src/ui/render/window_render_object.cpp +++ b/src/ui/render/window_render_object.cpp @@ -7,6 +7,26 @@ #include <cassert> namespace cru::ui::render { +class WindowRenderHost : public IRenderHost { + public: + WindowRenderHost(Window* window) : window_(window) { + assert(window != nullptr); + } + + void InvalidateLayout() override { window_->InvalidateLayout(); } + + void InvalidatePaint() override { window_->GetNativeWindow()->Repaint(); } + + private: + Window* window_; +}; + +WindowRenderObject::WindowRenderObject(Window* window) + : window_(window), render_host_(new WindowRenderHost(window)) { + SetChildMode(ChildMode::Single); + SetRenderHost(render_host_.get()); +} + void WindowRenderObject::MeasureAndLayout() { const auto client_size = window_->GetNativeWindow()->GetClientSize(); Measure(client_size); @@ -35,8 +55,21 @@ RenderObject* WindowRenderObject::HitTest(const Point& point) { return Rect{Point{}, GetSize()}.IsPointInside(point) ? this : nullptr; } +namespace { +void SetRenderHostRecursive(RenderObject* render_object, IRenderHost* host) { + render_object->SetRenderHost(host); + for (const auto child : render_object->GetChildren()) { + SetRenderHostRecursive(render_object, host); + } +} +} // namespace + void WindowRenderObject::OnAddChild(RenderObject* new_child, int position) { - assert(GetChildren().size() == 1); + SetRenderHostRecursive(new_child, render_host_.get()); +} + +void WindowRenderObject::OnRemoveChild(RenderObject* new_child, int position) { + SetRenderHostRecursive(new_child, nullptr); } Size WindowRenderObject::OnMeasureContent(const Size& available_size) { |