aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/ui/base.hpp14
-rw-r--r--include/cru/ui/controls/flex_layout.hpp5
-rw-r--r--include/cru/ui/controls/stack_layout.hpp37
-rw-r--r--include/cru/ui/controls/text_box.hpp20
-rw-r--r--include/cru/ui/render/flex_layout_render_object.hpp25
-rw-r--r--include/cru/ui/render/layout_render_object.hpp91
-rw-r--r--include/cru/ui/render/render_object.hpp16
-rw-r--r--include/cru/ui/render/stack_layout_render_object.hpp22
-rw-r--r--src/main.cpp11
-rw-r--r--src/ui/CMakeLists.txt7
-rw-r--r--src/ui/controls/flex_layout.cpp6
-rw-r--r--src/ui/controls/stack_layout.cpp27
-rw-r--r--src/ui/controls/text_box.cpp1
-rw-r--r--src/ui/render/flex_layout_render_object.cpp66
-rw-r--r--src/ui/render/stack_layout_render_object.cpp49
15 files changed, 305 insertions, 92 deletions
diff --git a/include/cru/ui/base.hpp b/include/cru/ui/base.hpp
index 90a3f746..703d61fc 100644
--- a/include/cru/ui/base.hpp
+++ b/include/cru/ui/base.hpp
@@ -27,4 +27,18 @@ using cru::platform::colors::black;
using cru::platform::colors::skyblue;
using cru::platform::colors::white;
} // namespace colors
+
+namespace internal {
+constexpr int align_start = 0;
+constexpr int align_end = align_start + 1;
+constexpr int align_center = align_end + 1;
+constexpr int align_stretch = align_center + 1;
+} // namespace internal
+
+enum class Alignment {
+ Start = internal::align_start,
+ End = internal::align_end,
+ Center = internal::align_center,
+ Stretch = internal::align_stretch
+};
} // namespace cru::ui
diff --git a/include/cru/ui/controls/flex_layout.hpp b/include/cru/ui/controls/flex_layout.hpp
index ff8ec53b..7861534a 100644
--- a/include/cru/ui/controls/flex_layout.hpp
+++ b/include/cru/ui/controls/flex_layout.hpp
@@ -2,7 +2,6 @@
#include "../layout_control.hpp"
#include "../render/flex_layout_render_object.hpp"
-#include "../window.hpp"
#include <memory>
@@ -29,9 +28,7 @@ class FlexLayout : public LayoutControl {
FlexLayout& operator=(FlexLayout&& other) = delete;
~FlexLayout() override = default;
- std::string_view GetControlType() const final {
- return control_type;
- }
+ std::string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/stack_layout.hpp b/include/cru/ui/controls/stack_layout.hpp
new file mode 100644
index 00000000..298de089
--- /dev/null
+++ b/include/cru/ui/controls/stack_layout.hpp
@@ -0,0 +1,37 @@
+#pragma once
+#include "../layout_control.hpp"
+
+#include <memory>
+
+namespace cru::ui::render {
+class StackLayoutRenderObject;
+}
+
+namespace cru::ui::controls {
+class StackLayout : public LayoutControl {
+ public:
+ static constexpr std::string_view control_type = "StackLayout";
+
+ static StackLayout* Create() { return new StackLayout(); }
+
+ protected:
+ StackLayout();
+
+ public:
+ CRU_DELETE_COPY(StackLayout)
+ CRU_DELETE_MOVE(StackLayout)
+
+ ~StackLayout() override;
+
+ std::string_view GetControlType() const final { return control_type; }
+
+ render::RenderObject* GetRenderObject() const override;
+
+ protected:
+ void OnAddChild(Control* child, int position) override;
+ void OnRemoveChild(Control* child, int position) override;
+
+ private:
+ std::shared_ptr<render::StackLayoutRenderObject> render_object_;
+};
+} // namespace cru::ui::controls
diff --git a/include/cru/ui/controls/text_box.hpp b/include/cru/ui/controls/text_box.hpp
new file mode 100644
index 00000000..48168e9d
--- /dev/null
+++ b/include/cru/ui/controls/text_box.hpp
@@ -0,0 +1,20 @@
+#pragma once
+#include "../no_child_control.hpp"
+
+namespace cru::ui::controls {
+class TextBox : public NoChildControl {
+ public:
+ static constexpr std::string_view control_type = "TextBox";
+
+ protected:
+ TextBox();
+
+ public:
+ CRU_DELETE_COPY(TextBox)
+ CRU_DELETE_MOVE(TextBox)
+
+ ~TextBox() override;
+
+ std::string_view GetControlType() const final { return control_type; }
+};
+} // namespace cru::ui::controls
diff --git a/include/cru/ui/render/flex_layout_render_object.hpp b/include/cru/ui/render/flex_layout_render_object.hpp
index ab6265d6..c2bc5fd1 100644
--- a/include/cru/ui/render/flex_layout_render_object.hpp
+++ b/include/cru/ui/render/flex_layout_render_object.hpp
@@ -1,5 +1,5 @@
#pragma once
-#include "render_object.hpp"
+#include "layout_render_object.hpp"
#include <optional>
@@ -39,9 +39,9 @@ struct FlexChildLayoutData {
std::optional<FlexCrossAlignment> cross_alignment = std::nullopt;
};
-class FlexLayoutRenderObject : public RenderObject {
+class FlexLayoutRenderObject : public LayoutRenderObject<FlexChildLayoutData> {
public:
- FlexLayoutRenderObject();
+ FlexLayoutRenderObject() = default;
FlexLayoutRenderObject(const FlexLayoutRenderObject& other) = delete;
FlexLayoutRenderObject& operator=(const FlexLayoutRenderObject& other) =
delete;
@@ -67,25 +67,7 @@ class FlexLayoutRenderObject : public RenderObject {
InvalidateLayout();
}
- FlexChildLayoutData GetChildLayoutData(int position) {
- assert(position >= 0 && position < static_cast<int>(child_layout_data_.size()));
- return child_layout_data_[position];
- }
-
- void SetChildLayoutData(int position, const FlexChildLayoutData& data) {
- assert(position >= 0 && position < static_cast<int>(child_layout_data_.size()));
- child_layout_data_[position] = data;
- InvalidateLayout();
- }
-
- 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;
-
Size OnMeasureContent(const Size& available_size) override;
void OnLayoutContent(const Rect& content_rect) override;
@@ -93,6 +75,5 @@ class FlexLayoutRenderObject : public RenderObject {
FlexDirection direction_ = FlexDirection::Horizontal;
FlexMainAlignment content_main_align_ = FlexMainAlignment::Start;
FlexCrossAlignment item_cross_align_ = FlexCrossAlignment::Center;
- std::vector<FlexChildLayoutData> child_layout_data_{};
};
} // namespace cru::ui::render
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
diff --git a/include/cru/ui/render/render_object.hpp b/include/cru/ui/render/render_object.hpp
index 3e351d34..73543aa3 100644
--- a/include/cru/ui/render/render_object.hpp
+++ b/include/cru/ui/render/render_object.hpp
@@ -34,7 +34,16 @@ struct IRenderHost : Interface {
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;
@@ -52,6 +61,7 @@ class RenderObject : public Object {
RenderObject* GetParent() const { return parent_; }
const std::vector<RenderObject*>& GetChildren() const { return children_; }
+ int GetChildCount() const { return static_cast<int>(children_.size()); }
void AddChild(RenderObject* render_object, int position);
void RemoveChild(int position);
@@ -79,12 +89,6 @@ 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 {
diff --git a/include/cru/ui/render/stack_layout_render_object.hpp b/include/cru/ui/render/stack_layout_render_object.hpp
new file mode 100644
index 00000000..0d33e7e3
--- /dev/null
+++ b/include/cru/ui/render/stack_layout_render_object.hpp
@@ -0,0 +1,22 @@
+#pragma once
+#include "layout_render_object.hpp"
+
+namespace cru::ui::render {
+struct StackChildLayoutData {
+ Alignment horizontal = Alignment::Start;
+ Alignment vertical = Alignment::Start;
+};
+
+class StackLayoutRenderObject
+ : public LayoutRenderObject<StackChildLayoutData> {
+ public:
+ StackLayoutRenderObject() = default;
+ CRU_DELETE_COPY(StackLayoutRenderObject)
+ CRU_DELETE_MOVE(StackLayoutRenderObject)
+ ~StackLayoutRenderObject() = default;
+
+ protected:
+ Size OnMeasureContent(const Size& available_size) override;
+ void OnLayoutContent(const Rect& content_rect) override;
+};
+} // namespace cru::ui::render
diff --git a/src/main.cpp b/src/main.cpp
index ece75367..e2a766dc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,6 +2,7 @@
#include "cru/platform/native/window.hpp"
#include "cru/ui/controls/button.hpp"
#include "cru/ui/controls/flex_layout.hpp"
+#include "cru/ui/controls/stack_layout.hpp"
#include "cru/ui/controls/text_block.hpp"
#include "cru/ui/window.hpp"
#include "cru/win/native/ui_application.hpp"
@@ -12,6 +13,7 @@ using cru::ui::Thickness;
using cru::ui::Window;
using cru::ui::controls::Button;
using cru::ui::controls::FlexLayout;
+using cru::ui::controls::StackLayout;
using cru::ui::controls::TextBlock;
int main() {
@@ -36,7 +38,14 @@ int main() {
const auto text_block2 = TextBlock::Create();
text_block2->SetText("Hello World!");
- flex_layout->AddChild(text_block2, 1);
+
+ const auto text_block3 = TextBlock::Create();
+ text_block3->SetText("Overlapped text");
+
+ const auto stack_layout = StackLayout::Create();
+ stack_layout->AddChild(text_block2, 0);
+ stack_layout->AddChild(text_block3, 1);
+ flex_layout->AddChild(stack_layout, 1);
window->ResolveNativeWindow()->SetVisible(true);
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 111e3e33..64799b7a 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -15,10 +15,13 @@ add_library(cru_ui STATIC
controls/button.cpp
controls/container.cpp
controls/flex_layout.cpp
+ controls/stack_layout.cpp
controls/text_block.cpp
+ controls/text_box.cpp
render/border_render_object.cpp
render/flex_layout_render_object.cpp
render/render_object.cpp
+ render/stack_layout_render_object.cpp
render/text_render_object.cpp
render/window_render_object.cpp
)
@@ -35,10 +38,14 @@ target_sources(cru_ui PUBLIC
${CRU_UI_INCLUDE_DIR}/controls/button.hpp
${CRU_UI_INCLUDE_DIR}/controls/container.hpp
${CRU_UI_INCLUDE_DIR}/controls/flex_layout.hpp
+ ${CRU_UI_INCLUDE_DIR}/controls/stack_layout.hpp
+ ${CRU_UI_INCLUDE_DIR}/controls/text_box.hpp
${CRU_UI_INCLUDE_DIR}/controls/text_block.hpp
${CRU_UI_INCLUDE_DIR}/render/border_render_object.hpp
${CRU_UI_INCLUDE_DIR}/render/flex_layout_render_object.hpp
+ ${CRU_UI_INCLUDE_DIR}/render/layout_render_object.hpp
${CRU_UI_INCLUDE_DIR}/render/render_object.hpp
+ ${CRU_UI_INCLUDE_DIR}/render/stack_layout_render_object.hpp
${CRU_UI_INCLUDE_DIR}/render/text_render_object.hpp
${CRU_UI_INCLUDE_DIR}/render/window_render_object.hpp
)
diff --git a/src/ui/controls/flex_layout.cpp b/src/ui/controls/flex_layout.cpp
index 6491b180..6ea26d92 100644
--- a/src/ui/controls/flex_layout.cpp
+++ b/src/ui/controls/flex_layout.cpp
@@ -28,15 +28,15 @@ int FindPosition(render::RenderObject* parent, render::RenderObject* child) {
FlexChildLayoutData FlexLayout::GetChildLayoutData(Control* control) {
assert(control);
- return render_object_->GetChildLayoutData(
+ return *render_object_->GetChildLayoutData(
FindPosition(render_object_.get(), control->GetRenderObject()));
}
void FlexLayout::SetChildLayoutData(Control* control,
const FlexChildLayoutData& data) {
assert(control);
- render_object_->SetChildLayoutData(
- FindPosition(render_object_.get(), control->GetRenderObject()), data);
+ *render_object_->GetChildLayoutData(
+ FindPosition(render_object_.get(), control->GetRenderObject())) = data;
}
void FlexLayout::OnAddChild(Control* child, int position) {
diff --git a/src/ui/controls/stack_layout.cpp b/src/ui/controls/stack_layout.cpp
new file mode 100644
index 00000000..b9abb510
--- /dev/null
+++ b/src/ui/controls/stack_layout.cpp
@@ -0,0 +1,27 @@
+#include "cru/ui/controls/stack_layout.hpp"
+
+#include "cru/ui/render/stack_layout_render_object.hpp"
+
+namespace cru::ui::controls {
+using render::StackLayoutRenderObject;
+
+StackLayout::StackLayout() : render_object_(new StackLayoutRenderObject()) {
+ render_object_->SetAttachedControl(this);
+}
+
+StackLayout::~StackLayout() = default;
+
+render::RenderObject* StackLayout::GetRenderObject() const {
+ return render_object_.get();
+}
+
+void StackLayout::OnAddChild(Control* child, int position) {
+ render_object_->AddChild(child->GetRenderObject(), position);
+}
+
+void StackLayout::OnRemoveChild(Control* child, int position) {
+ CRU_UNUSED(child)
+
+ render_object_->RemoveChild(position);
+}
+} // namespace cru::ui::controls
diff --git a/src/ui/controls/text_box.cpp b/src/ui/controls/text_box.cpp
new file mode 100644
index 00000000..7fde06d9
--- /dev/null
+++ b/src/ui/controls/text_box.cpp
@@ -0,0 +1 @@
+#include "cru/ui/controls/text_box.hpp"
diff --git a/src/ui/render/flex_layout_render_object.cpp b/src/ui/render/flex_layout_render_object.cpp
index 1cac6899..791e705a 100644
--- a/src/ui/render/flex_layout_render_object.cpp
+++ b/src/ui/render/flex_layout_render_object.cpp
@@ -7,60 +7,14 @@
#include <functional>
namespace cru::ui::render {
-FlexLayoutRenderObject::FlexLayoutRenderObject() {
- SetChildMode(ChildMode::Multiple);
-}
-
-void FlexLayoutRenderObject::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); });
- }
-}
-
-RenderObject* FlexLayoutRenderObject::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
-
-void FlexLayoutRenderObject::OnAddChild(RenderObject* new_child, int position) {
- CRU_UNUSED(new_child)
-
- child_layout_data_.emplace(child_layout_data_.cbegin() + position);
-}
-
-void FlexLayoutRenderObject::OnRemoveChild(RenderObject* removed_child,
- int position) {
- CRU_UNUSED(removed_child)
-
- child_layout_data_.erase(child_layout_data_.cbegin() + position);
-}
-
Size FlexLayoutRenderObject::OnMeasureContent(const Size& available_size) {
std::vector<int> has_basis_children;
std::vector<int> no_basis_children;
std::vector<int> grow_children;
std::vector<int> shrink_chilren;
- for (int i = 0; i < static_cast<int>(child_layout_data_.size()); i++) {
- const auto& layout_data = child_layout_data_[i];
+ const auto child_count = GetChildCount();
+ for (int i = 0; i < child_count; i++) {
+ const auto& layout_data = *GetChildLayoutData(i);
if (layout_data.flex_basis.has_value())
has_basis_children.push_back(i);
else
@@ -91,7 +45,7 @@ Size FlexLayoutRenderObject::OnMeasureContent(const Size& available_size) {
for (const int i : has_basis_children) {
const auto child = children[i];
- const float basis = child_layout_data_[i].flex_basis.value();
+ const float basis = GetChildLayoutData(i)->flex_basis.value();
child->Measure(create_size(basis, get_cross_length(available_size)));
remain_main_length -= basis;
const float child_preferred_cross_length =
@@ -112,11 +66,11 @@ Size FlexLayoutRenderObject::OnMeasureContent(const Size& available_size) {
if (remain_main_length > 0) {
float total_grow = 0;
for (const int i : grow_children)
- total_grow += child_layout_data_[i].flex_grow;
+ total_grow += GetChildLayoutData(i)->flex_grow;
for (const int i : grow_children) {
const float distributed_grow_length =
- remain_main_length * (child_layout_data_[i].flex_grow / total_grow);
+ remain_main_length * (GetChildLayoutData(i)->flex_grow / total_grow);
const auto child = children[i];
const float new_main_length =
get_main_length(child->GetPreferredSize()) + distributed_grow_length;
@@ -134,12 +88,12 @@ Size FlexLayoutRenderObject::OnMeasureContent(const Size& available_size) {
if (remain_main_length < 0) {
float total_shrink = 0;
for (const int i : shrink_chilren)
- total_shrink += child_layout_data_[i].flex_shrink;
+ total_shrink += GetChildLayoutData(i)->flex_shrink;
for (const int i : shrink_chilren) {
const float distributed_shrink_length = // negative
remain_main_length *
- (child_layout_data_[i].flex_shrink / total_shrink);
+ (GetChildLayoutData(i)->flex_shrink / total_shrink);
const auto child = children[i];
float new_main_length = get_main_length(child->GetPreferredSize()) +
distributed_shrink_length;
@@ -201,7 +155,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
child->Layout(Rect{
real_anchor_x,
calculate_anchor(
- static_cast<int>(child_layout_data_[i].cross_alignment.value_or(
+ static_cast<int>(GetChildLayoutData(i)->cross_alignment.value_or(
this->item_cross_align_)),
content_rect.top, content_rect.height, size.height),
size.width, size.height});
@@ -232,7 +186,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
child->Layout(Rect{
real_anchor_y,
calculate_anchor(
- static_cast<int>(child_layout_data_[i].cross_alignment.value_or(
+ static_cast<int>(GetChildLayoutData(i)->cross_alignment.value_or(
this->item_cross_align_)),
content_rect.left, content_rect.width, size.width),
size.width, size.height});
diff --git a/src/ui/render/stack_layout_render_object.cpp b/src/ui/render/stack_layout_render_object.cpp
new file mode 100644
index 00000000..1cb31252
--- /dev/null
+++ b/src/ui/render/stack_layout_render_object.cpp
@@ -0,0 +1,49 @@
+#include "cru/ui/render/stack_layout_render_object.hpp"
+
+#include <algorithm>
+
+namespace cru::ui::render {
+Size StackLayoutRenderObject::OnMeasureContent(const Size& available_size) {
+ auto size = Size{};
+ for (const auto child : GetChildren()) {
+ child->Measure(available_size);
+ const auto& preferred_size = child->GetPreferredSize();
+ size.width = std::max(size.width, preferred_size.width);
+ size.height = std::max(size.height, preferred_size.height);
+ }
+ return size;
+}
+
+void StackLayoutRenderObject::OnLayoutContent(const Rect& rect) {
+ auto calculate_anchor = [](int alignment, float start_point,
+ float total_length,
+ float content_length) -> float {
+ switch (alignment) {
+ case internal::align_start:
+ return start_point;
+ case internal::align_center:
+ return start_point + (total_length - content_length) / 2.0f;
+ case internal::align_end:
+ return start_point + total_length - content_length;
+ default:
+ return 0;
+ }
+ };
+
+ const auto count = GetChildCount();
+ const auto& children = GetChildren();
+
+ for (int i = 0; i < count; i++) {
+ const auto layout_data = GetChildLayoutData(i);
+ const auto child = children[i];
+ const auto& size = child->GetPreferredSize();
+ child->Layout(
+ Rect{calculate_anchor(static_cast<int>(layout_data->horizontal),
+ rect.left, rect.width, size.width),
+ calculate_anchor(static_cast<int>(layout_data->vertical), rect.top,
+ rect.height, size.height),
+ size.width, size.height});
+ }
+}
+
+} // namespace cru::ui::render