• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_PATTERNS_LIST_LIST_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H
18 
19 #include <tuple>
20 #include "core/animation/chain_animation.h"
21 #include "core/components_ng/pattern/list/list_accessibility_property.h"
22 #include "core/components_ng/pattern/list/list_children_main_size.h"
23 #include "core/components_ng/pattern/list/list_content_modifier.h"
24 #include "core/components_ng/pattern/list/list_event_hub.h"
25 #include "core/components_ng/pattern/list/list_item_pattern.h"
26 #include "core/components_ng/pattern/list/list_layout_algorithm.h"
27 #include "core/components_ng/pattern/list/list_layout_property.h"
28 #include "core/components_ng/pattern/list/list_paint_method.h"
29 #include "core/components_ng/pattern/list/list_position_map.h"
30 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h"
31 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h"
32 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
33 #include "core/components_ng/render/render_context.h"
34 #include "core/pipeline_ng/pipeline_context.h"
35 
36 namespace OHOS::Ace::NG {
37 class InspectorFilter;
38 
39 struct ListItemGroupPara {
40     int32_t lanes = -1;
41     int32_t itemEndIndex = -1;
42     int32_t displayStartIndex = -1;
43     int32_t displayEndIndex = -1;
44 };
45 
46 struct ListScrollTarget {
47     int32_t index = -1;
48     float extraOffset = 0.0f;
49     ScrollAlign align = ScrollAlign::START;
50     float targetOffset;
51 };
52 
53 class ListPattern : public ScrollablePattern {
54     DECLARE_ACE_TYPE(ListPattern, ScrollablePattern);
55 
56 public:
ListPattern()57     ListPattern() : ScrollablePattern(EdgeEffect::SPRING, false) {}
58     ~ListPattern() override = default;
59 
60     RefPtr<NodePaintMethod> CreateNodePaintMethod() override;
61 
CreateLayoutProperty()62     RefPtr<LayoutProperty> CreateLayoutProperty() override
63     {
64         return MakeRefPtr<ListLayoutProperty>();
65     }
66 
CreateEventHub()67     RefPtr<EventHub> CreateEventHub() override
68     {
69         return MakeRefPtr<ListEventHub>();
70     }
71 
CreateAccessibilityProperty()72     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
73     {
74         return MakeRefPtr<ListAccessibilityProperty>();
75     }
76 
UsResRegion()77     bool UsResRegion() override
78     {
79         return false;
80     }
81 
82     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override;
83 
84     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override;
85 
86     void FromJson(const std::unique_ptr<JsonValue>& json) override;
87 
88     bool UpdateCurrentOffset(float offset, int32_t source) override;
89 
90     DisplayMode GetDefaultScrollBarDisplayMode() const override;
91 
GetStartIndex()92     int32_t GetStartIndex() const
93     {
94         return startIndex_;
95     }
96 
GetEndIndex()97     int32_t GetEndIndex() const
98     {
99         return endIndex_;
100     }
101 
GetMaxListItemIndex()102     int32_t GetMaxListItemIndex() const
103     {
104         return maxListItemIndex_;
105     }
106 
IsScrollable()107     bool IsScrollable() const override
108     {
109         return isScrollable_;
110     }
111 
SetMaintainVisibleContentPosition(bool enabled)112     void SetMaintainVisibleContentPosition(bool enabled)
113     {
114         maintainVisibleContentPosition_ = enabled;
115     }
116 
GetMaintainVisibleContentPosition()117     bool GetMaintainVisibleContentPosition()
118     {
119         return maintainVisibleContentPosition_;
120     }
121 
MarkNeedReEstimateOffset()122     void MarkNeedReEstimateOffset()
123     {
124         needReEstimateOffset_ = true;
125     }
126 
127     void NotifyDataChange(int32_t index, int32_t count) override;
128 
129     bool IsAtTop() const override;
130     bool IsAtBottom() const override;
131     void OnTouchDown(const TouchEventInfo& info) override;
132     OverScrollOffset GetOutBoundaryOffset(float delta, bool useChainDelta = true) const;
133     OverScrollOffset GetOverScrollOffset(double delta) const override;
134     float GetOffsetWithLimit(float offset) const override;
135     void HandleScrollBarOutBoundary();
136 
GetFocusPattern()137     FocusPattern GetFocusPattern() const override
138     {
139         return { FocusType::SCOPE, true };
140     }
141 
GetScopeFocusAlgorithm()142     ScopeFocusAlgorithm GetScopeFocusAlgorithm() override
143     {
144         auto property = GetLayoutProperty<ListLayoutProperty>();
145         if (!property) {
146             return {};
147         }
148         return ScopeFocusAlgorithm(property->GetListDirection().value_or(Axis::VERTICAL) == Axis::VERTICAL, true,
149             ScopeType::OTHERS,
150             [wp = WeakClaim(this)](
151                 FocusStep step, const WeakPtr<FocusHub>& currFocusNode, WeakPtr<FocusHub>& nextFocusNode) -> bool {
152                 auto list = wp.Upgrade();
153                 if (list) {
154                     nextFocusNode = list->GetNextFocusNode(step, currFocusNode);
155                 }
156                 return nextFocusNode.Upgrade() != currFocusNode.Upgrade();
157             });
158     }
159 
160     ScrollOffsetAbility GetScrollOffsetAbility() override;
161 
162     std::function<bool(int32_t)> GetScrollIndexAbility() override;
163 
164     bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override;
165 
GetItemPosition()166     const ListLayoutAlgorithm::PositionMap& GetItemPosition() const
167     {
168         return itemPosition_;
169     }
170 
GetTotalOffset()171     float GetTotalOffset() const override
172     {
173         return currentOffset_;
174     }
175 
GetContentStartOffset()176     float GetContentStartOffset() const override
177     {
178         return contentStartOffset_;
179     }
180 
GetPositionController()181     RefPtr<ScrollControllerBase> GetPositionController() const
182     {
183         return positionController_;
184     }
185 
186     int32_t ProcessAreaVertical(double& x, double& y, Rect& groupRect, int32_t& index,
187         RefPtr<ListItemGroupPattern> groupItemPattern) const;
188     int32_t ProcessAreaHorizontal(double& x, double& y, Rect& groupRect, int32_t& index,
189         RefPtr<ListItemGroupPattern> groupItemPattern) const;
190     void TriggerModifyDone();
191 
192     float GetTotalHeight() const override;
193 
194     // scroller
195     void ScrollTo(float position) override;
196     void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START,
197         std::optional<float> extraOffset = std::nullopt) override;
198     void ScrollToItemInGroup(int32_t index, int32_t indexInGroup, bool smooth = false,
199         ScrollAlign align = ScrollAlign::START);
200     bool CheckTargetValid(int32_t index, int32_t indexInGroup);
201     void ScrollPage(bool reverse, bool smooth = false,
202         AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL) override;
203     void ScrollBy(float offset);
204     bool AnimateToTarget(int32_t index, std::optional<int32_t> indexInGroup, ScrollAlign align);
205     Offset GetCurrentOffset() const;
206     Rect GetItemRect(int32_t index) const override;
207     int32_t GetItemIndex(double x, double y) const override;
208     Rect GetItemRectInGroup(int32_t index, int32_t indexInGroup) const;
209     ListItemIndex GetItemIndexInGroup(double x, double y) const;
210     bool GetGroupItemIndex(double x, double y, RefPtr<FrameNode> itemFrameNode, int32_t& index,
211         ListItemIndex& itemIndex) const;
212     void OnAnimateStop() override;
GetMainContentSize()213     float GetMainContentSize() const override
214     {
215         return contentMainSize_;
216     }
GetLanes()217     int32_t GetLanes() const
218     {
219         return lanes_;
220     }
221 
222     void UpdatePosMapStart(float delta);
223     void UpdatePosMapEnd();
224     void CalculateCurrentOffset(float delta, const ListLayoutAlgorithm::PositionMap& recycledItemPosition);
225     void UpdateScrollBarOffset() override;
226     // chain animation
227     void SetChainAnimation();
228     void SetChainAnimationOptions(const ChainAnimationOptions& options);
229     float FlushChainAnimation(float dragOffset);
230     void ProcessDragStart(float startPosition);
231     void ProcessDragUpdate(float dragOffset, int32_t source);
232     float GetChainDelta(int32_t index) const;
233 
234     // multiSelectable
SetMultiSelectable(bool multiSelectable)235     void SetMultiSelectable(bool multiSelectable)
236     {
237         multiSelectable_ = multiSelectable;
238     }
239 
240     void SetSwiperItem(WeakPtr<ListItemPattern> swiperItem);
GetSwiperItem()241     WeakPtr<ListItemPattern> GetSwiperItem()
242     {
243         if (!swiperItem_.Upgrade()) {
244             return nullptr;
245         }
246         return swiperItem_;
247     }
SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem)248     void SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem)
249     {
250         if (swiperItem == swiperItem_) {
251             canReplaceSwiperItem_ = true;
252         }
253     }
IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem)254     bool IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem)
255     {
256         if (!swiperItem_.Upgrade()) {
257             return true;
258         }
259         return swiperItem == swiperItem_;
260     }
CanReplaceSwiperItem()261     bool CanReplaceSwiperItem()
262     {
263         auto listItemPattern = swiperItem_.Upgrade();
264         if (!listItemPattern) {
265             canReplaceSwiperItem_ = true;
266             return canReplaceSwiperItem_;
267         }
268         auto host = listItemPattern->GetHost();
269         if (!host || !host->IsOnMainTree()) {
270             canReplaceSwiperItem_ = true;
271             return canReplaceSwiperItem_;
272         }
273         return canReplaceSwiperItem_;
274     }
275 
SetPredictSnapOffset(float predictSnapOffset)276     void SetPredictSnapOffset(float predictSnapOffset)
277     {
278         predictSnapOffset_ = predictSnapOffset;
279     }
280     bool OnScrollSnapCallback(double targetOffset, double velocity) override;
281 
282     int32_t GetItemIndexByPosition(float xOffset, float yOffset);
283 
SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param)284     void SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param)
285     {
286         predictLayoutParam_ = param;
287     }
GetPredictLayoutParam()288     std::optional<ListPredictLayoutParam> GetPredictLayoutParam() const
289     {
290         return predictLayoutParam_;
291     }
292 
SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param)293     void SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param)
294     {
295         predictLayoutParamV2_ = param;
296     }
297 
GetPredictLayoutParamV2()298     std::optional<ListPredictLayoutParamV2> GetPredictLayoutParamV2() const
299     {
300         return predictLayoutParamV2_;
301     }
302 
303     void CloseAllSwipeActions(OnFinishFunc&&);
304 
305     std::string ProvideRestoreInfo() override;
306     void OnRestoreInfo(const std::string& restoreInfo) override;
307     void DumpAdvanceInfo() override;
308 
SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection)309     void SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection)
310     {
311         isNeedToUpdateListDirection_ = isNeedToUpdateListDirection;
312     }
313 
IsNeedToUpdateListDirectionInCardStyle()314     bool IsNeedToUpdateListDirectionInCardStyle() const
315     {
316         return isNeedToUpdateListDirection_;
317     }
318 
319     std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems() override;
320 
SetItemPressed(bool isPressed,int32_t id)321     void SetItemPressed(bool isPressed, int32_t id)
322     {
323         if (isPressed) {
324             pressedItem_.emplace(id);
325         } else {
326             pressedItem_.erase(id);
327         }
328     }
329 
330     RefPtr<ListChildrenMainSize> GetOrCreateListChildrenMainSize();
331     void SetListChildrenMainSize(float defaultSize, const std::vector<float>& mainSize);
332     void OnChildrenSizeChanged(std::tuple<int32_t, int32_t, int32_t> change, ListChangeFlag flag);
333     void ResetChildrenSize();
ListChildrenSizeExist()334     bool ListChildrenSizeExist()
335     {
336         return static_cast<bool>(childrenSize_);
337     }
CanOverScroll(int32_t source)338     bool CanOverScroll(int32_t source) override
339     {
340         auto canOverScroll = (IsScrollableSpringEffect() && source != SCROLL_FROM_AXIS && source != SCROLL_FROM_BAR &&
341             IsScrollable() && (!ScrollableIdle() || animateOverScroll_ || animateCanOverScroll_) &&
342             (IsAtBottom() || IsAtTop()));
343         if (canOverScroll != lastCanOverScroll_) {
344             lastCanOverScroll_ = canOverScroll;
345             AddScrollableFrameInfo(source);
346         }
347         return canOverScroll;
348     }
349     void UpdateChildPosInfo(int32_t index, float delta, float sizeChange);
350 
351     SizeF GetChildrenExpandedSize() override;
352 private:
353 
IsNeedInitClickEventRecorder()354     bool IsNeedInitClickEventRecorder() const override
355     {
356         return true;
357     }
358 
359     void OnScrollEndCallback() override;
360     void FireOnReachStart(const OnReachEvent& onReachStart) override;
361     void FireOnReachEnd(const OnReachEvent& onReachEnd) override;
362     void FireOnScrollIndex(bool indexChanged, const OnScrollIndexEvent& onScrollIndex);
363     void OnModifyDone() override;
364     void ChangeAxis(RefPtr<UINode> node);
365     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
366     float CalculateTargetPos(float startPos, float endPos);
367 
368     void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub);
369     bool OnKeyEvent(const KeyEvent& event);
370     bool HandleDirectionKey(const KeyEvent& event);
371     WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode);
372     WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarMainIndex, int32_t tarGroupIndex);
373     WeakPtr<FocusHub> ScrollAndFindFocusNode(int32_t nextIndex, int32_t curIndex, int32_t& nextIndexInGroup,
374         int32_t curIndexInGroup, int32_t moveStep, FocusStep step);
375     bool ScrollListForFocus(int32_t nextIndex, int32_t curIndex, int32_t nextIndexInGroup);
376     bool ScrollListItemGroupForFocus(int32_t nextIndex, int32_t& nextIndexInGroup, int32_t curIndexInGroup,
377         int32_t moveStep, FocusStep step, bool isScrollIndex);
378 
379     void MarkDirtyNodeSelf();
380     SizeF GetContentSize() const;
381     void ProcessEvent(bool indexChanged, float finalOffset, bool isJump);
382     void CheckScrollable();
383     bool IsOutOfBoundary(bool useCurrentDelta = true) override;
384     bool OnScrollCallback(float offset, int32_t source) override;
385     void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override;
386     void HandleScrollEffect(float offset);
387     void StartDefaultOrCustomSpringMotion(float start, float end, const RefPtr<InterpolatingSpring>& curve);
388     bool IsScrollSnapAlignCenter() const;
389     void SetChainAnimationCallback();
390     void SetChainAnimationToPosMap();
391     void SetChainAnimationLayoutAlgorithm(
392         RefPtr<ListLayoutAlgorithm> listLayoutAlgorithm, RefPtr<ListLayoutProperty> listLayoutProperty);
393     bool NeedScrollSnapAlignEffect() const;
394     ScrollAlign GetScrollAlignByScrollSnapAlign() const;
395     bool GetListItemAnimatePos(float startPos, float endPos, ScrollAlign align, float& targetPos);
396     bool GetListItemGroupAnimatePosWithoutIndexInGroup(int32_t index, float startPos, float endPos,
397         ScrollAlign align, float& targetPos);
398     bool GetListItemGroupAnimatePosWithIndexInGroup(int32_t index, int32_t indexInGroup, float startPos,
399         ScrollAlign align, float& targetPos);
400 
401     // multiSelectable
402     void ClearMultiSelect() override;
403     bool IsItemSelected(const GestureEvent& info) override;
404     void MultiSelectWithoutKeyboard(const RectF& selectedZone) override;
405     void HandleCardModeSelectedEvent(
406         const RectF& selectedZone, const RefPtr<FrameNode>& itemGroupNode, float itemGroupTop);
407 
408     void DrivenRender(const RefPtr<LayoutWrapper>& layoutWrapper);
409     ListItemGroupPara GetListItemGroupParameter(const RefPtr<FrameNode>& node);
410     bool IsListItemGroup(int32_t listIndex, RefPtr<FrameNode>& node);
411     void GetListItemGroupEdge(bool& groupAtStart, bool& groupAtEnd) const;
412     void RefreshLanesItemRange();
413     void UpdateListDirectionInCardStyle();
414     bool UpdateStartListItemIndex();
415     bool UpdateEndListItemIndex();
416     float GetStartOverScrollOffset(float offset, float startMainPos) const;
417     float GetEndOverScrollOffset(float offset, float endMainPos, float startMainPos) const;
418     float UpdateTotalOffset(const RefPtr<ListLayoutAlgorithm>& listLayoutAlgorithm, bool isJump);
419     RefPtr<ListContentModifier> listContentModifier_;
420 
421     int32_t maxListItemIndex_ = 0;
422     int32_t startIndex_ = -1;
423     int32_t endIndex_ = -1;
424     int32_t centerIndex_ = -1;
425     float startMainPos_ = 0.0f;
426     float endMainPos_ = 0.0f;
427     float prevStartOffset_ = 0.f;
428     float prevEndOffset_ = 0.f;
429     float currentOffset_ = 0.0f;
430     float spaceWidth_ = 0.0f;
431     float contentMainSize_ = 0.0f;
432     float contentStartOffset_ = 0.0f;
433     float contentEndOffset_ = 0.0f;
434     bool maintainVisibleContentPosition_ = false;
435 
436     float currentDelta_ = 0.0f;
437     bool crossMatchChild_ = false;
438     bool smooth_ = false;
439     float scrollSnapVelocity_ = 0.0f;
440     bool snapTrigOnScrollStart_ = false;
441 
442     std::optional<int32_t> jumpIndex_;
443     std::optional<int32_t> jumpIndexInGroup_;
444     std::optional<int32_t> targetIndex_;
445     std::optional<int32_t> targetIndexInGroup_;
446     std::optional<ListScrollTarget> scrollTarget_;
447     std::optional<float> predictSnapOffset_;
448     std::optional<float> predictSnapEndPos_;
449     ScrollAlign scrollAlign_ = ScrollAlign::START;
450     bool isScrollable_ = true;
451     bool paintStateFlag_ = false;
452     bool isFramePaintStateValid_ = false;
453     bool isNeedCheckOffset_ = false;
454 
455     ListLayoutAlgorithm::PositionMap itemPosition_;
456     ListLayoutAlgorithm::PositionMap cachedItemPosition_;
457     RefPtr<ListPositionMap> posMap_;
458     RefPtr<ListChildrenMainSize> childrenSize_;
459     float listTotalHeight_ = 0.0f;
460 
461     std::map<int32_t, int32_t> lanesItemRange_;
462     std::set<int32_t> pressedItem_;
463     int32_t lanes_ = 1;
464     float laneGutter_ = 0.0f;
465     // chain animation
466     RefPtr<ChainAnimation> chainAnimation_;
467     bool dragFromSpring_ = false;
468     RefPtr<SpringProperty> springProperty_;
469     std::optional<ChainAnimationOptions> chainAnimationOptions_;
470 
471     bool isOritationListenerRegisted_ = false;
472 
473     // ListItem swiperAction
474     WeakPtr<ListItemPattern> swiperItem_;
475     bool canReplaceSwiperItem_ = true;
476 
477     RefPtr<SpringMotion> scrollToIndexMotion_;
478     RefPtr<SpringMotion> scrollSnapMotion_;
479     RefPtr<Scrollable> scrollable_;
480 
481     bool isScrollEnd_ = false;
482     bool needReEstimateOffset_ = false;
483     std::optional<ListPredictLayoutParam> predictLayoutParam_;
484     std::optional<ListPredictLayoutParamV2> predictLayoutParamV2_;
485 
486     bool isNeedToUpdateListDirection_ = false;
487     bool startIndexChanged_ = false;
488     bool endIndexChanged_ = false;
489 
490     ListItemIndex startInfo_ = {-1, -1, -1};
491     ListItemIndex endInfo_ = {-1, -1, -1};
492 };
493 } // namespace OHOS::Ace::NG
494 
495 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H
496