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