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); 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); 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 SetScrollBar(DisplayMode displayMode); 194 void UpdateScrollBarOffset(); 195 void HandleScrollBarOutBoundary(float scrollBarOutBoundaryExtent); 196 void UpdateScrollBarRegion(float offset, float estimatedHeight, Size viewPort, Offset viewOffset); 197 void RegisterScrollBarEventTask(); 198 bool UpdateScrollBarDisplay(); 199 bool IsReverse() const; 200 void SetReverse(bool reverse); 201 GetGestureHub()202 RefPtr<GestureEventHub> GetGestureHub() 203 { 204 auto host = GetHost(); 205 CHECK_NULL_RETURN(host, nullptr); 206 auto hub = host->GetEventHub<EventHub>(); 207 CHECK_NULL_RETURN(hub, nullptr); 208 return hub->GetOrCreateGestureEventHub(); 209 } 210 GetInputHub()211 RefPtr<InputEventHub> GetInputHub() 212 { 213 auto host = GetHost(); 214 CHECK_NULL_RETURN(host, nullptr); 215 auto hub = host->GetEventHub<EventHub>(); 216 CHECK_NULL_RETURN(hub, nullptr); 217 return hub->GetOrCreateInputEventHub(); 218 } 219 CreateScrollBarOverlayModifier()220 void CreateScrollBarOverlayModifier() 221 { 222 CHECK_NULL_VOID(scrollBar_ && scrollBar_->NeedPaint()); 223 CHECK_NULL_VOID(!scrollBarOverlayModifier_); 224 scrollBarOverlayModifier_ = AceType::MakeRefPtr<ScrollBarOverlayModifier>(); 225 scrollBarOverlayModifier_->SetRect(scrollBar_->GetActiveRect()); 226 scrollBarOverlayModifier_->SetPositionMode(scrollBar_->GetPositionMode()); 227 } 228 CreateNodePaintMethod()229 RefPtr<NodePaintMethod> CreateNodePaintMethod() override 230 { 231 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) { 232 auto paint = MakeRefPtr<ScrollBarPaintMethod>(hasChild_); 233 paint->SetScrollBar(scrollBar_); 234 if (!HasChild()) { 235 auto activeRect = scrollBar_->GetActiveRect(); 236 auto offset = activeRect.GetOffset(); 237 auto offsetF = OffsetF(offset.GetX(), offset.GetY()); 238 auto size = activeRect.GetSize(); 239 auto sizeF = SizeF(size.Width(), size.Height()); 240 childRect_ = RectF(offsetF, sizeF); 241 } 242 CreateScrollBarOverlayModifier(); 243 paint->SetScrollBarOverlayModifier(scrollBarOverlayModifier_); 244 return paint; 245 } else { 246 return Pattern::CreateNodePaintMethod(); 247 } 248 } 249 SetChild(bool hasChild)250 void SetChild(bool hasChild) 251 { 252 hasChild_ = hasChild; 253 } 254 SetPreFrameChildState(bool preFrameChildState)255 void SetPreFrameChildState(bool preFrameChildState) 256 { 257 preFrameChildState_ = preFrameChildState; 258 } 259 GetPreFrameChildState()260 bool GetPreFrameChildState() 261 { 262 return preFrameChildState_; 263 } 264 HasChild()265 bool HasChild() 266 { 267 return hasChild_; 268 } 269 CheckChildState()270 bool CheckChildState() 271 { 272 auto currentChildState = HasChild(); 273 auto preChildState = GetPreFrameChildState(); 274 if (preChildState != currentChildState) { 275 SetPreFrameChildState(currentChildState); 276 return true; 277 } 278 return false; 279 } 280 void InitClickEvent(); 281 void HandleClickEvent(); 282 void InitLongPressEvent(); 283 void HandleLongPress(bool smooth); 284 void InitMouseEvent(); 285 bool IsInScrollBar(); 286 void ScheduleCaretLongPress(); 287 void StartLongPressEventTimer(); 288 void OnCollectClickTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 289 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent, 290 ResponseLinkResult& responseLinkResult); 291 void OnCollectLongPressTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 292 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent, 293 ResponseLinkResult& responseLinkResult); 294 void AddScrollBarLayoutInfo(); 295 296 void GetAxisDumpInfo(); 297 298 void GetDisplayModeDumpInfo(); 299 300 void GetPanDirectionDumpInfo(); 301 302 void DumpAdvanceInfo() override; 303 SetScrollEnabled(bool enabled)304 void SetScrollEnabled(bool enabled) 305 { 306 CHECK_NULL_VOID(scrollableEvent_); 307 scrollableEvent_->SetEnabled(enabled); 308 if (!enabled) { 309 scrollableEvent_->SetAxis(Axis::NONE); 310 } else { 311 scrollableEvent_->SetAxis(axis_); 312 } 313 } 314 315 void OnColorConfigurationUpdate() override; 316 GetScrollBarProxy()317 RefPtr<ScrollBarProxy> GetScrollBarProxy() 318 { 319 return scrollBarProxy_; 320 } 321 SetEnableNestedSorll(bool enableNestedSorll)322 void SetEnableNestedSorll(bool enableNestedSorll) 323 { 324 enableNestedSorll_ = enableNestedSorll; 325 } 326 GetEnableNestedSorll()327 bool GetEnableNestedSorll() const 328 { 329 return enableNestedSorll_; 330 } 331 332 void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override; 333 private: 334 void OnModifyDone() override; 335 void SetBarCollectClickAndLongPressTargetCallback(); 336 void SetInBarRectRegionCallback(); 337 void OnAttachToFrameNode() override; 338 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 339 void ValidateOffset(); 340 void SetAccessibilityAction(); 341 void InitPanRecognizer(); 342 void HandleDragStart(const GestureEvent& info); 343 void HandleDragUpdate(const GestureEvent& info); 344 void HandleDragEnd(const GestureEvent& info); 345 void ProcessFrictionMotion(double value); 346 void ProcessFrictionMotionStop(); 347 348 RefPtr<ScrollBarProxy> scrollBarProxy_; 349 RefPtr<ScrollableEvent> scrollableEvent_; 350 Axis axis_ = Axis::VERTICAL; 351 DisplayMode displayMode_ { DisplayMode::AUTO }; 352 float currentOffset_ = 0.0f; 353 float lastOffset_ = 0.0f; 354 float scrollableDistance_ = 0.0f; 355 float controlDistance_ = 0.0f; 356 bool controlDistanceChanged_ = false; 357 float scrollableNodeOffset_ = 0.0f; 358 bool hasChild_ = false; 359 bool preFrameChildState_ = false; 360 float friction_ = BAR_FRICTION; 361 float frictionPosition_ = 0.0; 362 float dragStartPosition_ = 0.0f; 363 float dragEndPosition_ = 0.0f; 364 365 float childOffset_ = 0.0f; // main size of child 366 RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier_; 367 RefPtr<ScrollBar> scrollBar_; 368 RefPtr<PanRecognizer> panRecognizer_; 369 RefPtr<FrictionMotion> frictionMotion_; 370 RefPtr<Animator> frictionController_; 371 ScrollPositionCallback scrollPositionCallback_; 372 ScrollEndCallback scrollEndCallback_; 373 RectF childRect_; 374 uint8_t opacity_ = UINT8_MAX; 375 CancelableCallback<void()> disapplearDelayTask_; 376 std::shared_ptr<AnimationUtils::Animation> disappearAnimation_; 377 bool isReverse_ = false; 378 379 // dump info 380 std::list<OuterScrollBarLayoutInfo> outerScrollBarLayoutInfos_; 381 bool enableNestedSorll_ = false; 382 bool isMousePressed_ = false; 383 RefPtr<ClickEvent> clickListener_; 384 RefPtr<ClickRecognizer> clickRecognizer_; 385 RefPtr<LongPressRecognizer> longPressRecognizer_; 386 RefPtr<InputEvent> mouseEvent_; 387 Offset locationInfo_; 388 //Determine whether the current scroll direction is scrolling upwards or downwards 389 bool scrollingUp_ = false; 390 bool scrollingDown_ = false; 391 }; 392 393 } // namespace OHOS::Ace::NG 394 395 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_BAR_SCROLL_BAR_PATTERN_H 396