diff options
Diffstat (limited to 'src/ui/render/FlexLayoutRenderObject.cpp')
-rw-r--r-- | src/ui/render/FlexLayoutRenderObject.cpp | 180 |
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) { |