• 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(bool useCurrentDelta) 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) {
152                 auto list = wp.Upgrade();
153                 if (list) {
154                     nextFocusNode = list->GetNextFocusNode(step, currFocusNode);
155                 }
156             });
157     }
158 
159     std::pair<std::function<bool(float)>, Axis> GetScrollOffsetAbility() override;
160 
161     std::function<bool(int32_t)> GetScrollIndexAbility() override;
162 
163     bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override;
164 
GetItemPosition()165     const ListLayoutAlgorithm::PositionMap& GetItemPosition() const
166     {
167         return itemPosition_;
168     }
169 
GetTotalOffset()170     float GetTotalOffset() const override
171     {
172         return currentOffset_;
173     }
174 
GetPositionController()175     RefPtr<ScrollControllerBase> GetPositionController() const
176     {
177         return positionController_;
178     }
179 
180     void TriggerModifyDone();
181 
182     float GetTotalHeight() const override;
183 
184     // scroller
185     void ScrollTo(float position) override;
186     void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START,
187         std::optional<float> extraOffset = std::nullopt) override;
188     void ScrollToItemInGroup(int32_t index, int32_t indexInGroup, bool smooth = false,
189         ScrollAlign align = ScrollAlign::START);
190     bool CheckTargetValid(int32_t index, int32_t indexInGroup);
191     bool ScrollPage(bool reverse, AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL);
192     void ScrollBy(float offset);
193     bool AnimateToTarget(int32_t index, std::optional<int32_t> indexInGroup, ScrollAlign align);
194     Offset GetCurrentOffset() const;
195     Rect GetItemRect(int32_t index) const override;
196     Rect GetItemRectInGroup(int32_t index, int32_t indexInGroup) const;
197     void OnAnimateStop() override;
GetMainContentSize()198     float GetMainContentSize() const override
199     {
200         return contentMainSize_;
201     }
GetLanes()202     int32_t GetLanes() const
203     {
204         return lanes_;
205     }
206 
207     void UpdatePosMapStart(float delta);
208     void UpdatePosMapEnd();
209     void CalculateCurrentOffset(float delta, const ListLayoutAlgorithm::PositionMap& recycledItemPosition);
210     void UpdateScrollBarOffset() override;
211     // chain animation
212     void SetChainAnimation();
213     void SetChainAnimationOptions(const ChainAnimationOptions& options);
214     float FlushChainAnimation(float dragOffset);
215     void ProcessDragStart(float startPosition);
216     void ProcessDragUpdate(float dragOffset, int32_t source);
217     float GetChainDelta(int32_t index) const;
218 
219     // multiSelectable
SetMultiSelectable(bool multiSelectable)220     void SetMultiSelectable(bool multiSelectable)
221     {
222         multiSelectable_ = multiSelectable;
223     }
224 
225     void SetSwiperItem(WeakPtr<ListItemPattern> swiperItem);
GetSwiperItem()226     WeakPtr<ListItemPattern> GetSwiperItem()
227     {
228         if (!swiperItem_.Upgrade()) {
229             return nullptr;
230         }
231         return swiperItem_;
232     }
SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem)233     void SetSwiperItemEnd(WeakPtr<ListItemPattern> swiperItem)
234     {
235         if (swiperItem == swiperItem_) {
236             canReplaceSwiperItem_ = true;
237         }
238     }
IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem)239     bool IsCurrentSwiperItem(WeakPtr<ListItemPattern> swiperItem)
240     {
241         if (!swiperItem_.Upgrade()) {
242             return true;
243         }
244         return swiperItem == swiperItem_;
245     }
CanReplaceSwiperItem()246     bool CanReplaceSwiperItem()
247     {
248         auto listItemPattern = swiperItem_.Upgrade();
249         if (!listItemPattern) {
250             canReplaceSwiperItem_ = true;
251             return canReplaceSwiperItem_;
252         }
253         auto host = listItemPattern->GetHost();
254         if (!host || !host->IsOnMainTree()) {
255             canReplaceSwiperItem_ = true;
256             return canReplaceSwiperItem_;
257         }
258         return canReplaceSwiperItem_;
259     }
260 
SetPredictSnapOffset(float predictSnapOffset)261     void SetPredictSnapOffset(float predictSnapOffset)
262     {
263         predictSnapOffset_ = predictSnapOffset;
264     }
265     bool OnScrollSnapCallback(double targetOffset, double velocity) override;
266 
267     int32_t GetItemIndexByPosition(float xOffset, float yOffset);
268 
SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param)269     void SetPredictLayoutParam(std::optional<ListPredictLayoutParam> param)
270     {
271         predictLayoutParam_ = param;
272     }
GetPredictLayoutParam()273     std::optional<ListPredictLayoutParam> GetPredictLayoutParam() const
274     {
275         return predictLayoutParam_;
276     }
277 
SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param)278     void SetPredictLayoutParamV2(std::optional<ListPredictLayoutParamV2> param)
279     {
280         predictLayoutParamV2_ = param;
281     }
282 
GetPredictLayoutParamV2()283     std::optional<ListPredictLayoutParamV2> GetPredictLayoutParamV2() const
284     {
285         return predictLayoutParamV2_;
286     }
287 
288     void CloseAllSwipeActions(OnFinishFunc&&);
289 
290     std::string ProvideRestoreInfo() override;
291     void OnRestoreInfo(const std::string& restoreInfo) override;
292     void DumpAdvanceInfo() override;
293 
SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection)294     void SetNeedToUpdateListDirectionInCardStyle(bool isNeedToUpdateListDirection)
295     {
296         isNeedToUpdateListDirection_ = isNeedToUpdateListDirection;
297     }
298 
IsNeedToUpdateListDirectionInCardStyle()299     bool IsNeedToUpdateListDirectionInCardStyle() const
300     {
301         return isNeedToUpdateListDirection_;
302     }
303 
304     std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems() override;
305 
SetItemPressed(bool isPressed,int32_t id)306     void SetItemPressed(bool isPressed, int32_t id)
307     {
308         if (isPressed) {
309             pressedItem_.emplace(id);
310         } else {
311             pressedItem_.erase(id);
312         }
313     }
314 
315     RefPtr<ListChildrenMainSize> GetOrCreateListChildrenMainSize();
316     void SetListChildrenMainSize(float defaultSize, const std::vector<float>& mainSize);
317     void OnChildrenSizeChanged(std::tuple<int32_t, int32_t, int32_t> change, ListChangeFlag flag);
318     void ResetChildrenSize();
ListChildrenSizeExist()319     bool ListChildrenSizeExist()
320     {
321         return static_cast<bool>(childrenSize_);
322     }
CanOverScroll(int32_t source)323     bool CanOverScroll(int32_t source) override
324     {
325         auto canOverScroll = (IsScrollableSpringEffect() && source != SCROLL_FROM_AXIS && source != SCROLL_FROM_BAR &&
326             IsScrollable() && (!ScrollableIdle() || animateOverScroll_ || animateCanOverScroll_) &&
327             (IsAtBottom() || IsAtTop()));
328         if (canOverScroll != lastCanOverScroll_) {
329             lastCanOverScroll_ = canOverScroll;
330             AddScrollableFrameInfo(source);
331         }
332         return canOverScroll;
333     }
334 private:
335 
IsNeedInitClickEventRecorder()336     bool IsNeedInitClickEventRecorder() const override
337     {
338         return true;
339     }
340 
341     void OnScrollEndCallback() override;
342     void FireOnReachStart(const OnReachEvent& onReachStart) override;
343     void FireOnReachEnd(const OnReachEvent& onReachEnd) override;
344     void FireOnScrollIndex(bool indexChanged, const OnScrollIndexEvent& onScrollIndex);
345     void OnModifyDone() override;
346     void ChangeAxis(RefPtr<UINode> node);
347     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
348     float CalculateTargetPos(float startPos, float endPos);
349 
350     void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub);
351     bool OnKeyEvent(const KeyEvent& event);
352     bool HandleDirectionKey(const KeyEvent& event);
353     WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode);
354     WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarMainIndex, int32_t tarGroupIndex);
355     WeakPtr<FocusHub> ScrollAndFindFocusNode(int32_t nextIndex, int32_t curIndex, int32_t& nextIndexInGroup,
356         int32_t curIndexInGroup, int32_t moveStep, FocusStep step);
357     bool ScrollListForFocus(int32_t nextIndex, int32_t curIndex, int32_t nextIndexInGroup);
358     bool ScrollListItemGroupForFocus(int32_t nextIndex, int32_t& nextIndexInGroup, int32_t curIndexInGroup,
359         int32_t moveStep, FocusStep step, bool isScrollIndex);
360 
361     void MarkDirtyNodeSelf();
362     SizeF GetContentSize() const;
363     void ProcessEvent(bool indexChanged, float finalOffset, bool isJump);
364     void CheckScrollable();
365     bool IsOutOfBoundary(bool useCurrentDelta = true) override;
366     bool OnScrollCallback(float offset, int32_t source) override;
367     void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override;
368     void HandleScrollEffect(float offset);
369     void StartDefaultOrCustomSpringMotion(float start, float end, const RefPtr<InterpolatingSpring>& curve);
370     bool IsScrollSnapAlignCenter() const;
371     void SetChainAnimationCallback();
372     void SetChainAnimationToPosMap();
373     void SetChainAnimationLayoutAlgorithm(
374         RefPtr<ListLayoutAlgorithm> listLayoutAlgorithm, RefPtr<ListLayoutProperty> listLayoutProperty);
375     bool NeedScrollSnapAlignEffect() const;
376     ScrollAlign GetScrollAlignByScrollSnapAlign() const;
377     bool GetListItemAnimatePos(float startPos, float endPos, ScrollAlign align, float& targetPos);
378     bool GetListItemGroupAnimatePosWithoutIndexInGroup(int32_t index, float startPos, float endPos,
379         ScrollAlign align, float& targetPos);
380     bool GetListItemGroupAnimatePosWithIndexInGroup(int32_t index, int32_t indexInGroup, float startPos,
381         ScrollAlign align, float& targetPos);
382 
383     // multiSelectable
384     void ClearMultiSelect() override;
385     bool IsItemSelected(const GestureEvent& info) override;
386     void MultiSelectWithoutKeyboard(const RectF& selectedZone) override;
387     void HandleCardModeSelectedEvent(
388         const RectF& selectedZone, const RefPtr<FrameNode>& itemGroupNode, float itemGroupTop);
389 
390     void DrivenRender(const RefPtr<LayoutWrapper>& layoutWrapper);
391     ListItemGroupPara GetListItemGroupParameter(const RefPtr<FrameNode>& node);
392     bool IsListItemGroup(int32_t listIndex, RefPtr<FrameNode>& node);
393     void GetListItemGroupEdge(bool& groupAtStart, bool& groupAtEnd) const;
394     void RefreshLanesItemRange();
395     void UpdateListDirectionInCardStyle();
396     bool UpdateStartListItemIndex();
397     bool UpdateEndListItemIndex();
398     float GetStartOverScrollOffset(float offset, float startMainPos) const;
399     float GetEndOverScrollOffset(float offset, float endMainPos, float startMainPos) const;
400     float UpdateTotalOffset(const RefPtr<ListLayoutAlgorithm>& listLayoutAlgorithm, bool isJump);
401     RefPtr<ListContentModifier> listContentModifier_;
402 
403     int32_t maxListItemIndex_ = 0;
404     int32_t startIndex_ = -1;
405     int32_t endIndex_ = -1;
406     int32_t centerIndex_ = -1;
407     float startMainPos_ = 0.0f;
408     float endMainPos_ = 0.0f;
409     float prevStartOffset_ = 0.f;
410     float prevEndOffset_ = 0.f;
411     float currentOffset_ = 0.0f;
412     float spaceWidth_ = 0.0f;
413     float contentMainSize_ = 0.0f;
414     float contentStartOffset_ = 0.0f;
415     float contentEndOffset_ = 0.0f;
416     bool maintainVisibleContentPosition_ = false;
417 
418     float currentDelta_ = 0.0f;
419     bool crossMatchChild_ = false;
420     bool smooth_ = false;
421     float scrollSnapVelocity_ = 0.0f;
422     bool snapTrigOnScrollStart_ = false;
423 
424     std::optional<int32_t> jumpIndex_;
425     std::optional<int32_t> jumpIndexInGroup_;
426     std::optional<int32_t> targetIndex_;
427     std::optional<int32_t> targetIndexInGroup_;
428     std::optional<ListScrollTarget> scrollTarget_;
429     std::optional<float> predictSnapOffset_;
430     std::optional<float> predictSnapEndPos_;
431     ScrollAlign scrollAlign_ = ScrollAlign::START;
432     bool isScrollable_ = true;
433     bool paintStateFlag_ = false;
434     bool isFramePaintStateValid_ = false;
435     bool isNeedCheckOffset_ = false;
436 
437     ListLayoutAlgorithm::PositionMap itemPosition_;
438     RefPtr<ListPositionMap> posMap_;
439     RefPtr<ListChildrenMainSize> childrenSize_;
440     float listTotalHeight_ = 0.0f;
441 
442     std::map<int32_t, int32_t> lanesItemRange_;
443     std::set<int32_t> pressedItem_;
444     int32_t lanes_ = 1;
445     float laneGutter_ = 0.0f;
446     // chain animation
447     RefPtr<ChainAnimation> chainAnimation_;
448     bool dragFromSpring_ = false;
449     RefPtr<SpringProperty> springProperty_;
450     std::optional<ChainAnimationOptions> chainAnimationOptions_;
451 
452     bool isOritationListenerRegisted_ = false;
453 
454     // ListItem swiperAction
455     WeakPtr<ListItemPattern> swiperItem_;
456     bool canReplaceSwiperItem_ = true;
457 
458     RefPtr<SpringMotion> scrollToIndexMotion_;
459     RefPtr<SpringMotion> scrollSnapMotion_;
460     RefPtr<Scrollable> scrollable_;
461 
462     bool isScrollEnd_ = false;
463     bool needReEstimateOffset_ = false;
464     std::optional<ListPredictLayoutParam> predictLayoutParam_;
465     std::optional<ListPredictLayoutParamV2> predictLayoutParamV2_;
466 
467     bool isNeedToUpdateListDirection_ = false;
468     bool startIndexChanged_ = false;
469     bool endIndexChanged_ = false;
470 
471     ListItemIndex startInfo_ = {-1, -1, -1};
472     ListItemIndex endInfo_ = {-1, -1, -1};
473 };
474 } // namespace OHOS::Ace::NG
475 
476 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_PATTERN_H
477