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