• 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     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