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_GESTURES_DRAG_RECOGNIZER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_GESTURES_DRAG_RECOGNIZER_H
18 
19 #include <functional>
20 #include <unordered_map>
21 
22 #include "base/geometry/axis.h"
23 #include "base/geometry/offset.h"
24 #include "core/event/touch_event.h"
25 #include "core/gestures/gesture_recognizer.h"
26 #include "core/gestures/velocity.h"
27 #include "core/gestures/velocity_tracker.h"
28 #include "core/pipeline/pipeline_context.h"
29 
30 
31 namespace OHOS::Ace {
32 
33 class DragStartInfo : public TouchLocationInfo {
34     DECLARE_RELATIONSHIP_OF_CLASSES(DragStartInfo, TouchLocationInfo);
35 
36 public:
DragStartInfo(int32_t fingerId)37     explicit DragStartInfo(int32_t fingerId) : TouchLocationInfo("onDragStart", fingerId) {}
38     ~DragStartInfo() override = default;
39 };
40 
41 class DragUpdateInfo : public TouchLocationInfo {
42     DECLARE_RELATIONSHIP_OF_CLASSES(DragUpdateInfo, TouchLocationInfo);
43 
44 public:
DragUpdateInfo(int32_t fingerId)45     explicit DragUpdateInfo(int32_t fingerId) : TouchLocationInfo("onDragUpdate", fingerId) {}
46     ~DragUpdateInfo() override = default;
47 
SetDelta(const Offset & delta)48     DragUpdateInfo& SetDelta(const Offset& delta)
49     {
50         delta_ = delta;
51         return *this;
52     }
SetMainDelta(double mainDelta)53     DragUpdateInfo& SetMainDelta(double mainDelta)
54     {
55         mainDelta_ = mainDelta;
56         return *this;
57     }
58 
GetDelta()59     const Offset& GetDelta() const
60     {
61         return delta_;
62     }
GetMainDelta()63     double GetMainDelta() const
64     {
65         return mainDelta_;
66     }
67 
68 private:
69     // The delta offset between current point and the previous update.
70     Offset delta_;
71 
72     // The delta offset in the main axis between current point and the previous update.
73     double mainDelta_ = 0.0;
74 };
75 
76 class DragEndInfo : public TouchLocationInfo {
77     DECLARE_RELATIONSHIP_OF_CLASSES(DragEndInfo, TouchLocationInfo);
78 
79 public:
DragEndInfo(int32_t fingerId)80     explicit DragEndInfo(int32_t fingerId) : TouchLocationInfo("onDragEnd", fingerId) {}
81     ~DragEndInfo() override = default;
82 
GetVelocity()83     const Velocity& GetVelocity() const
84     {
85         return velocity_;
86     }
GetMainVelocity()87     double GetMainVelocity() const
88     {
89         return mainVelocity_;
90     }
91 
GetOffset()92     const Offset& GetOffset() const
93     {
94         return offset_;
95     }
96 
SetVelocity(const Velocity & velocity)97     DragEndInfo& SetVelocity(const Velocity& velocity)
98     {
99         velocity_ = velocity;
100         return *this;
101     }
SetMainVelocity(double mainVelocity)102     DragEndInfo& SetMainVelocity(double mainVelocity)
103     {
104         mainVelocity_ = mainVelocity;
105         return *this;
106     }
107 
SetOffset(const Offset & offset)108     DragEndInfo& SetOffset(const Offset& offset)
109     {
110         offset_ = offset;
111         return *this;
112     }
113 
114 private:
115     // The velocity of the moving touch point when it leaves screen.
116     Velocity velocity_;
117 
118     // The offset from the original touch point
119     Offset offset_;
120 
121     // The velocity of the moving touch point in main axis when it leaves screen.
122     double mainVelocity_ = 0.0;
123 };
124 
125 using DragStartCallback = std::function<void(const DragStartInfo&)>;
126 using DragUpdateCallback = std::function<void(const DragUpdateInfo&)>;
127 using DragEndCallback = std::function<void(const DragEndInfo&)>;
128 using DragCancelCallback = std::function<void()>;
129 using DragUpdateNotifyCallback = std::function<void(double x, double y, const DragUpdateInfo& updateInfo)>;
130 using DragEndNotifyCallback = std::function<void(double x, double y, const DragEndInfo& endInfo)>;
131 
132 class DragRecognizer : public GestureRecognizer {
133     DECLARE_ACE_TYPE(DragRecognizer, GestureRecognizer);
134 
135 public:
DragRecognizer(Axis axis)136     explicit DragRecognizer(Axis axis) : axis_(axis) {}
137     ~DragRecognizer() override = default;
138 
139     void OnAccepted(size_t touchId) override;
140     void OnRejected(size_t touchId) override;
141 
SetOnDragStart(const DragStartCallback & onDragStart)142     void SetOnDragStart(const DragStartCallback& onDragStart)
143     {
144         onDragStart_ = onDragStart;
145     }
146 
SetOnDragUpdate(const DragUpdateCallback & onDragUpdate)147     void SetOnDragUpdate(const DragUpdateCallback& onDragUpdate)
148     {
149         onDragUpdate_ = onDragUpdate;
150     }
151 
SetOnDragEnd(const DragEndCallback & onDragEnd)152     void SetOnDragEnd(const DragEndCallback& onDragEnd)
153     {
154         onDragEnd_ = onDragEnd;
155     }
156 
SetOnDragCancel(const DragCancelCallback & onDragCancel)157     void SetOnDragCancel(const DragCancelCallback& onDragCancel)
158     {
159         onDragCancel_ = onDragCancel;
160     }
161 
SetDragUpdateNotify(const DragUpdateNotifyCallback & onDragNotifyCall)162     void SetDragUpdateNotify(const DragUpdateNotifyCallback& onDragNotifyCall)
163     {
164         onDragUpdateNotifyCall_ = onDragNotifyCall;
165     }
166 
SetDragEndNotify(const DragEndNotifyCallback & onDragNotifyCall)167     void SetDragEndNotify(const DragEndNotifyCallback& onDragNotifyCall)
168     {
169         onDragEndNotifyCall_ = onDragNotifyCall;
170     }
171 
GetTouchRestrict()172     const TouchRestrict& GetTouchRestrict() const
173     {
174         return touchRestrict_;
175     }
176 
ReconcileFrom(const RefPtr<GestureRecognizer> & recognizer)177     bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override
178     {
179         auto drag = AceType::DynamicCast<DragRecognizer>(recognizer);
180 
181         if (!drag) {
182             return false;
183         }
184 
185         if (axis_ != drag->axis_) {
186             return false;
187         }
188 
189         onDragStart_ = drag->onDragStart_;
190         onDragUpdate_ = drag->onDragUpdate_;
191         onDragEnd_ = drag->onDragEnd_;
192         onDragCancel_ = drag->onDragCancel_;
193 
194         return true;
195     }
196 
SetContext(WeakPtr<PipelineContext> context)197     void SetContext(WeakPtr<PipelineContext> context)
198     {
199         context_ = std::move(context);
200     }
201 
202 private:
203     void HandleTouchDownEvent(const TouchEvent& event) override;
204     void HandleTouchUpEvent(const TouchEvent& event) override;
205     void HandleTouchMoveEvent(const TouchEvent& event) override;
206     void HandleTouchCancelEvent(const TouchEvent& event) override;
207     bool IsDragGestureAccept(double offset) const;
208 
209     void Accept(size_t touchId);
210     void Reject(size_t touchId);
211 
212     template<typename TFunc, typename... Ts>
AsyncCallback(TFunc && func,Ts &&...args)213     void AsyncCallback(TFunc&& func, Ts&&... args)
214     {
215         auto ctx = context_.Upgrade();
216         if (!ctx) {
217             std::forward<TFunc>(func)(std::forward<Ts>(args)...);
218             return;
219         }
220 
221         auto marker = EventMarker(
222             [f = std::forward<TFunc>(func), args = std::make_tuple(std::forward<Ts>(args)...)]() mutable {
223                 std::apply(f, std::move(args));
224             });
225 
226         ctx->FireAsyncEvent(std::move(marker));
227     }
228 
229     WeakPtr<PipelineContext> context_;
230 
231     class DragFingersInfo {
232     public:
233         DragFingersInfo() = default;
DragFingersInfo(Axis axis)234         explicit DragFingersInfo(Axis axis) : velocityTracker_(axis) {}
235         ~DragFingersInfo() = default;
236 
237         VelocityTracker velocityTracker_;
238         Offset dragOffset_;
239         DetectState states_ { DetectState::READY };
240     };
241     std::unordered_map<size_t, DragFingersInfo> dragFingers_;
242 
243     Axis axis_;
244     DragStartCallback onDragStart_;
245     DragUpdateCallback onDragUpdate_;
246     DragEndCallback onDragEnd_;
247     DragCancelCallback onDragCancel_;
248     DragUpdateNotifyCallback onDragUpdateNotifyCall_;
249     DragEndNotifyCallback onDragEndNotifyCall_;
250 };
251 
252 class VerticalDragRecognizer : public DragRecognizer {
253     DECLARE_ACE_TYPE(VerticalDragRecognizer, DragRecognizer);
254 
255 public:
VerticalDragRecognizer()256     VerticalDragRecognizer() : DragRecognizer(Axis::VERTICAL) {}
257     ~VerticalDragRecognizer() override = default;
258 };
259 
260 class HorizontalDragRecognizer : public DragRecognizer {
261     DECLARE_ACE_TYPE(HorizontalDragRecognizer, DragRecognizer);
262 
263 public:
HorizontalDragRecognizer()264     HorizontalDragRecognizer() : DragRecognizer(Axis::HORIZONTAL) {}
265     ~HorizontalDragRecognizer() override = default;
266 };
267 
268 class FreeDragRecognizer : public DragRecognizer {
269     DECLARE_ACE_TYPE(FreeDragRecognizer, DragRecognizer);
270 
271 public:
FreeDragRecognizer()272     FreeDragRecognizer() : DragRecognizer(Axis::FREE) {}
273     ~FreeDragRecognizer() override = default;
274 };
275 
276 } // namespace OHOS::Ace
277 
278 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_GESTURES_DRAG_RECOGNIZER_H
279