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 controlDistanceChanged_ = Positive(controlDistance_) ? !Positive(controlDistance) : Positive(controlDistance); 115 controlDistance_ = controlDistance; 116 } 117 GetScrollableNodeOffset()118 float GetScrollableNodeOffset() const 119 { 120 return scrollableNodeOffset_; 121 } 122 SetScrollableNodeOffset(float scrollableNodeOffset)123 void SetScrollableNodeOffset(float scrollableNodeOffset) 124 { 125 scrollableNodeOffset_ = scrollableNodeOffset; 126 } 127 128 bool IsAtTop() const; 129 bool IsAtBottom() const; 130 bool UpdateCurrentOffset(float offset, int32_t source); 131 132 /** 133 * @brief Stops the motion animator of the scroll bar. 134 */ StopMotion()135 inline void StopMotion() 136 { 137 if (frictionController_ && frictionController_->IsRunning()) { 138 frictionController_->Stop(); 139 } 140 } 141 // disappear Animator 142 void StartDisappearAnimator(); 143 void StopDisappearAnimator(); 144 void SetOpacity(uint8_t value); 145 void SendAccessibilityEvent(AccessibilityEventType eventType); 146 SetChildOffset(float childOffset)147 void SetChildOffset(float childOffset) 148 { 149 childOffset_ = childOffset; 150 }; 151 GetChildOffset()152 float GetChildOffset() const 153 { 154 return childOffset_; 155 }; 156 SetChildRect(const RectF & rect)157 void SetChildRect(const RectF& rect) 158 { 159 childRect_ = rect; 160 } 161 SetDisappearAnimation(const std::shared_ptr<AnimationUtils::Animation> & disappearAnimation)162 void SetDisappearAnimation(const std::shared_ptr<AnimationUtils::Animation>& disappearAnimation) 163 { 164 disappearAnimation_ = disappearAnimation; 165 } 166 167 void OnCollectTouchTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, 168 TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent, 169 ResponseLinkResult& responseLinkResult); 170 GetMainOffset(const Offset & offset)171 float GetMainOffset(const Offset& offset) const 172 { 173 return axis_ == Axis::HORIZONTAL ? offset.GetX() : offset.GetY(); 174 } 175 SetDragStartPosition(float position)176 void SetDragStartPosition(float position) 177 { 178 dragStartPosition_ = position; 179 } 180 SetDragEndPosition(float position)181 void SetDragEndPosition(float position) 182 { 183 dragEndPosition_ = position; 184 } 185 GetDragOffset()186 float GetDragOffset() 187 { 188 return dragEndPosition_ - dragStartPosition_; 189 } 190 191 void SetScrollBar(DisplayMode displayMode); 192 void UpdateScrollBarOffset(); 193 void HandleScrollBarOutBoundary(float scrollBarOutBoundaryExtent); 194 void UpdateScrollBarRegion(float offset, float estimatedHeight, Size viewPort, Offset viewOffset); 195 void RegisterScrollBarEventTask(); 196 bool UpdateScrollBarDisplay(); 197 bool IsReverse() const; 198 void SetReverse(bool reverse); 199 GetGestureHub()200 RefPtr<GestureEventHub> GetGestureHub() 201 { 202 auto host = GetHost(); 203 CHECK_NULL_RETURN(host, nullptr); 204 auto hub = host->GetEventHub<EventHub>(); 205 CHECK_NULL_RETURN(hub, nullptr); 206 return hub->GetOrCreateGestureEventHub(); 207 } 208 GetInputHub()209 RefPtr<InputEventHub> GetInputHub() 210 { 211 auto host = GetHost(); 212 CHECK_NULL_RETURN(host, nullptr); 213 auto hub = host->GetEventHub<EventHub>(); 214 CHECK_NULL_RETURN(hub, nullptr); 215 return hub->GetOrCreateInputEventHub(); 216 } 217 CreateScrollBarOverlayModifier()218 void CreateScrollBarOverlayModifier() 219 { 220 CHECK_NULL_VOID(scrollBar_ && scrollBar_->NeedPaint()); 221 CHECK_NULL_VOID(!scrollBarOverlayModifier_); 222 scrollBarOverlayModifier_ = AceType::MakeRefPtr<ScrollBarOverlayModifier>(); 223 scrollBarOverlayModifier_->SetRect(scrollBar_->GetActiveRect()); 224 scrollBarOverlayModifier_->SetPositionMode(scrollBar_->GetPositionMode()); 225 } 226 CreateNodePaintMethod()227 RefPtr<NodePaintMethod> CreateNodePaintMethod() override 228 { 229 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) { 230 auto paint = MakeRefPtr<ScrollBarPaintMethod>(hasChild_); 231 paint->SetScrollBar(scrollBar_); 232 if (!HasChild()) { 233 auto activeRect = scrollBar_->GetActiveRect(); 234 auto offset = activeRect.GetOffset(); 235 auto offsetF = OffsetF(offset.GetX(), offset.GetY()); 236 auto size = activeRect.GetSize(); 237 auto sizeF = SizeF(size.Width(), size.Height()); 238 childRect_ = RectF(offsetF, sizeF); 239 } 240 CreateScrollBarOverlayModifier(); 241 paint->SetScrollBarOverlayModifier(scrollBarOverlayModifier_); 242 return paint; 243 } else { 244 return Pattern::CreateNodePaintMethod(); 245 } 246 } 247 SetChild(bool hasChild)248 void SetChild(bool hasChild) 249 { 250 hasChild_ = hasChild; 251 } 252 SetPreFrameChildState(bool preFrameChildState)253 void SetPreFrameChildState(bool preFrameChildState) 254 { 255 preFrameChildState_ = preFrameChildState; 256 } 257 GetPreFrameChildState()258 bool GetPreFrameChildState() 259 { 260 return preFrameChildState_; 261 } 262 HasChild()263 bool HasChild() 264 { 265 return hasChild_; 266 } 267 CheckChildState()268 bool CheckChildState() 269 { 270 auto currentChildState = HasChild(); 271 auto preChildState = GetPreFrameChildState(); 272 if (preChildState != currentChildState) { 273 SetPreFrameChildState(currentChildState); 274 return true; 275 } 276 return false; 277 } 278 279 void AddScrollBarLayoutInfo(); 280 281 void GetAxisDumpInfo(); 282 283 void GetDisplayModeDumpInfo(); 284 285 void GetPanDirectionDumpInfo(); 286 287 void DumpAdvanceInfo() override; 288 SetScrollEnabled(bool enabled)289 void SetScrollEnabled(bool enabled) 290 { 291 CHECK_NULL_VOID(scrollableEvent_); 292 scrollableEvent_->SetEnabled(enabled); 293 if (!enabled) { 294 scrollableEvent_->SetAxis(Axis::NONE); 295 } else { 296 scrollableEvent_->SetAxis(axis_); 297 } 298 } 299 300 void OnColorConfigurationUpdate() override; 301 302 private: 303 void OnModifyDone() override; 304 void OnAttachToFrameNode() override; 305 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 306 void ValidateOffset(); 307 void SetAccessibilityAction(); 308 void InitPanRecognizer(); 309 void HandleDragStart(const GestureEvent& info); 310 void HandleDragUpdate(const GestureEvent& info); 311 void HandleDragEnd(const GestureEvent& info); 312 void ProcessFrictionMotion(double value); 313 void ProcessFrictionMotionStop(); 314 315 RefPtr<ScrollBarProxy> scrollBarProxy_; 316 RefPtr<ScrollableEvent> scrollableEvent_; 317 Axis axis_ = Axis::VERTICAL; 318 DisplayMode displayMode_ { DisplayMode::AUTO }; 319 float currentOffset_ = 0.0f; 320 float lastOffset_ = 0.0f; 321 float scrollableDistance_ = 0.0f; 322 float controlDistance_ = 0.0f; 323 bool controlDistanceChanged_ = false; 324 float scrollableNodeOffset_ = 0.0f; 325 bool hasChild_ = false; 326 bool preFrameChildState_ = false; 327 float friction_ = BAR_FRICTION; 328 float frictionPosition_ = 0.0; 329 float dragStartPosition_ = 0.0f; 330 float dragEndPosition_ = 0.0f; 331 332 float childOffset_ = 0.0f; // main size of child 333 RefPtr<ScrollBarOverlayModifier> scrollBarOverlayModifier_; 334 RefPtr<ScrollBar> scrollBar_; 335 RefPtr<PanRecognizer> panRecognizer_; 336 RefPtr<FrictionMotion> frictionMotion_; 337 RefPtr<Animator> frictionController_; 338 ScrollPositionCallback scrollPositionCallback_; 339 ScrollEndCallback scrollEndCallback_; 340 RectF childRect_; 341 uint8_t opacity_ = UINT8_MAX; 342 CancelableCallback<void()> disapplearDelayTask_; 343 std::shared_ptr<AnimationUtils::Animation> disappearAnimation_; 344 bool isReverse_ = false; 345 346 // dump info 347 std::list<OuterScrollBarLayoutInfo> outerScrollBarLayoutInfos_; 348 }; 349 350 } // namespace OHOS::Ace::NG 351 352 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_BAR_SCROLL_BAR_PATTERN_H 353