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