1 /*
2  * Copyright (c) 2021-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 #include "core/components/scroll/scroll_position_controller.h"
17 
18 #include "core/components/scroll/render_scroll.h"
19 
20 namespace OHOS::Ace {
21 
ScrollEventInfo(ScrollEvent type,double scrollX,double scrollY,int32_t scrollState)22 ScrollEventInfo::ScrollEventInfo(ScrollEvent type, double scrollX, double scrollY, int32_t scrollState)
23     : BaseEventInfo("scroll"), type_(type), scrollX_(scrollX), scrollY_(scrollY), scrollState_(scrollState)
24 {}
25 
ToJSONString() const26 std::string ScrollEventInfo::ToJSONString() const
27 {
28     switch (type_) {
29         case ScrollEvent::SCROLL_TOP:
30             return std::string("\"scrolltop\",null");
31         case ScrollEvent::SCROLL_BOTTOM:
32             return std::string("\"scrollbottom\",null");
33         case ScrollEvent::SCROLL_END:
34             return std::string("\"scrollend\",null");
35         case ScrollEvent::SCROLL_TOUCHUP:
36             return std::string("\"scrolltouchup\",null");
37         case ScrollEvent::SCROLL_POSITION:
38             return std::string("\"scroll\",{\"scrollX\":")
39                         .append(std::to_string(scrollX_))
40                         .append(",\"scrollY\":")
41                         .append(std::to_string(scrollY_))
42                         .append(",\"scrollState\":")
43                         .append(std::to_string(scrollState_))
44                         .append("},null");
45         default:
46             return "";
47     }
48 }
49 
ScrollToIndex(int32_t index,bool,ScrollAlign,std::optional<float>)50 void ScrollPositionController::ScrollToIndex(
51     int32_t index, bool /* smooth */, ScrollAlign /* align */, std::optional<float> /* extraOffset */)
52 {
53     RefPtr<RenderNode> node = scroll_.Upgrade();
54     if (node) {
55         auto scroll = AceType::DynamicCast<RenderScroll>(node);
56         if (scroll) {
57             scroll->JumpToIndex(index);
58         }
59     }
60 }
61 
JumpTo(double position)62 void ScrollPositionController::JumpTo(double position)
63 {
64     RefPtr<RenderNode> node = scroll_.Upgrade();
65     if (node) {
66         auto scroll = AceType::DynamicCast<RenderScroll>(node);
67         if (scroll) {
68             scroll->JumpToPosition(position);
69         }
70     }
71 }
72 
AnimateTo(double position,float duration,const RefPtr<Curve> & curve,bool limitDuration,const std::function<void ()> & onFinish)73 bool ScrollPositionController::AnimateTo(double position, float duration, const RefPtr<Curve>& curve,
74     bool limitDuration, const std::function<void()>& onFinish)
75 {
76     RefPtr<RenderNode> node = scroll_.Upgrade();
77     if (node) {
78         auto scroll = AceType::DynamicCast<RenderScroll>(node);
79         if (scroll) {
80             scroll->AnimateTo(position, duration, curve, limitDuration, onFinish);
81             return true;
82         }
83     }
84     return false;
85 }
86 
AnimateTo(const Dimension & position,float duration,const RefPtr<Curve> & curve,bool smooth,bool canOverScroll)87 bool ScrollPositionController::AnimateTo(
88     const Dimension& position, float duration, const RefPtr<Curve>& curve, bool smooth, bool canOverScroll)
89 {
90     RefPtr<RenderNode> node = scroll_.Upgrade();
91     if (node) {
92         auto scroll = AceType::DynamicCast<RenderScroll>(node);
93         if (scroll && scroll->GetAxis() != Axis::NONE) {
94             auto normalizedPos = scroll->NormalizePercentToPx(position, scroll->GetAxis() == Axis::VERTICAL);
95             scroll->AnimateTo(normalizedPos, duration, curve, true, nullptr);
96             return true;
97         }
98     }
99     return false;
100 }
101 
AnimateToTarget(const ComposeId & targetId,float duration,const RefPtr<Curve> & curve,bool limitDuration,const std::function<void ()> & onFinish)102 bool ScrollPositionController::AnimateToTarget(const ComposeId& targetId, float duration, const RefPtr<Curve>& curve,
103     bool limitDuration, const std::function<void()>& onFinish)
104 {
105     RefPtr<RenderNode> node = scroll_.Upgrade();
106     if (node) {
107         auto scroll = AceType::DynamicCast<RenderScroll>(node);
108         if (scroll) {
109             return scroll->AnimateToTarget(targetId, duration, curve, limitDuration, onFinish);
110         }
111     }
112     return false;
113 }
114 
ScrollBy(double pixelX,double pixelY,bool smooth)115 void ScrollPositionController::ScrollBy(double pixelX, double pixelY, bool smooth)
116 {
117     RefPtr<RenderNode> node = scroll_.Upgrade();
118     if (node) {
119         auto scroll = AceType::DynamicCast<RenderScroll>(node);
120         if (scroll) {
121             scroll->ScrollBy(pixelX, pixelY, smooth);
122         }
123     }
124 }
125 
ScrollArrow(double scrollDistance,bool reverse,bool smooth)126 void ScrollPositionController::ScrollArrow(double scrollDistance, bool reverse, bool smooth)
127 {
128     if (scrollDistance > 0.0) {
129         RefPtr<RenderNode> node = scroll_.Upgrade();
130         if (node) {
131             auto scroll = AceType::DynamicCast<RenderScroll>(node);
132             if (scroll) {
133                 if (reverse) {
134                     ScrollBy(-scrollDistance, -scrollDistance, smooth);
135                 } else {
136                     ScrollBy(scrollDistance, scrollDistance, smooth);
137                 }
138             }
139         }
140     }
141 }
142 
GetCurrentPosition() const143 double ScrollPositionController::GetCurrentPosition() const
144 {
145     RefPtr<RenderNode> node = scroll_.Upgrade();
146     if (!node) {
147         return 0.0;
148     }
149     auto scroll = AceType::DynamicCast<RenderScroll>(node);
150     if (!scroll) {
151         return 0.0;
152     }
153 
154     return scroll->GetCurrentPosition();
155 }
156 
GetScrollDirection() const157 Axis ScrollPositionController::GetScrollDirection() const
158 {
159     auto direction = Axis::VERTICAL;
160     RefPtr<RenderNode> node = scroll_.Upgrade();
161     if (node) {
162         auto scroll = AceType::DynamicCast<RenderScroll>(node);
163         if (scroll) {
164             direction = scroll->GetAxis();
165         }
166     }
167     return direction;
168 }
169 
ScrollToEdge(ScrollEdgeType scrollEdgeType,bool smooth)170 void ScrollPositionController::ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth)
171 {
172     RefPtr<RenderNode> node = scroll_.Upgrade();
173     if (node) {
174         auto scroll = AceType::DynamicCast<RenderScroll>(node);
175         if (scroll && scroll->GetAxis() != Axis::NONE) {
176             scroll->ScrollToEdge(scrollEdgeType, smooth);
177         }
178     }
179 }
180 
ScrollPage(bool reverse,bool smooth)181 void ScrollPositionController::ScrollPage(bool reverse, bool smooth)
182 {
183     RefPtr<RenderNode> node = scroll_.Upgrade();
184     if (node) {
185         auto scroll = AceType::DynamicCast<RenderScroll>(node);
186         if (scroll && scroll->GetAxis() != Axis::NONE) {
187             scroll->ScrollPage(reverse, smooth);
188         }
189     }
190 }
191 
GetCurrentOffset() const192 Offset ScrollPositionController::GetCurrentOffset() const
193 {
194     RefPtr<RenderNode> node = scroll_.Upgrade();
195     auto scroll = AceType::DynamicCast<RenderScroll>(node);
196     if (!scroll) {
197         return Offset::Zero();
198     }
199 
200     auto ctx = scroll->GetContext().Upgrade();
201     if (!ctx) {
202         return Offset::Zero();
203     }
204     if (!ctx->GetIsDeclarative()) {
205         return scroll->GetCurrentOffset();
206     }
207 
208     auto pxOffset = scroll->GetCurrentOffset();
209     auto x = Dimension(pxOffset.GetX(), DimensionUnit::PX);
210     auto y = Dimension(pxOffset.GetY(), DimensionUnit::PX);
211     Offset offset(ctx->ConvertPxToVp(x), ctx->ConvertPxToVp(y));
212 
213     return offset;
214 }
215 } // namespace OHOS::Ace
216