• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_SCROLLABLE_SCROLLABLE_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLLABLE_SCROLLABLE_PATTERN_H
18 
19 #include "base/geometry/axis.h"
20 #include "core/animation/select_motion.h"
21 #include "core/components_ng/pattern/pattern.h"
22 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h"
23 #include "core/components_ng/pattern/scroll/inner/scroll_bar_overlay_modifier.h"
24 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h"
25 #include "core/components_ng/pattern/scrollable/scrollable_coordination_event.h"
26 #include "core/components_ng/pattern/scrollable/scrollable_paint_property.h"
27 #include "core/event/mouse_event.h"
28 #include "core/components_ng/pattern/navigation/nav_bar_pattern.h"
29 
30 namespace OHOS::Ace::NG {
31 #ifndef WEARABLE_PRODUCT
32 constexpr double FRICTION = 0.6;
33 #else
34 constexpr double FRICTION = 0.9;
35 #endif
36 class ScrollablePattern : public Pattern {
37     DECLARE_ACE_TYPE(ScrollablePattern, Pattern);
38 
39 public:
IsAtomicNode()40     bool IsAtomicNode() const override
41     {
42         return false;
43     }
44 
45     // scrollable
GetAxis()46     Axis GetAxis() const
47     {
48         return axis_;
49     }
50     void SetAxis(Axis axis);
51     virtual bool UpdateCurrentOffset(float delta, int32_t source) = 0;
IsScrollable()52     virtual bool IsScrollable() const
53     {
54         return false;
55     }
56     virtual bool IsAtTop() const = 0;
57     virtual bool IsAtBottom() const = 0;
OutBoundaryCallback()58     virtual bool OutBoundaryCallback()
59     {
60         return IsAtTop() || IsAtBottom();
61     }
62     void AddScrollEvent();
GetScrollableEvent()63     RefPtr<ScrollableEvent> GetScrollableEvent()
64     {
65         return scrollableEvent_;
66     }
67     virtual bool OnScrollCallback(float offset, int32_t source);
OnScrollEndCallback()68     virtual void OnScrollEndCallback() {};
OnScrollStartCallback()69     virtual void OnScrollStartCallback() {};
ScrollableIdle()70     bool ScrollableIdle()
71     {
72         return !scrollableEvent_ || scrollableEvent_->Idle();
73     }
SetScrollEnable(bool enable)74     void SetScrollEnable(bool enable)
75     {
76         CHECK_NULL_VOID_NOLOG(scrollableEvent_);
77         scrollableEvent_->SetEnabled(enable);
78         if (!enable) {
79             scrollableEvent_->SetAxis(Axis::NONE);
80         } else {
81             scrollableEvent_->SetAxis(axis_);
82         }
83     }
84     void SetScrollableAxis(Axis axis);
85     RefPtr<GestureEventHub> GetGestureHub();
86     RefPtr<InputEventHub> GetInputHub();
87 
88     // edgeEffect
GetScrollEdgeEffect()89     const RefPtr<ScrollEdgeEffect>& GetScrollEdgeEffect() const
90     {
91         return scrollEffect_;
92     }
93     void SetEdgeEffect(EdgeEffect edgeEffect);
94     void AddScrollEdgeEffect(RefPtr<ScrollEdgeEffect> edgeEffect);
95     bool HandleEdgeEffect(float offset, int32_t source, const SizeF& size);
SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect> & scrollEffect)96     virtual void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) {}
IsRestrictBoundary()97     bool IsRestrictBoundary()
98     {
99         return !scrollEffect_ || scrollEffect_->IsRestrictBoundary();
100     }
101 
102     // scrollBar
103     virtual void UpdateScrollBarOffset() = 0;
104     void SetScrollBar(const std::unique_ptr<ScrollBarProperty>& property);
105     void SetScrollBar(DisplayMode displayMode);
106     void SetScrollBarProxy(const RefPtr<ScrollBarProxy>& scrollBarProxy);
107     void CreateScrollBarOverlayModifier();
108 
GetScrollableDistance()109     float GetScrollableDistance() const
110     {
111         return estimatedHeight_;
112     }
113 
GetBarOffset()114     float GetBarOffset() const
115     {
116         return barOffset_;
117     }
118 
GetScrollBarOutBoundaryExtent()119     double GetScrollBarOutBoundaryExtent() const
120     {
121         return scrollBarOutBoundaryExtent_;
122     }
123 
SetScrollBarOutBoundaryExtent(float scrollBarOutBoundaryExtent)124     void SetScrollBarOutBoundaryExtent(float scrollBarOutBoundaryExtent)
125     {
126         scrollBarOutBoundaryExtent_ = scrollBarOutBoundaryExtent;
127     }
128 
129     void HandleScrollBarOutBoundary(float scrollBarOutBoundaryExtent);
130 
GetMainSize(const SizeF & size)131     double GetMainSize(const SizeF& size) const
132     {
133         return axis_ == Axis::HORIZONTAL ? size.Width() : size.Height();
134     }
135 
SetCoordinationEvent(RefPtr<ScrollableCoordinationEvent> coordinationEvent)136     void SetCoordinationEvent(RefPtr<ScrollableCoordinationEvent> coordinationEvent)
137     {
138         coordinationEvent_ = coordinationEvent;
139     }
140 
IsScrollableStopped()141     bool IsScrollableStopped() const
142     {
143         CHECK_NULL_RETURN_NOLOG(scrollableEvent_, true);
144         auto scrollable = scrollableEvent_->GetScrollable();
145         CHECK_NULL_RETURN_NOLOG(scrollable, true);
146         return scrollable->IsStopped();
147     }
148 
StopScrollable()149     void StopScrollable()
150     {
151         CHECK_NULL_VOID_NOLOG(scrollableEvent_);
152         auto scrollable = scrollableEvent_->GetScrollable();
153         CHECK_NULL_VOID_NOLOG(scrollable);
154         scrollable->StopScrollable();
155     }
156 
StartScrollSnapMotion(float scrollSnapDelta,float scrollSnapVelocity)157     void StartScrollSnapMotion(float scrollSnapDelta, float scrollSnapVelocity)
158     {
159         CHECK_NULL_VOID_NOLOG(scrollableEvent_);
160         auto scrollable = scrollableEvent_->GetScrollable();
161         CHECK_NULL_VOID_NOLOG(scrollable);
162         scrollable->ProcessScrollSnapSpringMotion(scrollSnapDelta, scrollSnapVelocity);
163     }
164 
SetScrollFrameBeginCallback(const ScrollFrameBeginCallback & scrollFrameBeginCallback)165     void SetScrollFrameBeginCallback(const ScrollFrameBeginCallback& scrollFrameBeginCallback)
166     {
167         CHECK_NULL_VOID_NOLOG(scrollableEvent_);
168         auto scrollable = scrollableEvent_->GetScrollable();
169         CHECK_NULL_VOID_NOLOG(scrollable);
170         scrollable->SetOnScrollFrameBegin(scrollFrameBeginCallback);
171     }
172 
IsScrollableSpringEffect()173     bool IsScrollableSpringEffect() const
174     {
175         CHECK_NULL_RETURN_NOLOG(scrollEffect_, false);
176         return scrollEffect_->IsSpringEffect();
177     }
178 
SetCoordEventNeedSpringEffect(bool IsCoordEventNeedSpring)179     void SetCoordEventNeedSpringEffect(bool IsCoordEventNeedSpring)
180     {
181         isCoordEventNeedSpring_ = IsCoordEventNeedSpring;
182     }
183 
184     void SetNestedScroll(const NestedScrollOptions& nestedOpt);
185     RefPtr<ScrollablePattern> GetParentScrollable();
186     void GetParentNavigition();
187 
GetOverScrollOffset(double delta)188     virtual OverScrollOffset GetOverScrollOffset(double delta) const
189     {
190         return { 0, 0 };
191     }
192 
OnScrollSnapCallback(double targetOffset,double velocity)193     virtual bool OnScrollSnapCallback(double targetOffset, double velocity)
194     {
195         return false;
196     }
197 
StartScrollBarAnimatorByProxy()198     void StartScrollBarAnimatorByProxy()
199     {
200         if (scrollBarProxy_) {
201             scrollBarProxy_->StartScrollBarAnimator();
202         }
203     }
204 
StopScrollBarAnimatorByProxy()205     void StopScrollBarAnimatorByProxy()
206     {
207         if (scrollBarProxy_) {
208             scrollBarProxy_->StopScrollBarAnimator();
209         }
210     }
211 
212     void SetFriction(double friction);
213 
GetFriction()214     double GetFriction() const
215     {
216         return friction_;
217     }
218 
219     void StopAnimate();
AnimateRunning()220     bool AnimateRunning() const
221     {
222         return animator_ && animator_->IsRunning();
223     }
AnimateStoped()224     bool AnimateStoped() const
225     {
226         return !animator_ || animator_->IsStopped();
227     }
AbortScrollAnimator()228     void AbortScrollAnimator()
229     {
230         if (animator_ && !animator_->IsStopped()) {
231             scrollAbort_ = true;
232             animator_->Stop();
233         }
234     }
GetScrollAbort()235     bool GetScrollAbort() const
236     {
237         return scrollAbort_;
238     }
SetScrollAbort(bool abort)239     void SetScrollAbort(bool abort)
240     {
241         scrollAbort_ = abort;
242     }
243     void PlaySpringAnimation(float position, float velocity, float mass, float stiffness, float damping);
GetTotalOffset()244     virtual float GetTotalOffset() const
245     {
246         return 0.0f;
247     }
248     // main size of all children
GetTotalHeight()249     virtual float GetTotalHeight() const
250     {
251         return 0.0f;
252     }
OnAnimateStop()253     virtual void OnAnimateStop() {}
254     virtual void ScrollTo(float position);
255     virtual void AnimateTo(float position, float duration, const RefPtr<Curve>& curve, bool smooth);
CanOverScroll(int32_t source)256     bool CanOverScroll(int32_t source)
257     {
258         return (IsScrollableSpringEffect() && source != SCROLL_FROM_AXIS && source != SCROLL_FROM_BAR &&
259             source != SCROLL_FROM_NONE && IsScrollable() && (!ScrollableIdle() || animateOverScroll_));
260     }
261     void MarkSelectedItems();
262     bool ShouldSelectScrollBeStopped();
263 
264     // scrollSnap
CalePredictSnapOffset(float delta)265     virtual std::optional<float> CalePredictSnapOffset(float delta)
266     {
267         std::optional<float> predictSnapPosition;
268         return predictSnapPosition;
269     }
270 
NeedScrollSnapToSide(float delta)271     virtual bool NeedScrollSnapToSide(float delta)
272     {
273         return false;
274     }
275 
SetScrollSource(int32_t scrollSource)276     void SetScrollSource(int32_t scrollSource)
277     {
278         if (scrollSource == SCROLL_FROM_JUMP) {
279             if (scrollBar_ && scrollBarOverlayModifier_) {
280                 scrollBarOverlayModifier_->SetOpacity(UINT8_MAX);
281                 scrollBar_->ScheduleDisapplearDelayTask();
282             }
283             StopScrollBarAnimatorByProxy();
284             StartScrollBarAnimatorByProxy();
285         }
286 
287         scrollSource_ = scrollSource;
288     }
289 
GetScrollSource()290     int32_t GetScrollSource() const
291     {
292         return scrollSource_;
293     }
294 
295 protected:
GetScrollBar()296     RefPtr<ScrollBar> GetScrollBar() const
297     {
298         return scrollBar_;
299     }
GetScrollBarProxy()300     RefPtr<NG::ScrollBarProxy> GetScrollBarProxy() const
301     {
302         return scrollBarProxy_;
303     }
304     void UpdateScrollBarRegion(float offset, float estimatedHeight, Size viewPort, Offset viewOffset);
305 
306     // select with mouse
307     struct ItemSelectedStatus {
308         std::function<void(bool)> onSelected;
309         std::function<void(bool)> selectChangeEvent;
310         RectF rect;
311         bool selected = false;
FireSelectChangeEventItemSelectedStatus312         void FireSelectChangeEvent(bool isSelected)
313         {
314             if (selected == isSelected) {
315                 return;
316             }
317             selected = isSelected;
318             if (onSelected) {
319                 onSelected(isSelected);
320             }
321             if (selectChangeEvent) {
322                 selectChangeEvent(isSelected);
323             }
324         }
325     };
326     void InitMouseEvent();
327     void UninitMouseEvent();
328     void DrawSelectedZone(const RectF& selectedZone);
329     void ClearSelectedZone();
330     bool multiSelectable_ = false;
331     bool isMouseEventInit_ = false;
332     OffsetF mouseStartOffset_;
333     float totalOffsetOfMousePressed_ = 0.0f;
334     std::unordered_map<int32_t, ItemSelectedStatus> itemToBeSelected_;
335 
GetScrollBarOverlayModifier()336     RefPtr<ScrollBarOverlayModifier> GetScrollBarOverlayModifier() const
337     {
338         return scrollBarOverlayModifier_;
339     }
340 
SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier)341     void SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier)
342     {
343         scrollBarOverlayModifier_ = scrollBarOverlayModifier;
344     }
345 
346 private:
347     void DraggedDownScrollEndProcess();
348     void RegisterScrollBarEventTask();
349     void OnScrollEnd();
350     bool OnScrollPosition(double offset, int32_t source);
351     void SetParentScrollable();
352     void ProcessNavBarReactOnStart();
353     bool ProcessNavBarReactOnUpdate(bool isDraggedDown, float offset);
354     void ProcessNavBarReactOnEnd();
355 
356     void OnAttachToFrameNode() override;
357 
358     // select with mouse
MultiSelectWithoutKeyboard(const RectF & selectedZone)359     virtual void MultiSelectWithoutKeyboard(const RectF& selectedZone) {};
ClearMultiSelect()360     virtual void ClearMultiSelect() {};
IsItemSelected(const MouseInfo & info)361     virtual bool IsItemSelected(const MouseInfo& info)
362     {
363         return false;
364     }
365     void ClearInvisibleItemsSelectedStatus();
366     void HandleInvisibleItemsSelectedStatus(const RectF& selectedZone);
367     void HandleMouseEventWithoutKeyboard(const MouseInfo& info);
368     void OnMouseRelease();
369     void SelectWithScroll();
370     RectF ComputeSelectedZone(const OffsetF& startOffset, const OffsetF& endOffset);
371     float GetOutOfScrollableOffset() const;
372     void SetNavBarVelocity();
373 
374     Axis axis_;
375     RefPtr<ScrollableEvent> scrollableEvent_;
376     RefPtr<ScrollEdgeEffect> scrollEffect_;
377     RefPtr<ScrollableCoordinationEvent> coordinationEvent_;
378     int32_t scrollSource_ = SCROLL_FROM_NONE;
379     // scrollBar
380     RefPtr<ScrollBar> scrollBar_;
381     RefPtr<NG::ScrollBarProxy> scrollBarProxy_;
382     RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier_;
383     float barOffset_ = 0.0f;
384     float estimatedHeight_ = 0.0f;
385     bool isReactInParentMovement_ = false;
386     double scrollBarOutBoundaryExtent_ = 0.0;
387     bool isCoordEventNeedSpring_ = true;
388     double friction_ = FRICTION;
389     // scroller
390     RefPtr<Animator> animator_;
391     RefPtr<SpringMotion> springMotion_;
392     bool scrollAbort_ = false;
393     bool animateOverScroll_ = false;
394 
395     NestedScrollOptions nestedScroll_;
396 
397     // select with mouse
398     bool mousePressed_ = false;
399     OffsetF mouseEndOffset_;
400     OffsetF mousePressOffset_;
401     MouseInfo lastMouseMove_;
402     RefPtr<SelectMotion> selectMotion_;
403     RefPtr<InputEvent> mouseEvent_;
404     RefPtr<NavBarPattern> navBarPattern_;
405 };
406 } // namespace OHOS::Ace::NG
407 
408 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_SCROLL_PATTERN_H
409