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_INNER_SCROLL_BAR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_INNER_SCROLL_BAR_H
18 
19 #include <cmath>
20 
21 #include "base/geometry/dimension.h"
22 #include "base/geometry/offset.h"
23 #include "base/geometry/rect.h"
24 #include "base/utils/utils.h"
25 #include "core/animation/friction_motion.h"
26 #include "core/components/common/layout/constants.h"
27 #include "core/components/common/properties/color.h"
28 #include "core/components/common/properties/edge.h"
29 #include "core/components/scroll/scroll_bar_theme.h"
30 #include "core/components_ng/base/frame_scene_status.h"
31 #include "core/components_ng/event/input_event.h"
32 #include "core/components_ng/event/touch_event.h"
33 #include "core/components_ng/gestures/recognizers/pan_recognizer.h"
34 #include "core/components_ng/pattern/scroll/inner/scroll_bar_overlay_modifier.h"
35 #include "core/components_ng/pattern/scrollable/scrollable_properties.h"
36 #include "core/components_ng/property/border_property.h"
37 
38 
39 namespace OHOS::Ace::NG {
40 
41 constexpr double FACTOR_HALF = 0.5;
42 constexpr double DEFAULT_TOPANGLE = 60.0;
43 constexpr double DEFAULT_BOTTOMANGLE = 120.0;
44 constexpr double DEFAULT_MINANGLE = 10.0;
45 constexpr double STRAIGHT_ANGLE = 180.0;
46 constexpr double BAR_FRICTION = 0.9;
47 constexpr Color PRESSED_BLEND_COLOR = Color(0x19000000);
48 using DragFRCSceneCallback = std::function<void(double velocity, NG::SceneStatus sceneStatus)>;
49 
50 enum class BarDirection {
51     BAR_NONE = 0,
52     PAGE_UP,
53     PAGE_DOWN,
54 };
55 
56 class ScrollBar final : public AceType {
57     DECLARE_ACE_TYPE(ScrollBar, AceType);
58 
59 public:
60     ScrollBar();
61     ScrollBar(DisplayMode displayMode, ShapeMode shapeMode = ShapeMode::RECT,
62         PositionMode positionMode = PositionMode::RIGHT);
63     ~ScrollBar() override = default;
64 
GetShapeMode()65     ShapeMode GetShapeMode() const
66     {
67         return shapeMode_;
68     }
GetDisplayMode()69     DisplayMode GetDisplayMode() const
70     {
71         return displayMode_;
72     }
GetPositionMode()73     PositionMode GetPositionMode() const
74     {
75         return positionMode_;
76     }
SetPadding(const Edge & padding)77     void SetPadding(const Edge& padding)
78     {
79         padding_ = padding;
80     }
GetPadding()81     const Edge& GetPadding() const
82     {
83         return padding_;
84     }
SetBackgroundColor(const Color & backgroundColor)85     void SetBackgroundColor(const Color& backgroundColor)
86     {
87         backgroundColor_ = backgroundColor;
88     }
GetBackgroundColor()89     const Color& GetBackgroundColor() const
90     {
91         return backgroundColor_;
92     }
SetForegroundColor(const Color & foregroundColor)93     void SetForegroundColor(const Color& foregroundColor)
94     {
95         foregroundColor_ = foregroundColor;
96     }
GetTopAngle()97     double GetTopAngle() const
98     {
99         return topAngle_;
100     }
GetBottomAngle()101     double GetBottomAngle() const
102     {
103         return bottomAngle_;
104     }
GetTrickStartAngle()105     double GetTrickStartAngle() const
106     {
107         return trickStartAngle_;
108     }
GetTrickSweepAngle()109     double GetTrickSweepAngle() const
110     {
111         return trickSweepAngle_;
112     }
SetMinHeight(const Dimension & minHeight)113     void SetMinHeight(const Dimension& minHeight)
114     {
115         minHeight_ = minHeight;
116     }
GetMinHeight()117     const Dimension& GetMinHeight() const
118     {
119         return minHeight_;
120     }
SetMinDynamicHeight(const Dimension & minDynamicHeight)121     void SetMinDynamicHeight(const Dimension& minDynamicHeight)
122     {
123         minDynamicHeight_ = minDynamicHeight;
124     }
GetMinDynamicHeight()125     const Dimension& GetMinDynamicHeight() const
126     {
127         return minDynamicHeight_;
128     }
SetInactiveWidth(const Dimension & inactiveWidth)129     void SetInactiveWidth(const Dimension& inactiveWidth)
130     {
131         inactiveWidth_ = inactiveWidth;
132     }
SetActiveWidth(const Dimension & activeWidth)133     void SetActiveWidth(const Dimension& activeWidth)
134     {
135         activeWidth_ = activeWidth;
136     }
GetActiveWidth()137     const Dimension& GetActiveWidth() const
138     {
139         return activeWidth_;
140     }
GetActiveRect()141     const Rect& GetActiveRect() const
142     {
143         return activeRect_;
144     }
SetTouchWidth(const Dimension & touchWidth)145     void SetTouchWidth(const Dimension& touchWidth)
146     {
147         touchWidth_ = touchWidth;
148     }
GetTouchWidth()149     const Dimension& GetTouchWidth() const
150     {
151         return touchWidth_;
152     }
GetBarRect()153     const Rect& GetBarRect() const
154     {
155         return barRect_;
156     }
IsScrollable()157     bool IsScrollable() const
158     {
159         return isScrollable_;
160     }
GetPositionModeUpdate()161     bool GetPositionModeUpdate() const
162     {
163         return positionModeUpdate_;
164     }
165 
SetShapeMode(ShapeMode shapeMode)166     void SetShapeMode(ShapeMode shapeMode)
167     {
168         shapeMode_ = shapeMode;
169     }
GetOutBoundary()170     double GetOutBoundary() const
171     {
172         return outBoundary_;
173     }
SetOutBoundary(double outBoundary)174     void SetOutBoundary(double outBoundary)
175     {
176         outBoundary_ = outBoundary;
177     }
SetIsOutOfBoundary(bool isOutOfBoundary)178     void SetIsOutOfBoundary(bool isOutOfBoundary)
179     {
180         isOutOfBoundary_ = isOutOfBoundary;
181     }
SetPosition(const Dimension & position)182     void SetPosition(const Dimension& position)
183     {
184         position_ = position;
185     }
GetPosition()186     const Dimension& GetPosition() const
187     {
188         return position_;
189     }
SetPressed(bool press)190     void SetPressed(bool press)
191     {
192         isPressed_ = press;
193     }
IsPressed()194     bool IsPressed() const
195     {
196         return isPressed_;
197     }
SetHover(bool hover)198     void SetHover(bool hover)
199     {
200         isHover_ = hover;
201     }
IsHover()202     bool IsHover() const
203     {
204         return isHover_;
205     }
GetOpacityAnimationType()206     OpacityAnimationType GetOpacityAnimationType() const
207     {
208         return opacityAnimationType_;
209     }
SetOpacityAnimationType(OpacityAnimationType opacityAnimationType)210     void SetOpacityAnimationType(OpacityAnimationType opacityAnimationType)
211     {
212         opacityAnimationType_ = opacityAnimationType;
213     }
GetHoverAnimationType()214     HoverAnimationType GetHoverAnimationType() const
215     {
216         return hoverAnimationType_;
217     }
SetHoverAnimationType(HoverAnimationType hoverAnimationType)218     void SetHoverAnimationType(HoverAnimationType hoverAnimationType)
219     {
220         hoverAnimationType_ = hoverAnimationType;
221     }
GetNeedAdaptAnimation()222     bool GetNeedAdaptAnimation() const
223     {
224         return needAdaptAnimation_;
225     }
SetMarkNeedRenderFunc(std::function<void ()> && func)226     void SetMarkNeedRenderFunc(std::function<void()>&& func)
227     {
228         markNeedRenderFunc_ = func;
229     }
GetTouchEvent()230     RefPtr<TouchEventImpl> GetTouchEvent()
231     {
232         return touchEvent_;
233     }
GetMouseEvent()234     RefPtr<InputEvent> GetMouseEvent()
235     {
236         return mouseEvent_;
237     }
GetHoverEvent()238     RefPtr<InputEvent> GetHoverEvent() const
239     {
240         return hoverEvent_;
241     }
SetIsUserNormalWidth(bool isUserNormalWidth)242     void SetIsUserNormalWidth(bool isUserNormalWidth)
243     {
244         isUserNormalWidth_ = isUserNormalWidth;
245     }
GetIsUserNormalWidth()246     bool GetIsUserNormalWidth() const
247     {
248         return isUserNormalWidth_;
249     }
SetStartReservedHeight(const Dimension & startReservedHeight)250     void SetStartReservedHeight(const Dimension& startReservedHeight)
251     {
252         startReservedHeight_ = startReservedHeight;
253     }
GetStartReservedHeight()254     const Dimension& GetStartReservedHeight() const
255     {
256         return startReservedHeight_;
257     }
SetEndReservedHeight(const Dimension & endReservedHeight)258     void SetEndReservedHeight(const Dimension& endReservedHeight)
259     {
260         endReservedHeight_ = endReservedHeight;
261     }
GetEndReservedHeight()262     const Dimension& GetEndReservedHeight() const
263     {
264         return endReservedHeight_;
265     }
SetHostBorderRadius(const BorderRadiusProperty & hostBorderRadius)266     void SetHostBorderRadius(const BorderRadiusProperty& hostBorderRadius)
267     {
268         hostBorderRadius_ = hostBorderRadius;
269     }
GetHostBorderRadius()270     const BorderRadiusProperty& GetHostBorderRadius() const
271     {
272         return hostBorderRadius_;
273     }
SetScrollPositionCallback(ScrollPositionCallback && callback)274     void SetScrollPositionCallback(ScrollPositionCallback&& callback)
275     {
276         scrollPositionCallback_ = std::move(callback);
277     }
GetScrollPositionCallback()278     const ScrollPositionCallback& GetScrollPositionCallback() const
279     {
280         return scrollPositionCallback_;
281     }
SetScrollEndCallback(ScrollEndCallback && scrollEndCallback)282     void SetScrollEndCallback(ScrollEndCallback&& scrollEndCallback)
283     {
284         scrollEndCallback_ = std::move(scrollEndCallback);
285     }
GetScrollEndCallback()286     const ScrollEndCallback& GetScrollEndCallback() const
287     {
288         return scrollEndCallback_;
289     }
SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback && calePredictSnapOffsetCallback)290     void SetCalePredictSnapOffsetCallback(CalePredictSnapOffsetCallback&& calePredictSnapOffsetCallback)
291     {
292         calePredictSnapOffsetCallback_ = std::move(calePredictSnapOffsetCallback);
293     }
GetCalePredictSnapOffsetCallback()294     const CalePredictSnapOffsetCallback& GetCalePredictSnapOffsetCallback() const
295     {
296         return calePredictSnapOffsetCallback_;
297     }
SetStartScrollSnapMotionCallback(StartScrollSnapMotionCallback && startScrollSnapMotionCallback)298     void SetStartScrollSnapMotionCallback(StartScrollSnapMotionCallback&& startScrollSnapMotionCallback)
299     {
300         startScrollSnapMotionCallback_ = std::move(startScrollSnapMotionCallback);
301     }
GetStartScrollSnapMotionCallback()302     const StartScrollSnapMotionCallback& GetStartScrollSnapMotionCallback() const
303     {
304         return startScrollSnapMotionCallback_;
305     }
SetDragFRCSceneCallback(DragFRCSceneCallback && dragFRCSceneCallback)306     void SetDragFRCSceneCallback(DragFRCSceneCallback&& dragFRCSceneCallback)
307     {
308         dragFRCSceneCallback_ = std::move(dragFRCSceneCallback);
309     }
SetDragStartPosition(float position)310     void SetDragStartPosition(float position)
311     {
312         dragStartPosition_ = position;
313     }
SetDragEndPosition(float position)314     void SetDragEndPosition(float position)
315     {
316         dragEndPosition_ = position;
317     }
GetDragOffset()318     float GetDragOffset()
319     {
320         return dragEndPosition_ - dragStartPosition_;
321     }
IsReverse()322     bool IsReverse()
323     {
324         return isReverse_;
325     }
326 
327     Axis GetPanDirection() const;
328 
GetTouchRegion()329     Rect GetTouchRegion() const
330     {
331         return touchRegion_;
332     }
333     BarDirection CheckBarDirection(const Point& point);
GetClickEvent()334     RefPtr<ClickEvent> GetClickEvent()
335     {
336         return clickevent_;
337     }
SetAxis(Axis axis)338     void SetAxis(Axis axis)
339     {
340         axis_ = axis;
341     }
342 
343     void OnCollectTouchTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl,
344         TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent,
345         ResponseLinkResult& responseLinkResult);
346     bool InBarTouchRegion(const Point& point) const;
347     bool InBarHoverRegion(const Point& point) const;
348     bool InBarRectRegion(const Point& point) const;
349     bool NeedScrollBar() const;
350     bool NeedPaint() const;
351     void UpdateScrollBarRegion(
352         const Offset& offset, const Size& size, const Offset& lastOffset, double estimatedHeight);
353     double GetNormalWidthToPx() const;
354     float CalcPatternOffset(float scrollBarOffset) const;
355     Color GetForegroundColor() const;
356     void SetHoverWidth(const RefPtr<ScrollBarTheme>& theme);
357     void SetNormalWidth(const Dimension& normalWidth);
358     void SetScrollable(bool isScrollable);
359     void SetPositionMode(PositionMode positionMode);
360     void SetDisplayMode(DisplayMode displayMode);
361     void PlayScrollBarDisappearAnimation();
362     void PlayScrollBarAppearAnimation();
363     void PlayScrollBarGrowAnimation();
364     void PlayScrollBarShrinkAnimation();
365     void PlayScrollBarAdaptAnimation();
366     void MarkNeedRender();
367     void SetGestureEvent();
368     void SetMouseEvent();
369     void SetHoverEvent();
370     void FlushBarWidth();
371     void CalcReservedHeight();
372     void ScheduleDisappearDelayTask();
373     float GetMainOffset(const Offset& offset) const;
374     void SetReverse(bool reverse);
375     // infos for dump
376     void AddScrollBarLayoutInfo();
377     void GetShapeModeDumpInfo();
378     void GetPositionModeDumpInfo();
379     void GetAxisDumpInfo();
380     void GetPanDirectionDumpInfo();
381     void DumpAdvanceInfo();
382     void StopFlingAnimation();
SetScrollPageCallback(ScrollPageCallback && scrollPageCallback)383     void SetScrollPageCallback(ScrollPageCallback&& scrollPageCallback)
384     {
385         scrollPageCallback_ = std::move(scrollPageCallback);
386     }
387     void OnCollectLongPressTarget(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl,
388         TouchTestResult& result, const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent,
389         ResponseLinkResult& responseLinkResult);
390     void InitLongPressEvent();
391     void HandleLongPress(bool smooth);
392     bool AnalysisUpOrDown(Point point, bool& reverse);
393     void ScheduleCaretLongPress();
394 
395 protected:
396     void InitTheme();
397 
398 private:
399     void SetBarRegion(const Offset& offset, const Size& size);
400     void SetRectTrickRegion(const Offset& offset, const Size& size, const Offset& lastOffset, double mainScrollExtent);
401     void SetRoundTrickRegion(const Offset& offset, const Size& size, const Offset& lastOffset, double mainScrollExtent);
402     void UpdateActiveRectSize(double activeSize);
403     void UpdateActiveRectOffset(double activeMainOffset);
404     double NormalizeToPx(const Dimension& dimension) const;
405     void InitPanRecognizer();
406     void HandleDragStart(const GestureEvent& info);
407     void HandleDragUpdate(const GestureEvent& info);
408     void HandleDragEnd(const GestureEvent& info);
409     void ProcessFrictionMotion(double value);
410     void ProcessFrictionMotionStop();
411 
412     DisplayMode displayMode_ = DisplayMode::AUTO;
413     ShapeMode shapeMode_ = ShapeMode::RECT;
414     PositionMode positionMode_ = PositionMode::RIGHT;
415     BorderRadiusProperty hostBorderRadius_;
416     Edge padding_;
417     Color backgroundColor_;
418     Color foregroundColor_;
419     Rect touchRegion_;
420     Rect hoverRegion_;
421     Rect barRect_;
422     Rect activeRect_;
423     Dimension minHeight_;           // this is min static height
424     Dimension minDynamicHeight_;    // this is min dynamic height when on the top or bottom
425     Dimension startReservedHeight_; // this is reservedHeight on the start
426     Dimension endReservedHeight_;   // this is reservedHeight on the end
427     Dimension inactiveWidth_;
428     Dimension activeWidth_;
429     double barWidth_ = 0.0;         // actual width of the scrollbar
430     Dimension normalWidth_;         // user-set width of the scrollbar
431     Dimension themeNormalWidth_;
432     Dimension touchWidth_;
433     Dimension hoverWidth_;
434 
435     Dimension position_;
436 
437     double trickStartAngle_ = 0.0;
438     double trickSweepAngle_ = 0.0;
439     double topAngle_ = DEFAULT_TOPANGLE;
440     double bottomAngle_ = DEFAULT_BOTTOMANGLE;
441     double minAngle_ = DEFAULT_MINANGLE;
442     double outBoundary_ = 0.0;
443     double offsetScale_ = 1.0f;
444     double scrollableOffset_ = 0.0;
445     double barRegionSize_ = 0.0;
446     double friction_ = BAR_FRICTION;
447     double frictionPosition_ = 0.0;
448     float dragStartPosition_ = 0.0f;
449     float dragEndPosition_ = 0.0f;
450 
451     bool isScrollable_ = false;
452 
453     bool isPressed_ = false;
454     bool isDriving_ = false; // false: scroll driving; true: bar driving
455     bool isHover_ = false;
456     bool isOutOfBoundary_ = false; // whether bar in the spring state
457     bool positionModeUpdate_ = false;
458     bool normalWidthUpdate_ = false;
459     bool isUserNormalWidth_ = false;
460     bool needAdaptAnimation_ = false;
461     bool isReverse_ = false;
462     bool isReverseUpdate_ = false;
463 
464     Offset paintOffset_;
465     Size viewPortSize_;
466     Offset lastOffset_;
467     double estimatedHeight_ = 0.0;
468     RefPtr<TouchEventImpl> touchEvent_;
469     RefPtr<InputEvent> mouseEvent_;
470     RefPtr<InputEvent> hoverEvent_;
471     RefPtr<PanRecognizer> panRecognizer_;
472     RefPtr<Animator> frictionController_;
473     RefPtr<FrictionMotion> frictionMotion_;
474     std::function<void()> markNeedRenderFunc_;
475     ScrollPositionCallback scrollPositionCallback_;
476     ScrollEndCallback scrollEndCallback_;
477     CalePredictSnapOffsetCallback calePredictSnapOffsetCallback_;
478     StartScrollSnapMotionCallback startScrollSnapMotionCallback_;
479     ScrollPageCallback scrollPageCallback_;
480     OpacityAnimationType opacityAnimationType_ = OpacityAnimationType::NONE;
481     HoverAnimationType hoverAnimationType_ = HoverAnimationType::NONE;
482     CancelableCallback<void()> disappearDelayTask_;
483     Axis axis_ = Axis::VERTICAL;
484 
485     DragFRCSceneCallback dragFRCSceneCallback_;
486 
487     // dump info
488     std::list<InnerScrollBarLayoutInfo> innerScrollBarLayoutInfos_;
489     bool needAddLayoutInfo = false;
490 
491     RefPtr<ClickEvent> clickevent_;
492     RefPtr<LongPressRecognizer> longPressRecognizer_;
493     bool isMousePressed_ = false;
494     Offset locationInfo_;
495 };
496 
497 } // namespace OHOS::Ace::NG
498 
499 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_INNER_SCROLL_BAR_H
500