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
|
#include "cru/ui/render/render_object.hpp"
#include "cru/common/logger.hpp"
#include <algorithm>
#include <cassert>
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.
assert(position <= children_.size()); // Position index is out of bound.
children_.insert(children_.cbegin() + position, render_object);
render_object->SetParent(this);
OnAddChild(render_object, position);
}
void RenderObject::RemoveChild(const int position) {
assert(position >= 0); // Position index is less than 0.
assert(position < children_.size()); // Position index is out of bound.
const auto i = children_.cbegin() + position;
const auto removed_child = *i;
children_.erase(i);
removed_child->SetParent(nullptr);
OnRemoveChild(removed_child, position);
}
void RenderObject::Measure(const Size& available_size) {
OnMeasureCore(available_size);
}
void RenderObject::Layout(const Rect& rect) {
SetOffset(rect.GetLeftTop());
SetSize(rect.GetSize());
OnLayoutCore(Rect{Point{}, rect.GetSize()});
}
void RenderObject::OnParentChanged(RenderObject* old_parent,
RenderObject* new_parent) {}
void RenderObject::OnAddChild(RenderObject* new_child, int position) {
InvalidateLayout();
InvalidatePaint();
}
void RenderObject::OnRemoveChild(RenderObject* removed_child, int position) {
InvalidateLayout();
InvalidatePaint();
}
void RenderObject::OnSizeChanged(const Size& old_size, const Size& new_size) {}
void RenderObject::OnMeasureCore(const Size& available_size) {
Size margin_padding_size{
margin_.GetHorizontalTotal() + padding_.GetHorizontalTotal(),
margin_.GetVerticalTotal() + padding_.GetVerticalTotal()};
auto coerced_margin_padding_size = margin_padding_size;
if (coerced_margin_padding_size.width > available_size.width) {
log::Warn(
L"Measure: horizontal length of padding and margin is bigger than "
L"available length.");
coerced_margin_padding_size.width = available_size.width;
}
if (coerced_margin_padding_size.height > available_size.height) {
log::Warn(
L"Measure: vertical length of padding and margin is bigger than "
L"available length.");
coerced_margin_padding_size.height = available_size.height;
}
const auto coerced_content_available_size =
available_size - coerced_margin_padding_size;
const auto actual_content_size =
OnMeasureContent(coerced_content_available_size);
SetPreferredSize(coerced_margin_padding_size + actual_content_size);
}
void RenderObject::OnLayoutCore(const Rect& rect) {
Size margin_padding_size{
margin_.GetHorizontalTotal() + padding_.GetHorizontalTotal(),
margin_.GetVerticalTotal() + padding_.GetVerticalTotal()};
const auto content_available_size = rect.GetSize() - margin_padding_size;
auto coerced_content_available_size = content_available_size;
if (coerced_content_available_size.width < 0) {
log::Warn(
L"Layout: horizontal length of padding and margin is bigger than "
L"available length.");
coerced_content_available_size.width = 0;
}
if (coerced_content_available_size.height < 0) {
log::Warn(
L"Layout: vertical length of padding and margin is bigger than "
L"available length.");
coerced_content_available_size.height = 0;
}
OnLayoutContent(Rect{margin_.left + padding_.left, margin_.top + padding_.top,
coerced_content_available_size.width,
coerced_content_available_size.height});
}
Rect RenderObject::GetContentRect() const {
Rect rect{Point{}, GetSize()};
rect = rect.Shrink(GetMargin());
rect = rect.Shrink(GetPadding());
rect.width = std::max(rect.width, 0.0f);
rect.height = std::max(rect.height, 0.0f);
return rect;
}
void RenderObject::SetParent(RenderObject* new_parent) {
const auto old_parent = parent_;
parent_ = new_parent;
OnParentChanged(old_parent, new_parent);
}
} // namespace cru::ui::render
|