• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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