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