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_LIST_COMPONENT_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_LIST_COMPONENT_H
18 
19 #include "base/utils/macros.h"
20 #include "core/animation/simple_spring_chain.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components/common/properties/scroll_bar.h"
23 #include "core/components/common/rotation/rotation_controller.h"
24 #include "core/components/list/list_element.h"
25 #include "core/components/list/list_item_component.h"
26 #include "core/components/list/list_theme.h"
27 #include "core/components/list/render_list.h"
28 #include "core/components/scroll/scroll_edge_effect.h"
29 #include "core/components/scroll/scroll_position_controller.h"
30 #include "core/pipeline/base/component_group.h"
31 
32 namespace OHOS::Ace {
33 
34 inline constexpr int32_t INDEX_EXPAND_ALL = -999;
35 
36 class ACE_EXPORT ListComponent : public ComponentGroup {
37     DECLARE_ACE_TYPE(ListComponent, ComponentGroup);
38 
39 public:
40     ListComponent() = default;
41     explicit ListComponent(const std::list<RefPtr<Component>>& children);
42     ~ListComponent() override = default;
43 
44     void InsertChild(int32_t position, const RefPtr<Component>& child) override;
45     void AppendChild(const RefPtr<Component>& child) override;
46     void RemoveChild(const RefPtr<Component>& child) override;
47     void SetGroupState(int32_t expandIndex, bool expand);
48 
49     RefPtr<Element> CreateElement() override;
50     RefPtr<RenderNode> CreateRenderNode() override;
51 
SetScrollPage(bool scrollPage)52     void SetScrollPage(bool scrollPage)
53     {
54         scrollPage_ = scrollPage;
55     }
56 
SetChainAnimation(bool chainAnimation)57     void SetChainAnimation(bool chainAnimation)
58     {
59         chainAnimation_ = chainAnimation;
60     }
61 
SetOnScroll(const EventMarker & onScroll)62     void SetOnScroll(const EventMarker& onScroll)
63     {
64         onScroll_ = onScroll;
65     }
66 
SetOnScrollBottom(const EventMarker & onScrollBottom)67     void SetOnScrollBottom(const EventMarker& onScrollBottom)
68     {
69         onScrollBottom_ = onScrollBottom;
70     }
71 
SetOnScrollTop(const EventMarker & onScrollTop)72     void SetOnScrollTop(const EventMarker& onScrollTop)
73     {
74         onScrollTop_ = onScrollTop;
75     }
76 
SetOnScrollEnd(const EventMarker & onScrollEnd)77     void SetOnScrollEnd(const EventMarker& onScrollEnd)
78     {
79         onScrollEnd_ = onScrollEnd;
80     }
81 
SetOnScrollTouchUp(const EventMarker & onScrollTouchUp)82     void SetOnScrollTouchUp(const EventMarker& onScrollTouchUp)
83     {
84         onScrollTouchUp_ = onScrollTouchUp;
85     }
86 
GetScrollPage()87     bool GetScrollPage() const
88     {
89         return scrollPage_;
90     }
91 
GetChainAnimation()92     bool GetChainAnimation() const
93     {
94         return chainAnimation_;
95     }
96 
GetDirection()97     FlexDirection GetDirection() const
98     {
99         return direction_;
100     }
101 
SetDirection(FlexDirection direction)102     void SetDirection(FlexDirection direction)
103     {
104         direction_ = direction;
105     }
106 
GetTotalCount()107     int32_t GetTotalCount() const
108     {
109         return totalCount_;
110     }
111 
GetItemsCount()112     int32_t GetItemsCount() const
113     {
114         return GetChildren().size();
115     }
116 
SetTotalCount(int32_t totalCount)117     void SetTotalCount(int32_t totalCount)
118     {
119         if (totalCount < 0) {
120             LOGE("Invalid TotalCount %{public}d", totalCount);
121             return;
122         }
123         totalCount_ = totalCount;
124     }
125 
GetOnRequestItem()126     const EventMarker& GetOnRequestItem() const
127     {
128         return onRequestItem_;
129     }
130 
SetOnRequestItem(const EventMarker & onRequestItem)131     void SetOnRequestItem(const EventMarker& onRequestItem)
132     {
133         onRequestItem_ = onRequestItem;
134     }
135 
GetCachedCount()136     int32_t GetCachedCount() const
137     {
138         return cachedCount_;
139     }
140 
GetBeginIndex()141     int32_t GetBeginIndex() const
142     {
143         return beginIndex_;
144     }
145 
GetEndIndex()146     int32_t GetEndIndex() const
147     {
148         return endIndex_;
149     }
150 
GetRepeatedLength()151     int32_t GetRepeatedLength() const
152     {
153         return repeatedLength_;
154     }
155 
GetIndexOffset()156     int32_t GetIndexOffset() const
157     {
158         return indexOffset_;
159     }
160 
SetCachedCount(int32_t cachedCount)161     void SetCachedCount(int32_t cachedCount)
162     {
163         if (cachedCount <= 0) {
164             LOGE("Invalid CachedCount %{public}d", cachedCount);
165             return;
166         }
167         cachedCount_ = cachedCount;
168     }
169 
SetBeginIndex(int32_t beginIndex)170     void SetBeginIndex(int32_t beginIndex)
171     {
172         beginIndex_ = beginIndex;
173     }
174 
SetEndIndex(int32_t endIndex)175     void SetEndIndex(int32_t endIndex)
176     {
177         endIndex_ = endIndex;
178     }
179 
SetRepeatedLength(int32_t repeatedLength)180     void SetRepeatedLength(int32_t repeatedLength)
181     {
182         repeatedLength_ = repeatedLength;
183     }
184 
SetIndexOffset(int32_t indexOffset)185     void SetIndexOffset(int32_t indexOffset)
186     {
187         indexOffset_ = indexOffset;
188     }
189 
GetPositionController()190     RefPtr<ScrollPositionController> GetPositionController() const
191     {
192         return positionController_;
193     }
194 
SetPositionController(const RefPtr<ScrollPositionController> & controller)195     void SetPositionController(const RefPtr<ScrollPositionController>& controller)
196     {
197         positionController_ = controller;
198     }
199 
GetScrollEffect()200     const RefPtr<ScrollEdgeEffect>& GetScrollEffect() const
201     {
202         return scrollEffect_;
203     }
204 
SetScrollEffect(const RefPtr<ScrollEdgeEffect> & scrollEffect)205     void SetScrollEffect(const RefPtr<ScrollEdgeEffect>& scrollEffect)
206     {
207         scrollEffect_ = scrollEffect;
208     }
209 
GetOnScroll()210     const EventMarker& GetOnScroll() const
211     {
212         return onScroll_;
213     }
214 
GetOnScrollBottom()215     const EventMarker& GetOnScrollBottom() const
216     {
217         return onScrollBottom_;
218     }
219 
GetOnScrollTop()220     const EventMarker& GetOnScrollTop() const
221     {
222         return onScrollTop_;
223     }
224 
GetOnScrollEnd()225     const EventMarker& GetOnScrollEnd() const
226     {
227         return onScrollEnd_;
228     }
229 
GetOnScrollTouchUp()230     const EventMarker& GetOnScrollTouchUp() const
231     {
232         return onScrollTouchUp_;
233     }
234 
235     void InitStyle(const RefPtr<ListTheme>& theme);
236 
GetGradientWidth()237     const Dimension& GetGradientWidth() const
238     {
239         return gradientWidth_;
240     }
241 
SetGradientWidth(const Dimension & gradientWidth)242     void SetGradientWidth(const Dimension& gradientWidth)
243     {
244         if (gradientWidth.Value() < 0.0) {
245             LOGE("Invalid GradientWidth %{public}lf", gradientWidth_.Value());
246             return;
247         }
248         gradientWidth_ = gradientWidth;
249     }
250 
GetBackgroundColor()251     const Color& GetBackgroundColor() const
252     {
253         return backgroundColor_;
254     }
255 
SetBackgroundColor(const Color & backgroundColor)256     void SetBackgroundColor(const Color& backgroundColor)
257     {
258         backgroundColor_ = backgroundColor;
259     }
260 
261     void SetFlexAlign(FlexAlign flexAlign);
262 
263     void SetColumnCount(int32_t count);
264 
265     void SetColumnExtent(int32_t extent);
266 
267     void SetItemExtent(const Dimension& itemExtent);
268 
269     void SetWidth(double width);
270 
271     void SetHeight(double height);
272 
SetInRefresh(bool inRefresh)273     void SetInRefresh(bool inRefresh)
274     {
275         inRefresh_ = inRefresh;
276     }
277 
SetSupportItemCenter(bool center)278     void SetSupportItemCenter(bool center)
279     {
280         supportItemCenter_ = center;
281     }
282 
GetSupportItemCenter()283     bool GetSupportItemCenter() const
284     {
285         return supportItemCenter_;
286     }
287 
GetFlexAlign()288     FlexAlign GetFlexAlign() const
289     {
290         return flexAlign_;
291     }
292 
GetColumnCount()293     int32_t GetColumnCount() const
294     {
295         return columnCount_;
296     }
297 
GetColumnExtent()298     int32_t GetColumnExtent() const
299     {
300         return columnExtent_;
301     }
302 
GetItemExtent()303     const Dimension& GetItemExtent() const
304     {
305         return itemExtent_;
306     }
307 
GetWidth()308     double GetWidth() const
309     {
310         return width_;
311     }
312 
GetHeight()313     double GetHeight() const
314     {
315         return height_;
316     }
317 
NeedPreBuild()318     bool NeedPreBuild() const
319     {
320         return needPreBuild_;
321     }
322 
NeedUpdateElement()323     bool NeedUpdateElement() const
324     {
325         return needUpdateElement_;
326     }
327 
IsInRefresh()328     bool IsInRefresh() const
329     {
330         return inRefresh_;
331     }
332 
MarkNeedUpdateElement(bool needUpdateElement)333     void MarkNeedUpdateElement(bool needUpdateElement)
334     {
335         needUpdateElement_ = needUpdateElement;
336     }
337 
SetScrollBar(const RefPtr<ScrollBar> & scrollBar)338     void SetScrollBar(const RefPtr<ScrollBar>& scrollBar)
339     {
340         scrollBar_ = scrollBar;
341     }
342 
GetScrollBar()343     RefPtr<ScrollBar> GetScrollBar() const
344     {
345         return scrollBar_;
346     }
347 
SetRightToLeft(bool rightToLeft)348     void SetRightToLeft(bool rightToLeft)
349     {
350         rightToLeft_ = rightToLeft;
351     }
352 
GetRightToLeft()353     bool GetRightToLeft() const
354     {
355         return rightToLeft_;
356     }
357 
SetUpdateEffect(bool updateEffect)358     void SetUpdateEffect(bool updateEffect)
359     {
360         updateEffect_ = updateEffect;
361     }
362 
GetUpdateEffect()363     bool GetUpdateEffect() const
364     {
365         return updateEffect_;
366     }
367 
UpdateListItemIndex()368     void UpdateListItemIndex()
369     {
370         int32_t index = 0; // Update the item index by the order in list.
371         for (const auto& iter : GetChildren()) {
372             auto listItemComponent = ListItemComponent::GetListItem(iter);
373             if (listItemComponent) {
374                 listItemComponent->SetIndex(index++);
375             }
376         }
377     }
378 
SetPageReady(bool pageReady)379     void SetPageReady(bool pageReady)
380     {
381         pageReady_ = pageReady;
382     }
383 
GetPageReady()384     bool GetPageReady() const
385     {
386         return pageReady_;
387     }
388 
IsCenterLayout()389     bool IsCenterLayout() const
390     {
391         return isCenterLayout_;
392     }
393 
MarkCenterLayout(bool isCenter)394     void MarkCenterLayout(bool isCenter)
395     {
396         isCenterLayout_ = isCenter;
397     }
398 
IsItemScale()399     bool IsItemScale() const
400     {
401         return itemScale_;
402     }
403 
SetItemScale(bool itemScale)404     void SetItemScale(bool itemScale)
405     {
406         itemScale_ = itemScale;
407     }
408 
GetRotationController()409     const RefPtr<RotationController>& GetRotationController() const
410     {
411         return rotationController_;
412     }
413 
SetChainProperty(const SpringChainProperty & property)414     void SetChainProperty(const SpringChainProperty& property)
415     {
416         chainProperty_ = property;
417     }
418 
GetChainProperty()419     const SpringChainProperty& GetChainProperty() const
420     {
421         return chainProperty_;
422     }
423 
SetOverSpringProperty(const RefPtr<SpringProperty> & property)424     void SetOverSpringProperty(const RefPtr<SpringProperty>& property)
425     {
426         if (property && property->IsValid()) {
427             overSpringProperty_ = property;
428         }
429     }
430 
SetOverSpringProperty(double mass,double stiffness,double damping)431     void SetOverSpringProperty(double mass, double stiffness, double damping)
432     {
433         overSpringProperty_ = AceType::MakeRefPtr<SpringProperty>(mass, stiffness, damping);
434     }
435 
OverSpringProperty()436     const RefPtr<SpringProperty>& OverSpringProperty()
437     {
438         return overSpringProperty_;
439     }
440 
NeedDivider()441     bool NeedDivider() const
442     {
443         return needDivider_;
444     }
445 
MarkNeedDivider(bool needDivider)446     void MarkNeedDivider(bool needDivider)
447     {
448         needDivider_ = needDivider;
449     }
450 
GetDividerOrigin()451     const Dimension& GetDividerOrigin() const
452     {
453         return dividerOrigin_;
454     }
455 
SetDividerOrigin(const Dimension & origin)456     void SetDividerOrigin(const Dimension& origin)
457     {
458         dividerOrigin_ = origin;
459     }
460 
GetDividerLength()461     const Dimension& GetDividerLength() const
462     {
463         return dividerLength_;
464     }
465 
SetDividerLength(const Dimension & length)466     void SetDividerLength(const Dimension& length)
467     {
468         dividerLength_ = length;
469     }
470 
GetDividerColor()471     const Color& GetDividerColor() const
472     {
473         return dividerColor_;
474     }
475 
SetDividerColor(const Color & color)476     void SetDividerColor(const Color& color)
477     {
478         dividerColor_ = color;
479     }
480 
GetDividerHeight()481     const Dimension& GetDividerHeight() const
482     {
483         return dividerHeight_;
484     }
485 
SetDividerHeight(const Dimension & dividerHeight)486     void SetDividerHeight(const Dimension& dividerHeight)
487     {
488         dividerHeight_ = dividerHeight;
489     }
490 
GetOnRotateId()491     const EventMarker& GetOnRotateId() const
492     {
493         return onRotateId_;
494     }
495 
SetOnRotateId(const EventMarker & onRotateId)496     void SetOnRotateId(const EventMarker& onRotateId)
497     {
498         onRotateId_ = onRotateId;
499     }
500 
SetScrollVibrate(bool scrollVibrate)501     void SetScrollVibrate(bool scrollVibrate)
502     {
503         scrollVibrate_ = scrollVibrate;
504     }
505 
GetScrollVibrate()506     bool GetScrollVibrate()
507     {
508         return scrollVibrate_;
509     }
510 
IsRotationVibrate()511     bool IsRotationVibrate() const
512     {
513         return rotationVibrate_;
514     }
515 
MarkNeedRotationVibrate(bool needVibrate)516     void MarkNeedRotationVibrate(bool needVibrate)
517     {
518         rotationVibrate_ = needVibrate;
519     }
520 
SetAccessibilityDisabled(bool disable)521     void SetAccessibilityDisabled(bool disable)
522     {
523         accessibilityDisabled_ = disable;
524     }
525 
IsAccessibilityDisabled()526     bool IsAccessibilityDisabled() const
527     {
528         return accessibilityDisabled_;
529     }
530 
531 private:
532     EventMarker onRequestItem_;
533     EventMarker onScroll_;
534     EventMarker onScrollBottom_;
535     EventMarker onScrollTop_;
536     EventMarker onScrollEnd_;
537     EventMarker onScrollTouchUp_;
538     EventMarker onRotateId_;
539     Dimension gradientWidth_;
540     Color backgroundColor_ = Color::WHITE;
541     FlexDirection direction_ = FlexDirection::COLUMN;
542     bool scrollPage_ { false };
543     bool chainAnimation_ { false };
544     int32_t totalCount_ { 0 };
545     int32_t cachedCount_ { 1 }; // the default value of cached child number.
546     int32_t beginIndex_ { LIST_PARAM_INVAID };
547     int32_t endIndex_ { LIST_PARAM_INVAID };
548     int32_t repeatedLength_ { 0 };
549     int32_t indexOffset_ { 0 };
550     RefPtr<ScrollPositionController> positionController_;
551     RefPtr<RotationController> rotationController_ = AceType::MakeRefPtr<RotationController>();
552     RefPtr<ScrollEdgeEffect> scrollEffect_;
553     FlexAlign flexAlign_ { FlexAlign::STRETCH };
554     double width_ { DEFAULT_GRID_WIDTH };
555     double height_ { DEFAULT_GRID_HEIGHT };
556     int32_t columnCount_ { DEFAULT_COLUMN_COUNT };
557     int32_t columnExtent_ { DEFAULT_COLUMN_EXTENT };
558     Dimension itemExtent_;
559     bool needPreBuild_ = false;
560     bool needUpdateElement_ = false;
561     bool rightToLeft_ = false;
562     RefPtr<ScrollBar> scrollBar_;
563     bool inRefresh_ = false;
564     bool supportItemCenter_ = false;
565     bool updateEffect_ = false;
566     bool pageReady_ = false;
567     bool itemScale_ = false;
568     bool isCenterLayout_ = false;
569     SpringChainProperty chainProperty_;
570     RefPtr<SpringProperty> overSpringProperty_;
571     WeakPtr<ListElement> listElement_;
572 
573     // divider style
574     Dimension dividerOrigin_;
575     Dimension dividerLength_;
576     Dimension dividerHeight_ = DIVIDER_DEFAULT_HEIGHT;
577     Color dividerColor_;
578     bool needDivider_ = false;
579 
580     bool scrollVibrate_ = true;
581     bool rotationVibrate_ = false;
582     bool accessibilityDisabled_ = false;
583 };
584 
585 } // namespace OHOS::Ace
586 
587 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_LIST_COMPONENT_H
588