• 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/event/axis_event.h"
27 #include "core/event/touch_event.h"
28 #include "core/gestures/pan_recognizer.h"
29 #include "core/gestures/raw_recognizer.h"
30 #include "core/gestures/timeout_recognizer.h"
31 #include "core/pipeline/base/related_node.h"
32 #include "core/pipeline/base/render_node.h"
33 
34 namespace OHOS::Ace {
35 
36 enum class ScrollState {
37     IDLE = 0,
38     SCROLL,
39     FLING,
40 };
41 
42 struct ScrollInfo {
43     Dimension dx;
44     Dimension dy;
45 
46     bool operator==(const ScrollInfo& scrollInfo) const
47     {
48         return dx == scrollInfo.dx && dy == scrollInfo.dy;
49     }
50 };
51 
52 struct ScrollFrameInfo {
53     Dimension offset;
54     ScrollState state;
55 
56     bool operator==(const ScrollFrameInfo& scrollInfo) const
57     {
58         return offset == scrollInfo.offset && state == scrollInfo.state;
59     }
60 };
61 
62 struct ScrollFrameResult {
63     Dimension offset;
64 
65     bool operator==(const ScrollFrameResult& scrollRes) const
66     {
67         return offset == scrollRes.offset;
68     }
69 };
70 
71 constexpr int32_t SCROLL_FROM_NONE = 0;
72 constexpr int32_t SCROLL_FROM_UPDATE = 1;
73 constexpr int32_t SCROLL_FROM_ANIMATION = 2;
74 constexpr int32_t SCROLL_FROM_JUMP = 3;
75 constexpr int32_t SCROLL_FROM_ANIMATION_SPRING = 4;
76 constexpr int32_t SCROLL_FROM_CHILD = 5;
77 constexpr int32_t SCROLL_FROM_BAR = 6;
78 constexpr int32_t SCROLL_FROM_FOCUS_JUMP = 7;
79 constexpr int32_t SCROLL_FROM_ROTATE = 8;
80 constexpr int32_t SCROLL_FROM_INDEXER = 9;
81 constexpr int32_t SCROLL_FROM_START = 10; // from drag start
82 constexpr int32_t SCROLL_FROM_AXIS = 11;
83 
84 using ScrollPositionCallback = std::function<bool(double, int32_t source)>;
85 using ScrollEventCallback = std::function<void()>;
86 using OutBoundaryCallback = std::function<bool()>;
87 using ScrollOverCallback = std::function<void(double velocity)>;
88 using WatchFixCallback = std::function<double(double final, double current)>;
89 using ScrollBeginCallback = std::function<ScrollInfo(Dimension, Dimension)>;
90 using ScrollFrameBeginCallback = std::function<ScrollFrameResult(Dimension, ScrollState)>;
91 using DragEndForRefreshCallback = std::function<void()>;
92 using DragCancelRefreshCallback = std::function<void()>;
93 
94 class Scrollable : public TouchEventTarget, public RelatedChild {
95     DECLARE_ACE_TYPE(Scrollable, TouchEventTarget);
96 
97 public:
98     Scrollable() = default;
Scrollable(ScrollPositionCallback && callback,Axis axis)99     Scrollable(ScrollPositionCallback&& callback, Axis axis) : callback_(std::move(callback)), axis_(axis) {}
Scrollable(const ScrollPositionCallback & callback,Axis axis)100     Scrollable(const ScrollPositionCallback& callback, Axis axis) : callback_(callback), axis_(axis) {}
101     ~Scrollable() override;
102 
103     static void SetVelocityScale(double sVelocityScale);
104     static void SetFriction(double sFriction);
105 
106     void Initialize(const WeakPtr<PipelineBase>& context);
107 
IsMotionStop()108     bool IsMotionStop() const
109     {
110         return (springController_ ? (!springController_->IsRunning()) : true) &&
111                (controller_ ? (!controller_->IsRunning()) : true) && !moved_;
112     }
113 
IsSpringMotionRunning()114     bool IsSpringMotionRunning() const
115     {
116         return springController_ ? springController_->IsRunning() : false;
117     }
118 
IsDragging()119     bool IsDragging() const
120     {
121         return isTouching_ && controller_->IsRunning();
122     }
123 
124     void SetAxis(Axis axis);
125 
SetScrollableNode(const WeakPtr<RenderNode> & node)126     void SetScrollableNode(const WeakPtr<RenderNode>& node)
127     {
128         scrollableNode_ = node;
129     }
130 
GetMainOffset(const Offset & offset)131     double GetMainOffset(const Offset& offset) const
132     {
133         return axis_ == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
134     }
135 
GetMainSize(const Size & size)136     double GetMainSize(const Size& size) const
137     {
138         return axis_ == Axis::HORIZONTAL ? size.Width() : size.Height();
139     }
140 
SetCallback(const ScrollPositionCallback & callback)141     void SetCallback(const ScrollPositionCallback& callback)
142     {
143         callback_ = callback;
144     }
145 
SetCoordinateOffset(const Offset & offset)146     void SetCoordinateOffset(const Offset& offset) const
147     {
148         if (panRecognizer_) {
149             panRecognizer_->SetCoordinateOffset(offset);
150         }
151 
152         if (panRecognizerNG_) {
153             panRecognizerNG_->SetCoordinateOffset(offset);
154         }
155 
156         if (rawRecognizer_) {
157             rawRecognizer_->SetCoordinateOffset(offset);
158         }
159     }
160 
OnCollectTouchTarget(TouchTestResult & result)161     void OnCollectTouchTarget(TouchTestResult& result)
162     {
163         if (panRecognizerNG_) {
164             result.emplace_back(panRecognizerNG_);
165         }
166 
167         if (rawRecognizer_) {
168             result.emplace_back(rawRecognizer_);
169         }
170     }
171 
SetDragTouchRestrict(const TouchRestrict & touchRestrict)172     void SetDragTouchRestrict(const TouchRestrict& touchRestrict)
173     {
174         if (panRecognizer_) {
175             panRecognizer_->SetTouchRestrict(touchRestrict);
176         }
177         if (panRecognizerNG_) {
178             panRecognizerNG_->SetTouchRestrict(touchRestrict);
179         }
180     }
181 
SetScrollEndCallback(const ScrollEventCallback & scrollEndCallback)182     void SetScrollEndCallback(const ScrollEventCallback& scrollEndCallback)
183     {
184         scrollEndCallback_ = scrollEndCallback;
185     }
186 
SetScrollTouchUpCallback(const ScrollEventCallback & scrollTouchUpCallback)187     void SetScrollTouchUpCallback(const ScrollEventCallback& scrollTouchUpCallback)
188     {
189         scrollTouchUpCallback_ = scrollTouchUpCallback;
190     }
191 
192     void HandleTouchDown();
193     void HandleTouchUp();
194     void HandleTouchCancel();
195     void HandleDragStart(const GestureEvent& info);
196     void HandleDragUpdate(const GestureEvent& info);
197     void HandleDragEnd(const GestureEvent& info);
198 
199     void ProcessScrollMotionStop();
200 
DispatchEvent(const TouchEvent & point)201     bool DispatchEvent(const TouchEvent& point) override
202     {
203         return true;
204     }
HandleEvent(const TouchEvent & event)205     bool HandleEvent(const TouchEvent& event) override
206     {
207         if (!available_) {
208             return true;
209         }
210         if (panRecognizer_) {
211             panRecognizer_->HandleEvent(event);
212         }
213         if (rawRecognizer_) {
214             return rawRecognizer_->HandleEvent(event);
215         }
216         return true;
217     }
HandleEvent(const AxisEvent & event)218     bool HandleEvent(const AxisEvent& event) override
219     {
220         if (panRecognizer_) {
221             return panRecognizer_->HandleEvent(event);
222         }
223         return false;
224     }
225 
SetScrollEnd(const ScrollEventCallback & scrollEnd)226     void SetScrollEnd(const ScrollEventCallback& scrollEnd)
227     {
228         scrollEnd_ = scrollEnd;
229     }
230 
SetScrollOverCallBack(const ScrollOverCallback & scrollOverCallback)231     void SetScrollOverCallBack(const ScrollOverCallback& scrollOverCallback)
232     {
233         scrollOverCallback_ = scrollOverCallback;
234     }
235 
SetNotifyScrollOverCallBack(const ScrollOverCallback & scrollOverCallback)236     void SetNotifyScrollOverCallBack(const ScrollOverCallback& scrollOverCallback)
237     {
238         notifyScrollOverCallback_ = scrollOverCallback;
239     }
240 
SetOutBoundaryCallback(const OutBoundaryCallback & outBoundaryCallback)241     void SetOutBoundaryCallback(const OutBoundaryCallback& outBoundaryCallback)
242     {
243         outBoundaryCallback_ = outBoundaryCallback;
244     }
245 
SetDragEndCallback(const DragEndForRefreshCallback & dragEndCallback)246     void SetDragEndCallback(const DragEndForRefreshCallback& dragEndCallback)
247     {
248         dragEndCallback_ = dragEndCallback;
249     }
250 
SetDragCancelCallback(const DragCancelRefreshCallback & dragCancelCallback)251     void SetDragCancelCallback(const DragCancelRefreshCallback& dragCancelCallback)
252     {
253         dragCancelCallback_ = dragCancelCallback;
254     }
255 
GetDragEndCallback()256     const DragEndForRefreshCallback& GetDragEndCallback() const
257     {
258         return dragEndCallback_;
259     }
260 
GetDragCancelCallback()261     const DragCancelRefreshCallback& GetDragCancelCallback() const
262     {
263         return dragCancelCallback_;
264     }
265 
SetWatchFixCallback(const WatchFixCallback & watchFixCallback)266     void SetWatchFixCallback(const WatchFixCallback& watchFixCallback)
267     {
268         watchFixCallback_ = watchFixCallback;
269     }
270 
MarkNeedCenterFix(bool needFix)271     void MarkNeedCenterFix(bool needFix)
272     {
273         needCenterFix_ = needFix;
274     }
275 
GetCurrentVelocity()276     double GetCurrentVelocity() const
277     {
278         return currentVelocity_;
279     };
280 
281     void StartSpringMotion(
282         double mainPosition, double mainVelocity, const ExtentPair& extent, const ExtentPair& initExtent);
283 
284     bool IsAnimationNotRunning() const;
285 
286     bool Idle() const;
287 
288     bool IsStopped() const;
289 
290     bool IsSpringStopped() const;
291 
292     void StopScrollable();
293 
Available()294     bool Available() const
295     {
296         return available_;
297     }
298 
MarkAvailable(bool available)299     void MarkAvailable(bool available)
300     {
301         available_ = available;
302     }
303 
GetContext()304     WeakPtr<PipelineBase> GetContext() const
305     {
306         return context_;
307     }
308 
SetNodeId(int32_t nodeId)309     void SetNodeId(int32_t nodeId)
310     {
311         nodeId_ = nodeId;
312     }
313 
314     void ProcessScrollOverCallback(double velocity);
315 
316     void SetSlipFactor(double SlipFactor);
317 
SetOverSpringProperty(const RefPtr<SpringProperty> & property)318     void SetOverSpringProperty(const RefPtr<SpringProperty>& property)
319     {
320         if (property && property->IsValid()) {
321             spring_ = property;
322         }
323     }
324 
ChangeMoveStatus(bool flag)325     void ChangeMoveStatus(bool flag)
326     {
327         moved_ = flag;
328     }
329 
330     static const RefPtr<SpringProperty>& GetDefaultOverSpringProperty();
331 
GetPanRecognizer()332     RefPtr<PanRecognizer> GetPanRecognizer() const
333     {
334         return panRecognizer_;
335     }
336 
SetOnScrollBegin(const ScrollBeginCallback & scrollBeginCallback)337     void SetOnScrollBegin(const ScrollBeginCallback& scrollBeginCallback)
338     {
339         scrollBeginCallback_ = scrollBeginCallback;
340     }
341 
SetOnScrollFrameBegin(const ScrollFrameBeginCallback & scrollFrameBeginCallback)342     void SetOnScrollFrameBegin(const ScrollFrameBeginCallback& scrollFrameBeginCallback)
343     {
344         scrollFrameBeginCallback_ = scrollFrameBeginCallback;
345     }
346 
347     void OnFlushTouchEventsBegin() override;
348     void OnFlushTouchEventsEnd() override;
349 
350 private:
351     bool UpdateScrollPosition(double offset, int32_t source) const;
352     void ProcessSpringMotion(double position);
353     void ProcessScrollMotion(double position);
354     void FixScrollMotion(double position);
355     void ExecuteScrollBegin(double& mainDelta);
356     void ExecuteScrollFrameBegin(double& mainDelta, ScrollState state);
357 
358     ScrollPositionCallback callback_;
359     ScrollEventCallback scrollEnd_;
360     ScrollEventCallback scrollEndCallback_;
361     ScrollEventCallback scrollTouchUpCallback_;
362     ScrollOverCallback scrollOverCallback_;       // scroll motion controller when edge set to spring
363     ScrollOverCallback notifyScrollOverCallback_; // scroll motion controller when edge set to spring
364     OutBoundaryCallback outBoundaryCallback_;     // whether out of boundary check when edge set to spring
365 
366     WatchFixCallback watchFixCallback_;
367     ScrollBeginCallback scrollBeginCallback_;
368     ScrollFrameBeginCallback scrollFrameBeginCallback_;
369     DragEndForRefreshCallback dragEndCallback_;
370     DragCancelRefreshCallback dragCancelCallback_;
371     Axis axis_;
372     RefPtr<PanRecognizer> panRecognizer_;
373 
374     // used for ng structure.
375     RefPtr<NG::PanRecognizer> panRecognizerNG_;
376 
377     RefPtr<RawRecognizer> rawRecognizer_;
378     RefPtr<Animator> controller_;
379     RefPtr<Animator> springController_;
380     RefPtr<FrictionMotion> motion_;
381     RefPtr<ScrollMotion> scrollMotion_;
382     RefPtr<SpringProperty> spring_;
383     WeakPtr<PipelineBase> context_;
384     WeakPtr<RenderNode> scrollableNode_;
385     double currentPos_ = 0.0;
386     double currentVelocity_ = 0.0;
387     bool scrollPause_ = false;
388     bool touchUp_ = false;
389     bool moved_ = false;
390     bool isTouching_ = false;
391     bool available_ = true;
392     bool needCenterFix_ = false;
393     bool isDragUpdateStop_ = false;
394     int32_t nodeId_ = 0;
395     double slipFactor_ = 0.0;
396     static double sFriction_;
397     static double sVelocityScale_;
398 #ifdef OHOS_PLATFORM
399     int64_t startIncreaseTime_ = 0;
400 #endif
401 };
402 
403 } // namespace OHOS::Ace
404 
405 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLLABLE_H
406