• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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_SCROLL_SCROLLABLE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLLABLE_H
18 
19 #include <functional>
20 
21 #include "base/geometry/dimension.h"
22 #include "core/animation/animator.h"
23 #include "core/animation/friction_motion.h"
24 #include "core/animation/scroll_motion.h"
25 #include "core/components_ng/gestures/recognizers/pan_recognizer.h"
26 #include "core/components_ng/pattern/scrollable/scrollable_properties.h"
27 #include "core/event/axis_event.h"
28 #include "core/event/touch_event.h"
29 #include "core/gestures/pan_recognizer.h"
30 #include "core/gestures/raw_recognizer.h"
31 #include "core/gestures/timeout_recognizer.h"
32 #include "core/pipeline/base/related_node.h"
33 #include "core/pipeline/base/render_node.h"
34 
35 namespace OHOS::Ace {
36 enum class NestedState {
37     GESTURE = 0,
38     CHILD_SCROLL,
39     CHILD_OVER_SCROLL,
40 };
41 
42 struct OverScrollOffset {
43     double start;
44     double end;
45 };
46 
47 struct ScrollResult {
48     double remain;
49     bool reachEdge;
50 };
51 
52 using ScrollEventCallback = std::function<void()>;
53 using OutBoundaryCallback = std::function<bool()>;
54 using ScrollOverCallback = std::function<void(double velocity)>;
55 using WatchFixCallback = std::function<double(double final, double current)>;
56 using ScrollBeginCallback = std::function<ScrollInfo(Dimension, Dimension)>;
57 using ScrollFrameBeginCallback = std::function<ScrollFrameResult(Dimension, ScrollState)>;
58 using DragEndForRefreshCallback = std::function<void()>;
59 using DragCancelRefreshCallback = std::function<void()>;
60 using MouseLeftButtonScroll = std::function<bool()>;
61 using ScrollSnapCallback = std::function<bool(double targetOffset, double velocity)>;
62 using ContinuousSlidingCallback= std::function<double()>;
63 using CalePredictSnapOffsetCallback = std::function<std::optional<float>(float delta)>;
64 using NeedScrollSnapToSideCallback = std::function<bool(float delta)>;
65 
66 class Scrollable : public TouchEventTarget, public RelatedChild {
67     DECLARE_ACE_TYPE(Scrollable, TouchEventTarget);
68 
69 public:
70     Scrollable() = default;
Scrollable(ScrollPositionCallback && callback,Axis axis)71     Scrollable(ScrollPositionCallback&& callback, Axis axis) : callback_(std::move(callback)), axis_(axis) {}
Scrollable(const ScrollPositionCallback & callback,Axis axis)72     Scrollable(const ScrollPositionCallback& callback, Axis axis) : callback_(callback), axis_(axis) {}
73     ~Scrollable() override;
74 
75     static void SetVelocityScale(double sVelocityScale);
76     static void SetFriction(double sFriction);
77 
78     void Initialize(const WeakPtr<PipelineBase>& context);
79 
IsMotionStop()80     bool IsMotionStop() const
81     {
82         return (springController_ ? (!springController_->IsRunning()) : true) &&
83                (controller_ ? (!controller_->IsRunning()) : true) && !moved_;
84     }
85 
IsSpringMotionRunning()86     bool IsSpringMotionRunning() const
87     {
88         return springController_ ? springController_->IsRunning() : false;
89     }
90 
IsDragging()91     bool IsDragging() const
92     {
93         return isTouching_ && controller_->IsRunning();
94     }
95 
96     void SetAxis(Axis axis);
97 
SetScrollableNode(const WeakPtr<RenderNode> & node)98     void SetScrollableNode(const WeakPtr<RenderNode>& node)
99     {
100         scrollableNode_ = node;
101     }
102 
GetMainOffset(const Offset & offset)103     double GetMainOffset(const Offset& offset) const
104     {
105         return axis_ == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
106     }
107 
GetMainSize(const Size & size)108     double GetMainSize(const Size& size) const
109     {
110         return axis_ == Axis::HORIZONTAL ? size.Width() : size.Height();
111     }
112 
SetCallback(const ScrollPositionCallback & callback)113     void SetCallback(const ScrollPositionCallback& callback)
114     {
115         callback_ = callback;
116     }
117 
SetCoordinateOffset(const Offset & offset)118     void SetCoordinateOffset(const Offset& offset) const
119     {
120         if (panRecognizer_) {
121             panRecognizer_->SetCoordinateOffset(offset);
122         }
123 
124         if (panRecognizerNG_) {
125             panRecognizerNG_->SetCoordinateOffset(offset);
126         }
127 
128         if (rawRecognizer_) {
129             rawRecognizer_->SetCoordinateOffset(offset);
130         }
131     }
132 
OnCollectTouchTarget(TouchTestResult & result)133     void OnCollectTouchTarget(TouchTestResult& result)
134     {
135         if (panRecognizerNG_) {
136             result.emplace_back(panRecognizerNG_);
137         }
138 
139         if (rawRecognizer_) {
140             result.emplace_back(rawRecognizer_);
141         }
142     }
143 
SetDragTouchRestrict(const TouchRestrict & touchRestrict)144     void SetDragTouchRestrict(const TouchRestrict& touchRestrict)
145     {
146         if (panRecognizer_) {
147             panRecognizer_->SetTouchRestrict(touchRestrict);
148         }
149         if (panRecognizerNG_) {
150             panRecognizerNG_->SetTouchRestrict(touchRestrict);
151         }
152     }
153 
SetScrollEndCallback(const ScrollEventCallback & scrollEndCallback)154     void SetScrollEndCallback(const ScrollEventCallback& scrollEndCallback)
155     {
156         scrollEndCallback_ = scrollEndCallback;
157     }
158 
SetScrollTouchUpCallback(const ScrollEventCallback & scrollTouchUpCallback)159     void SetScrollTouchUpCallback(const ScrollEventCallback& scrollTouchUpCallback)
160     {
161         scrollTouchUpCallback_ = scrollTouchUpCallback;
162     }
163 
SetUnstaticFriction(double friction)164     void SetUnstaticFriction(double friction)
165     {
166         friction_ = friction;
167     }
168 
169     void HandleTouchDown();
170     void HandleTouchUp();
171     void HandleTouchCancel();
172     void HandleDragStart(const GestureEvent& info);
173     void HandleDragUpdate(const GestureEvent& info);
174     void HandleDragEnd(const GestureEvent& info);
175     void HandleScrollEnd();
176     bool HandleOverScroll(double velocity);
177     ScrollResult HandleScroll(double offset, int32_t source, NestedState state);
178     ScrollResult HandleScrollParentFirst(double& offset, int32_t source, NestedState state);
179     ScrollResult HandleScrollSelfFirst(double& offset, int32_t source, NestedState state);
180     ScrollResult HandleScrollSelfOnly(double& offset, int32_t source, NestedState state);
181     ScrollResult HandleScrollParallel(double& offset, int32_t source, NestedState state);
182 
183     void ProcessScrollMotionStop();
184 
DispatchEvent(const TouchEvent & point)185     bool DispatchEvent(const TouchEvent& point) override
186     {
187         return true;
188     }
HandleEvent(const TouchEvent & event)189     bool HandleEvent(const TouchEvent& event) override
190     {
191         if (!available_) {
192             return true;
193         }
194         if (panRecognizer_) {
195             panRecognizer_->HandleEvent(event);
196         }
197         if (rawRecognizer_) {
198             return rawRecognizer_->HandleEvent(event);
199         }
200         return true;
201     }
HandleEvent(const AxisEvent & event)202     bool HandleEvent(const AxisEvent& event) override
203     {
204         if (panRecognizer_) {
205             return panRecognizer_->HandleEvent(event);
206         }
207         return false;
208     }
209 
SetScrollEnd(const ScrollEventCallback & scrollEnd)210     void SetScrollEnd(const ScrollEventCallback& scrollEnd)
211     {
212         scrollEnd_ = scrollEnd;
213     }
214 
SetScrollOverCallBack(const ScrollOverCallback & scrollOverCallback)215     void SetScrollOverCallBack(const ScrollOverCallback& scrollOverCallback)
216     {
217         scrollOverCallback_ = scrollOverCallback;
218     }
219 
SetNotifyScrollOverCallBack(const ScrollOverCallback & scrollOverCallback)220     void SetNotifyScrollOverCallBack(const ScrollOverCallback& scrollOverCallback)
221     {
222         notifyScrollOverCallback_ = scrollOverCallback;
223     }
224 
SetOutBoundaryCallback(const OutBoundaryCallback & outBoundaryCallback)225     void SetOutBoundaryCallback(const OutBoundaryCallback& outBoundaryCallback)
226     {
227         outBoundaryCallback_ = outBoundaryCallback;
228     }
229 
SetDragEndCallback(const DragEndForRefreshCallback & dragEndCallback)230     void SetDragEndCallback(const DragEndForRefreshCallback& dragEndCallback)
231     {
232         dragEndCallback_ = dragEndCallback;
233     }
234 
SetDragCancelCallback(const DragCancelRefreshCallback & dragCancelCallback)235     void SetDragCancelCallback(const DragCancelRefreshCallback& dragCancelCallback)
236     {
237         dragCancelCallback_ = dragCancelCallback;
238     }
239 
GetDragEndCallback()240     const DragEndForRefreshCallback& GetDragEndCallback() const
241     {
242         return dragEndCallback_;
243     }
244 
GetDragCancelCallback()245     const DragCancelRefreshCallback& GetDragCancelCallback() const
246     {
247         return dragCancelCallback_;
248     }
249 
SetWatchFixCallback(const WatchFixCallback & watchFixCallback)250     void SetWatchFixCallback(const WatchFixCallback& watchFixCallback)
251     {
252         watchFixCallback_ = watchFixCallback;
253     }
254 
MarkNeedCenterFix(bool needFix)255     void MarkNeedCenterFix(bool needFix)
256     {
257         needCenterFix_ = needFix;
258     }
259 
GetCurrentVelocity()260     double GetCurrentVelocity() const
261     {
262         return currentVelocity_;
263     };
264 
265     void OnAnimateStop();
266     void ProcessScrollSnapStop();
267     void StartSpringMotion(
268         double mainPosition, double mainVelocity, const ExtentPair& extent, const ExtentPair& initExtent);
269 
270     void UpdateScrollSnapStartOffset(double offset);
271     void StartScrollSnapMotion(float predictSnapOffset, float scrollSnapVelocity);
272 
273     bool IsAnimationNotRunning() const;
274 
275     bool Idle() const;
276 
277     bool IsStopped() const;
278 
279     bool IsSpringStopped() const;
280 
281     bool IsSnapStopped() const;
282 
283     void StopScrollable();
284 
Available()285     bool Available() const
286     {
287         return available_;
288     }
289 
MarkAvailable(bool available)290     void MarkAvailable(bool available)
291     {
292         available_ = available;
293     }
294 
GetContext()295     WeakPtr<PipelineBase> GetContext() const
296     {
297         return context_;
298     }
299 
SetNodeId(int32_t nodeId)300     void SetNodeId(int32_t nodeId)
301     {
302         nodeId_ = nodeId;
303     }
304 
305     void ProcessScrollOverCallback(double velocity);
306 
307     void SetSlipFactor(double SlipFactor);
308 
SetOverSpringProperty(const RefPtr<SpringProperty> & property)309     void SetOverSpringProperty(const RefPtr<SpringProperty>& property)
310     {
311         if (property && property->IsValid()) {
312             spring_ = property;
313         }
314     }
315 
ChangeMoveStatus(bool flag)316     void ChangeMoveStatus(bool flag)
317     {
318         moved_ = flag;
319     }
320 
321     static const RefPtr<SpringProperty>& GetDefaultOverSpringProperty();
322 
GetPanRecognizer()323     RefPtr<PanRecognizer> GetPanRecognizer() const
324     {
325         return panRecognizer_;
326     }
327 
SetOnScrollBegin(const ScrollBeginCallback & scrollBeginCallback)328     void SetOnScrollBegin(const ScrollBeginCallback& scrollBeginCallback)
329     {
330         scrollBeginCallback_ = scrollBeginCallback;
331     }
332 
SetOnScrollFrameBegin(const ScrollFrameBeginCallback & scrollFrameBeginCallback)333     void SetOnScrollFrameBegin(const ScrollFrameBeginCallback& scrollFrameBeginCallback)
334     {
335         scrollFrameBeginCallback_ = scrollFrameBeginCallback;
336     }
337 
SetOnContinuousSliding(const ContinuousSlidingCallback & continuousSlidingCallback)338     void SetOnContinuousSliding(const ContinuousSlidingCallback& continuousSlidingCallback)
339     {
340         continuousSlidingCallback_ = continuousSlidingCallback;
341     }
342 
343     void OnFlushTouchEventsBegin() override;
344     void OnFlushTouchEventsEnd() override;
345 
SetNestedScrollOptions(NestedScrollOptions opt)346     void SetNestedScrollOptions(NestedScrollOptions opt)
347     {
348         nestedOpt_ = opt;
349     }
SetOverScrollOffsetCallback(std::function<OverScrollOffset (double)> && overScroll)350     void SetOverScrollOffsetCallback(std::function<OverScrollOffset(double)>&& overScroll)
351     {
352         overScrollOffsetCallback_ = std::move(overScroll);
353     }
SetParent(RefPtr<Scrollable> parent)354     void SetParent(RefPtr<Scrollable> parent)
355     {
356         parent_ = AceType::WeakClaim(AceType::RawPtr(parent));
357     }
SetEdgeEffect(EdgeEffect effect)358     void SetEdgeEffect(EdgeEffect effect)
359     {
360         edgeEffect_ = effect;
361     }
362 
SetOnScrollSnapCallback(const ScrollSnapCallback & scrollSnapCallback)363     void SetOnScrollSnapCallback(const ScrollSnapCallback& scrollSnapCallback)
364     {
365         scrollSnapCallback_ = scrollSnapCallback;
366     }
SetContinuousDragStatus(bool status)367     void SetContinuousDragStatus(bool status)
368     {
369         continuousDragStatus_ = status;
370     }
IncreaseContinueDragCount()371     void IncreaseContinueDragCount()
372     {
373         dragCount_++;
374     }
ResetContinueDragCount()375     void ResetContinueDragCount()
376     {
377         dragCount_ = 1;
378     }
SetDragStartPosition(double position)379     void SetDragStartPosition(double position)
380     {
381         dragStartPosition_ = position;
382     }
SetDragEndPosition(double position)383     void SetDragEndPosition(double position)
384     {
385         dragEndPosition_ = position;
386     }
GetDragOffset()387     double GetDragOffset()
388     {
389         return dragEndPosition_ - dragStartPosition_;
390     }
391 
SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback && calePredictSnapOffsetCallback)392     void SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback&& calePredictSnapOffsetCallback)
393     {
394         calePredictSnapOffsetCallback_ = std::move(calePredictSnapOffsetCallback);
395     }
396 
SetNeedScrollSnapToSideCallback(NeedScrollSnapToSideCallback && needScrollSnapToSideCallback)397     void SetNeedScrollSnapToSideCallback(NeedScrollSnapToSideCallback&& needScrollSnapToSideCallback)
398     {
399         needScrollSnapToSideCallback_ = std::move(needScrollSnapToSideCallback);
400     }
401 
402     void ProcessScrollSnapSpringMotion(float scrollSnapDelta, float scrollSnapVelocity);
403 
StopSnapController()404     void StopSnapController()
405     {
406         if (snapController_ && !snapController_->IsStopped()) {
407             snapController_->Stop();
408         }
409     }
410 
GetCurrentPos()411     double GetCurrentPos() const
412     {
413         return currentPos_;
414     }
415 
GetNeedScrollSnapChange()416     bool GetNeedScrollSnapChange() const
417     {
418         return needScrollSnapChange_;
419     }
420 
421 private:
422     bool UpdateScrollPosition(double offset, int32_t source) const;
423     void ProcessSpringMotion(double position);
424     void ProcessScrollMotion(double position);
425     void ProcessScrollSnapMotion(double position);
426     void FixScrollMotion(double position);
427     void ExecuteScrollBegin(double& mainDelta);
428     void ExecuteScrollFrameBegin(double& mainDelta, ScrollState state);
429     double ComputeCap(int dragCount);
430     double GetGain(double delta);
431     void SetDelayedTask();
432 
433     ScrollPositionCallback callback_;
434     ScrollEventCallback scrollEnd_;
435     ScrollEventCallback scrollEndCallback_;
436     ScrollEventCallback scrollTouchUpCallback_;
437     ScrollOverCallback scrollOverCallback_;       // scroll motion controller when edge set to spring
438     ScrollOverCallback notifyScrollOverCallback_; // scroll motion controller when edge set to spring
439     OutBoundaryCallback outBoundaryCallback_;     // whether out of boundary check when edge set to spring
440 
441     WatchFixCallback watchFixCallback_;
442     ScrollBeginCallback scrollBeginCallback_;
443     ScrollFrameBeginCallback scrollFrameBeginCallback_;
444     ScrollSnapCallback scrollSnapCallback_;
445     DragEndForRefreshCallback dragEndCallback_;
446     DragCancelRefreshCallback dragCancelCallback_;
447     ContinuousSlidingCallback continuousSlidingCallback_;
448     Axis axis_;
449     RefPtr<PanRecognizer> panRecognizer_;
450 
451     // used for ng structure.
452     RefPtr<NG::PanRecognizer> panRecognizerNG_;
453 
454     RefPtr<RawRecognizer> rawRecognizer_;
455     RefPtr<Animator> controller_;
456     RefPtr<Animator> springController_;
457     RefPtr<Animator> scrollSnapController_;
458     RefPtr<Animator> snapController_;
459     RefPtr<FrictionMotion> motion_;
460     RefPtr<ScrollMotion> scrollMotion_;
461     RefPtr<SpringMotion> scrollSnapMotion_;
462     RefPtr<SpringMotion> snapMotion_;
463     RefPtr<SpringProperty> spring_;
464     WeakPtr<PipelineBase> context_;
465     WeakPtr<RenderNode> scrollableNode_;
466     double currentPos_ = 0.0;
467     double currentVelocity_ = 0.0;
468     bool scrollPause_ = false;
469     bool touchUp_ = false;
470     bool moved_ = false;
471     bool isTouching_ = false;
472     bool available_ = true;
473     bool needCenterFix_ = false;
474     bool isDragUpdateStop_ = false;
475     int32_t nodeId_ = 0;
476     double slipFactor_ = 0.0;
477     static double sFriction_;
478     static double sVelocityScale_;
479     bool continuousDragStatus_ = false;
480     CancelableCallback<void()> task_;
481     int32_t dragCount_ = 0;
482     double lastPos_ = 0.0;
483     double dragStartPosition_ = 0.0;
484     double dragEndPosition_ = 0.0;
485     double lastVelocity_ = 0.0;
486     double friction_ = -1.0;
487 #ifdef OHOS_PLATFORM
488     int64_t startIncreaseTime_ = 0;
489 #endif
490 
491     // nested scroll
492     WeakPtr<Scrollable> parent_;
493     NestedScrollOptions nestedOpt_ = { NestedScrollMode::SELF_ONLY, NestedScrollMode::SELF_ONLY };
494     std::function<OverScrollOffset(double)> overScrollOffsetCallback_;
495     EdgeEffect edgeEffect_ = EdgeEffect::NONE;
496     bool canOverScroll_ = true;
497 
498     // scrollSnap
499     bool needScrollSnapChange_ = false;
500     CalePredictSnapOffsetCallback calePredictSnapOffsetCallback_;
501     NeedScrollSnapToSideCallback needScrollSnapToSideCallback_;
502 };
503 
504 } // namespace OHOS::Ace
505 
506 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLLABLE_H
507