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_PATTERN_LIST_LIST_LAYOUT_ALGORITHM_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_LIST_LIST_LAYOUT_ALGORITHM_H 18 19 #include <map> 20 #include <optional> 21 22 #include "base/geometry/axis.h" 23 #include "base/memory/referenced.h" 24 #include "core/components_ng/layout/layout_algorithm.h" 25 #include "core/components_ng/layout/layout_wrapper.h" 26 #include "core/components_ng/pattern/list/list_layout_property.h" 27 #include "core/components_v2/list/list_component.h" 28 #include "core/components_v2/list/list_properties.h" 29 30 namespace OHOS::Ace::NG { 31 class PipelineContext; 32 33 struct ListItemInfo { 34 int32_t id; 35 float startPos; 36 float endPos; 37 bool isGroup; 38 }; 39 40 struct ListPredictLayoutParam { 41 std::list<int32_t> items; 42 LayoutConstraintF layoutConstraint; 43 }; 44 45 enum class ScrollAutoType { 46 NOT_CHANGE = 0, 47 START, 48 END, 49 }; 50 51 // TextLayoutAlgorithm acts as the underlying text layout. 52 class ACE_EXPORT ListLayoutAlgorithm : public LayoutAlgorithm { 53 DECLARE_ACE_TYPE(ListLayoutAlgorithm, LayoutAlgorithm); 54 55 public: 56 using PositionMap = std::map<int32_t, ListItemInfo>; 57 static const int32_t LAST_ITEM = -1; 58 59 ListLayoutAlgorithm() = default; 60 61 ~ListLayoutAlgorithm() override = default; 62 OnReset()63 void OnReset() override {} 64 GetItemPosition()65 const PositionMap& GetItemPosition() const 66 { 67 return itemPosition_; 68 } 69 SetItemsPosition(const PositionMap & itemPosition)70 void SetItemsPosition(const PositionMap& itemPosition) 71 { 72 itemPosition_ = itemPosition; 73 } 74 75 void ClearAllItemPosition(LayoutWrapper* layoutWrapper); 76 SetOverScrollFeature()77 void SetOverScrollFeature() 78 { 79 overScrollFeature_ = true; 80 } 81 SetCanOverScroll(bool canOverScroll)82 void SetCanOverScroll(bool canOverScroll) 83 { 84 canOverScroll_ = canOverScroll; 85 } 86 SetIsSpringEffect(bool isSpringEffect)87 void SetIsSpringEffect(bool isSpringEffect) 88 { 89 isSpringEffect_ = isSpringEffect; 90 } 91 SetIndex(int32_t index)92 void SetIndex(int32_t index) 93 { 94 jumpIndex_ = index; 95 } 96 SetTargetIndex(int32_t index)97 void SetTargetIndex(int32_t index) 98 { 99 targetIndex_ = index; 100 } 101 GetTargetIndex()102 std::optional<int32_t> GetTargetIndex() const 103 { 104 return targetIndexStaged_; 105 } 106 SetPredictSnapOffset(float predictSnapOffset)107 void SetPredictSnapOffset(float predictSnapOffset) 108 { 109 predictSnapOffset_ = predictSnapOffset; 110 } 111 GetPredictSnapOffset()112 std::optional<float> GetPredictSnapOffset() const 113 { 114 return predictSnapOffset_; 115 } 116 SetPredictSnapEndPosition(float predictSnapEndPos)117 void SetPredictSnapEndPosition(float predictSnapEndPos) 118 { 119 predictSnapEndPos_ = predictSnapEndPos; 120 } 121 GetPredictSnapEndPosition()122 std::optional<float> GetPredictSnapEndPosition() 123 { 124 return predictSnapEndPos_; 125 } 126 SetIndexInGroup(int32_t index)127 void SetIndexInGroup(int32_t index) 128 { 129 jumpIndexInGroup_ = index; 130 } 131 SetIndexAlignment(ScrollAlign align)132 void SetIndexAlignment(ScrollAlign align) 133 { 134 scrollAlign_ = align; 135 } 136 SetCurrentDelta(float offset)137 void SetCurrentDelta(float offset) 138 { 139 currentDelta_ = offset; 140 currentOffset_ = offset; 141 } 142 GetCurrentOffset()143 float GetCurrentOffset() const 144 { 145 return currentOffset_; 146 } 147 SetIsNeedCheckOffset(bool isNeedCheckOffset)148 void SetIsNeedCheckOffset(bool isNeedCheckOffset) 149 { 150 isNeedCheckOffset_ = isNeedCheckOffset; 151 } 152 SetTotalOffset(float totalOffset)153 void SetTotalOffset(float totalOffset) 154 { 155 totalOffset_ = totalOffset; 156 } 157 GetContentMainSize()158 float GetContentMainSize() const 159 { 160 return contentMainSize_; 161 } 162 SetPrevContentMainSize(float mainSize)163 void SetPrevContentMainSize(float mainSize) 164 { 165 prevContentMainSize_ = mainSize; 166 } 167 GetStartIndex()168 int32_t GetStartIndex() const 169 { 170 return itemPosition_.empty() ? -1 : itemPosition_.begin()->first; 171 } 172 GetEndIndex()173 int32_t GetEndIndex() const 174 { 175 return itemPosition_.empty() ? -1 : itemPosition_.rbegin()->first; 176 } 177 178 int32_t GetMidIndex(LayoutWrapper* layoutWrapper, bool usePreContentMainSize = false); 179 GetMaxListItemIndex()180 int32_t GetMaxListItemIndex() const 181 { 182 return totalItemCount_ - 1; 183 } 184 SetSpaceWidth(float spaceWidth)185 void SetSpaceWidth(float spaceWidth) 186 { 187 spaceWidth_ = spaceWidth; 188 } 189 GetSpaceWidth()190 float GetSpaceWidth() const 191 { 192 return spaceWidth_; 193 } 194 NeedEstimateOffset()195 bool NeedEstimateOffset() const 196 { 197 return needEstimateOffset_; 198 } 199 SetContentStartOffset(float startOffset)200 void SetContentStartOffset(float startOffset) 201 { 202 contentStartOffset_ = startOffset; 203 } 204 SetContentEndOffset(float endOffset)205 void SetContentEndOffset(float endOffset) 206 { 207 contentEndOffset_ = endOffset; 208 } 209 GetContentStartOffset()210 float GetContentStartOffset() const 211 { 212 return contentStartOffset_; 213 } 214 GetContentEndOffset()215 float GetContentEndOffset() const 216 { 217 return contentEndOffset_; 218 } 219 GetStartPosition()220 float GetStartPosition() const 221 { 222 if (itemPosition_.empty()) { 223 return 0.0f; 224 } 225 if (GetStartIndex() == 0) { 226 return itemPosition_.begin()->second.startPos; 227 } 228 return itemPosition_.begin()->second.startPos - spaceWidth_; 229 } 230 GetEndPosition()231 float GetEndPosition() const 232 { 233 if (itemPosition_.empty()) { 234 return 0.0f; 235 } 236 if (GetEndIndex() == totalItemCount_ - 1) { 237 return itemPosition_.rbegin()->second.endPos; 238 } 239 return itemPosition_.rbegin()->second.endPos + spaceWidth_; 240 } 241 SetChainOffsetCallback(std::function<float (int32_t)> func)242 void SetChainOffsetCallback(std::function<float(int32_t)> func) 243 { 244 chainOffsetFunc_ = std::move(func); 245 } 246 SetChainInterval(float interval)247 void SetChainInterval(float interval) 248 { 249 chainInterval_ = interval; 250 } 251 IsCrossMatchChild()252 bool IsCrossMatchChild() const 253 { 254 return crossMatchChild_; 255 } 256 257 float GetChildMaxCrossSize(LayoutWrapper* layoutWrapper, Axis axis) const; 258 259 void Measure(LayoutWrapper* layoutWrapper) override; 260 261 void Layout(LayoutWrapper* layoutWrapper) override; 262 263 void LayoutForward(LayoutWrapper* layoutWrapper, int32_t startIndex, float startPos); 264 void LayoutBackward(LayoutWrapper* layoutWrapper, int32_t endIndex, float endPos); 265 266 void BeginLayoutForward(float startPos, LayoutWrapper* layoutWrapper); 267 268 void BeginLayoutBackward(float startPos, LayoutWrapper* layoutWrapper); 269 270 void HandleJumpAuto(LayoutWrapper* layoutWrapper, 271 int32_t& startIndex, int32_t& endIndex, float& startPos, float& endPos); 272 273 void HandleJumpCenter(LayoutWrapper* layoutWrapper); 274 275 void HandleJumpStart(LayoutWrapper* layoutWrapper); 276 277 void HandleJumpEnd(LayoutWrapper* layoutWrapper); 278 279 bool NoNeedJump(LayoutWrapper* layoutWrapper, float startPos, float endPos, 280 int32_t startIndex, int32_t endIndex, int32_t jumpIndex, float jumpIndexStartPos); 281 282 bool CheckNoNeedJumpListItem(LayoutWrapper* layoutWrapper, float startPos, float endPos, 283 int32_t startIndex, int32_t endIndex, int32_t jumpIndex); 284 285 bool CheckNoNeedJumpListItemGroup(LayoutWrapper* layoutWrapper, int32_t startIndex, int32_t endIndex, 286 int32_t jumpIndex, float jumpIndexStartPos); 287 288 virtual float MeasureAndGetChildHeight(LayoutWrapper* layoutWrapper, int32_t childIndex); 289 GetLanes()290 virtual int32_t GetLanes() const 291 { 292 return 1; 293 } 294 SetLaneGutter(float laneGutter)295 void SetLaneGutter(float laneGutter) 296 { 297 laneGutter_ = laneGutter; 298 } 299 GetLaneGutter()300 float GetLaneGutter() const 301 { 302 return laneGutter_; 303 } 304 305 void OffScreenLayoutDirection(); 306 GetScrollAutoType()307 ScrollAutoType GetScrollAutoType() const 308 { 309 return scrollAutoType_; 310 } 311 312 bool CheckJumpValid(LayoutWrapper* layoutWrapper); 313 314 float GetListGroupItemHeight(const RefPtr<LayoutWrapper>& layoutWrapper, int32_t index); 315 316 bool JudgeInOfScreenScrollAutoType(const RefPtr<LayoutWrapper>& layoutWrapper, 317 const RefPtr<ListLayoutProperty>& layoutProperty, float topPos, float bottomPos); 318 319 void JudgeOutOfScreenScrollAutoType(const RefPtr<LayoutWrapper>& layoutWrapper, int32_t index, 320 const RefPtr<ListLayoutProperty>& layoutProperty, int32_t indexInGroup, int32_t judgeIndex, 321 int32_t startIndex, int32_t endIndex); 322 GetGroupLayoutConstraint()323 virtual LayoutConstraintF& GetGroupLayoutConstraint() 324 { 325 return childLayoutConstraint_; 326 } 327 328 void OnItemPositionAddOrUpdate(LayoutWrapper* layoutWrapper, uint32_t index); 329 330 protected: 331 virtual void UpdateListItemConstraint( 332 Axis axis, const OptionalSizeF& selfIdealSize, LayoutConstraintF& contentConstraint); 333 virtual int32_t LayoutALineForward( 334 LayoutWrapper* layoutWrapper, int32_t& currentIndex, float startPos, float& endPos); 335 virtual int32_t LayoutALineBackward( 336 LayoutWrapper* layoutWrapper, int32_t& currentIndex, float endPos, float& startPos); 337 virtual float CalculateLaneCrossOffset(float crossSize, float childCrossSize); CalculateLanes(const RefPtr<ListLayoutProperty> & layoutProperty,const LayoutConstraintF & layoutConstraint,std::optional<float> crossSizeOptional,Axis axis)338 virtual void CalculateLanes(const RefPtr<ListLayoutProperty>& layoutProperty, 339 const LayoutConstraintF& layoutConstraint, std::optional<float> crossSizeOptional, Axis axis) {}; GetLanesFloor(LayoutWrapper * layoutWrapper,int32_t index)340 virtual int32_t GetLanesFloor(LayoutWrapper* layoutWrapper, int32_t index) 341 { 342 return index; 343 } GetLanesCeil(LayoutWrapper * layoutWrapper,int32_t index)344 virtual int32_t GetLanesCeil(LayoutWrapper* layoutWrapper, int32_t index) 345 { 346 return index; 347 } 348 virtual void SetCacheCount(LayoutWrapper* layoutWrapper, int32_t cacheCount); 349 350 void SetListItemGroupParam(const RefPtr<LayoutWrapper>& layoutWrapper, int32_t index, float referencePos, 351 bool forwardLayout, const RefPtr<ListLayoutProperty>& layoutProperty, bool groupNeedAllLayout); 352 static void SetListItemIndex(const RefPtr<LayoutWrapper>& layoutWrapper, int32_t index); 353 void CheckListItemGroupRecycle( 354 LayoutWrapper* layoutWrapper, int32_t index, float referencePos, bool forwardLayout) const; 355 void AdjustPostionForListItemGroup(LayoutWrapper* layoutWrapper, Axis axis, int32_t index, bool forwardLayout); SetItemInfo(int32_t index,ListItemInfo && info)356 void SetItemInfo(int32_t index, ListItemInfo&& info) 357 { 358 itemPosition_[index] = info; 359 } 360 void LayoutItem(RefPtr<LayoutWrapper>& layoutWrapper, int32_t index, const ListItemInfo& pos, 361 int32_t& startIndex, float crossSize); 362 static void SyncGeometry(RefPtr<LayoutWrapper>& wrapper); 363 ListItemInfo GetListItemGroupPosition(const RefPtr<LayoutWrapper>& layoutWrapper, int32_t index); 364 365 Axis axis_ = Axis::VERTICAL; 366 LayoutConstraintF childLayoutConstraint_; 367 private: 368 void MeasureList(LayoutWrapper* layoutWrapper); 369 void CheckJumpToIndex(); 370 371 std::pair<int32_t, float> RequestNewItemsForward(LayoutWrapper* layoutWrapper, 372 const LayoutConstraintF& layoutConstraint, int32_t startIndex, float startPos, Axis axis); 373 374 std::pair<int32_t, float> RequestNewItemsBackward(LayoutWrapper* layoutWrapper, 375 const LayoutConstraintF& layoutConstraint, int32_t startIndex, float startPos, Axis axis); 376 377 void OnSurfaceChanged(LayoutWrapper* layoutWrapper); 378 379 void FixPredictSnapOffset(const RefPtr<ListLayoutProperty>& listLayoutProperty); 380 void FixPredictSnapOffsetAlignStart(); 381 void FixPredictSnapOffsetAlignCenter(); 382 void FixPredictSnapOffsetAlignEnd(); 383 bool IsScrollSnapAlignCenter(LayoutWrapper* layoutWrapper); 384 virtual std::list<int32_t> LayoutCachedItem(LayoutWrapper* layoutWrapper, int32_t cacheCount); 385 static void PostIdleTask(RefPtr<FrameNode> frameNode, const ListPredictLayoutParam& param); 386 static bool PredictBuildItem(RefPtr<LayoutWrapper> wrapper, const LayoutConstraintF& constraint); 387 388 float GetStopOnScreenOffset(V2::ScrollSnapAlign scrollSnapAlign); 389 int32_t FindPredictSnapEndIndexInItemPositions(float predictEndPos, V2::ScrollSnapAlign scrollSnapAlign); 390 bool IsUniformHeightProbably(); 391 float CalculatePredictSnapEndPositionByIndex(uint32_t index, V2::ScrollSnapAlign scrollSnapAlign); 392 void UpdateSnapCenterContentOffset(LayoutWrapper* layoutWrapper); 393 394 std::optional<int32_t> jumpIndex_; 395 std::optional<int32_t> jumpIndexInGroup_; 396 std::optional<int32_t> targetIndex_; 397 std::optional<int32_t> targetIndexStaged_; 398 std::optional<float> predictSnapOffset_; 399 std::optional<float> predictSnapEndPos_; 400 ScrollAlign scrollAlign_ = ScrollAlign::START; 401 ScrollAutoType scrollAutoType_ = ScrollAutoType::NOT_CHANGE; 402 403 PositionMap itemPosition_; 404 float currentOffset_ = 0.0f; 405 float totalOffset_ = 0.0f; 406 float currentDelta_ = 0.0f; 407 float startMainPos_ = 0.0f; 408 float endMainPos_ = 0.0f; 409 float contentStartOffset_ = 0.0f; 410 float contentEndOffset_ = 0.0f; 411 float spaceWidth_ = 0.0f; 412 bool overScrollFeature_ = false; 413 bool canOverScroll_ = false; 414 bool isSpringEffect_ = false; 415 bool forwardFeature_ = false; 416 bool backwardFeature_ = false; 417 bool isNeedCheckOffset_ = false; 418 419 int32_t totalItemCount_ = 0; 420 421 V2::ListItemAlign listItemAlign_ = V2::ListItemAlign::START; 422 423 bool needEstimateOffset_ = false; 424 425 bool mainSizeIsDefined_ = false; 426 bool crossMatchChild_ = false; 427 float contentMainSize_ = 0.0f; 428 float prevContentMainSize_ = 0.0f; 429 float paddingBeforeContent_ = 0.0f; 430 float paddingAfterContent_ = 0.0f; 431 float laneGutter_ = 0.0f; 432 OffsetF paddingOffset_; 433 434 V2::StickyStyle stickyStyle_ = V2::StickyStyle::NONE; 435 436 std::function<float(int32_t)> chainOffsetFunc_; 437 float chainInterval_ = 0.0f; 438 }; 439 } // namespace OHOS::Ace::NG 440 441 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_LIST_LIST_LAYOUT_ALGORITHM_H 442