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