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