1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_UTILS_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_UTILS_H 18 19 #include <optional> 20 21 #include "base/geometry/axis.h" 22 #include "base/memory/referenced.h" 23 #include "base/utils/utils.h" 24 #include "core/components/common/layout/constants.h" 25 #include "core/components_ng/pattern/swiper/swiper_layout_property.h" 26 #include "core/components_ng/pattern/swiper/swiper_paint_property.h" 27 #include "core/components_ng/property/measure_utils.h" 28 29 namespace OHOS::Ace::NG { 30 31 class SwiperUtils { 32 public: 33 SwiperUtils() = delete; 34 ~SwiperUtils() = delete; 35 IsStretch(const RefPtr<SwiperLayoutProperty> & property)36 static bool IsStretch(const RefPtr<SwiperLayoutProperty>& property) 37 { 38 // If display count is setted, use stretch mode. 39 CHECK_NULL_RETURN(property, true); 40 if (property->HasDisplayCount() && !property->HasMinSize()) { 41 return true; 42 } 43 44 return property->GetDisplayMode().value_or(SwiperDisplayMode::STRETCH) == SwiperDisplayMode::STRETCH; 45 } 46 GetItemSpace(const RefPtr<SwiperLayoutProperty> & property)47 static float GetItemSpace(const RefPtr<SwiperLayoutProperty>& property) 48 { 49 auto scale = property->GetLayoutConstraint()->scaleProperty; 50 return ConvertToPx(property->GetItemSpace().value_or(0.0_px), scale).value_or(0); 51 } 52 CreateChildConstraint(const RefPtr<SwiperLayoutProperty> & property,const OptionalSizeF & idealSize,bool getAutoFill)53 static LayoutConstraintF CreateChildConstraint( 54 const RefPtr<SwiperLayoutProperty>& property, const OptionalSizeF& idealSize, bool getAutoFill) 55 { 56 auto layoutConstraint = property->CreateChildConstraint(); 57 layoutConstraint.parentIdealSize = idealSize; 58 auto displayCount = property->GetDisplayCount().value_or(1); 59 if ((!getAutoFill && !IsStretch(property)) || NonPositive(static_cast<double>(displayCount))) { 60 return layoutConstraint; 61 } 62 auto axis = property->GetDirection().value_or(Axis::HORIZONTAL); 63 auto itemSpace = GetItemSpace(property); 64 auto parentMainSize = idealSize.MainSize(axis); 65 if (parentMainSize.has_value() && itemSpace > parentMainSize.value()) { 66 itemSpace = 0.0f; 67 } 68 auto prevMargin = property->GetPrevMarginValue(0.0_px).ConvertToPx(); 69 auto nextMargin = property->GetNextMarginValue(0.0_px).ConvertToPx(); 70 auto itemSpaceCount = CaculateDisplayItemSpaceCount(property, prevMargin, nextMargin); 71 auto childSelfIdealSize = idealSize; 72 float childCalcIdealLength = 0.0f; 73 74 if ((axis == Axis::HORIZONTAL && idealSize.Width().has_value()) || 75 (axis == Axis::VERTICAL && idealSize.Height().has_value())) { 76 auto length = axis == Axis::HORIZONTAL ? idealSize.Width().value() : 77 idealSize.Height().value(); 78 childCalcIdealLength = (length - itemSpace * itemSpaceCount - 79 static_cast<float>(prevMargin + nextMargin)) / displayCount; 80 if (LessNotEqual(childCalcIdealLength, 0.0)) { 81 itemSpace = 0.0f; 82 childCalcIdealLength = (length - itemSpace * itemSpaceCount - 83 static_cast<float>(prevMargin + nextMargin)) / displayCount; 84 property->UpdateItemSpace(Dimension(0.0)); 85 } 86 if (CheckMarginPropertyExceed(property, childCalcIdealLength)) { 87 prevMargin = 0.0; 88 nextMargin = 0.0; 89 itemSpaceCount = CaculateDisplayItemSpaceCount(property, prevMargin, nextMargin); 90 childCalcIdealLength = (length - itemSpace * itemSpaceCount) / displayCount; 91 } 92 axis == Axis::HORIZONTAL ? childSelfIdealSize.SetWidth(childCalcIdealLength) : 93 childSelfIdealSize.SetHeight(childCalcIdealLength); 94 } 95 96 layoutConstraint.selfIdealSize = childSelfIdealSize; 97 return layoutConstraint; 98 } 99 CaculateDisplayItemSpaceCount(const RefPtr<SwiperLayoutProperty> & property,double prevMargin,double nextMargin)100 static int32_t CaculateDisplayItemSpaceCount( 101 const RefPtr<SwiperLayoutProperty>& property, double prevMargin, double nextMargin) 102 { 103 CHECK_NULL_RETURN(property, 0); 104 auto count = property->GetDisplayCountValue(1); 105 count = (Positive(static_cast<double>(count)) ? count : 1); 106 if (Positive(prevMargin) && Positive(nextMargin)) { 107 return count + 1; 108 } else if (NonPositive(prevMargin) && NonPositive(nextMargin)) { 109 return count - 1; 110 } else { 111 return count; 112 } 113 } 114 115 private: CheckMarginPropertyExceed(const RefPtr<SwiperLayoutProperty> & property,float childCalcIdealLength)116 static bool CheckMarginPropertyExceed( 117 const RefPtr<SwiperLayoutProperty>& property, float childCalcIdealLength) 118 { 119 CHECK_NULL_RETURN(property, false); 120 auto prevMargin = property->GetPrevMarginValue(0.0_px).ConvertToPx(); 121 auto nextMargin = property->GetNextMarginValue(0.0_px).ConvertToPx(); 122 if (GreatNotEqual(prevMargin, childCalcIdealLength) || 123 GreatNotEqual(nextMargin, childCalcIdealLength)) { 124 property->UpdatePrevMarginWithoutMeasure(0.0_px); 125 property->UpdateNextMarginWithoutMeasure(0.0_px); 126 return true; 127 } 128 return false; 129 } 130 }; 131 } // namespace OHOS::Ace::NG 132 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_SWIPER_UTILS_H 133