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