• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/declarative_frontend/jsview/js_indicator.h"
17 
18 #include "bridge/declarative_frontend/engine/functions/js_event_function.h"
19 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
20 #include "core/components/swiper/swiper_indicator_theme.h"
21 #include "core/components_ng/base/view_stack_processor.h"
22 #include "core/components_ng/pattern/swiper_indicator/indicator_common/indicator_model.h"
23 #include "core/components_ng/pattern/swiper_indicator/indicator_common/indicator_model_ng.h"
24 
25 namespace OHOS::Ace {
26 namespace {
27 constexpr int32_t DEFAULT_INDICATOR_COUNT = 2;
28 } // namespace
29 std::unique_ptr<IndicatorModel> IndicatorModel::instance_ = nullptr;
30 std::mutex IndicatorModel::mutex_;
31 
GetInstance()32 IndicatorModel* IndicatorModel::GetInstance()
33 {
34     if (!instance_) {
35         std::lock_guard<std::mutex> lock(mutex_);
36         if (!instance_) {
37             instance_.reset(new NG::IndicatorModelNG());
38         }
39     }
40     return instance_.get();
41 }
42 
43 } // namespace OHOS::Ace
44 namespace OHOS::Ace::Framework {
45 namespace {
SwiperChangeEventToJSValue(const SwiperChangeEvent & eventInfo)46 JSRef<JSVal> SwiperChangeEventToJSValue(const SwiperChangeEvent& eventInfo)
47 {
48     return JSRef<JSVal>::Make(ToJSValue(eventInfo.GetIndex()));
49 }
50 
51 } // namespace
52 
Create(const JSCallbackInfo & info)53 void JSIndicator::Create(const JSCallbackInfo& info)
54 {
55     auto indicatorController = IndicatorModel::GetInstance()->Create();
56     if (info[0]->IsObject()) {
57         auto* jsController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSIndicatorController>();
58         if (jsController) {
59             jsController->SetInstanceId(Container::CurrentId());
60             auto indicatorNode = AceType::Claim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
61             jsController->SetController(indicatorController, indicatorNode);
62         }
63     }
64 }
65 
JSBind(BindingTarget globalObj)66 void JSIndicator::JSBind(BindingTarget globalObj)
67 {
68     JSClass<JSIndicator>::Declare("IndicatorComponent");
69     MethodOptions opt = MethodOptions::NONE;
70     JSClass<JSIndicator>::StaticMethod("create", &JSIndicator::Create, opt);
71     JSClass<JSIndicator>::StaticMethod("count", &JSIndicator::SetCount, opt);
72     JSClass<JSIndicator>::StaticMethod("loop", &JSIndicator::SetLoop, opt);
73     JSClass<JSIndicator>::StaticMethod("vertical", &JSIndicator::SetVertical, opt);
74     JSClass<JSIndicator>::StaticMethod("style", &JSIndicator::SetStyle, opt);
75     JSClass<JSIndicator>::StaticMethod("initialIndex", &JSIndicator::SetInitialIndex, opt);
76     JSClass<JSIndicator>::StaticMethod("onChange", &JSIndicator::SetOnChange);
77     JSClass<JSIndicator>::InheritAndBind<JSViewAbstract>(globalObj);
78 }
79 
SetCount(const JSCallbackInfo & info)80 void JSIndicator::SetCount(const JSCallbackInfo& info)
81 {
82     if (!info[0]->IsNumber()) {
83         IndicatorModel::GetInstance()->SetCount(DEFAULT_INDICATOR_COUNT);
84         return;
85     }
86 
87     auto count = std::max(DEFAULT_INDICATOR_COUNT, info[0]->ToNumber<int32_t>());
88     IndicatorModel::GetInstance()->SetCount(count);
89 }
90 
SetLoop(const JSCallbackInfo & info)91 void JSIndicator::SetLoop(const JSCallbackInfo& info)
92 {
93     if (!info[0]->IsBoolean()) {
94         IndicatorModel::GetInstance()->SetLoop(true);
95         return;
96     }
97 
98     IndicatorModel::GetInstance()->SetLoop(info[0]->ToBoolean());
99 }
100 
SetVertical(const JSCallbackInfo & info)101 void JSIndicator::SetVertical(const JSCallbackInfo& info)
102 {
103     if (!info[0]->IsBoolean()) {
104         IndicatorModel::GetInstance()->SetDirection(Axis::HORIZONTAL);
105         return;
106     }
107 
108     IndicatorModel::GetInstance()->SetDirection(info[0]->ToBoolean() ? Axis::VERTICAL : Axis::HORIZONTAL);
109 }
110 
GetFontContent(const JSRef<JSVal> & font,bool isSelected,SwiperDigitalParameters & digitalParameters)111 void JSIndicator::GetFontContent(const JSRef<JSVal>& font, bool isSelected, SwiperDigitalParameters& digitalParameters)
112 {
113     JSRef<JSVal> size;
114     JSRef<JSVal> weight;
115     if (font->IsObject()) {
116         JSRef<JSObject> obj = JSRef<JSObject>::Cast(font);
117         size = obj->GetProperty("size");
118         weight = obj->GetProperty("weight");
119     }
120 
121     auto pipelineContext = PipelineBase::GetCurrentContext();
122     CHECK_NULL_VOID(pipelineContext);
123     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
124     CHECK_NULL_VOID(swiperIndicatorTheme);
125     // set font size, unit FP
126     CalcDimension fontSize;
127     RefPtr<ResourceObject> resObj;
128     if (!size->IsUndefined() && !size->IsNull() && ParseJsDimensionFpNG(size, fontSize, resObj)) {
129         if (LessOrEqual(fontSize.Value(), 0.0) || LessOrEqual(size->ToNumber<double>(), 0.0) ||
130             fontSize.Unit() == DimensionUnit::PERCENT) {
131             fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
132         }
133     } else {
134         fontSize = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontSize();
135     }
136     if (SystemProperties::ConfigChangePerform()) {
137         if (isSelected) {
138             digitalParameters.resourceSelectedFontSizeValueObject = resObj;
139         } else {
140             digitalParameters.resourceFontSizeValueObject = resObj;
141         }
142     }
143     if (isSelected) {
144         digitalParameters.selectedFontSize = fontSize;
145     } else {
146         digitalParameters.fontSize = fontSize;
147     }
148 
149     if (!weight->IsNull()) {
150         std::string weightValue;
151         if (weight->IsNumber()) {
152             weightValue = std::to_string(weight->ToNumber<int32_t>());
153         } else {
154             ParseJsString(weight, weightValue);
155         }
156         if (isSelected) {
157             digitalParameters.selectedFontWeight = ConvertStrToFontWeight(weightValue);
158         } else {
159             digitalParameters.fontWeight = ConvertStrToFontWeight(weightValue);
160         }
161     } else {
162         if (isSelected) {
163             digitalParameters.selectedFontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
164         } else {
165             digitalParameters.fontWeight = swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetFontWeight();
166         }
167     }
168 }
169 
ParseIndicatorDimension(const JSRef<JSVal> & value)170 std::optional<Dimension> JSIndicator::ParseIndicatorDimension(const JSRef<JSVal>& value)
171 {
172     std::optional<Dimension> indicatorDimension;
173     if (value->IsUndefined()) {
174         return indicatorDimension;
175     }
176     CalcDimension dimPosition;
177     auto parseOk = ParseJsDimensionVpNG(value, dimPosition);
178     indicatorDimension = parseOk && dimPosition.ConvertToPx() >= 0.0f ? dimPosition : 0.0_vp;
179     return indicatorDimension;
180 }
181 
GetDotIndicatorInfo(const JSRef<JSObject> & obj)182 SwiperParameters JSIndicator::GetDotIndicatorInfo(const JSRef<JSObject>& obj)
183 {
184     JSRef<JSVal> leftValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT_VALUE));
185     JSRef<JSVal> topValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP_VALUE));
186     JSRef<JSVal> rightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT_VALUE));
187     JSRef<JSVal> bottomValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM_VALUE));
188     JSRef<JSVal> startValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::START_VALUE));
189     JSRef<JSVal> endValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::END_VALUE));
190     JSRef<JSVal> itemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_WIDTH_VALUE));
191     JSRef<JSVal> itemHeightValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::ITEM_HEIGHT_VALUE));
192     JSRef<JSVal> selectedItemWidthValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_WIDTH_VALUE));
193     JSRef<JSVal> selectedItemHeightValue =
194         obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_ITEM_HEIGHT_VALUE));
195     auto pipelineContext = PipelineBase::GetCurrentContext();
196     CHECK_NULL_RETURN(pipelineContext, SwiperParameters());
197     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
198     CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperParameters());
199     SwiperParameters swiperParameters;
200     swiperParameters.dimLeft = ParseIndicatorDimension(leftValue);
201     swiperParameters.dimTop = ParseIndicatorDimension(topValue);
202     swiperParameters.dimRight = ParseIndicatorDimension(rightValue);
203     swiperParameters.dimBottom = ParseIndicatorDimension(bottomValue);
204     CalcDimension dimStart;
205     CalcDimension dimEnd;
206     std::optional<Dimension> indicatorDimension;
207     swiperParameters.dimStart = ParseLengthMetricsToDimension(startValue, dimStart) ? dimStart : indicatorDimension;
208     swiperParameters.dimEnd = ParseLengthMetricsToDimension(endValue, dimEnd) ? dimEnd : indicatorDimension;
209 
210     CalcDimension dimPosition;
211     RefPtr<ResourceObject> resItemWidthObj;
212     RefPtr<ResourceObject> resItemHeightObj;
213     RefPtr<ResourceObject> resSelectedItemWidthObj;
214     RefPtr<ResourceObject> resSelectedItemHeightObj;
215     bool parseItemWOk = ParseJsDimensionVpNG(itemWidthValue, dimPosition, resItemWidthObj) &&
216         (dimPosition.Unit() != DimensionUnit::PERCENT);
217     auto defaultSize = swiperIndicatorTheme->GetSize();
218     swiperParameters.itemWidth = parseItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
219     bool parseItemHOk = ParseJsDimensionVpNG(itemHeightValue, dimPosition, resItemHeightObj) &&
220         (dimPosition.Unit() != DimensionUnit::PERCENT);
221     swiperParameters.itemHeight = parseItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
222     bool parseSelectedItemWOk = ParseJsDimensionVpNG(selectedItemWidthValue, dimPosition, resSelectedItemWidthObj) &&
223         (dimPosition.Unit() != DimensionUnit::PERCENT);
224     swiperParameters.selectedItemWidth = parseSelectedItemWOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
225     bool parseSelectedItemHOk = ParseJsDimensionVpNG(selectedItemHeightValue, dimPosition, resSelectedItemHeightObj) &&
226         (dimPosition.Unit() != DimensionUnit::PERCENT);
227     swiperParameters.selectedItemHeight = parseSelectedItemHOk && dimPosition > 0.0_vp ? dimPosition : defaultSize;
228     if (SystemProperties::ConfigChangePerform()) {
229         swiperParameters.resourceItemWidthValueObject = resItemWidthObj;
230         swiperParameters.resourceItemHeightValueObject = resItemHeightObj;
231         swiperParameters.resourceSelectedItemWidthValueObject = resSelectedItemWidthObj;
232         swiperParameters.resourceSelectedItemHeightValueObject = resSelectedItemHeightObj;
233     }
234     IndicatorModel::GetInstance()->SetIsIndicatorCustomSize(
235         parseSelectedItemWOk || parseSelectedItemHOk || parseItemWOk || parseItemHOk);
236     SetDotIndicatorInfo(obj, swiperParameters, swiperIndicatorTheme);
237     return swiperParameters;
238 }
SetDotIndicatorInfo(const JSRef<JSObject> & obj,SwiperParameters & swiperParameters,const RefPtr<SwiperIndicatorTheme> & swiperIndicatorTheme)239 void JSIndicator::SetDotIndicatorInfo(const JSRef<JSObject>& obj, SwiperParameters& swiperParameters,
240     const RefPtr<SwiperIndicatorTheme>& swiperIndicatorTheme)
241 {
242     JSRef<JSVal> maskValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MASK_VALUE));
243     JSRef<JSVal> colorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR_VALUE));
244     JSRef<JSVal> selectedColorValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SELECTED_COLOR_VALUE));
245     JSRef<JSVal> maxDisplayCountVal = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::MAX_DISPLAY_COUNT_VALUE));
246     JSRef<JSVal> spaceValue = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::SPACE_VALUE));
247     if (maskValue->IsBoolean()) {
248         auto mask = maskValue->ToBoolean();
249         swiperParameters.maskValue = mask;
250     }
251     Color colorVal;
252     RefPtr<ResourceObject> resColorObj;
253     RefPtr<ResourceObject> resSelectedColorObj;
254     auto parseOk = ParseJsColor(colorValue, colorVal, resColorObj);
255     swiperParameters.colorVal = parseOk ? (swiperParameters.parametersByUser.insert("colorVal"), colorVal)
256         : swiperIndicatorTheme->GetColor();
257     parseOk = ParseJsColor(selectedColorValue, colorVal, resSelectedColorObj);
258     swiperParameters.selectedColorVal = parseOk
259         ? (swiperParameters.parametersByUser.insert("selectedColorVal"), colorVal)
260         : swiperIndicatorTheme->GetSelectedColor();
261     if (SystemProperties::ConfigChangePerform()) {
262         swiperParameters.resourceColorValueObject = resColorObj;
263         swiperParameters.resourceSelectedColorValueObject = resSelectedColorObj;
264     }
265     auto defalutSpace = swiperIndicatorTheme->GetIndicatorDotItemSpace();
266     CalcDimension dimSpace;
267     auto parseSpaceOk = ParseLengthMetricsToDimension(spaceValue, dimSpace) &&
268         (dimSpace.Unit() != DimensionUnit::PERCENT);
269     swiperParameters.dimSpace =  (parseSpaceOk && !(dimSpace < 0.0_vp)) ? dimSpace : defalutSpace;
270     if (maxDisplayCountVal->IsUndefined()) {
271         return;
272     }
273     uint32_t result = 0;
274     auto setMaxDisplayCountVal = ParseJsInteger(maxDisplayCountVal, result);
275     swiperParameters.maxDisplayCountVal = setMaxDisplayCountVal && result > 0 ? result : 0;
276 }
277 
GetDigitIndicatorInfo(const JSRef<JSObject> & obj)278 SwiperDigitalParameters JSIndicator::GetDigitIndicatorInfo(const JSRef<JSObject>& obj)
279 {
280     JSRef<JSVal> dotLeftValue = obj->GetProperty("leftValue");
281     JSRef<JSVal> dotTopValue = obj->GetProperty("topValue");
282     JSRef<JSVal> dotRightValue = obj->GetProperty("rightValue");
283     JSRef<JSVal> dotBottomValue = obj->GetProperty("bottomValue");
284     JSRef<JSVal> fontColorValue = obj->GetProperty("fontColorValue");
285     JSRef<JSVal> selectedFontColorValue = obj->GetProperty("selectedFontColorValue");
286     JSRef<JSVal> digitFontValue = obj->GetProperty("digitFontValue");
287     JSRef<JSVal> selectedDigitFontValue = obj->GetProperty("selectedDigitFontValue");
288     auto pipelineContext = PipelineBase::GetCurrentContext();
289     CHECK_NULL_RETURN(pipelineContext, SwiperDigitalParameters());
290     auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
291     CHECK_NULL_RETURN(swiperIndicatorTheme, SwiperDigitalParameters());
292     SwiperDigitalParameters digitalParameters;
293     digitalParameters.dimLeft = ParseIndicatorDimension(dotLeftValue);
294     digitalParameters.dimTop = ParseIndicatorDimension(dotTopValue);
295     digitalParameters.dimRight = ParseIndicatorDimension(dotRightValue);
296     digitalParameters.dimBottom = ParseIndicatorDimension(dotBottomValue);
297     Color fontColor;
298     RefPtr<ResourceObject> resFontColorObj;
299     RefPtr<ResourceObject> resSelectedFontColorObj;
300     auto parseOk = JSViewAbstract::ParseJsColor(fontColorValue, fontColor, resFontColorObj);
301     digitalParameters.fontColor =
302         parseOk ? (digitalParameters.parametersByUser.insert("fontColor"), fontColor)
303         : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
304     parseOk = JSViewAbstract::ParseJsColor(selectedFontColorValue, fontColor, resSelectedFontColorObj);
305     digitalParameters.selectedFontColor =
306         parseOk ? (digitalParameters.parametersByUser.insert("selectedFontColor"), fontColor)
307         : swiperIndicatorTheme->GetDigitalIndicatorTextStyle().GetTextColor();
308     if (SystemProperties::ConfigChangePerform()) {
309         digitalParameters.resourceFontColorValueObject = resFontColorObj;
310         digitalParameters.resourceSelectedFontColorValueObject = resSelectedFontColorObj;
311     }
312     if (!digitFontValue->IsNull() && digitFontValue->IsObject()) {
313         GetFontContent(digitFontValue, false, digitalParameters);
314     }
315     if (!selectedDigitFontValue->IsNull() && selectedDigitFontValue->IsObject()) {
316         GetFontContent(selectedDigitFontValue, true, digitalParameters);
317     }
318     return digitalParameters;
319 }
320 
SetStyle(const JSCallbackInfo & info)321 void JSIndicator::SetStyle(const JSCallbackInfo& info)
322 {
323     if (info[0]->IsObject()) {
324         auto obj = JSRef<JSObject>::Cast(info[0]);
325 
326         JSRef<JSVal> typeParam = obj->GetProperty("type");
327         if (typeParam->IsString()) {
328             auto type = typeParam->ToString();
329             if (type == "DigitIndicator") {
330                 SwiperDigitalParameters digitalParameters = GetDigitIndicatorInfo(obj);
331                 IndicatorModel::GetInstance()->SetDigitIndicatorStyle(digitalParameters);
332                 IndicatorModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DIGIT);
333             } else {
334                 SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
335                 IndicatorModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
336                 IndicatorModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
337             }
338         } else {
339             SwiperParameters swiperParameters = GetDotIndicatorInfo(obj);
340             IndicatorModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
341             IndicatorModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
342         }
343     } else {
344         SwiperParameters swiperParameters = GetDotIndicatorInfo(JSRef<JSObject>::New());
345         IndicatorModel::GetInstance()->SetDotIndicatorStyle(swiperParameters);
346         IndicatorModel::GetInstance()->SetIndicatorType(SwiperIndicatorType::DOT);
347     }
348 }
349 
SetOnChange(const JSCallbackInfo & info)350 void JSIndicator::SetOnChange(const JSCallbackInfo& info)
351 {
352     if (!info[0]->IsFunction()) {
353         return;
354     }
355     auto changeHandler = AceType::MakeRefPtr<JsEventFunction<SwiperChangeEvent, 1>>(
356         JSRef<JSFunc>::Cast(info[0]), SwiperChangeEventToJSValue);
357     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
358     auto onChange = [executionContext = info.GetExecutionContext(), func = std::move(changeHandler), node = targetNode](
359                         const BaseEventInfo* info) {
360         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
361         const auto* swiperInfo = TypeInfoHelper::DynamicCast<SwiperChangeEvent>(info);
362         if (!swiperInfo) {
363             return;
364         }
365         PipelineContext::SetCallBackNode(node);
366         func->Execute(*swiperInfo);
367     };
368 
369     IndicatorModel::GetInstance()->SetOnChange(std::move(onChange));
370 }
371 
SetInitialIndex(const JSCallbackInfo & info)372 void JSIndicator::SetInitialIndex(const JSCallbackInfo& info)
373 {
374     if (!info[0]->IsNumber()) {
375         IndicatorModel::GetInstance()->SetInitialIndex(0);
376         return;
377     }
378 
379     auto index = std::max(0, info[0]->ToNumber<int32_t>());
380     IndicatorModel::GetInstance()->SetInitialIndex(index);
381 }
382 
JSBind(BindingTarget globalObj)383 void JSIndicatorController::JSBind(BindingTarget globalObj)
384 {
385     JSClass<JSIndicatorController>::Declare("IndicatorComponentController");
386     JSClass<JSIndicatorController>::CustomMethod("showNext", &JSIndicatorController::ShowNext);
387     JSClass<JSIndicatorController>::CustomMethod("showPrevious", &JSIndicatorController::ShowPrevious);
388     JSClass<JSIndicatorController>::CustomMethod("changeIndex", &JSIndicatorController::ChangeIndex);
389 
390     JSClass<JSIndicatorController>::Bind(
391         globalObj, JSIndicatorController::Constructor, JSIndicatorController::Destructor);
392 }
393 
Constructor(const JSCallbackInfo & args)394 void JSIndicatorController::Constructor(const JSCallbackInfo& args)
395 {
396     auto scroller = Referenced::MakeRefPtr<JSIndicatorController>();
397     scroller->IncRefCount();
398     args.SetReturnValue(Referenced::RawPtr(scroller));
399 }
400 
Destructor(JSIndicatorController * scroller)401 void JSIndicatorController::Destructor(JSIndicatorController* scroller)
402 {
403     if (scroller != nullptr) {
404         scroller->DecRefCount();
405     }
406 }
407 
ChangeIndex(const JSCallbackInfo & args)408 void JSIndicatorController::ChangeIndex(const JSCallbackInfo& args)
409 {
410     auto controller = controller_.Upgrade();
411     CHECK_NULL_VOID(controller);
412     ContainerScope scope(instanceId_);
413     if (!args[0]->IsNumber()) {
414         return;
415     }
416     bool useAnimation = false;
417     if (args.Length() > 1 && args[1]->IsBoolean()) {
418         useAnimation = args[1]->ToBoolean();
419     }
420     auto index = args[0]->ToNumber<int32_t>();
421     controller->ChangeIndex(index, useAnimation);
422 }
423 
424 } // namespace OHOS::Ace::Framework
425