aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author杨宇千 <crupest@outlook.com>2019-09-16 21:45:01 +0800
committer杨宇千 <crupest@outlook.com>2019-09-16 21:45:01 +0800
commitf1da8e06253748887ae769845a6e605d56d5789b (patch)
tree3a2a92cc52f77b4b2e77b5a802ed477525253bc2
parent574e69fb379cd54fc3034fe45a155e770435b97d (diff)
downloadcru-f1da8e06253748887ae769845a6e605d56d5789b.tar.gz
cru-f1da8e06253748887ae769845a6e605d56d5789b.tar.bz2
cru-f1da8e06253748887ae769845a6e605d56d5789b.zip
...
-rw-r--r--include/cru/ui/render/border_render_object.hpp2
-rw-r--r--include/cru/ui/render/flex_layout_render_object.hpp2
-rw-r--r--include/cru/ui/render/render_object.hpp37
-rw-r--r--include/cru/ui/render/window_render_object.hpp7
-rw-r--r--src/ui/render/border_render_object.cpp9
-rw-r--r--src/ui/render/flex_layout_render_object.cpp4
-rw-r--r--src/ui/render/render_object.cpp13
-rw-r--r--src/ui/render/text_render_object.cpp2
-rw-r--r--src/ui/render/window_render_object.cpp35
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) {