1 /*
2 * Copyright (c) 2023-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_SCROLLABLE_SCROLLABLE_PROPERTIES_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLLABLE_SCROLLABLE_PROPERTIES_H
18
19 #include <functional>
20 #include <optional>
21
22 #include "base/geometry/dimension.h"
23 #include "base/geometry/ng/size_t.h"
24 #include "core/components_ng/base/frame_scene_status.h"
25 #include "core/components_ng/event/touch_event.h"
26 #include "core/components_ng/property/layout_constraint.h"
27
28 namespace OHOS::Ace {
29 constexpr float DEFAULT_SCROLL_TO_MASS = 1.0f;
30 constexpr float DEFAULT_SCROLL_TO_STIFFNESS = 227.0f;
31 constexpr float DEFAULT_SCROLL_TO_DAMPING = 33.0f;
32 constexpr float DEFAULT_SCROLL_TO_VELOCITY = 7.0f;
33 // for add item and scrollEdge(Edge.Bottom) in one layout
34 constexpr int32_t LAST_ITEM = -1;
35
36 enum class ScrollState {
37 IDLE = 0,
38 SCROLL,
39 FLING,
40 };
41
42 enum class NestedScrollMode {
43 SELF_ONLY = 0,
44 SELF_FIRST,
45 PARENT_FIRST,
46 PARALLEL,
47 };
48
49 enum class ScrollSnapAlign {
50 NONE = 0,
51 START,
52 CENTER,
53 END,
54 };
55
56 enum class ScrollBarShape {
57 RECT = 0,
58 ARC,
59 };
60
61 enum class ScrollPagingStatus {
62 // no enablePaging set
63 NONE = 0,
64 // enablePaging is false
65 INVALID,
66 // enablePaging is true
67 VALID,
68 };
69
70 enum class SnapType {
71 SCROLL_SNAP = 0,
72 LIST_SNAP,
73 NONE_SNAP
74 };
75
76 enum class SnapDirection {
77 FORWARD = 0,
78 BACKWARD,
79 NONE
80 };
81
82 // use in dumpInfo, excluding events truggered per frame,
83 // such as onScroll, onScrollFrameBegin, onWillScroll, onDidScroll
84 enum class ScrollableEventType {
85 ON_SCROLL_START = 0,
86 ON_SCROLL_STOP,
87 ON_SCROLL_EDGE,
88 ON_REACH_START,
89 ON_REACH_END,
90 };
91
92 struct ScrollInfo {
93 Dimension dx;
94 Dimension dy;
95
96 bool operator==(const ScrollInfo& scrollInfo) const
97 {
98 return dx == scrollInfo.dx && dy == scrollInfo.dy;
99 }
100 };
101
102 struct ScrollFrameInfo {
103 Dimension offset;
104 ScrollState state;
105
106 bool operator==(const ScrollFrameInfo& scrollInfo) const
107 {
108 return offset == scrollInfo.offset && state == scrollInfo.state;
109 }
110 };
111
112 struct ScrollFrameResult {
113 Dimension offset;
114
115 bool operator==(const ScrollFrameResult& scrollRes) const
116 {
117 return offset == scrollRes.offset;
118 }
119 };
120
121 struct ScrollSnapOptions {
122 int32_t snapAlign;
123 int32_t enableSnapToStart;
124 int32_t enableSnapToEnd;
125 std::vector<Dimension> paginationParams;
126 };
127
128 struct NestedScrollOptions {
129 NestedScrollMode forward;
130 NestedScrollMode backward;
131
NeedParentNestedScrollOptions132 bool NeedParent() const
133 {
134 return forward != NestedScrollMode::SELF_ONLY || backward != NestedScrollMode::SELF_ONLY;
135 }
136
NeedParentNestedScrollOptions137 bool NeedParent(bool forward) const
138 {
139 return forward ? this->forward != NestedScrollMode::SELF_ONLY : backward != NestedScrollMode::SELF_ONLY;
140 }
141
142 bool operator==(const NestedScrollOptions& other) const
143 {
144 return forward == other.forward && backward == other.backward;
145 }
146
147 bool operator!=(const NestedScrollOptions& other) const
148 {
149 return !(*this == other);
150 }
151
ToStringNestedScrollOptions152 std::string ToString() const
153 {
154 return "NestedScrollOptions forward: " + std::to_string(static_cast<int32_t>(forward)) +
155 ", backward: " + std::to_string(static_cast<int32_t>(backward));
156 }
157
GetNestedScrollModeStrNestedScrollOptions158 std::string GetNestedScrollModeStr(NestedScrollMode mode) const
159 {
160 switch (mode) {
161 case NestedScrollMode::SELF_ONLY:
162 return "NestedScrollMode.SELF_ONLY";
163 case NestedScrollMode::SELF_FIRST:
164 return "NestedScrollMode.SELF_FIRST";
165 case NestedScrollMode::PARENT_FIRST:
166 return "NestedScrollMode.PARENT_FIRST";
167 case NestedScrollMode::PARALLEL:
168 return "NestedScrollMode.PARALLEL";
169 default:
170 return "";
171 }
172 }
173 };
174
175 struct NestedScrollOptionsExt {
176 NestedScrollMode scrollUp;
177 NestedScrollMode scrollDown;
178 NestedScrollMode scrollLeft;
179 NestedScrollMode scrollRight;
180
ToStringNestedScrollOptionsExt181 std::string ToString() const
182 {
183 return "NestedScrollOptionsExt scrollUp: " + std::to_string(static_cast<int32_t>(scrollUp)) +
184 ", scrollDown: " + std::to_string(static_cast<int32_t>(scrollDown)) +
185 ", scrollLeft: " + std::to_string(static_cast<int32_t>(scrollLeft)) +
186 ", scrollRight: " + std::to_string(static_cast<int32_t>(scrollRight));
187 }
188 };
189
190 struct ListItemIndex {
191 int32_t index = -1;
192 int32_t area = -1;
193 int32_t indexInGroup = -1;
194 };
195
196 constexpr int32_t SCROLL_FROM_NONE = 0;
197 constexpr int32_t SCROLL_FROM_UPDATE = 1;
198 constexpr int32_t SCROLL_FROM_ANIMATION = 2;
199 constexpr int32_t SCROLL_FROM_JUMP = 3;
200 constexpr int32_t SCROLL_FROM_ANIMATION_SPRING = 4;
201 constexpr int32_t SCROLL_FROM_CHILD = 5;
202 constexpr int32_t SCROLL_FROM_BAR = 6;
203 constexpr int32_t SCROLL_FROM_FOCUS_JUMP = 7;
204 constexpr int32_t SCROLL_FROM_ROTATE = 8;
205 constexpr int32_t SCROLL_FROM_INDEXER = 9;
206 constexpr int32_t SCROLL_FROM_START = 10; // from drag start
207 constexpr int32_t SCROLL_FROM_AXIS = 11;
208 constexpr int32_t SCROLL_FROM_ANIMATION_CONTROLLER = 12;
209 constexpr int32_t SCROLL_FROM_BAR_FLING = 13;
210 constexpr int32_t SCROLL_FROM_CROWN = 14;
211 constexpr int32_t SCROLL_FROM_STATUSBAR = 15;
212
GetSourceStr(int32_t scrollSource)213 inline std::string GetSourceStr(int32_t scrollSource)
214 {
215 switch (scrollSource) {
216 case SCROLL_FROM_NONE:
217 return "SCROLL_FROM_NONE";
218 case SCROLL_FROM_UPDATE:
219 return "SCROLL_FROM_UPDATE";
220 case SCROLL_FROM_ANIMATION:
221 return "SCROLL_FROM_ANIMATION";
222 case SCROLL_FROM_JUMP:
223 return "SCROLL_FROM_JUMP";
224 case SCROLL_FROM_ANIMATION_SPRING:
225 return "SCROLL_FROM_ANIMATION_SPRING";
226 case SCROLL_FROM_CHILD:
227 return "SCROLL_FROM_CHILD";
228 case SCROLL_FROM_BAR:
229 return "SCROLL_FROM_BAR";
230 case SCROLL_FROM_FOCUS_JUMP:
231 return "SCROLL_FROM_FOCUS_JUMP";
232 case SCROLL_FROM_ROTATE:
233 return "SCROLL_FROM_ROTATE";
234 case SCROLL_FROM_INDEXER:
235 return "SCROLL_FROM_INDEXER";
236 case SCROLL_FROM_START:
237 return "SCROLL_FROM_START";
238 case SCROLL_FROM_AXIS:
239 return "SCROLL_FROM_AXIS";
240 case SCROLL_FROM_ANIMATION_CONTROLLER:
241 return "SCROLL_FROM_ANIMATION_CONTROLLER";
242 case SCROLL_FROM_BAR_FLING:
243 return "SCROLL_FROM_BAR_FLING";
244 default:
245 return "";
246 }
247 }
248
249 struct ScrollableEventsFiredInfo {
250 uint64_t eventFiredTime_ = 0;
251 ScrollableEventType eventType_;
252 int32_t scrollSource_ = 0;
253
ToStringScrollableEventsFiredInfo254 std::string ToString() const
255 {
256 return std::string("event type: ")
257 .append(GetEventStr())
258 .append(" fired in ")
259 .append(std::to_string(eventFiredTime_))
260 .append(", source is ")
261 .append(GetSourceStr(scrollSource_));
262 }
263
GetEventStrScrollableEventsFiredInfo264 std::string GetEventStr() const
265 {
266 switch (eventType_) {
267 case ScrollableEventType::ON_SCROLL_START:
268 return "onScrollStart";
269 case ScrollableEventType::ON_SCROLL_STOP:
270 return "onScrollStop";
271 case ScrollableEventType::ON_SCROLL_EDGE:
272 return "onScrollEdge";
273 case ScrollableEventType::ON_REACH_START:
274 return "onReachStart";
275 case ScrollableEventType::ON_REACH_END:
276 return "onReachEnd";
277 default:
278 return "";
279 }
280 }
281
ToJsonScrollableEventsFiredInfo282 void ToJson(std::unique_ptr<JsonValue>& json) const
283 {
284 json->Put("event type", GetEventStr().c_str());
285 json->Put("fired in", std::to_string(eventFiredTime_).c_str());
286 json->Put("source is", GetSourceStr(scrollSource_).c_str());
287 }
288 };
289
290 struct ScrollableFrameInfo {
291 uint64_t scrollStateTime_ = 0;
292 int32_t scrollState_ = 0;
293 bool canOverScroll_ = false;
294 uint32_t canOverScrollInfo_ = 0;
295
ToStringScrollableFrameInfo296 std::string ToString() const
297 {
298 return std::string("scroll from: ")
299 .append(GetSourceStr(scrollState_))
300 .append(" canOverScroll: ")
301 .append(std::to_string(canOverScroll_))
302 .append(" isScrollableSpringEffect: ")
303 .append((canOverScrollInfo_ >> 4) & 1 ? "true" : "false")
304 .append(" isScrollable: ")
305 .append((canOverScrollInfo_ >> 3) & 1 ? "true" : "false")
306 .append(" scrollableIdle: ")
307 .append((canOverScrollInfo_ >> 2) & 1 ? "true" : "false")
308 .append(" animateOverScroll: ")
309 .append((canOverScrollInfo_ >> 1) & 1 ? "true" : "false")
310 .append(" animateCanOverScroll: ")
311 .append(canOverScrollInfo_ & 1 ? "true" : "false")
312 .append(" fired in ")
313 .append(std::to_string(scrollStateTime_));
314 }
315
ToJsonScrollableFrameInfo316 void ToJson(std::unique_ptr<JsonValue>& json) const
317 {
318 json->Put("scroll from", GetSourceStr(scrollState_).c_str());
319 json->Put("canOverScroll", std::to_string(canOverScroll_).c_str());
320 json->Put("isScrollableSpringEffect",
321 (canOverScrollInfo_ >> 4) & 1 ? "true" : "false"); // 4: isScrollableSpringEffect
322 json->Put("isScrollable", (canOverScrollInfo_ >> 3) & 1 ? "true" : "false"); // 3: isScrollable
323 json->Put("scrollableIdle", (canOverScrollInfo_ >> 2) & 1 ? "true" : "false"); // 2: scrollableIdle
324 json->Put("animateOverScroll", (canOverScrollInfo_ >> 1) & 1 ? "true" : "false");
325 json->Put("animateCanOverScroll", canOverScrollInfo_ & 1 ? "true" : "false");
326 json->Put("scroll from", std::to_string(scrollStateTime_).c_str());
327 }
328 };
329
330 struct ScrollLayoutInfo {
331 uint64_t changedTime_ = 0;
332 float scrollableDistance_ = 0;
333 NG::SizeF scrollSize_;
334 NG::SizeF viewPort_;
335 NG::SizeF childSize_;
336
ToStringScrollLayoutInfo337 std::string ToString() const
338 {
339 return std::string("scrollableDistance changed, scrollableDistance: ")
340 .append(std::to_string(scrollableDistance_))
341 .append(" scrollSize: ")
342 .append(scrollSize_.ToString())
343 .append(" viewPort: ")
344 .append(viewPort_.ToString())
345 .append(" childSize: ")
346 .append(childSize_.ToString())
347 .append(" fired in ")
348 .append(std::to_string(changedTime_));
349 }
350
ToJsonScrollLayoutInfo351 void ToJson(std::unique_ptr<JsonValue>& json) const
352 {
353 json->Put("scrollableDistance changed, scrollableDistance", std::to_string(scrollableDistance_).c_str());
354 json->Put("scrollSize", scrollSize_.ToString().c_str());
355 json->Put("viewPort", viewPort_.ToString().c_str());
356 json->Put("childSize", childSize_.ToString().c_str());
357 json->Put("fired in", std::to_string(changedTime_).c_str());
358 }
359 };
360
361 struct ScrollMeasureInfo {
362 uint64_t changedTime_ = 0;
363 std::optional<NG::LayoutConstraintF> parentConstraint_;
364 std::optional<NG::LayoutConstraintF> childConstraint_;
365 NG::SizeF selfSize_;
366 NG::SizeF childSize_;
367
ToStringScrollMeasureInfo368 std::string ToString() const
369 {
370 return std::string("Scroll Measure changed, parentConstraint: ")
371 .append(parentConstraint_->ToString())
372 .append(" childConstraint: ")
373 .append(childConstraint_->ToString())
374 .append(" selfSize: ")
375 .append(selfSize_.ToString())
376 .append(" childSize: ")
377 .append(childSize_.ToString())
378 .append(" fired in ")
379 .append(std::to_string(changedTime_));
380 }
381
ToJsonScrollMeasureInfo382 void ToJson(std::unique_ptr<JsonValue>& json) const
383 {
384 json->Put("Scroll Measure changed, parentConstraint", parentConstraint_->ToString().c_str());
385 json->Put("childConstraint", childConstraint_->ToString().c_str());
386 json->Put("selfSize", selfSize_.ToString().c_str());
387 json->Put("childSize", childSize_.ToString().c_str());
388 json->Put("fired in", std::to_string(changedTime_).c_str());
389 }
390 };
391
392 struct InnerScrollBarLayoutInfo {
393 uint64_t layoutTime_ = 0;
394 Size viewPortSize_;
395 Offset lastOffset_;
396 double estimatedHeight_ = 0.0;
397 double outBoundary_ = 0.0;
398 Rect activeRect_;
399
ToStringInnerScrollBarLayoutInfo400 std::string ToString() const
401 {
402 return std::string("inner scrollBar layout, viewPortSize:")
403 .append(viewPortSize_.ToString())
404 .append(" lastOffset: ")
405 .append(lastOffset_.ToString())
406 .append(" estimatedHeight: ")
407 .append(std::to_string(estimatedHeight_))
408 .append(" outBoundary: ")
409 .append(std::to_string(outBoundary_))
410 .append(" activeRect: ")
411 .append(activeRect_.ToString())
412 .append(" fired in ")
413 .append(std::to_string(layoutTime_));
414 }
415
ToJsonInnerScrollBarLayoutInfo416 void ToJson(std::unique_ptr<JsonValue>& json) const
417 {
418 json->Put("inner scrollBar layout, viewPortSize", viewPortSize_.ToString().c_str());
419 json->Put("lastOffset", lastOffset_.ToString().c_str());
420 json->Put("estimatedHeight", estimatedHeight_);
421 json->Put("outBoundary", std::to_string(outBoundary_).c_str());
422 json->Put("activeRect", activeRect_.ToString().c_str());
423 json->Put("fired in", std::to_string(layoutTime_).c_str());
424 }
425 };
426
427 struct OuterScrollBarLayoutInfo {
428 uint64_t layoutTime_ = 0;
429 float currentOffset_ = 0.f;
430 float scrollableNodeOffset_ = 0.f;
431
ToStringOuterScrollBarLayoutInfo432 std::string ToString() const
433 {
434 return std::string("outer scrollBar layout, currentOffset:")
435 .append(std::to_string(currentOffset_))
436 .append(" scrollableNodeOffset: ")
437 .append(std::to_string(scrollableNodeOffset_))
438 .append(" fired in ")
439 .append(std::to_string(layoutTime_));
440 }
441
ToJsonOuterScrollBarLayoutInfo442 void ToJson(std::unique_ptr<JsonValue>& json) const
443 {
444 json->Put("outer scrollBar layout, currentOffset", std::to_string(currentOffset_).c_str());
445 json->Put("scrollableNodeOffset", std::to_string(scrollableNodeOffset_).c_str());
446 json->Put("fired in", std::to_string(layoutTime_).c_str());
447 }
448 };
449
450 enum class ScrollSource {
451 DRAG = 0, // constexpr int32_t SCROLL_FROM_UPDATE = 1;
452 FLING, // constexpr int32_t SCROLL_FROM_ANIMATION = 2;
453 EDGE_EFFECT, // constexpr int32_t SCROLL_FROM_ANIMATION_SPRING = 4;
454 OTHER_USER_INPUT, // constexpr int32_t SCROLL_FROM_AXIS = 11;
455 SCROLL_BAR, // constexpr int32_t SCROLL_FROM_BAR = 6;
456 SCROLL_BAR_FLING, // constexpr int32_t SCROLL_FROM_BAR_FLING = 13;
457 SCROLLER, // constexpr int32_t SCROLL_FROM_JUMP = 3;
458 SCROLLER_ANIMATION, // constexpr int32_t SCROLL_FROM_ANIMATION_CONTROLLER = 12;
459 };
460
461 struct SnapAnimationOptions {
462 float snapDelta = 0.f;
463 float animationVelocity = 0.f;
464 float dragDistance = 0.f;
465 SnapDirection snapDirection = SnapDirection::NONE;
466 bool fromScrollBar = false;
467 };
468
469 // app tail animation
470 constexpr char TRAILING_ANIMATION[] = "TRAILING_ANIMATION ";
471
472 // scroller animation, such as scrollTo, scrollPage
473 constexpr char SCROLLER_ANIMATION[] = "CUSTOM_ANIMATOR_SCROLLER_ANIMATION ";
474
475 // scrollToEdge at a fixed speed
476 constexpr char SCROLLER_FIX_VELOCITY_ANIMATION[] = "SCROLLER_FIX_VELOCITY_ANIMATION ";
477
478 using OnScrollEvent = std::function<void(Dimension, ScrollState)>;
479 using OnDidScrollEvent = std::function<void(Dimension, ScrollSource, bool, bool)>;
480 using OnWillScrollEvent = std::function<ScrollFrameResult(Dimension, ScrollState, ScrollSource)>;
481 using OnScrollBeginEvent = std::function<ScrollInfo(Dimension, Dimension)>;
482 using OnScrollFrameBeginEvent = std::function<ScrollFrameResult(Dimension, ScrollState)>;
483 using OnScrollStartEvent = std::function<void()>;
484 using OnScrollStopEvent = std::function<void()>;
485 using OnReachEvent = std::function<void()>;
486 using OnScrollIndexEvent = std::function<void(int32_t, int32_t, int32_t)>;
487 using OnScrollVisibleContentChangeEvent = std::function<void(ListItemIndex, ListItemIndex)>;
488
489 using ScrollPositionCallback = std::function<bool(double, int32_t source)>;
490 using ScrollEndCallback = std::function<void()>;
491 using StartSnapAnimationCallback = std::function<bool(SnapAnimationOptions)>;
492 using ScrollBarFRCallback = std::function<void(double velocity, NG::SceneStatus sceneStatus)>;
493 using ScrollPageCallback = std::function<void(bool, bool smooth)>;
494
495 struct ScrollerObserver {
496 RefPtr<NG::TouchEventImpl> onTouchEvent;
497 OnReachEvent onReachStartEvent;
498 OnReachEvent onReachEndEvent;
499 OnScrollStartEvent onScrollStartEvent;
500 OnScrollStopEvent onScrollStopEvent;
501 OnDidScrollEvent onDidScrollEvent;
502 };
503 } // namespace OHOS::Ace
504
505 #endif
506