1 /*
2  * Copyright (c) 2023-2024 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_SCROLLABLE_SCROLLABLE_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLLABLE_SCROLLABLE_PATTERN_H
18 
19 #include <cmath>
20 #include <vector>
21 
22 #include "base/geometry/axis.h"
23 #include "core/animation/select_motion.h"
24 #include "core/animation/spring_curve.h"
25 #include "core/animation/bezier_variable_velocity_motion.h"
26 #include "core/animation/velocity_motion.h"
27 #include "core/components_ng/base/frame_scene_status.h"
28 #include "core/components_ng/event/drag_event.h"
29 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
30 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
31 #include "core/components_ng/pattern/pattern.h"
32 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h"
33 #include "core/components_ng/pattern/scroll/inner/scroll_bar_overlay_modifier.h"
34 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h"
35 #include "core/components_ng/pattern/scrollable/nestable_scroll_container.h"
36 #include "core/components_ng/pattern/scrollable/refresh_coordination.h"
37 #include "core/components_ng/pattern/scrollable/scrollable_controller.h"
38 #include "core/components_ng/pattern/scrollable/scrollable_coordination_event.h"
39 #include "core/components_ng/pattern/scrollable/scrollable_paint_method.h"
40 #include "core/components_ng/pattern/scrollable/scrollable_paint_property.h"
41 #include "core/components_ng/pattern/scrollable/scrollable_properties.h"
42 #include "core/components_ng/render/animation_utils.h"
43 #include "core/event/mouse_event.h"
44 #include "core/components_ng/event/scrollable_event.h"
45 namespace OHOS::Ace::NG {
46 class InspectorFilter;
47 #ifndef WEARABLE_PRODUCT
48 constexpr double FRICTION = 0.6;
49 constexpr double API11_FRICTION = 0.7;
50 constexpr double API12_FRICTION = 0.75;
51 constexpr double MAX_VELOCITY = 9000.0;
52 #else
53 constexpr double FRICTION = 0.9;
54 constexpr double MAX_VELOCITY = 5000.0;
55 #endif
56 constexpr float SPRING_ACCURACY = 0.1f;
57 enum class ModalSheetCoordinationMode : char {
58     UNKNOWN = 0,
59     SHEET_SCROLL = 1,
60     SCROLLABLE_SCROLL = 2,
61 };
62 struct ScrollOffsetAbility {
63     std::function<bool(float)> scrollFunc = nullptr;
64     Axis axis = Axis::VERTICAL;
65     float contentStartOffset = 0.0f;
66     float contentEndOffset = 0.0f;
67 };
68 class ScrollablePattern : public NestableScrollContainer {
69     DECLARE_ACE_TYPE(ScrollablePattern, NestableScrollContainer);
70 
71 public:
72     ScrollablePattern();
73     ScrollablePattern(EdgeEffect edgeEffect, bool alwaysEnabled);
74 
~ScrollablePattern()75     ~ScrollablePattern()
76     {
77         UnRegister2DragDropManager();
78         if (scrollBarProxy_) {
79             scrollBarProxy_->UnRegisterNestScrollableNode(AceType::WeakClaim(this));
80         }
81     }
82 
IsAtomicNode()83     bool IsAtomicNode() const override
84     {
85         return false;
86     }
87 
88     RefPtr<PaintProperty> CreatePaintProperty() override;
89 
90     void CreateAnalyzerOverlay(const RefPtr<FrameNode> node);
91 
92     void UpdateFadingEdge(const RefPtr<ScrollablePaintMethod>& paint);
93 
94     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override;
95     void OnWindowHide() override;
96 
97     // scrollable
GetAxis()98     Axis GetAxis() const override
99     {
100         return axis_;
101     }
102 
IsReverse()103     virtual bool IsReverse() const
104     {
105         if (GetAxis() != Axis::HORIZONTAL) {
106             return false;
107         }
108         auto host = GetHost();
109         CHECK_NULL_RETURN(host, false);
110         auto layoutProperty = host->GetLayoutProperty<LayoutProperty>();
111         CHECK_NULL_RETURN(layoutProperty, false);
112         auto layoutDirection = layoutProperty->GetNonAutoLayoutDirection();
113         return (layoutDirection == TextDirection::RTL);
114     };
115 
ShouldDelayChildPressedState()116     virtual bool ShouldDelayChildPressedState() const override
117     {
118         return true;
119     }
120 
121     void RegisterScrollingListener(const RefPtr<ScrollingListener> listener) override;
122     void FireAndCleanScrollingListener() override;
123     void CleanScrollingListener() override;
124 
125     void SetAxis(Axis axis);
126     virtual bool UpdateCurrentOffset(float delta, int32_t source) = 0;
IsScrollable()127     virtual bool IsScrollable() const
128     {
129         return false;
130     }
131     virtual bool IsAtTop() const = 0;
132     virtual bool IsAtBottom() const = 0;
IsFadingBottom()133     virtual bool IsFadingBottom() const
134     {
135         return !IsAtBottom();
136     }
OutBoundaryCallback()137     virtual bool OutBoundaryCallback()
138     {
139         return IsOutOfBoundary();
140     }
141 
142     virtual bool IsOutOfBoundary(bool useCurrentDelta = true)
143     {
144         return false;
145     }
146 
147     virtual void OnTouchDown(const TouchEventInfo& info);
148 
149     void AddScrollEvent();
GetScrollableEvent()150     RefPtr<ScrollableEvent> GetScrollableEvent()
151     {
152         return scrollableEvent_;
153     }
154     virtual bool OnScrollCallback(float offset, int32_t source);
155     virtual void OnScrollStartCallback();
156     virtual void FireOnScrollStart();
FireOnReachStart(const OnReachEvent & onReachStart)157     virtual void FireOnReachStart(const OnReachEvent& onReachStart) {}
FireOnReachEnd(const OnReachEvent & onReachEnd)158     virtual void FireOnReachEnd(const OnReachEvent& onReachEnd) {}
ScrollableIdle()159     bool ScrollableIdle()
160     {
161         return !scrollableEvent_ || scrollableEvent_->Idle();
162     }
SetScrollEnabled(bool enabled)163     void SetScrollEnabled(bool enabled)
164     {
165         CHECK_NULL_VOID(scrollableEvent_);
166         bool bNest = false;
167         if (scrollBarProxy_) {
168             bNest = scrollBarProxy_->IsNestScroller();
169         }
170 
171         if (enabled || bNest) {
172             enabled = true;
173             scrollableEvent_->SetAxis(axis_);
174         } else {
175             scrollableEvent_->SetAxis(Axis::NONE);
176         }
177         scrollableEvent_->SetEnabled(enabled);
178 
179         if (scrollBarProxy_) {
180             scrollBarProxy_->SetScrollEnabled(enabled, AceType::WeakClaim(this));
181         }
182     }
183 
GetScrollEnabled()184     bool GetScrollEnabled() const
185     {
186         CHECK_NULL_RETURN(scrollableEvent_, false);
187         return scrollableEvent_->GetEnabled();
188     }
189 
190     RefPtr<GestureEventHub> GetGestureHub();
191     RefPtr<InputEventHub> GetInputHub();
192 
193     // edgeEffect
GetScrollEdgeEffect()194     const RefPtr<ScrollEdgeEffect>& GetScrollEdgeEffect() const
195     {
196         return scrollEffect_;
197     }
198     bool HandleEdgeEffect(float offset, int32_t source, const SizeF& size);
199     void HandleFadeEffect(float offset, int32_t source, const SizeF& size,
200         bool isNotPositiveScrollableDistance);
SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect> & scrollEffect)201     virtual void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) {}
IsRestrictBoundary()202     bool IsRestrictBoundary()
203     {
204         return !scrollEffect_ || scrollEffect_->IsRestrictBoundary();
205     }
206 
207     // scrollBar
208     virtual void UpdateScrollBarOffset() = 0;
209     void SetScrollBar(const std::unique_ptr<ScrollBarProperty>& property);
210     void SetScrollBar(DisplayMode displayMode);
211     void SetScrollBarProxy(const RefPtr<ScrollBarProxy>& scrollBarProxy);
212     void CreateScrollBarOverlayModifier();
213 
GetScrollableDistance()214     float GetScrollableDistance() const
215     {
216         return estimatedHeight_;
217     }
218 
GetBarOffset()219     float GetBarOffset() const
220     {
221         return barOffset_;
222     }
223 
GetScrollBarOutBoundaryExtent()224     double GetScrollBarOutBoundaryExtent() const
225     {
226         return scrollBarOutBoundaryExtent_;
227     }
228 
SetScrollBarOutBoundaryExtent(float scrollBarOutBoundaryExtent)229     void SetScrollBarOutBoundaryExtent(float scrollBarOutBoundaryExtent)
230     {
231         scrollBarOutBoundaryExtent_ = scrollBarOutBoundaryExtent;
232     }
233 
234     void HandleScrollBarOutBoundary(float scrollBarOutBoundaryExtent);
235 
GetMainSize(const SizeF & size)236     double GetMainSize(const SizeF& size) const
237     {
238         return axis_ == Axis::HORIZONTAL ? size.Width() : size.Height();
239     }
240 
IsScrollableStopped()241     bool IsScrollableStopped() const
242     {
243         CHECK_NULL_RETURN(scrollableEvent_, true);
244         auto scrollable = scrollableEvent_->GetScrollable();
245         CHECK_NULL_RETURN(scrollable, true);
246         return scrollable->IsStopped();
247     }
248 
GetIsDragging()249     bool GetIsDragging() const
250     {
251         CHECK_NULL_RETURN(scrollableEvent_, false);
252         auto scrollable = scrollableEvent_->GetScrollable();
253         CHECK_NULL_RETURN(scrollable, false);
254         return scrollable->GetIsDragging();
255     }
256 
StopScrollable()257     void StopScrollable()
258     {
259         CHECK_NULL_VOID(scrollableEvent_);
260         auto scrollable = scrollableEvent_->GetScrollable();
261         CHECK_NULL_VOID(scrollable);
262         scrollable->StopScrollable();
263     }
264 
StartScrollSnapMotion(float scrollSnapDelta,float scrollSnapVelocity)265     void StartScrollSnapMotion(float scrollSnapDelta, float scrollSnapVelocity)
266     {
267         CHECK_NULL_VOID(scrollableEvent_);
268         auto scrollable = scrollableEvent_->GetScrollable();
269         CHECK_NULL_VOID(scrollable);
270         scrollable->ProcessScrollSnapSpringMotion(scrollSnapDelta, scrollSnapVelocity);
271     }
272 
IsScrollableSpringEffect()273     bool IsScrollableSpringEffect() const
274     {
275         CHECK_NULL_RETURN(scrollEffect_, false);
276         return scrollEffect_->IsSpringEffect();
277     }
278 
SetCoordEventNeedSpringEffect(bool IsCoordEventNeedSpring)279     void SetCoordEventNeedSpringEffect(bool IsCoordEventNeedSpring)
280     {
281         isCoordEventNeedSpring_ = IsCoordEventNeedSpring;
282     }
283 
284     void GetParentNavigation();
285     void GetParentModalSheet();
286 
287     /**
288      * @brief Return the portion of delta that's in overScroll range.
289      *
290      * @param delta incoming offset change.
291      * @return the portion of delta in overScroll range. Both top overScroll and bottom overScroll.
292      */
GetOverScrollOffset(double delta)293     virtual OverScrollOffset GetOverScrollOffset(double delta) const
294     {
295         return { 0, 0 };
296     }
297 
OnScrollSnapCallback(double targetOffset,double velocity)298     virtual bool OnScrollSnapCallback(double targetOffset, double velocity)
299     {
300         return false;
301     }
302 
StartScrollBarAnimatorByProxy()303     void StartScrollBarAnimatorByProxy()
304     {
305         if (scrollBarProxy_) {
306             scrollBarProxy_->StartScrollBarAnimator();
307         }
308 
309         for (auto proxy : nestScrollBarProxy_) {
310             auto scrollBarProxy = proxy.Upgrade();
311             CHECK_NULL_CONTINUE(scrollBarProxy);
312             scrollBarProxy->StartScrollBarAnimator();
313         }
314     }
315 
StopScrollBarAnimatorByProxy()316     void StopScrollBarAnimatorByProxy()
317     {
318         if (scrollBarProxy_) {
319             scrollBarProxy_->StopScrollBarAnimator();
320         }
321 
322         for (auto proxy : nestScrollBarProxy_) {
323             auto scrollBarProxy = proxy.Upgrade();
324             CHECK_NULL_CONTINUE(scrollBarProxy);
325             scrollBarProxy->StopScrollBarAnimator();
326         }
327     }
328 
329     void SetFriction(double friction);
330 
GetFriction()331     double GetFriction() const
332     {
333         return friction_;
334     }
335 
336     void SetMaxFlingVelocity(double max);
337 
GetMaxFlingVelocity()338     double GetMaxFlingVelocity() const
339     {
340         CHECK_NULL_RETURN(scrollableEvent_, 0.0);
341         auto scrollable = scrollableEvent_->GetScrollable();
342         CHECK_NULL_RETURN(scrollable, 0.0);
343         return scrollable->GetMaxFlingVelocity();
344     }
345 
346     virtual void StopAnimate();
347 
AnimateRunning()348     bool AnimateRunning() const
349     {
350         return (animator_ && animator_->IsRunning()) || !isAnimationStop_;
351     }
AnimateStoped()352     bool AnimateStoped() const
353     {
354         return (!animator_ || animator_->IsStopped()) && isAnimationStop_;
355     }
356 
AbortScrollAnimator()357     void AbortScrollAnimator()
358     {
359         if (animator_ && !animator_->IsStopped()) {
360             scrollAbort_ = true;
361             animator_->Stop();
362         }
363         if (!isAnimationStop_) {
364             scrollAbort_ = true;
365             StopAnimation(springAnimation_);
366             StopAnimation(curveAnimation_);
367         }
368     }
GetScrollAbort()369     bool GetScrollAbort() const
370     {
371         return scrollAbort_;
372     }
SetScrollAbort(bool abort)373     void SetScrollAbort(bool abort)
374     {
375         scrollAbort_ = abort;
376     }
377     void PlaySpringAnimation(float position, float velocity, float mass, float stiffness, float damping,
378                             bool useTotalOffset = true);
379     void PlayCurveAnimation(float position, float duration, const RefPtr<Curve>& curve, bool canOverScroll);
GetTotalOffset()380     virtual float GetTotalOffset() const
381     {
382         return 0.0f;
383     }
384     // main size of all children
GetTotalHeight()385     virtual float GetTotalHeight() const
386     {
387         return 0.0f;
388     }
OnAnimateStop()389     virtual void OnAnimateStop() {}
390     virtual void ScrollTo(float position);
391     virtual void AnimateTo(
392         float position, float duration, const RefPtr<Curve>& curve, bool smooth, bool canOverScroll = false,
393         bool useTotalOffset = true);
CanOverScroll(int32_t source)394     virtual bool CanOverScroll(int32_t source)
395     {
396         auto canOverScroll = (IsScrollableSpringEffect() && source != SCROLL_FROM_AXIS && source != SCROLL_FROM_BAR &&
397             IsScrollable() && (!ScrollableIdle() || animateOverScroll_ || animateCanOverScroll_));
398         if (canOverScroll != lastCanOverScroll_) {
399             lastCanOverScroll_ = canOverScroll;
400             AddScrollableFrameInfo(source);
401         }
402         return canOverScroll;
403     }
404     void MarkSelectedItems();
405     bool ShouldSelectScrollBeStopped();
406     void UpdateMouseStart(float offset);
407 
408     // scrollSnap
CalePredictSnapOffset(float delta,float dragDistance,float velocity)409     virtual std::optional<float> CalePredictSnapOffset(float delta, float dragDistance, float velocity)
410     {
411         std::optional<float> predictSnapPosition;
412         return predictSnapPosition;
413     }
414 
NeedScrollSnapToSide(float delta)415     virtual bool NeedScrollSnapToSide(float delta)
416     {
417         return false;
418     }
419 
SetScrollSource(int32_t scrollSource)420     void SetScrollSource(int32_t scrollSource)
421     {
422         if (scrollSource == SCROLL_FROM_JUMP || scrollSource == SCROLL_FROM_FOCUS_JUMP) {
423             if (scrollBar_ && scrollBar_->IsScrollable() && scrollBarOverlayModifier_) {
424                 scrollBarOverlayModifier_->SetOpacity(UINT8_MAX);
425                 scrollBar_->ScheduleDisappearDelayTask();
426             }
427             StopScrollBarAnimatorByProxy();
428             StartScrollBarAnimatorByProxy();
429         }
430         if (scrollSource == SCROLL_FROM_NONE) {
431             if (lastScrollSource_ != scrollSource_) {
432                 AddScrollableFrameInfo(scrollSource_);
433             }
434             lastScrollSource_ = scrollSource_;
435         }
436         scrollSource_ = scrollSource;
437     }
438 
GetScrollSource()439     int32_t GetScrollSource() const
440     {
441         return scrollSource_;
442     }
443 
GetCurrentVelocity()444     float GetCurrentVelocity() const
445     {
446         return currentVelocity_;
447     }
448 
449     ScrollState GetScrollState() const;
450 
451     static ScrollState GetScrollState(int32_t scrollSource);
452 
453     static ScrollSource ConvertScrollSource(int32_t source);
454 
CalculateFriction(float gamma)455     static float CalculateFriction(float gamma)
456     {
457         constexpr float RATIO = 1.848f;
458         if (GreatOrEqual(gamma, 1.0)) {
459             gamma = 1.0f;
460         }
461         return exp(-RATIO * gamma);
462     }
463     virtual float GetMainContentSize() const;
464 
SupportScrollToIndex()465     virtual bool SupportScrollToIndex() const
466     {
467         return true;
468     }
469 
GetDefaultScrollAlign()470     virtual ScrollAlign GetDefaultScrollAlign() const
471     {
472         return ScrollAlign::START;
473     }
474 
475     virtual void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::START,
476         std::optional<float> extraOffset = std::nullopt)
477     {}
478 
SetExtraOffset(std::optional<float> extraOffset)479     void SetExtraOffset(std::optional<float> extraOffset)
480     {
481         extraOffset_ = extraOffset;
482     }
483 
GetExtraOffset()484     const std::optional<float>& GetExtraOffset() const
485     {
486         return extraOffset_;
487     }
488 
ResetExtraOffset()489     void ResetExtraOffset()
490     {
491         extraOffset_.reset();
492     }
493 
494     virtual void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth);
495 
GetScrollEdgeType()496     virtual ScrollEdgeType GetScrollEdgeType() const
497     {
498         return ScrollEdgeType::SCROLL_NONE;
499     }
500 
SetScrollEdgeType(ScrollEdgeType scrollEdgeType)501     virtual void SetScrollEdgeType(ScrollEdgeType scrollEdgeType) {}
502 
503     virtual void Fling(double flingVelocity);
504 
SetPositionController(RefPtr<ScrollableController> control)505     void SetPositionController(RefPtr<ScrollableController> control)
506     {
507         positionController_ = control;
508         if (control) {
509             control->SetScrollPattern(AceType::WeakClaim(this));
510         }
511     }
512 
GetOrCreatePositionController()513     RefPtr<ScrollableController> GetOrCreatePositionController()
514     {
515         if (!positionController_) {
516             auto controller = AceType::MakeRefPtr<NG::ScrollableController>();
517             SetPositionController(controller);
518         }
519         return positionController_;
520     }
521 
GetItemRect(int32_t index)522     virtual Rect GetItemRect(int32_t index) const
523     {
524         return Rect();
525     };
526 
GetItemIndex(double x,double y)527     virtual int32_t GetItemIndex(double x, double y) const
528     {
529         return -1;
530     }
531 
SetEdgeEffect(EdgeEffect edgeEffect,bool alwaysEnabled)532     void SetEdgeEffect(EdgeEffect edgeEffect, bool alwaysEnabled)
533     {
534         edgeEffect_ = edgeEffect;
535         edgeEffectAlwaysEnabled_ = alwaysEnabled;
536     }
537 
GetEdgeEffect()538     EdgeEffect GetEdgeEffect()
539     {
540         return edgeEffect_;
541     }
542 
GetAlwaysEnabled()543     bool GetAlwaysEnabled() const
544     {
545         return edgeEffectAlwaysEnabled_;
546     }
547 
SetAlwaysEnabled(bool alwaysEnabled)548     void SetAlwaysEnabled(bool alwaysEnabled)
549     {
550         edgeEffectAlwaysEnabled_ = alwaysEnabled;
551     }
552 
IsScrollableAnimationNotRunning()553     bool IsScrollableAnimationNotRunning()
554     {
555         if (scrollableEvent_) {
556             auto scrollable = scrollableEvent_->GetScrollable();
557             if (scrollable) {
558                 return scrollable->IsAnimationNotRunning();
559             }
560             return false;
561         }
562         return false;
563     }
564 
GetFinalPosition()565     float GetFinalPosition() const
566     {
567         return finalPosition_;
568     }
569     void HandleOnDragStatusCallback(
570         const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent) override;
571 
IsScrollableSpringMotionRunning()572     bool IsScrollableSpringMotionRunning()
573     {
574         CHECK_NULL_RETURN(scrollableEvent_, false);
575         auto scrollable = scrollableEvent_->GetScrollable();
576         CHECK_NULL_RETURN(scrollable, false);
577         return scrollable->IsSpringMotionRunning();
578     }
579 
IsScrollSnap()580     virtual bool IsScrollSnap()
581     {
582         // When setting snap or enablePaging in scroll, the PARENT_FIRST in nestedScroll_ is invalid
583         return false;
584     }
585 
SetNeedLinked(bool needLinked)586     void SetNeedLinked(bool needLinked)
587     {
588         needLinked_ = needLinked;
589     }
590 
SetAnimateCanOverScroll(bool animateCanOverScroll)591     void SetAnimateCanOverScroll(bool animateCanOverScroll)
592     {
593         bool isScrollable = !(IsAtBottom() && IsAtTop() && !GetAlwaysEnabled());
594         animateCanOverScroll_ = isScrollable && animateCanOverScroll;
595     }
596 
GetVisibleSelectedItems()597     virtual std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems()
598     {
599         std::vector<RefPtr<FrameNode>> children;
600         return children;
601     }
602     void InitScrollBarGestureEvent();
603 
604     virtual void InitScrollBarClickEvent();
605     void HandleClickEvent();
606     void InitScrollBarMouseEvent();
607     virtual void ScrollPage(
608         bool reverse, bool smooth = false, AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL);
609     void PrintOffsetLog(AceLogTag tag, int32_t id, double finalOffset);
610 
611     void CheckRestartSpring(bool sizeDiminished, bool needNestedScrolling = true);
612 
GetScrollablePanDirection()613     Axis GetScrollablePanDirection()
614     {
615         CHECK_NULL_RETURN(scrollableEvent_, Axis::NONE);
616         auto scrollable = scrollableEvent_->GetScrollable();
617         CHECK_NULL_RETURN(scrollable, Axis::NONE);
618         return scrollable->GetPanDirection();
619     }
620 
621     void AddEventsFiredInfo(ScrollableEventType eventType);
622 
623     void AddScrollableFrameInfo(int32_t scrollSource);
624 
625     void GetEdgeEffectDumpInfo();
626 
627     void GetAxisDumpInfo();
628 
629     void GetPanDirectionDumpInfo();
630 
631     void GetPaintPropertyDumpInfo();
632 
633     void GetEventDumpInfo();
634 
635     void DumpAdvanceInfo() override;
636 
SetScrollToSafeAreaHelper(bool isScrollToSafeAreaHelper)637     void SetScrollToSafeAreaHelper(bool isScrollToSafeAreaHelper)
638     {
639         isScrollToSafeAreaHelper_ = isScrollToSafeAreaHelper;
640     }
641 
IsScrollToSafeAreaHelper()642     bool IsScrollToSafeAreaHelper() const
643     {
644         return isScrollToSafeAreaHelper_;
645     }
646 
GetScrollOffsetAbility()647     virtual ScrollOffsetAbility GetScrollOffsetAbility()
648     {
649         return { nullptr, Axis::NONE };
650     }
651 
GetScrollIndexAbility()652     virtual std::function<bool(int32_t)> GetScrollIndexAbility()
653     {
654         return nullptr;
655     }
656 
657     void ScrollAtFixedVelocity(float velocity);
658 
659     PositionMode GetPositionMode();
660 
661     void HandleMoveEventInComp(const PointF& point);
662     void HandleLeaveHotzoneEvent();
SetHotZoneScrollCallback(std::function<void (void)> && func)663     void SetHotZoneScrollCallback(std::function<void(void)>&& func)
664     {
665         hotZoneScrollCallback_ = func;
666     }
667 
668     void OnCollectClickTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl,
669         TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent,
670         ResponseLinkResult& responseLinkResult);
671 
672     virtual void SetAccessibilityAction();
GetScrollBarProxy()673     RefPtr<NG::ScrollBarProxy> GetScrollBarProxy() const
674     {
675         return scrollBarProxy_;
676     }
677 
678     virtual void OnAttachToMainTree() override;
679 
680     void AddNestScrollBarProxy(const WeakPtr<ScrollBarProxy>& scrollBarProxy);
681 
682     void SetParentNestedScroll(RefPtr<ScrollablePattern>& parentPattern);
683 
684     void SearchAndSetParentNestedScroll(const RefPtr<FrameNode>& node);
685 
686     void UnsetParentNestedScroll(RefPtr<ScrollablePattern>& parentPattern);
687 
688     void SearchAndUnsetParentNestedScroll(const RefPtr<FrameNode>& node);
689 
690     void DeleteNestScrollBarProxy(const WeakPtr<ScrollBarProxy>& scrollBarProxy);
691 
SetUseTotalOffset(bool useTotalOffset)692     void SetUseTotalOffset(bool useTotalOffset)
693     {
694         useTotalOffset_ = useTotalOffset;
695     }
696 
GetNestedScrolling()697     bool GetNestedScrolling() const
698     {
699         CHECK_NULL_RETURN(scrollableEvent_, false);
700         auto scrollable = scrollableEvent_->GetScrollable();
701         CHECK_NULL_RETURN(scrollable, false);
702         return scrollable->GetNestedScrolling();
703     }
704 
705     void ScrollEndCallback(bool nestedScroll, float velocity);
706 
GetChildrenExpandedSize()707     virtual SizeF GetChildrenExpandedSize()
708     {
709         return SizeF();
710     }
711 
712     SizeF GetViewSizeMinusPadding();
713 
714 protected:
715     void SuggestOpIncGroup(bool flag);
716     void OnDetachFromFrameNode(FrameNode* frameNode) override;
GetDefaultScrollBarDisplayMode()717     virtual DisplayMode GetDefaultScrollBarDisplayMode() const
718     {
719         return DisplayMode::AUTO;
720     }
GetScrollBar()721     RefPtr<ScrollBar> GetScrollBar() const
722     {
723         return scrollBar_;
724     }
725     void UpdateScrollBarRegion(float offset, float estimatedHeight, Size viewPort, Offset viewOffset);
726 
727     EdgeEffect GetEdgeEffect() const;
SetEdgeEffect()728     void SetEdgeEffect()
729     {
730         SetEdgeEffect(edgeEffect_);
731     }
732 
733     virtual void FireOnScroll(float finalOffset, OnScrollEvent& onScroll) const;
734 
735     void FireObserverOnTouch(const TouchEventInfo& info);
736     void FireObserverOnPanActionEnd(GestureEvent& info);
737     void FireObserverOnReachStart();
738     void FireObserverOnReachEnd();
739     void FireObserverOnScrollStart();
740     void FireObserverOnScrollStop();
741     void FireObserverOnDidScroll(float finalOffset);
742 
743     virtual void OnScrollStop(const OnScrollStopEvent& onScrollStop);
744 
745     float FireOnWillScroll(float offset) const;
746 
747     // select with mouse
748     struct ItemSelectedStatus {
749         std::function<void(bool)> onSelected;
750         std::function<void(bool)> selectChangeEvent;
751         RectF rect;
752         bool selected = false;
FireSelectChangeEventItemSelectedStatus753         void FireSelectChangeEvent(bool isSelected)
754         {
755             if (selected == isSelected) {
756                 return;
757             }
758             selected = isSelected;
759             if (onSelected) {
760                 onSelected(isSelected);
761             }
762             if (selectChangeEvent) {
763                 selectChangeEvent(isSelected);
764             }
765         }
766     };
767     void InitMouseEvent();
768     void UninitMouseEvent();
769     void DrawSelectedZone(const RectF& selectedZone);
770     void ClearSelectedZone();
771     bool multiSelectable_ = false;
772     bool isMouseEventInit_ = false;
773     OffsetF mouseStartOffset_;
774     float totalOffsetOfMousePressed_ = 0.0f;
775     std::unordered_map<int32_t, ItemSelectedStatus> itemToBeSelected_;
776     bool animateOverScroll_ = false;
777     bool animateCanOverScroll_ = false;
778 
GetScrollBarOverlayModifier()779     RefPtr<ScrollBarOverlayModifier> GetScrollBarOverlayModifier() const
780     {
781         return scrollBarOverlayModifier_;
782     }
783 
SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier)784     void SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier)
785     {
786         scrollBarOverlayModifier_ = scrollBarOverlayModifier;
787     }
788     // just for hold ScrollableController
789     RefPtr<ScrollableController> positionController_;
790 
791     bool scrollStop_ = false;
792 
793     // for onReachStart of the first layout
794     bool isInitialized_ = false;
795 
796     void Register2DragDropManager();
797 
SetScrollOriginChild(const WeakPtr<NestableScrollContainer> & scrollOriginChild)798     void SetScrollOriginChild(const WeakPtr<NestableScrollContainer>& scrollOriginChild)
799     {
800         scrollOriginChild_ = scrollOriginChild;
801     }
802 
GetScrollOriginChild()803     RefPtr<NestableScrollContainer> GetScrollOriginChild()
804     {
805         return scrollOriginChild_.Upgrade();
806     }
807 
808     void SetCanOverScroll(bool val);
809     bool GetCanOverScroll() const;
810     bool lastCanOverScroll_ = false;
811 
812     void CheckScrollBarOff();
813 
814 private:
OnScrollEndCallback()815     virtual void OnScrollEndCallback() {};
816 
817     void RegisterScrollBarEventTask();
818     bool OnScrollPosition(double& offset, int32_t source);
819     void ProcessNavBarReactOnStart();
820     float ProcessNavBarReactOnUpdate(float offset);
821     void ProcessNavBarReactOnEnd();
822     void InitSpringOffsetProperty();
823     void InitCurveOffsetProperty();
824     void OnAnimateFinish();
825     void StopAnimation(std::shared_ptr<AnimationUtils::Animation> animation);
826     void PauseAnimation(std::shared_ptr<AnimationUtils::Animation> animation);
827     void InitOption(AnimationOption &option, float duration, const RefPtr<Curve>& curve);
828     float GetScrollDelta(float offset, bool& stopAnimation);
829 
830     void OnAttachToFrameNode() override;
831     void AttachAnimatableProperty(RefPtr<Scrollable> scrollable);
832     void InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub);
833     void RegisterWindowStateChangedCallback();
834 
835     // select with mouse
MultiSelectWithoutKeyboard(const RectF & selectedZone)836     virtual void MultiSelectWithoutKeyboard(const RectF& selectedZone) {};
ClearMultiSelect()837     virtual void ClearMultiSelect() {};
IsItemSelected(const GestureEvent & info)838     virtual bool IsItemSelected(const GestureEvent& info)
839     {
840         return false;
841     }
842     void ClearInvisibleItemsSelectedStatus();
843     void HandleInvisibleItemsSelectedStatus(const RectF& selectedZone);
844     void HandleDragStart(const GestureEvent& info);
845     void HandleDragUpdate(const GestureEvent& info);
846     void HandleDragEnd();
847     void SelectWithScroll();
848     RectF ComputeSelectedZone(const OffsetF& startOffset, const OffsetF& endOffset);
849     float GetOutOfScrollableOffset() const;
850     virtual float GetOffsetWithLimit(float offset) const;
851     void LimitMouseEndOffset();
852     void UpdateBorderRadius();
853 
854     /******************************************************************************
855      * NestableScrollContainer implementations
856      */
857     ScrollResult HandleScroll(
858         float offset, int32_t source, NestedState state = NestedState::GESTURE, float velocity = 0.f) override;
859     bool HandleScrollVelocity(float velocity, const RefPtr<NestableScrollContainer>& child = nullptr) override;
860 
861     void RemainVelocityToChild(float remainVelocity) override;
NestedScrollOutOfBoundary()862     bool NestedScrollOutOfBoundary() override
863     {
864         return OutBoundaryCallback();
865     }
866     void UpdateNestedScrollVelocity(float offset, NestedState state);
867     float GetNestedScrollVelocity();
868 
869     void OnScrollEndRecursive(const std::optional<float>& velocity) override;
870     void OnScrollEndRecursiveInner(const std::optional<float>& velocity);
871     void OnScrollStartRecursive(WeakPtr<NestableScrollContainer> child, float position, float velocity = 0.f) override;
872     void OnScrollStartRecursiveInner(WeakPtr<NestableScrollContainer> child, float position, float velocity = 0.f);
873     void OnScrollDragEndRecursive() override;
874     void StopScrollAnimation() override;
875 
876     ScrollResult HandleScrollParentFirst(float& offset, int32_t source, NestedState state);
877     ScrollResult HandleScrollSelfFirst(float& offset, int32_t source, NestedState state);
878     ScrollResult HandleScrollSelfOnly(float& offset, int32_t source, NestedState state);
879     ScrollResult HandleScrollParallel(float& offset, int32_t source, NestedState state);
880     bool HandleOutBoundary(float& offset, int32_t source, NestedState state, ScrollResult& result);
881     bool HandleSelfOutBoundary(float& offset, int32_t source, const float backOverOffset, float oppositeOverOffset);
882 
883     void ExecuteScrollFrameBegin(float& mainDelta, ScrollState state);
884 
885     void OnScrollEnd();
886     void ProcessSpringEffect(float velocity, bool needRestart = false);
887     void SetEdgeEffect(EdgeEffect edgeEffect);
888 
889     // Scrollable::UpdateScrollPosition
890     bool HandleScrollImpl(float offset, int32_t source);
891     void NotifyMoved(bool value);
892 
893     /*
894      *  End of NestableScrollContainer implementations
895      *******************************************************************************/
896 
897     bool HandleOverScroll(float velocity);
898     bool HandleScrollableOverScroll(float velocity);
899 
CreateRefreshCoordination()900     void CreateRefreshCoordination()
901     {
902         if (!refreshCoordination_) {
903             auto host = GetHost();
904             CHECK_NULL_VOID(host);
905             refreshCoordination_ = AceType::MakeRefPtr<RefreshCoordination>(host);
906         }
907     }
908     float GetVelocity() const;
909     bool NeedSplitScroll(OverScrollOffset& overOffsets, int32_t source);
910     RefreshCoordinationMode CoordinateWithRefresh(double& offset, int32_t source, bool isAtTop);
911     bool CoordinateWithNavigation(double& offset, int32_t source, bool isAtTop);
912     void NotifyFRCSceneInfo(const std::string& scene, double velocity, SceneStatus sceneStatus);
913     ModalSheetCoordinationMode CoordinateWithSheet(double& offset, int32_t source, bool isAtTop);
914     bool NeedCoordinateScrollWithNavigation(double offset, int32_t source, const OverScrollOffset& overOffsets);
915     void SetUiDvsyncSwitch(bool on);
916     void SetNestedScrolling(bool nestedScrolling);
917 
918     Axis axis_ = Axis::VERTICAL;
919     RefPtr<ScrollableEvent> scrollableEvent_;
920     RefPtr<TouchEventImpl> touchEvent_;
921     RefPtr<ScrollEdgeEffect> scrollEffect_;
922     RefPtr<RefreshCoordination> refreshCoordination_;
923     int32_t scrollSource_ = SCROLL_FROM_NONE;
924     int32_t lastScrollSource_ = SCROLL_FROM_NONE;
925     // scrollBar
926     RefPtr<ScrollBar> scrollBar_;
927     RefPtr<NG::ScrollBarProxy> scrollBarProxy_;
928     std::list<WeakPtr<NG::ScrollBarProxy>> nestScrollBarProxy_;
929     RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier_;
930     float barOffset_ = 0.0f;
931     float estimatedHeight_ = 0.0f;
932     bool isReactInParentMovement_ = false;
933     bool isRefreshInReactive_ = false; // true if Refresh component is ready to receive scroll offset.
934     bool isSheetInReactive_ = false;
935     bool isCoordEventNeedSpring_ = true;
936     double scrollBarOutBoundaryExtent_ = 0.0;
937     double friction_ = 0.0;
938     double maxFlingVelocity_ = MAX_VELOCITY;
939     // scroller
940     RefPtr<Animator> animator_;
941     bool scrollAbort_ = false;
942     bool isAnimateOverScroll_ = false;
943     bool isScrollToSafeAreaHelper_ = true;
944     bool inScrollingStatus_ = false;
945     bool switchOnStatus_ = false;
946 
947     float startPercent_ = 0.0f;
948     float endPercent_ = 1.0f;
949     void UpdateFadeInfo(
950         bool isFadingTop, bool isFadingBottom, float fadeFrameSize, const RefPtr<ScrollablePaintMethod>& paint);
951 
952     // select with mouse
953     enum SelectDirection { SELECT_DOWN, SELECT_UP, SELECT_NONE };
954     SelectDirection selectDirection_ = SELECT_NONE;
955     bool mousePressed_ = false;
956     bool canMultiSelect_ = false;
957     OffsetF mouseEndOffset_;
958     OffsetF mousePressOffset_;
959     OffsetF lastMouseStart_;
960     GestureEvent lastMouseMove_;
961     RefPtr<SelectMotion> selectMotion_;
962     RefPtr<PanEvent> boxSelectPanEvent_;
963 
964     RefPtr<NavBarPattern> navBarPattern_;
965     RefPtr<SheetPresentationPattern> sheetPattern_;
966     std::vector<RefPtr<ScrollingListener>> scrollingListener_;
967 
968     EdgeEffect edgeEffect_ = EdgeEffect::NONE;
969     bool edgeEffectAlwaysEnabled_ = false;
970     bool needLinked_ = true;
971 
972     RefPtr<NodeAnimatablePropertyFloat> springOffsetProperty_;
973     RefPtr<NodeAnimatablePropertyFloat> curveOffsetProperty_;
974     std::shared_ptr<AnimationUtils::Animation> springAnimation_;
975     std::shared_ptr<AnimationUtils::Animation> curveAnimation_;
976     uint64_t lastVsyncTime_ = 0;
977     bool isAnimationStop_ = true; // graphic animation flag
978     float currentVelocity_ = 0.0f;
979     float lastPosition_ = 0.0f;
980     float finalPosition_ = 0.0f;
981     bool useTotalOffset_ = true;
982     bool animateToTraceFlag_ = false;
983     std::optional<float> extraOffset_;
984 
985     RefPtr<Animator> hotzoneAnimator_;
986     float lastHonezoneOffsetPct_ = 0.0f;
987     RefPtr<BezierVariableVelocityMotion> velocityMotion_;
988     RefPtr<VelocityMotion> fixedVelocityMotion_;
989     std::function<void(void)> hotZoneScrollCallback_;
990     void UnRegister2DragDropManager();
991     float IsInHotZone(const PointF& point);
992     void HotZoneScroll(const float offset);
993     void StopHotzoneScroll();
994     void HandleHotZone(const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent);
995     bool isVertical() const;
996     Offset locationInfo_;
997     WeakPtr<NestableScrollContainer> scrollOriginChild_;
998     float nestedScrollVelocity_ = 0.0f;
999     uint64_t nestedScrollTimestamp_ = 0;
1000     bool prevHasFadingEdge_ = false;
1001 
1002     RefPtr<ClickRecognizer> clickRecognizer_;
1003     // dump info
1004     std::list<ScrollableEventsFiredInfo> eventsFiredInfos_;
1005     std::list<ScrollableFrameInfo> scrollableFrameInfos_;
1006     RefPtr<InputEvent> mouseEvent_;
1007     bool isMousePressed_ = false;
1008 };
1009 } // namespace OHOS::Ace::NG
1010 
1011 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_SCROLL_PATTERN_H
1012