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