aboutsummaryrefslogtreecommitdiff
path: root/src/ui/render/FlexLayoutRenderObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/render/FlexLayoutRenderObject.cpp')
-rw-r--r--src/ui/render/FlexLayoutRenderObject.cpp180
1 files changed, 92 insertions, 88 deletions
diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp
index b609fd97..079bc5a9 100644
--- a/src/ui/render/FlexLayoutRenderObject.cpp
+++ b/src/ui/render/FlexLayoutRenderObject.cpp
@@ -6,111 +6,115 @@
#include <functional>
namespace cru::ui::render {
-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;
- 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
- no_basis_children.push_back(i);
- if (layout_data.flex_grow > 0) grow_children.push_back(i);
- if (layout_data.flex_shrink > 0) shrink_chilren.push_back(i);
- }
+Size FlexLayoutRenderObject::OnMeasureContent(
+ const MeasureRequirement& requirement) {
+ const bool horizontal = (direction_ == FlexDirection::Horizontal ||
+ direction_ == FlexDirection::HorizontalReverse);
+
+ const auto main_max_length =
+ horizontal ? requirement.max_width : requirement.max_height;
+ const auto cross_max_length =
+ horizontal ? requirement.max_height : requirement.max_width;
std::function<float(const Size&)> get_main_length;
std::function<float(const Size&)> get_cross_length;
- std::function<Size(float main, float cross)> create_size;
+ std::function<void(Size&, const Size&)> calculate_result_size;
+ std::function<MeasureRequirement(MeasureLength main, MeasureLength cross)>
+ create_requirement;
- if (direction_ == FlexDirection::Horizontal ||
- direction_ == FlexDirection::HorizontalReverse) {
+ if (horizontal) {
get_main_length = [](const Size& size) { return size.width; };
get_cross_length = [](const Size& size) { return size.height; };
- create_size = [](float main, float cross) { return Size(main, cross); };
+ calculate_result_size = [](Size& result, const Size& child_size) {
+ result.width += child_size.width;
+ result.height = std::max(result.height, child_size.height);
+ };
+ create_requirement = [](MeasureLength main, MeasureLength cross) {
+ return MeasureRequirement{main, cross};
+ };
} else {
get_main_length = [](const Size& size) { return size.height; };
get_cross_length = [](const Size& size) { return size.width; };
- create_size = [](float main, float cross) { return Size(cross, main); };
+ calculate_result_size = [](Size& result, const Size& child_size) {
+ result.height += child_size.height;
+ result.width = std::max(result.width, child_size.width);
+ };
+ create_requirement = [](MeasureLength main, MeasureLength cross) {
+ return MeasureRequirement{cross, main};
+ };
}
const auto& children = GetChildren();
+ Index children_count = children.size();
- float remain_main_length = get_main_length(available_size);
- float max_cross_length = 0;
-
- for (const int i : has_basis_children) {
- const auto child = children[i];
- 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 =
- get_cross_length(child->GetPreferredSize());
- child->SetPreferredSize(create_size(basis, child_preferred_cross_length));
- max_cross_length = std::max(max_cross_length, child_preferred_cross_length);
- }
-
- for (const int i : no_basis_children) {
- const auto child = children[i];
- child->Measure(create_size(remain_main_length > 0 ? remain_main_length : 0,
- get_cross_length(available_size)));
- remain_main_length -= get_main_length(child->GetPreferredSize());
- max_cross_length =
- std::max(max_cross_length, get_cross_length(child->GetPreferredSize()));
- }
-
- if (remain_main_length > 0) {
- float total_grow = 0;
- for (const int i : grow_children)
- total_grow += GetChildLayoutData(i)->flex_grow;
+ if (!main_max_length.IsInfinate()) {
+ float remain_main_length = main_max_length.GetLength();
- for (const int i : grow_children) {
- const float distributed_grow_length =
- remain_main_length * (GetChildLayoutData(i)->flex_grow / total_grow);
+ for (Index i = 0; i < children_count; i++) {
const auto child = children[i];
- const float new_main_length =
- get_main_length(child->GetPreferredSize()) + distributed_grow_length;
- child->Measure(
- create_size(new_main_length, get_cross_length(available_size)));
- const float new_child_preferred_cross_length =
- get_cross_length(child->GetPreferredSize());
- child->SetPreferredSize(
- create_size(new_main_length, new_child_preferred_cross_length));
- max_cross_length =
- std::max(max_cross_length, new_child_preferred_cross_length);
+ child->Measure(create_requirement(remain_main_length, cross_max_length));
+ const auto measure_result = child->GetMeasuredSize();
+ remain_main_length -= get_main_length(measure_result);
}
- }
- if (remain_main_length < 0) {
- float total_shrink = 0;
- for (const int i : shrink_chilren)
- total_shrink += GetChildLayoutData(i)->flex_shrink;
+ if (remain_main_length > 0) {
+ std::vector<Index> expand_children;
+ float total_expand_factor = 0;
+
+ for (Index i = 0; i < children_count; i++) {
+ const auto factor = GetChildLayoutData(i)->expand_factor;
+ if (factor > 0) {
+ expand_children.push_back(i);
+ total_expand_factor += factor;
+ }
+ }
- for (const int i : shrink_chilren) {
- const float distributed_shrink_length = // negative
- remain_main_length *
- (GetChildLayoutData(i)->flex_shrink / total_shrink);
+ for (const int i : expand_children) {
+ const float distributed_grow_length =
+ remain_main_length *
+ (GetChildLayoutData(i)->expand_factor / total_expand_factor);
+ const auto child = children[i];
+ const float new_main_length =
+ get_main_length(child->GetMeasuredSize()) +
+ distributed_grow_length;
+ child->Measure(create_requirement(new_main_length, cross_max_length));
+ }
+ } else if (remain_main_length < 0) {
+ std::vector<Index> shrink_children;
+ float total_shrink_factor = 0;
+
+ for (Index i = 0; i < children_count; i++) {
+ const auto factor = GetChildLayoutData(i)->shrink_factor;
+ if (factor > 0) {
+ shrink_children.push_back(i);
+ total_shrink_factor += factor;
+ }
+ }
+
+ for (const int i : shrink_children) {
+ const float distributed_shrink_length = // negative
+ remain_main_length *
+ (GetChildLayoutData(i)->shrink_factor / total_shrink_factor);
+ const auto child = children[i];
+ float new_main_length = get_main_length(child->GetMeasuredSize()) +
+ distributed_shrink_length;
+ new_main_length = new_main_length > 0 ? new_main_length : 0;
+ child->Measure(create_requirement(new_main_length, cross_max_length));
+ }
+ }
+ } else {
+ for (Index i = 0; i < children_count; i++) {
const auto child = children[i];
- float new_main_length = get_main_length(child->GetPreferredSize()) +
- distributed_shrink_length;
- new_main_length = new_main_length > 0 ? new_main_length : 0;
- child->Measure(
- create_size(new_main_length, get_cross_length(available_size)));
- const float new_child_preferred_cross_length =
- get_cross_length(child->GetPreferredSize());
- child->SetPreferredSize(
- create_size(new_main_length, new_child_preferred_cross_length));
- max_cross_length =
- std::max(max_cross_length, new_child_preferred_cross_length);
+ child->Measure(requirement);
}
}
- return create_size(get_main_length(available_size) -
- (remain_main_length > 0 ? remain_main_length : 0),
- max_cross_length);
+ Size result;
+ for (auto child : children) {
+ calculate_result_size(result, child->GetMeasuredSize());
+ }
+
+ return result;
}
void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
@@ -125,7 +129,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
case internal::align_end:
return start_point + total_length - content_length;
default:
- return 0;
+ return start_point;
}
};
@@ -134,7 +138,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
direction_ == FlexDirection::HorizontalReverse) {
float actual_content_width = 0;
for (const auto child : children) {
- actual_content_width += child->GetPreferredSize().width;
+ actual_content_width += child->GetMeasuredSize().width;
}
const float content_anchor_x =
@@ -144,7 +148,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
float anchor_x = 0;
for (int i = 0; i < static_cast<int>(children.size()); i++) {
const auto child = children[i];
- const auto size = child->GetPreferredSize();
+ const auto size = child->GetMeasuredSize();
float real_anchor_x = anchor_x + content_anchor_x;
if (direction_ == FlexDirection::Horizontal)
@@ -164,7 +168,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
} else {
float actual_content_height = 0;
for (const auto child : children) {
- actual_content_height = child->GetPreferredSize().height;
+ actual_content_height = child->GetMeasuredSize().height;
}
const float content_anchor_y =
@@ -174,7 +178,7 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) {
float anchor_y = 0;
for (int i = 0; i < static_cast<int>(children.size()); i++) {
const auto child = children[i];
- const auto size = child->GetPreferredSize();
+ const auto size = child->GetMeasuredSize();
float real_anchor_y = anchor_y + content_anchor_y;
if (direction_ == FlexDirection::Vertical) {