1 /*
2  * Copyright (c) 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 "bridge/cj_frontend/interfaces/cj_ffi/cj_list_ffi.h"
17 #include "core/components/scroll/scroll_controller_base.h"
18 #include "core/components/scroll/scroll_controller.h"
19 #include "cj_lambda.h"
20 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_scroll_ffi.h"
21 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_view_abstract_ffi.h"
22 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
23 #include "core/components_ng/base/view_abstract.h"
24 #include "core/components_ng/base/view_abstract_model.h"
25 #include "core/components_ng/pattern/list/list_model.h"
26 #include "core/components_ng/pattern/list/list_position_controller.h"
27 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h"
28 
29 using namespace OHOS::Ace;
30 using namespace OHOS::FFI;
31 using namespace OHOS::Ace::Framework;
32 
33 namespace {
34 const std::vector<Axis> AXIS = { Axis::VERTICAL, Axis::HORIZONTAL };
35 const std::vector<EdgeEffect> LIST_EDGE_EFFECT = { EdgeEffect::SPRING, EdgeEffect::FADE, EdgeEffect::NONE };
36 const std::vector<DisplayMode> DISPLAY_MODE = { DisplayMode::OFF, DisplayMode::AUTO, DisplayMode::ON };
37 const std::vector<ScrollState> SCROLL_STATE = { ScrollState::IDLE, ScrollState::SCROLL,
38     ScrollState::FLING };
39 const std::vector<V2::ListItemAlign> LIST_ITEM_ALIGN = { V2::ListItemAlign::START, V2::ListItemAlign::CENTER,
40     V2::ListItemAlign::END };
41 const std::vector<V2::StickyStyle> STICKY_STYLE = { V2::StickyStyle::NONE, V2::StickyStyle::HEADER,
42     V2::StickyStyle::FOOTER, V2::StickyStyle::BOTH };
43 
FormatOnScrollFunction(void (* callback)(double offset,int32_t state))44 std::function<void(Dimension, ScrollState)> FormatOnScrollFunction(void (*callback)(double offset, int32_t state))
45 {
46     auto result = [lambda = CJLambda::Create(callback)](const Dimension& offset, const ScrollState& state) -> void {
47         int32_t offseState = 0;
48         for (size_t  i = 0; i < SCROLL_STATE.size(); i++) {
49             if (SCROLL_STATE[i] == state) {
50                 offseState = static_cast<int32_t>(i);
51             }
52         }
53         lambda(offset.Value(), offseState);
54     };
55     return result;
56 }
57 
FormatOnScrollBeginFunction(FfiOffsetRemain (* callback)(double dx,double dy))58 OnScrollBeginEvent FormatOnScrollBeginFunction(FfiOffsetRemain (*callback)(double dx, double dy))
59 {
60     auto result = [lambda = CJLambda::Create(callback)](const Dimension& dx, const Dimension& dy) -> ScrollInfo {
61         ScrollInfo scrollInfo;
62         FfiOffsetRemain result = lambda(dx.Value(), dy.Value());
63         scrollInfo.dx = Dimension { result.dxRemain, DimensionUnit::VP };
64         scrollInfo.dy = Dimension { result.dyRemain, DimensionUnit::VP };
65         return scrollInfo;
66     };
67     return result;
68 }
69 } // namespace
70 
71 extern "C" {
FfiOHOSAceFrameworkListCreate(double space,int32_t unit,int32_t initialIndex,int64_t scrollerID)72 void FfiOHOSAceFrameworkListCreate(double space, int32_t unit, int32_t initialIndex, int64_t scrollerID)
73 {
74     Dimension spaceDime(space, static_cast<DimensionUnit>(unit));
75 
76     ListModel::GetInstance()->Create();
77     ListModel::GetInstance()->SetSpace(spaceDime);
78     if (initialIndex >= 0) {
79         ListModel::GetInstance()->SetInitialIndex(initialIndex);
80     }
81     if (scrollerID > 0) {
82         auto scroller = FFIData::GetData<NativeNGScroller>(scrollerID);
83         if (scroller == nullptr) {
84             LOGE("invalid scrollerID");
85             return;
86         }
87         RefPtr<ScrollControllerBase> listController = ListModel::GetInstance()->CreateScrollController();
88         scroller->SetController(listController);
89 
90         auto proxy = AceType::DynamicCast<NG::ScrollBarProxy>(scroller->GetScrollBarProxy());
91         if (!proxy) {
92             proxy = AceType::MakeRefPtr<NG::ScrollBarProxy>();
93             scroller->SetScrollBarProxy(proxy);
94         }
95         ListModel::GetInstance()->SetScroller(listController, proxy);
96     }
97 }
98 
FfiOHOSAceFrameworkListSetHeight(double height,int32_t unit)99 void FfiOHOSAceFrameworkListSetHeight(double height, int32_t unit)
100 {
101     Dimension value(height, static_cast<DimensionUnit>(unit));
102     if (value.Value() < 0.0f) {
103         value.SetValue(0.0);
104     }
105 
106     ViewAbstractModel::GetInstance()->SetHeight(value);
107     ListModel::GetInstance()->SetHasHeight(true);
108 }
109 
FfiOHOSAceFrameworkListSetWidth(double width,int32_t unit)110 void FfiOHOSAceFrameworkListSetWidth(double width, int32_t unit)
111 {
112     Dimension value(width, static_cast<DimensionUnit>(unit));
113     if (value.Value() < 0.0f) {
114         value.SetValue(0.0);
115     }
116 
117     ViewAbstractModel::GetInstance()->SetWidth(value);
118     ListModel::GetInstance()->SetHasWidth(true);
119 }
120 
FfiOHOSAceFrameworkListSetDirection(int32_t direction)121 void FfiOHOSAceFrameworkListSetDirection(int32_t direction)
122 {
123     if (!Utils::CheckParamsValid(direction, AXIS.size())) {
124         LOGE("bindContextMenu error, invalid value for responseType");
125         return;
126     }
127     ListModel::GetInstance()->SetListDirection(AXIS[direction]);
128 }
129 
FfiOHOSAceFrameworkListSetDivider(DividerParams params)130 void FfiOHOSAceFrameworkListSetDivider(DividerParams params)
131 {
132     Dimension widthDime(params.width, static_cast<DimensionUnit>(params.widthUnit));
133     Dimension startMarginDime(params.startMargin, static_cast<DimensionUnit>(params.startMarginUnit));
134     Dimension endMarginDime(params.endMargin, static_cast<DimensionUnit>(params.endMarginUnit));
135 
136     V2::ItemDivider divider;
137     divider.strokeWidth = widthDime;
138     divider.color = Color(params.color);
139     divider.startMargin = startMarginDime;
140     divider.endMargin = endMarginDime;
141 
142     ListModel::GetInstance()->SetDivider(divider);
143 }
144 
FfiOHOSAceFrameworkListSetEditMode(bool flag)145 void FfiOHOSAceFrameworkListSetEditMode(bool flag)
146 {
147     ListModel::GetInstance()->SetEditMode(flag);
148 }
149 
FfiOHOSAceFrameworkListSetEdgeEffect(int32_t edgeEffect)150 void FfiOHOSAceFrameworkListSetEdgeEffect(int32_t edgeEffect)
151 {
152     if (!Utils::CheckParamsValid(edgeEffect, LIST_EDGE_EFFECT.size())) {
153         LOGE("bindContextMenu error, invalid value for responseType");
154         return;
155     }
156     ListModel::GetInstance()->SetEdgeEffect(LIST_EDGE_EFFECT[edgeEffect], true);
157 }
158 
FfiOHOSAceFrameworkListSetChainAnimation(bool flag)159 void FfiOHOSAceFrameworkListSetChainAnimation(bool flag)
160 {
161     ListModel::GetInstance()->SetChainAnimation(flag);
162 }
163 
FfiOHOSAceFrameworkListSetMultiSelectable(bool flag)164 void FfiOHOSAceFrameworkListSetMultiSelectable(bool flag)
165 {
166     ListModel::GetInstance()->SetMultiSelectable(flag);
167 }
168 
FfiOHOSAceFrameworkListSetLanes(int32_t lanes)169 void FfiOHOSAceFrameworkListSetLanes(int32_t lanes)
170 {
171     ListModel::GetInstance()->SetLanes(lanes);
172 }
173 
FfiOHOSAceFrameworkListSetLanesByLengthConstrain(double min,int32_t minUnit,double max,int32_t maxUnit)174 void FfiOHOSAceFrameworkListSetLanesByLengthConstrain(double min, int32_t minUnit, double max, int32_t maxUnit)
175 {
176     Dimension minDime(min, static_cast<DimensionUnit>(minUnit));
177     Dimension maxDime(max, static_cast<DimensionUnit>(maxUnit));
178     ListModel::GetInstance()->SetLaneConstrain(minDime, maxDime);
179 }
180 
FfiOHOSAceFrameworkListSetAlignListItem(int32_t align)181 void FfiOHOSAceFrameworkListSetAlignListItem(int32_t align)
182 {
183     if (!Utils::CheckParamsValid(align, LIST_ITEM_ALIGN.size())) {
184         LOGE("bindContextMenu error, invalid value for listItemAlign");
185         return;
186     }
187     ListModel::GetInstance()->SetListItemAlign(LIST_ITEM_ALIGN[align]);
188 }
189 
FfiOHOSAceFrameworkListSetSticky(int32_t style)190 void FfiOHOSAceFrameworkListSetSticky(int32_t style)
191 {
192     if (!Utils::CheckParamsValid(style, STICKY_STYLE.size())) {
193         LOGE("bindContextMenu error, invalid value for listItemAlign");
194         return;
195     }
196     ListModel::GetInstance()->SetSticky(STICKY_STYLE[style]);
197 }
198 
FfiOHOSAceFrameworkListSetNestedScroll(int32_t scrollForward,int32_t scrollBackward)199 void FfiOHOSAceFrameworkListSetNestedScroll(int32_t scrollForward, int32_t scrollBackward)
200 {
201     NestedScrollOptions localNestedScrollOptions = {.forward = NestedScrollMode(scrollForward),
202         .backward = NestedScrollMode(scrollBackward)};
203     ListModel::GetInstance()->SetNestedScroll(localNestedScrollOptions);
204 }
205 
FfiOHOSAceFrameworkListSetCachedCount(int32_t cachedCount)206 void FfiOHOSAceFrameworkListSetCachedCount(int32_t cachedCount)
207 {
208     int32_t value = cachedCount < 0 ? 1 : cachedCount;
209     ListModel::GetInstance()->SetCachedCount(value);
210 }
211 
FfiOHOSAceFrameworkListSetScrollBar(int32_t barState)212 void FfiOHOSAceFrameworkListSetScrollBar(int32_t barState)
213 {
214     if (!Utils::CheckParamsValid(barState, DISPLAY_MODE.size())) {
215         LOGE("bindContextMenu error, invalid value for barState");
216         return;
217     }
218     ListModel::GetInstance()->SetScrollBar(DISPLAY_MODE[barState]);
219 }
220 
FfiOHOSAceFrameworkListSetItemDeleteCallback(bool (* callback)(int32_t value))221 void FfiOHOSAceFrameworkListSetItemDeleteCallback(bool (*callback)(int32_t value))
222 {
223     ListModel::GetInstance()->SetOnItemDelete(CJLambda::Create(callback));
224 }
225 
FfiOHOSAceFrameworkListSetScrollIndexCallback(void (* callback)(int32_t firstIndex,int32_t lastIndex))226 void FfiOHOSAceFrameworkListSetScrollIndexCallback(void (*callback)(int32_t firstIndex, int32_t lastIndex))
227 {
228     auto lambda = [callback = CJLambda::Create(callback)](int32_t a, int32_t b, int32_t c) {
229         callback(a, b);
230     };
231     ListModel::GetInstance()->SetOnScrollIndex(lambda);
232 }
233 
FfiOHOSAceFrameworkListSetOnScrollFrameBegin(double (* callback)(double offset,int32_t state))234 void FfiOHOSAceFrameworkListSetOnScrollFrameBegin(double (*callback)(double offset, int32_t state))
235 {
236     auto lambda = [callback = CJLambda::Create(callback)](const Dimension& offset, const ScrollState& state)
237      -> ScrollFrameResult {
238         auto res = callback(offset.Value(), static_cast<int32_t>(state));
239         ScrollFrameResult scrollRes { .offset = Dimension { res, DimensionUnit::VP } };
240         return scrollRes;
241     };
242     ListModel::GetInstance()->SetOnScrollFrameBegin(lambda);
243 }
244 
FfiOHOSAceFrameworkListSetOnScrollCallback(void (* callback)(double offset,int32_t state))245 void FfiOHOSAceFrameworkListSetOnScrollCallback(void (*callback)(double offset, int32_t state))
246 {
247     ListModel::GetInstance()->SetOnScroll(FormatOnScrollFunction(callback));
248 }
249 
FfiOHOSAceFrameworkListSetOnReachStartCallback(void (* callback)())250 void FfiOHOSAceFrameworkListSetOnReachStartCallback(void (*callback)())
251 {
252     ListModel::GetInstance()->SetOnReachStart(CJLambda::Create(callback));
253 }
254 
FfiOHOSAceFrameworkListSetOnReachEndCallback(void (* callback)())255 void FfiOHOSAceFrameworkListSetOnReachEndCallback(void (*callback)())
256 {
257     ListModel::GetInstance()->SetOnReachEnd(CJLambda::Create(callback));
258 }
259 
FfiOHOSAceFrameworkListSetOnScrollStartCallback(void (* callback)())260 void FfiOHOSAceFrameworkListSetOnScrollStartCallback(void (*callback)())
261 {
262     ListModel::GetInstance()->SetOnScrollStart(CJLambda::Create(callback));
263 }
264 
FfiOHOSAceFrameworkListSetOnScrollStopCallback(void (* callback)())265 void FfiOHOSAceFrameworkListSetOnScrollStopCallback(void (*callback)())
266 {
267     ListModel::GetInstance()->SetOnScrollStop(CJLambda::Create(callback));
268 }
269 
FfiOHOSAceFrameworkListSetOnScrollBeginCallback(FfiOffsetRemain (* callback)(double dx,double dy))270 void FfiOHOSAceFrameworkListSetOnScrollBeginCallback(FfiOffsetRemain (*callback)(double dx, double dy))
271 {
272     ListModel::GetInstance()->SetOnScrollBegin(FormatOnScrollBeginFunction(callback));
273 }
274 }
275