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