1 /*
2 * Copyright (c) 2025 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_ng/pattern/scrollable/scrollable_controller.h"
17
18 #include "base/memory/referenced.h"
19 #include "base/utils/multi_thread.h"
20 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
21 #include "core/components_ng/pattern/waterflow/water_flow_pattern.h"
22
23 namespace OHOS::Ace::NG {
24
AnimateToMultiThread(const Dimension & position,float duration,const RefPtr<Curve> & curve,bool smooth,bool canOverScroll)25 bool ScrollableController::AnimateToMultiThread(
26 const Dimension& position, float duration, const RefPtr<Curve>& curve, bool smooth, bool canOverScroll)
27 {
28 auto pattern = scroll_.Upgrade();
29 CHECK_NULL_RETURN(pattern, false);
30 auto host = pattern->GetHost();
31 CHECK_NULL_RETURN(host, false);
32 if (pattern->GetAxis() != Axis::NONE) {
33 if (position.Unit() == DimensionUnit::PERCENT) {
34 return false;
35 }
36 if (Positive(duration) || smooth) {
37 host->PostAfterAttachMainTreeTask([weak = AceType::WeakClaim(AceType::RawPtr(pattern)),
38 weakPtr = AceType::WeakClaim(AceType::RawPtr(host)), position,
39 duration, curve, smooth, canOverScroll]() {
40 auto host = weakPtr.Upgrade();
41 CHECK_NULL_VOID(host);
42 auto pattern = weak.Upgrade();
43 CHECK_NULL_VOID(pattern);
44 ACE_SCOPED_TRACE(
45 "ScrollTo with animation, position:%f, duration:%f, smooth:%u, canOverScroll:%u, id:%d, tag:%s",
46 position.ConvertToPx(), duration, smooth, canOverScroll,
47 static_cast<int32_t>(host->GetAccessibilityId()), host->GetTag().c_str());
48 pattern->AnimateTo(position.ConvertToPx(), duration, curve, smooth, canOverScroll);
49 });
50 } else {
51 host->PostAfterAttachMainTreeTask([weak = AceType::WeakClaim(AceType::RawPtr(pattern)),
52 weakPtr = AceType::WeakClaim(AceType::RawPtr(host)), position]() {
53 auto host = weakPtr.Upgrade();
54 CHECK_NULL_VOID(host);
55 auto pattern = weak.Upgrade();
56 CHECK_NULL_VOID(pattern);
57 ACE_SCOPED_TRACE("ScrollTo without animation, position:%f, id:%d, tag:%s", position.ConvertToPx(),
58 static_cast<int32_t>(host->GetAccessibilityId()), host->GetTag().c_str());
59
60 pattern->ScrollTo(position.ConvertToPx());
61 });
62 }
63 return true;
64 }
65 return false;
66 }
67
ScrollToEdgeMultiThread(ScrollEdgeType scrollEdgeType,bool smooth)68 void ScrollableController::ScrollToEdgeMultiThread(ScrollEdgeType scrollEdgeType, bool smooth)
69 {
70 auto pattern = scroll_.Upgrade();
71 CHECK_NULL_VOID(pattern);
72 if (pattern->GetAxis() == Axis::FREE && pattern->FreeScrollToEdge(scrollEdgeType, smooth, std::nullopt)) {
73 return;
74 }
75 auto host = pattern->GetHost();
76 CHECK_NULL_VOID(host);
77 host->PostAfterAttachMainTreeTask([weak = AceType::WeakClaim(AceType::RawPtr(pattern)), scrollEdgeType, smooth]() {
78 auto pattern = weak.Upgrade();
79 CHECK_NULL_VOID(pattern);
80 if (pattern->GetAxis() != Axis::NONE) {
81 pattern->ScrollToEdge(scrollEdgeType, smooth);
82 }
83 });
84 }
85
ScrollByMultiThread(double pixelX,double pixelY,bool)86 void ScrollableController::ScrollByMultiThread(double pixelX, double pixelY, bool /* smooth */)
87 {
88 auto pattern = scroll_.Upgrade();
89 CHECK_NULL_VOID(pattern);
90 if (pattern->GetAxis() == Axis::FREE && pattern->FreeScrollBy(OffsetF { -pixelX, -pixelY })) {
91 return;
92 }
93 auto host = pattern->GetHost();
94 CHECK_NULL_VOID(host);
95 host->PostAfterAttachMainTreeTask([weak = AceType::WeakClaim(AceType::RawPtr(pattern)),
96 weakNode = AceType::WeakClaim(AceType::RawPtr(host)), pixelX, pixelY]() {
97 auto pattern = weak.Upgrade();
98 CHECK_NULL_VOID(pattern);
99 auto host = weakNode.Upgrade();
100 CHECK_NULL_VOID(host);
101 pattern->StopAnimate();
102 auto offset = pattern->GetAxis() == Axis::VERTICAL ? pixelY : pixelX;
103 ACE_SCOPED_TRACE("ScrollBy, offset:%f, id:%d, tag:%s", static_cast<float>(-offset),
104 static_cast<int32_t>(host->GetAccessibilityId()), host->GetTag().c_str());
105 if (pattern->GetAxis() == Axis::FREE && pattern->FreeScrollBy(OffsetF { -pixelX, -pixelY })) {
106 return;
107 }
108 pattern->SetIsOverScroll(false);
109 pattern->UpdateCurrentOffset(static_cast<float>(-offset), SCROLL_FROM_JUMP);
110 });
111 }
112
FlingMultiThread(double flingVelocity)113 void ScrollableController::FlingMultiThread(double flingVelocity)
114 {
115 auto pattern = scroll_.Upgrade();
116 CHECK_NULL_VOID(pattern);
117 auto host = pattern->GetHost();
118 CHECK_NULL_VOID(host);
119 host->PostAfterAttachMainTreeTask([weak = AceType::WeakClaim(AceType::RawPtr(pattern)),
120 weakNode = AceType::WeakClaim(AceType::RawPtr(host)), flingVelocity]() {
121 auto pattern = weak.Upgrade();
122 CHECK_NULL_VOID(pattern);
123 auto host = weakNode.Upgrade();
124 CHECK_NULL_VOID(host);
125 ACE_SCOPED_TRACE("Fling, flingVelocity:%f, id:%d, tag:%s", static_cast<float>(flingVelocity),
126 static_cast<int32_t>(host->GetAccessibilityId()), host->GetTag().c_str());
127 pattern->Fling(flingVelocity);
128 });
129 }
130
131 } // namespace OHOS::Ace::NG
132