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