• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bridge/declarative_frontend/jsview/js_textpicker.h"
17 
18 #include <securec.h>
19 
20 #include "base/log/ace_scoring_log.h"
21 #include "bridge/common/utils/engine_helper.h"
22 #include "bridge/declarative_frontend/engine/functions/js_function.h"
23 #include "bridge/declarative_frontend/jsview/js_datepicker.h"
24 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
25 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
26 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
27 #include "bridge/declarative_frontend/jsview/models/textpicker_model_impl.h"
28 #include "bridge/declarative_frontend/view_stack_processor.h"
29 #include "core/components/picker/picker_base_component.h"
30 #include "core/components/picker/picker_theme.h"
31 #include "core/components_ng/pattern/text_picker/textpicker_model.h"
32 #include "core/components_ng/pattern/text_picker/textpicker_model_ng.h"
33 #include "core/pipeline_ng/pipeline_context.h"
34 
35 namespace OHOS::Ace {
36 namespace {
37 const DimensionOffset TEXT_PICKER_OFFSET_DEFAULT_TOP = DimensionOffset(0.0_vp, 40.0_vp);
38 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
39     DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
40     DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
41     DialogAlignment::BOTTOM_END };
42 }
43 
44 std::unique_ptr<TextPickerModel> TextPickerModel::textPickerInstance_ = nullptr;
45 std::unique_ptr<TextPickerDialogModel> TextPickerDialogModel::textPickerDialogInstance_ = nullptr;
46 std::mutex TextPickerModel::mutex_;
47 std::mutex TextPickerDialogModel::mutex_;
48 
GetInstance()49 TextPickerModel* TextPickerModel::GetInstance()
50 {
51     if (!textPickerInstance_) {
52         std::lock_guard<std::mutex> lock(mutex_);
53         if (!textPickerInstance_) {
54 #ifdef NG_BUILD
55             textPickerInstance_.reset(new NG::TextPickerModelNG());
56 #else
57             if (Container::IsCurrentUseNewPipeline()) {
58                 textPickerInstance_.reset(new NG::TextPickerModelNG());
59             } else {
60                 textPickerInstance_.reset(new Framework::TextPickerModelImpl());
61             }
62 #endif
63         }
64     }
65     return textPickerInstance_.get();
66 }
67 
GetInstance()68 TextPickerDialogModel* TextPickerDialogModel::GetInstance()
69 {
70     if (!textPickerDialogInstance_) {
71         std::lock_guard<std::mutex> lock(mutex_);
72         if (!textPickerDialogInstance_) {
73 #ifdef NG_BUILD
74             textPickerDialogInstance_.reset(new NG::TextPickerDialogModelNG());
75 #else
76             if (Container::IsCurrentUseNewPipeline()) {
77                 textPickerDialogInstance_.reset(new NG::TextPickerDialogModelNG());
78             } else {
79                 textPickerDialogInstance_.reset(new Framework::TextPickerDialogModelImpl());
80             }
81 #endif
82         }
83     }
84     return textPickerDialogInstance_.get();
85 }
86 } // namespace OHOS::Ace
87 
88 namespace OHOS::Ace::Framework {
JSBind(BindingTarget globalObj)89 void JSTextPicker::JSBind(BindingTarget globalObj)
90 {
91     JSClass<JSTextPicker>::Declare("TextPicker");
92     MethodOptions opt = MethodOptions::NONE;
93     JSClass<JSTextPicker>::StaticMethod("create", &JSTextPicker::Create, opt);
94     JSClass<JSTextPicker>::StaticMethod("defaultPickerItemHeight", &JSTextPicker::SetDefaultPickerItemHeight);
95     JSClass<JSTextPicker>::StaticMethod("canLoop", &JSTextPicker::SetCanLoop);
96     JSClass<JSTextPicker>::StaticMethod("disappearTextStyle", &JSTextPicker::SetDisappearTextStyle);
97     JSClass<JSTextPicker>::StaticMethod("textStyle", &JSTextPicker::SetTextStyle);
98     JSClass<JSTextPicker>::StaticMethod("selectedTextStyle", &JSTextPicker::SetSelectedTextStyle);
99     JSClass<JSTextPicker>::StaticMethod("selectedIndex", &JSTextPicker::SetSelectedIndex);
100     JSClass<JSTextPicker>::StaticMethod("onAccept", &JSTextPicker::OnAccept);
101     JSClass<JSTextPicker>::StaticMethod("onCancel", &JSTextPicker::OnCancel);
102     JSClass<JSTextPicker>::StaticMethod("onChange", &JSTextPicker::OnChange);
103     JSClass<JSTextPicker>::StaticMethod("backgroundColor", &JSTextPicker::PickerBackgroundColor);
104     JSClass<JSTextPicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
105     JSClass<JSTextPicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
106     JSClass<JSTextPicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
107     JSClass<JSTextPicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
108     JSClass<JSTextPicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
109     JSClass<JSTextPicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
110     JSClass<JSTextPicker>::InheritAndBind<JSViewAbstract>(globalObj);
111 }
112 
PickerBackgroundColor(const JSCallbackInfo & info)113 void JSTextPicker::PickerBackgroundColor(const JSCallbackInfo& info)
114 {
115     JSViewAbstract::JsBackgroundColor(info);
116 
117     if (info.Length() < 1) {
118         LOGI("The arg(PickerBackgroundColor) is wrong, it is supposed to have at least 1 argument");
119         return;
120     }
121     Color backgroundColor;
122     if (!ParseJsColor(info[0], backgroundColor)) {
123         LOGI("the info[0] is null");
124         return;
125     }
126     TextPickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
127 }
128 
ProcessCascadeOptionDepth(const NG::TextCascadePickerOptions & option)129 size_t JSTextPicker::ProcessCascadeOptionDepth(const NG::TextCascadePickerOptions& option)
130 {
131     size_t depth = 1;
132     if (option.children.size() == 0) {
133         return depth;
134     }
135 
136     for (auto&& pos : option.children) {
137         size_t tmpDep = 1;
138         tmpDep += ProcessCascadeOptionDepth(pos);
139         if (tmpDep > depth) {
140             depth = tmpDep;
141         }
142     }
143     return depth;
144 }
145 
CreateMulti(const RefPtr<PickerTheme> & theme,const std::vector<std::string> & values,const std::vector<uint32_t> & selectedValues,const NG::TextCascadePickerOptionsAttr & attr,const std::vector<NG::TextCascadePickerOptions> & options)146 void JSTextPicker::CreateMulti(const RefPtr<PickerTheme>& theme, const std::vector<std::string>& values,
147     const std::vector<uint32_t>& selectedValues, const NG::TextCascadePickerOptionsAttr& attr,
148     const std::vector<NG::TextCascadePickerOptions>& options)
149 {
150     TextPickerModel::GetInstance()->MultiInit(theme);
151     TextPickerModel::GetInstance()->SetValues(values);
152     TextPickerModel::GetInstance()->SetSelecteds(selectedValues);
153     TextPickerModel::GetInstance()->SetIsCascade(attr.isCascade);
154     TextPickerModel::GetInstance()->SetHasSelectAttr(attr.isHasSelectAttr);
155     TextPickerModel::GetInstance()->SetColumns(options);
156 }
157 
ParseTextPickerValueObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)158 void ParseTextPickerValueObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
159 {
160     CHECK_NULL_VOID(changeEventVal->IsFunction());
161 
162     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
163     auto onValueChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](
164                              const std::vector<std::string>& value) {
165         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
166         ACE_SCORING_EVENT("TextPicker.onValueChange");
167         if (value.size() == 1) {
168             JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(value[0]));
169             func->ExecuteJS(1, &newJSVal);
170         } else {
171             JSRef<JSArray> valueArray = JSRef<JSArray>::New();
172             for (uint32_t i = 0; i < value.size(); i++) {
173                 valueArray->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(value[i])));
174             }
175             JSRef<JSVal> newJSVal = JSRef<JSVal>::Cast(valueArray);
176             func->ExecuteJS(1, &newJSVal);
177         }
178     };
179     TextPickerModel::GetInstance()->SetOnValueChangeEvent(std::move(onValueChange));
180 }
181 
ParseTextPickerSelectedObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)182 void ParseTextPickerSelectedObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
183 {
184     CHECK_NULL_VOID(changeEventVal->IsFunction());
185 
186     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
187     auto onSelectedChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](
188                                 const std::vector<double>& index) {
189         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
190         ACE_SCORING_EVENT("TextPicker.onSelectedChange");
191         if (index.size() == 1) {
192             JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(index[0]));
193             func->ExecuteJS(1, &newJSVal);
194         } else {
195             JSRef<JSArray> indexArray = JSRef<JSArray>::New();
196             for (uint32_t i = 0; i < index.size(); i++) {
197                 indexArray->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(index[i])));
198             }
199             JSRef<JSVal> newJSVal = JSRef<JSVal>::Cast(indexArray);
200             func->ExecuteJS(1, &newJSVal);
201         }
202     };
203     TextPickerModel::GetInstance()->SetOnSelectedChangeEvent(std::move(onSelectedChange));
204 }
205 
Create(const JSCallbackInfo & info)206 void JSTextPicker::Create(const JSCallbackInfo& info)
207 {
208     if (info.Length() >= 1 && info[0]->IsObject()) {
209         auto paramObject = JSRef<JSObject>::Cast(info[0]);
210         ParseTextArrayParam param;
211         NG::TextCascadePickerOptionsAttr optionsAttr;
212         bool isSingleRange = false;
213         bool optionsMultiContentCheckErr = false;
214         bool optionsCascadeContentCheckErr = false;
215         isSingleRange = ProcessSingleRangeValue(paramObject, param);
216         if (!isSingleRange) {
217             if (!JSTextPickerParser::ParseMultiTextArray(paramObject, param)) {
218                 param.options.clear();
219                 optionsMultiContentCheckErr = true;
220             }
221             if (optionsMultiContentCheckErr) {
222                 optionsCascadeContentCheckErr =
223                     !ProcessCascadeOptions(paramObject, param.options, param.selecteds, param.values, optionsAttr);
224             }
225         }
226         if (!isSingleRange && optionsMultiContentCheckErr && optionsCascadeContentCheckErr) {
227             LOGE("parse range all type error.");
228             param.result.clear();
229             param.options.clear();
230             return;
231         }
232         auto theme = GetTheme<PickerTheme>();
233         if (!theme) {
234             LOGE("PickerText Theme is null");
235             return;
236         }
237         if (!param.result.empty()) {
238             TextPickerModel::GetInstance()->Create(theme, param.kind);
239             TextPickerModel::GetInstance()->SetRange(param.result);
240             TextPickerModel::GetInstance()->SetSelected(param.selected);
241             TextPickerModel::GetInstance()->SetValue(param.value);
242         } else {
243             CreateMulti(theme, param.values, param.selecteds, optionsAttr, param.options);
244         }
245         TextPickerModel::GetInstance()->SetDefaultAttributes(theme);
246         JSInteractableView::SetFocusable(true);
247         JSInteractableView::SetFocusNode(true);
248         if (param.valueChangeEventVal->IsFunction()) {
249             ParseTextPickerValueObject(info, param.valueChangeEventVal);
250         }
251         if (param.selectedChangeEventVal->IsFunction()) {
252             ParseTextPickerSelectedObject(info, param.selectedChangeEventVal);
253         }
254     }
255 }
256 
ProcessSingleRangeValue(const JSRef<JSObject> & paramObjec,ParseTextArrayParam & param)257 bool JSTextPicker::ProcessSingleRangeValue(const JSRef<JSObject>& paramObjec, ParseTextArrayParam& param)
258 {
259     bool ret = true;
260     auto getRange = paramObjec->GetProperty("range");
261     if (getRange->IsNull() || getRange->IsUndefined()) {
262         return ret;
263     }
264     if (!JSTextPickerParser::ParseTextArray(paramObjec, param)) {
265         if (!JSTextPickerParser::ParseIconTextArray(paramObjec, param.result, param.kind, param.selected)) {
266             LOGI("parse range error.");
267             param.result.clear();
268             ret = false;
269         }
270     }
271     return ret;
272 }
273 
ProcessCascadeOptions(const JSRef<JSObject> & paramObject,std::vector<NG::TextCascadePickerOptions> & options,std::vector<uint32_t> & selectedValues,std::vector<std::string> & values,NG::TextCascadePickerOptionsAttr & attr)274 bool JSTextPicker::ProcessCascadeOptions(const JSRef<JSObject>& paramObject,
275     std::vector<NG::TextCascadePickerOptions>& options, std::vector<uint32_t>& selectedValues,
276     std::vector<std::string>& values, NG::TextCascadePickerOptionsAttr& attr)
277 {
278     auto getRange = paramObject->GetProperty("range");
279     if (getRange->IsNull() || getRange->IsUndefined()) {
280         options.clear();
281         LOGE("parse cascade Options error.");
282         return false;
283     }
284     if (!JSTextPickerParser::ParseCascadeTextArray(paramObject, selectedValues, values, attr)) {
285         LOGE("parse cascade text error.");
286         options.clear();
287         return false;
288     } else {
289         JSTextPickerParser::GenerateCascadeOptions(getRange, options);
290         uint32_t maxCount = options.empty() ? 0 : 1;
291         for (size_t i = 0; i < options.size(); i++) {
292             size_t tmp = ProcessCascadeOptionDepth(options[i]);
293             if (tmp > maxCount) {
294                 maxCount = tmp;
295             }
296         }
297         if (selectedValues.size() < maxCount) {
298             auto differ = maxCount - selectedValues.size();
299             for (uint32_t i = 0; i < differ; i++) {
300                 selectedValues.emplace_back(0);
301             }
302         }
303         if (values.size() < maxCount) {
304             auto differ = maxCount - values.size();
305             for (uint32_t i = 0; i < differ; i++) {
306                 values.emplace_back("");
307             }
308         }
309         attr.isCascade = true;
310         TextPickerModel::GetInstance()->SetMaxCount(maxCount);
311     }
312     return true;
313 }
314 
GenerateCascadeOptionsInternal(const JSRef<JSObject> & jsObj,std::vector<NG::TextCascadePickerOptions> & options)315 bool JSTextPickerParser::GenerateCascadeOptionsInternal(
316     const JSRef<JSObject>& jsObj, std::vector<NG::TextCascadePickerOptions>& options)
317 {
318     NG::TextCascadePickerOptions option;
319     auto text = jsObj->GetProperty("text");
320     std::string textStr = "";
321     if (ParseJsString(text, textStr)) {
322         option.rangeResult.emplace_back(textStr);
323     } else {
324         return false;
325     }
326 
327     auto children = jsObj->GetProperty("children");
328     if (children->IsArray()) {
329         JSRef<JSArray> arrayChildren = JSRef<JSArray>::Cast(children);
330         if (arrayChildren->Length() > 0) {
331             if (!GenerateCascadeOptions(arrayChildren, option.children)) {
332                 return false;
333             }
334         }
335     }
336     options.emplace_back(option);
337     return true;
338 }
339 
GenerateCascadeOptions(const JSRef<JSArray> & array,std::vector<NG::TextCascadePickerOptions> & options)340 bool JSTextPickerParser::GenerateCascadeOptions(
341     const JSRef<JSArray>& array, std::vector<NG::TextCascadePickerOptions>& options)
342 {
343     for (size_t i = 0; i < array->Length(); i++) {
344         if (array->GetValueAt(i)->IsObject()) {
345             auto jsObj = JSRef<JSObject>::Cast(array->GetValueAt(i));
346             if (!GenerateCascadeOptionsInternal(jsObj, options)) {
347                 return false;
348             }
349         } else {
350             options.clear();
351             return false;
352         }
353     }
354     return true;
355 }
356 
ParseMultiTextArrayRangeInternal(const JSRef<JSVal> & value,std::vector<NG::TextCascadePickerOptions> & options)357 bool JSTextPickerParser::ParseMultiTextArrayRangeInternal(
358     const JSRef<JSVal>& value, std::vector<NG::TextCascadePickerOptions>& options)
359 {
360     if (value->IsArray()) {
361         NG::TextCascadePickerOptions option;
362         if (!ParseJsStrArray(value, option.rangeResult)) {
363             LOGI("parse str array error.");
364             return false;
365         } else {
366             options.emplace_back(option);
367         }
368     } else {
369         return false;
370     }
371     return true;
372 }
373 
ParseMultiTextArrayRange(const JSRef<JSArray> & jsRangeValue,std::vector<NG::TextCascadePickerOptions> & options)374 bool JSTextPickerParser::ParseMultiTextArrayRange(
375     const JSRef<JSArray>& jsRangeValue, std::vector<NG::TextCascadePickerOptions>& options)
376 {
377     options.clear();
378     if (jsRangeValue->Length() > 0) {
379         for (size_t i = 0; i < jsRangeValue->Length(); i++) {
380             JSRef<JSVal> value = jsRangeValue->GetValueAt(i);
381             if (!ParseMultiTextArrayRangeInternal(value, options)) {
382                 return false;
383             }
384         }
385     } else {
386         return false;
387     }
388     return true;
389 }
390 
ParseMultiTextArraySelectInternal(const std::vector<NG::TextCascadePickerOptions> & options,const std::vector<std::string> & values,std::vector<uint32_t> & selectedValues)391 void JSTextPickerParser::ParseMultiTextArraySelectInternal(const std::vector<NG::TextCascadePickerOptions>& options,
392     const std::vector<std::string>& values, std::vector<uint32_t>& selectedValues)
393 {
394     uint32_t selectedValue = 0;
395     for (uint32_t i = 0; i < options.size(); i++) {
396         if (i > values.size() - 1 || values[i].empty()) {
397             selectedValues.emplace_back(0);
398             continue;
399         }
400 
401         auto valueIterator = std::find(options[i].rangeResult.begin(), options[i].rangeResult.end(), values[i]);
402         if (valueIterator != options[i].rangeResult.end()) {
403             selectedValue = std::distance(options[i].rangeResult.begin(), valueIterator);
404             selectedValues.emplace_back(selectedValue);
405         } else {
406             selectedValues.emplace_back(0);
407         }
408     }
409 }
410 
ParseMultiTextArraySelectArrayInternal(const std::vector<NG::TextCascadePickerOptions> & options,std::vector<uint32_t> & selectedValues)411 void JSTextPickerParser::ParseMultiTextArraySelectArrayInternal(
412     const std::vector<NG::TextCascadePickerOptions>& options, std::vector<uint32_t>& selectedValues)
413 {
414     for (uint32_t i = 0; i < options.size(); i++) {
415         if (i > selectedValues.size() - 1) {
416             selectedValues.emplace_back(0);
417         } else {
418             if (selectedValues[i] >= options[i].rangeResult.size()) {
419                 LOGW("selectedValue is out of range");
420                 selectedValues[i] = 0;
421             }
422         }
423     }
424 }
425 
ParseMultiTextArraySelect(const JsiRef<JsiValue> & jsSelectedValue,ParseTextArrayParam & param)426 bool JSTextPickerParser::ParseMultiTextArraySelect(const JsiRef<JsiValue>& jsSelectedValue, ParseTextArrayParam& param)
427 {
428     if (jsSelectedValue->IsArray()) {
429         if (!ParseJsIntegerArray(jsSelectedValue, param.selecteds)) {
430             LOGE("parse selectedValues array error.");
431             return false;
432         }
433         ParseMultiTextArraySelectArrayInternal(param.options, param.selecteds);
434     } else {
435         uint32_t selectedValue = 0;
436         if (ParseJsInteger(jsSelectedValue, selectedValue)) {
437             if (param.options.size() < 1 || selectedValue >= param.options[0].rangeResult.size()) {
438                 LOGW("selectedValue is out of range");
439                 selectedValue = 0;
440             }
441             param.selecteds.emplace_back(selectedValue);
442             for (uint32_t i = 1; i < param.options.size(); i++) {
443                 param.selecteds.emplace_back(0);
444             }
445         } else {
446             ParseMultiTextArraySelectInternal(param.options, param.values, param.selecteds);
447         }
448     }
449     return true;
450 }
451 
ParseMultiTextArrayValueInternal(const std::vector<NG::TextCascadePickerOptions> & options,std::vector<std::string> & values)452 void JSTextPickerParser::ParseMultiTextArrayValueInternal(
453     const std::vector<NG::TextCascadePickerOptions>& options, std::vector<std::string>& values)
454 {
455     for (uint32_t i = 0; i < options.size(); i++) {
456         if (i > values.size() - 1) {
457             if (options[i].rangeResult.size() > 0) {
458                 values.emplace_back(options[i].rangeResult[0]);
459             } else {
460                 values.emplace_back("");
461             }
462         } else {
463             auto valueIterator = std::find(options[i].rangeResult.begin(), options[i].rangeResult.end(), values[i]);
464             if (valueIterator == options[i].rangeResult.end()) {
465                 values[i] = options[i].rangeResult.front();
466             }
467         }
468     }
469 }
470 
ParseMultiTextArrayValueSingleInternal(const std::vector<NG::TextCascadePickerOptions> & options,const std::string & value,std::vector<std::string> & values)471 void JSTextPickerParser::ParseMultiTextArrayValueSingleInternal(
472     const std::vector<NG::TextCascadePickerOptions>& options, const std::string& value,
473     std::vector<std::string>& values)
474 {
475     if (options.size() > 0) {
476         auto valueIterator = std::find(options[0].rangeResult.begin(), options[0].rangeResult.end(), value);
477         if (valueIterator != options[0].rangeResult.end()) {
478             values.emplace_back(value);
479         } else {
480             values.emplace_back(options[0].rangeResult.front());
481         }
482         for (uint32_t i = 1; i < options.size(); i++) {
483             values.emplace_back(options[i].rangeResult.front());
484         }
485     } else {
486         for (uint32_t i = 0; i < options.size(); i++) {
487             values.emplace_back(options[i].rangeResult.front());
488         }
489     }
490 }
491 
ParseMultiTextArrayValue(const JsiRef<JsiValue> & jsValue,ParseTextArrayParam & param)492 bool JSTextPickerParser::ParseMultiTextArrayValue(const JsiRef<JsiValue>& jsValue, ParseTextArrayParam& param)
493 {
494     if (jsValue->IsArray()) {
495         if (!ParseJsStrArray(jsValue, param.values)) {
496             LOGE("parse value array error.");
497             return false;
498         }
499         ParseMultiTextArrayValueInternal(param.options, param.values);
500     } else {
501         std::string value;
502         if (ParseJsString(jsValue, value)) {
503             ParseMultiTextArrayValueSingleInternal(param.options, value, param.values);
504         } else {
505             for (uint32_t i = 0; i < param.options.size(); i++) {
506                 if (param.options[i].rangeResult.size() > 0) {
507                     param.values.emplace_back(param.options[i].rangeResult.front());
508                 }
509             }
510         }
511     }
512     return true;
513 }
514 
ParseMultiTextArray(const JSRef<JSObject> & paramObject,ParseTextArrayParam & param)515 bool JSTextPickerParser::ParseMultiTextArray(const JSRef<JSObject>& paramObject, ParseTextArrayParam& param)
516 {
517     auto getSelected = paramObject->GetProperty("selected");
518     auto getValue = paramObject->GetProperty("value");
519     auto getRange = paramObject->GetProperty("range");
520     if (getRange->IsNull() || getRange->IsUndefined()) {
521         return false;
522     }
523     JSRef<JSArray> array = JSRef<JSArray>::Cast(getRange);
524     if (!ParseMultiTextArrayRange(array, param.options)) {
525         return false;
526     }
527     if (getValue->IsObject()) {
528         JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(getValue);
529         param.valueChangeEventVal = valueObj->GetProperty("changeEvent");
530         if (param.valueChangeEventVal->IsFunction()) {
531             getValue = valueObj->GetProperty("value");
532         }
533     }
534     if (!ParseMultiTextArrayValue(getValue, param)) {
535         return false;
536     }
537     if (getSelected->IsObject()) {
538         JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(getSelected);
539         param.selectedChangeEventVal = selectedObj->GetProperty("changeEvent");
540         if (param.selectedChangeEventVal->IsFunction()) {
541             getSelected = selectedObj->GetProperty("value");
542         }
543     }
544     if (!ParseMultiTextArraySelect(getSelected, param)) {
545         return false;
546     }
547     return true;
548 }
549 
ParseInternalArray(const JSRef<JSArray> & jsRangeValue,std::vector<uint32_t> & selectedValues,std::vector<std::string> & values,uint32_t index,bool isHasSelectAttr)550 bool JSTextPickerParser::ParseInternalArray(const JSRef<JSArray>& jsRangeValue, std::vector<uint32_t>& selectedValues,
551     std::vector<std::string>& values, uint32_t index, bool isHasSelectAttr)
552 {
553     std::vector<std::string> resultStr;
554     for (size_t i = 0; i < jsRangeValue->Length(); i++) {
555         if (jsRangeValue->GetValueAt(i)->IsObject()) {
556             auto jsObj = JSRef<JSObject>::Cast(jsRangeValue->GetValueAt(i));
557             auto getText = jsObj->GetProperty("text");
558             std::string textStr = "";
559             if (ParseJsString(getText, textStr)) {
560                 resultStr.emplace_back(textStr);
561             } else {
562                 return false;
563             }
564         }
565     }
566     if (index > values.size() - 1) {
567         if (resultStr.size() > 0) {
568             values.emplace_back(resultStr.front());
569         } else {
570             values.emplace_back("");
571         }
572     } else {
573         if (resultStr.size() > 0) {
574             auto valueIterator = std::find(resultStr.begin(), resultStr.end(), values[index]);
575             if (valueIterator == resultStr.end()) {
576                 values[index] = resultStr.front();
577             }
578         } else {
579             values[index] = "";
580         }
581     }
582 
583     if (index > selectedValues.size() - 1) {
584         selectedValues.emplace_back(0);
585     } else {
586         if (selectedValues[index] >= resultStr.size()) {
587             LOGW("selectedValue is out of range");
588             selectedValues[index] = 0;
589         }
590     }
591 
592     if (!isHasSelectAttr && selectedValues[index] == 0 && !values[index].empty()) {
593         auto valueIterator = std::find(resultStr.begin(), resultStr.end(), values[index]);
594         if (valueIterator != resultStr.end()) {
595             selectedValues[index] = std::distance(resultStr.begin(), valueIterator);
596         }
597     }
598     auto jsObj = JSRef<JSObject>::Cast(jsRangeValue->GetValueAt(selectedValues[index]));
599     auto getChildren = jsObj->GetProperty("children");
600     if (getChildren->IsArray()) {
601         ParseInternalArray(getChildren, selectedValues, values, index + 1, isHasSelectAttr);
602     }
603     return true;
604 }
605 
ParseCascadeTextArray(const JSRef<JSObject> & paramObject,std::vector<uint32_t> & selectedValues,std::vector<std::string> & values,NG::TextCascadePickerOptionsAttr & attr)606 bool JSTextPickerParser::ParseCascadeTextArray(const JSRef<JSObject>& paramObject,
607     std::vector<uint32_t>& selectedValues, std::vector<std::string>& values, NG::TextCascadePickerOptionsAttr& attr)
608 {
609     JSRef<JSArray> getRange = paramObject->GetProperty("range");
610     auto getSelected = paramObject->GetProperty("selected");
611     auto getValue = paramObject->GetProperty("value");
612     if (getValue->IsArray()) {
613         if (!ParseJsStrArray(getValue, values)) {
614             LOGE("parse value array error.");
615             return false;
616         }
617     } else {
618         std::string value = "";
619         if (!ParseJsString(getValue, value)) {
620             value = "";
621         }
622         values.emplace_back(value);
623     }
624     if (getSelected->IsArray()) {
625         if (!ParseJsIntegerArray(getSelected, selectedValues)) {
626             LOGE("parse selectedValues array error.");
627             attr.isHasSelectAttr = false;
628             return false;
629         } else {
630             attr.isHasSelectAttr = true;
631         }
632     } else {
633         uint32_t selectValue = 0;
634         if (!ParseJsInteger(getSelected, selectValue)) {
635             selectValue = 0;
636             attr.isHasSelectAttr = false;
637         } else {
638             attr.isHasSelectAttr = true;
639         }
640         selectedValues.emplace_back(selectValue);
641     }
642     return ParseInternalArray(getRange, selectedValues, values, 0, attr.isHasSelectAttr);
643 }
644 
ParseTextArray(const JSRef<JSObject> & paramObject,ParseTextArrayParam & param)645 bool JSTextPickerParser::ParseTextArray(const JSRef<JSObject>& paramObject, ParseTextArrayParam& param)
646 {
647     auto getSelected = paramObject->GetProperty("selected");
648     auto getValue = paramObject->GetProperty("value");
649     JSRef<JSArray> getRange = paramObject->GetProperty("range");
650     std::vector<std::string> getRangeVector;
651     if (getRange->Length() > 0) {
652         if (!ParseJsStrArray(getRange, getRangeVector)) {
653             LOGE("parse str array error.");
654             return false;
655         }
656 
657         param.result.clear();
658         for (const auto& text : getRangeVector) {
659             NG::RangeContent content;
660             content.icon_ = "";
661             content.text_ = text;
662             param.result.emplace_back(content);
663         }
664         param.kind = NG::TEXT;
665         if (getValue->IsObject()) {
666             JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(getValue);
667             param.valueChangeEventVal = valueObj->GetProperty("changeEvent");
668             if (param.valueChangeEventVal->IsFunction()) {
669                 getValue = valueObj->GetProperty("value");
670             }
671         }
672         if (!ParseJsString(getValue, param.value)) {
673             param.value = getRangeVector.front();
674         }
675         if (getSelected->IsObject()) {
676             JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(getSelected);
677             param.selectedChangeEventVal = selectedObj->GetProperty("changeEvent");
678             if (param.selectedChangeEventVal->IsFunction()) {
679                 getSelected = selectedObj->GetProperty("value");
680             }
681         }
682         if (!ParseJsInteger(getSelected, param.selected) && !param.value.empty()) {
683             auto valueIterator = std::find(getRangeVector.begin(), getRangeVector.end(), param.value);
684             if (valueIterator != getRangeVector.end()) {
685                 param.selected = std::distance(getRangeVector.begin(), valueIterator);
686             }
687         }
688         if (param.selected >= getRangeVector.size()) {
689             LOGW("selectedValue is out of range");
690             param.selected = 0;
691         }
692     }
693 
694     return true;
695 }
696 
ParseIconTextArray(const JSRef<JSObject> & paramObject,std::vector<NG::RangeContent> & result,uint32_t & kind,uint32_t & selectedValue)697 bool JSTextPickerParser::ParseIconTextArray(
698     const JSRef<JSObject>& paramObject, std::vector<NG::RangeContent>& result, uint32_t& kind, uint32_t& selectedValue)
699 {
700     auto getSelected = paramObject->GetProperty("selected");
701     auto getRange = paramObject->GetProperty("range");
702     if (!getRange->IsArray()) {
703         LOGE("arg is not array.");
704         return false;
705     }
706     JSRef<JSArray> array = JSRef<JSArray>::Cast(getRange);
707     result.clear();
708     kind = 0;
709     for (size_t i = 0; i < array->Length(); i++) {
710         if (!array->GetValueAt(i)->IsObject()) {
711             continue;
712         }
713         auto jsObj = JSRef<JSObject>::Cast(array->GetValueAt(i));
714         auto rangeIcon = jsObj->GetProperty("icon");
715         auto rangeText = jsObj->GetProperty("text");
716         NG::RangeContent content;
717         std::string icon;
718         std::string text;
719         if (ParseJsMedia(rangeIcon, icon)) {
720             content.icon_ = icon;
721             kind |= NG::ICON;
722         }
723 
724         if (ParseJsString(rangeText, text)) {
725             content.text_ = text;
726             kind |= NG::TEXT;
727         }
728         result.emplace_back(content);
729     }
730 
731     if (kind != NG::ICON && kind != (NG::ICON | NG::TEXT)) {
732         LOGE("kind is wrong.");
733         return false;
734     }
735 
736     if (!ParseJsInteger(getSelected, selectedValue)) {
737         selectedValue = 0;
738     }
739     return true;
740 }
741 
ParseTextStyle(const JSRef<JSObject> & paramObj,NG::PickerTextStyle & textStyle)742 void JSTextPickerParser::ParseTextStyle(const JSRef<JSObject>& paramObj, NG::PickerTextStyle& textStyle)
743 {
744     auto fontColor = paramObj->GetProperty("color");
745     auto fontOptions = paramObj->GetProperty("font");
746 
747     Color textColor;
748     if (ParseJsColor(fontColor, textColor)) {
749         textStyle.textColor = textColor;
750     }
751 
752     if (!fontOptions->IsObject()) {
753         LOGE("fontStyle is not obj.");
754         return;
755     }
756     JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(fontOptions);
757     auto fontSize = fontObj->GetProperty("size");
758     auto fontWeight = fontObj->GetProperty("weight");
759     auto fontFamily = fontObj->GetProperty("family");
760     auto fontStyle = fontObj->GetProperty("style");
761     if (fontSize->IsNull() || fontSize->IsUndefined()) {
762         textStyle.fontSize = Dimension(-1);
763     } else {
764         CalcDimension size;
765         if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) {
766             textStyle.fontSize = Dimension(-1);
767             LOGW("Parse to dimension FP failed.");
768         } else {
769             textStyle.fontSize = size;
770         }
771     }
772 
773     if (!fontWeight->IsNull() && !fontWeight->IsUndefined()) {
774         std::string weight;
775         if (fontWeight->IsNumber()) {
776             weight = std::to_string(fontWeight->ToNumber<int32_t>());
777         } else {
778             ParseJsString(fontWeight, weight);
779         }
780         textStyle.fontWeight = ConvertStrToFontWeight(weight);
781     }
782 
783     if (!fontFamily->IsNull() && !fontFamily->IsUndefined()) {
784         std::vector<std::string> families;
785         if (ParseJsFontFamilies(fontFamily, families)) {
786             textStyle.fontFamily = families;
787         }
788     }
789 
790     if (fontStyle->IsNumber()) {
791         auto style = fontStyle->ToNumber<int32_t>();
792         if (style < 0 || style > 1) {
793             LOGE("Text fontStyle(%d) is invalid value", style);
794             return;
795         }
796         textStyle.fontStyle = static_cast<FontStyle>(style);
797     }
798 }
799 
SetDefaultPickerItemHeight(const JSCallbackInfo & info)800 void JSTextPicker::SetDefaultPickerItemHeight(const JSCallbackInfo& info)
801 {
802     if (info.Length() < 1) {
803         LOGE("The arg is wrong, it is supposed to have atleast 1 argument.");
804         return;
805     }
806     CalcDimension height;
807     if (info[0]->IsNumber() || info[0]->IsString()) {
808         if (!ParseJsDimensionFp(info[0], height)) {
809             return;
810         }
811     }
812     TextPickerModel::GetInstance()->SetDefaultPickerItemHeight(height);
813 }
SetCanLoop(const JSCallbackInfo & info)814 void JSTextPicker::SetCanLoop(const JSCallbackInfo& info)
815 {
816     bool value = true;
817     if (info.Length() != 1 || !info[0]->IsBoolean()) {
818         LOGE("parse canLoop error.");
819     } else {
820         value = info[0]->ToBoolean();
821     }
822 
823     TextPickerModel::GetInstance()->SetCanLoop(value);
824 }
825 
SetDisappearTextStyle(const JSCallbackInfo & info)826 void JSTextPicker::SetDisappearTextStyle(const JSCallbackInfo& info)
827 {
828     auto theme = GetTheme<PickerTheme>();
829     if (!theme) {
830         LOGE("PickerText Theme is null");
831         return;
832     }
833     NG::PickerTextStyle textStyle;
834     if (info.Length() < 1 || !info[0]->IsObject()) {
835         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
836     } else {
837         JSTextPickerParser::ParseTextStyle(info[0], textStyle);
838     }
839     TextPickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
840 }
841 
SetTextStyle(const JSCallbackInfo & info)842 void JSTextPicker::SetTextStyle(const JSCallbackInfo& info)
843 {
844     auto theme = GetTheme<PickerTheme>();
845     if (!theme) {
846         LOGE("PickerText Theme is null");
847         return;
848     }
849     NG::PickerTextStyle textStyle;
850     if (info.Length() < 1 || !info[0]->IsObject()) {
851         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
852     } else {
853         JSTextPickerParser::ParseTextStyle(info[0], textStyle);
854     }
855     TextPickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
856 }
857 
SetSelectedTextStyle(const JSCallbackInfo & info)858 void JSTextPicker::SetSelectedTextStyle(const JSCallbackInfo& info)
859 {
860     auto theme = GetTheme<PickerTheme>();
861     if (!theme) {
862         LOGE("PickerText Theme is null");
863         return;
864     }
865     NG::PickerTextStyle textStyle;
866     if (info.Length() < 1 || !info[0]->IsObject()) {
867         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
868     } else {
869         JSTextPickerParser::ParseTextStyle(info[0], textStyle);
870     }
871     TextPickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
872 }
873 
ProcessCascadeSelected(const std::vector<NG::TextCascadePickerOptions> & options,uint32_t index,std::vector<uint32_t> & selectedValues)874 void JSTextPicker::ProcessCascadeSelected(
875     const std::vector<NG::TextCascadePickerOptions>& options, uint32_t index, std::vector<uint32_t>& selectedValues)
876 {
877     std::vector<std::string> rangeResultValue;
878     for (size_t i = 0; i < options.size(); i++) {
879         rangeResultValue.emplace_back(options[i].rangeResult[0]);
880     }
881 
882     if (index > selectedValues.size() - 1) {
883         selectedValues.emplace_back(0);
884     }
885     if (selectedValues[index] >= rangeResultValue.size()) {
886         LOGW("selectedValue is out of range");
887         selectedValues[index] = 0;
888     }
889     if (selectedValues[index] <= options.size() - 1 && options[selectedValues[index]].children.size() > 0) {
890         ProcessCascadeSelected(options[selectedValues[index]].children, index + 1, selectedValues);
891     }
892 }
893 
SetSelectedInternal(uint32_t count,std::vector<NG::TextCascadePickerOptions> & options,std::vector<uint32_t> & selectedValues)894 void JSTextPicker::SetSelectedInternal(
895     uint32_t count, std::vector<NG::TextCascadePickerOptions>& options, std::vector<uint32_t>& selectedValues)
896 {
897     for (uint32_t i = 0; i < count; i++) {
898         if (i > selectedValues.size() - 1) {
899             selectedValues.emplace_back(0);
900         } else {
901             if (selectedValues[i] >= options[i].rangeResult.size()) {
902                 LOGW("selectedValue is out of range");
903                 selectedValues[i] = 0;
904             }
905         }
906     }
907 }
908 
SetSelectedIndexMultiInternal(uint32_t count,std::vector<NG::TextCascadePickerOptions> & options,std::vector<uint32_t> & selectedValues)909 void JSTextPicker::SetSelectedIndexMultiInternal(
910     uint32_t count, std::vector<NG::TextCascadePickerOptions>& options, std::vector<uint32_t>& selectedValues)
911 {
912     if (!TextPickerModel::GetInstance()->IsCascade()) {
913         SetSelectedInternal(count, options, selectedValues);
914     } else {
915         TextPickerModel::GetInstance()->SetHasSelectAttr(true);
916         ProcessCascadeSelected(options, 0, selectedValues);
917         uint32_t maxCount = TextPickerModel::GetInstance()->GetMaxCount();
918         if (selectedValues.size() < maxCount) {
919             auto differ = maxCount - selectedValues.size();
920             for (uint32_t i = 0; i < differ; i++) {
921                 selectedValues.emplace_back(0);
922             }
923         }
924     }
925 }
926 
SetSelectedIndexSingleInternal(const std::vector<NG::TextCascadePickerOptions> & options,uint32_t count,uint32_t & selectedValue,std::vector<uint32_t> & selectedValues)927 void JSTextPicker::SetSelectedIndexSingleInternal(const std::vector<NG::TextCascadePickerOptions>& options,
928     uint32_t count, uint32_t& selectedValue, std::vector<uint32_t>& selectedValues)
929 {
930     if (options.size() > 0) {
931         if (selectedValue >= options[0].rangeResult.size()) {
932             LOGW("selectedValue is out of range");
933             selectedValue = 0;
934         }
935         selectedValues.emplace_back(selectedValue);
936         for (uint32_t i = 1; i < count; i++) {
937             selectedValues.emplace_back(0);
938         }
939     } else {
940         for (uint32_t i = 0; i < count; i++) {
941             selectedValues.emplace_back(0);
942         }
943     }
944 }
945 
SetSelectedIndexMulti(const JsiRef<JsiValue> & jsSelectedValue)946 void JSTextPicker::SetSelectedIndexMulti(const JsiRef<JsiValue>& jsSelectedValue)
947 {
948     std::vector<uint32_t> selectedValues;
949     std::vector<NG::TextCascadePickerOptions> options;
950     TextPickerModel::GetInstance()->GetMultiOptions(options);
951     auto count =
952         TextPickerModel::GetInstance()->IsCascade() ? TextPickerModel::GetInstance()->GetMaxCount() : options.size();
953     if (jsSelectedValue->IsArray()) {
954         if (!ParseJsIntegerArray(jsSelectedValue, selectedValues)) {
955             LOGE("parse selectedValues array error.");
956             selectedValues.clear();
957             for (uint32_t i = 0; i < count; i++) {
958                 selectedValues.emplace_back(0);
959             }
960             TextPickerModel::GetInstance()->SetSelecteds(selectedValues);
961             TextPickerModel::GetInstance()->SetHasSelectAttr(false);
962             return;
963         }
964         SetSelectedIndexMultiInternal(count, options, selectedValues);
965     } else {
966         uint32_t selectedValue = 0;
967         if (ParseJsInteger(jsSelectedValue, selectedValue)) {
968             TextPickerModel::GetInstance()->SetHasSelectAttr(true);
969             SetSelectedIndexSingleInternal(options, count, selectedValue, selectedValues);
970         } else {
971             selectedValues.clear();
972             TextPickerModel::GetInstance()->SetHasSelectAttr(false);
973             for (uint32_t i = 0; i < count; i++) {
974                 selectedValues.emplace_back(0);
975             }
976         }
977     }
978     TextPickerModel::GetInstance()->SetSelecteds(selectedValues);
979 }
980 
SetSelectedIndexSingle(const JsiRef<JsiValue> & jsSelectedValue)981 void JSTextPicker::SetSelectedIndexSingle(const JsiRef<JsiValue>& jsSelectedValue)
982 {
983     // Single
984     std::vector<NG::RangeContent> rangeResult;
985     TextPickerModel::GetInstance()->GetSingleRange(rangeResult);
986     if (jsSelectedValue->IsArray()) {
987         std::vector<uint32_t> selectedValues;
988         if (!ParseJsIntegerArray(jsSelectedValue, selectedValues)) {
989             LOGE("SetselectedIndex parse selectedValues array error.");
990             uint32_t selectedValue = 0;
991             TextPickerModel::GetInstance()->SetSelected(selectedValue);
992             return;
993         }
994         if (selectedValues.size() > 0) {
995             if (selectedValues[0] >= rangeResult.size()) {
996                 LOGW("selectedValue is out of range");
997                 selectedValues[0] = 0;
998             }
999         } else {
1000             selectedValues.emplace_back(0);
1001         }
1002 
1003         TextPickerModel::GetInstance()->SetSelected(selectedValues[0]);
1004     } else {
1005         uint32_t selectedValue = 0;
1006         if (ParseJsInteger(jsSelectedValue, selectedValue)) {
1007             if (selectedValue >= rangeResult.size()) {
1008                 LOGW("selectedValue is out of range");
1009                 selectedValue = 0;
1010             }
1011         }
1012         TextPickerModel::GetInstance()->SetSelected(selectedValue);
1013     }
1014 }
1015 
SetSelectedIndex(const JSCallbackInfo & info)1016 void JSTextPicker::SetSelectedIndex(const JSCallbackInfo& info)
1017 {
1018     if (info.Length() >= 1) {
1019         auto jsSelectedValue = info[0];
1020         if (jsSelectedValue->IsNull() || jsSelectedValue->IsUndefined()) {
1021             return;
1022         }
1023         if (TextPickerModel::GetInstance()->IsSingle()) {
1024             SetSelectedIndexSingle(jsSelectedValue);
1025         } else {
1026             SetSelectedIndexMulti(jsSelectedValue);
1027         }
1028     }
1029 }
1030 
OnAccept(const JSCallbackInfo & info)1031 void JSTextPicker::OnAccept(const JSCallbackInfo& info) {}
1032 
OnCancel(const JSCallbackInfo & info)1033 void JSTextPicker::OnCancel(const JSCallbackInfo& info) {}
1034 
OnChange(const JSCallbackInfo & info)1035 void JSTextPicker::OnChange(const JSCallbackInfo& info)
1036 {
1037     if (!info[0]->IsFunction()) {
1038         return;
1039     }
1040     auto jsFunc = JSRef<JSFunc>::Cast(info[0]);
1041     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](
1042                         const std::vector<std::string>& value, const std::vector<double>& index) {
1043         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1044         ACE_SCORING_EVENT("TextPicker.onChange");
1045         if (value.size() == 1 && index.size() == 1) {
1046             auto params = ConvertToJSValues(value[0], index[0]);
1047             func->Call(JSRef<JSObject>(), static_cast<int>(params.size()), params.data());
1048         } else {
1049             std::vector<JSRef<JSVal>> result;
1050             JSRef<JSArray> valueArray = JSRef<JSArray>::New();
1051             for (uint32_t i = 0; i < value.size(); i++) {
1052                 valueArray->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(value[i])));
1053             }
1054             JSRef<JSVal> valueJs = JSRef<JSVal>::Cast(valueArray);
1055             result.emplace_back(valueJs);
1056             JSRef<JSArray> selectedArray = JSRef<JSArray>::New();
1057             for (uint32_t i = 0; i < index.size(); i++) {
1058                 selectedArray->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(index[i])));
1059             }
1060             JSRef<JSVal> selectedJs = JSRef<JSVal>::Cast(selectedArray);
1061             result.emplace_back(selectedJs);
1062             func->Call(JSRef<JSObject>(), static_cast<int>(result.size()), result.data());
1063         }
1064     };
1065     TextPickerModel::GetInstance()->SetOnCascadeChange(std::move(onChange));
1066     info.ReturnSelf();
1067 }
1068 
JSBind(BindingTarget globalObj)1069 void JSTextPickerDialog::JSBind(BindingTarget globalObj)
1070 {
1071     JSClass<JSTextPickerDialog>::Declare("TextPickerDialog");
1072     JSClass<JSTextPickerDialog>::StaticMethod("show", &JSTextPickerDialog::Show);
1073 
1074     JSClass<JSTextPickerDialog>::Bind<>(globalObj);
1075 }
1076 
Show(const JSCallbackInfo & info)1077 void JSTextPickerDialog::Show(const JSCallbackInfo& info)
1078 {
1079     auto scopedDelegate = EngineHelper::GetCurrentDelegate();
1080     if (!scopedDelegate) {
1081         // this case usually means there is no foreground container, need to figure out the reason.
1082         LOGE("scopedDelegate is null, please check");
1083         return;
1084     }
1085     if (info.Length() < 1 || !info[0]->IsObject()) {
1086         LOGE("TextPicker create error, info is non-valid");
1087         return;
1088     }
1089 
1090     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1091     std::function<void()> cancelEvent;
1092     std::function<void(const std::string&)> acceptEvent;
1093     std::function<void(const std::string&)> changeEvent;
1094     auto onCancel = paramObject->GetProperty("onCancel");
1095     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1096         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1097         cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)]() {
1098             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1099             ACE_SCORING_EVENT("TextPickerDialog.onCancel");
1100             func->Execute();
1101         };
1102     }
1103     auto onAccept = paramObject->GetProperty("onAccept");
1104     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1105         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1106         acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& info) {
1107             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1108             std::vector<std::string> keys = { "value", "index" };
1109             ACE_SCORING_EVENT("TextPickerDialog.onAccept");
1110             func->Execute(keys, info);
1111         };
1112     }
1113     auto onChange = paramObject->GetProperty("onChange");
1114     if (!onChange->IsUndefined() && onChange->IsFunction()) {
1115         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
1116         changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& info) {
1117             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1118             std::vector<std::string> keys = { "value", "index" };
1119             ACE_SCORING_EVENT("TextPickerDialog.onChange");
1120             func->Execute(keys, info);
1121         };
1122     }
1123     NG::TextPickerSettingData settingData;
1124     TextPickerDialog textPickerDialog;
1125 
1126     auto pickerText = TextPickerDialogModel::GetInstance()->CreateObject();
1127     if (pickerText == nullptr) {
1128         // parse Multi column text
1129         if (!ParseShowData(paramObject, settingData)) {
1130             return;
1131         }
1132     } else {
1133         auto getSelected = paramObject->GetProperty("selected");
1134         auto defaultHeight = paramObject->GetProperty("defaultPickerItemHeight");
1135         auto canLoop = paramObject->GetProperty("canLoop");
1136         JSRef<JSArray> getRange = paramObject->GetProperty("range");
1137         std::vector<std::string> getRangeVector;
1138         if (!JSViewAbstract::ParseJsStrArray(getRange, getRangeVector)) {
1139             LOGE("parse range failed");
1140             return;
1141         }
1142         std::string value = "";
1143         uint32_t selectedValue = 0;
1144         auto getValue = paramObject->GetProperty("value");
1145         if (!JSViewAbstract::ParseJsInteger(getSelected, selectedValue) &&
1146             JSViewAbstract::ParseJsString(getValue, value)) {
1147             auto valueIterator = std::find(getRangeVector.begin(), getRangeVector.end(), value);
1148             if (valueIterator != getRangeVector.end()) {
1149                 selectedValue = std::distance(getRangeVector.begin(), valueIterator);
1150             }
1151         }
1152         if (selectedValue >= getRangeVector.size()) {
1153             LOGW("selectedValue is out of range");
1154             selectedValue = 0;
1155         }
1156         CalcDimension height;
1157         if (defaultHeight->IsNumber() || defaultHeight->IsString()) {
1158             if (!JSViewAbstract::ParseJsDimensionFp(defaultHeight, height)) {
1159                 return;
1160             }
1161         }
1162         if (!defaultHeight->IsEmpty()) {
1163             textPickerDialog.isDefaultHeight = true;
1164         }
1165         textPickerDialog.height = height;
1166         textPickerDialog.selectedValue = selectedValue;
1167         textPickerDialog.getRangeVector = getRangeVector;
1168     }
1169 
1170     // Parse alignment
1171     auto alignmentValue = paramObject->GetProperty("alignment");
1172     if (alignmentValue->IsNumber()) {
1173         auto alignment = alignmentValue->ToNumber<int32_t>();
1174         if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
1175             textPickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
1176         }
1177         if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
1178             alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
1179             alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
1180             textPickerDialog.offset = TEXT_PICKER_OFFSET_DEFAULT_TOP;
1181         }
1182     }
1183 
1184     // Parse offset
1185     auto offsetValue = paramObject->GetProperty("offset");
1186     if (offsetValue->IsObject()) {
1187         auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
1188         CalcDimension dx;
1189         auto dxValue = offsetObj->GetProperty("dx");
1190         JSAlertDialog::ParseJsDimensionVp(dxValue, dx);
1191         CalcDimension dy;
1192         auto dyValue = offsetObj->GetProperty("dy");
1193         JSAlertDialog::ParseJsDimensionVp(dyValue, dy);
1194         textPickerDialog.offset = DimensionOffset(dx, dy);
1195     }
1196 
1197     // Parse maskRect.
1198     auto maskRectValue = paramObject->GetProperty("maskRect");
1199     DimensionRect maskRect;
1200     if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
1201         textPickerDialog.maskRect = maskRect;
1202     }
1203 
1204     TextPickerDialogModel::GetInstance()->SetTextPickerDialogShow(pickerText, settingData, std::move(cancelEvent),
1205         std::move(acceptEvent), std::move(changeEvent), textPickerDialog);
1206 }
1207 
TextPickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogTextEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)1208 void JSTextPickerDialog::TextPickerDialogShow(const JSRef<JSObject>& paramObj,
1209     const std::map<std::string, NG::DialogTextEvent>& dialogEvent,
1210     const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
1211 {
1212     auto container = Container::Current();
1213     if (!container) {
1214         return;
1215     }
1216     auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1217     if (!pipelineContext) {
1218         return;
1219     }
1220 
1221     auto executor = pipelineContext->GetTaskExecutor();
1222     if (!executor) {
1223         return;
1224     }
1225 
1226     auto theme = JSTextPicker::GetTheme<DialogTheme>();
1227     if (!theme) {
1228         LOGE("DialogTheme is null");
1229         return;
1230     }
1231 
1232     NG::TextPickerSettingData settingData;
1233     if (!ParseShowData(paramObj, settingData)) {
1234         return;
1235     }
1236 
1237     DialogProperties properties;
1238     ButtonInfo buttonInfo;
1239     if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
1240         properties.alignment = DialogAlignment::BOTTOM;
1241     } else {
1242         properties.alignment = DialogAlignment::CENTER;
1243     }
1244     properties.customStyle = false;
1245     properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1246 
1247     auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
1248     auto overlayManager = context ? context->GetOverlayManager() : nullptr;
1249     executor->PostTask(
1250         [properties, settingData, dialogEvent, dialogCancelEvent, weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
1251             auto overlayManager = weak.Upgrade();
1252             CHECK_NULL_VOID(overlayManager);
1253             overlayManager->ShowTextDialog(properties, settingData, dialogEvent, dialogCancelEvent);
1254         },
1255         TaskExecutor::TaskType::UI);
1256 }
1257 
ParseShowDataOptions(const JSRef<JSObject> & paramObject,ParseTextArrayParam & param,NG::TextCascadePickerOptionsAttr & attr)1258 bool JSTextPickerDialog::ParseShowDataOptions(
1259     const JSRef<JSObject>& paramObject, ParseTextArrayParam& param, NG::TextCascadePickerOptionsAttr& attr)
1260 {
1261     bool optionsMultiContentCheckErr = false;
1262     bool optionsCascadeContentCheckErr = false;
1263     if (!JSTextPickerParser::ParseMultiTextArray(paramObject, param)) {
1264         LOGI("parse multi text error.");
1265         param.options.clear();
1266         optionsMultiContentCheckErr = true;
1267     }
1268 
1269     if (optionsMultiContentCheckErr) {
1270         if (!JSTextPickerParser::ParseCascadeTextArray(paramObject, param.selecteds, param.values, attr)) {
1271             LOGI("parse cascade text error.");
1272             param.options.clear();
1273             optionsCascadeContentCheckErr = true;
1274         } else {
1275             JSRef<JSArray> getRange = paramObject->GetProperty("range");
1276             JSTextPickerParser::GenerateCascadeOptions(getRange, param.options);
1277             attr.isCascade = true;
1278         }
1279     }
1280     if (optionsMultiContentCheckErr && optionsCascadeContentCheckErr) {
1281         LOGI("parse option error.");
1282         param.options.clear();
1283         return false;
1284     }
1285     return true;
1286 }
1287 
ParseShowDataAttribute(const JSRef<JSObject> & paramObject,NG::TextPickerSettingData & settingData)1288 bool JSTextPickerDialog::ParseShowDataAttribute(
1289     const JSRef<JSObject>& paramObject, NG::TextPickerSettingData& settingData)
1290 {
1291     CalcDimension height;
1292     auto defaultHeight = paramObject->GetProperty("defaultPickerItemHeight");
1293     if (defaultHeight->IsNumber() || defaultHeight->IsString()) {
1294         if (!JSViewAbstract::ParseJsDimensionFp(defaultHeight, height)) {
1295             return false;
1296         }
1297     }
1298     settingData.height = height;
1299     ParseTextProperties(paramObject, settingData.properties);
1300     return true;
1301 }
ParseCanLoop(const JSRef<JSObject> & paramObject,bool & canLoop)1302 bool JSTextPickerDialog::ParseCanLoop(const JSRef<JSObject>& paramObject, bool& canLoop)
1303 {
1304     bool result = false;
1305     auto prop = paramObject->GetProperty("canLoop");
1306     bool value = false;
1307     if (prop->IsBoolean() && JSViewAbstract::ParseJsBool(prop, value)) {
1308         canLoop = value;
1309         result = true;
1310     } else {
1311         canLoop = true;
1312         result = false;
1313     }
1314     return result;
1315 }
1316 
ParseShowDataMultiContent(const std::vector<NG::TextCascadePickerOptions> & options,const std::vector<uint32_t> & selectedValues,const std::vector<std::string> & values,NG::TextCascadePickerOptionsAttr & attr,NG::TextPickerSettingData & settingData)1317 void JSTextPickerDialog::ParseShowDataMultiContent(const std::vector<NG::TextCascadePickerOptions>& options,
1318     const std::vector<uint32_t>& selectedValues, const std::vector<std::string>& values,
1319     NG::TextCascadePickerOptionsAttr& attr, NG::TextPickerSettingData& settingData)
1320 {
1321     settingData.columnKind = NG::TEXT;
1322     for (auto& item : selectedValues) {
1323         settingData.selectedValues.emplace_back(item);
1324     }
1325     for (auto& item : values) {
1326         settingData.values.emplace_back(item);
1327     }
1328     for (auto& item : options) {
1329         settingData.options.emplace_back(item);
1330     }
1331     settingData.attr.isCascade = attr.isCascade;
1332     settingData.attr.isHasSelectAttr = attr.isHasSelectAttr;
1333 }
1334 
ParseShowData(const JSRef<JSObject> & paramObject,NG::TextPickerSettingData & settingData)1335 bool JSTextPickerDialog::ParseShowData(const JSRef<JSObject>& paramObject, NG::TextPickerSettingData& settingData)
1336 {
1337     ParseTextArrayParam param;
1338     bool rangeContentCheckErr = false;
1339     bool optionsCascadeContentCheckErr = false;
1340     NG::TextCascadePickerOptionsAttr attr;
1341     auto getRange = paramObject->GetProperty("range");
1342     if (getRange->IsNull() || getRange->IsUndefined()) {
1343         return false;
1344     }
1345     if (!JSTextPickerParser::ParseTextArray(paramObject, param)) {
1346         if (!JSTextPickerParser::ParseIconTextArray(paramObject, param.result, param.kind, param.selected)) {
1347             LOGI("parse range error.");
1348             rangeContentCheckErr = true;
1349             param.result.clear();
1350         }
1351     }
1352     if (rangeContentCheckErr) {
1353         optionsCascadeContentCheckErr = !ParseShowDataOptions(paramObject, param, attr);
1354     }
1355     if (rangeContentCheckErr && optionsCascadeContentCheckErr) {
1356         LOGE("parse option all type error.");
1357         return false;
1358     }
1359     if (memset_s(&settingData, sizeof(NG::TextPickerSettingData), 0, sizeof(NG::TextPickerSettingData)) != EOK) {
1360         LOGE("memset settingData error.");
1361         return false;
1362     }
1363     if (!ParseShowDataAttribute(paramObject, settingData)) {
1364         return false;
1365     }
1366     if (!ParseCanLoop(paramObject, settingData.canLoop)) {
1367         LOGW("don't find property(canLoop), set default true");
1368     }
1369     if (param.result.size() > 0) {
1370         settingData.selected = param.selected;
1371         settingData.columnKind = param.kind;
1372         for (const auto& item : param.result) {
1373             settingData.rangeVector.emplace_back(item);
1374         }
1375     } else {
1376         ParseShowDataMultiContent(param.options, param.selecteds, param.values, attr, settingData);
1377     }
1378     return true;
1379 }
1380 
ParseTextProperties(const JSRef<JSObject> & paramObj,NG::PickerTextProperties & result)1381 void JSTextPickerDialog::ParseTextProperties(const JSRef<JSObject>& paramObj, NG::PickerTextProperties& result)
1382 {
1383     auto disappearProperty = paramObj->GetProperty("disappearTextStyle");
1384     auto normalProperty = paramObj->GetProperty("textStyle");
1385     auto selectedProperty = paramObj->GetProperty("selectedTextStyle");
1386 
1387     if (!disappearProperty->IsNull() && disappearProperty->IsObject()) {
1388         JSRef<JSObject> disappearObj = JSRef<JSObject>::Cast(disappearProperty);
1389         JSTextPickerParser::ParseTextStyle(disappearObj, result.disappearTextStyle_);
1390     }
1391 
1392     if (!normalProperty->IsNull() && normalProperty->IsObject()) {
1393         JSRef<JSObject> noramlObj = JSRef<JSObject>::Cast(normalProperty);
1394         JSTextPickerParser::ParseTextStyle(noramlObj, result.normalTextStyle_);
1395     }
1396 
1397     if (!selectedProperty->IsNull() && selectedProperty->IsObject()) {
1398         JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(selectedProperty);
1399         JSTextPickerParser::ParseTextStyle(selectedObj, result.selectedTextStyle_);
1400     }
1401 }
1402 
DialogEvent(const JSCallbackInfo & info)1403 std::map<std::string, NG::DialogTextEvent> JSTextPickerDialog::DialogEvent(const JSCallbackInfo& info)
1404 {
1405     std::map<std::string, NG::DialogTextEvent> dialogEvent;
1406     if (info.Length() < 1 || !info[0]->IsObject()) {
1407         LOGE("TextPicker AddEvent error, info is non-valid");
1408         return dialogEvent;
1409     }
1410     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1411     auto onAccept = paramObject->GetProperty("onAccept");
1412     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1413         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1414         auto acceptId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& info) {
1415             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1416             std::vector<std::string> keys = { "value", "index" };
1417             ACE_SCORING_EVENT("TextPickerDialog.onAccept");
1418             func->Execute(keys, info);
1419         };
1420         dialogEvent["acceptId"] = acceptId;
1421     }
1422     auto onChange = paramObject->GetProperty("onChange");
1423     if (!onChange->IsUndefined() && onChange->IsFunction()) {
1424         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
1425         auto changeId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& info) {
1426             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1427             std::vector<std::string> keys = { "value", "index" };
1428             ACE_SCORING_EVENT("TextPickerDialog.onChange");
1429             func->Execute(keys, info);
1430         };
1431         dialogEvent["changeId"] = changeId;
1432     }
1433     return dialogEvent;
1434 }
1435 
DialogCancelEvent(const JSCallbackInfo & info)1436 std::map<std::string, NG::DialogGestureEvent> JSTextPickerDialog::DialogCancelEvent(const JSCallbackInfo& info)
1437 {
1438     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent;
1439     if (info.Length() < 1 || !info[0]->IsObject()) {
1440         LOGE("TextPicker AddEvent error, info is non-valid");
1441         return dialogCancelEvent;
1442     }
1443     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1444     auto onCancel = paramObject->GetProperty("onCancel");
1445     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1446         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1447         auto cancelId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](
1448                             const GestureEvent& /* info */) {
1449             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1450             ACE_SCORING_EVENT("TextPickerDialog.onCancel");
1451             func->Execute();
1452         };
1453         dialogCancelEvent["cancelId"] = cancelId;
1454     }
1455     return dialogCancelEvent;
1456 }
1457 
AddEvent(RefPtr<PickerTextComponent> & picker,const JSCallbackInfo & info)1458 void JSTextPickerDialog::AddEvent(RefPtr<PickerTextComponent>& picker, const JSCallbackInfo& info)
1459 {
1460     if (info.Length() < 1 || !info[0]->IsObject()) {
1461         LOGE("TextPicker AddEvent error, info is non-valid");
1462         return;
1463     }
1464     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1465     auto onAccept = paramObject->GetProperty("onAccept");
1466     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1467         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1468         auto acceptId =
1469             EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& info) {
1470                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1471                 std::vector<std::string> keys = { "value", "index" };
1472                 ACE_SCORING_EVENT("TextPickerDialog.onAccept");
1473                 func->Execute(keys, info);
1474             });
1475         picker->SetDialogAcceptEvent(acceptId);
1476     }
1477     auto onCancel = paramObject->GetProperty("onCancel");
1478     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1479         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1480         auto cancelId = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc)]() {
1481             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1482             ACE_SCORING_EVENT("TextPickerDialog.onCancel");
1483             func->Execute();
1484         });
1485         picker->SetDialogCancelEvent(cancelId);
1486     }
1487     auto onChange = paramObject->GetProperty("onChange");
1488     if (!onChange->IsUndefined() && onChange->IsFunction()) {
1489         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
1490         auto changeId =
1491             EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& info) {
1492                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1493                 std::vector<std::string> keys = { "value", "index" };
1494                 ACE_SCORING_EVENT("TextPickerDialog.onChange");
1495                 func->Execute(keys, info);
1496             });
1497         picker->SetDialogChangeEvent(changeId);
1498     }
1499 }
1500 
ParseText(RefPtr<PickerTextComponent> & component,const JSRef<JSObject> & paramObj)1501 void JSTextPickerDialog::ParseText(RefPtr<PickerTextComponent>& component, const JSRef<JSObject>& paramObj)
1502 {
1503     auto getSelected = paramObj->GetProperty("selected");
1504     auto defaultHeight = paramObj->GetProperty("defaultPickerItemHeight");
1505     auto canLoop = paramObj->GetProperty("canLoop");
1506     JSRef<JSArray> getRange = paramObj->GetProperty("range");
1507     std::vector<std::string> getRangeVector;
1508     if (!JSViewAbstract::ParseJsStrArray(getRange, getRangeVector)) {
1509         LOGE("parse range failed");
1510         return;
1511     }
1512 
1513     std::string value = "";
1514     uint32_t selectedValue = 0;
1515     auto getValue = paramObj->GetProperty("value");
1516     if (!JSViewAbstract::ParseJsInteger(getSelected, selectedValue) && JSViewAbstract::ParseJsString(getValue, value)) {
1517         auto valueIterator = std::find(getRangeVector.begin(), getRangeVector.end(), value);
1518         if (valueIterator != getRangeVector.end()) {
1519             selectedValue = std::distance(getRangeVector.begin(), valueIterator);
1520         }
1521     }
1522 
1523     if (selectedValue >= getRangeVector.size()) {
1524         LOGW("selectedValue is out of range");
1525         selectedValue = 0;
1526     }
1527 
1528     CalcDimension height;
1529     if (defaultHeight->IsNumber() || defaultHeight->IsString()) {
1530         if (!JSViewAbstract::ParseJsDimensionFp(defaultHeight, height)) {
1531             return;
1532         }
1533     }
1534 
1535     component->SetIsDialog(true);
1536     component->SetIsCreateDialogComponent(true);
1537     if (!defaultHeight->IsEmpty()) {
1538         component->SetColumnHeight(height);
1539         component->SetDefaultHeight(true);
1540     }
1541     component->SetSelected(selectedValue);
1542     component->SetRange(getRangeVector);
1543 }
1544 } // namespace OHOS::Ace::Framework
1545