diff options
author | crupest <crupest@outlook.com> | 2020-06-28 21:25:09 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-06-28 21:25:09 +0800 |
commit | b3c0c076e5a1b1e7d76fa8d32af0bcbb2c1cd4cf (patch) | |
tree | df90c6ae501508931fbd46ebc6340c90391e1ed5 /src | |
parent | 698242c10cbef4ceaade848fa6aedac71baaf1f2 (diff) | |
download | cru-b3c0c076e5a1b1e7d76fa8d32af0bcbb2c1cd4cf.tar.gz cru-b3c0c076e5a1b1e7d76fa8d32af0bcbb2c1cd4cf.tar.bz2 cru-b3c0c076e5a1b1e7d76fa8d32af0bcbb2c1cd4cf.zip |
...
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/ui/render/FlexLayoutRenderObject.cpp | 77 | ||||
-rw-r--r-- | src/ui/render/LayoutHelper.cpp | 36 | ||||
-rw-r--r-- | src/ui/render/StackLayoutRenderObject.cpp | 85 |
4 files changed, 117 insertions, 83 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 9043974e..954dacb0 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -23,6 +23,7 @@ add_library(cru_ui STATIC render/BorderRenderObject.cpp render/CanvasRenderObject.cpp render/FlexLayoutRenderObject.cpp + render/LayoutHelper.cpp render/RenderObject.cpp render/ScrollRenderObject.cpp render/StackLayoutRenderObject.cpp @@ -51,6 +52,7 @@ target_sources(cru_ui PUBLIC ${CRU_UI_INCLUDE_DIR}/render/BorderRenderObject.hpp ${CRU_UI_INCLUDE_DIR}/render/CanvasRenderObject.hpp ${CRU_UI_INCLUDE_DIR}/render/FlexLayoutRenderObject.hpp + ${CRU_UI_INCLUDE_DIR}/render/LayoutHelper.hpp ${CRU_UI_INCLUDE_DIR}/render/LayoutRenderObject.hpp ${CRU_UI_INCLUDE_DIR}/render/MeasureRequirement.hpp ${CRU_UI_INCLUDE_DIR}/render/RenderObject.hpp diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp index 0afe6ef5..9e5139ff 100644 --- a/src/ui/render/FlexLayoutRenderObject.cpp +++ b/src/ui/render/FlexLayoutRenderObject.cpp @@ -2,6 +2,7 @@ #include "cru/common/Logger.hpp" #include "cru/platform/graph/util/Painter.hpp" +#include "cru/ui/render/LayoutHelper.hpp" #include <algorithm> #include <functional> @@ -101,11 +102,25 @@ Size FlexLayoutMeasureContentImpl( MeasureLength min_main_length = GetMain(requirement.min, direction_tag); MeasureLength min_cross_length = GetCross(requirement.min, direction_tag); - // step 1. + std::vector<MeasureLength> child_cross_measure_requirement; + child_cross_measure_requirement.reserve(children.size()); + for (auto child : children) { + child_cross_measure_requirement.push_back( + StackLayoutCalculateChildMaxLength( + preferred_cross_length, max_cross_length, + GetCross(child->GetMinSize(), direction_tag), + "StackLayoutRenderObject: Child's min cross size is bigger than " + "parent's max cross size.")); + } + + // step 1. + for (Index i = 0; i < child_count; i++) { + const auto child = children[i]; child->Measure(MeasureRequirement{CreateTSize<MeasureSize>( MeasureLength::NotSpecified(), - max_cross_length, direction_tag), + child_cross_measure_requirement[i], + direction_tag), MeasureSize::NotSpecified()}, MeasureSize::NotSpecified()); } @@ -193,13 +208,15 @@ Size FlexLayoutMeasureContentImpl( new_measure_length = 0.f; } - child->Measure(MeasureRequirement{CreateTSize<MeasureSize>( - new_measure_length, - max_cross_length, direction_tag), - MeasureSize::NotSpecified()}, - CreateTSize<MeasureSize>(new_measure_length, - MeasureLength::NotSpecified(), - direction_tag)); + child->Measure( + MeasureRequirement{ + CreateTSize<MeasureSize>(new_measure_length, + child_cross_measure_requirement[i], + direction_tag), + MeasureSize::NotSpecified()}, + CreateTSize<MeasureSize>(new_measure_length, + MeasureLength::NotSpecified(), + direction_tag)); const Size new_size = child->GetSize(); const float new_main_length = GetMain(new_size, direction_tag); @@ -256,7 +273,8 @@ Size FlexLayoutMeasureContentImpl( child->Measure( MeasureRequirement{ CreateTSize<MeasureSize>(MeasureLength::NotSpecified(), - max_cross_length, direction_tag), + child_cross_measure_requirement[i], + direction_tag), CreateTSize<MeasureSize>(new_measure_length, MeasureLength::NotSpecified(), direction_tag)}, @@ -303,10 +321,10 @@ Size FlexLayoutMeasureContentImpl( total_length = min_main_length.GetLengthOrUndefined(); } - if (min_main_length.IsSpecified() && - child_max_cross_length < min_main_length.GetLengthOrUndefined()) { - child_max_cross_length = min_main_length.GetLengthOrUndefined(); - } + child_max_cross_length = + std::max(preferred_cross_length.GetLengthOr0(), child_max_cross_length); + child_max_cross_length = + std::max(min_cross_length.GetLengthOr0(), child_max_cross_length); return CreateTSize<Size>(total_length, child_max_cross_length, direction_tag); } @@ -326,21 +344,6 @@ Size FlexLayoutRenderObject::OnMeasureContent( } void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { - auto calculate_cross_anchor = [](FlexCrossAlignment alignment, - float start_point, float content_length, - float child_length) -> float { - switch (alignment) { - case FlexCrossAlignment::Start: - return start_point; - case FlexCrossAlignment::Center: - return start_point + (content_length - child_length) / 2.0f; - case FlexCrossAlignment::End: - return start_point + content_length - child_length; - default: - return start_point; - } - }; - const auto& children = GetChildren(); const Index child_count = children.size(); @@ -354,8 +357,8 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { GetItemCrossAlign()); child->Layout( Point{content_rect.left + current_main_offset, - calculate_cross_anchor(cross_align, content_rect.top, - content_rect.height, size.height)}); + CalculateAnchorByAlignment(cross_align, content_rect.top, + content_rect.height, size.height)}); current_main_offset += size.width; } @@ -369,8 +372,8 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { GetItemCrossAlign()); child->Layout( Point{content_rect.GetRight() - current_main_offset, - calculate_cross_anchor(cross_align, content_rect.top, - content_rect.height, size.height)}); + CalculateAnchorByAlignment(cross_align, content_rect.top, + content_rect.height, size.height)}); current_main_offset += size.width; } } else if (direction_ == FlexDirection::Vertical) { @@ -383,8 +386,8 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { GetItemCrossAlign()); child->Layout( Point{content_rect.top + current_main_offset, - calculate_cross_anchor(cross_align, content_rect.left, - content_rect.width, size.width)}); + CalculateAnchorByAlignment(cross_align, content_rect.left, + content_rect.width, size.width)}); current_main_offset += size.height; } } else { @@ -397,8 +400,8 @@ void FlexLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { GetItemCrossAlign()); child->Layout( Point{content_rect.GetBottom() - current_main_offset, - calculate_cross_anchor(cross_align, content_rect.left, - content_rect.width, size.width)}); + CalculateAnchorByAlignment(cross_align, content_rect.left, + content_rect.width, size.width)}); current_main_offset += size.height; } } diff --git a/src/ui/render/LayoutHelper.cpp b/src/ui/render/LayoutHelper.cpp new file mode 100644 index 00000000..31cf5c08 --- /dev/null +++ b/src/ui/render/LayoutHelper.cpp @@ -0,0 +1,36 @@ +#include "cru/ui/render/LayoutHelper.hpp" + +#include "cru/common/Logger.hpp" + +namespace cru::ui::render { +float CalculateAnchorByAlignment(Alignment alignment, float start_point, + float content_length, float child_length) { + switch (alignment) { + case FlexCrossAlignment::Start: + return start_point; + case FlexCrossAlignment::Center: + return start_point + (content_length - child_length) / 2.0f; + case FlexCrossAlignment::End: + return start_point + content_length - child_length; + default: + return start_point; + } +} + +MeasureLength StackLayoutCalculateChildMaxLength( + MeasureLength parent_preferred_size, MeasureLength parent_max_size, + MeasureLength child_min_size, std::string_view exceeds_message) { + if (parent_max_size.GetLengthOrMax() < child_min_size.GetLengthOr0()) { + log::Warn(exceeds_message); + return parent_max_size; + } + + if (parent_preferred_size.IsSpecified() && + parent_preferred_size.GetLengthOrUndefined() >= + child_min_size.GetLengthOr0()) { + return parent_preferred_size; + } else { + return parent_max_size; + } +} +} // namespace cru::ui::render diff --git a/src/ui/render/StackLayoutRenderObject.cpp b/src/ui/render/StackLayoutRenderObject.cpp index b953ae7e..a6ed7708 100644 --- a/src/ui/render/StackLayoutRenderObject.cpp +++ b/src/ui/render/StackLayoutRenderObject.cpp @@ -1,60 +1,53 @@ #include "cru/ui/render/StackLayoutRenderObject.hpp" +#include "cru/common/Logger.hpp" +#include "cru/ui/render/LayoutHelper.hpp" + #include <algorithm> namespace cru::ui::render { Size StackLayoutRenderObject::OnMeasureContent( const MeasureRequirement& requirement, const MeasureSize& preferred_size) { - // TODO: Rewrite this. - CRU_UNUSED(requirement); - CRU_UNUSED(preferred_size); - throw std::runtime_error("Not implemented."); + Size max_size; + for (const auto child : GetChildren()) { + child->Measure( + MeasureRequirement{ + MeasureSize{StackLayoutCalculateChildMaxLength( + preferred_size.width, requirement.max.width, + child->GetMinSize().width, + "StackLayoutRenderObject: Child's min width is " + "bigger than parent's max width."), + StackLayoutCalculateChildMaxLength( + preferred_size.height, requirement.max.height, + child->GetMinSize().height, + "StackLayoutRenderObject: Child's min height is " + "bigger than parent's max height.")}, + MeasureSize::NotSpecified()}, + MeasureSize::NotSpecified()); + const auto size = child->GetSize(); + max_size.width = std::max(max_size.width, size.width); + max_size.height = std::max(max_size.height, size.height); + } + + max_size = Max(preferred_size.GetSizeOr0(), max_size); + max_size = Max(requirement.min.GetSizeOr0(), max_size); - // throw std::runtime_error("Not implemented."); - // auto size = Size{}; - // for (const auto child : GetChildren()) { - // child->Measure(requirement); - // const auto& measure_result = child->GetMeasuredSize(); - // size.width = std::max(size.width, measure_result.width); - // size.height = std::max(size.height, measure_result.height); - // } - // return size; + return max_size; } void StackLayoutRenderObject::OnLayoutContent(const Rect& content_rect) { - // TODO: Rewrite this. - CRU_UNUSED(content_rect); - throw std::runtime_error("Not implemented."); - - // 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 start_point; - // } - // }; - - // const auto count = GetChildCount(); - // const auto& children = GetChildren(); + 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->GetMeasuredSize(); - // 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}); - // } + for (int i = 0; i < count; i++) { + const auto child = children[i]; + const auto& layout_data = GetChildLayoutData(i); + const auto& size = child->GetSize(); + child->Layout(Point{ + CalculateAnchorByAlignment(layout_data.horizontal, content_rect.left, + content_rect.width, size.width), + CalculateAnchorByAlignment(layout_data.vertical, content_rect.top, + content_rect.height, size.height)}); + } } } // namespace cru::ui::render |