1 /* 2 * Copyright (c) 2022-2023 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_PATTERN_LIST_LIST_ITEM_GROUP_LAYOUT_ALGORITHM_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_LIST_LIST_ITEM_GROUP_LAYOUT_ALGORITHM_H 18 19 #include <optional> 20 #include "base/geometry/axis.h" 21 #include "core/components_ng/layout/layout_algorithm.h" 22 #include "core/components_ng/layout/layout_wrapper.h" 23 #include "core/components_ng/pattern/list/list_layout_property.h" 24 #include "core/components_v2/list/list_properties.h" 25 26 namespace OHOS::Ace::NG { 27 class ListPositionMap; 28 class ListChildrenMainSize; 29 struct ListItemGroupLayoutInfo; 30 struct LayoutedItemInfo { 31 int32_t startIndex = 0; 32 float startPos = 0.0f; 33 int32_t endIndex = 0; 34 float endPos = 0.0f; 35 }; 36 37 struct ListItemGroupInfo { 38 int32_t id = -1; 39 float startPos = 0.0f; 40 float endPos = 0.0f; 41 bool isPressed = false; 42 }; 43 44 struct ListItemGroupCacheParam { 45 bool forward = true; 46 int32_t cacheCount = 0; 47 int32_t forwardCachedIndex = -1; 48 int32_t backwardCachedIndex = INT_MAX; 49 int64_t deadline = 0; 50 }; 51 52 // TextLayoutAlgorithm acts as the underlying text layout. 53 class ACE_EXPORT ListItemGroupLayoutAlgorithm : public LayoutAlgorithm { 54 DECLARE_ACE_TYPE(ListItemGroupLayoutAlgorithm, LayoutAlgorithm); 55 public: 56 using PositionMap = std::map<int32_t, ListItemGroupInfo>; 57 58 static const int32_t LAST_ITEM = -1; 59 ListItemGroupLayoutAlgorithm(int32_t headerIndex,int32_t footerIndex,int32_t itemStartIndex)60 ListItemGroupLayoutAlgorithm(int32_t headerIndex, int32_t footerIndex, int32_t itemStartIndex) 61 :headerIndex_(headerIndex), footerIndex_(footerIndex), itemStartIndex_(itemStartIndex) {} 62 63 void Measure(LayoutWrapper* layoutWrapper) override; 64 65 void Layout(LayoutWrapper* layoutWrapper) override; 66 GetItemPosition()67 const PositionMap& GetItemPosition() const 68 { 69 return itemPosition_; 70 } 71 SetItemsPosition(const PositionMap & itemPosition)72 void SetItemsPosition(const PositionMap& itemPosition) 73 { 74 itemPosition_ = itemPosition; 75 } 76 77 void ClearItemPosition(); 78 GetSpaceWidth()79 float GetSpaceWidth() const 80 { 81 return spaceWidth_; 82 } 83 GetAxis()84 Axis GetAxis() const 85 { 86 return axis_; 87 } 88 GetLayoutDirection()89 TextDirection GetLayoutDirection() const 90 { 91 return layoutDirection_; 92 } 93 GetMainSize()94 float GetMainSize() const 95 { 96 return totalMainSize_; 97 } 98 GetLanes()99 int32_t GetLanes() const 100 { 101 return lanes_; 102 } 103 GetLaneGutter()104 float GetLaneGutter() const 105 { 106 return laneGutter_; 107 } 108 GetLanesFloor(int32_t index)109 int32_t GetLanesFloor(int32_t index) const 110 { 111 if (lanes_ <= 1) { 112 return index; 113 } 114 return index - index % lanes_; 115 } 116 GetLanesCeil(int32_t index)117 int32_t GetLanesCeil(int32_t index) const 118 { 119 int32_t tmpIndex = (lanes_ <= 1) ? index : (index - index % lanes_ + lanes_ - 1); 120 tmpIndex = tmpIndex >= totalItemCount_ ? totalItemCount_ - 1 : tmpIndex; 121 return tmpIndex; 122 } 123 SetListMainSize(float startPos,float endPos,float referencePos,float prevContentSize,bool forwardLayout)124 void SetListMainSize(float startPos, float endPos, float referencePos, float prevContentSize, bool forwardLayout) 125 { 126 startPos_ = startPos; 127 endPos_ = endPos; 128 referencePos_ = referencePos; 129 forwardLayout_ = forwardLayout; 130 refPos_ = referencePos; 131 prevContentMainSize_ = prevContentSize; 132 } 133 134 void ModifyReferencePos(int32_t index, float pos); 135 SetNeedAdjustRefPos(bool needAdjust)136 void SetNeedAdjustRefPos(bool needAdjust) 137 { 138 needAdjustRefPos_ = needAdjust; 139 } 140 SetNeedCheckOffset(bool needCheckOffset)141 void SetNeedCheckOffset(bool needCheckOffset) 142 { 143 isNeedCheckOffset_ = needCheckOffset; 144 } 145 GetRefPos()146 float GetRefPos() const 147 { 148 return refPos_; 149 } 150 SetContentOffset(float contentStartOffset,float contentEndOffset)151 void SetContentOffset(float contentStartOffset, float contentEndOffset) 152 { 153 contentStartOffset_ = contentStartOffset; 154 contentEndOffset_ = contentEndOffset; 155 } 156 SetListLayoutProperty(RefPtr<ListLayoutProperty> layoutProperty)157 void SetListLayoutProperty(RefPtr<ListLayoutProperty> layoutProperty) 158 { 159 listLayoutProperty_ = std::move(layoutProperty); 160 } 161 SetJumpIndex(int32_t index)162 void SetJumpIndex(int32_t index) 163 { 164 jumpIndex_ = index; 165 } 166 SetTargetIndex(int32_t index)167 void SetTargetIndex(int32_t index) 168 { 169 targetIndex_ = index; 170 } 171 GetStartIndex()172 int32_t GetStartIndex() const 173 { 174 return itemPosition_.empty() ? 0 : itemPosition_.begin()->first; 175 } 176 GetEndIndex()177 int32_t GetEndIndex() const 178 { 179 return itemPosition_.empty() ? 0 : itemPosition_.rbegin()->first; 180 } 181 GetStartPosition()182 float GetStartPosition() const 183 { 184 if (itemPosition_.empty()) { 185 return 0.0f; 186 } 187 if (GetStartIndex() == 0) { 188 return itemPosition_.begin()->second.startPos; 189 } 190 return itemPosition_.begin()->second.startPos - spaceWidth_; 191 } 192 GetEndPosition()193 float GetEndPosition() const 194 { 195 if (itemPosition_.empty()) { 196 return 0.0f; 197 } 198 if (GetEndIndex() == totalItemCount_ - 1) { 199 return itemPosition_.rbegin()->second.endPos; 200 } 201 return itemPosition_.rbegin()->second.endPos + spaceWidth_; 202 } 203 GetTotalItemCount()204 int32_t GetTotalItemCount() const 205 { 206 return totalItemCount_; 207 } 208 209 float GetChildMaxCrossSize(LayoutWrapper* layoutWrapper, Axis axis); 210 211 void CheckRecycle(const RefPtr<LayoutWrapper>& layoutWrapper, float startPos, float endPos, float referencePos, 212 bool forwardLayout); 213 SetNeedAllLayout()214 void SetNeedAllLayout() 215 { 216 needAllLayout_ = true; 217 } 218 219 void CheckNeedAllLayout(const RefPtr<LayoutWrapper>& layoutWrapper, bool forwardLayout); 220 SetScrollAlign(ScrollAlign align)221 void SetScrollAlign(ScrollAlign align) 222 { 223 scrollAlign_ = align; 224 } 225 226 std::pair<float, float> GetItemGroupPosition(int32_t index); 227 GetHeaderMainSize()228 float GetHeaderMainSize() const 229 { 230 return headerMainSize_; 231 } 232 GetFooterMainSize()233 float GetFooterMainSize() const 234 { 235 return footerMainSize_; 236 } 237 238 float GetItemHeight(int32_t index); 239 GetItemStartIndex()240 int32_t GetItemStartIndex() 241 { 242 return itemStartIndex_; 243 } 244 SetLayoutedItemInfo(const std::optional<LayoutedItemInfo> & itemInfo)245 void SetLayoutedItemInfo(const std::optional<LayoutedItemInfo>& itemInfo) 246 { 247 layoutedItemInfo_ = itemInfo; 248 } 249 GetLayoutedItemInfo()250 std::optional<LayoutedItemInfo> GetLayoutedItemInfo() const 251 { 252 return layoutedItemInfo_; 253 } 254 SetListChildrenMainSize(const RefPtr<ListChildrenMainSize> & childrenMainSize)255 void SetListChildrenMainSize(const RefPtr<ListChildrenMainSize>& childrenMainSize) 256 { 257 childrenSize_ = childrenMainSize; 258 } 259 SetListPositionMap(const RefPtr<ListPositionMap> & posMap)260 void SetListPositionMap(const RefPtr<ListPositionMap>& posMap) 261 { 262 posMap_ = posMap; 263 } 264 265 void AdjustByPosMap(); 266 267 static void SyncGeometry(RefPtr<LayoutWrapper>& wrapper); 268 GetStartHeaderPos()269 float GetStartHeaderPos() const 270 { 271 return startHeaderPos_; 272 } 273 GetEndFooterPos()274 float GetEndFooterPos() const 275 { 276 return endFooterPos_; 277 } 278 SetCacheParam(std::optional<ListItemGroupCacheParam> param)279 void SetCacheParam(std::optional<ListItemGroupCacheParam> param) 280 { 281 cacheParam_ = param; 282 } 283 GetCacheParam()284 std::optional<ListItemGroupCacheParam> GetCacheParam() const 285 { 286 return cacheParam_; 287 } 288 SetNeedMeasureFormLastItem(bool needMeasureFormLastItem)289 void SetNeedMeasureFormLastItem(bool needMeasureFormLastItem) 290 { 291 isNeedMeasureFormLastItem_ = needMeasureFormLastItem; 292 } 293 294 ListItemGroupLayoutInfo GetLayoutInfo() const; 295 GetAdjustReferenceDelta()296 float GetAdjustReferenceDelta() const 297 { 298 return adjustReferenceDelta_; 299 } 300 GetListItemCount()301 int32_t GetListItemCount() const 302 { 303 return static_cast<int32_t>(itemPosition_.size()); 304 } 305 306 private: 307 float CalculateLaneCrossOffset(float crossSize, float childCrossSize); 308 void UpdateListItemConstraint(const OptionalSizeF& selfIdealSize, LayoutConstraintF& contentConstraint); 309 void LayoutListItem(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize); 310 void LayoutListItemAll(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, float startPos); 311 void LayoutHeaderFooterRTL(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize); 312 void LayoutHeaderFooterLTR(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize); 313 void UpdateZIndex(const RefPtr<LayoutWrapper>& layoutWrapper); 314 void LayoutIndex(const RefPtr<LayoutWrapper>& wrapper, const OffsetF& paddingOffset, 315 float crossSize, float startPos); GetListItem(LayoutWrapper * layoutWrapper,int32_t index)316 inline RefPtr<LayoutWrapper> GetListItem(LayoutWrapper* layoutWrapper, int32_t index) const 317 { 318 return layoutWrapper->GetOrCreateChildByIndex(index + itemStartIndex_); 319 } 320 void CalculateLanes(const RefPtr<ListLayoutProperty>& layoutProperty, 321 const LayoutConstraintF& layoutConstraint, std::optional<float> crossSizeOptional, Axis axis); 322 323 void MeasureListItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint); 324 int32_t MeasureALineForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 325 int32_t& currentIndex, float startPos, float& endPos); 326 int32_t MeasureALineBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 327 int32_t& currentIndex, float endPos, float& startPos); 328 int32_t MeasureALineCenter(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 329 int32_t currentIndex); 330 int32_t MeasureALineAuto(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 331 int32_t currentIndex); 332 void CheckJumpForwardForBigOffset(int32_t& startIndex, float& startPos); 333 void CheckJumpBackwardForBigOffset(int32_t& endIndex, float& endPos); 334 void MeasureForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 335 int32_t startIndex, float startPos); 336 void MeasureBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 337 int32_t endIndex, float endPos); 338 void MeasureJumpToItemForward(LayoutWrapper* layoutWrapper, 339 const LayoutConstraintF& layoutConstraint, int32_t startIndex, float startPos); 340 void MeasureJumpToItemBackward(LayoutWrapper* layoutWrapper, 341 const LayoutConstraintF& layoutConstraint, int32_t endIndex, float endPos); 342 void MeasureCenter(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 343 void MeasureStart(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 344 void MeasureEnd(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 345 void MeasureAuto(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 346 void MeasureHeaderFooter(LayoutWrapper* layoutWrapper); 347 void SetActiveChildRange(LayoutWrapper* layoutWrapper, int32_t cacheCount); 348 float UpdateReferencePos(RefPtr<LayoutProperty> layoutProperty, bool forwardLayout, float referencePos); 349 bool NeedMeasureItem(LayoutWrapper* layoutWrapper); 350 static void SetListItemIndex(const LayoutWrapper* groupLayoutWrapper, 351 const RefPtr<LayoutWrapper>& itemLayoutWrapper, int32_t indexInGroup); 352 bool IsCardStyleForListItemGroup(const LayoutWrapper* groupLayoutWrapper); 353 float GetListItemGroupMaxWidth(const OptionalSizeF& parentIdealSize, RefPtr<LayoutProperty> layoutProperty); 354 void AdjustItemPosition(); 355 bool CheckNeedMeasure(const RefPtr<LayoutWrapper>& layoutWrapper) const; 356 void MeasureCacheItem(LayoutWrapper* layoutWrapper); 357 void LayoutCacheItem(LayoutWrapper* layoutWrapper); 358 359 bool isCardStyle_ = false; 360 int32_t headerIndex_; 361 int32_t footerIndex_; 362 int32_t itemStartIndex_; 363 RefPtr<ListLayoutProperty> listLayoutProperty_; 364 float paddingBeforeContent_ = 0.0f; 365 float paddingAfterContent_ = 0.0f; 366 367 PositionMap itemPosition_; 368 RefPtr<ListChildrenMainSize> childrenSize_; 369 RefPtr<ListPositionMap> posMap_; 370 Axis axis_ = Axis::VERTICAL; 371 int32_t lanes_ = 1; 372 float laneGutter_ = 0.0f; 373 std::optional<float> minLaneLength_; 374 std::optional<float> maxLaneLength_; 375 V2::ListItemAlign itemAlign_ = V2::ListItemAlign::START; 376 float spaceWidth_ = 0.0f; 377 378 std::optional<int32_t> jumpIndex_; 379 std::optional<int32_t> targetIndex_; 380 ScrollAlign scrollAlign_ = ScrollAlign::NONE; 381 int32_t totalItemCount_ = 0; 382 float totalMainSize_ = 0.0f; 383 float headerMainSize_ = 0.0f; 384 float footerMainSize_ = 0.0f; 385 float startPos_ = 0.0f; 386 float startHeaderPos_ = 0.0f; 387 float endFooterPos_ = 0.0f; 388 float prevStartPos_ = 0.0f; 389 float prevEndPos_ = 0.0f; 390 float endPos_ = 0.0f; 391 float referencePos_ = 0.0f; 392 float adjustReferenceDelta_ = 0.0f; 393 float refPos_ = 0.0f; 394 float prevContentMainSize_ = 0.0f; 395 float contentStartOffset_ = 0.0f; 396 float contentEndOffset_ = 0.0f; 397 bool forwardLayout_ = true; 398 bool needAllLayout_ = false; 399 bool needAdjustRefPos_ = false; 400 bool isNeedCheckOffset_ = false; 401 bool isNeedMeasureFormLastItem_ = false; 402 403 std::optional<LayoutedItemInfo> layoutedItemInfo_; 404 LayoutConstraintF childLayoutConstraint_; 405 TextDirection layoutDirection_ = TextDirection::LTR; 406 407 std::optional<ListItemGroupCacheParam> cacheParam_; 408 std::list<int32_t> cachedItem_; 409 }; 410 } // namespace OHOS::Ace::NG 411 412 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_LIST_LIST_LAYOUT_ALGORITHM_H 413