• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "bridge/declarative_frontend/jsview/js_select.h"
17 
18 #include <cstdint>
19 #include <string>
20 #include <vector>
21 
22 #include "base/log/ace_scoring_log.h"
23 #include "base/utils/utils.h"
24 #include "bridge/common/utils/utils.h"
25 #include "bridge/declarative_frontend/engine/functions/js_function.h"
26 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
27 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
28 #include "bridge/declarative_frontend/jsview/models/select_model_impl.h"
29 #include "core/components_ng/base/view_abstract_model.h"
30 #include "core/components_ng/base/view_stack_processor.h"
31 #include "core/components_ng/pattern/select/select_model.h"
32 #include "core/components_ng/pattern/select/select_model_ng.h"
33 #include "core/components_v2/inspector/inspector_constants.h"
34 #include "core/pipeline/pipeline_base.h"
35 
36 namespace OHOS::Ace {
37 std::unique_ptr<SelectModel> SelectModel::instance_ = nullptr;
38 std::mutex SelectModel::mutex_;
39 
GetInstance()40 SelectModel* SelectModel::GetInstance()
41 {
42     if (!instance_) {
43         std::lock_guard<std::mutex> lock(mutex_);
44         if (!instance_) {
45 #ifdef NG_BUILD
46             instance_.reset(new NG::SelectModelNG());
47 #else
48             if (Container::IsCurrentUseNewPipeline()) {
49                 instance_.reset(new NG::SelectModelNG());
50             } else {
51                 instance_.reset(new Framework::SelectModelImpl());
52             }
53 #endif
54         }
55     }
56     return instance_.get();
57 }
58 } // namespace OHOS::Ace
59 
60 namespace OHOS::Ace::Framework {
Create(const JSCallbackInfo & info)61 void JSSelect::Create(const JSCallbackInfo& info)
62 {
63     if (info.Length() < 0) {
64         return;
65     }
66     if (info[0]->IsArray()) {
67         auto paramArray = JSRef<JSArray>::Cast(info[0]);
68         size_t size = paramArray->Length();
69         std::vector<SelectParam> params(size);
70         for (size_t i = 0; i < size; i++) {
71             std::string value;
72             std::string icon;
73             JSRef<JSVal> indexVal = paramArray->GetValueAt(i);
74             if (!indexVal->IsObject()) {
75                 return;
76             }
77             auto indexObject = JSRef<JSObject>::Cast(indexVal);
78             auto selectValue = indexObject->GetProperty("value");
79             auto selectIcon = indexObject->GetProperty("icon");
80             ParseJsString(selectValue, value);
81             ParseJsMedia(selectIcon, icon);
82             params[i] = { value, icon };
83         }
84         SelectModel::GetInstance()->Create(params);
85     }
86 }
87 
JSBind(BindingTarget globalObj)88 void JSSelect::JSBind(BindingTarget globalObj)
89 {
90     JSClass<JSSelect>::Declare("Select");
91     MethodOptions opt = MethodOptions::NONE;
92     JSClass<JSSelect>::StaticMethod("create", &JSSelect::Create, opt);
93 
94     JSClass<JSSelect>::StaticMethod("selected", &JSSelect::Selected, opt);
95     JSClass<JSSelect>::StaticMethod("value", &JSSelect::Value, opt);
96     JSClass<JSSelect>::StaticMethod("font", &JSSelect::Font, opt);
97     JSClass<JSSelect>::StaticMethod("fontColor", &JSSelect::FontColor, opt);
98     JSClass<JSSelect>::StaticMethod("selectedOptionBgColor", &JSSelect::SelectedOptionBgColor, opt);
99     JSClass<JSSelect>::StaticMethod("selectedOptionFont", &JSSelect::SelectedOptionFont, opt);
100     JSClass<JSSelect>::StaticMethod("selectedOptionFontColor", &JSSelect::SelectedOptionFontColor, opt);
101     JSClass<JSSelect>::StaticMethod("optionBgColor", &JSSelect::OptionBgColor, opt);
102     JSClass<JSSelect>::StaticMethod("optionFont", &JSSelect::OptionFont, opt);
103     JSClass<JSSelect>::StaticMethod("optionFontColor", &JSSelect::OptionFontColor, opt);
104     JSClass<JSSelect>::StaticMethod("onSelect", &JSSelect::OnSelected, opt);
105     JSClass<JSSelect>::StaticMethod("space", &JSSelect::SetSpace, opt);
106     JSClass<JSSelect>::StaticMethod("arrowPosition", &JSSelect::SetArrowPosition, opt);
107     JSClass<JSSelect>::StaticMethod("menuAlign", &JSSelect::SetMenuAlign, opt);
108 
109     // API7 onSelected deprecated
110     JSClass<JSSelect>::StaticMethod("onSelected", &JSSelect::OnSelected, opt);
111     JSClass<JSSelect>::StaticMethod("width", &JSSelect::JsWidth);
112     JSClass<JSSelect>::StaticMethod("height", &JSSelect::JsHeight);
113     JSClass<JSSelect>::StaticMethod("size", &JSSelect::JsSize);
114     JSClass<JSSelect>::StaticMethod("padding", &JSSelect::JsPadding);
115     JSClass<JSSelect>::StaticMethod("paddingTop", &JSSelect::SetPaddingTop, opt);
116     JSClass<JSSelect>::StaticMethod("paddingBottom", &JSSelect::SetPaddingBottom, opt);
117     JSClass<JSSelect>::StaticMethod("paddingLeft", &JSSelect::SetPaddingLeft, opt);
118     JSClass<JSSelect>::StaticMethod("paddingRight", &JSSelect::SetPaddingRight, opt);
119     JSClass<JSSelect>::StaticMethod("optionWidth", &JSSelect::SetOptionWidth, opt);
120     JSClass<JSSelect>::StaticMethod("optionHeight", &JSSelect::SetOptionHeight, opt);
121     JSClass<JSSelect>::StaticMethod("optionWidthFitTrigger", &JSSelect::SetOptionWidthFitTrigger, opt);
122     JSClass<JSSelect>::StaticMethod("menuBackgroundColor", &JSSelect::SetMenuBackgroundColor, opt);
123     JSClass<JSSelect>::StaticMethod("menuBackgroundBlurStyle", &JSSelect::SetMenuBackgroundBlurStyle, opt);
124 
125     JSClass<JSSelect>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
126     JSClass<JSSelect>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
127     JSClass<JSSelect>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
128     JSClass<JSSelect>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
129     JSClass<JSSelect>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
130     JSClass<JSSelect>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
131     JSClass<JSSelect>::InheritAndBind<JSViewAbstract>(globalObj);
132 }
133 
ParseSelectedObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)134 void ParseSelectedObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
135 {
136     CHECK_NULL_VOID(changeEventVal->IsFunction());
137 
138     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
139     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
140     auto onSelect = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](int32_t index) {
141         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
142         ACE_SCORING_EVENT("Select.SelectChangeEvent");
143         PipelineContext::SetCallBackNode(node);
144         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(index));
145         func->ExecuteJS(1, &newJSVal);
146     };
147     SelectModel::GetInstance()->SetSelectChangeEvent(onSelect);
148 }
149 
Selected(const JSCallbackInfo & info)150 void JSSelect::Selected(const JSCallbackInfo& info)
151 {
152     if (info.Length() < 1 || info.Length() > 2) {
153         return;
154     }
155 
156     int32_t value = 0;
157     if (info.Length() > 0) {
158         ParseJsInteger<int32_t>(info[0], value);
159     }
160 
161     if (value < -1) {
162         value = -1;
163     }
164     if (info.Length() > 1 && info[1]->IsFunction()) {
165         ParseSelectedObject(info, info[1]);
166     }
167     SelectModel::GetInstance()->SetSelected(value);
168 }
169 
ParseValueObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)170 void ParseValueObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
171 {
172     CHECK_NULL_VOID(changeEventVal->IsFunction());
173 
174     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
175     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
176     auto onSelect = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
177                         const std::string& value) {
178         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
179         ACE_SCORING_EVENT("Select.ValueChangeEvent");
180         PipelineContext::SetCallBackNode(node);
181         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(value));
182         func->ExecuteJS(1, &newJSVal);
183     };
184     SelectModel::GetInstance()->SetValueChangeEvent(onSelect);
185 }
186 
Value(const JSCallbackInfo & info)187 void JSSelect::Value(const JSCallbackInfo& info)
188 {
189     if (info.Length() < 1 || info.Length() > 2) {
190         return;
191     }
192 
193     std::string value;
194     if (info.Length() > 0) {
195         ParseJsString(info[0], value);
196     }
197 
198     if (info.Length() > 1 && info[1]->IsFunction()) {
199         ParseValueObject(info, info[1]);
200     }
201     SelectModel::GetInstance()->SetValue(value);
202 }
203 
Font(const JSCallbackInfo & info)204 void JSSelect::Font(const JSCallbackInfo& info)
205 {
206     if (info[0]->IsUndefined() || info[0]->IsNull()) {
207         auto pipeline = PipelineBase::GetCurrentContext();
208         CHECK_NULL_VOID(pipeline);
209         auto selectTheme = pipeline->GetTheme<SelectTheme>();
210         CHECK_NULL_VOID(selectTheme);
211         auto textTheme = pipeline->GetTheme<TextTheme>();
212         CHECK_NULL_VOID(textTheme);
213         SelectModel::GetInstance()->SetFontSize(selectTheme->GetFontSize());
214         SelectModel::GetInstance()->SetFontWeight(FontWeight::MEDIUM);
215         SelectModel::GetInstance()->SetFontFamily(textTheme->GetTextStyle().GetFontFamilies());
216         SelectModel::GetInstance()->SetItalicFontStyle(textTheme->GetTextStyle().GetFontStyle());
217         return;
218     }
219 
220     if (!info[0]->IsObject()) {
221         return;
222     }
223 
224     auto param = JSRef<JSObject>::Cast(info[0]);
225     auto size = param->GetProperty("size");
226     if (!size->IsNull()) {
227         CalcDimension fontSize;
228         if (ParseJsDimensionFp(size, fontSize)) {
229             SelectModel::GetInstance()->SetFontSize(fontSize);
230         }
231     }
232     std::string weight;
233     auto fontWeight = param->GetProperty("weight");
234     if (!fontWeight->IsNull()) {
235         if (fontWeight->IsNumber()) {
236             weight = std::to_string(fontWeight->ToNumber<int32_t>());
237         } else {
238             ParseJsString(fontWeight, weight);
239         }
240         SelectModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(weight));
241     }
242 
243     auto family = param->GetProperty("family");
244     if (!family->IsNull() && family->IsString()) {
245         auto familyVal = family->ToString();
246         SelectModel::GetInstance()->SetFontFamily(ConvertStrToFontFamilies(familyVal));
247     }
248 
249     auto style = param->GetProperty("style");
250     if (!style->IsNull() && style->IsNumber()) {
251         auto styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
252         SelectModel::GetInstance()->SetItalicFontStyle(styleVal);
253     }
254 }
255 
FontColor(const JSCallbackInfo & info)256 void JSSelect::FontColor(const JSCallbackInfo& info)
257 {
258     if (info.Length() < 1) {
259         return;
260     }
261 
262     Color textColor;
263     if (!ParseJsColor(info[0], textColor)) {
264         if (info[0]->IsNull() || info[0]->IsUndefined()) {
265             auto pipeline = PipelineBase::GetCurrentContext();
266             CHECK_NULL_VOID(pipeline);
267             auto theme = pipeline->GetTheme<SelectTheme>();
268             CHECK_NULL_VOID(theme);
269             textColor = theme->GetFontColor();
270         } else {
271             return;
272         }
273     }
274 
275     SelectModel::GetInstance()->SetFontColor(textColor);
276 }
277 
SelectedOptionBgColor(const JSCallbackInfo & info)278 void JSSelect::SelectedOptionBgColor(const JSCallbackInfo& info)
279 {
280     if (info.Length() < 1) {
281         return;
282     }
283     Color bgColor;
284     if (!ParseJsColor(info[0], bgColor)) {
285         if (info[0]->IsUndefined() || info[0]->IsNull()) {
286             auto pipeline = PipelineBase::GetCurrentContext();
287             CHECK_NULL_VOID(pipeline);
288             auto theme = pipeline->GetTheme<SelectTheme>();
289             CHECK_NULL_VOID(theme);
290             bgColor = theme->GetSelectedColor();
291         } else {
292             return;
293         }
294     }
295     SelectModel::GetInstance()->SetSelectedOptionBgColor(bgColor);
296 }
297 
SelectedOptionFont(const JSCallbackInfo & info)298 void JSSelect::SelectedOptionFont(const JSCallbackInfo& info)
299 {
300     if (info.Length() < 1) {
301         return;
302     }
303     auto pipeline = PipelineBase::GetCurrentContext();
304     CHECK_NULL_VOID(pipeline);
305     auto selectTheme = pipeline->GetTheme<SelectTheme>();
306     CHECK_NULL_VOID(selectTheme);
307     if (info[0]->IsUndefined() || info[0]->IsNull()) {
308         auto textTheme = pipeline->GetTheme<TextTheme>();
309         CHECK_NULL_VOID(textTheme);
310         SelectModel::GetInstance()->SetSelectedOptionFontSize(selectTheme->GetFontSize());
311         SelectModel::GetInstance()->SetSelectedOptionFontWeight(textTheme->GetTextStyle().GetFontWeight());
312         SelectModel::GetInstance()->SetSelectedOptionFontFamily(textTheme->GetTextStyle().GetFontFamilies());
313         SelectModel::GetInstance()->SetSelectedOptionItalicFontStyle(textTheme->GetTextStyle().GetFontStyle());
314         return;
315     }
316     if (!info[0]->IsObject()) {
317         return;
318     }
319     auto param = JSRef<JSObject>::Cast(info[0]);
320     auto size = param->GetProperty("size");
321     if (!size->IsNull()) {
322         CalcDimension fontSize;
323         if (ParseJsDimensionFp(size, fontSize)) {
324             SelectModel::GetInstance()->SetSelectedOptionFontSize(fontSize);
325         } else if (size->IsUndefined()) {
326             SelectModel::GetInstance()->SetSelectedOptionFontSize(selectTheme->GetFontSize());
327         }
328     }
329     std::string weight;
330     auto fontWeight = param->GetProperty("weight");
331     if (!fontWeight->IsNull()) {
332         if (fontWeight->IsNumber()) {
333             weight = std::to_string(fontWeight->ToNumber<int32_t>());
334         } else {
335             ParseJsString(fontWeight, weight);
336         }
337         SelectModel::GetInstance()->SetSelectedOptionFontWeight(ConvertStrToFontWeight(weight));
338     }
339     auto family = param->GetProperty("family");
340     if (!family->IsNull() && family->IsString()) {
341         auto familyVal = family->ToString();
342         SelectModel::GetInstance()->SetSelectedOptionFontFamily(ConvertStrToFontFamilies(familyVal));
343     }
344     auto style = param->GetProperty("style");
345     if (!style->IsNull() && style->IsNumber()) {
346         auto styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
347         SelectModel::GetInstance()->SetSelectedOptionItalicFontStyle(styleVal);
348     }
349 }
350 
SelectedOptionFontColor(const JSCallbackInfo & info)351 void JSSelect::SelectedOptionFontColor(const JSCallbackInfo& info)
352 {
353     if (info.Length() < 1) {
354         return;
355     }
356     Color textColor;
357     if (!ParseJsColor(info[0], textColor)) {
358         if (info[0]->IsNull() || info[0]->IsUndefined()) {
359             auto pipeline = PipelineBase::GetCurrentContext();
360             CHECK_NULL_VOID(pipeline);
361             auto theme = pipeline->GetTheme<SelectTheme>();
362             CHECK_NULL_VOID(theme);
363             textColor = theme->GetSelectedColorText();
364         } else {
365             return;
366         }
367     }
368     SelectModel::GetInstance()->SetSelectedOptionFontColor(textColor);
369 }
370 
OptionBgColor(const JSCallbackInfo & info)371 void JSSelect::OptionBgColor(const JSCallbackInfo& info)
372 {
373     if (info.Length() < 1) {
374         return;
375     }
376     Color bgColor;
377     if (!ParseJsColor(info[0], bgColor)) {
378         if (info[0]->IsUndefined() || info[0]->IsNull()) {
379             auto pipeline = PipelineBase::GetCurrentContext();
380             CHECK_NULL_VOID(pipeline);
381             auto theme = pipeline->GetTheme<SelectTheme>();
382             CHECK_NULL_VOID(theme);
383             bgColor = theme->GetBackgroundColor();
384         } else {
385             return;
386         }
387     }
388 
389     SelectModel::GetInstance()->SetOptionBgColor(bgColor);
390 }
391 
OptionFont(const JSCallbackInfo & info)392 void JSSelect::OptionFont(const JSCallbackInfo& info)
393 {
394     if (info[0]->IsUndefined() || info[0]->IsNull()) {
395         auto pipeline = PipelineBase::GetCurrentContext();
396         CHECK_NULL_VOID(pipeline);
397         auto selectTheme = pipeline->GetTheme<SelectTheme>();
398         CHECK_NULL_VOID(selectTheme);
399         auto textTheme = pipeline->GetTheme<TextTheme>();
400         CHECK_NULL_VOID(textTheme);
401         SelectModel::GetInstance()->SetOptionFontSize(selectTheme->GetMenuFontSize());
402         SelectModel::GetInstance()->SetOptionFontWeight(textTheme->GetTextStyle().GetFontWeight());
403         SelectModel::GetInstance()->SetOptionFontFamily(textTheme->GetTextStyle().GetFontFamilies());
404         SelectModel::GetInstance()->SetOptionItalicFontStyle(textTheme->GetTextStyle().GetFontStyle());
405         return;
406     }
407 
408     if (!info[0]->IsObject()) {
409         return;
410     }
411     auto param = JSRef<JSObject>::Cast(info[0]);
412 
413     auto size = param->GetProperty("size");
414     if (!size->IsNull()) {
415         CalcDimension fontSize;
416         if (ParseJsDimensionFp(size, fontSize)) {
417             SelectModel::GetInstance()->SetOptionFontSize(fontSize);
418         }
419         if (size->IsUndefined()) {
420             auto pipeline = PipelineBase::GetCurrentContext();
421             CHECK_NULL_VOID(pipeline);
422             auto theme = pipeline->GetTheme<SelectTheme>();
423             CHECK_NULL_VOID(theme);
424             SelectModel::GetInstance()->SetOptionFontSize(theme->GetMenuFontSize());
425         }
426     }
427     std::string weight;
428     auto fontWeight = param->GetProperty("weight");
429     if (!fontWeight->IsNull()) {
430         if (fontWeight->IsNumber()) {
431             weight = std::to_string(fontWeight->ToNumber<int32_t>());
432         } else {
433             ParseJsString(fontWeight, weight);
434         }
435         SelectModel::GetInstance()->SetOptionFontWeight(ConvertStrToFontWeight(weight));
436     }
437 
438     auto family = param->GetProperty("family");
439     if (!family->IsNull() && family->IsString()) {
440         auto familyVal = family->ToString();
441         SelectModel::GetInstance()->SetOptionFontFamily(ConvertStrToFontFamilies(familyVal));
442     }
443 
444     auto style = param->GetProperty("style");
445     if (!style->IsNull() && style->IsNumber()) {
446         auto styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
447         SelectModel::GetInstance()->SetOptionItalicFontStyle(styleVal);
448     }
449 }
450 
OptionFontColor(const JSCallbackInfo & info)451 void JSSelect::OptionFontColor(const JSCallbackInfo& info)
452 {
453     if (info.Length() < 1) {
454         return;
455     }
456     Color textColor;
457     if (!ParseJsColor(info[0], textColor)) {
458         if (info[0]->IsUndefined() || info[0]->IsNull()) {
459             auto pipeline = PipelineBase::GetCurrentContext();
460             CHECK_NULL_VOID(pipeline);
461             auto theme = pipeline->GetTheme<SelectTheme>();
462             CHECK_NULL_VOID(theme);
463             textColor = theme->GetMenuFontColor();
464         } else {
465             return;
466         }
467     }
468 
469     SelectModel::GetInstance()->SetOptionFontColor(textColor);
470 }
471 
OnSelected(const JSCallbackInfo & info)472 void JSSelect::OnSelected(const JSCallbackInfo& info)
473 {
474     if (!info[0]->IsFunction()) {
475         return;
476     }
477     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
478     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
479     auto onSelect = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
480                         int32_t index, const std::string& value) {
481         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
482         ACE_SCORING_EVENT("Select.onSelect");
483         PipelineContext::SetCallBackNode(node);
484         JSRef<JSVal> params[2];
485         params[0] = JSRef<JSVal>::Make(ToJSValue(index));
486         params[1] = JSRef<JSVal>::Make(ToJSValue(value));
487         func->ExecuteJS(2, params);
488     };
489     SelectModel::GetInstance()->SetOnSelect(std::move(onSelect));
490     info.ReturnSelf();
491 }
492 
JsWidth(const JSCallbackInfo & info)493 void JSSelect::JsWidth(const JSCallbackInfo& info)
494 {
495     if (info.Length() < 1) {
496         return;
497     }
498     CalcDimension value;
499     if (!ParseJsDimensionVp(info[0], value)) {
500         return;
501     }
502 
503     SelectModel::GetInstance()->SetWidth(value);
504 }
505 
JsHeight(const JSCallbackInfo & info)506 void JSSelect::JsHeight(const JSCallbackInfo& info)
507 {
508     if (info.Length() < 1) {
509         return;
510     }
511 
512     CalcDimension value;
513     if (!ParseJsDimensionVp(info[0], value)) {
514         return;
515     }
516 
517     SelectModel::GetInstance()->SetHeight(value);
518 }
519 
CheckJSCallbackInfo(const std::string & callerName,const JSCallbackInfo & info,std::vector<JSCallbackInfoType> & infoTypes)520 bool CheckJSCallbackInfo(
521     const std::string& callerName, const JSCallbackInfo& info, std::vector<JSCallbackInfoType>& infoTypes)
522 {
523     if (info.Length() < 1) {
524         return false;
525     }
526     bool typeVerified = false;
527     std::string unrecognizedType;
528     for (const auto& infoType : infoTypes) {
529         switch (infoType) {
530             case JSCallbackInfoType::STRING:
531                 if (info[0]->IsString()) {
532                     typeVerified = true;
533                 } else {
534                     unrecognizedType += "string|";
535                 }
536                 break;
537             case JSCallbackInfoType::NUMBER:
538                 if (info[0]->IsNumber()) {
539                     typeVerified = true;
540                 } else {
541                     unrecognizedType += "number|";
542                 }
543                 break;
544             case JSCallbackInfoType::OBJECT:
545                 if (info[0]->IsObject()) {
546                     typeVerified = true;
547                 } else {
548                     unrecognizedType += "object|";
549                 }
550                 break;
551             case JSCallbackInfoType::FUNCTION:
552                 if (info[0]->IsFunction()) {
553                     typeVerified = true;
554                 } else {
555                     unrecognizedType += "Function|";
556                 }
557                 break;
558             default:
559                 break;
560         }
561     }
562     return typeVerified || infoTypes.size() == 0;
563 }
564 
JsSize(const JSCallbackInfo & info)565 void JSSelect::JsSize(const JSCallbackInfo& info)
566 {
567     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
568     if (!CheckJSCallbackInfo("JsSize", info, checkList)) {
569         return;
570     }
571 
572     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
573 
574     CalcDimension width;
575     if (!ParseJsDimensionVp(sizeObj->GetProperty("width"), width)) {
576         return;
577     }
578 
579     CalcDimension height;
580     if (!ParseJsDimensionVp(sizeObj->GetProperty("height"), height)) {
581         return;
582     }
583 
584     SelectModel::GetInstance()->SetSize(width, height);
585 }
586 
JsPadding(const JSCallbackInfo & info)587 void JSSelect::JsPadding(const JSCallbackInfo& info)
588 {
589     if (!info[0]->IsString() && !info[0]->IsNumber() && !info[0]->IsObject()) {
590         return;
591     }
592 
593     if (info[0]->IsObject()) {
594         std::optional<CalcDimension> left;
595         std::optional<CalcDimension> right;
596         std::optional<CalcDimension> top;
597         std::optional<CalcDimension> bottom;
598         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info[0]);
599 
600         CalcDimension leftDimen;
601         if (ParseJsDimensionVp(paddingObj->GetProperty("left"), leftDimen)) {
602             left = leftDimen;
603         }
604         CalcDimension rightDimen;
605         if (ParseJsDimensionVp(paddingObj->GetProperty("right"), rightDimen)) {
606             right = rightDimen;
607         }
608         CalcDimension topDimen;
609         if (ParseJsDimensionVp(paddingObj->GetProperty("top"), topDimen)) {
610             top = topDimen;
611         }
612         CalcDimension bottomDimen;
613         if (ParseJsDimensionVp(paddingObj->GetProperty("bottom"), bottomDimen)) {
614             bottom = bottomDimen;
615         }
616         if (left.has_value() || right.has_value() || top.has_value() || bottom.has_value()) {
617             ViewAbstractModel::GetInstance()->SetPaddings(top, bottom, left, right);
618             return;
619         }
620     }
621 
622     CalcDimension value;
623     if (!ParseJsDimensionVp(info[0], value)) {
624         value.Reset();
625     }
626     SelectModel::GetInstance()->SetPadding(value);
627 }
628 
SetPaddingLeft(const JSCallbackInfo & info)629 void JSSelect::SetPaddingLeft(const JSCallbackInfo& info)
630 {
631     if (info.Length() < 1) {
632         return;
633     }
634     CalcDimension value;
635     if (!ParseJsDimensionVp(info[0], value)) {
636         return;
637     }
638     SelectModel::GetInstance()->SetPaddingLeft(value);
639 }
640 
SetPaddingTop(const JSCallbackInfo & info)641 void JSSelect::SetPaddingTop(const JSCallbackInfo& info)
642 {
643     if (info.Length() < 1) {
644         return;
645     }
646     CalcDimension value;
647     if (!ParseJsDimensionVp(info[0], value)) {
648         return;
649     }
650     SelectModel::GetInstance()->SetPaddingTop(value);
651 }
652 
SetPaddingRight(const JSCallbackInfo & info)653 void JSSelect::SetPaddingRight(const JSCallbackInfo& info)
654 {
655     if (info.Length() < 1) {
656         return;
657     }
658     CalcDimension value;
659     if (!ParseJsDimensionVp(info[0], value)) {
660         return;
661     }
662     SelectModel::GetInstance()->SetPaddingRight(value);
663 }
664 
SetPaddingBottom(const JSCallbackInfo & info)665 void JSSelect::SetPaddingBottom(const JSCallbackInfo& info)
666 {
667     if (info.Length() < 1) {
668         return;
669     }
670     CalcDimension value;
671     if (!ParseJsDimensionVp(info[0], value)) {
672         return;
673     }
674     SelectModel::GetInstance()->SetPaddingBottom(value);
675 }
676 
SetSpace(const JSCallbackInfo & info)677 void JSSelect::SetSpace(const JSCallbackInfo& info)
678 {
679     if (info.Length() < 1) {
680         return;
681     }
682 
683     auto selectTheme = GetTheme<SelectTheme>();
684 
685     CalcDimension value;
686     if (!ParseJsDimensionVp(info[0], value)) {
687         value = selectTheme->GetContentSpinnerPadding();
688     }
689     if (LessNotEqual(value.Value(), 0.0) || value.Unit() == DimensionUnit::PERCENT) {
690         value = selectTheme->GetContentSpinnerPadding();
691     }
692 
693     SelectModel::GetInstance()->SetSpace(value);
694 }
695 
SetArrowPosition(const JSCallbackInfo & info)696 void JSSelect::SetArrowPosition(const JSCallbackInfo& info)
697 {
698     if (info.Length() < 1) {
699         return;
700     }
701 
702     int32_t direction = 0;
703     if (!ParseJsInt32(info[0], direction)) {
704         direction = 0;
705     }
706 
707     if (static_cast<ArrowPosition>(direction) != ArrowPosition::START &&
708         static_cast<ArrowPosition>(direction) != ArrowPosition::END) {
709         direction = 0;
710     }
711 
712     SelectModel::GetInstance()->SetArrowPosition(static_cast<ArrowPosition>(direction));
713 }
714 
SetMenuAlign(const JSCallbackInfo & info)715 void JSSelect::SetMenuAlign(const JSCallbackInfo& info)
716 {
717     if (info.Length() < 1) {
718         return;
719     }
720 
721     MenuAlign menuAlignObj;
722 
723     if (!info[0]->IsNumber()) {
724         if (!(info[0]->IsUndefined() || info[0]->IsNull())) {
725             return;
726         }
727     } else {
728         menuAlignObj.alignType = static_cast<MenuAlignType>(info[0]->ToNumber<int32_t>());
729     }
730 
731     if (info.Length() > 1) {
732         if (info[1]->IsUndefined() || info[1]->IsNull()) {
733             SelectModel::GetInstance()->SetMenuAlign(menuAlignObj);
734             return;
735         }
736         if (!info[1]->IsObject()) {
737             return;
738         }
739         auto offsetObj = JSRef<JSObject>::Cast(info[1]);
740         CalcDimension dx;
741         auto dxValue = offsetObj->GetProperty("dx");
742         ParseJsDimensionVp(dxValue, dx);
743         CalcDimension dy;
744         auto dyValue = offsetObj->GetProperty("dy");
745         ParseJsDimensionVp(dyValue, dy);
746         menuAlignObj.offset = DimensionOffset(dx, dy);
747     }
748 
749     SelectModel::GetInstance()->SetMenuAlign(menuAlignObj);
750 }
751 
IsPercentStr(std::string & percent)752 bool JSSelect::IsPercentStr(std::string& percent)
753 {
754     if (percent.find("%") != std::string::npos) {
755         size_t index = percent.find("%");
756         percent = percent.substr(0, index);
757         return true;
758     }
759     return false;
760 }
761 
SetOptionWidth(const JSCallbackInfo & info)762 void JSSelect::SetOptionWidth(const JSCallbackInfo& info)
763 {
764     SelectModel::GetInstance()->SetHasOptionWidth(true);
765     CalcDimension value;
766     if (info[0]->IsUndefined()) {
767         LOGE("OptionWidth is undefined");
768         return;
769     } else if (info[0]->IsNull()) {
770         LOGE("OptionWidth is null");
771         return;
772     } else if (info[0]->IsString()) {
773         std::string modeFlag = info[0]->ToString();
774         if (modeFlag.compare("fit_content") == 0) {
775             SelectModel::GetInstance()->SetOptionWidthFitTrigger(false);
776         } else if (modeFlag.compare("fit_trigger") == 0) {
777             SelectModel::GetInstance()->SetOptionWidthFitTrigger(true);
778         } else if (IsPercentStr(modeFlag)) {
779             LOGE("OptionWidth is percentage");
780             return;
781         } else {
782             ParseJsDimensionVpNG(info[0], value);
783             if (value.IsNegative()) {
784                 value.Reset();
785             }
786             SelectModel::GetInstance()->SetOptionWidth(value);
787         }
788     } else {
789         ParseJsDimensionVpNG(info[0], value);
790         if (value.IsNegative()) {
791             value.Reset();
792         }
793         SelectModel::GetInstance()->SetOptionWidth(value);
794     }
795 }
796 
SetOptionHeight(const JSCallbackInfo & info)797 void JSSelect::SetOptionHeight(const JSCallbackInfo& info)
798 {
799     CalcDimension value;
800     if (info[0]->IsUndefined()) {
801         LOGE("OptionHeight is undefined");
802         return;
803     } else if (info[0]->IsNull()) {
804         LOGE("OptionHeight is null");
805         return;
806     } else if (info[0]->IsString()) {
807         std::string modeFlag = info[0]->ToString();
808         if (IsPercentStr(modeFlag)) {
809             LOGE("OptionHeight is a percentage");
810             return;
811         } else {
812             ParseJsDimensionVpNG(info[0], value);
813             if (value.IsNegative()) {
814                 LOGE("OptionHeight is negative");
815                 return;
816             } else if (NEAR_ZERO(value.Value())) {
817                 LOGE("OptionHeight is zero");
818                 return;
819             }
820             SelectModel::GetInstance()->SetOptionHeight(value);
821         }
822     } else {
823         ParseJsDimensionVpNG(info[0], value);
824         if (value.IsNegative()) {
825             LOGE("OptionHeight is negative");
826             return;
827         } else if (NEAR_ZERO(value.Value())) {
828             LOGE("OptionHeight is zero");
829             return;
830         }
831         SelectModel::GetInstance()->SetOptionHeight(value);
832     }
833 }
834 
SetOptionWidthFitTrigger(const JSCallbackInfo & info)835 void JSSelect::SetOptionWidthFitTrigger(const JSCallbackInfo& info)
836 {
837     bool isFitTrigger = false;
838     if (info[0]->IsBoolean()) {
839         isFitTrigger = info[0]->ToBoolean();
840     }
841 
842     SelectModel::GetInstance()->SetOptionWidthFitTrigger(isFitTrigger);
843 }
844 
SetMenuBackgroundColor(const JSCallbackInfo & info)845 void JSSelect::SetMenuBackgroundColor(const JSCallbackInfo& info)
846 {
847     if (info.Length() < 1) {
848         return;
849     }
850     Color menuBackgroundColor;
851     if (!ParseJsColor(info[0], menuBackgroundColor)) {
852         if (info[0]->IsNull() || info[0]->IsUndefined()) {
853             menuBackgroundColor = Color::TRANSPARENT;
854         } else {
855             return;
856         }
857     }
858 
859     SelectModel::GetInstance()->SetMenuBackgroundColor(menuBackgroundColor);
860 }
861 
SetMenuBackgroundBlurStyle(const JSCallbackInfo & info)862 void JSSelect::SetMenuBackgroundBlurStyle(const JSCallbackInfo& info)
863 {
864     if (info.Length() < 1) {
865         return;
866     }
867 
868     BlurStyleOption styleOption;
869     if (info[0]->IsNumber()) {
870         auto blurStyle = info[0]->ToNumber<int32_t>();
871         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
872             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
873             styleOption.blurStyle = static_cast<BlurStyle>(blurStyle);
874             SelectModel::GetInstance()->SetMenuBackgroundBlurStyle(styleOption);
875         }
876     }
877 }
878 } // namespace OHOS::Ace::Framework
879