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