1 /* 2 * Copyright (c) 2022-2023 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_NG_PATTERNS_SCROLL_INNER_SCROLL_BAR_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_INNER_SCROLL_BAR_H 18 19 #include <cmath> 20 21 #include "base/geometry/dimension.h" 22 #include "base/geometry/offset.h" 23 #include "base/geometry/rect.h" 24 #include "base/utils/utils.h" 25 #include "core/animation/friction_motion.h" 26 #include "core/components/common/layout/constants.h" 27 #include "core/components/common/properties/color.h" 28 #include "core/components/common/properties/edge.h" 29 #include "core/components/scroll/scroll_bar_theme.h" 30 #include "core/components_ng/base/frame_scene_status.h" 31 #include "core/components_ng/event/input_event.h" 32 #include "core/components_ng/event/touch_event.h" 33 #include "core/components_ng/gestures/recognizers/pan_recognizer.h" 34 #include "core/components_ng/pattern/scroll/inner/scroll_bar_overlay_modifier.h" 35 #include "core/components_ng/pattern/scrollable/scrollable_properties.h" 36 #include "core/components_ng/property/border_property.h" 37 38 namespace OHOS::Ace::NG { 39 40 constexpr double FACTOR_HALF = 0.5; 41 constexpr double DEFAULT_TOPANGLE = 60.0; 42 constexpr double DEFAULT_BOTTOMANGLE = 120.0; 43 constexpr double DEFAULT_MINANGLE = 10.0; 44 constexpr double STRAIGHT_ANGLE = 180.0; 45 constexpr double BAR_FRICTION = 0.9; 46 constexpr Color PRESSED_BLEND_COLOR = Color(0x19000000); 47 using DragFRCSceneCallback = std::function<void(double velocity, NG::SceneStatus sceneStatus)>; 48 49 class ScrollBar final : public AceType { 50 DECLARE_ACE_TYPE(ScrollBar, AceType); 51 52 public: 53 ScrollBar(); 54 ScrollBar(DisplayMode displayMode, ShapeMode shapeMode = ShapeMode::RECT, 55 PositionMode positionMode = PositionMode::RIGHT); 56 ~ScrollBar() override = default; 57 58 bool InBarTouchRegion(const Point& point) const; 59 bool InBarHoverRegion(const Point& point) const; 60 bool InBarRectRegion(const Point& point) const; 61 bool NeedScrollBar() const; 62 bool NeedPaint() const; 63 void UpdateScrollBarRegion( 64 const Offset& offset, const Size& size, const Offset& lastOffset, double estimatedHeight); 65 double GetNormalWidthToPx() const; 66 float CalcPatternOffset(float scrollBarOffset) const; 67 GetShapeMode()68 ShapeMode GetShapeMode() const 69 { 70 return shapeMode_; 71 } 72 GetDisplayMode()73 DisplayMode GetDisplayMode() const 74 { 75 return displayMode_; 76 } 77 GetPositionMode()78 PositionMode GetPositionMode() const 79 { 80 return positionMode_; 81 } 82 SetPadding(const Edge & padding)83 void SetPadding(const Edge& padding) 84 { 85 padding_ = padding; 86 } 87 GetPadding()88 const Edge& GetPadding() const 89 { 90 return padding_; 91 } 92 SetBackgroundColor(const Color & backgroundColor)93 void SetBackgroundColor(const Color& backgroundColor) 94 { 95 backgroundColor_ = backgroundColor; 96 } 97 GetBackgroundColor()98 const Color& GetBackgroundColor() const 99 { 100 return backgroundColor_; 101 } 102 SetForegroundColor(const Color & foregroundColor)103 void SetForegroundColor(const Color& foregroundColor) 104 { 105 foregroundColor_ = foregroundColor; 106 } 107 GetForegroundColor()108 Color GetForegroundColor() const 109 { 110 return IsPressed() ? foregroundColor_.BlendColor(PRESSED_BLEND_COLOR) : foregroundColor_; 111 } 112 GetTopAngle()113 double GetTopAngle() const 114 { 115 return topAngle_; 116 } 117 GetBottomAngle()118 double GetBottomAngle() const 119 { 120 return bottomAngle_; 121 } 122 GetTrickStartAngle()123 double GetTrickStartAngle() const 124 { 125 return trickStartAngle_; 126 } 127 GetTrickSweepAngle()128 double GetTrickSweepAngle() const 129 { 130 return trickSweepAngle_; 131 } 132 SetMinHeight(const Dimension & minHeight)133 void SetMinHeight(const Dimension& minHeight) 134 { 135 minHeight_ = minHeight; 136 } 137 GetMinHeight()138 const Dimension& GetMinHeight() const 139 { 140 return minHeight_; 141 } 142 SetMinDynamicHeight(const Dimension & minDynamicHeight)143 void SetMinDynamicHeight(const Dimension& minDynamicHeight) 144 { 145 minDynamicHeight_ = minDynamicHeight; 146 } 147 GetMinDynamicHeight()148 const Dimension& GetMinDynamicHeight() const 149 { 150 return minDynamicHeight_; 151 } 152 SetInactiveWidth(const Dimension & inactiveWidth)153 void SetInactiveWidth(const Dimension& inactiveWidth) 154 { 155 inactiveWidth_ = inactiveWidth; 156 } 157 SetActiveWidth(const Dimension & activeWidth)158 void SetActiveWidth(const Dimension& activeWidth) 159 { 160 activeWidth_ = activeWidth; 161 } 162 SetHoverWidth(const RefPtr<ScrollBarTheme> & theme)163 void SetHoverWidth(const RefPtr<ScrollBarTheme>& theme) 164 { 165 hoverWidth_ = theme->GetActiveWidth() + theme->GetScrollBarMargin() * 2; 166 } 167 GetActiveWidth()168 const Dimension& GetActiveWidth() const 169 { 170 return activeWidth_; 171 } 172 SetNormalWidth(const Dimension & normalWidth)173 void SetNormalWidth(const Dimension& normalWidth) 174 { 175 if (normalWidth_ != normalWidth) { 176 normalWidthUpdate_ = true; 177 normalWidth_ = normalWidth; 178 CalcReservedHeight(); 179 MarkNeedRender(); 180 } 181 } 182 GetActiveRect()183 const Rect& GetActiveRect() const 184 { 185 return activeRect_; 186 } 187 SetTouchWidth(const Dimension & touchWidth)188 void SetTouchWidth(const Dimension& touchWidth) 189 { 190 touchWidth_ = touchWidth; 191 } 192 GetTouchWidth()193 const Dimension& GetTouchWidth() const 194 { 195 return touchWidth_; 196 } 197 GetBarRect()198 const Rect& GetBarRect() const 199 { 200 return barRect_; 201 } 202 SetScrollable(bool isScrollable)203 void SetScrollable(bool isScrollable) 204 { 205 CHECK_NULL_VOID(isScrollable_ != isScrollable); 206 isScrollable_ = isScrollable; 207 } 208 IsScrollable()209 bool IsScrollable() const 210 { 211 return isScrollable_; 212 } 213 SetPositionMode(PositionMode positionMode)214 void SetPositionMode(PositionMode positionMode) 215 { 216 if (positionMode_ != positionMode) { 217 positionModeUpdate_ = true; 218 positionMode_ = positionMode; 219 if (panRecognizer_) { 220 PanDirection panDirection; 221 panDirection.type = 222 positionMode_ == PositionMode::BOTTOM ? PanDirection::HORIZONTAL : PanDirection::VERTICAL; 223 panRecognizer_->SetDirection(panDirection); 224 } 225 } 226 } 227 GetPositionModeUpdate()228 bool GetPositionModeUpdate() const 229 { 230 return positionModeUpdate_; 231 } 232 SetShapeMode(ShapeMode shapeMode)233 void SetShapeMode(ShapeMode shapeMode) 234 { 235 shapeMode_ = shapeMode; 236 } 237 SetDisplayMode(DisplayMode displayMode)238 void SetDisplayMode(DisplayMode displayMode) 239 { 240 CHECK_NULL_VOID(displayMode_ != displayMode); 241 displayMode_ = displayMode; 242 } 243 GetOutBoundary()244 double GetOutBoundary() const 245 { 246 return outBoundary_; 247 } 248 SetOutBoundary(double outBoundary)249 void SetOutBoundary(double outBoundary) 250 { 251 outBoundary_ = outBoundary; 252 } 253 SetIsOutOfBoundary(bool isOutOfBoundary)254 void SetIsOutOfBoundary(bool isOutOfBoundary) 255 { 256 isOutOfBoundary_ = isOutOfBoundary; 257 } 258 SetPosition(const Dimension & position)259 void SetPosition(const Dimension& position) 260 { 261 position_ = position; 262 } 263 GetPosition()264 const Dimension& GetPosition() const 265 { 266 return position_; 267 } 268 SetPressed(bool press)269 void SetPressed(bool press) 270 { 271 isPressed_ = press; 272 } 273 IsPressed()274 bool IsPressed() const 275 { 276 return isPressed_; 277 } 278 SetHover(bool hover)279 void SetHover(bool hover) 280 { 281 isHover_ = hover; 282 } 283 IsHover()284 bool IsHover() const 285 { 286 return isHover_; 287 } 288 PlayScrollBarDisappearAnimation()289 void PlayScrollBarDisappearAnimation() 290 { 291 if (displayMode_ == DisplayMode::AUTO && isScrollable_ && !isHover_ && !isPressed_) { 292 opacityAnimationType_ = OpacityAnimationType::DISAPPEAR; 293 MarkNeedRender(); 294 } 295 } 296 PlayScrollBarAppearAnimation()297 void PlayScrollBarAppearAnimation() 298 { 299 if (displayMode_ == DisplayMode::AUTO && isScrollable_) { 300 disappearDelayTask_.Cancel(); 301 opacityAnimationType_ = OpacityAnimationType::APPEAR; 302 MarkNeedRender(); 303 } 304 } 305 GetOpacityAnimationType()306 OpacityAnimationType GetOpacityAnimationType() const 307 { 308 return opacityAnimationType_; 309 } 310 SetOpacityAnimationType(OpacityAnimationType opacityAnimationType)311 void SetOpacityAnimationType(OpacityAnimationType opacityAnimationType) 312 { 313 opacityAnimationType_ = opacityAnimationType; 314 } 315 GetHoverAnimationType()316 HoverAnimationType GetHoverAnimationType() const 317 { 318 return hoverAnimationType_; 319 } 320 SetHoverAnimationType(HoverAnimationType hoverAnimationType)321 void SetHoverAnimationType(HoverAnimationType hoverAnimationType) 322 { 323 hoverAnimationType_ = hoverAnimationType; 324 } 325 326 PlayScrollBarGrowAnimation()327 void PlayScrollBarGrowAnimation() 328 { 329 PlayScrollBarAppearAnimation(); 330 normalWidth_ = activeWidth_; 331 FlushBarWidth(); 332 hoverAnimationType_ = HoverAnimationType::GROW; 333 MarkNeedRender(); 334 } 335 PlayScrollBarShrinkAnimation()336 void PlayScrollBarShrinkAnimation() 337 { 338 normalWidth_ = inactiveWidth_; 339 FlushBarWidth(); 340 hoverAnimationType_ = HoverAnimationType::SHRINK; 341 MarkNeedRender(); 342 } 343 PlayScrollBarAdaptAnimation()344 void PlayScrollBarAdaptAnimation() 345 { 346 needAdaptAnimation_ = true; 347 MarkNeedRender(); 348 } 349 GetNeedAdaptAnimation()350 bool GetNeedAdaptAnimation() const 351 { 352 return needAdaptAnimation_; 353 } 354 MarkNeedRender()355 void MarkNeedRender() 356 { 357 if (markNeedRenderFunc_) { 358 markNeedRenderFunc_(); 359 } 360 } 361 SetMarkNeedRenderFunc(std::function<void ()> && func)362 void SetMarkNeedRenderFunc(std::function<void()>&& func) 363 { 364 markNeedRenderFunc_ = func; 365 } 366 GetTouchEvent()367 RefPtr<TouchEventImpl> GetTouchEvent() 368 { 369 return touchEvent_; 370 } 371 GetMouseEvent()372 RefPtr<InputEvent> GetMouseEvent() 373 { 374 return mouseEvent_; 375 } 376 GetHoverEvent()377 RefPtr<InputEvent> GetHoverEvent() const 378 { 379 return hoverEvent_; 380 } 381 SetIsUserNormalWidth(bool isUserNormalWidth)382 void SetIsUserNormalWidth(bool isUserNormalWidth) 383 { 384 isUserNormalWidth_ = isUserNormalWidth; 385 } 386 GetIsUserNormalWidth()387 bool GetIsUserNormalWidth() const 388 { 389 return isUserNormalWidth_; 390 } 391 SetStartReservedHeight(const Dimension & startReservedHeight)392 void SetStartReservedHeight(const Dimension& startReservedHeight) 393 { 394 startReservedHeight_ = startReservedHeight; 395 } 396 GetStartReservedHeight()397 const Dimension& GetStartReservedHeight() const 398 { 399 return startReservedHeight_; 400 } 401 SetEndReservedHeight(const Dimension & endReservedHeight)402 void SetEndReservedHeight(const Dimension& endReservedHeight) 403 { 404 endReservedHeight_ = endReservedHeight; 405 } 406 GetEndReservedHeight()407 const Dimension& GetEndReservedHeight() const 408 { 409 return endReservedHeight_; 410 } 411 SetHostBorderRadius(const BorderRadiusProperty & hostBorderRadius)412 void SetHostBorderRadius(const BorderRadiusProperty& hostBorderRadius) 413 { 414 hostBorderRadius_ = hostBorderRadius; 415 } 416 GetHostBorderRadius()417 const BorderRadiusProperty& GetHostBorderRadius() const 418 { 419 return hostBorderRadius_; 420 } 421 SetScrollPositionCallback(ScrollPositionCallback && callback)422 void SetScrollPositionCallback(ScrollPositionCallback&& callback) 423 { 424 scrollPositionCallback_ = std::move(callback); 425 } 426 GetScrollPositionCallback()427 const ScrollPositionCallback& GetScrollPositionCallback() const 428 { 429 return scrollPositionCallback_; 430 } 431 SetScrollEndCallback(ScrollEndCallback && scrollEndCallback)432 void SetScrollEndCallback(ScrollEndCallback&& scrollEndCallback) 433 { 434 scrollEndCallback_ = std::move(scrollEndCallback); 435 } 436 GetScrollEndCallback()437 const ScrollEndCallback& GetScrollEndCallback() const 438 { 439 return scrollEndCallback_; 440 } 441 SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback && calePredictSnapOffsetCallback)442 void SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback&& calePredictSnapOffsetCallback) 443 { 444 calePredictSnapOffsetCallback_ = std::move(calePredictSnapOffsetCallback); 445 } 446 GetCalePredictSnapOffsetCallback()447 const CalePredictSnapOffsetCallback& GetCalePredictSnapOffsetCallback() const 448 { 449 return calePredictSnapOffsetCallback_; 450 } 451 SetStartScrollSnapMotionCallback(StartScrollSnapMotionCallback && startScrollSnapMotionCallback)452 void SetStartScrollSnapMotionCallback(StartScrollSnapMotionCallback&& startScrollSnapMotionCallback) 453 { 454 startScrollSnapMotionCallback_ = std::move(startScrollSnapMotionCallback); 455 } 456 GetStartScrollSnapMotionCallback()457 const StartScrollSnapMotionCallback& GetStartScrollSnapMotionCallback() const 458 { 459 return startScrollSnapMotionCallback_; 460 } 461 462 void SetGestureEvent(); 463 void SetMouseEvent(); 464 void SetHoverEvent(); 465 void FlushBarWidth(); 466 void CalcReservedHeight(); 467 void OnCollectTouchTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 468 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent); 469 void ScheduleDisappearDelayTask(); 470 SetDragFRCSceneCallback(DragFRCSceneCallback && dragFRCSceneCallback)471 void SetDragFRCSceneCallback(DragFRCSceneCallback&& dragFRCSceneCallback) 472 { 473 dragFRCSceneCallback_ = std::move(dragFRCSceneCallback); 474 } 475 GetMainOffset(const Offset & offset)476 float GetMainOffset(const Offset& offset) const 477 { 478 return positionMode_ == PositionMode::BOTTOM ? offset.GetX() : offset.GetY(); 479 } 480 SetDragStartPosition(float position)481 void SetDragStartPosition(float position) 482 { 483 dragStartPosition_ = position; 484 } 485 SetDragEndPosition(float position)486 void SetDragEndPosition(float position) 487 { 488 dragEndPosition_ = position; 489 } 490 GetDragOffset()491 float GetDragOffset() 492 { 493 return dragEndPosition_ - dragStartPosition_; 494 } 495 SetReverse(bool reverse)496 void SetReverse(bool reverse) 497 { 498 isReverse_ = reverse; 499 } 500 IsReverse()501 bool IsReverse() 502 { 503 return isReverse_; 504 } 505 506 protected: 507 void InitTheme(); 508 509 private: 510 void SetBarRegion(const Offset& offset, const Size& size); 511 void SetRectTrickRegion(const Offset& offset, const Size& size, const Offset& lastOffset, double mainScrollExtent); 512 void SetRoundTrickRegion(const Offset& offset, const Size& size, const Offset& lastOffset, double mainScrollExtent); 513 void UpdateActiveRectSize(double activeSize); 514 void UpdateActiveRectOffset(double activeMainOffset); 515 double NormalizeToPx(const Dimension& dimension) const; 516 void InitPanRecognizer(); 517 void HandleDragStart(const GestureEvent& info); 518 void HandleDragUpdate(const GestureEvent& info); 519 void HandleDragEnd(const GestureEvent& info); 520 void ProcessFrictionMotion(double value); 521 void ProcessFrictionMotionStop(); 522 523 DisplayMode displayMode_ = DisplayMode::AUTO; 524 ShapeMode shapeMode_ = ShapeMode::RECT; 525 PositionMode positionMode_ = PositionMode::RIGHT; 526 BorderRadiusProperty hostBorderRadius_; 527 Edge padding_; 528 Color backgroundColor_; 529 Color foregroundColor_; 530 Rect touchRegion_; 531 Rect hoverRegion_; 532 Rect barRect_; 533 Rect activeRect_; 534 Dimension minHeight_; // this is min static height 535 Dimension minDynamicHeight_; // this is min dynamic height when on the top or bottom 536 Dimension startReservedHeight_; // this is reservedHeight on the start 537 Dimension endReservedHeight_; // this is reservedHeight on the end 538 Dimension inactiveWidth_; 539 Dimension activeWidth_; 540 Dimension normalWidth_; 541 Dimension touchWidth_; 542 Dimension hoverWidth_; 543 544 Dimension position_; 545 546 double trickStartAngle_ = 0.0; 547 double trickSweepAngle_ = 0.0; 548 double topAngle_ = DEFAULT_TOPANGLE; 549 double bottomAngle_ = DEFAULT_BOTTOMANGLE; 550 double minAngle_ = DEFAULT_MINANGLE; 551 double outBoundary_ = 0.0; 552 double offsetScale_ = 1.0f; 553 double scrollableOffset_ = 0.0; 554 double barRegionSize_ = 0.0; 555 double friction_ = BAR_FRICTION; 556 double frictionPosition_ = 0.0; 557 float dragStartPosition_ = 0.0f; 558 float dragEndPosition_ = 0.0f; 559 560 bool isScrollable_ = false; 561 562 bool isPressed_ = false; 563 bool isDriving_ = false; // false: scroll driving; true: bar driving 564 bool isHover_ = false; 565 bool isOutOfBoundary_ = false; // whether bar in the spring state 566 bool positionModeUpdate_ = false; 567 bool normalWidthUpdate_ = false; 568 bool isUserNormalWidth_ = false; 569 bool needAdaptAnimation_ = false; 570 bool isReverse_ = false; 571 572 Offset paintOffset_; 573 Size viewPortSize_; 574 Offset lastOffset_; 575 double estimatedHeight_ = 0.0; 576 RefPtr<TouchEventImpl> touchEvent_; 577 RefPtr<InputEvent> mouseEvent_; 578 RefPtr<InputEvent> hoverEvent_; 579 RefPtr<PanRecognizer> panRecognizer_; 580 RefPtr<Animator> frictionController_; 581 RefPtr<FrictionMotion> frictionMotion_; 582 std::function<void()> markNeedRenderFunc_; 583 ScrollPositionCallback scrollPositionCallback_; 584 ScrollEndCallback scrollEndCallback_; 585 CalePredictSnapOffsetCallback calePredictSnapOffsetCallback_; 586 StartScrollSnapMotionCallback startScrollSnapMotionCallback_; 587 OpacityAnimationType opacityAnimationType_ = OpacityAnimationType::NONE; 588 HoverAnimationType hoverAnimationType_ = HoverAnimationType::NONE; 589 CancelableCallback<void()> disappearDelayTask_; 590 591 DragFRCSceneCallback dragFRCSceneCallback_; 592 }; 593 594 } // namespace OHOS::Ace::NG 595 596 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_INNER_SCROLL_BAR_H 597