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