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 bool backward = false; 47 bool show = false; 48 int32_t cacheCountForward = 0; 49 int32_t cacheCountBackward = 0; 50 int32_t forwardCachedIndex = -1; 51 int32_t backwardCachedIndex = INT_MAX; 52 int64_t deadline = 0; 53 }; 54 55 struct CachedIndexInfo { 56 int32_t forwardCachedCount = 0; 57 int32_t backwardCachedCount = 0; 58 int32_t forwardCacheMax = 0; 59 int32_t backwardCacheMax = 0; 60 }; 61 62 // TextLayoutAlgorithm acts as the underlying text layout. 63 class ACE_EXPORT ListItemGroupLayoutAlgorithm : public LayoutAlgorithm { 64 DECLARE_ACE_TYPE(ListItemGroupLayoutAlgorithm, LayoutAlgorithm); 65 public: 66 using PositionMap = std::map<int32_t, ListItemGroupInfo>; 67 68 static const int32_t LAST_ITEM = -1; 69 ListItemGroupLayoutAlgorithm(int32_t headerIndex,int32_t footerIndex,int32_t itemStartIndex)70 ListItemGroupLayoutAlgorithm(int32_t headerIndex, int32_t footerIndex, int32_t itemStartIndex) 71 :headerIndex_(headerIndex), footerIndex_(footerIndex), itemStartIndex_(itemStartIndex) {} 72 73 void Measure(LayoutWrapper* layoutWrapper) override; 74 75 void Layout(LayoutWrapper* layoutWrapper) override; 76 GetItemPosition()77 const PositionMap& GetItemPosition() const 78 { 79 return itemPosition_; 80 } 81 GetCachedItemPosition()82 const PositionMap& GetCachedItemPosition() const 83 { 84 return cachedItemPosition_; 85 } 86 ResetCachedItemPosition()87 void ResetCachedItemPosition() 88 { 89 cachedItemPosition_.clear(); 90 } 91 ResetCachedIndex()92 void ResetCachedIndex() 93 { 94 forwardCachedIndex_ = -1; 95 backwardCachedIndex_ = INT_MAX; 96 } 97 SetItemsPosition(const PositionMap & itemPosition)98 void SetItemsPosition(const PositionMap& itemPosition) 99 { 100 itemPosition_ = itemPosition; 101 } 102 SetCachedItemsPosition(const PositionMap & itemPosition)103 void SetCachedItemsPosition(const PositionMap& itemPosition) 104 { 105 cachedItemPosition_ = itemPosition; 106 } 107 108 void ClearItemPosition(); 109 GetSpaceWidth()110 float GetSpaceWidth() const 111 { 112 return spaceWidth_; 113 } 114 GetAxis()115 Axis GetAxis() const 116 { 117 return axis_; 118 } 119 GetLayoutDirection()120 TextDirection GetLayoutDirection() const 121 { 122 return layoutDirection_; 123 } 124 GetMainSize()125 float GetMainSize() const 126 { 127 return totalMainSize_; 128 } 129 GetLanes()130 int32_t GetLanes() const 131 { 132 return lanes_; 133 } 134 GetLaneGutter()135 float GetLaneGutter() const 136 { 137 return laneGutter_; 138 } 139 GetLanesFloor(int32_t index)140 int32_t GetLanesFloor(int32_t index) const 141 { 142 if (lanes_ <= 1) { 143 return index; 144 } 145 return index - index % lanes_; 146 } 147 GetLanesCeil(int32_t index)148 int32_t GetLanesCeil(int32_t index) const 149 { 150 int32_t tmpIndex = (lanes_ <= 1) ? index : (index - index % lanes_ + lanes_ - 1); 151 tmpIndex = tmpIndex >= totalItemCount_ ? totalItemCount_ - 1 : tmpIndex; 152 return tmpIndex; 153 } 154 SetListMainSize(float startPos,float endPos,float referencePos,float prevContentSize,bool forwardLayout)155 void SetListMainSize(float startPos, float endPos, float referencePos, float prevContentSize, bool forwardLayout) 156 { 157 startPos_ = startPos; 158 endPos_ = endPos; 159 referencePos_ = referencePos; 160 forwardLayout_ = forwardLayout; 161 refPos_ = referencePos; 162 prevContentMainSize_ = prevContentSize; 163 } 164 165 void ModifyReferencePos(int32_t index, float pos); 166 SetNeedAdjustRefPos(bool needAdjust)167 void SetNeedAdjustRefPos(bool needAdjust) 168 { 169 needAdjustRefPos_ = needAdjust; 170 } 171 SetNeedCheckOffset(bool needCheckOffset)172 void SetNeedCheckOffset(bool needCheckOffset) 173 { 174 isNeedCheckOffset_ = needCheckOffset; 175 } 176 GetRefPos()177 float GetRefPos() const 178 { 179 return refPos_; 180 } 181 SetContentOffset(float contentStartOffset,float contentEndOffset)182 void SetContentOffset(float contentStartOffset, float contentEndOffset) 183 { 184 contentStartOffset_ = contentStartOffset; 185 contentEndOffset_ = contentEndOffset; 186 } 187 SetListLayoutProperty(RefPtr<ListLayoutProperty> layoutProperty)188 void SetListLayoutProperty(RefPtr<ListLayoutProperty> layoutProperty) 189 { 190 listLayoutProperty_ = std::move(layoutProperty); 191 } 192 SetJumpIndex(int32_t index)193 void SetJumpIndex(int32_t index) 194 { 195 jumpIndex_ = index; 196 } 197 SetTargetIndex(int32_t index)198 void SetTargetIndex(int32_t index) 199 { 200 targetIndex_ = index; 201 } 202 GetStartIndex()203 int32_t GetStartIndex() const 204 { 205 return itemPosition_.empty() ? 0 : itemPosition_.begin()->first; 206 } 207 GetEndIndex()208 int32_t GetEndIndex() const 209 { 210 return itemPosition_.empty() ? 0 : itemPosition_.rbegin()->first; 211 } 212 GetCacheStartIndex()213 int32_t GetCacheStartIndex() const 214 { 215 return cachedItemPosition_.empty() ? -1 : cachedItemPosition_.begin()->first; 216 } 217 GetCacheEndIndex()218 int32_t GetCacheEndIndex() const 219 { 220 return cachedItemPosition_.empty() ? -1 : cachedItemPosition_.rbegin()->first; 221 } 222 GetStartPosition()223 float GetStartPosition() const 224 { 225 if (itemPosition_.empty()) { 226 return 0.0f; 227 } 228 if (GetStartIndex() == 0) { 229 return itemPosition_.begin()->second.startPos; 230 } 231 return itemPosition_.begin()->second.startPos - spaceWidth_; 232 } 233 GetEndPosition()234 float GetEndPosition() const 235 { 236 if (itemPosition_.empty()) { 237 return 0.0f; 238 } 239 if (GetEndIndex() == totalItemCount_ - 1) { 240 return itemPosition_.rbegin()->second.endPos; 241 } 242 return itemPosition_.rbegin()->second.endPos + spaceWidth_; 243 } 244 GetCacheStartPosition()245 float GetCacheStartPosition() const 246 { 247 if (cachedItemPosition_.empty()) { 248 return 0.0f; 249 } 250 if (GetCacheStartIndex() == 0) { 251 return cachedItemPosition_.begin()->second.startPos; 252 } 253 return cachedItemPosition_.begin()->second.startPos - spaceWidth_; 254 } 255 GetCacheEndPosition()256 float GetCacheEndPosition() const 257 { 258 if (cachedItemPosition_.empty()) { 259 return 0.0f; 260 } 261 if (GetCacheEndIndex() == totalItemCount_ - 1) { 262 return cachedItemPosition_.rbegin()->second.endPos; 263 } 264 return cachedItemPosition_.rbegin()->second.endPos + spaceWidth_; 265 } 266 GetTotalItemCount()267 int32_t GetTotalItemCount() const 268 { 269 return totalItemCount_; 270 } 271 272 float GetChildMaxCrossSize(LayoutWrapper* layoutWrapper, Axis axis); 273 274 void CheckRecycle(const RefPtr<LayoutWrapper>& layoutWrapper, float startPos, float endPos, float referencePos, 275 bool forwardLayout); 276 SetNeedAllLayout()277 void SetNeedAllLayout() 278 { 279 needAllLayout_ = true; 280 } 281 282 void CheckNeedAllLayout(const RefPtr<LayoutWrapper>& layoutWrapper, bool forwardLayout); 283 SetScrollAlign(ScrollAlign align)284 void SetScrollAlign(ScrollAlign align) 285 { 286 scrollAlign_ = align; 287 } 288 289 std::pair<float, float> GetItemGroupPosition(int32_t index); 290 GetHeaderMainSize()291 float GetHeaderMainSize() const 292 { 293 return headerMainSize_; 294 } 295 GetFooterMainSize()296 float GetFooterMainSize() const 297 { 298 return footerMainSize_; 299 } 300 301 float GetItemHeight(int32_t index); 302 GetItemStartIndex()303 int32_t GetItemStartIndex() 304 { 305 return itemStartIndex_; 306 } 307 SetLayoutedItemInfo(const std::optional<LayoutedItemInfo> & itemInfo)308 void SetLayoutedItemInfo(const std::optional<LayoutedItemInfo>& itemInfo) 309 { 310 layoutedItemInfo_ = itemInfo; 311 } 312 GetLayoutedItemInfo()313 std::optional<LayoutedItemInfo> GetLayoutedItemInfo() const 314 { 315 return layoutedItemInfo_; 316 } 317 SetListChildrenMainSize(const RefPtr<ListChildrenMainSize> & childrenMainSize)318 void SetListChildrenMainSize(const RefPtr<ListChildrenMainSize>& childrenMainSize) 319 { 320 childrenSize_ = childrenMainSize; 321 } 322 SetListPositionMap(const RefPtr<ListPositionMap> & posMap)323 void SetListPositionMap(const RefPtr<ListPositionMap>& posMap) 324 { 325 posMap_ = posMap; 326 } 327 328 void AdjustByPosMap(); 329 330 static void SyncGeometry(RefPtr<LayoutWrapper>& wrapper); 331 GetStartHeaderPos()332 float GetStartHeaderPos() const 333 { 334 return startHeaderPos_; 335 } 336 GetEndFooterPos()337 float GetEndFooterPos() const 338 { 339 return endFooterPos_; 340 } 341 SetCacheParam(std::optional<ListItemGroupCacheParam> param)342 void SetCacheParam(std::optional<ListItemGroupCacheParam> param) 343 { 344 cacheParam_ = param; 345 } 346 GetCacheParam()347 std::optional<ListItemGroupCacheParam> GetCacheParam() const 348 { 349 return cacheParam_; 350 } 351 SetNeedMeasureFormLastItem(bool needMeasureFormLastItem)352 void SetNeedMeasureFormLastItem(bool needMeasureFormLastItem) 353 { 354 isNeedMeasureFormLastItem_ = needMeasureFormLastItem; 355 } 356 357 ListItemGroupLayoutInfo GetLayoutInfo() const; 358 GetAdjustReferenceDelta()359 float GetAdjustReferenceDelta() const 360 { 361 return adjustReferenceDelta_; 362 } 363 GetAdjustTotalSize()364 float GetAdjustTotalSize() const 365 { 366 return adjustTotalSize_; 367 } 368 SetCachedIndex(int32_t forwardIndex,int32_t backwardIndex)369 void SetCachedIndex(int32_t forwardIndex, int32_t backwardIndex) 370 { 371 forwardCachedIndex_ = forwardIndex; 372 backwardCachedIndex_ = backwardIndex; 373 } 374 GetCachedIndex()375 std::pair<int32_t, int32_t> GetCachedIndex() const 376 { 377 return { forwardCachedIndex_, backwardCachedIndex_ }; 378 } 379 GetListItemCount()380 int32_t GetListItemCount() const 381 { 382 return static_cast<int32_t>(itemPosition_.size()); 383 } 384 385 private: 386 float CalculateLaneCrossOffset(float crossSize, float childCrossSize); 387 void UpdateListItemConstraint(const OptionalSizeF& selfIdealSize, LayoutConstraintF& contentConstraint); 388 void LayoutListItem(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize); 389 void LayoutListItemAll(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, float startPos); 390 void LayoutHeaderFooterRTL(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize); 391 void LayoutHeaderFooterLTR(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize); 392 void UpdateZIndex(const RefPtr<LayoutWrapper>& layoutWrapper); 393 void LayoutIndex(const RefPtr<LayoutWrapper>& wrapper, const OffsetF& paddingOffset, 394 float crossSize, float startPos); GetListItem(LayoutWrapper * layoutWrapper,int32_t index)395 inline RefPtr<LayoutWrapper> GetListItem(LayoutWrapper* layoutWrapper, int32_t index) const 396 { 397 return layoutWrapper->GetOrCreateChildByIndex(index + itemStartIndex_); 398 } 399 void CalculateLanes(const RefPtr<ListLayoutProperty>& layoutProperty, 400 const LayoutConstraintF& layoutConstraint, std::optional<float> crossSizeOptional, Axis axis); 401 402 void MeasureListItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint); 403 int32_t MeasureALineForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 404 int32_t& currentIndex, float startPos, float& endPos); 405 int32_t MeasureALineBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 406 int32_t& currentIndex, float endPos, float& startPos); 407 int32_t MeasureALineCenter(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 408 int32_t currentIndex); 409 int32_t MeasureALineAuto(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 410 int32_t currentIndex); 411 void CheckJumpForwardForBigOffset(int32_t& startIndex, float& startPos); 412 void CheckJumpBackwardForBigOffset(int32_t& endIndex, float& endPos); 413 void MeasureForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 414 int32_t startIndex, float startPos); 415 void MeasureBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, 416 int32_t endIndex, float endPos); 417 void MeasureJumpToItemForward(LayoutWrapper* layoutWrapper, 418 const LayoutConstraintF& layoutConstraint, int32_t startIndex, float startPos); 419 void MeasureJumpToItemBackward(LayoutWrapper* layoutWrapper, 420 const LayoutConstraintF& layoutConstraint, int32_t endIndex, float endPos); 421 void MeasureCenter(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 422 void MeasureStart(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 423 void MeasureEnd(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 424 void MeasureAuto(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex); 425 void MeasureHeaderFooter(LayoutWrapper* layoutWrapper); 426 void SetActiveChildRange(LayoutWrapper* layoutWrapper, int32_t cacheCount, bool show); 427 float UpdateReferencePos(RefPtr<LayoutProperty> layoutProperty, bool forwardLayout, float referencePos); 428 bool NeedMeasureItem(LayoutWrapper* layoutWrapper); 429 static void SetListItemIndex(const LayoutWrapper* groupLayoutWrapper, 430 const RefPtr<LayoutWrapper>& itemLayoutWrapper, int32_t indexInGroup); 431 bool IsCardStyleForListItemGroup(const LayoutWrapper* groupLayoutWrapper); 432 float GetListItemGroupMaxWidth(const OptionalSizeF& parentIdealSize, RefPtr<LayoutProperty> layoutProperty); 433 void AdjustItemPosition(); 434 bool CheckNeedMeasure(const RefPtr<LayoutWrapper>& layoutWrapper) const; 435 void MeasureCacheItem(LayoutWrapper* layoutWrapper); 436 void MeasureCacheForward(LayoutWrapper* layoutWrapper, ListItemGroupCacheParam& param); 437 void MeasureCacheBackward(LayoutWrapper* layoutWrapper, ListItemGroupCacheParam& param); 438 void LayoutCacheItem(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize, bool show); 439 void CheckUpdateGroupAndItemPos(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize); 440 void UpdateCachedItemPosition(int32_t cacheCount); 441 void UpdateLayoutedItemInfo(); 442 443 bool isCardStyle_ = false; 444 int32_t headerIndex_; 445 int32_t footerIndex_; 446 int32_t itemStartIndex_; 447 RefPtr<ListLayoutProperty> listLayoutProperty_; 448 float paddingBeforeContent_ = 0.0f; 449 float paddingAfterContent_ = 0.0f; 450 451 PositionMap itemPosition_; 452 RefPtr<ListChildrenMainSize> childrenSize_; 453 RefPtr<ListPositionMap> posMap_; 454 Axis axis_ = Axis::VERTICAL; 455 int32_t lanes_ = 1; 456 float laneGutter_ = 0.0f; 457 std::optional<float> minLaneLength_; 458 std::optional<float> maxLaneLength_; 459 V2::ListItemAlign itemAlign_ = V2::ListItemAlign::START; 460 float spaceWidth_ = 0.0f; 461 462 std::optional<int32_t> jumpIndex_; 463 std::optional<int32_t> targetIndex_; 464 ScrollAlign scrollAlign_ = ScrollAlign::NONE; 465 int32_t totalItemCount_ = 0; 466 int32_t forwardCachedIndex_ = -1; 467 int32_t backwardCachedIndex_ = INT_MAX; 468 float totalMainSize_ = 0.0f; 469 float headerMainSize_ = 0.0f; 470 float footerMainSize_ = 0.0f; 471 float startPos_ = 0.0f; 472 float startHeaderPos_ = 0.0f; 473 float endFooterPos_ = 0.0f; 474 float prevStartPos_ = 0.0f; 475 float prevEndPos_ = 0.0f; 476 float endPos_ = 0.0f; 477 float referencePos_ = 0.0f; 478 float adjustReferenceDelta_ = 0.0f; 479 float adjustTotalSize_ = 0.0f; 480 float refPos_ = 0.0f; 481 float prevContentMainSize_ = 0.0f; 482 float contentStartOffset_ = 0.0f; 483 float contentEndOffset_ = 0.0f; 484 bool forwardLayout_ = true; 485 bool needAllLayout_ = false; 486 bool needAdjustRefPos_ = false; 487 bool isNeedCheckOffset_ = false; 488 bool isNeedMeasureFormLastItem_ = false; 489 490 std::optional<LayoutedItemInfo> layoutedItemInfo_; 491 LayoutConstraintF childLayoutConstraint_; 492 TextDirection layoutDirection_ = TextDirection::LTR; 493 494 std::optional<ListItemGroupCacheParam> cacheParam_; 495 PositionMap cachedItemPosition_; 496 }; 497 } // namespace OHOS::Ace::NG 498 499 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_LIST_LIST_LAYOUT_ALGORITHM_H 500