• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_LIST_RENDER_LIST_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_RENDER_LIST_H
18 
19 #include <functional>
20 #include <map>
21 #include <vector>
22 
23 #include "core/animation/simple_spring_chain.h"
24 #include "core/components/common/layout/constants.h"
25 #include "core/components/list/layout_manager.h"
26 #include "core/components/list/render_list_item.h"
27 #include "core/components/scroll/render_scroll.h"
28 #include "core/components/scroll/scrollable.h"
29 
30 namespace OHOS::Ace {
31 
32 class ListComponent;
33 
34 constexpr int32_t INVALID_INDEX = -1;
35 constexpr int32_t ZERO_INDEX = 0;
36 
37 using RotationEventFunc = std::function<void(const RotationEvent& info)>;
38 
39 class RenderList : public RenderNode {
40     DECLARE_ACE_TYPE(RenderList, RenderNode);
41 
42 public:
43     static RefPtr<RenderNode> Create();
44 
45     void Update(const RefPtr<Component>& component) override;
46 
47     void UpdateTouchRect() override;
48 
49     void PerformLayout() override;
50 
51     void OnPaintFinish() override;
52 
53     bool TouchTest(const Point& globalPoint, const Point& parentLocalPoint, const TouchRestrict& touchRestrict,
54         TouchTestResult& result) override;
55 
56     void ResetLayoutRange(double head, double tail, Offset position, Size viewport);
57 
58     using RequestListDataFunc = std::function<void(int32_t index, int32_t count)>;
RegisterRequestItemsCallback(const RequestListDataFunc & requestItems)59     void RegisterRequestItemsCallback(const RequestListDataFunc& requestItems)
60     {
61         requestItems_ = requestItems;
62     }
63 
64     using StickyItemBuildFunc = std::function<RefPtr<RenderNode>(int32_t index, bool next)>;
RegisterStickyItemBuilderCallback(const StickyItemBuildFunc & stickyItemBuilder)65     void RegisterStickyItemBuilderCallback(const StickyItemBuildFunc& stickyItemBuilder)
66     {
67         stickyItemBuilder_ = stickyItemBuilder;
68     }
69 
70     using StickyItemSearchFunc = std::function<int32_t(int32_t index)>;
RegisterStickyItemSearcherCallback(const StickyItemSearchFunc & stickyItemSearcher)71     void RegisterStickyItemSearcherCallback(const StickyItemSearchFunc& stickyItemSearcher)
72     {
73         stickyItemSearcher_ = stickyItemSearcher;
74     }
75 
76     using RecycleByRangeFunc = std::function<bool(int32_t& from, int32_t& to)>;
RegisterRecycleByRangeCallback(const RecycleByRangeFunc & recycle)77     void RegisterRecycleByRangeCallback(const RecycleByRangeFunc& recycle)
78     {
79         recycleByRange_ = recycle;
80     }
81 
82     using RecycleByItemsFunc = std::function<bool(const std::vector<int32_t>& items)>;
RegisterRecycleByItemsCallback(const RecycleByItemsFunc & recycle)83     void RegisterRecycleByItemsCallback(const RecycleByItemsFunc& recycle)
84     {
85         recycleByItems_ = recycle;
86     }
87 
88     using BuildListDataFunc = std::function<bool(int32_t index)>;
RegisterBuildItemCallback(const BuildListDataFunc & buildItem)89     void RegisterBuildItemCallback(const BuildListDataFunc& buildItem)
90     {
91         buildItem_ = buildItem;
92     }
93 
94     using OnRefreshedFunc = std::function<void()>;
RegisterOnRefreshedCallback(const OnRefreshedFunc & onRefreshed)95     void RegisterOnRefreshedCallback(const OnRefreshedFunc& onRefreshed)
96     {
97         onRefreshed_ = onRefreshed;
98     }
99 
100     void AddListItem(int32_t index, const RefPtr<RenderNode>& renderNode);
101 
102     template<typename T>
MakeValue(double mainValue,double crossValue)103     T MakeValue(double mainValue, double crossValue) const
104     {
105         return direction_ == FlexDirection::ROW ? T(mainValue, crossValue) : T(crossValue, mainValue);
106     }
107 
SetMainSize(Size & size,double mainValue)108     void SetMainSize(Size& size, double mainValue)
109     {
110         direction_ == FlexDirection::ROW ? size.SetWidth(mainValue) : size.SetHeight(mainValue);
111     }
112 
SetCrossSize(Size & size,double crossValue)113     void SetCrossSize(Size& size, double crossValue)
114     {
115         direction_ == FlexDirection::ROW ? size.SetHeight(crossValue) : size.SetWidth(crossValue);
116     }
117 
GetMainSize(const Size & size)118     double GetMainSize(const Size& size) const
119     {
120         return direction_ == FlexDirection::ROW ? size.Width() : size.Height();
121     }
122 
GetCrossSize(const Size & size)123     double GetCrossSize(const Size& size) const
124     {
125         return direction_ == FlexDirection::ROW ? size.Height() : size.Width();
126     }
127 
GetMainPosition(const Offset & offset)128     double GetMainPosition(const Offset& offset) const
129     {
130         return direction_ == FlexDirection::ROW ? offset.GetX() : offset.GetY();
131     }
132 
IsLayoutChanged()133     bool IsLayoutChanged() const
134     {
135         return IsLayoutParamChanged();
136     }
137 
GetMaxCount()138     int32_t GetMaxCount() const
139     {
140         return maxCount_;
141     }
142 
SetMaxCount(int32_t maxCount)143     void SetMaxCount(int32_t maxCount)
144     {
145         maxCount_ = maxCount;
146     }
147 
GetCurrentMinIndex()148     int32_t GetCurrentMinIndex() const
149     {
150         int32_t currentMin = -1;
151         if (items_.begin() != items_.end()) {
152             currentMin = items_.begin()->first;
153         }
154         return currentMin;
155     }
156 
GetCurrentMaxIndex()157     int32_t GetCurrentMaxIndex() const
158     {
159         int32_t currentMax = -1;
160         if (items_.rbegin() != items_.rend()) {
161             currentMax = items_.rbegin()->first;
162         }
163         return currentMax;
164     }
165 
GetDirection()166     FlexDirection GetDirection() const
167     {
168         return direction_;
169     }
170 
GetCachedCount()171     int32_t GetCachedCount() const
172     {
173         return cachedCount_;
174     }
175 
GetBeginIndex()176     int32_t GetBeginIndex() const
177     {
178         return beginIndex_;
179     }
180 
GetEndIndex()181     int32_t GetEndIndex() const
182     {
183         return endIndex_;
184     }
185 
GetRepeatedLength()186     int32_t GetRepeatedLength() const
187     {
188         return repeatLength_;
189     }
190 
GetLength()191     int32_t GetLength() const
192     {
193         return length_;
194     }
195 
SetLength(int32_t length)196     void SetLength(int32_t length)
197     {
198         length_ = length;
199     }
200 
GetIndexOffset()201     int32_t GetIndexOffset() const
202     {
203         return indexOffset_;
204     }
205 
GetFlexAlign()206     FlexAlign GetFlexAlign() const
207     {
208         return crossAxisAlign_;
209     }
210 
GetColumnCount()211     int32_t GetColumnCount() const
212     {
213         return columnCount_;
214     }
215 
GetColumnExtent()216     int32_t GetColumnExtent() const
217     {
218         return columnExtent_;
219     }
220 
GetWidth()221     double GetWidth() const
222     {
223         return listWidth_;
224     }
225 
GetHeight()226     double GetHeight() const
227     {
228         return listHeight_;
229     }
230 
GetItemExtent()231     const Dimension& GetItemExtent() const
232     {
233         return itemExtent_;
234     }
235 
GetRightToLeft()236     bool GetRightToLeft() const
237     {
238         return rightToLeft_;
239     }
240 
GetItems()241     const std::map<int32_t, RefPtr<RenderNode>>& GetItems() const
242     {
243         return items_;
244     }
245 
ResetItems(std::map<int32_t,RefPtr<RenderNode>> & items)246     void ResetItems(std::map<int32_t, RefPtr<RenderNode>>& items)
247     {
248         items_.clear();
249         items_.swap(items);
250     }
251 
252     void CalculateStickyItem(const Offset& position);
253 
254     void RequestMoreItems(int32_t index, int32_t count);
255 
256     int32_t RequestNextFocus(bool vertical, bool reverse);
257 
258     void ListItemFocused(int32_t focusIndex);
259 
260     void MoveItemToViewPort(double position);
261 
262     void MoveItemGroupToViewPort(double position, double size);
263 
264     RefPtr<RenderListItem> GetItemByIndex(int32_t index);
265 
266     RefPtr<RenderNode> GetChildByPosition(double position) const;
267     RefPtr<RenderNode> GetNearChildByPosition(double position) const;
268     RefPtr<RenderNode> GetChildByIndex(int32_t index);
269     int32_t GetIndexByPosition(double position) const;
270     bool RecycleByRange(int32_t from, int32_t to);
271     bool RecycleByItems(const std::vector<int32_t>& items);
272     bool RecycleAllChild();
273     void RecycleHead(int32_t head);
274     void RecycleTail(int32_t tail);
275     void SyncIndex(int32_t begin, int32_t end);
276 
277     void CalculateFocusIndexPosition();
278 
279     double CalculateItemPosition(int32_t index, ScrollType type);
280 
281     void CalculateItemPosition(double targetPos);
282 
283     void MarkNeedRefresh();
284 
285     void RefreshOffset(double offset);
286 
287     void RefreshScrollExtent();
288 
289     void SetGroupState(int32_t index, bool expand);
290 
OnRefreshed()291     void OnRefreshed()
292     {
293         onRefreshed_();
294     }
295 
GetLayoutManager()296     const RefPtr<LayoutManager>& GetLayoutManager() const
297     {
298         return layoutManager_;
299     }
300 
GetItemPosition(int32_t index)301     double GetItemPosition(int32_t index) const
302     {
303         if (layoutManager_) {
304             return layoutManager_->GetItemPosition(index);
305         }
306         return 0.0;
307     }
308 
GetItemAnimationPosition(int32_t index)309     double GetItemAnimationPosition(int32_t index) const
310     {
311         if (layoutManager_) {
312             return layoutManager_->GetItemAnimationValue(index);
313         }
314         return 0.0;
315     }
316 
GetController()317     const RefPtr<ScrollPositionController>& GetController() const
318     {
319         return controller_;
320     }
321 
IsSupportScale()322     bool IsSupportScale() const
323     {
324         return itemScale_;
325     }
326 
SetSupportItemCenter(bool center)327     void SetSupportItemCenter(bool center)
328     {
329         supportItemCenter_ = center;
330     }
331 
GetSupportItemCenter()332     bool GetSupportItemCenter() const
333     {
334         return supportItemCenter_;
335     }
336 
SupportStickyItem()337     bool SupportStickyItem() const
338     {
339         return !chainAnimation_ && direction_ == FlexDirection::COLUMN;
340     }
341 
IsCenterLayout()342     bool IsCenterLayout() const
343     {
344         return isCenterLayout_;
345     }
346 
IsPageReady()347     bool IsPageReady() const
348     {
349         return pageReady_;
350     }
351 
GetAddDeleteEffect()352     bool GetAddDeleteEffect() const
353     {
354         return updateEffect_ && pageReady_;
355     }
356 
SetAddDeleteEffect(bool enabled)357     void SetAddDeleteEffect(bool enabled)
358     {
359         updateEffect_ = enabled;
360     }
361 
362     void BuildNextItem(double start, double end, Offset position, Size viewPort);
363 
SetShiftHeight(double shiftHeight)364     void SetShiftHeight(double shiftHeight)
365     {
366         shiftHeight_ = shiftHeight;
367     }
368 
369     // notify start position in global main axis
370     void NotifyDragStart(double startPosition);
371 
372     // notify drag offset in global main axis
373     void NotifyDragUpdate(double dragOffset);
374 
375     void NotifyScrollOver(double velocity, bool isCrashTop, bool isCrashBottom);
376 
IsEnableChain()377     bool IsEnableChain() const
378     {
379         return chainAnimation_;
380     }
381 
GetDragStartIndexPending()382     int32_t GetDragStartIndexPending() const
383     {
384         return dragStartIndexPending_;
385     }
386 
SetDragStartIndexPending(int32_t index)387     void SetDragStartIndexPending(int32_t index)
388     {
389         dragStartIndexPending_ = index;
390     }
391 
GetDragStartIndex()392     int32_t GetDragStartIndex() const
393     {
394         return dragStartIndex_;
395     }
396 
SetDragStartIndex(int32_t index)397     void SetDragStartIndex(int32_t index)
398     {
399         dragStartIndex_ = index;
400     }
401 
GetCurrentDelta()402     double GetCurrentDelta() const
403     {
404         return currentDelta_;
405     }
406 
407     // Reset when performLayout done.
ResetCurrentDelta()408     void ResetCurrentDelta()
409     {
410         currentDelta_ = 0.0;
411     }
412 
GetOverSpringProperty()413     const RefPtr<SpringProperty>& GetOverSpringProperty() const
414     {
415         return overSpringProperty_;
416     }
417 
GetChainProperty()418     const SpringChainProperty& GetChainProperty() const
419     {
420         return chainProperty_;
421     }
422 
FlushChainAnimation()423     double FlushChainAnimation()
424     {
425         if (!layoutManager_) {
426             return 0.0;
427         }
428         return layoutManager_->FlushChainAnimation();
429     }
430 
GetHeadAnimationValue()431     double GetHeadAnimationValue() const
432     {
433         if (chainAnimation_ && layoutManager_) {
434             return layoutManager_->GetItemAnimationValue(GetCurrentMinIndex());
435         } else {
436             return 0.0;
437         }
438     }
439 
IsVertical()440     bool IsVertical() const
441     {
442         return direction_ == FlexDirection::COLUMN || direction_ == FlexDirection::COLUMN_REVERSE;
443     }
444 
GetListPosition()445     double GetListPosition() const
446     {
447         if (layoutManager_) {
448             return IsVertical() ? layoutManager_->GetPosition().GetY() : layoutManager_->GetPosition().GetX();
449         }
450         return 0.0;
451     }
452 
EstimateIndexByPosition(double position)453     double EstimateIndexByPosition(double position) const
454     {
455         if (layoutManager_) {
456             return layoutManager_->GetIndexByPosition(position);
457         }
458         return INVALID_INDEX;
459     }
460 
GetTailAnimationValue()461     double GetTailAnimationValue() const
462     {
463         if (chainAnimation_ && layoutManager_) {
464             return GetItemAnimationPosition(GetCurrentMaxIndex());
465         } else {
466             return 0.0;
467         }
468     }
469 
SetMakeCardTransition(bool makeCardTransition)470     void SetMakeCardTransition(bool makeCardTransition)
471     {
472         makeCardTransition_ = makeCardTransition;
473     }
474 
GetCenterIndex()475     int32_t GetCenterIndex() const
476     {
477         return centerIndex_;
478     }
479 
SetCenterIndex(int32_t centerIndex)480     void SetCenterIndex(int32_t centerIndex)
481     {
482         centerIndex_ = centerIndex;
483     }
484 
NeedRefresh()485     bool NeedRefresh() const
486     {
487         return needRefresh_;
488     }
489 
SetNeedRefresh(bool needRefresh)490     void SetNeedRefresh(bool needRefresh)
491     {
492         needRefresh_ = needRefresh;
493     }
494 
495     void OnChildRemoved(const RefPtr<RenderNode>& child) override;
496     void SetOnRotateCallback(const RefPtr<ListComponent>& component);
497 
GetOnRotateCallback()498     const RotationEventFunc& GetOnRotateCallback() const
499     {
500         return rotationEvent_;
501     }
502 
503 protected:
GetStickyItem()504     RefPtr<RenderNode> GetStickyItem() const
505     {
506         return stickyItem_;
507     }
508 
GetStickyNext()509     RefPtr<RenderNode> GetStickyNext() const
510     {
511         return stickyNext_;
512     }
513 
GetStickyItemOffset()514     Offset GetStickyItemOffset() const
515     {
516         return stickyItemOffset_;
517     }
518 
GetStickyNextOffset()519     Offset GetStickyNextOffset() const
520     {
521         return stickyNextOffset_;
522     }
523 
524     double shiftHeight_ = 0.0;
525     bool makeCardTransition_ = false;
526 
527 private:
528     double GetStickyMainSize(int32_t index);
529     void CalculateStickyItemOffset(int32_t index, double position);
530     void UpdateAccessibilityAttr();
531     bool HandleActionScroll(bool forward);
532     void ResetGroupItem(const RefPtr<RenderNode>& renderNode);
533 
534     FlexDirection direction_ { FlexDirection::COLUMN };
535     FlexAlign crossAxisAlign_ = FlexAlign::STRETCH;
536 
537     int32_t cachedCount_ = 1;
538     int32_t beginIndex_ = LIST_PARAM_INVAID;
539     int32_t endIndex_ = LIST_PARAM_INVAID;
540     int32_t repeatLength_ = 0;
541     int32_t length_ = 0;
542     int32_t indexOffset_ = 0;
543     int32_t maxCount_ = 0;
544     int32_t itemsCount_ = 0;
545     // center list-item index if item center option is enabled.
546     int32_t centerIndex_ = INVALID_INDEX;
547 
548     double listWidth_ = -1.0;
549     double listHeight_ = -1.0;
550     double currentDelta_ = 0.0;
551     SpringChainProperty chainProperty_;
552     RefPtr<SpringProperty> overSpringProperty_;
553     int32_t dragStartIndexPending_ = 0;
554     int32_t dragStartIndex_ = 0;
555     int32_t columnCount_ = 0;
556     int32_t columnExtent_ = 0;
557     int32_t firstItemIndex_ = 0;
558     Dimension itemExtent_;
559     bool rightToLeft_ = false;
560     bool updateEffect_ = false;
561     bool supportItemCenter_ = false;
562     bool isCenterLayout_ = false;
563     bool pageReady_ = false;
564     bool itemScale_ = false;
565     bool chainAnimation_ = false;
566     bool needRefresh_ = false;
567 
568     std::map<int32_t, RefPtr<RenderNode>> items_;
569     RequestListDataFunc requestItems_;
570     RecycleByRangeFunc recycleByRange_;
571     RecycleByItemsFunc recycleByItems_;
572     BuildListDataFunc buildItem_;
573     OnRefreshedFunc onRefreshed_;
574     RefPtr<ScrollPositionController> controller_;
575     RefPtr<LayoutManager> layoutManager_;
576 
577     StickyItemBuildFunc stickyItemBuilder_;
578     StickyItemSearchFunc stickyItemSearcher_;
579     RefPtr<RenderNode> stickyItem_;
580     RefPtr<RenderNode> stickyNext_;
581     std::map<int32_t, double> stickyItemMap_;
582     Offset stickyItemOffset_;
583     Offset stickyNextOffset_;
584     Offset currentOffset_;
585     RotationEventFunc rotationEvent_;
586 };
587 
588 } // namespace OHOS::Ace
589 
590 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_RENDER_LIST_H
591