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