1  /*
2   * Copyright (c) 2021-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_SCROLL_SCROLL_BAR_CONTROLLER_H
17  #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLL_BAR_CONTROLLER_H
18  
19  #include <functional>
20  
21  #include "core/animation/animator.h"
22  #include "core/animation/friction_motion.h"
23  #include "core/animation/scroll_motion.h"
24  #include "core/common/vibrator/vibrator.h"
25  #include "core/event/touch_event.h"
26  #include "core/gestures/drag_recognizer.h"
27  #include "core/gestures/pan_recognizer.h"
28  #include "core/gestures/raw_recognizer.h"
29  #include "core/pipeline/base/render_node.h"
30  
31  namespace OHOS::Ace {
32  
33  using ScrollBarPositionCallback = std::function<bool(double, int32_t source)>;
34  using ScrollBarEndCallback = std::function<void(int32_t)>;
35  using ScrollBarEventCallback = std::function<void()>;
36  using ScrollBarTouchEventCallback = std::function<void(double)>;
37  
38  class ScrollBarController : public TouchEventTarget {
39      DECLARE_ACE_TYPE(ScrollBarController, TouchEventTarget);
40  
41  public:
42      ScrollBarController() = default;
43      ~ScrollBarController() override = default;
44  
45      void Initialize(const WeakPtr<PipelineContext>& context, bool isVertical);
46      void HandleScrollBarEnd();
47      void HandleTouchDown();
48      void HandleTouchUp();
49      void HandleDragUpdate(const GestureEvent& info);
50      void HandleDragEnd(const GestureEvent& info);
51      virtual void MarkScrollRender();
52      void Reset();
53  
DispatchEvent(const TouchEvent & point)54      bool DispatchEvent(const TouchEvent& point) override
55      {
56          return true;
57      }
HandleEvent(const TouchEvent & event)58      bool HandleEvent(const TouchEvent& event) override
59      {
60          if (panRecognizer_) {
61              panRecognizer_->HandleEvent(event);
62          }
63          if (rawRecognizer_) {
64              return rawRecognizer_->HandleEvent(event);
65          }
66          return true;
67      }
HandleEvent(const AxisEvent & event)68      bool HandleEvent(const AxisEvent& event) override
69      {
70          if (panRecognizer_) {
71              return panRecognizer_->HandleEvent(event);
72          }
73          return false;
74      }
75  
SetCallback(const ScrollBarPositionCallback & callback)76      void SetCallback(const ScrollBarPositionCallback& callback)
77      {
78          callback_ = callback;
79      }
80  
SetBarEndCallback(const ScrollBarEndCallback & barEndCallback)81      void SetBarEndCallback(const ScrollBarEndCallback& barEndCallback)
82      {
83          barEndCallback_ = barEndCallback;
84      }
85  
SetCoordinateOffset(const Offset & offset)86      void SetCoordinateOffset(const Offset& offset) const
87      {
88          if (panRecognizer_) {
89              panRecognizer_->SetCoordinateOffset(offset);
90          }
91          if (rawRecognizer_) {
92              rawRecognizer_->SetCoordinateOffset(offset);
93          }
94      }
95  
SetScrollEndCallback(const ScrollBarEventCallback & scrollEndCallback)96      void SetScrollEndCallback(const ScrollBarEventCallback& scrollEndCallback)
97      {
98          scrollEndCallback_ = scrollEndCallback;
99      }
100  
SetTouchUpCallback(const ScrollBarTouchEventCallback & touchUpCallback)101      void SetTouchUpCallback(const ScrollBarTouchEventCallback& touchUpCallback)
102      {
103          touchUpCallback_ = touchUpCallback;
104      }
105  
SetTouchDownCallback(const ScrollBarTouchEventCallback & touchDownCallback)106      void SetTouchDownCallback(const ScrollBarTouchEventCallback& touchDownCallback)
107      {
108          touchDownCallback_ = touchDownCallback;
109      }
110  
SetScrollNode(const WeakPtr<RenderNode> & scroll)111      void SetScrollNode(const WeakPtr<RenderNode>& scroll)
112      {
113          scroll_ = scroll;
114      }
115  
IsActive()116      bool IsActive() const
117      {
118          return isActive_;
119      }
120  
SetActive(bool isActive)121      void SetActive(bool isActive)
122      {
123          isActive_ = isActive;
124      }
125  
SetInactiveWidth(const Dimension & inactiveWidth)126      void SetInactiveWidth(const Dimension& inactiveWidth)
127      {
128          inactiveWidth_ = inactiveWidth;
129      }
130  
SetActiveWidth(const Dimension & activeWidth)131      void SetActiveWidth(const Dimension& activeWidth)
132      {
133          activeWidth_ = activeWidth;
134      }
135  
GetInactiveWidth()136      const Dimension& GetInactiveWidth() const
137      {
138          return inactiveWidth_;
139      }
140  
GetActiveWidth()141      const Dimension& GetActiveWidth() const
142      {
143          return activeWidth_;
144      }
145  
IsPressed()146      bool IsPressed() const
147      {
148          return isPressed_;
149      }
150  
151      void SetIsHover(bool isInBarRegion);
152  
StopScrollEndAnimator()153      void StopScrollEndAnimator()
154      {
155          if (scrollEndAnimator_ && !scrollEndAnimator_->IsStopped()) {
156              scrollEndAnimator_->Stop();
157          }
158      }
159      void OnFlushTouchEventsBegin() override;
160      void OnFlushTouchEventsEnd() override;
161  
162  protected:
163      virtual bool UpdateScrollPosition(double offset, int32_t source);
164  
165      virtual void ProcessScrollMotion(double position);
166  
167      virtual bool CheckScroll();
168  
169      // Play grow when hover or pressed, from inactive with to active width.
170      void PlayGrowAnimation();
171      // Play shrink animation when lost hover or pressed state, from active with to inactive width.
172      void PlayShrinkAnimation();
173  
174      void InitBarEndAnimation(const WeakPtr<PipelineContext>& context);
175  
176      WeakPtr<RenderNode> scroll_;
177      ScrollBarPositionCallback callback_;
178      ScrollBarEventCallback scrollEndCallback_;
179      ScrollBarEndCallback barEndCallback_;
180      ScrollBarTouchEventCallback touchUpCallback_;
181      ScrollBarTouchEventCallback touchDownCallback_;
182  
183      RefPtr<PanRecognizer> panRecognizer_;
184      RefPtr<RawRecognizer> rawRecognizer_;
185  
186      RefPtr<Animator> scrollEndAnimator_;
187      RefPtr<Animator> touchAnimator_;
188      RefPtr<Animator> dragEndAnimator_;
189      RefPtr<FrictionMotion> dragEndMotion_;
190      RefPtr<Vibrator> vibrator_;
191      WeakPtr<PipelineContext> context_;
192  
193      bool isVertical_ = true;
194      bool isActive_ = false;
195      // Whether scroll bar is pressed, use different style when pressed.
196      bool isPressed_ = false;
197      // Whether scroll bar is hover.
198      bool isHover_ = false;
199      // Whether event is in scroll bar region.
200      bool isInBar_ = false;
201      double currentPos_ = 0.0;
202      Dimension activeWidth_;
203      Dimension inactiveWidth_;
204  };
205  
206  } // namespace OHOS::Ace
207  
208  #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLL_SCROLL_BAR_CONTROLLER_H
209