blob: 33ef3d1a30b3aedbdfa938d716a05f33d73c06b9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#pragma once
#include "base.hpp"
#include "cru/common/event.hpp"
namespace cru::ui::render {
struct AfterLayoutEventArgs {};
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;
virtual IEvent<AfterLayoutEventArgs>* AfterLayoutEvent() = 0;
};
// Render object will not destroy its children when destroyed. Control must
// manage lifecycle of its render objects. Since control will destroy its
// children when destroyed, render objects will be destroyed along with it.
class RenderObject : public Object {
protected:
enum class ChildMode {
None,
Single,
Multiple,
};
RenderObject() = default;
RenderObject(ChildMode child_mode) : RenderObject() {
SetChildMode(child_mode);
}
public:
RenderObject(const RenderObject& other) = delete;
RenderObject(RenderObject&& other) = delete;
RenderObject& operator=(const RenderObject& other) = delete;
RenderObject& operator=(RenderObject&& other) = delete;
~RenderObject() override = default;
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_; }
Index GetChildCount() const { return static_cast<Index>(children_.size()); }
void AddChild(RenderObject* render_object, Index position);
void RemoveChild(Index position);
Point GetOffset() const { return offset_; }
void SetOffset(const Point& offset) { offset_ = offset; }
Point GetTotalOffset() const;
Point FromRootToContent(const Point& point) const;
Size GetSize() const { return size_; }
void SetSize(const Size& size) { size_ = size; }
Thickness GetMargin() const { return margin_; }
void SetMargin(const Thickness& margin) { margin_ = margin; }
Thickness GetPadding() const { return padding_; }
void SetPadding(const Thickness& padding) { padding_ = padding; }
Size GetPreferredSize() const { return preferred_size_; }
void SetPreferredSize(const Size& preferred_size) {
preferred_size_ = preferred_size;
}
void Measure(const Size& available_size);
void Layout(const Rect& rect);
virtual void Draw(platform::graph::IPainter* painter) = 0;
virtual RenderObject* HitTest(const Point& point) = 0;
public:
void InvalidateLayout() const {
if (render_host_ != nullptr) render_host_->InvalidateLayout();
}
void InvalidatePaint() const {
if (render_host_ != nullptr) render_host_->InvalidatePaint();
}
protected:
void SetChildMode(ChildMode mode) { child_mode_ = mode; }
protected:
virtual void OnParentChanged(RenderObject* old_parent,
RenderObject* new_parent);
// default is to invalidate both layout and paint
virtual void OnAddChild(RenderObject* new_child, Index position);
// default is to invalidate both layout and paint
virtual void OnRemoveChild(RenderObject* removed_child, Index position);
virtual void OnMeasureCore(const Size& available_size);
virtual void OnLayoutCore(const Rect& rect);
virtual Size OnMeasureContent(const Size& available_size) = 0;
virtual void OnLayoutContent(const Rect& content_rect) = 0;
virtual void OnAfterLayout();
static void NotifyAfterLayoutRecursive(RenderObject* render_object);
Rect GetPaddingRect() const;
Rect GetContentRect() const;
private:
void SetParent(RenderObject* new_parent);
void SetRenderHostRecursive(IRenderHost* host);
private:
Control* control_ = nullptr;
IRenderHost* render_host_ = nullptr;
RenderObject* parent_ = nullptr;
std::vector<RenderObject*> children_{};
ChildMode child_mode_ = ChildMode::None;
Point offset_{};
Size size_{};
Thickness margin_{};
Thickness padding_{};
Size preferred_size_{};
};
} // namespace cru::ui::render
|