1 /* 2 * Copyright (c) 2022-2024 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_BAR_SCROLL_BAR_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_BAR_SCROLL_BAR_PATTERN_H 18 19 #include "base/geometry/axis.h" 20 #include "base/utils/utils.h" 21 #include "core/common/container.h" 22 #include "core/components/common/layout/constants.h" 23 #include "core/components_ng/pattern/pattern.h" 24 #include "core/components_ng/pattern/scroll/inner/scroll_bar.h" 25 #include "core/components_ng/pattern/scroll/scroll_event_hub.h" 26 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h" 27 #include "core/components_ng/pattern/scroll_bar/scroll_bar_accessibility_property.h" 28 #include "core/components_ng/pattern/scroll_bar/scroll_bar_layout_algorithm.h" 29 #include "core/components_ng/pattern/scroll_bar/scroll_bar_layout_property.h" 30 #include "core/components_ng/pattern/scroll_bar/scroll_bar_paint_property.h" 31 #include "core/components_ng/pattern/scroll_bar/scroll_bar_paint_method.h" 32 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" 33 #include "core/components_ng/render/animation_utils.h" 34 35 namespace OHOS::Ace::NG { 36 37 class ScrollBarPattern : public Pattern { 38 DECLARE_ACE_TYPE(ScrollBarPattern, Pattern); 39 40 public: 41 ScrollBarPattern() = default; ~ScrollBarPattern()42 ~ScrollBarPattern() override 43 { 44 if (scrollBarProxy_) { 45 scrollBarProxy_->UnRegisterScrollBar(AceType::WeakClaim(this)); 46 } 47 scrollBarProxy_ = nullptr; 48 scrollableEvent_ = nullptr; 49 disappearAnimation_ = nullptr; 50 } 51 IsAtomicNode()52 bool IsAtomicNode() const override 53 { 54 return false; 55 } 56 CreateLayoutProperty()57 RefPtr<LayoutProperty> CreateLayoutProperty() override 58 { 59 return MakeRefPtr<ScrollBarLayoutProperty>(); 60 } 61 CreatePaintProperty()62 RefPtr<PaintProperty> CreatePaintProperty() override 63 { 64 return MakeRefPtr<ScrollBarPaintProperty>(); 65 } 66 CreateAccessibilityProperty()67 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 68 { 69 return MakeRefPtr<ScrollBarAccessibilityProperty>(); 70 } 71 CreateLayoutAlgorithm()72 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override 73 { 74 auto layoutAlgorithm = MakeRefPtr<ScrollBarLayoutAlgorithm>(currentOffset_); 75 return layoutAlgorithm; 76 } 77 CreateEventHub()78 RefPtr<EventHub> CreateEventHub() override 79 { 80 return MakeRefPtr<ScrollEventHub>(); 81 } 82 GetCurrentPosition()83 float GetCurrentPosition() const 84 { 85 return currentOffset_; 86 } 87 SetCurrentPosition(float currentOffset)88 void SetCurrentPosition(float currentOffset) 89 { 90 currentOffset_ = currentOffset; 91 } 92 GetAxis()93 Axis GetAxis() const 94 { 95 return axis_; 96 } 97 GetScrollableDistance()98 float GetScrollableDistance() const 99 { 100 return scrollableDistance_; 101 } 102 SetScrollBarProxy(const RefPtr<ScrollBarProxy> & scrollBarProxy)103 void SetScrollBarProxy(const RefPtr<ScrollBarProxy>& scrollBarProxy) 104 { 105 scrollBarProxy_ = scrollBarProxy; 106 } 107 GetDisplayMode()108 const DisplayMode& GetDisplayMode() const 109 { 110 return displayMode_; 111 } 112 GetControlDistance()113 float GetControlDistance() const 114 { 115 return controlDistance_; 116 } 117 SetControlDistance(float controlDistance)118 void SetControlDistance(float controlDistance) 119 { 120 if (Positive(controlDistance_) ? !Positive(controlDistance) : Positive(controlDistance)) { 121 controlDistanceChanged_ = true; 122 } 123 controlDistance_ = controlDistance; 124 } 125 GetScrollableNodeOffset()126 float GetScrollableNodeOffset() const 127 { 128 return scrollableNodeOffset_; 129 } 130 SetScrollableNodeOffset(float scrollableNodeOffset)131 void SetScrollableNodeOffset(float scrollableNodeOffset) 132 { 133 scrollableNodeOffset_ = scrollableNodeOffset; 134 } 135 136 bool IsAtTop() const; 137 bool IsAtBottom() const; 138 bool UpdateCurrentOffset(float offset, int32_t source, bool isMouseWheelScroll = false); 139 140 /** 141 * @brief Stops the motion animator of the scroll bar. 142 */ StopMotion()143 inline void StopMotion() 144 { 145 if (frictionController_ && frictionController_->IsRunning()) { 146 frictionController_->Stop(); 147 } 148 } 149 // disappear Animator 150 void StartDisappearAnimator(); 151 void StopDisappearAnimator(); 152 void SetOpacity(uint8_t value); 153 void SendAccessibilityEvent(AccessibilityEventType eventType); 154 SetChildOffset(float childOffset)155 void SetChildOffset(float childOffset) 156 { 157 childOffset_ = childOffset; 158 }; 159 GetChildOffset()160 float GetChildOffset() const 161 { 162 return childOffset_; 163 }; 164 SetChildRect(const RectF & rect)165 void SetChildRect(const RectF& rect) 166 { 167 childRect_ = rect; 168 } 169 SetDisappearAnimation(const std::shared_ptr<AnimationUtils::Animation> & disappearAnimation)170 void SetDisappearAnimation(const std::shared_ptr<AnimationUtils::Animation>& disappearAnimation) 171 { 172 disappearAnimation_ = disappearAnimation; 173 } 174 175 void OnCollectTouchTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 176 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent, 177 ResponseLinkResult& responseLinkResult, bool inBarRect = false); 178 GetMainOffset(const Offset & offset)179 float GetMainOffset(const Offset& offset) const 180 { 181 return axis_ == Axis::HORIZONTAL ? offset.GetX() : offset.GetY(); 182 } 183 SetDragStartPosition(float position)184 void SetDragStartPosition(float position) 185 { 186 dragStartPosition_ = position; 187 } 188 SetDragEndPosition(float position)189 void SetDragEndPosition(float position) 190 { 191 dragEndPosition_ = position; 192 } 193 GetDragOffset()194 float GetDragOffset() 195 { 196 return dragEndPosition_ - dragStartPosition_; 197 } 198 199 void SetScrollBar(DisplayMode displayMode); 200 void UpdateScrollBarOffset(int32_t scrollSource); 201 void HandleScrollBarOutBoundary(float scrollBarOutBoundaryExtent); 202 void UpdateScrollBarRegion( 203 float offset, float estimatedHeight, Size viewPort, Offset viewOffset, int32_t scrollSource); 204 void RegisterScrollBarEventTask(); 205 void InitScrollBarGestureEvent(); 206 bool UpdateScrollBarDisplay(); 207 bool IsReverse() const; 208 void SetReverse(bool reverse); 209 GetGestureHub()210 RefPtr<GestureEventHub> GetGestureHub() 211 { 212 auto host = GetHost(); 213 CHECK_NULL_RETURN(host, nullptr); 214 auto hub = host->GetOrCreateEventHub<EventHub>(); 215 CHECK_NULL_RETURN(hub, nullptr); 216 return hub->GetOrCreateGestureEventHub(); 217 } 218 GetInputHub()219 RefPtr<InputEventHub> GetInputHub() 220 { 221 auto host = GetHost(); 222 CHECK_NULL_RETURN(host, nullptr); 223 auto hub = host->GetOrCreateEventHub<EventHub>(); 224 CHECK_NULL_RETURN(hub, nullptr); 225 return hub->GetOrCreateInputEventHub(); 226 } 227 CreateScrollBarOverlayModifier()228 void CreateScrollBarOverlayModifier() 229 { 230 CHECK_NULL_VOID(scrollBar_ && scrollBar_->NeedPaint()); 231 CHECK_NULL_VOID(!scrollBarOverlayModifier_); 232 scrollBarOverlayModifier_ = AceType::MakeRefPtr<ScrollBarOverlayModifier>(); 233 scrollBarOverlayModifier_->SetRect(scrollBar_->GetActiveRect()); 234 scrollBarOverlayModifier_->SetPositionMode(scrollBar_->GetPositionMode()); 235 } 236 CreateNodePaintMethod()237 RefPtr<NodePaintMethod> CreateNodePaintMethod() override 238 { 239 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) { 240 auto paint = MakeRefPtr<ScrollBarPaintMethod>(hasChild_); 241 paint->SetScrollBar(scrollBar_); 242 if (scrollBar_ && !HasChild()) { 243 auto activeRect = scrollBar_->GetActiveRect(); 244 auto offset = activeRect.GetOffset(); 245 auto offsetF = OffsetF(offset.GetX(), offset.GetY()); 246 auto size = activeRect.GetSize(); 247 auto sizeF = SizeF(size.Width(), size.Height()); 248 childRect_ = RectF(offsetF, sizeF); 249 } 250 CreateScrollBarOverlayModifier(); 251 paint->SetScrollBarOverlayModifier(scrollBarOverlayModifier_); 252 return paint; 253 } else { 254 return Pattern::CreateNodePaintMethod(); 255 } 256 } 257 SetChild(bool hasChild)258 void SetChild(bool hasChild) 259 { 260 hasChild_ = hasChild; 261 } 262 SetPreFrameChildState(bool preFrameChildState)263 void SetPreFrameChildState(bool preFrameChildState) 264 { 265 preFrameChildState_ = preFrameChildState; 266 } 267 GetPreFrameChildState()268 bool GetPreFrameChildState() 269 { 270 return preFrameChildState_; 271 } 272 HasChild()273 bool HasChild() 274 { 275 return hasChild_; 276 } 277 CheckChildState()278 bool CheckChildState() 279 { 280 auto currentChildState = HasChild(); 281 auto preChildState = GetPreFrameChildState(); 282 if (preChildState != currentChildState) { 283 SetPreFrameChildState(currentChildState); 284 return true; 285 } 286 return false; 287 } 288 void InitClickEvent(); 289 void HandleClickEvent(); 290 void InitLongPressEvent(); 291 void HandleLongPress(bool smooth); 292 void InitMouseEvent(); 293 bool IsInScrollBar(); 294 void ScheduleCaretLongPress(); 295 void StartLongPressEventTimer(); 296 void OnCollectClickTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 297 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent, 298 ResponseLinkResult& responseLinkResult); 299 void OnCollectLongPressTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 300 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent, 301 ResponseLinkResult& responseLinkResult); 302 void AddScrollBarLayoutInfo(); 303 304 void GetAxisDumpInfo(); 305 void GetAxisDumpInfo(std::unique_ptr<JsonValue>& json); 306 307 void GetDisplayModeDumpInfo(); 308 void GetDisplayModeDumpInfo(std::unique_ptr<JsonValue>& json); 309 310 void GetPanDirectionDumpInfo(); 311 void GetPanDirectionDumpInfo(std::unique_ptr<JsonValue>& json); 312 void DumpAdvanceInfo() override; 313 void DumpAdvanceInfo(std::unique_ptr<JsonValue>& json) override; 314 SetScrollEnabled(bool enabled)315 void SetScrollEnabled(bool enabled) 316 { 317 CHECK_NULL_VOID(scrollableEvent_); 318 scrollableEvent_->SetEnabled(enabled); 319 if (!enabled) { 320 scrollableEvent_->SetAxis(Axis::NONE); 321 } else { 322 scrollableEvent_->SetAxis(axis_); 323 } 324 } 325 326 void OnColorConfigurationUpdate() override; 327 void OnColorModeChange(uint32_t colorMode) override; 328 GetScrollBarProxy()329 RefPtr<ScrollBarProxy> GetScrollBarProxy() 330 { 331 return scrollBarProxy_; 332 } 333 SetEnableNestedSorll(bool enableNestedSorll)334 void SetEnableNestedSorll(bool enableNestedSorll) 335 { 336 enableNestedSorll_ = enableNestedSorll; 337 } 338 GetEnableNestedSorll()339 bool GetEnableNestedSorll() const 340 { 341 return enableNestedSorll_; 342 } 343 344 void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override; 345 GetScrollBar()346 RefPtr<ScrollBar> GetScrollBar() const 347 { 348 return scrollBar_; 349 } 350 351 PositionMode GetPositionMode(); 352 GetScrollBarOverlayModifier()353 RefPtr<ScrollBarOverlayModifier> GetScrollBarOverlayModifier() const 354 { 355 return scrollBarOverlayModifier_; 356 } 357 CreateScrollBar()358 virtual RefPtr<ScrollBar> CreateScrollBar() const 359 { 360 return AceType::MakeRefPtr<ScrollBar>(); 361 } 362 UseInnerScrollBar()363 virtual bool UseInnerScrollBar() const 364 { 365 return !hasChild_ && Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE); 366 } 367 368 virtual void SetBarCollectClickAndLongPressTargetCallback(); 369 SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier> & scrollBarOverlayModifier)370 void SetScrollBarOverlayModifier(RefPtr<ScrollBarOverlayModifier>& scrollBarOverlayModifier) 371 { 372 scrollBarOverlayModifier_ = scrollBarOverlayModifier; 373 } 374 375 void OnModifyDone() override; 376 377 private: 378 bool ScrollPositionCallback(double offset, int32_t source, bool isMouseWheelScroll = false); 379 void InitScrollEndCallback(); 380 void AddScrollableEvent(); 381 void SetInBarRegionCallback(); 382 void SetBarCollectTouchTargetCallback(); 383 void SetBarRectCollectTouchTargetCallback(); 384 void SetInBarRectRegionCallback(); 385 void OnAttachToFrameNode() override; 386 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 387 void ValidateOffset(); 388 void SetAccessibilityAction(); 389 void InitPanRecognizer(); 390 void HandleDragStart(const GestureEvent& info); 391 void HandleDragUpdate(const GestureEvent& info); 392 void HandleDragEnd(const GestureEvent& info); 393 void ProcessFrictionMotion(double value); 394 void ProcessFrictionMotionStop(); 395 396 RefPtr<ScrollBarProxy> scrollBarProxy_; 397 RefPtr<ScrollableEvent> scrollableEvent_; 398 Axis axis_ = Axis::VERTICAL; 399 DisplayMode displayMode_ { DisplayMode::AUTO }; 400 float currentOffset_ = 0.0f; 401 float lastOffset_ = 0.0f; 402 float scrollableDistance_ = 0.0f; 403 float controlDistance_ = 0.0f; 404 bool controlDistanceChanged_ = false; 405 float scrollableNodeOffset_ = 0.0f; 406 bool hasChild_ = false; 407 bool preFrameChildState_ = false; 408 float friction_ = BAR_FRICTION; 409 float frictionPosition_ = 0.0; 410 float dragStartPosition_ = 0.0f; 411 float dragEndPosition_ = 0.0f; 412 413 float childOffset_ = 0.0f; // main size of child 414 RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier_; 415 RefPtr<ScrollBar> scrollBar_; 416 RefPtr<PanRecognizer> panRecognizer_; 417 RefPtr<FrictionMotion> frictionMotion_; 418 RefPtr<Animator> frictionController_; 419 ScrollEndCallback scrollEndCallback_; 420 RectF childRect_; 421 uint8_t opacity_ = UINT8_MAX; 422 CancelableCallback<void()> disapplearDelayTask_; 423 std::shared_ptr<AnimationUtils::Animation> disappearAnimation_; 424 bool isReverse_ = false; 425 426 // dump info 427 std::list<OuterScrollBarLayoutInfo> outerScrollBarLayoutInfos_; 428 bool isMousePressed_ = false; 429 bool isScrolling_ = false; 430 RefPtr<ClickRecognizer> clickRecognizer_; 431 RefPtr<LongPressRecognizer> longPressRecognizer_; 432 RefPtr<InputEvent> mouseEvent_; 433 Offset locationInfo_; 434 //Determine whether the current scroll direction is scrolling upwards or downwards 435 bool scrollingUp_ = false; 436 bool scrollingDown_ = false; 437 bool enableNestedSorll_ = false; 438 }; 439 440 } // namespace OHOS::Ace::NG 441 442 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_BAR_SCROLL_BAR_PATTERN_H 443