1 /*
2 * Copyright (c) 2021-2023 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 "frameworks/bridge/declarative_frontend/jsview/js_swiper.h"
17
18 #include <algorithm>
19 #include <cstdint>
20 #include <iterator>
21
22 #include "base/log/ace_scoring_log.h"
23 #include "base/utils/utils.h"
24 #include "bridge/common/utils/utils.h"
25 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
26 #include "bridge/declarative_frontend/engine/functions/js_swiper_function.h"
27 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
28 #include "bridge/declarative_frontend/jsview/models/swiper_model_impl.h"
29 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme_utils.h"
30 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_swiper_theme.h"
31 #include "bridge/declarative_frontend/view_stack_processor.h"
32 #include "bridge/js_frontend/engine/jsi/js_value.h"
33 #include "core/animation/curve.h"
34 #include "core/components/common/layout/constants.h"
35 #include "core/components/common/properties/scroll_bar.h"
36 #include "core/components/swiper/swiper_component.h"
37 #include "core/components/swiper/swiper_indicator_theme.h"
38 #include "core/components_ng/base/view_stack_processor.h"
39 #include "core/components_ng/pattern/scrollable/scrollable_properties.h"
40 #include "core/components_ng/pattern/swiper/swiper_content_transition_proxy.h"
41 #include "core/components_ng/pattern/swiper/swiper_model.h"
42 #include "core/components_ng/pattern/swiper/swiper_model_ng.h"
43 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
44 #include "bridge/declarative_frontend/jsview/js_indicator.h"
45
46 namespace OHOS::Ace {
47 namespace {
48 constexpr float ARROW_SIZE_COEFFICIENT = 0.75f;
49 constexpr int32_t DEFAULT_CUSTOM_ANIMATION_TIMEOUT = 0;
50 const auto DEFAULT_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(-1, 1, 328, 34);
51 } // namespace
52 std::unique_ptr<SwiperModel> SwiperModel::instance_ = nullptr;
53 std::mutex SwiperModel::mutex_;
54
GetInstance()55 SwiperModel* SwiperModel::GetInstance()
56 {
57 if (!instance_) {
58 std::lock_guard<std::mutex> lock(mutex_);
59 if (!instance_) {
60 #ifdef NG_BUILD
61 instance_.reset(new NG::SwiperModelNG());
62 #else
63 if (Container::IsCurrentUseNewPipeline()) {
64 instance_.reset(new NG::SwiperModelNG());
65 } else {
66 instance_.reset(new Framework::SwiperModelImpl());
67 }
68 #endif
69 }
70 }
71 return instance_.get();
72 }
73
74 } // namespace OHOS::Ace
75 namespace OHOS::Ace::Framework {
76 namespace {
77
78 const std::vector<EdgeEffect> EDGE_EFFECT = { EdgeEffect::SPRING, EdgeEffect::FADE, EdgeEffect::NONE };
79 const std::vector<SwiperDisplayMode> DISPLAY_MODE = { SwiperDisplayMode::STRETCH, SwiperDisplayMode::AUTO_LINEAR };
80 const std::vector<SwiperIndicatorType> INDICATOR_TYPE = { SwiperIndicatorType::DOT, SwiperIndicatorType::DIGIT };
81 const static int32_t DEFAULT_INTERVAL = 3000;
82 const static int32_t DEFAULT_DURATION = 400;
83 const static int32_t DEFAULT_DISPLAY_COUNT = 1;
84 const static int32_t DEFAULT_CACHED_COUNT = 1;
85
SwiperChangeEventToJSValue(const SwiperChangeEvent& eventInfo)86 JSRef<JSVal> SwiperChangeEventToJSValue(const SwiperChangeEvent& eventInfo)
87 {
88 return JSRef<JSVal>::Make(ToJSValue(eventInfo.GetIndex()));
89 }
90
91 } // namespace
92
Create(const JSCallbackInfo& info)93 void JSSwiper::Create(const JSCallbackInfo& info)
94 {
95 auto controller = SwiperModel::GetInstance()->Create();
96
97 if (info.Length() > 0 && info[0]->IsObject()) {
98 auto* jsController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSwiperController>();
99 if (jsController) {
100 jsController->SetInstanceId(Container::CurrentId());
101 jsController->SetController(controller);
102 }
103 }
104
105 JSSwiperTheme::ApplyThemeInConstructor();
106 }
107
JsRemoteMessage(const JSCallbackInfo& info)108 void JSSwiper::JsRemoteMessage(const JSCallbackInfo& info)
109 {
110 RemoteCallback remoteCallback;
111 JSInteractableView::JsRemoteMessage(info, remoteCallback);
112
113 SwiperModel::GetInstance()->SetRemoteMessageEventId(std::move(remoteCallback));
114 }
115
JSBind(BindingTarget globalObj)116 void JSSwiper::JSBind(BindingTarget globalObj)
117 {
118 JsSwiperContentTransitionProxy::JSBind(globalObj);
119 JSClass<JSSwiper>::Declare("Swiper");
120 MethodOptions opt = MethodOptions::NONE;
121 JSClass<JSSwiper>::StaticMethod("create", &JSSwiper::Create, opt);
122 JSClass<JSSwiper>::StaticMethod("indicatorInteractive", &JSSwiper::SetIndicatorInteractive, opt);
123 JSClass<JSSwiper>::StaticMethod("autoPlay", &JSSwiper::SetAutoPlay, opt);
124 JSClass<JSSwiper>::StaticMethod("duration", &JSSwiper::SetDuration, opt);
125 JSClass<JSSwiper>::StaticMethod("index", &JSSwiper::SetIndex, opt);
126 JSClass<JSSwiper>::StaticMethod("interval", &JSSwiper::SetInterval, opt);
127 JSClass<JSSwiper>::StaticMethod("loop", &JSSwiper::SetLoop, opt);
128 JSClass<JSSwiper>::StaticMethod("vertical", &JSSwiper::SetVertical, opt);
129 JSClass<JSSwiper>::StaticMethod("indicator", &JSSwiper::SetIndicator, opt);
130 JSClass<JSSwiper>::StaticMethod("displayMode", &JSSwiper::SetDisplayMode);
131 JSClass<JSSwiper>::StaticMethod("effectMode", &JSSwiper::SetEffectMode);
132 JSClass<JSSwiper>::StaticMethod("displayCount", &JSSwiper::SetDisplayCount);
133 JSClass<JSSwiper>::StaticMethod("itemSpace", &JSSwiper::SetItemSpace);
134 JSClass<JSSwiper>::StaticMethod("prevMargin", &JSSwiper::SetPreviousMargin);
135 JSClass<JSSwiper>::StaticMethod("nextMargin", &JSSwiper::SetNextMargin);
136 JSClass<JSSwiper>::StaticMethod("cachedCount", &JSSwiper::SetCachedCount);
137 JSClass<JSSwiper>::StaticMethod("curve", &JSSwiper::SetCurve);
138 JSClass<JSSwiper>::StaticMethod("onChange", &JSSwiper::SetOnChange);
139 JSClass<JSSwiper>::StaticMethod("onAnimationStart", &JSSwiper::SetOnAnimationStart);
140 JSClass<JSSwiper>::StaticMethod("onAnimationEnd", &JSSwiper::SetOnAnimationEnd);
141 JSClass<JSSwiper>::StaticMethod("onGestureSwipe", &JSSwiper::SetOnGestureSwipe);
142 JSClass<JSSwiper>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
143 JSClass<JSSwiper>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
144 JSClass<JSSwiper>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
145 JSClass<JSSwiper>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
146 JSClass<JSSwiper>::StaticMethod("remoteMessage", &JSSwiper::JsRemoteMessage);
147 JSClass<JSSwiper>::StaticMethod("onClick", &JSSwiper::SetOnClick);
148 JSClass<JSSwiper>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
149 JSClass<JSSwiper>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
150 JSClass<JSSwiper>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
151 JSClass<JSSwiper>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
152 JSClass<JSSwiper>::StaticMethod("indicatorStyle", &JSSwiper::SetIndicatorStyle);
153 JSClass<JSSwiper>::StaticMethod("enabled", &JSSwiper::SetEnabled);
154 JSClass<JSSwiper>::StaticMethod("disableSwipe", &JSSwiper::SetDisableSwipe);
155 JSClass<JSSwiper>::StaticMethod("height", &JSSwiper::SetHeight);
156 JSClass<JSSwiper>::StaticMethod("width", &JSSwiper::SetWidth);
157 JSClass<JSSwiper>::StaticMethod("size", &JSSwiper::SetSize);
158 JSClass<JSSwiper>::StaticMethod("displayArrow", &JSSwiper::SetDisplayArrow);
159 JSClass<JSSwiper>::StaticMethod("nestedScroll", &JSSwiper::SetNestedScroll);
160 JSClass<JSSwiper>::StaticMethod("customContentTransition", &JSSwiper::SetCustomContentTransition);
161 JSClass<JSSwiper>::StaticMethod("onContentDidScroll", &JSSwiper::SetOnContentDidScroll);
162 JSClass<JSSwiper>::InheritAndBind<JSContainerBase>(globalObj);
163 }
164
SetIndicatorInteractive(const JSCallbackInfo& info)165 void JSSwiper::SetIndicatorInteractive(const JSCallbackInfo& info)
166 {
167 if (info.Length() < 1) {
168 return;
169 }
170
171 if (info[0]->IsBoolean()) {
172 SwiperModel::GetInstance()->SetIndicatorInteractive(info[0]->ToBoolean());
173 } else {
174 SwiperModel::GetInstance()->SetIndicatorInteractive(true);
175 }
176 }
177
SetAutoPlay(bool autoPlay)178 void JSSwiper::SetAutoPlay(bool autoPlay)
179 {
180 SwiperModel::GetInstance()->SetAutoPlay(autoPlay);
181 }
182
SetEnabled(const JSCallbackInfo& info)183 void JSSwiper::SetEnabled(const JSCallbackInfo& info)
184 {
185 JSViewAbstract::JsEnabled(info);
186 if (info.Length() < 1) {
187 return;
188 }
189
190 if (!info[0]->IsBoolean()) {
191 return;
192 }
193
194 SwiperModel::GetInstance()->SetEnabled(info[0]->ToBoolean());
195 }
196
SetDisableSwipe(bool disableSwipe)197 void JSSwiper::SetDisableSwipe(bool disableSwipe)
198 {
199 SwiperModel::GetInstance()->SetDisableSwipe(disableSwipe);
200 }
201
SetEffectMode(const JSCallbackInfo& info)202 void JSSwiper::SetEffectMode(const JSCallbackInfo& info)
203 {
204 if (info.Length() < 1) {
205 return;
206 }
207
208 if (!info[0]->IsNumber()) {
209 return;
210 }
211
212 auto edgeEffect = info[0]->ToNumber<int32_t>();
213 if (edgeEffect < 0 || edgeEffect >= static_cast<int32_t>(EDGE_EFFECT.size())) {
214 return;
215 }
216
217 SwiperModel::GetInstance()->SetEdgeEffect(EDGE_EFFECT[edgeEffect]);
218 }
219
SetDisplayCount(const JSCallbackInfo& info)220 void JSSwiper::SetDisplayCount(const JSCallbackInfo& info)
221 {
222 if (info.Length() < 1) {
223 return;
224 }
225
226 if (info.Length() == 2) {
227 if (info[1]->IsBoolean()) {
228 SwiperModel::GetInstance()->SetSwipeByGroup(info[1]->ToBoolean());
229 } else {
230 SwiperModel::GetInstance()->SetSwipeByGroup(false);
231 }
232 }
233
234 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
235 if (info[0]->IsString() && info[0]->ToString() == "auto") {
236 SwiperModel::GetInstance()->SetDisplayMode(SwiperDisplayMode::AUTO_LINEAR);
237 SwiperModel::GetInstance()->ResetDisplayCount();
238 } else if (info[0]->IsNumber() && info[0]->ToNumber<int32_t>() > 0) {
239 SwiperModel::GetInstance()->SetDisplayCount(info[0]->ToNumber<int32_t>());
240 } else if (info[0]->IsObject()) {
241 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
242 auto minSizeParam = jsObj->GetProperty("minSize");
243 if (minSizeParam->IsNull()) {
244 return;
245 }
246 CalcDimension minSizeValue;
247 if (!ParseJsDimensionVp(minSizeParam, minSizeValue)) {
248 SwiperModel::GetInstance()->SetMinSize(0.0_vp);
249 return;
250 }
251 SwiperModel::GetInstance()->SetMinSize(minSizeValue);
252 } else {
253 SwiperModel::GetInstance()->SetDisplayCount(DEFAULT_DISPLAY_COUNT);
254 }
255
256 return;
257 }
258
259 if (info[0]->IsString() && info[0]->ToString() == "auto") {
260 SwiperModel::GetInstance()->SetDisplayMode(SwiperDisplayMode::AUTO_LINEAR);
261 SwiperModel::GetInstance()->ResetDisplayCount();
262 } else if (info[0]->IsNumber()) {
263 SwiperModel::GetInstance()->SetDisplayCount(info[0]->ToNumber<int32_t>());
264 }
265 }
266
SetDuration(const JSCallbackInfo& info)267 void JSSwiper::SetDuration(const JSCallbackInfo& info)
268 {
269 int32_t duration = DEFAULT_DURATION;
270
271 if (info.Length() < 1) { // user do not set any value
272 return;
273 }
274
275 // undefined value turn to default 400
276 if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
277 duration = info[0]->ToNumber<int32_t>();
278 if (duration < 0) {
279 duration = DEFAULT_DURATION;
280 }
281 }
282
283 SwiperModel::GetInstance()->SetDuration(duration);
284 }
285
ParseSwiperIndexObject(const JSCallbackInfo& args, const JSRef<JSVal>& changeEventVal)286 void ParseSwiperIndexObject(const JSCallbackInfo& args, const JSRef<JSVal>& changeEventVal)
287 {
288 CHECK_NULL_VOID(changeEventVal->IsFunction());
289
290 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
291 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
292 auto onIndex = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
293 const BaseEventInfo* info) {
294 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
295 ACE_SCORING_EVENT("Swiper.onChangeEvent");
296 PipelineContext::SetCallBackNode(node);
297 const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
298 if (!swiperInfo) {
299 return;
300 }
301 auto newJSVal = JSRef<JSVal>::Make(ToJSValue(swiperInfo->GetIndex()));
302 func->ExecuteJS(1, &newJSVal);
303 };
304 SwiperModel::GetInstance()->SetOnChangeEvent(std::move(onIndex));
305 }
306
SetIndex(const JSCallbackInfo& info)307 void JSSwiper::SetIndex(const JSCallbackInfo& info)
308 {
309 auto length = info.Length();
310 if (length < 1 || length > 2) {
311 return;
312 }
313
314 int32_t index = 0;
315 auto jsIndex = info[0];
316 if (length > 0 && jsIndex->IsNumber()) {
317 index = jsIndex->ToNumber<int32_t>();
318 }
319
320 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
321 index = index < 0 ? 0 : index;
322 }
323
324 if (index < 0) {
325 return;
326 }
327 SwiperModel::GetInstance()->SetIndex(index);
328
329 if (length > 1 && info[1]->IsFunction()) {
330 ParseSwiperIndexObject(info, info[1]);
331 }
332 }
333
334 void JSSwiper::SetInterval(const JSCallbackInfo& info)
335 {
336 int32_t interval = DEFAULT_INTERVAL;
337
338 if (info.Length() < 1) { // user do not set any value
339 return;
340 }
341
342 // undefined value turn to default 3000
343 if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
344 interval = info[0]->ToNumber<int32_t>();
345 if (interval < 0) {
346 interval = DEFAULT_INTERVAL;
347 }
348 }
349
350 SwiperModel::GetInstance()->SetAutoPlayInterval(interval);
351 }
352
353 void JSSwiper::SetLoop(const JSCallbackInfo& info)
354 {
355 if (info.Length() < 1) {
356 return;
357 }
358
359 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
360 SwiperModel::GetInstance()->SetLoop(info[0]->ToBoolean());
361 return;
362 }
363
364 if (info[0]->IsBoolean()) {
365 SwiperModel::GetInstance()->SetLoop(info[0]->ToBoolean());
366 } else {
367 SwiperModel::GetInstance()->SetLoop(true);
368 }
369 }
370
371 void JSSwiper::SetVertical(bool isVertical)
372 {
373 SwiperModel::GetInstance()->SetDirection(isVertical ? Axis::VERTICAL : Axis::HORIZONTAL);
374 }
375
376 void JSSwiper::GetFontContent(const JSRef<JSVal>& font, bool isSelected, SwiperDigitalParameters& digitalParameters)
377 {
378 JSRef<JSObject> obj = JSRef<JSObject>::Cast(font);
379 JSRef<JSVal> size = obj->GetProperty("size");
380 auto pipelineContext = PipelineBase::GetCurrentContext();
381 CHECK_NULL_VOID(pipelineContext);
382 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
383 CHECK_NULL_VOID(swiperIndicatorTheme);
384 // set font size, unit FP
385 CalcDimension fontSize;
386 if (!size->IsUndefined() && !size->IsNull() && ParseJsDimensionFp(size, fontSize)) {
387 if (LessOrEqual(fontSize.Value(), 0.0) || LessOrEqual(size->ToNumber<double>(), 0.0) ||
388 fontSize.Unit() == DimensionUnit::PERCENT) {
389 fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
390 }
391 } else {
392 fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
393 }
394 if (isSelected) {
395 digitalParameters.selectedFontSize = fontSize;
396 } else {
397 digitalParameters.fontSize = fontSize;
398 }
399 JSRef<JSVal> weight = obj->GetProperty("weight");
400 if (!weight->IsNull()) {
401 std::string weightValue;
402 if (weight->IsNumber()) {
403 weightValue = std::to_string(weight->ToNumber<int32_t>());
404 } else {
405 ParseJsString(weight, weightValue);
406 }
407 if (isSelected) {
408 digitalParameters.selectedFontWeight = ConvertStrToFontWeight(weightValue);
409 } else {
410 digitalParameters.fontWeight = ConvertStrToFontWeight(weightValue);
411 }
412 } else {
413 if (isSelected) {
414 digitalParameters.selectedFontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
415 } else {
416 digitalParameters.fontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
417 }
418 }
419 }
420
421 void JSSwiper::SetIsIndicatorCustomSize(const Dimension& dimPosition, bool parseOk)
422 {
423 if (parseOk && dimPosition > 0.0_vp) {
424 SwiperModel::GetInstance()->SetIsIndicatorCustomSize(true);
425 } else {
426 SwiperModel::GetInstance()->SetIsIndicatorCustomSize(false);
427 }
428 }
429
430 std::optional<Dimension> JSSwiper::ParseIndicatorDimension(const JSRef<JSVal>& value)
431 {
432 std::optional<Dimension> indicatorDimension;
433 if (value->IsUndefined()) {
434 return indicatorDimension;
435 }
436 CalcDimension dimPosition;
437 auto parseOk = ParseJsDimensionVp(value, dimPosition);
438 indicatorDimension = parseOk && dimPosition.ConvertToPx() >= 0.0f ? dimPosition : 0.0_vp;
439 return indicatorDimension;
440 }
441
442 SwiperParameters JSSwiper::GetDotIndicatorInfo(const JSRef<JSObject>& obj)
443 {
444 JSRef<JSVal> leftValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT_VALUE));
445 JSRef<JSVal> topValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP_VALUE));
446 JSRef<JSVal> rightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT_VALUE));
447 JSRef<JSVal> bottomValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM_VALUE));
448 JSRef<JSVal> startValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::START_VALUE));
449 JSRef<JSVal> endValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::END_VALUE));
450 JSRef<JSVal> itemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_WIDTH_VALUE));
451 JSRef<JSVal> itemHeightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_HEIGHT_VALUE));
452 JSRef<JSVal> selectedItemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_WIDTH_VALUE));
453 JSRef<JSVal> selectedItemHeightValue =
454 obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_HEIGHT_VALUE));
455 auto pipelineContext = PipelineBase::GetCurrentContext();
456 CHECK_NULL_RETURN(pipelineContext, SwiperParameters());
457 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
458 CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperParameters());
459 SwiperParameters swiperParameters;
460 swiperParameters.dimLeft = ParseIndicatorDimension(leftValue);
461 swiperParameters.dimTop = ParseIndicatorDimension(topValue);
462 swiperParameters.dimRight = ParseIndicatorDimension(rightValue);
463 swiperParameters.dimBottom = ParseIndicatorDimension(bottomValue);
464 CalcDimension dimStart;
465 CalcDimension dimEnd;
466 std::optional<Dimension> indicatorDimension;
467 swiperParameters.dimStart = ParseLengthMetricsToDimension(startValue, dimStart) ? dimStart : indicatorDimension;
468 swiperParameters.dimEnd = ParseLengthMetricsToDimension(endValue, dimEnd) ? dimEnd : indicatorDimension;
469
470 CalcDimension dimPosition;
471 bool parseItemWOk =
472 ParseJsDimensionVp(itemWidthValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
473 auto defaultSize = swiperIndicatorTheme->GetSize();
474 swiperParameters.itemWidth = parseItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
475 bool parseItemHOk =
476 ParseJsDimensionVp(itemHeightValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
477 swiperParameters.itemHeight = parseItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
478 bool parseSelectedItemWOk =
479 ParseJsDimensionVp(selectedItemWidthValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
480 swiperParameters.selectedItemWidth = parseSelectedItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
481 bool parseSelectedItemHOk =
482 ParseJsDimensionVp(selectedItemHeightValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
483 swiperParameters.selectedItemHeight = parseSelectedItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
484 SwiperModel::GetInstance()->SetIsIndicatorCustomSize(
485 parseSelectedItemWOk || parseSelectedItemHOk || parseItemWOk || parseItemHOk);
486 SetDotIndicatorInfo(obj, swiperParameters, swiperIndicatorTheme);
487 return swiperParameters;
488 }
489 void JSSwiper::SetDotIndicatorInfo(const JSRef<JSObject>& obj, SwiperParameters& swiperParameters,
490 const RefPtr<SwiperIndicatorTheme>& swiperIndicatorTheme)
491 {
492 JSRef<JSVal> maskValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MASK_VALUE));
493 JSRef<JSVal> colorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR_VALUE));
494 JSRef<JSVal> selectedColorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_COLOR_VALUE));
495 JSRef<JSVal> maxDisplayCountVal = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MAX_DISPLAY_COUNT_VALUE));
496 if (maskValue->IsBoolean()) {
497 auto mask = maskValue->ToBoolean();
498 swiperParameters.maskValue = mask;
499 }
500 Color colorVal;
501 auto parseOk = ParseJsColor(colorValue, colorVal);
502 swiperParameters.colorVal = parseOk ? colorVal : swiperIndicatorTheme->GetColor();
503 parseOk = ParseJsColor(selectedColorValue, colorVal);
504 swiperParameters.selectedColorVal = parseOk ? colorVal : swiperIndicatorTheme->GetSelectedColor();
505 if (maxDisplayCountVal->IsUndefined()) {
506 return;
507 }
508 uint32_t result = 0;
509 auto setMaxDisplayCountVal = ParseJsInteger(maxDisplayCountVal, result);
510 swiperParameters.maxDisplayCountVal = setMaxDisplayCountVal && result > 0 ? result : 0;
511 }
512 bool JSSwiper::ParseLengthMetricsToDimension(const JSRef<JSVal>& jsValue, CalcDimension& result)
513 {
514 if (jsValue->IsNumber()) {
515 result = CalcDimension(jsValue->ToNumber<double>(), DimensionUnit::VP);
516 return true;
517 }
518 if (jsValue->IsString()) {
519 auto value = jsValue->ToString();
520 StringUtils::StringToCalcDimensionNG(value, result, false, DimensionUnit::VP);
521 return true;
522 }
523 if (jsValue->IsObject()) {
524 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
525 double value = jsObj->GetProperty("value")->ToNumber<double>();
526 auto unit = static_cast<DimensionUnit>(jsObj->GetProperty("unit")->ToNumber<int32_t>());
527 result = CalcDimension(value, unit);
528 return true;
529 }
530 if (jsValue->IsNull()) {
531 result = CalcDimension(0.0f, DimensionUnit::VP);
532 return true;
533 }
534
535 return false;
536 }
537
538 SwiperDigitalParameters JSSwiper::GetDigitIndicatorInfo(const JSRef<JSObject>& obj)
539 {
540 JSRef<JSVal> dotLeftValue = obj->GetProperty("leftValue");
541 JSRef<JSVal> dotTopValue = obj->GetProperty("topValue");
542 JSRef<JSVal> dotRightValue = obj->GetProperty("rightValue");
543 JSRef<JSVal> dotBottomValue = obj->GetProperty("bottomValue");
544 JSRef<JSVal> startValue = obj->GetProperty("startValue");
545 JSRef<JSVal> endValue = obj->GetProperty("endValue");
546 JSRef<JSVal> fontColorValue = obj->GetProperty("fontColorValue");
547 JSRef<JSVal> selectedFontColorValue = obj->GetProperty("selectedFontColorValue");
548 JSRef<JSVal> digitFontValue = obj->GetProperty("digitFontValue");
549 JSRef<JSVal> selectedDigitFontValue = obj->GetProperty("selectedDigitFontValue");
550 auto pipelineContext = PipelineBase::GetCurrentContext();
551 CHECK_NULL_RETURN(pipelineContext, SwiperDigitalParameters());
552 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
553 CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperDigitalParameters());
554 SwiperDigitalParameters digitalParameters;
555 digitalParameters.dimLeft = ParseIndicatorDimension(dotLeftValue);
556 digitalParameters.dimTop = ParseIndicatorDimension(dotTopValue);
557 digitalParameters.dimRight = ParseIndicatorDimension(dotRightValue);
558 digitalParameters.dimBottom = ParseIndicatorDimension(dotBottomValue);
559 std::optional<Dimension> indicatorDimension;
560 CalcDimension dimStart;
561 CalcDimension dimEnd;
562 digitalParameters.dimStart = ParseLengthMetricsToDimension(startValue, dimStart) ? dimStart : indicatorDimension;
563 digitalParameters.dimEnd = ParseLengthMetricsToDimension(endValue, dimEnd) ? dimEnd : indicatorDimension;
564
565 Color fontColor;
566 auto parseOk = JSViewAbstract::ParseJsColor(fontColorValue, fontColor);
567 digitalParameters.fontColor =
568 parseOk ? fontColor : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
569 parseOk = JSViewAbstract::ParseJsColor(selectedFontColorValue, fontColor);
570 digitalParameters.selectedFontColor =
571 parseOk ? fontColor : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
572 if (!digitFontValue->IsNull() && digitFontValue->IsObject()) {
573 GetFontContent(digitFontValue, false, digitalParameters);
574 }
575 if (!selectedDigitFontValue->IsNull() && selectedDigitFontValue->IsObject()) {
576 GetFontContent(selectedDigitFontValue, true, digitalParameters);
577 }
578 return digitalParameters;
579 }
580
581 bool JSSwiper::GetArrowInfo(const JSRef<JSObject>& obj, SwiperArrowParameters& swiperArrowParameters)
582 {
583 auto isShowBackgroundValue = obj->GetProperty("showBackground");
584 auto isSidebarMiddleValue = obj->GetProperty("isSidebarMiddle");
585 auto backgroundSizeValue = obj->GetProperty("backgroundSize");
586 auto backgroundColorValue = obj->GetProperty("backgroundColor");
587 auto arrowSizeValue = obj->GetProperty("arrowSize");
588 auto arrowColorValue = obj->GetProperty("arrowColor");
589 auto pipelineContext = PipelineBase::GetCurrentContext();
590 CHECK_NULL_RETURN(pipelineContext, false);
591 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
592 CHECK_NULL_RETURN(swiperIndicatorTheme, false);
593 swiperArrowParameters.isShowBackground = isShowBackgroundValue->IsBoolean()
594 ? isShowBackgroundValue->ToBoolean()
595 : swiperIndicatorTheme->GetIsShowArrowBackground();
596 swiperArrowParameters.isSidebarMiddle = isSidebarMiddleValue->IsBoolean()
597 ? isSidebarMiddleValue->ToBoolean()
598 : swiperIndicatorTheme->GetIsSidebarMiddle();
599 bool parseOk = false;
600 CalcDimension dimension;
601 Color color;
602 if (swiperArrowParameters.isSidebarMiddle.value()) {
603 parseOk = ParseJsDimensionVp(backgroundSizeValue, dimension);
604 swiperArrowParameters.backgroundSize =
605 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
606 ? dimension
607 : swiperIndicatorTheme->GetBigArrowBackgroundSize();
608 parseOk = ParseJsColor(backgroundColorValue, color);
609 swiperArrowParameters.backgroundColor = parseOk ? color : swiperIndicatorTheme->GetBigArrowBackgroundColor();
610 if (swiperArrowParameters.isShowBackground.value()) {
611 swiperArrowParameters.arrowSize = swiperArrowParameters.backgroundSize.value() * ARROW_SIZE_COEFFICIENT;
612 } else {
613 parseOk = ParseJsDimensionVpNG(arrowSizeValue, dimension);
614 swiperArrowParameters.arrowSize =
615 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
616 ? dimension
617 : swiperIndicatorTheme->GetBigArrowSize();
618 swiperArrowParameters.backgroundSize = swiperArrowParameters.arrowSize;
619 }
620 parseOk = ParseJsColor(arrowColorValue, color);
621 swiperArrowParameters.arrowColor = parseOk ? color : swiperIndicatorTheme->GetBigArrowColor();
622 } else {
623 parseOk = ParseJsDimensionVp(backgroundSizeValue, dimension);
624 swiperArrowParameters.backgroundSize =
625 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
626 ? dimension
627 : swiperIndicatorTheme->GetSmallArrowBackgroundSize();
628 parseOk = ParseJsColor(backgroundColorValue, color);
629 swiperArrowParameters.backgroundColor = parseOk ? color : swiperIndicatorTheme->GetSmallArrowBackgroundColor();
630 if (swiperArrowParameters.isShowBackground.value()) {
631 swiperArrowParameters.arrowSize = swiperArrowParameters.backgroundSize.value() * ARROW_SIZE_COEFFICIENT;
632 } else {
633 parseOk = ParseJsDimensionVpNG(arrowSizeValue, dimension);
634 swiperArrowParameters.arrowSize =
635 parseOk && GreatNotEqual(dimension.ConvertToVp(), 0.0) && !(dimension.Unit() == DimensionUnit::PERCENT)
636 ? dimension
637 : swiperIndicatorTheme->GetSmallArrowSize();
638 swiperArrowParameters.backgroundSize = swiperArrowParameters.arrowSize;
639 }
640 parseOk = ParseJsColor(arrowColorValue, color);
641 swiperArrowParameters.arrowColor = parseOk ? color : swiperIndicatorTheme->GetSmallArrowColor();
642 }
643 return true;
644 }
645
646 void JSSwiper::SetDisplayArrow(const JSCallbackInfo& info)
647 {
648 if (info[0]->IsEmpty() || info[0]->IsUndefined()) {
649 SwiperModel::GetInstance()->SetDisplayArrow(false);
650 return;
651 }
652 if (info.Length() > 0 && info[0]->IsObject()) {
653 auto obj = JSRef<JSObject>::Cast(info[0]);
654 SwiperArrowParameters swiperArrowParameters;
655 if (!GetArrowInfo(obj, swiperArrowParameters)) {
656 SwiperModel::GetInstance()->SetDisplayArrow(false);
657 return;
658 }
659 JSSwiperTheme::ApplyThemeToDisplayArrow(swiperArrowParameters, obj);
660 SwiperModel::GetInstance()->SetArrowStyle(swiperArrowParameters);
661 SwiperModel::GetInstance()->SetDisplayArrow(true);
662 } else if (info[0]->IsBoolean()) {
663 if (info[0]->ToBoolean()) {
664 auto pipelineContext = PipelineBase::GetCurrentContext();
665 CHECK_NULL_VOID(pipelineContext);
666 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
667 CHECK_NULL_VOID(swiperIndicatorTheme);
668 SwiperArrowParameters swiperArrowParameters;
669 swiperArrowParameters.isShowBackground = swiperIndicatorTheme->GetIsShowArrowBackground();
670 swiperArrowParameters.isSidebarMiddle = swiperIndicatorTheme->GetIsSidebarMiddle();
671 swiperArrowParameters.backgroundSize = swiperIndicatorTheme->GetSmallArrowBackgroundSize();
672 swiperArrowParameters.backgroundColor = swiperIndicatorTheme->GetSmallArrowBackgroundColor();
673 swiperArrowParameters.arrowSize = swiperIndicatorTheme->GetSmallArrowSize();
674 swiperArrowParameters.arrowColor = swiperIndicatorTheme->GetSmallArrowColor();
675 JSSwiperTheme::ApplyThemeToDisplayArrowForce(swiperArrowParameters);
676 SwiperModel::GetInstance()->SetArrowStyle(swiperArrowParameters);
677 SwiperModel::GetInstance()->SetDisplayArrow(true);
678 } else {
679 SwiperModel::GetInstance()->SetDisplayArrow(false);
680 return;
681 }
682 } else {
683 SwiperModel::GetInstance()->SetDisplayArrow(false);
684 return;
685 }
686 if (info.Length() > 1 && info[1]->IsBoolean()) {
687 SwiperModel::GetInstance()->SetHoverShow(info[1]->ToBoolean());
688 } else {
689 SwiperModel::GetInstance()->SetHoverShow(false);
690 }
691 }
692
693 void JSSwiper::SetIndicatorController(const JSCallbackInfo& info)
694 {
695 if (info.Length() < 1 || !info[0]->IsObject()) {
696 return;
697 }
698
699 auto* jsIndicatorController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSIndicatorController>();
700 if (!jsIndicatorController) {
701 return;
702 }
703
704 WeakPtr<NG::UINode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
705 jsIndicatorController->SetSwiperNode(targetNode);
706 SwiperModel::GetInstance()->SetBindIndicator(true);
707 }
708
709 void JSSwiper::SetIndicator(const JSCallbackInfo& info)
710 {
711 if (info.Length() < 1) {
712 return;
713 }
714
715 if (info[0]->IsEmpty()) {
716 SwiperModel::GetInstance()->SetShowIndicator(true);
717 return;
718 }
719 SwiperModel::GetInstance()->SetBindIndicator(false);
720 if (info[0]->IsObject()) {
721 auto obj = JSRef<JSObject>::Cast(info[0]);
722 SwiperModel::GetInstance()->SetIndicatorIsBoolean(false);
723
724 JSRef<JSVal> typeParam = obj->GetProperty("type");
725 if (typeParam->IsString()) {
726 auto type = typeParam->ToString();
727 if (type == "DigitIndicator") {
728 SwiperDigitalParameters digitalParameters = GetDigitIndicatorInfo(obj);
729 JSSwiperTheme::ApplyThemeToDigitIndicator(digitalParameters, obj);
730 SwiperModel::GetInstance()->SetDigitIndicatorStyle(digitalParameters);
731 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DIGIT);
732 } else {
733 SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
734 JSSwiperTheme::ApplyThemeToDotIndicator(swiperParameters, obj);
735 SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
736 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
737 }
738 } else if (typeParam->IsUndefined()) {
739 SetIndicatorController(info);
740 } else {
741 SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
742 JSSwiperTheme::ApplyThemeToDotIndicatorForce(swiperParameters);
743 SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
744 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
745 }
746 } else {
747 SwiperParameters swiperParameters = GetDotIndicatorInfo(JSRef<JSObject>::New());
748 JSSwiperTheme::ApplyThemeToDotIndicatorForce(swiperParameters);
749 SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
750 SwiperModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
751 }
752 if (info[0]->IsBoolean()) {
753 bool showIndicator = false;
754 ParseJsBool(info[0], showIndicator);
755 SwiperModel::GetInstance()->SetShowIndicator(showIndicator);
756 } else {
757 SwiperModel::GetInstance()->SetShowIndicator(true);
758 }
759 }
760
761 void JSSwiper::SetIndicatorStyle(const JSCallbackInfo& info)
762 {
763 SwiperParameters swiperParameters;
764 if (info[0]->IsObject()) {
765 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
766 JSRef<JSVal> leftValue = obj->GetProperty("left");
767 JSRef<JSVal> topValue = obj->GetProperty("top");
768 JSRef<JSVal> rightValue = obj->GetProperty("right");
769 JSRef<JSVal> bottomValue = obj->GetProperty("bottom");
770 JSRef<JSVal> sizeValue = obj->GetProperty("size");
771 JSRef<JSVal> maskValue = obj->GetProperty("mask");
772 JSRef<JSVal> colorValue = obj->GetProperty("color");
773 JSRef<JSVal> selectedColorValue = obj->GetProperty("selectedColor");
774 auto pipelineContext = PipelineBase::GetCurrentContext();
775 CHECK_NULL_VOID(pipelineContext);
776 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
777 CHECK_NULL_VOID(swiperIndicatorTheme);
778 swiperParameters.dimLeft = ParseIndicatorDimension(leftValue);
779 swiperParameters.dimTop = ParseIndicatorDimension(topValue);
780 swiperParameters.dimRight = ParseIndicatorDimension(rightValue);
781 swiperParameters.dimBottom = ParseIndicatorDimension(bottomValue);
782 CalcDimension dimPosition;
783 auto parseOk = ParseJsDimensionVp(sizeValue, dimPosition) && (dimPosition.Unit() != DimensionUnit::PERCENT);
784 SetIsIndicatorCustomSize(dimPosition, parseOk);
785 swiperParameters.itemWidth = parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
786 swiperParameters.itemHeight = parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
787 swiperParameters.selectedItemWidth =
788 parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
789 swiperParameters.selectedItemHeight =
790 parseOk && dimPosition > 0.0_vp ? dimPosition : swiperIndicatorTheme->GetSize();
791 if (maskValue->IsBoolean()) {
792 auto mask = maskValue->ToBoolean();
793 swiperParameters.maskValue = mask;
794 }
795 Color colorVal;
796 parseOk = ParseJsColor(colorValue, colorVal);
797 swiperParameters.colorVal = parseOk ? colorVal : swiperIndicatorTheme->GetColor();
798 parseOk = ParseJsColor(selectedColorValue, colorVal);
799 swiperParameters.selectedColorVal = parseOk ? colorVal : swiperIndicatorTheme->GetSelectedColor();
800 }
801 SwiperModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
802 info.ReturnSelf();
803 }
804
805 void JSSwiper::SetItemSpace(const JSCallbackInfo& info)
806 {
807 if (info.Length() < 1) {
808 return;
809 }
810
811 CalcDimension value;
812 if (!ParseJsDimensionVp(info[0], value) || LessNotEqual(value.Value(), 0.0)) {
813 value.SetValue(0.0);
814 }
815
816 SwiperModel::GetInstance()->SetItemSpace(value);
817 }
818
819 void JSSwiper::SetPreviousMargin(const JSCallbackInfo& info)
820 {
821 if (info.Length() < 1) {
822 return;
823 }
824
825 CalcDimension value;
826 bool ignoreBlank = false;
827 if (!ParseJsDimensionVp(info[0], value) || info[0]->IsNull() || info[0]->IsUndefined() ||
828 LessNotEqual(value.Value(), 0.0)) {
829 value.SetValue(0.0);
830 }
831 if (info.Length() > 1 && info[1]->IsBoolean()) {
832 ignoreBlank = info[1]->ToBoolean();
833 }
834 SwiperModel::GetInstance()->SetPreviousMargin(value, ignoreBlank);
835 }
836
837 void JSSwiper::SetNextMargin(const JSCallbackInfo& info)
838 {
839 if (info.Length() < 1) {
840 return;
841 }
842
843 CalcDimension value;
844 bool ignoreBlank = false;
845 if (!ParseJsDimensionVp(info[0], value) || info[0]->IsNull() || info[0]->IsUndefined() ||
846 LessNotEqual(value.Value(), 0.0)) {
847 value.SetValue(0.0);
848 }
849 if (info.Length() > 1 && info[1]->IsBoolean()) {
850 ignoreBlank = info[1]->ToBoolean();
851 }
852 SwiperModel::GetInstance()->SetNextMargin(value, ignoreBlank);
853 }
854
855 void JSSwiper::SetDisplayMode(int32_t index)
856 {
857 if (index < 0 || index >= static_cast<int32_t>(DISPLAY_MODE.size())) {
858 return;
859 }
860
861 SwiperModel::GetInstance()->SetDisplayMode(DISPLAY_MODE[index]);
862 }
863
864 void JSSwiper::SetCachedCount(const JSCallbackInfo& info)
865 {
866 if (info.Length() < 1) {
867 return;
868 }
869
870 int32_t cachedCount = DEFAULT_CACHED_COUNT;
871 if (!info[0]->IsUndefined() && info[0]->IsNumber()) {
872 cachedCount = info[0]->ToNumber<int32_t>();
873 if (cachedCount < 0) {
874 cachedCount = DEFAULT_CACHED_COUNT;
875 }
876 }
877 SwiperModel::GetInstance()->SetCachedCount(cachedCount);
878 }
879
880 void JSSwiper::SetCurve(const JSCallbackInfo& info)
881 {
882 RefPtr<Curve> curve = DEFAULT_CURVE;
883 if (info[0]->IsString()) {
884 curve = CreateCurve(info[0]->ToString(), false);
885 if (!curve) {
886 curve = DEFAULT_CURVE;
887 }
888 } else if (info[0]->IsObject()) {
889 auto object = JSRef<JSObject>::Cast(info[0]);
890 std::function<float(float)> customCallBack = nullptr;
891 JSRef<JSVal> onCallBack = object->GetProperty("__curveCustomFunc");
892 if (onCallBack->IsFunction()) {
893 RefPtr<JsFunction> jsFuncCallBack =
894 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCallBack));
895 customCallBack = [func = std::move(jsFuncCallBack), id = Container::CurrentId()](float time) -> float {
896 ContainerScope scope(id);
897 JSRef<JSVal> params[1];
898 params[0] = JSRef<JSVal>::Make(ToJSValue(time));
899 auto result = func->ExecuteJS(1, params);
900 auto resultValue = result->IsNumber() ? result->ToNumber<float>() : 1.0f;
901 return resultValue;
902 };
903 }
904 auto jsCurveString = object->GetProperty("__curveString");
905 if (jsCurveString->IsString()) {
906 auto aniTimFunc = jsCurveString->ToString();
907 if (aniTimFunc == DOM_ANIMATION_TIMING_FUNCTION_CUSTOM && customCallBack) {
908 curve = CreateCurve(customCallBack);
909 } else if (aniTimFunc != DOM_ANIMATION_TIMING_FUNCTION_CUSTOM) {
910 curve = CreateCurve(aniTimFunc);
911 }
912 }
913 }
914 SwiperModel::GetInstance()->SetCurve(curve);
915 }
916
917 void JSSwiper::SetOnChange(const JSCallbackInfo& info)
918 {
919 if (!info[0]->IsFunction()) {
920 return;
921 }
922
923 auto changeHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
924 JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
925 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
926 auto onChange = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler), node = targetNode](
927 const BaseEventInfo* info) {
928 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
929 const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
930 if (!swiperInfo) {
931 TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onChange callback execute failed.");
932 return;
933 }
934 ACE_SCORING_EVENT("Swiper.OnChange");
935 PipelineContext::SetCallBackNode(node);
936 func->Execute(*swiperInfo);
937 };
938
939 SwiperModel::GetInstance()->SetOnChange(std::move(onChange));
940 }
941
942 void JSSwiper::SetOnAnimationStart(const JSCallbackInfo& info)
943 {
944 if (!info[0]->IsFunction()) {
945 return;
946 }
947
948 if (Container::IsCurrentUseNewPipeline()) {
949 auto animationStartHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
950 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
951 auto onAnimationStart = [executionContext = info.GetExecutionContext(), func = std::move(animationStartHandler),
952 node = targetNode](
953 int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) {
954 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
955 ACE_SCORING_EVENT("Swiper.onAnimationStart");
956 PipelineContext::SetCallBackNode(node);
957 func->Execute(index, targetIndex, info);
958 };
959
960 SwiperModel::GetInstance()->SetOnAnimationStart(std::move(onAnimationStart));
961 return;
962 }
963
964 auto animationStartHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
965 JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
966 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
967 auto onAnimationStart = [executionContext = info.GetExecutionContext(), func = std::move(animationStartHandler),
968 node = targetNode](const BaseEventInfo* info) {
969 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
970 const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
971 if (!swiperInfo) {
972 TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onAnimationStart callback execute failed.");
973 return;
974 }
975 ACE_SCORING_EVENT("Swiper.onAnimationStart");
976 PipelineContext::SetCallBackNode(node);
977 func->Execute(*swiperInfo);
978 };
979
980 SwiperModel::GetInstance()->SetOnAnimationStart(std::move(onAnimationStart));
981 }
982
983 void JSSwiper::SetOnAnimationEnd(const JSCallbackInfo& info)
984 {
985 if (!info[0]->IsFunction()) {
986 return;
987 }
988
989 if (Container::IsCurrentUseNewPipeline()) {
990 auto animationEndHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
991 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
992 auto onAnimationEnd = [executionContext = info.GetExecutionContext(), func = std::move(animationEndHandler),
993 node = targetNode](int32_t index, const AnimationCallbackInfo& info) {
994 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
995 ACE_SCORING_EVENT("Swiper.onAnimationEnd");
996 PipelineContext::SetCallBackNode(node);
997 func->Execute(index, info);
998 };
999
1000 SwiperModel::GetInstance()->SetOnAnimationEnd(std::move(onAnimationEnd));
1001 return;
1002 }
1003
1004 auto animationEndHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
1005 JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
1006 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1007 auto onAnimationEnd = [executionContext = info.GetExecutionContext(), func = std::move(animationEndHandler),
1008 node = targetNode](const BaseEventInfo* info) {
1009 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1010 const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
1011 if (!swiperInfo) {
1012 TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onAnimationEnd callback execute failed.");
1013 return;
1014 }
1015 ACE_SCORING_EVENT("Swiper.onAnimationEnd");
1016 PipelineContext::SetCallBackNode(node);
1017 func->Execute(*swiperInfo);
1018 };
1019
1020 SwiperModel::GetInstance()->SetOnAnimationEnd(std::move(onAnimationEnd));
1021 }
1022
1023 void JSSwiper::SetOnGestureSwipe(const JSCallbackInfo& info)
1024 {
1025 if (!info[0]->IsFunction()) {
1026 return;
1027 }
1028
1029 auto gestureSwipeHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1030 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1031 auto onGestureSwipe = [executionContext = info.GetExecutionContext(), func = std::move(gestureSwipeHandler),
1032 node = targetNode](int32_t index, const AnimationCallbackInfo& info) {
1033 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
1034 ACE_SCORING_EVENT("Swiper.onGestureSwipe");
1035 PipelineContext::SetCallBackNode(node);
1036 func->Execute(index, info);
1037 };
1038
1039 SwiperModel::GetInstance()->SetOnGestureSwipe(std::move(onGestureSwipe));
1040 }
1041
1042 void JSSwiper::SetOnClick(const JSCallbackInfo& info)
1043 {
1044 if (Container::IsCurrentUseNewPipeline()) {
1045 JSInteractableView::JsOnClick(info);
1046 return;
1047 }
1048
1049 if (!info[0]->IsFunction()) {
1050 return;
1051 }
1052
1053 RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
1054 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1055 auto onClick = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), node = targetNode](
1056 const BaseEventInfo* info, const RefPtr<V2::InspectorFunctionImpl>& impl) {
1057 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1058 const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
1059 if (!clickInfo) {
1060 TAG_LOGW(AceLogTag::ACE_SWIPER, "Swiper onClick callback execute failed.");
1061 return;
1062 }
1063 auto newInfo = *clickInfo;
1064 if (impl) {
1065 impl->UpdateEventInfo(newInfo);
1066 }
1067 ACE_SCORING_EVENT("onClick");
1068 PipelineContext::SetCallBackNode(node);
1069 func->Execute(newInfo);
1070 };
1071
1072 SwiperModel::GetInstance()->SetOnClick(onClick);
1073 }
1074
1075 void JSSwiper::SetWidth(const JSCallbackInfo& info)
1076 {
1077 if (info.Length() < 1) {
1078 return;
1079 }
1080
1081 SetWidth(info[0]);
1082 }
1083
1084 void JSSwiper::SetWidth(const JSRef<JSVal>& jsValue)
1085 {
1086 if (Container::IsCurrentUseNewPipeline()) {
1087 JSViewAbstract::JsWidth(jsValue);
1088 return;
1089 }
1090
1091 JSViewAbstract::JsWidth(jsValue);
1092 SwiperModel::GetInstance()->SetMainSwiperSizeWidth();
1093 }
1094
1095 void JSSwiper::SetHeight(const JSRef<JSVal>& jsValue)
1096 {
1097 if (Container::IsCurrentUseNewPipeline()) {
1098 JSViewAbstract::JsHeight(jsValue);
1099 return;
1100 }
1101
1102 JSViewAbstract::JsHeight(jsValue);
1103 SwiperModel::GetInstance()->SetMainSwiperSizeHeight();
1104 }
1105
1106 void JSSwiper::SetHeight(const JSCallbackInfo& info)
1107 {
1108 if (info.Length() < 1) {
1109 return;
1110 }
1111
1112 SetHeight(info[0]);
1113 }
1114
1115 void JSSwiper::SetSize(const JSCallbackInfo& info)
1116 {
1117 if (info.Length() < 1) {
1118 return;
1119 }
1120
1121 if (!info[0]->IsObject()) {
1122 return;
1123 }
1124
1125 JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
1126 SetWidth(sizeObj->GetProperty("width"));
1127 SetHeight(sizeObj->GetProperty("height"));
1128 }
1129
1130 void JSSwiperController::JSBind(BindingTarget globalObj)
1131 {
1132 JSClass<JSSwiperController>::Declare("SwiperController");
1133 JSClass<JSSwiperController>::CustomMethod("swipeTo", &JSSwiperController::SwipeTo);
1134 JSClass<JSSwiperController>::CustomMethod("showNext", &JSSwiperController::ShowNext);
1135 JSClass<JSSwiperController>::CustomMethod("showPrevious", &JSSwiperController::ShowPrevious);
1136 JSClass<JSSwiperController>::CustomMethod("changeIndex", &JSSwiperController::ChangeIndex);
1137 JSClass<JSSwiperController>::CustomMethod("finishAnimation", &JSSwiperController::FinishAnimation);
1138 JSClass<JSSwiperController>::CustomMethod("preloadItems", &JSSwiperController::PreloadItems);
1139 JSClass<JSSwiperController>::Bind(globalObj, JSSwiperController::Constructor, JSSwiperController::Destructor);
1140 }
1141
1142 void JSSwiperController::Constructor(const JSCallbackInfo& args)
1143 {
1144 auto scroller = Referenced::MakeRefPtr<JSSwiperController>();
1145 scroller->IncRefCount();
1146 args.SetReturnValue(Referenced::RawPtr(scroller));
1147 }
1148
1149 void JSSwiperController::Destructor(JSSwiperController* scroller)
1150 {
1151 if (scroller != nullptr) {
1152 scroller->DecRefCount();
1153 }
1154 }
1155
1156 void JSSwiperController::ChangeIndex(const JSCallbackInfo& args)
1157 {
1158 if (!controller_) {
1159 return;
1160 }
1161 if (args.Length() < 1 || !args[0]->IsNumber()) {
1162 return;
1163 }
1164 int32_t index = -1;
1165 bool useAnimation = false;
1166 if (args.Length() > 1 && args[1]->IsBoolean()) {
1167 useAnimation = args[1]->ToBoolean();
1168 }
1169 index = args[0]->ToNumber<int32_t>();
1170 controller_->ChangeIndex(index, useAnimation);
1171 }
1172
1173 void JSSwiperController::FinishAnimation(const JSCallbackInfo& args)
1174 {
1175 ContainerScope scope(instanceId_);
1176 if (!controller_) {
1177 return;
1178 }
1179
1180 if (args.Length() > 0 && args[0]->IsFunction()) {
1181 RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
1182 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1183 auto onFinish = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1184 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1185 ACE_SCORING_EVENT("Swiper.finishAnimation");
1186 PipelineContext::SetCallBackNode(node);
1187 TAG_LOGD(AceLogTag::ACE_SWIPER, "SwiperController finishAnimation callback execute.");
1188 func->Execute();
1189 };
1190
1191 controller_->SetFinishCallback(onFinish);
1192 controller_->FinishAnimation();
1193 return;
1194 }
1195
1196 controller_->FinishAnimation();
1197 }
1198
1199 void JSSwiperController::PreloadItems(const JSCallbackInfo& args)
1200 {
1201 ContainerScope scope(instanceId_);
1202 if (!controller_) {
1203 return;
1204 }
1205
1206 if (args.Length() != 2 || !args[0]->IsArray() || !args[1]->IsFunction()) {
1207 return;
1208 }
1209
1210 auto indexArray = JSRef<JSArray>::Cast(args[0]);
1211 size_t size = indexArray->Length();
1212 std::set<int32_t> indexSet;
1213 for (size_t i = 0; i < size; i++) {
1214 int32_t index = -1;
1215 JSViewAbstract::ParseJsInt32(indexArray->GetValueAt(i), index);
1216 indexSet.emplace(index);
1217 }
1218
1219 RefPtr<JsSwiperFunction> jsFunc = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(args[1]));
1220 auto onPreloadFinish =
1221 [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](int32_t errorCode, std::string message) {
1222 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1223 ACE_SCORING_EVENT("Swiper.preloadItems");
1224 TAG_LOGI(AceLogTag::ACE_SWIPER, "SwiperController preloadItems callback execute.");
1225 func->Execute(errorCode);
1226 };
1227
1228 controller_->SetPreloadFinishCallback(onPreloadFinish);
1229 controller_->PreloadItems(indexSet);
1230 }
1231
1232 void JSSwiper::SetNestedScroll(const JSCallbackInfo& args)
1233 {
1234 // default value
1235 NestedScrollOptions nestedOpt = {
1236 .forward = NestedScrollMode::SELF_ONLY,
1237 .backward = NestedScrollMode::SELF_ONLY,
1238 };
1239 if (args.Length() < 1 || !args[0]->IsNumber()) {
1240 SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1241 return;
1242 }
1243 int32_t value = -1;
1244 JSViewAbstract::ParseJsInt32(args[0], value);
1245 auto mode = static_cast<NestedScrollMode>(value);
1246 if (mode < NestedScrollMode::SELF_ONLY || mode > NestedScrollMode::SELF_FIRST) {
1247 SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1248 return;
1249 }
1250 nestedOpt.forward = mode;
1251 nestedOpt.backward = mode;
1252 SwiperModel::GetInstance()->SetNestedScroll(nestedOpt);
1253 args.ReturnSelf();
1254 }
1255
1256 void JSSwiper::SetCustomContentTransition(const JSCallbackInfo& info)
1257 {
1258 if (info.Length() < 1 || !info[0]->IsObject()) {
1259 return;
1260 }
1261
1262 SwiperContentAnimatedTransition transitionInfo;
1263 auto transitionObj = JSRef<JSObject>::Cast(info[0]);
1264 JSRef<JSVal> timeoutProperty = transitionObj->GetProperty("timeout");
1265 if (timeoutProperty->IsNumber()) {
1266 auto timeout = timeoutProperty->ToNumber<int32_t>();
1267 transitionInfo.timeout = timeout < 0 ? DEFAULT_CUSTOM_ANIMATION_TIMEOUT : timeout;
1268 } else {
1269 transitionInfo.timeout = DEFAULT_CUSTOM_ANIMATION_TIMEOUT;
1270 }
1271
1272 JSRef<JSVal> transition = transitionObj->GetProperty("transition");
1273 if (transition->IsFunction()) {
1274 auto jsOnTransition = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(transition));
1275 auto onTransition = [execCtx = info.GetExecutionContext(), func = std::move(jsOnTransition)](
1276 const RefPtr<SwiperContentTransitionProxy>& proxy) {
1277 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1278 ACE_SCORING_EVENT("Swiper.customContentTransition");
1279 func->Execute(proxy);
1280 };
1281 transitionInfo.transition = std::move(onTransition);
1282 }
1283 SwiperModel::GetInstance()->SetCustomContentTransition(transitionInfo);
1284 }
1285
1286 void JSSwiper::SetOnContentDidScroll(const JSCallbackInfo& info)
1287 {
1288 if (info.Length() < 1 || !info[0]->IsFunction()) {
1289 return;
1290 }
1291
1292 auto contentDidScrollHandler = AceType::MakeRefPtr<JsSwiperFunction>(JSRef<JSFunc>::Cast(info[0]));
1293 auto onContentDidScroll = [execCtx = info.GetExecutionContext(),
1294 func = std::move(contentDidScrollHandler)](
1295 int32_t selectedIndex, int32_t index, float position, float mainAxisLength) {
1296 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1297 ACE_SCORING_EVENT("Swiper.onContentDidScroll");
1298 func->Execute(selectedIndex, index, position, mainAxisLength);
1299 };
1300 SwiperModel::GetInstance()->SetOnContentDidScroll(std::move(onContentDidScroll));
1301 }
1302 } // namespace OHOS::Ace::Framework
1303