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