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