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