• 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_indexer.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/log/ace_scoring_log.h"
20 #include "base/utils/utils.h"
21 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
22 #include "bridge/declarative_frontend/jsview/js_scroller.h"
23 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
24 #include "bridge/declarative_frontend/jsview/models/indexer_model_impl.h"
25 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_indexer_theme.h"
26 #include "core/common/resource/resource_object.h"
27 #include "core/components/common/layout/constants.h"
28 #include "core/components/common/properties/decoration.h"
29 #include "core/components/common/properties/text_style.h"
30 #include "core/components/indexer/indexer_theme.h"
31 #include "core/components_ng/pattern/indexer/indexer_model_ng.h"
32 
33 namespace OHOS::Ace {
34 std::unique_ptr<IndexerModel> IndexerModel::instance_ = nullptr;
35 std::mutex IndexerModel::mutex_;
GetInstance()36 IndexerModel* IndexerModel::GetInstance()
37 {
38     if (!instance_) {
39         std::lock_guard<std::mutex> lock(mutex_);
40         if (!instance_) {
41 #ifdef NG_BUILD
42             instance_.reset(new NG::IndexerModelNG());
43 #else
44             if (Container::IsCurrentUseNewPipeline()) {
45                 instance_.reset(new NG::IndexerModelNG());
46             } else {
47                 instance_.reset(new Framework::IndexerModelImpl());
48             }
49 #endif
50         }
51     }
52     return instance_.get();
53 }
54 } // namespace OHOS::Ace
55 
56 namespace OHOS::Ace::Framework {
57 namespace {
58 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
59 const std::vector<V2::AlignStyle> ALIGN_STYLE = { V2::AlignStyle::LEFT, V2::AlignStyle::RIGHT, V2::AlignStyle::START,
60     V2::AlignStyle::END };
61 const std::vector<NG::AlignStyle> NG_ALIGN_STYLE = { NG::AlignStyle::LEFT, NG::AlignStyle::RIGHT, NG::AlignStyle::START,
62     NG::AlignStyle::END };
63 constexpr Dimension DEFAULT_ITEM_SIZE = 16.0_vp;
64 constexpr double ZERO_RADIUS = 0.0;
65 constexpr double POPUP_ITEM_DEFAULT_RADIUS = 24.0;
66 constexpr double ITEM_DEFAULT_RADIUS = 8.0;
67 constexpr double RADIUS_OFFSET = 4.0;
68 }; // namespace
69 
ParseIndexerSelectedObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal,bool isMethodProp=false)70 void JSIndexer::ParseIndexerSelectedObject(
71     const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal, bool isMethodProp = false)
72 {
73     CHECK_NULL_VOID(changeEventVal->IsFunction());
74     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
75     auto changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const int32_t selected) {
76         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
77         ACE_SCORING_EVENT("Indexer.SelectedChangeEvent");
78         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(selected));
79         func->ExecuteJS(1, &newJSVal);
80     };
81 
82     if (isMethodProp) {
83         IndexerModel::GetInstance()->SetChangeEvent(changeEvent);
84     } else {
85         IndexerModel::GetInstance()->SetCreatChangeEvent(changeEvent);
86     }
87 }
88 
CreateArc(const JSCallbackInfo & args)89 void JSIndexer::CreateArc(const JSCallbackInfo& args)
90 {
91     Create(args, true);
92 }
93 
Create(const JSCallbackInfo & args)94 void JSIndexer::Create(const JSCallbackInfo& args)
95 {
96     Create(args, false);
97 }
98 
Create(const JSCallbackInfo & args,bool isArc)99 void JSIndexer::Create(const JSCallbackInfo& args, bool isArc)
100 {
101     if (args.Length() < 1 || !args[0]->IsObject()) {
102         return;
103     }
104     size_t length = 0;
105     int32_t selectedVal = 0;
106     std::vector<std::string> indexerArray;
107     JSRef<JSObject> paramObj = JSRef<JSObject>::Cast(args[0]);
108     JSRef<JSVal> arrayVal = paramObj->GetProperty("arrayValue");
109     if (arrayVal->IsArray()) {
110         JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(arrayVal);
111         length = jsArray->Length();
112         for (size_t i = 0; i < length; i++) {
113             auto value = jsArray->GetValueAt(i);
114             if (value->IsString()) {
115                 indexerArray.emplace_back(value->ToString());
116             }
117         }
118     }
119 
120     JSRef<JSVal> selectedProperty = paramObj->GetProperty("selected");
121     if (selectedProperty->IsNumber()) {
122         selectedVal = selectedProperty->ToNumber<int32_t>();
123         IndexerModel::GetInstance()->Create(indexerArray, selectedVal, isArc);
124         JSIndexerTheme::ApplyTheme();
125         JSRef<JSVal> changeEventVal = paramObj->GetProperty("$selected");
126         ParseIndexerSelectedObject(args, changeEventVal);
127     } else if (!isArc && length > 0 && selectedProperty->IsObject()) {
128         JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(selectedProperty);
129         auto selectedValueProperty = selectedObj->GetProperty("value");
130         if (selectedValueProperty->IsNumber()) {
131             selectedVal = selectedValueProperty->ToNumber<int32_t>();
132         }
133         IndexerModel::GetInstance()->Create(indexerArray, selectedVal, isArc);
134         JSIndexerTheme::ApplyTheme();
135         JSRef<JSVal> changeEventVal = selectedObj->GetProperty("changeEvent");
136         if (!changeEventVal.IsEmpty()) {
137             if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
138                 ParseIndexerSelectedObject(args, changeEventVal);
139             }
140             return;
141         }
142 
143         args.ReturnSelf();
144     } else {
145         IndexerModel::GetInstance()->Create(indexerArray, selectedVal, isArc);
146         JSIndexerTheme::ApplyTheme();
147     }
148 }
149 
SetSelectedColor(const JSCallbackInfo & args)150 void JSIndexer::SetSelectedColor(const JSCallbackInfo& args)
151 {
152     if (args.Length() < 1) {
153         return;
154     }
155     std::optional<Color> colorOpt;
156     Color selectedColor;
157     RefPtr<ResourceObject> resObj;
158     bool setByUser = false;
159     if (ParseJsColor(args[0], selectedColor, resObj)) {
160         colorOpt = selectedColor;
161         setByUser = true;
162     }
163     IndexerModel::GetInstance()->SetSelectedColor(colorOpt);
164     if (SystemProperties::ConfigChangePerform()) {
165         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::SELECTED_COLOR, resObj);
166         IndexerModel::GetInstance()->SetSelectedColorByUser(setByUser);
167     }
168 }
169 
SetColor(const JSCallbackInfo & args)170 void JSIndexer::SetColor(const JSCallbackInfo& args)
171 {
172     if (args.Length() < 1) {
173         return;
174     }
175     std::optional<Color> colorOpt;
176     Color color;
177     RefPtr<ResourceObject> resObj;
178     bool setByUser = false;
179     if (ParseJsColor(args[0], color, resObj)) {
180         colorOpt = color;
181         setByUser = true;
182     }
183     IndexerModel::GetInstance()->SetColor(colorOpt);
184     if (SystemProperties::ConfigChangePerform()) {
185         IndexerModel::GetInstance()->SetColorByUser(setByUser);
186         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::COLOR, resObj);
187     }
188 }
189 
SetPopupColor(const JSCallbackInfo & args)190 void JSIndexer::SetPopupColor(const JSCallbackInfo& args)
191 {
192     if (args.Length() < 1) {
193         return;
194     }
195     std::optional<Color> colorOpt;
196     Color popupColor;
197     RefPtr<ResourceObject> resObj;
198     bool setByUser = false;
199     if (ParseJsColor(args[0], popupColor, resObj)) {
200         colorOpt = popupColor;
201         setByUser = true;
202     }
203     IndexerModel::GetInstance()->SetPopupColor(colorOpt);
204     if (SystemProperties::ConfigChangePerform()) {
205         IndexerModel::GetInstance()->SetPopupColorByUser(setByUser);
206         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_COLOR, resObj);
207     }
208 }
209 
SetSelectedBackgroundColor(const JSCallbackInfo & args)210 void JSIndexer::SetSelectedBackgroundColor(const JSCallbackInfo& args)
211 {
212     if (args.Length() < 1) {
213         return;
214     }
215     std::optional<Color> colorOpt;
216     Color selectedBackgroundColor;
217     RefPtr<ResourceObject> resObj;
218     bool setByUser = false;
219     if (ParseJsColor(args[0], selectedBackgroundColor, resObj)) {
220         colorOpt = selectedBackgroundColor;
221         setByUser = true;
222     }
223     IndexerModel::GetInstance()->SetSelectedBackgroundColor(colorOpt);
224     if (SystemProperties::ConfigChangePerform()) {
225         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::SELECTED_BACKGROUND_COLOR, resObj);
226         IndexerModel::GetInstance()->SetSelectedBGColorByUser(setByUser);
227     }
228 }
229 
SetPopupBackground(const JSCallbackInfo & args)230 void JSIndexer::SetPopupBackground(const JSCallbackInfo& args)
231 {
232     if (args.Length() < 1) {
233         return;
234     }
235     std::optional<Color> colorOpt;
236     Color popupBackground;
237     RefPtr<ResourceObject> resObj;
238     bool setByUser = false;
239     if (ParseJsColor(args[0], popupBackground, resObj)) {
240         colorOpt = popupBackground;
241         setByUser = true;
242     }
243     IndexerModel::GetInstance()->SetPopupBackground(colorOpt);
244     if (SystemProperties::ConfigChangePerform()) {
245         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_BACKGROUND, resObj);
246         IndexerModel::GetInstance()->SetPopupBackgroundColorByUser(setByUser);
247     }
248 }
249 
SetUsingPopup(bool state)250 void JSIndexer::SetUsingPopup(bool state)
251 {
252     IndexerModel::GetInstance()->SetUsingPopup(state);
253 }
254 
SetSelectedFont(const JSCallbackInfo & args)255 void JSIndexer::SetSelectedFont(const JSCallbackInfo& args)
256 {
257     if (args.Length() < 1) {
258         return;
259     }
260     IndexerTextStyle textStyle;
261     if (args[0]->IsObject()) {
262         GetFontContent(args, textStyle);
263     }
264     IndexerModel::GetInstance()->SetSelectedFont(
265         textStyle.fontSize, textStyle.fontWeight, textStyle.fontFamily, textStyle.fontStyle);
266     if (SystemProperties::ConfigChangePerform()) {
267         IndexerModel::GetInstance()->CreateWithResourceObj(
268             IndexerJsResourceType::SELECTED_FONT_SIZE, textStyle.fontSizeResObj);
269         IndexerModel::GetInstance()->CreateWithResourceObj(
270             IndexerJsResourceType::SELECTED_FONT_FAMILY, textStyle.fontFamilyResObj);
271     }
272 }
273 
SetPopupFont(const JSCallbackInfo & args)274 void JSIndexer::SetPopupFont(const JSCallbackInfo& args)
275 {
276     if (args.Length() < 1) {
277         return;
278     }
279     IndexerTextStyle textStyle;
280     if (args[0]->IsObject()) {
281         GetFontContent(args, textStyle);
282     }
283     IndexerModel::GetInstance()->SetPopupFont(
284         textStyle.fontSize, textStyle.fontWeight, textStyle.fontFamily, textStyle.fontStyle);
285     if (SystemProperties::ConfigChangePerform()) {
286         IndexerModel::GetInstance()->CreateWithResourceObj(
287             IndexerJsResourceType::POPUP_FONT_SIZE, textStyle.fontSizeResObj);
288         IndexerModel::GetInstance()->CreateWithResourceObj(
289             IndexerJsResourceType::POPUP_FONT_FAMILY, textStyle.fontFamilyResObj);
290     }
291 }
292 
SetFont(const JSCallbackInfo & args)293 void JSIndexer::SetFont(const JSCallbackInfo& args)
294 {
295     if (args.Length() < 1) {
296         return;
297     }
298     IndexerTextStyle textStyle;
299     if (args[0]->IsObject()) {
300          GetFontContent(args, textStyle);
301     }
302     IndexerModel::GetInstance()->SetFont(
303         textStyle.fontSize, textStyle.fontWeight, textStyle.fontFamily, textStyle.fontStyle);
304     if (SystemProperties::ConfigChangePerform()) {
305         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::FONT_SIZE, textStyle.fontSizeResObj);
306         IndexerModel::GetInstance()->CreateWithResourceObj(
307             IndexerJsResourceType::FONT_FAMILY, textStyle.fontFamilyResObj);
308     }
309 }
310 
JsOnSelected(const JSCallbackInfo & args)311 void JSIndexer::JsOnSelected(const JSCallbackInfo& args)
312 {
313     if (args[0]->IsFunction()) {
314         auto onSelected = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
315                               const int32_t selected) {
316             JAVASCRIPT_EXECUTION_SCOPE(execCtx);
317             auto params = ConvertToJSValues(selected);
318             func->Call(JSRef<JSObject>(), params.size(), params.data());
319         };
320         IndexerModel::GetInstance()->SetOnSelected(onSelected);
321     }
322 }
323 
JsOnRequestPopupData(const JSCallbackInfo & args)324 void JSIndexer::JsOnRequestPopupData(const JSCallbackInfo& args)
325 {
326     if (args[0]->IsFunction()) {
327         auto requestPopupData = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
328                                     const int32_t selected) {
329             std::vector<std::string> popupData;
330             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, popupData);
331             auto params = ConvertToJSValues(selected);
332             JSRef<JSArray> result = func->Call(JSRef<JSObject>(), params.size(), params.data());
333             if (result.IsEmpty()) {
334                 return popupData;
335             }
336 
337             if (!result->IsArray()) {
338                 return popupData;
339             }
340 
341             for (size_t i = 0; i < result->Length(); i++) {
342                 if (result->GetValueAt(i)->IsString()) {
343                     auto item = result->GetValueAt(i);
344                     popupData.emplace_back(item->ToString());
345                 }
346             }
347             return popupData;
348         };
349         IndexerModel::GetInstance()->SetOnRequestPopupData(requestPopupData);
350     }
351 }
352 
JsOnPopupSelected(const JSCallbackInfo & args)353 void JSIndexer::JsOnPopupSelected(const JSCallbackInfo& args)
354 {
355     if (args[0]->IsFunction()) {
356         auto onPopupSelected = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
357                                    const int32_t selected) {
358             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
359             auto params = ConvertToJSValues(selected);
360             func->Call(JSRef<JSObject>(), params.size(), params.data());
361         };
362         IndexerModel::GetInstance()->SetOnPopupSelected(onPopupSelected);
363     }
364 }
365 
GetFontContent(const JSCallbackInfo & args,IndexerTextStyle & textStyle)366 void JSIndexer::GetFontContent(const JSCallbackInfo& args, IndexerTextStyle& textStyle)
367 {
368     JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
369     JSRef<JSVal> size = obj->GetProperty("size");
370     CalcDimension fontSizeData;
371     if (ParseJsDimensionFp(size, fontSizeData, textStyle.fontSizeResObj) && !fontSizeData.IsNegative() &&
372         fontSizeData.Unit() != DimensionUnit::PERCENT) {
373         textStyle.fontSize = fontSizeData;
374     }
375 
376     JSRef<JSVal> weight = obj->GetProperty("weight");
377     if (weight->IsString() || weight->IsNumber()) {
378         textStyle.fontWeight = ConvertStrToFontWeight(weight->ToString());
379     }
380 
381     JSRef<JSVal> family = obj->GetProperty("family");
382     std::vector<std::string> fontFamilies;
383     if (ParseJsFontFamilies(family, fontFamilies, textStyle.fontFamilyResObj)) {
384         textStyle.fontFamily = fontFamilies;
385     }
386 
387     JSRef<JSVal> style = obj->GetProperty("style");
388     if (style->IsNumber()) {
389         int32_t value = style->ToNumber<int32_t>();
390         if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
391             textStyle.fontStyle = FONT_STYLES[value];
392         }
393     }
394 }
395 
SetItemSize(const JSCallbackInfo & args)396 void JSIndexer::SetItemSize(const JSCallbackInfo& args)
397 {
398     if (args.Length() < 1) {
399         return;
400     }
401     CalcDimension itemSize;
402     if (ParseJsDimensionVp(args[0], itemSize) && GreatNotEqual(itemSize.Value(), 0.0) &&
403         itemSize.Unit() != DimensionUnit::PERCENT) {
404         IndexerModel::GetInstance()->SetItemSize(itemSize);
405         return;
406     }
407     IndexerModel::GetInstance()->SetItemSize(DEFAULT_ITEM_SIZE);
408 }
409 
SetAlignStyle(const JSCallbackInfo & args)410 void JSIndexer::SetAlignStyle(const JSCallbackInfo& args)
411 {
412     if (args.Length() < 1) {
413         return;
414     }
415     int32_t value = Container::IsCurrentUseNewPipeline() ? static_cast<int32_t>(NG::AlignStyle::END)
416                                                          : static_cast<int32_t>(V2::AlignStyle::END);
417     auto alignValue = -1;
418     if (args[0]->IsNumber()) {
419         alignValue = args[0]->ToNumber<int32_t>();
420     }
421     if (alignValue >= 0 && alignValue < static_cast<int32_t>(ALIGN_STYLE.size())) {
422         value = alignValue;
423     }
424     IndexerModel::GetInstance()->SetAlignStyle(value);
425     CalcDimension popupHorizontalSpace(-1.0);
426     RefPtr<ResourceObject> resObj;
427     if (args.Length() > 1) {
428         ParseJsDimensionVp(args[1], popupHorizontalSpace, resObj);
429     }
430     if (SystemProperties::ConfigChangePerform()) {
431         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::ALIGN_OFFSET, resObj);
432     }
433     IndexerModel::GetInstance()->SetPopupHorizontalSpace(popupHorizontalSpace);
434 }
435 
SetSelected(const JSCallbackInfo & args)436 void JSIndexer::SetSelected(const JSCallbackInfo& args)
437 {
438     if (args.Length() < 1) {
439         return;
440     }
441     int32_t selected = 0;
442     auto selectedVal = args[0];
443     JSRef<JSVal> changeEventVal;
444     if (selectedVal->IsObject()) {
445         JSRef<JSObject> obj = JSRef<JSObject>::Cast(selectedVal);
446         selectedVal = obj->GetProperty("value");
447         changeEventVal = obj->GetProperty("$value");
448     } else if (args.Length() > 1) {
449         changeEventVal = args[1];
450     }
451     if (ParseJsInteger<int32_t>(selectedVal, selected)) {
452         IndexerModel::GetInstance()->SetSelected(selected);
453     }
454     ParseIndexerSelectedObject(args, changeEventVal, true);
455 }
456 
SetPopupPosition(const JSCallbackInfo & args)457 void JSIndexer::SetPopupPosition(const JSCallbackInfo& args)
458 {
459     std::optional<Dimension> xOpt;
460     std::optional<Dimension> yOpt;
461     if (args[0]->IsObject()) {
462         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
463         CalcDimension x;
464         CalcDimension y;
465         RefPtr<ResourceObject> resObjX;
466         RefPtr<ResourceObject> resObjY;
467         JSRef<JSVal> xVal = obj->GetProperty("x");
468         JSRef<JSVal> yVal = obj->GetProperty("y");
469         if ((xVal->IsString() && StringUtils::StringToCalcDimensionNG(xVal->ToString(), x, false)) ||
470             (!xVal->IsString() && JSViewAbstract::ParseJsDimensionVp(xVal, x, resObjX))) {
471             xOpt = x;
472         }
473         if ((yVal->IsString() && StringUtils::StringToCalcDimensionNG(yVal->ToString(), y, false)) ||
474             (!yVal->IsString() && JSViewAbstract::ParseJsDimensionVp(yVal, y, resObjY))) {
475             yOpt = y;
476         }
477         if (SystemProperties::ConfigChangePerform()) {
478             IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_POSITION_X, resObjX);
479             IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_POSITION_Y, resObjY);
480         }
481     } else if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
482         return;
483     }
484     IndexerModel::GetInstance()->SetPopupPositionX(xOpt);
485     IndexerModel::GetInstance()->SetPopupPositionY(yOpt);
486 }
487 
SetPopupSelectedColor(const JSCallbackInfo & args)488 void JSIndexer::SetPopupSelectedColor(const JSCallbackInfo& args)
489 {
490     if (args.Length() < 1) {
491         return;
492     }
493     std::optional<Color> colorOpt;
494     Color popupSelectedColor;
495     RefPtr<ResourceObject> resObj;
496     bool setByUser = false;
497     if (ParseJsColor(args[0], popupSelectedColor, resObj)) {
498         colorOpt = popupSelectedColor;
499         setByUser = true;
500     }
501     IndexerModel::GetInstance()->SetPopupSelectedColor(colorOpt);
502     if (SystemProperties::ConfigChangePerform()) {
503         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_SELECTED_COLOR, resObj);
504         IndexerModel::GetInstance()->SetPopupSelectedColorByUser(setByUser);
505     }
506 }
507 
SetPopupUnselectedColor(const JSCallbackInfo & args)508 void JSIndexer::SetPopupUnselectedColor(const JSCallbackInfo& args)
509 {
510     if (args.Length() < 1) {
511         return;
512     }
513     std::optional<Color> colorOpt;
514     Color popupUnselectedColor;
515     RefPtr<ResourceObject> resObj;
516     bool setByUser = false;
517     if (ParseJsColor(args[0], popupUnselectedColor, resObj)) {
518         colorOpt = popupUnselectedColor;
519         setByUser = true;
520     }
521     IndexerModel::GetInstance()->SetPopupUnselectedColor(colorOpt);
522     if (SystemProperties::ConfigChangePerform()) {
523         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_UNSELECTED_COLOR, resObj);
524         IndexerModel::GetInstance()->SetPopupUnselectedColorByUser(setByUser);
525     }
526 }
527 
SetPopupItemFont(const JSCallbackInfo & args)528 void JSIndexer::SetPopupItemFont(const JSCallbackInfo& args)
529 {
530     CalcDimension fontSize;
531     std::string weight;
532     RefPtr<ResourceObject> resObj;
533     if (args[0]->IsObject()) {
534         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
535         JSRef<JSVal> size = obj->GetProperty("size");
536         if (!size->IsNull()) {
537             CalcDimension fontSizeData;
538             if (ParseJsDimensionFp(size, fontSizeData, resObj) && !fontSizeData.IsNegative() &&
539                 fontSizeData.Unit() != DimensionUnit::PERCENT) {
540                 fontSize = fontSizeData;
541             }
542         }
543 
544         auto jsWeight = obj->GetProperty("weight");
545         if (!jsWeight->IsNull()) {
546             if (jsWeight->IsNumber()) {
547                 weight = std::to_string(jsWeight->ToNumber<int32_t>());
548             } else {
549                 ParseJsString(jsWeight, weight);
550             }
551         }
552     }
553     IndexerModel::GetInstance()->SetFontSize(fontSize);
554     IndexerModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(weight, FontWeight::MEDIUM));
555     if (SystemProperties::ConfigChangePerform()) {
556         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_ITEM_FONT_SIZE, resObj);
557     }
558 }
559 
SetPopupItemBackgroundColor(const JSCallbackInfo & args)560 void JSIndexer::SetPopupItemBackgroundColor(const JSCallbackInfo& args)
561 {
562     if (args.Length() < 1) {
563         return;
564     }
565     std::optional<Color> colorOpt;
566     Color popupItemBackgroundColor;
567     RefPtr<ResourceObject> resObj;
568     bool setByUser = false;
569     if (ParseJsColor(args[0], popupItemBackgroundColor, resObj)) {
570         colorOpt = popupItemBackgroundColor;
571         setByUser = true;
572     }
573     IndexerModel::GetInstance()->SetPopupItemBackground(colorOpt);
574     if (SystemProperties::ConfigChangePerform()) {
575         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_ITEM_BACKGROUND_COLOR, resObj);
576         IndexerModel::GetInstance()->SetPopupItemBackgroundColorByUser(setByUser);
577     }
578 }
579 
PaseColor(const JSCallbackInfo & args)580 std::optional<Color> JSIndexer::PaseColor(const JSCallbackInfo& args)
581 {
582     std::optional<Color> colorOpt;
583     Color color;
584     if (ParseJsColor(args[0], color)) {
585         colorOpt = color;
586     }
587     return colorOpt;
588 }
589 
SetAutoCollapse(const JSCallbackInfo & args)590 void JSIndexer::SetAutoCollapse(const JSCallbackInfo& args)
591 {
592     bool state = true;
593     if (args[0]->IsBoolean()) {
594         state = args[0]->ToBoolean();
595     }
596     IndexerModel::GetInstance()->SetAutoCollapse(state);
597 }
598 
SetPopupItemBorderRadius(const JSCallbackInfo & args)599 void JSIndexer::SetPopupItemBorderRadius(const JSCallbackInfo& args)
600 {
601     auto radius = Dimension(ZERO_RADIUS, DimensionUnit::VP);
602     auto popupRadius = Dimension(ZERO_RADIUS, DimensionUnit::VP);
603     if (args.Length() > 0 && args[0]->IsNumber()) {
604         auto radiusValue = args[0]->ToNumber<double>();
605         if (radiusValue >= 0) {
606             radius.SetValue(radiusValue);
607             radius.SetUnit(DimensionUnit::VP);
608             popupRadius.SetValue(radiusValue + RADIUS_OFFSET);
609             popupRadius.SetUnit(DimensionUnit::VP);
610         }
611     } else {
612         radius.SetValue(POPUP_ITEM_DEFAULT_RADIUS);
613         radius.SetUnit(DimensionUnit::VP);
614         popupRadius.SetValue(radius.Value() + RADIUS_OFFSET);
615         popupRadius.SetUnit(DimensionUnit::VP);
616     }
617     IndexerModel::GetInstance()->SetPopupItemBorderRadius(radius);
618     IndexerModel::GetInstance()->SetPopupBorderRadius(popupRadius);
619 }
620 
SetItemBorderRadius(const JSCallbackInfo & args)621 void JSIndexer::SetItemBorderRadius(const JSCallbackInfo& args)
622 {
623     auto radius = Dimension(ZERO_RADIUS, DimensionUnit::VP);
624     auto indexerRadius = Dimension(ZERO_RADIUS, DimensionUnit::VP);
625     if (args.Length() > 0 && args[0]->IsNumber()) {
626         auto radiusValue = args[0]->ToNumber<double>();
627         if (radiusValue >= 0) {
628             radius.SetValue(radiusValue);
629             radius.SetUnit(DimensionUnit::VP);
630             indexerRadius.SetValue(radiusValue + RADIUS_OFFSET);
631             indexerRadius.SetUnit(DimensionUnit::VP);
632         }
633     } else {
634         radius.SetValue(ITEM_DEFAULT_RADIUS);
635         radius.SetUnit(DimensionUnit::VP);
636         indexerRadius.SetValue(radius.Value() + RADIUS_OFFSET);
637         indexerRadius.SetUnit(DimensionUnit::VP);
638     }
639     IndexerModel::GetInstance()->SetItemBorderRadius(radius);
640     IndexerModel::GetInstance()->SetIndexerBorderRadius(indexerRadius);
641 }
642 
SetPopupBackgroundBlurStyle(const JSCallbackInfo & args)643 void JSIndexer::SetPopupBackgroundBlurStyle(const JSCallbackInfo& args)
644 {
645     if (args.Length() < 1) {
646         return;
647     }
648 
649     BlurStyleOption styleOption;
650     if (args[0]->IsNumber()) {
651         auto blurStyle = args[0]->ToNumber<int32_t>();
652         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
653             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
654             styleOption.blurStyle = static_cast<BlurStyle>(blurStyle);
655         } else {
656             styleOption.blurStyle = BlurStyle::COMPONENT_REGULAR;
657         }
658     } else {
659         styleOption.blurStyle = BlurStyle::COMPONENT_REGULAR;
660     }
661     IndexerModel::GetInstance()->SetPopupBackgroundBlurStyle(styleOption);
662 }
663 
SetPopupTitleBackground(const JSCallbackInfo & args)664 void JSIndexer::SetPopupTitleBackground(const JSCallbackInfo& args)
665 {
666     if (args.Length() < 1) {
667         return;
668     }
669     std::optional<Color> colorOpt;
670     Color popupTitleBackground;
671     RefPtr<ResourceObject> resObj;
672     bool setByUser = false;
673     if (ParseJsColor(args[0], popupTitleBackground, resObj)) {
674         colorOpt = popupTitleBackground;
675         setByUser = true;
676     }
677     IndexerModel::GetInstance()->SetPopupTitleBackground(colorOpt);
678     if (SystemProperties::ConfigChangePerform()) {
679         IndexerModel::GetInstance()->CreateWithResourceObj(IndexerJsResourceType::POPUP_TITLE_BACKGROUND, resObj);
680         IndexerModel::GetInstance()->SetPopupTitleBackgroundByUser(setByUser);
681     }
682 }
683 
SetWidth(const JSCallbackInfo & args)684 void JSIndexer::SetWidth(const JSCallbackInfo& args)
685 {
686     JSViewAbstract::JsWidth(args);
687     if (args[0]->IsString() && args[0]->ToString() == "auto") {
688         IndexerModel::GetInstance()->SetAdaptiveWidth(true);
689     } else {
690         IndexerModel::GetInstance()->SetAdaptiveWidth(false);
691     }
692 }
693 
SetEnableHapticFeedback(const JSCallbackInfo & args)694 void JSIndexer::SetEnableHapticFeedback(const JSCallbackInfo& args)
695 {
696     bool state = true;
697     if (args.Length() > 0 && args[0]->IsBoolean()) {
698         state = args[0]->ToBoolean();
699     }
700     IndexerModel::GetInstance()->SetEnableHapticFeedback(state);
701 }
702 
JSBind(BindingTarget globalObj)703 void JSIndexer::JSBind(BindingTarget globalObj)
704 {
705     MethodOptions opt = MethodOptions::NONE;
706     JSClass<JSIndexer>::Declare("AlphabetIndexer");
707     JSClass<JSIndexer>::StaticMethod("create", &JSIndexer::Create);
708     JSClass<JSIndexer>::StaticMethod("createArc", &JSIndexer::CreateArc);
709     // API7 onSelected deprecated
710     JSClass<JSIndexer>::StaticMethod("onSelected", &JSIndexer::JsOnSelected);
711     JSClass<JSIndexer>::StaticMethod("onSelect", &JSIndexer::JsOnSelected);
712     JSClass<JSIndexer>::StaticMethod("color", &JSIndexer::SetColor, opt);
713     JSClass<JSIndexer>::StaticMethod("selectedColor", &JSIndexer::SetSelectedColor, opt);
714     JSClass<JSIndexer>::StaticMethod("popupColor", &JSIndexer::SetPopupColor, opt);
715     JSClass<JSIndexer>::StaticMethod("selectedBackgroundColor", &JSIndexer::SetSelectedBackgroundColor, opt);
716     JSClass<JSIndexer>::StaticMethod("popupBackground", &JSIndexer::SetPopupBackground, opt);
717     JSClass<JSIndexer>::StaticMethod("usingPopup", &JSIndexer::SetUsingPopup, opt);
718     JSClass<JSIndexer>::StaticMethod("selectedFont", &JSIndexer::SetSelectedFont);
719     JSClass<JSIndexer>::StaticMethod("font", &JSIndexer::SetFont);
720     JSClass<JSIndexer>::StaticMethod("popupFont", &JSIndexer::SetPopupFont);
721     JSClass<JSIndexer>::StaticMethod("itemSize", &JSIndexer::SetItemSize, opt);
722     JSClass<JSIndexer>::StaticMethod("alignStyle", &JSIndexer::SetAlignStyle, opt);
723     JSClass<JSIndexer>::StaticMethod("onRequestPopupData", &JSIndexer::JsOnRequestPopupData, opt);
724     JSClass<JSIndexer>::StaticMethod("selected", &JSIndexer::SetSelected, opt);
725     JSClass<JSIndexer>::StaticMethod("popupPosition", &JSIndexer::SetPopupPosition, opt);
726     JSClass<JSIndexer>::StaticMethod("popupSelectedColor", &JSIndexer::SetPopupSelectedColor, opt);
727     JSClass<JSIndexer>::StaticMethod("popupUnselectedColor", &JSIndexer::SetPopupUnselectedColor, opt);
728     JSClass<JSIndexer>::StaticMethod("popupItemFont", &JSIndexer::SetPopupItemFont);
729     JSClass<JSIndexer>::StaticMethod("popupItemBackgroundColor", &JSIndexer::SetPopupItemBackgroundColor, opt);
730     JSClass<JSIndexer>::StaticMethod("autoCollapse", &JSIndexer::SetAutoCollapse, opt);
731     JSClass<JSIndexer>::StaticMethod("popupItemBorderRadius", &JSIndexer::SetPopupItemBorderRadius);
732     JSClass<JSIndexer>::StaticMethod("itemBorderRadius", &JSIndexer::SetItemBorderRadius);
733     JSClass<JSIndexer>::StaticMethod("popupBackgroundBlurStyle", &JSIndexer::SetPopupBackgroundBlurStyle);
734     JSClass<JSIndexer>::StaticMethod("popupTitleBackground", &JSIndexer::SetPopupTitleBackground, opt);
735     JSClass<JSIndexer>::StaticMethod("width", &JSIndexer::SetWidth);
736     JSClass<JSIndexer>::StaticMethod("enableHapticFeedback", &JSIndexer::SetEnableHapticFeedback, opt);
737     // keep compatible, need remove after
738     JSClass<JSIndexer>::StaticMethod("onPopupSelect", &JSIndexer::JsOnPopupSelected, opt);
739     JSClass<JSIndexer>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
740     JSClass<JSIndexer>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
741     JSClass<JSIndexer>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
742     JSClass<JSIndexer>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
743     JSClass<JSIndexer>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
744     JSClass<JSIndexer>::InheritAndBind<JSViewAbstract>(globalObj);
745 }
746 } // namespace OHOS::Ace::Framework
747