• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "frameworks/bridge/declarative_frontend/jsview/js_textfield.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <string>
21 #include <vector>
22 #include "base/utils/utf_helper.h"
23 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
24 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
25 
26 #include "base/geometry/dimension.h"
27 #include "base/log/ace_scoring_log.h"
28 #include "base/utils/utils.h"
29 #include "bridge/common/utils/utils.h"
30 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
31 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
32 #include "bridge/declarative_frontend/engine/functions/js_function.h"
33 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
34 #include "bridge/declarative_frontend/jsview/js_container_base.h"
35 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
36 #include "bridge/declarative_frontend/jsview/js_text_editable_controller.h"
37 #include "bridge/declarative_frontend/jsview/js_textarea.h"
38 #include "bridge/declarative_frontend/jsview/js_textinput.h"
39 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
40 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
41 #include "bridge/declarative_frontend/jsview/models/text_field_model_impl.h"
42 #include "core/common/container.h"
43 #include "core/common/ime/text_input_action.h"
44 #include "core/common/ime/text_input_type.h"
45 #include "core/components/common/layout/constants.h"
46 #include "core/components/common/properties/text_style_parser.h"
47 #include "core/components/text_field/textfield_theme.h"
48 #include "core/components_ng/base/view_abstract.h"
49 #include "core/components_ng/pattern/text_field/text_content_type.h"
50 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
51 #include "core/image/image_source_info.h"
52 #include "core/text/text_emoji_processor.h"
53 
54 namespace OHOS::Ace {
55 
56 std::unique_ptr<TextFieldModel> TextFieldModel::instance_ = nullptr;
57 std::mutex TextFieldModel::mutex_;
58 
GetInstance()59 TextFieldModel* TextFieldModel::GetInstance()
60 {
61 #ifdef NG_BUILD
62     static NG::TextFieldModelNG instance;
63     return &instance;
64 #else
65     if (Container::IsCurrentUseNewPipeline()) {
66         static NG::TextFieldModelNG instance;
67         return &instance;
68     } else {
69         static Framework::TextFieldModelImpl instance;
70         return &instance;
71     }
72 #endif
73 }
74 
75 } // namespace OHOS::Ace
76 
77 namespace OHOS::Ace::Framework {
78 
79 namespace {
80 
81 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY };
82 const std::vector<LineBreakStrategy> LINE_BREAK_STRATEGY_TYPES = { LineBreakStrategy::GREEDY,
83     LineBreakStrategy::HIGH_QUALITY, LineBreakStrategy::BALANCED };
84 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
85 const std::vector<std::string> INPUT_FONT_FAMILY_VALUE = { "sans-serif" };
86 const std::vector<WordBreak> WORD_BREAK_TYPES = { WordBreak::NORMAL, WordBreak::BREAK_ALL, WordBreak::BREAK_WORD,
87     WordBreak::HYPHENATION };
88 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
89     TextOverflow::MARQUEE, TextOverflow::DEFAULT };
90 const std::vector<EllipsisMode> ELLIPSIS_MODALS = { EllipsisMode::HEAD, EllipsisMode::MIDDLE, EllipsisMode::TAIL };
91 constexpr uint32_t MAX_LINES = 3;
92 constexpr uint32_t MINI_VAILD_VALUE = 1;
93 constexpr uint32_t MAX_VAILD_VALUE = 100;
94 constexpr uint32_t ILLEGAL_VALUE = 0;
95 constexpr uint32_t DEFAULT_MODE = -1;
96 constexpr uint32_t DEFAULT_OVERFLOW = 4;
97 const char* TOP_START_PROPERTY = "topStart";
98 const char* TOP_END_PROPERTY = "topEnd";
99 const char* BOTTOM_START_PROPERTY = "bottomStart";
100 const char* BOTTOM_END_PROPERTY = "bottomEnd";
101 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICY = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
102     TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
103 constexpr TextDecorationStyle DEFAULT_TEXT_DECORATION_STYLE = TextDecorationStyle::SOLID;
104 
ParseJsLengthMetrics(const JSRef<JSObject> & obj,CalcDimension & result)105 bool ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)
106 {
107     auto value = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::VALUE));
108     if (!value->IsNumber()) {
109         return false;
110     }
111     auto unit = DimensionUnit::VP;
112     auto jsUnit = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::UNIT));
113     if (jsUnit->IsNumber()) {
114         unit = static_cast<DimensionUnit>(jsUnit->ToNumber<int32_t>());
115     }
116     CalcDimension dimension(value->ToNumber<double>(), unit);
117     result = dimension;
118     return true;
119 }
120 } // namespace
121 
ParseTextFieldTextObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)122 void ParseTextFieldTextObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
123 {
124     CHECK_NULL_VOID(changeEventVal->IsFunction());
125 
126     JsEventCallback<void(const std::u16string&)> onChangeEvent(
127         info.GetExecutionContext(), JSRef<JSFunc>::Cast(changeEventVal));
128     TextFieldModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
129 }
130 
ParseTextProperty(const JSRef<JSVal> & textValue,std::optional<std::u16string> & value,std::u16string & text)131 void ParseTextProperty(const JSRef<JSVal>& textValue, std::optional<std::u16string>& value, std::u16string& text)
132 {
133     if (JSViewAbstract::ParseJsString(textValue, text)) {
134         value = text;
135     }
136     if (textValue->IsUndefined()) {
137         value = u"";
138     }
139 }
140 
CreateTextInput(const JSCallbackInfo & info)141 void JSTextField::CreateTextInput(const JSCallbackInfo& info)
142 {
143     std::optional<std::u16string> placeholderSrc;
144     std::optional<std::u16string> value;
145     JSTextEditableController* jsController = nullptr;
146     JSRef<JSVal> changeEventVal = JSRef<JSVal>::Make();
147     auto jsValue = info[0];
148     if (jsValue->IsObject()) {
149         auto paramObject = JSRef<JSObject>::Cast(jsValue);
150         std::u16string placeholder;
151         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
152             placeholderSrc = placeholder;
153         }
154         std::u16string text;
155         JSRef<JSVal> textValue = paramObject->GetProperty("text");
156         if (textValue->IsObject()) {
157             JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
158             changeEventVal = valueObj->GetProperty("changeEvent");
159             if (changeEventVal->IsFunction()) {
160                 textValue = valueObj->GetProperty("value");
161             }
162             value = u"";
163             if (ParseJsString(textValue, text)) {
164                 value = text;
165             }
166         } else if (paramObject->GetProperty("$text")->IsFunction()) {
167             changeEventVal = paramObject->GetProperty("$text");
168             value = u"";
169             if (ParseJsString(textValue, text)) {
170                 value = text;
171             }
172         } else if (paramObject->HasProperty("text")) {
173             ParseTextProperty(textValue, value, text);
174         }
175         auto controllerObj = paramObject->GetProperty("controller");
176         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
177             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
178         }
179     }
180     auto controller = TextFieldModel::GetInstance()->CreateTextInput(placeholderSrc, value);
181     if (jsController) {
182         jsController->SetController(controller);
183     }
184     if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
185         ParseTextFieldTextObject(info, changeEventVal);
186     }
187 
188     TextFieldModel::GetInstance()->SetFocusableAndFocusNode();
189 }
190 
CreateTextArea(const JSCallbackInfo & info)191 void JSTextField::CreateTextArea(const JSCallbackInfo& info)
192 {
193     std::optional<std::u16string> placeholderSrc;
194     std::optional<std::u16string> value;
195     JSTextEditableController* jsController = nullptr;
196     JSRef<JSVal> changeEventVal = JSRef<JSVal>::Make();
197     auto jsValue = info[0];
198     if (jsValue->IsObject()) {
199         auto paramObject = JSRef<JSObject>::Cast(jsValue);
200         std::u16string placeholder;
201         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
202             placeholderSrc = placeholder;
203         }
204         std::u16string text;
205         JSRef<JSVal> textValue = paramObject->GetProperty("text");
206         if (textValue->IsObject()) {
207             JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
208             changeEventVal = valueObj->GetProperty("changeEvent");
209             if (changeEventVal->IsFunction()) {
210                 textValue = valueObj->GetProperty("value");
211             }
212             if (ParseJsString(textValue, text)) {
213                 value = text;
214             }
215         } else if (paramObject->GetProperty("$text")->IsFunction()) {
216             changeEventVal = paramObject->GetProperty("$text");
217             if (ParseJsString(textValue, text)) {
218                 value = text;
219             }
220         } else if (paramObject->HasProperty("text")) {
221             ParseTextProperty(textValue, value, text);
222         }
223         auto controllerObj = paramObject->GetProperty("controller");
224         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
225             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
226         }
227     }
228     auto controller = TextFieldModel::GetInstance()->CreateTextArea(placeholderSrc, value);
229     if (jsController) {
230         jsController->SetController(controller);
231     }
232     if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
233         ParseTextFieldTextObject(info, changeEventVal);
234     }
235 
236     TextFieldModel::GetInstance()->SetFocusableAndFocusNode();
237 }
238 
SetType(const JSCallbackInfo & info)239 void JSTextField::SetType(const JSCallbackInfo& info)
240 {
241     if (info.Length() < 1) {
242         return;
243     }
244     auto jsValue = info[0];
245     if (jsValue->IsUndefined()) {
246         TextFieldModel::GetInstance()->SetType(TextInputType::UNSPECIFIED);
247         return;
248     }
249     if (!jsValue->IsNumber()) {
250         return;
251     }
252     TextInputType textInputType = CastToTextInputType(jsValue->ToNumber<int32_t>());
253     TextFieldModel::GetInstance()->SetType(textInputType);
254 }
255 
SetContentType(const JSCallbackInfo & info)256 void JSTextField::SetContentType(const JSCallbackInfo& info)
257 {
258     if (info.Length() < 1) {
259         return;
260     }
261     auto jsValue = info[0];
262     if (jsValue->IsUndefined()) {
263         TextFieldModel::GetInstance()->SetContentType(NG::TextContentType::UNSPECIFIED);
264         return;
265     }
266     if (!jsValue->IsNumber()) {
267         return;
268     }
269     NG::TextContentType textContentType = static_cast<NG::TextContentType>(jsValue->ToNumber<int32_t>());
270     TextFieldModel::GetInstance()->SetContentType(textContentType);
271 }
272 
SetPlaceholderColor(const JSCallbackInfo & info)273 void JSTextField::SetPlaceholderColor(const JSCallbackInfo& info)
274 {
275     if (info.Length() < 1) {
276         return;
277     }
278 
279     auto theme = GetTheme<TextFieldTheme>();
280     CHECK_NULL_VOID(theme);
281     Color color = theme->GetPlaceholderColor();
282     if (!CheckColor(info[0], color, V2::TEXTINPUT_ETS_TAG, "PlaceholderColor")) {
283         TextFieldModel::GetInstance()->ResetPlaceholderColor();
284         return;
285     }
286     TextFieldModel::GetInstance()->SetPlaceholderColor(color);
287 }
288 
SetPlaceholderFont(const JSCallbackInfo & info)289 void JSTextField::SetPlaceholderFont(const JSCallbackInfo& info)
290 {
291     if (info.Length() < 1 || !info[0]->IsObject()) {
292         return;
293     }
294     Font font;
295     auto paramObject = JSRef<JSObject>::Cast(info[0]);
296     auto fontSize = paramObject->GetProperty("size");
297     if (fontSize->IsNull() || fontSize->IsUndefined()) {
298         font.fontSize = Dimension(-1);
299     } else {
300         CalcDimension size;
301         auto theme = GetTheme<TextFieldTheme>();
302         CHECK_NULL_VOID(theme);
303         if (fontSize->IsString()) {
304             auto result = StringUtils::StringToDimensionWithThemeValue(
305                 fontSize->ToString(), true, Dimension(theme->GetFontSize()));
306             if (result.Unit() == DimensionUnit::PERCENT) {
307                 result = theme->GetFontSize();
308             }
309             font.fontSize = result;
310         } else if (ParseJsDimensionFp(fontSize, size) && size.Unit() != DimensionUnit::PERCENT) {
311             font.fontSize = size;
312         } else {
313             font.fontSize = Dimension(theme->GetFontSize());
314         }
315     }
316 
317     std::string weight;
318     auto fontWeight = paramObject->GetProperty("weight");
319     if (!fontWeight->IsNull()) {
320         if (fontWeight->IsNumber()) {
321             weight = std::to_string(fontWeight->ToNumber<int32_t>());
322         } else {
323             ParseJsString(fontWeight, weight);
324         }
325         font.fontWeight = ConvertStrToFontWeight(weight);
326     }
327 
328     auto fontFamily = paramObject->GetProperty("family");
329     if (!fontFamily->IsNull()) {
330         std::vector<std::string> fontFamilies;
331         if (ParseJsFontFamilies(fontFamily, fontFamilies)) {
332             font.fontFamilies = fontFamilies;
333         }
334     }
335 
336     auto style = paramObject->GetProperty("style");
337     if (!style->IsNull()) {
338         font.fontStyle = static_cast<FontStyle>(style->ToNumber<int32_t>());
339     }
340     TextFieldModel::GetInstance()->SetPlaceholderFont(font);
341 }
342 
SetEnterKeyType(const JSCallbackInfo & info)343 void JSTextField::SetEnterKeyType(const JSCallbackInfo& info)
344 {
345     if (info.Length() < 1) {
346         return;
347     }
348     auto jsValue = info[0];
349     if (jsValue->IsUndefined()) {
350         TextFieldModel::GetInstance()->SetEnterKeyType(TextInputAction::UNSPECIFIED);
351         return;
352     }
353     if (!jsValue->IsNumber()) {
354         return;
355     }
356     TextInputAction textInputAction = CastToTextInputAction(jsValue->ToNumber<int32_t>());
357     TextFieldModel::GetInstance()->SetEnterKeyType(textInputAction);
358 }
359 
SetTextAlign(int32_t value)360 void JSTextField::SetTextAlign(int32_t value)
361 {
362     if (value >= 0 && value < static_cast<int32_t>(TEXT_ALIGNS.size())) {
363         TextFieldModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
364     }
365 }
366 
SetLineBreakStrategy(const JSCallbackInfo & info)367 void JSTextField::SetLineBreakStrategy(const JSCallbackInfo& info)
368 {
369     if (info.Length() < 1) {
370         TextFieldModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
371         return;
372     }
373     if (!info[0]->IsNumber()) {
374         TextFieldModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
375         return;
376     }
377     auto index = info[0]->ToNumber<int32_t>();
378     if (index < 0 || index >= static_cast<int32_t>(LINE_BREAK_STRATEGY_TYPES.size())) {
379         TextFieldModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
380         return;
381     }
382     TextFieldModel::GetInstance()->SetLineBreakStrategy(LINE_BREAK_STRATEGY_TYPES[index]);
383 }
384 
SetInputStyle(const JSCallbackInfo & info)385 void JSTextField::SetInputStyle(const JSCallbackInfo& info)
386 {
387     if (info.Length() < 1) {
388         return;
389     }
390     auto styleString = info[0]->ToString();
391     if (styleString == "Inline") {
392         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::INLINE);
393     } else {
394         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::DEFAULT);
395     }
396 }
397 
SetCaretColor(const JSCallbackInfo & info)398 void JSTextField::SetCaretColor(const JSCallbackInfo& info)
399 {
400     if (info.Length() < 1) {
401         return;
402     }
403 
404     Color color;
405     if (!ParseJsColor(info[0], color)) {
406         TextFieldModel::GetInstance()->ResetCaretColor();
407         return;
408     }
409     TextFieldModel::GetInstance()->SetCaretColor(color);
410 }
411 
SetCaretStyle(const JSCallbackInfo & info)412 void JSTextField::SetCaretStyle(const JSCallbackInfo& info)
413 {
414     if (info.Length() < 1) {
415         return;
416     }
417     auto jsValue = info[0];
418     if (jsValue->IsObject()) {
419         CaretStyle caretStyle;
420         auto paramObject = JSRef<JSObject>::Cast(jsValue);
421         auto caretWidth = paramObject->GetProperty("width");
422 
423         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
424         CHECK_NULL_VOID(pipeline);
425         auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
426         CHECK_NULL_VOID(theme);
427         if (caretWidth->IsNull() || caretWidth->IsUndefined()) {
428             caretStyle.caretWidth = theme->GetCursorWidth();
429         } else {
430             CalcDimension width;
431             if (!ParseJsDimensionVpNG(caretWidth, width, false)) {
432                 width = theme->GetCursorWidth();
433             }
434             if (LessNotEqual(width.Value(), 0.0)) {
435                 width = theme->GetCursorWidth();
436             }
437             caretStyle.caretWidth = width;
438         }
439         TextFieldModel::GetInstance()->SetCaretStyle(caretStyle);
440 
441         // set caret color
442         Color caretColor;
443         if (!paramObject->HasProperty("color")) {
444             return;
445         } else {
446             auto caretColorProp = paramObject->GetProperty("color");
447             if (caretColorProp->IsUndefined() || caretColorProp->IsNull()
448                 || !ParseJsColor(caretColorProp, caretColor)) {
449                 caretColor = theme->GetCursorColor();
450             }
451             TextFieldModel::GetInstance()->SetCaretColor(caretColor);
452         }
453     }
454 }
455 
SetCaretPosition(const JSCallbackInfo & info)456 void JSTextField::SetCaretPosition(const JSCallbackInfo& info)
457 {
458     if (info.Length() < 1) {
459         return;
460     }
461     int32_t caretPosition = 0;
462     auto tempInfo = info[0];
463     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
464         if (!ParseJsInt32(tempInfo, caretPosition) || caretPosition < 0) {
465             caretPosition = 0;
466         }
467     } else {
468         if (!ParseJsInt32(tempInfo, caretPosition)) {
469             return;
470         }
471         if (caretPosition < 0) {
472             return;
473         }
474     }
475     TextFieldModel::GetInstance()->SetCaretPosition(caretPosition);
476 }
477 
SetSelectedBackgroundColor(const JSCallbackInfo & info)478 void JSTextField::SetSelectedBackgroundColor(const JSCallbackInfo& info)
479 {
480     if (info.Length() < 1) {
481         return;
482     }
483 
484     Color selectedColor;
485     if (!ParseJsColor(info[0], selectedColor)) {
486         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
487         CHECK_NULL_VOID(pipeline);
488         auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
489         CHECK_NULL_VOID(theme);
490         selectedColor = theme->GetSelectedColor();
491     }
492     // Alpha = 255 means opaque
493     if (selectedColor.GetAlpha() == 255) {
494         // Default setting of 20% opacity
495         selectedColor = selectedColor.ChangeOpacity(0.2);
496     }
497     TextFieldModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
498 }
499 
SetMaxLength(const JSCallbackInfo & info)500 void JSTextField::SetMaxLength(const JSCallbackInfo& info)
501 {
502     if (info.Length() < 1) {
503         return;
504     }
505     auto jsValue = info[0];
506     int32_t maxLength = 0;
507     if (jsValue->IsUndefined()) {
508         TextFieldModel::GetInstance()->ResetMaxLength();
509         return;
510     } else if (!jsValue->IsNumber()) {
511         TextFieldModel::GetInstance()->ResetMaxLength();
512         return;
513     }
514     maxLength = jsValue->ToNumber<int32_t>();
515     if (std::isinf(jsValue->ToNumber<float>())) {
516         maxLength = INT32_MAX; // Infinity
517     }
518     if (GreatOrEqual(maxLength, 0)) {
519         TextFieldModel::GetInstance()->SetMaxLength(maxLength);
520     } else {
521         TextFieldModel::GetInstance()->ResetMaxLength();
522     }
523 }
524 
SetFontSize(const JSCallbackInfo & info)525 void JSTextField::SetFontSize(const JSCallbackInfo& info)
526 {
527     if (info.Length() < 1) {
528         return;
529     }
530     CalcDimension fontSize;
531     if (!ParseJsDimensionNG(info[0], fontSize, DimensionUnit::FP, false)) {
532         auto theme = GetTheme<TextFieldTheme>();
533         CHECK_NULL_VOID(theme);
534         fontSize = theme->GetFontSize();
535     }
536     TextFieldModel::GetInstance()->SetFontSize(fontSize);
537 }
538 
SetFontWeight(const JSCallbackInfo & info)539 void JSTextField::SetFontWeight(const JSCallbackInfo& info)
540 {
541     if (info.Length() < 1) {
542         return;
543     }
544     JSRef<JSVal> args = info[0];
545     std::string fontWeight;
546     if (args->IsNumber()) {
547         fontWeight = args->ToString();
548     } else {
549         ParseJsString(args, fontWeight);
550     }
551     FontWeight formatFontWeight = ConvertStrToFontWeight(fontWeight);
552     TextFieldModel::GetInstance()->SetFontWeight(formatFontWeight);
553 }
554 
SetMinFontScale(const JSCallbackInfo & info)555 void JSTextField::SetMinFontScale(const JSCallbackInfo& info)
556 {
557     double minFontScale = 0.0;
558     if (info.Length() < 1 || !ParseJsDouble(info[0], minFontScale)) {
559         return;
560     }
561     if (LessOrEqual(minFontScale, 0.0f)) {
562         TextFieldModel::GetInstance()->SetMinFontScale(0.0f);
563         return;
564     }
565     if (GreatOrEqual(minFontScale, 1.0f)) {
566         TextFieldModel::GetInstance()->SetMinFontScale(1.0f);
567         return;
568     }
569     TextFieldModel::GetInstance()->SetMinFontScale(static_cast<float>(minFontScale));
570 }
571 
SetMaxFontScale(const JSCallbackInfo & info)572 void JSTextField::SetMaxFontScale(const JSCallbackInfo& info)
573 {
574     double maxFontScale = 0.0;
575     if (info.Length() < 1 || !ParseJsDouble(info[0], maxFontScale)) {
576         return;
577     }
578     if (LessOrEqual(maxFontScale, 1.0f)) {
579         TextFieldModel::GetInstance()->SetMaxFontScale(1.0f);
580         return;
581     }
582     TextFieldModel::GetInstance()->SetMaxFontScale(static_cast<float>(maxFontScale));
583 }
584 
SetTextColor(const JSCallbackInfo & info)585 void JSTextField::SetTextColor(const JSCallbackInfo& info)
586 {
587     if (info.Length() < 1) {
588         return;
589     }
590     Color textColor;
591     if (!ParseJsColor(info[0], textColor)) {
592         TextFieldModel::GetInstance()->ResetTextColor();
593         return;
594     }
595     TextFieldModel::GetInstance()->SetTextColor(textColor);
596 }
597 
SetWordBreak(const JSCallbackInfo & info)598 void JSTextField::SetWordBreak(const JSCallbackInfo& info)
599 {
600     if (info.Length() < 1) {
601         return;
602     }
603     auto jsValue = info[0];
604     if (!jsValue->IsNumber()) {
605         TextFieldModel::GetInstance()->SetWordBreak(WordBreak::BREAK_WORD);
606         return;
607     }
608     auto index = jsValue->ToNumber<int32_t>();
609     if (index < 0 || index >= static_cast<int32_t>(WORD_BREAK_TYPES.size())) {
610         TextFieldModel::GetInstance()->SetWordBreak(WordBreak::BREAK_WORD);
611         return;
612     }
613     TextFieldModel::GetInstance()->SetWordBreak(WORD_BREAK_TYPES[index]);
614 }
615 
SetForegroundColor(const JSCallbackInfo & info)616 void JSTextField::SetForegroundColor(const JSCallbackInfo& info)
617 {
618     if (info.Length() < 1) {
619         return;
620     }
621     auto jsValue = info[0];
622     ForegroundColorStrategy strategy;
623     if (ParseJsColorStrategy(jsValue, strategy)) {
624         ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
625         TextFieldModel::GetInstance()->SetForegroundColor(Color::FOREGROUND);
626         return;
627     }
628     Color foregroundColor;
629     if (!ParseJsColor(jsValue, foregroundColor)) {
630         return;
631     }
632     ViewAbstractModel::GetInstance()->SetForegroundColor(foregroundColor);
633     TextFieldModel::GetInstance()->SetForegroundColor(foregroundColor);
634 }
635 
SetFontStyle(int32_t value)636 void JSTextField::SetFontStyle(int32_t value)
637 {
638     if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
639         TextFieldModel::GetInstance()->SetFontStyle(FONT_STYLES[value]);
640     }
641 }
642 
SetFontFamily(const JSCallbackInfo & info)643 void JSTextField::SetFontFamily(const JSCallbackInfo& info)
644 {
645     if (info.Length() < 1) {
646         return;
647     }
648     std::vector<std::string> fontFamilies;
649     if (!ParseJsFontFamilies(info[0], fontFamilies)) {
650         return;
651     }
652     TextFieldModel::GetInstance()->SetFontFamily(fontFamilies);
653 }
654 
SetInputFilter(const JSCallbackInfo & info)655 void JSTextField::SetInputFilter(const JSCallbackInfo& info)
656 {
657     if (info.Length() < 1) {
658         return;
659     }
660     auto jsValue = info[0];
661     std::string inputFilter;
662     if (jsValue->IsUndefined()) {
663         TextFieldModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
664         return;
665     }
666     if (!ParseJsString(jsValue, inputFilter)) {
667         return;
668     }
669     if (!CheckRegexValid(inputFilter)) {
670         inputFilter = "";
671     }
672     if (info.Length() > 1 && info[1]->IsFunction()) {
673         auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(info[1]));
674         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
675         auto resultId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
676                             const std::u16string& info) {
677             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
678             PipelineContext::SetCallBackNode(node);
679             func->Execute(info);
680         };
681         TextFieldModel::GetInstance()->SetInputFilter(inputFilter, resultId);
682         return;
683     }
684     TextFieldModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
685 }
686 
SetShowPasswordIcon(const JSCallbackInfo & info)687 void JSTextField::SetShowPasswordIcon(const JSCallbackInfo& info)
688 {
689     auto jsValue = info[0];
690     if (!jsValue->IsBoolean()) {
691         TextFieldModel::GetInstance()->SetShowPasswordIcon(true);
692         return;
693     }
694 
695     bool isShowPasswordIcon = jsValue->ToBoolean();
696     TextFieldModel::GetInstance()->SetShowPasswordIcon(isShowPasswordIcon);
697 }
698 
ShowPasswordText(const JSCallbackInfo & info)699 void JSTextField::ShowPasswordText(const JSCallbackInfo& info)
700 {
701     auto tmpInfo = info[0];
702     if (!tmpInfo->IsBoolean()) {
703         TextFieldModel::GetInstance()->SetShowPasswordText(false);
704         return;
705     }
706 
707     bool showPassword = tmpInfo->ToBoolean();
708     TextFieldModel::GetInstance()->SetShowPasswordText(showPassword);
709 }
710 
SetBackgroundColor(const JSCallbackInfo & info)711 void JSTextField::SetBackgroundColor(const JSCallbackInfo& info)
712 {
713     if (info.Length() < 1) {
714         return;
715     }
716     Color backgroundColor;
717     if (!ParseJsColor(info[0], backgroundColor)) {
718         TextFieldModel::GetInstance()->ResetBackgroundColor();
719         return;
720     }
721     TextFieldModel::GetInstance()->SetBackgroundColor(backgroundColor, false);
722 }
723 
JsHeight(const JSCallbackInfo & info)724 void JSTextField::JsHeight(const JSCallbackInfo& info)
725 {
726     JSViewAbstract::JsHeight(info);
727     if (info.Length() < 1) {
728         return;
729     }
730     CalcDimension value;
731     if (!ParseJsDimensionVp(info[0], value)) {
732         return;
733     }
734     if (LessNotEqual(value.Value(), 0.0)) {
735         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
736         return;
737     }
738     TextFieldModel::GetInstance()->SetHeight(value);
739 }
740 
JsWidth(const JSCallbackInfo & info)741 void JSTextField::JsWidth(const JSCallbackInfo& info)
742 {
743     if (info.Length() < 1) {
744         return;
745     }
746     auto jsValue = info[0];
747     if (jsValue->IsString() && jsValue->ToString().empty()) {
748         return;
749     }
750     if (jsValue->IsString() && jsValue->ToString() == "auto") {
751         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
752         TextFieldModel::GetInstance()->SetWidthAuto(true);
753         return;
754     }
755 
756     TextFieldModel::GetInstance()->SetWidthAuto(false);
757     CalcDimension value;
758     if (!ParseJsDimensionVp(jsValue, value)) {
759         return;
760     }
761     if (LessNotEqual(value.Value(), 0.0)) {
762         return;
763     }
764     ViewAbstractModel::GetInstance()->SetWidth(value);
765 }
766 
CheckIsIllegalString(const std::string & value)767 bool CheckIsIllegalString(const std::string& value)
768 {
769     if (value.empty()) {
770         return true;
771     }
772     errno = 0;
773     char* pEnd = nullptr;
774     std::strtod(value.c_str(), &pEnd);
775     return (pEnd == value.c_str() || errno == ERANGE);
776 }
777 
JsMargin(const JSCallbackInfo & info)778 void JSTextField::JsMargin(const JSCallbackInfo& info)
779 {
780     JSViewAbstract::JsMargin(info);
781     TextFieldModel::GetInstance()->SetMargin();
782 }
783 
JsPadding(const JSCallbackInfo & info)784 void JSTextField::JsPadding(const JSCallbackInfo& info)
785 {
786     auto jsValue = info[0];
787     if (jsValue->IsUndefined() || (jsValue->IsString() && CheckIsIllegalString(jsValue->ToString()))) {
788         return;
789     };
790     CalcDimension length;
791     ParseJsDimensionVp(jsValue, length);
792     if (length.IsNegative()) {
793         TextFieldModel::GetInstance()->SetPadding(NG::PaddingProperty(), Edge(), true);
794         return;
795     }
796     bool tmp = !jsValue->IsString() && !jsValue->IsNumber() && !jsValue->IsObject();
797 
798     NG::PaddingProperty newPadding = GetNewPadding(info);
799     Edge oldPadding = Edge(GetOldPadding(info));
800     TextFieldModel::GetInstance()->SetPadding(newPadding, oldPadding, tmp);
801 }
802 
GetOldPadding(const JSCallbackInfo & info)803 Edge JSTextField::GetOldPadding(const JSCallbackInfo& info)
804 {
805     Edge padding;
806     auto jsValue = info[0];
807     if (jsValue->IsNumber() || jsValue->IsString()) {
808         CalcDimension edgeValue;
809         if (ParseJsDimensionVp(jsValue, edgeValue)) {
810             padding = Edge(edgeValue);
811         }
812     }
813     if (jsValue->IsObject()) {
814         JSRef<JSObject> object = JSRef<JSObject>::Cast(jsValue);
815         CalcDimension left = CalcDimension(0.0, DimensionUnit::VP);
816         CalcDimension top = CalcDimension(0.0, DimensionUnit::VP);
817         CalcDimension right = CalcDimension(0.0, DimensionUnit::VP);
818         CalcDimension bottom = CalcDimension(0.0, DimensionUnit::VP);
819         ParseJsDimensionVp(object->GetProperty("left"), left);
820         ParseJsDimensionVp(object->GetProperty("top"), top);
821         ParseJsDimensionVp(object->GetProperty("right"), right);
822         ParseJsDimensionVp(object->GetProperty("bottom"), bottom);
823         padding = Edge(left, top, right, bottom);
824     }
825     return padding;
826 }
827 
GetNewPadding(const JSCallbackInfo & info)828 NG::PaddingProperty JSTextField::GetNewPadding(const JSCallbackInfo& info)
829 {
830     NG::PaddingProperty padding;
831     auto jsValue = info[0];
832     if (jsValue->IsObject()) {
833         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(jsValue);
834         CommonCalcDimension commonCalcDimension;
835         ParseCommonMarginOrPaddingCorner(paddingObj, commonCalcDimension);
836         if (commonCalcDimension.left.has_value() || commonCalcDimension.right.has_value() ||
837             commonCalcDimension.top.has_value() || commonCalcDimension.bottom.has_value()) {
838             padding = SetPaddings(commonCalcDimension.top, commonCalcDimension.bottom, commonCalcDimension.left,
839                 commonCalcDimension.right);
840             return padding;
841         }
842     }
843 
844     CalcDimension length;
845     if (!ParseJsDimensionVp(jsValue, length)) {
846         // use default value.
847         length.Reset();
848     }
849     padding.SetEdges(NG::CalcLength(length.IsNonNegative() ? length : CalcDimension()));
850     return padding;
851 }
852 
SetPaddings(const std::optional<CalcDimension> & top,const std::optional<CalcDimension> & bottom,const std::optional<CalcDimension> & left,const std::optional<CalcDimension> & right)853 NG::PaddingProperty JSTextField::SetPaddings(const std::optional<CalcDimension>& top,
854     const std::optional<CalcDimension>& bottom, const std::optional<CalcDimension>& left,
855     const std::optional<CalcDimension>& right)
856 {
857     NG::PaddingProperty paddings;
858     if (top.has_value()) {
859         if (top.value().Unit() == DimensionUnit::CALC) {
860             paddings.top =
861                 NG::CalcLength(top.value().IsNonNegative() ? top.value().CalcValue() : CalcDimension().CalcValue());
862         } else {
863             paddings.top = NG::CalcLength(top.value().IsNonNegative() ? top.value() : CalcDimension());
864         }
865     }
866     if (bottom.has_value()) {
867         if (bottom.value().Unit() == DimensionUnit::CALC) {
868             paddings.bottom = NG::CalcLength(
869                 bottom.value().IsNonNegative() ? bottom.value().CalcValue() : CalcDimension().CalcValue());
870         } else {
871             paddings.bottom = NG::CalcLength(bottom.value().IsNonNegative() ? bottom.value() : CalcDimension());
872         }
873     }
874     if (left.has_value()) {
875         if (left.value().Unit() == DimensionUnit::CALC) {
876             paddings.left =
877                 NG::CalcLength(left.value().IsNonNegative() ? left.value().CalcValue() : CalcDimension().CalcValue());
878         } else {
879             paddings.left = NG::CalcLength(left.value().IsNonNegative() ? left.value() : CalcDimension());
880         }
881     }
882     if (right.has_value()) {
883         if (right.value().Unit() == DimensionUnit::CALC) {
884             paddings.right =
885                 NG::CalcLength(right.value().IsNonNegative() ? right.value().CalcValue() : CalcDimension().CalcValue());
886         } else {
887             paddings.right = NG::CalcLength(right.value().IsNonNegative() ? right.value() : CalcDimension());
888         }
889     }
890 
891     return paddings;
892 }
893 
JsBorder(const JSCallbackInfo & info)894 void JSTextField::JsBorder(const JSCallbackInfo& info)
895 {
896     if (!info[0]->IsObject()) {
897         CalcDimension borderWidth;
898         ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
899         ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
900         ViewAbstractModel::GetInstance()->SetBorderRadius(borderWidth);
901         ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
902         ViewAbstractModel::GetInstance()->SetDashGap(Dimension(-1));
903         ViewAbstractModel::GetInstance()->SetDashWidth(Dimension(-1));
904         return;
905     }
906     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
907 
908     auto valueWidth = object->GetProperty(static_cast<int32_t>(ArkUIIndex::WIDTH));
909     if (!valueWidth->IsUndefined()) {
910         JSViewAbstract::ParseBorderWidth(valueWidth);
911     }
912 
913     // use default value when undefined.
914     JSViewAbstract::ParseBorderColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR)));
915 
916     auto valueRadius = object->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS));
917     if (!valueRadius->IsUndefined()) {
918         ParseBorderRadius(valueRadius);
919     }
920     // use default value when undefined.
921     JSViewAbstract::ParseBorderStyle(object->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE)));
922 
923     auto dashGap = object->GetProperty("dashGap");
924     if (!dashGap->IsUndefined()) {
925         JSViewAbstract::ParseDashGap(dashGap);
926     }
927     auto dashWidth = object->GetProperty("dashWidth");
928     if (!dashWidth->IsUndefined()) {
929         JSViewAbstract::ParseDashWidth(dashWidth);
930     }
931 
932     TextFieldModel::GetInstance()->SetBackBorder();
933     info.ReturnSelf();
934 }
935 
JsBorderWidth(const JSCallbackInfo & info)936 void JSTextField::JsBorderWidth(const JSCallbackInfo& info)
937 {
938     auto jsValue = info[0];
939     if (!jsValue->IsObject() && !jsValue->IsString() && !jsValue->IsNumber()) {
940         return;
941     }
942     JSViewAbstract::JsBorderWidth(info);
943     TextFieldModel::GetInstance()->SetBackBorder();
944 }
945 
JsBorderColor(const JSCallbackInfo & info)946 void JSTextField::JsBorderColor(const JSCallbackInfo& info)
947 {
948     auto jsValue = info[0];
949     if (!jsValue->IsObject() && !jsValue->IsString() && !jsValue->IsNumber()) {
950         return;
951     }
952     JSViewAbstract::JsBorderColor(info);
953     TextFieldModel::GetInstance()->SetBackBorder();
954 }
955 
JsBorderStyle(const JSCallbackInfo & info)956 void JSTextField::JsBorderStyle(const JSCallbackInfo& info)
957 {
958     auto jsValue = info[0];
959     if (!jsValue->IsObject() && !jsValue->IsNumber()) {
960         return;
961     }
962     JSViewAbstract::JsBorderStyle(info);
963     TextFieldModel::GetInstance()->SetBackBorder();
964 }
965 
GetBorderRadiusByLengthMetrics(const char * key,JSRef<JSObject> & object,std::optional<CalcDimension> & radius)966 void JSTextField::GetBorderRadiusByLengthMetrics(const char* key, JSRef<JSObject>& object,
967     std::optional<CalcDimension>& radius)
968 {
969     if (object->HasProperty(key) && object->GetProperty(key)->IsObject()) {
970         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(object->GetProperty(key));
971         CalcDimension value;
972         ParseJsLengthMetrics(startObj, value);
973         radius = value;
974     }
975 }
976 
ParseAllBorderRadiuses(JSRef<JSObject> & object,CalcDimension & topLeft,CalcDimension & topRight,CalcDimension & bottomLeft,CalcDimension & bottomRight)977 bool JSTextField::ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft,
978     CalcDimension& topRight, CalcDimension& bottomLeft, CalcDimension& bottomRight)
979 {
980     if (object->HasProperty(TOP_START_PROPERTY) || object->HasProperty(TOP_END_PROPERTY) ||
981         object->HasProperty(BOTTOM_START_PROPERTY) || object->HasProperty(BOTTOM_END_PROPERTY)) {
982         std::optional<CalcDimension> topStart;
983         std::optional<CalcDimension> topEnd;
984         std::optional<CalcDimension> bottomStart;
985         std::optional<CalcDimension> bottomEnd;
986         GetBorderRadiusByLengthMetrics(TOP_START_PROPERTY, object, topStart);
987         GetBorderRadiusByLengthMetrics(TOP_END_PROPERTY, object, topEnd);
988         GetBorderRadiusByLengthMetrics(BOTTOM_START_PROPERTY, object, bottomStart);
989         GetBorderRadiusByLengthMetrics(BOTTOM_END_PROPERTY, object, bottomEnd);
990         topLeft = topStart.has_value() ? topStart.value() : topLeft;
991         topRight = topEnd.has_value() ? topEnd.value() : topRight;
992         bottomLeft = bottomStart.has_value() ? bottomStart.value() : bottomLeft;
993         bottomRight = bottomEnd.has_value() ? bottomEnd.value() : bottomRight;
994         return true;
995     }
996     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topLeft"), topLeft);
997     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topRight"), topRight);
998     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomLeft"), bottomLeft);
999     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomRight"), bottomRight);
1000     return false;
1001 }
1002 
ParseBorderRadius(const JSRef<JSVal> & args)1003 void JSTextField::ParseBorderRadius(const JSRef<JSVal>& args)
1004 {
1005     CalcDimension borderRadius;
1006     if (ParseJsDimensionVp(args, borderRadius)) {
1007         ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius);
1008     } else if (args->IsObject()) {
1009         auto textFieldTheme = GetTheme<TextFieldTheme>();
1010         CHECK_NULL_VOID(textFieldTheme);
1011         auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
1012         NG::BorderRadiusProperty defaultBorderRadius {
1013             borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
1014             borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
1015         };
1016 
1017         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
1018         CalcDimension topLeft = defaultBorderRadius.radiusTopLeft.value();
1019         CalcDimension topRight = defaultBorderRadius.radiusTopRight.value();
1020         CalcDimension bottomLeft = defaultBorderRadius.radiusBottomLeft.value();
1021         CalcDimension bottomRight = defaultBorderRadius.radiusBottomRight.value();
1022         if (ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight)) {
1023             ViewAbstractModel::GetInstance()->SetBorderRadius(
1024                 JSViewAbstract::GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
1025                 return;
1026         }
1027         ViewAbstractModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
1028     }
1029 }
1030 
JsBorderRadius(const JSCallbackInfo & info)1031 void JSTextField::JsBorderRadius(const JSCallbackInfo& info)
1032 {
1033     auto jsValue = info[0];
1034     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING,
1035         JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
1036     if (!CheckJSCallbackInfo("JsBorderRadius", jsValue, checkList)) {
1037         auto textFieldTheme = GetTheme<TextFieldTheme>();
1038         CHECK_NULL_VOID(textFieldTheme);
1039         auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
1040         NG::BorderRadiusProperty defaultBorderRadius {
1041             borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
1042             borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
1043         };
1044         ViewAbstractModel::GetInstance()->SetBorderRadius(defaultBorderRadius);
1045         return;
1046     }
1047     ParseBorderRadius(jsValue);
1048     TextFieldModel::GetInstance()->SetBackBorder();
1049 }
1050 
JsHoverEffect(const JSCallbackInfo & info)1051 void JSTextField::JsHoverEffect(const JSCallbackInfo& info)
1052 {
1053     auto jsValue = info[0];
1054     if (!jsValue->IsNumber()) {
1055         return;
1056     }
1057     TextFieldModel::GetInstance()->SetHoverEffect(static_cast<HoverEffectType>(jsValue->ToNumber<int32_t>()));
1058 }
1059 
SetOnEditChanged(const JSCallbackInfo & info)1060 void JSTextField::SetOnEditChanged(const JSCallbackInfo& info)
1061 {
1062     auto jsValue = info[0];
1063     CHECK_NULL_VOID(jsValue->IsFunction());
1064     JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1065     TextFieldModel::GetInstance()->SetOnEditChanged(std::move(callback));
1066 }
1067 
JsKeepEditableState(panda::JsiRuntimeCallInfo * info)1068 Local<JSValueRef> JSTextField::JsKeepEditableState(panda::JsiRuntimeCallInfo *info)
1069 {
1070     Local<JSValueRef> thisObj = info->GetThisRef();
1071     auto eventInfo = static_cast<NG::TextFieldCommonEvent*>(
1072         panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(info->GetVM(), 0));
1073     if (eventInfo) {
1074         eventInfo->SetKeepEditable(true);
1075     }
1076     return JSValueRef::Undefined(info->GetVM());
1077 }
1078 
CreateJsTextFieldCommonEvent(const JSCallbackInfo & info)1079 void JSTextField::CreateJsTextFieldCommonEvent(const JSCallbackInfo &info)
1080 {
1081     if (info.Length() < 1 || !info[0]->IsObject()) {
1082         return;
1083     }
1084     auto jsValue = info[0];
1085     auto jsTextFunc = AceType::MakeRefPtr<JsCommonEventFunction<NG::TextFieldCommonEvent, 2>>(
1086         JSRef<JSFunc>::Cast(jsValue));
1087     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1088     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc), node = targetNode](int32_t key,
1089                        NG::TextFieldCommonEvent& event) {
1090         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1091         ACE_SCORING_EVENT("onSubmit");
1092         PipelineContext::SetCallBackNode(node);
1093         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1094         objectTemplate->SetInternalFieldCount(2);
1095         JSRef<JSObject> object = objectTemplate->NewInstance();
1096         object->SetProperty<std::u16string>("text", event.GetText());
1097         object->SetPropertyObject("keepEditableState", JSRef<JSFunc>::New<FunctionCallback>(JsKeepEditableState));
1098         object->Wrap<NG::TextFieldCommonEvent>(&event);
1099         JSRef<JSVal> keyEvent = JSRef<JSVal>::Make(ToJSValue(key));
1100         JSRef<JSVal> dataObject = JSRef<JSVal>::Cast(object);
1101         JSRef<JSVal> param[2] = {keyEvent, dataObject};
1102         func->Execute(param);
1103         UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "onSubmit");
1104     };
1105     TextFieldModel::GetInstance()->SetOnSubmit(std::move(callback));
1106 }
1107 
SetOnSubmit(const JSCallbackInfo & info)1108 void JSTextField::SetOnSubmit(const JSCallbackInfo& info)
1109 {
1110     auto jsValue = info[0];
1111     CHECK_NULL_VOID(jsValue->IsFunction());
1112 #ifdef NG_BUILD
1113     CreateJsTextFieldCommonEvent(info);
1114 #else
1115     if (Container::IsCurrentUseNewPipeline()) {
1116         CreateJsTextFieldCommonEvent(info);
1117     } else {
1118         JsEventCallback<void(int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1119         TextFieldModel::GetInstance()->SetOnSubmit(std::move(callback));
1120     }
1121 #endif
1122 }
1123 
CreateJsOnChangeObj(const PreviewText & previewText)1124 JSRef<JSVal> JSTextField::CreateJsOnChangeObj(const PreviewText& previewText)
1125 {
1126     JSRef<JSObject> previewTextObj = JSRef<JSObject>::New();
1127     previewTextObj->SetProperty<int32_t>("offset", previewText.offset);
1128     previewTextObj->SetProperty<std::u16string>("value", previewText.value);
1129     return JSRef<JSVal>::Cast(previewTextObj);
1130 }
1131 
SetOnChange(const JSCallbackInfo & info)1132 void JSTextField::SetOnChange(const JSCallbackInfo& info)
1133 {
1134     auto jsValue = info[0];
1135     CHECK_NULL_VOID(jsValue->IsFunction());
1136     auto jsChangeFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsValue));
1137     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
1138         const ChangeValueInfo& changeValueInfo) {
1139         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1140         ACE_SCORING_EVENT("onChange");
1141         JSRef<JSVal> valueObj = JSRef<JSVal>::Make(ToJSValue(changeValueInfo.value));
1142         auto previewTextObj = CreateJsOnChangeObj(changeValueInfo.previewText);
1143         auto optionsObj = JSRef<JSObject>::New();
1144         auto rangeBeforeObj = JSRef<JSObject>::New();
1145         rangeBeforeObj->SetProperty<int32_t>("start", changeValueInfo.rangeBefore.start);
1146         rangeBeforeObj->SetProperty<int32_t>("end", changeValueInfo.rangeBefore.end);
1147         optionsObj->SetPropertyObject("rangeBefore", rangeBeforeObj);
1148         auto rangeAfterObj = JSRef<JSObject>::New();
1149         rangeAfterObj->SetProperty<int32_t>("start", changeValueInfo.rangeAfter.start);
1150         rangeAfterObj->SetProperty<int32_t>("end", changeValueInfo.rangeAfter.end);
1151         optionsObj->SetPropertyObject("rangeAfter", rangeAfterObj);
1152         optionsObj->SetProperty<std::u16string>("oldContent", changeValueInfo.oldContent);
1153         auto oldPreviewTextObj = CreateJsOnChangeObj(changeValueInfo.oldPreviewText);
1154         optionsObj->SetPropertyObject("oldPreviewText", oldPreviewTextObj);
1155         JSRef<JSVal> argv[] = { valueObj, previewTextObj, optionsObj };
1156         func->ExecuteJS(3, argv);
1157     };
1158     TextFieldModel::GetInstance()->SetOnChange(std::move(onChange));
1159 }
1160 
SetOnTextSelectionChange(const JSCallbackInfo & info)1161 void JSTextField::SetOnTextSelectionChange(const JSCallbackInfo& info)
1162 {
1163     auto jsValue = info[0];
1164     CHECK_NULL_VOID(jsValue->IsFunction());
1165     JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1166     TextFieldModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
1167 }
1168 
SetOnSecurityStateChange(const JSCallbackInfo & info)1169 void JSTextField::SetOnSecurityStateChange(const JSCallbackInfo& info)
1170 {
1171     auto jsValue = info[0];
1172     CHECK_NULL_VOID(jsValue->IsFunction());
1173     JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1174     TextFieldModel::GetInstance()->SetOnSecurityStateChange(std::move(callback));
1175 }
1176 
SetOnContentScroll(const JSCallbackInfo & info)1177 void JSTextField::SetOnContentScroll(const JSCallbackInfo& info)
1178 {
1179     auto jsValue = info[0];
1180     CHECK_NULL_VOID(jsValue->IsFunction());
1181     JsEventCallback<void(float, float)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1182     TextFieldModel::GetInstance()->SetOnContentScroll(std::move(callback));
1183 }
1184 
SetOnCopy(const JSCallbackInfo & info)1185 void JSTextField::SetOnCopy(const JSCallbackInfo& info)
1186 {
1187     auto jsValue = info[0];
1188     CHECK_NULL_VOID(jsValue->IsFunction());
1189     JsEventCallback<void(const std::u16string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1190     TextFieldModel::GetInstance()->SetOnCopy(std::move(callback));
1191 }
1192 
SetOnCut(const JSCallbackInfo & info)1193 void JSTextField::SetOnCut(const JSCallbackInfo& info)
1194 {
1195     auto jsValue = info[0];
1196     CHECK_NULL_VOID(jsValue->IsFunction());
1197     JsEventCallback<void(const std::u16string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1198     TextFieldModel::GetInstance()->SetOnCut(std::move(callback));
1199 }
1200 
CreateJSTextCommonEvent(NG::TextCommonEvent & event)1201 JSRef<JSVal> JSTextField::CreateJSTextCommonEvent(NG::TextCommonEvent& event)
1202 {
1203     JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1204     objectTemplate->SetInternalFieldCount(1);
1205     JSRef<JSObject> object = objectTemplate->NewInstance();
1206     object->SetPropertyObject("preventDefault", JSRef<JSFunc>::New<FunctionCallback>(JsPreventDefault));
1207     object->Wrap<NG::TextCommonEvent>(&event);
1208     return JSRef<JSVal>::Cast(object);
1209 }
1210 
SetOnPaste(const JSCallbackInfo & info)1211 void JSTextField::SetOnPaste(const JSCallbackInfo& info)
1212 {
1213     auto jsValue = info[0];
1214     CHECK_NULL_VOID(jsValue->IsFunction());
1215     auto jsTextFunc = AceType::MakeRefPtr<JsCitedEventFunction<NG::TextCommonEvent, 2>>(
1216         JSRef<JSFunc>::Cast(jsValue), CreateJSTextCommonEvent);
1217 
1218     auto onPaste = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc)](
1219         const std::u16string& val, NG::TextCommonEvent& info) {
1220         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1221         ACE_SCORING_EVENT("onPaste");
1222         func->Execute(val, info);
1223         UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "onPaste");
1224     };
1225     TextFieldModel::GetInstance()->SetOnPasteWithEvent(std::move(onPaste));
1226 }
1227 
SetOnClick(const JSCallbackInfo & info)1228 void JSTextField::SetOnClick(const JSCallbackInfo& info)
1229 {
1230     if (Container::IsCurrentUseNewPipeline()) {
1231         JSInteractableView::JsOnClick(info);
1232         return;
1233     }
1234     JsEventCallback<void(const ClickInfo&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
1235     TextFieldModel::GetInstance()->SetOnClick(std::move(callback));
1236     info.ReturnSelf();
1237 }
1238 
SetCopyOption(const JSCallbackInfo & info)1239 void JSTextField::SetCopyOption(const JSCallbackInfo& info)
1240 {
1241     if (info.Length() == 0) {
1242         return;
1243     }
1244     auto jsValue = info[0];
1245     if (jsValue->IsUndefined()) {
1246         TextFieldModel::GetInstance()->SetCopyOption(CopyOptions::Local);
1247         return;
1248     }
1249     auto copyOptions = CopyOptions::Local;
1250     if (jsValue->IsNumber()) {
1251         auto emunNumber = jsValue->ToNumber<int>();
1252         copyOptions = static_cast<CopyOptions>(emunNumber);
1253     }
1254     TextFieldModel::GetInstance()->SetCopyOption(copyOptions);
1255 }
1256 
SetShowUnderline(const JSCallbackInfo & info)1257 void JSTextField::SetShowUnderline(const JSCallbackInfo& info)
1258 {
1259     auto jsValue = info[0];
1260     if (!jsValue->IsBoolean()) {
1261         TextFieldModel::GetInstance()->SetShowUnderline(false);
1262         return;
1263     }
1264     TextFieldModel::GetInstance()->SetShowUnderline(jsValue->ToBoolean());
1265 }
1266 
SetUnderlineColor(const JSCallbackInfo & info)1267 void JSTextField::SetUnderlineColor(const JSCallbackInfo& info)
1268 {
1269     if (info.Length() < 1) {
1270         return;
1271     }
1272     auto jsValue = info[0];
1273     Color underlineColor;
1274     if (ParseJsColor(jsValue, underlineColor)) {
1275         TextFieldModel::GetInstance()->SetNormalUnderlineColor(underlineColor);
1276     } else if (jsValue->IsObject()) {
1277         auto param = JSRef<JSObject>::Cast(jsValue);
1278         UserUnderlineColor userColor = UserUnderlineColor();
1279         auto typingColorProp = param->GetProperty("typing");
1280         Color typing;
1281         if (ParseJsColor(typingColorProp, typing)) {
1282             userColor.typing = typing;
1283         }
1284         auto normalColorProp = param->GetProperty("normal");
1285         Color normal;
1286         if (ParseJsColor(normalColorProp, normal)) {
1287             userColor.normal = normal;
1288         }
1289         auto errorColorProp = param->GetProperty("error");
1290         Color error;
1291         if (ParseJsColor(errorColorProp, error)) {
1292             userColor.error = error;
1293         }
1294         auto disableColorProp = param->GetProperty("disable");
1295         Color disable;
1296         if (ParseJsColor(disableColorProp, disable)) {
1297             userColor.disable = disable;
1298         }
1299         TextFieldModel::GetInstance()->SetUserUnderlineColor(userColor);
1300     } else {
1301         TextFieldModel::GetInstance()->SetUserUnderlineColor(UserUnderlineColor());
1302     }
1303 }
1304 
SetPasswordIcon(const JSCallbackInfo & info)1305 void JSTextField::SetPasswordIcon(const JSCallbackInfo& info)
1306 {
1307     if (!Container::IsCurrentUseNewPipeline()) {
1308         return;
1309     }
1310     auto jsValue = info[0];
1311     if (!jsValue->IsObject()) {
1312         return;
1313     }
1314     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
1315     JSRef<JSVal> showVal = jsObj->GetProperty("onIconSrc");
1316     JSRef<JSVal> hideVal = jsObj->GetProperty("offIconSrc");
1317     PasswordIcon passwordIcon;
1318     if (showVal->IsString()) {
1319         passwordIcon.showResult = showVal->ToString();
1320     }
1321     if (hideVal->IsString()) {
1322         passwordIcon.hideResult = hideVal->ToString();
1323     }
1324     if (showVal->IsObject()) {
1325         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(showVal)->GetProperty("bundleName");
1326         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(showVal)->GetProperty("moduleName");
1327         if (bundleName->IsString()) {
1328             passwordIcon.showBundleName = bundleName->ToString();
1329         }
1330         if (moduleName->IsString()) {
1331             passwordIcon.showModuleName = moduleName->ToString();
1332         }
1333         ParseJsMedia(JSRef<JSObject>::Cast(showVal), passwordIcon.showResult);
1334     }
1335     if (hideVal->IsObject()) {
1336         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("bundleName");
1337         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("moduleName");
1338         if (bundleName->IsString()) {
1339             passwordIcon.hideBundleName = bundleName->ToString();
1340         }
1341         if (moduleName->IsString()) {
1342             passwordIcon.hideModuleName = moduleName->ToString();
1343         }
1344         ParseJsMedia(JSRef<JSObject>::Cast(hideVal), passwordIcon.hideResult);
1345     }
1346     if (!showVal->IsString() && !showVal->IsObject()) {
1347         passwordIcon.showResult = "";
1348     }
1349     if (!hideVal->IsString() && !hideVal->IsObject()) {
1350         passwordIcon.hideResult = "";
1351     }
1352     TextFieldModel::GetInstance()->SetPasswordIcon(passwordIcon);
1353 }
1354 
UpdateDecoration(const RefPtr<BoxComponent> & boxComponent,const RefPtr<TextFieldComponent> & component,const Border & boxBorder,const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme> & textFieldTheme)1355 void JSTextField::UpdateDecoration(const RefPtr<BoxComponent>& boxComponent,
1356     const RefPtr<TextFieldComponent>& component, const Border& boxBorder,
1357     const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)
1358 {
1359     if (!textFieldTheme) {
1360         return;
1361     }
1362 
1363     RefPtr<Decoration> decoration = component->GetDecoration();
1364     RefPtr<Decoration> boxDecoration = boxComponent->GetBackDecoration();
1365     if (!decoration) {
1366         decoration = AceType::MakeRefPtr<Decoration>();
1367     }
1368     if (boxDecoration) {
1369         Border border = decoration->GetBorder();
1370         border.SetLeftEdge(boxBorder.Left());
1371         border.SetRightEdge(boxBorder.Right());
1372         border.SetTopEdge(boxBorder.Top());
1373         border.SetBottomEdge(boxBorder.Bottom());
1374         border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1375         decoration->SetBorder(border);
1376         component->SetOriginBorder(decoration->GetBorder());
1377 
1378         if (boxDecoration->GetImage() || boxDecoration->GetGradient().IsValid()) {
1379             // clear box properties except background image and radius.
1380             boxDecoration->SetBackgroundColor(Color::TRANSPARENT);
1381             Border border;
1382             border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1383             boxDecoration->SetBorder(border);
1384         }
1385     } else {
1386         boxDecoration = AceType::MakeRefPtr<Decoration>();
1387         boxDecoration->SetBorderRadius(textFieldTheme->GetBorderRadius());
1388         boxComponent->SetBackDecoration(boxDecoration);
1389     }
1390 }
1391 
SetShowUnit(const JSCallbackInfo & info)1392 void JSTextField::SetShowUnit(const JSCallbackInfo& info)
1393 {
1394     auto jsValue = info[0];
1395     if (!jsValue->IsFunction()) {
1396         TextFieldModel::GetInstance()->SetShowUnit(nullptr);
1397         return;
1398     }
1399 
1400     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsValue));
1401     auto unitFunc = [builderFunc]() { builderFunc->Execute(); };
1402     TextFieldModel::GetInstance()->SetShowUnit(std::move(unitFunc));
1403 }
1404 
SetShowError(const JSCallbackInfo & info)1405 void JSTextField::SetShowError(const JSCallbackInfo& info)
1406 {
1407     auto jsValue = info[0];
1408     if (Container::IsCurrentUseNewPipeline()) {
1409         bool isVisible = false;
1410         std::u16string errorText;
1411         if (ParseJsString(jsValue, errorText)) {
1412             isVisible = true;
1413         }
1414         TextFieldModel::GetInstance()->SetShowError(errorText, isVisible);
1415     }
1416 }
1417 
SetShowCounter(const JSCallbackInfo & info)1418 void JSTextField::SetShowCounter(const JSCallbackInfo& info)
1419 {
1420     auto jsValue = info[0];
1421     auto secondJSValue = info[1];
1422     if ((!jsValue->IsBoolean() && !secondJSValue->IsObject())) {
1423         TextFieldModel::GetInstance()->SetShowCounter(false);
1424         return;
1425     }
1426     if (secondJSValue->IsObject()) {
1427         auto paramObject = JSRef<JSObject>::Cast(secondJSValue);
1428         auto param = paramObject->GetProperty("highlightBorder");
1429         auto isBorderShow = param->ToBoolean();
1430         if (!param->IsBoolean() || param->IsUndefined() || param->IsNull()) {
1431             TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1432         } else {
1433             TextFieldModel::GetInstance()->SetShowCounterBorder(isBorderShow);
1434         }
1435         auto parameter = paramObject->GetProperty("thresholdPercentage");
1436         auto inputNumber = parameter->ToNumber<int32_t>();
1437         TextFieldModel::GetInstance()->SetCounterType(inputNumber);
1438         if (parameter->IsNull() || parameter->IsUndefined()) {
1439             TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1440             TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1441             return;
1442         }
1443         if (static_cast<uint32_t>(inputNumber) < MINI_VAILD_VALUE ||
1444             static_cast<uint32_t>(inputNumber) > MAX_VAILD_VALUE) {
1445             LOGI("The info is wrong, it is supposed to be a right number");
1446             TextFieldModel::GetInstance()->SetCounterType(ILLEGAL_VALUE);
1447             TextFieldModel::GetInstance()->SetShowCounter(false);
1448             return;
1449         }
1450         TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1451         return;
1452     }
1453     TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1454     TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1455     TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1456 }
1457 
SetBarState(const JSCallbackInfo & info)1458 void JSTextField::SetBarState(const JSCallbackInfo& info)
1459 {
1460     if (info.Length() < 1) {
1461         TextFieldModel::GetInstance()->SetBarState(DisplayMode::AUTO);
1462         return;
1463     }
1464     auto jsValue = info[0];
1465     if (!jsValue->IsNumber()) {
1466         TextFieldModel::GetInstance()->SetBarState(DisplayMode::AUTO);
1467         return;
1468     }
1469     DisplayMode displayMode = static_cast<DisplayMode>(jsValue->ToNumber<int32_t>());
1470     TextFieldModel::GetInstance()->SetBarState(displayMode);
1471 }
1472 
SetMaxLines(const JSCallbackInfo & info)1473 void JSTextField::SetMaxLines(const JSCallbackInfo& info)
1474 {
1475     if (info.Length() < 1) {
1476         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1477         return;
1478     }
1479     auto jsValue = info[0];
1480     if (!jsValue->IsNumber() || jsValue->ToNumber<int32_t>() <= 0) {
1481         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1482         return;
1483     }
1484     TextFieldModel::GetInstance()->SetMaxViewLines(jsValue->ToNumber<uint32_t>());
1485 }
1486 
SetEnableKeyboardOnFocus(const JSCallbackInfo & info)1487 void JSTextField::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
1488 {
1489     if (info.Length() < 1) {
1490         return;
1491     }
1492     auto jsValue = info[0];
1493     if (jsValue->IsUndefined() || !jsValue->IsBoolean()) {
1494         TextFieldModel::GetInstance()->RequestKeyboardOnFocus(true);
1495         return;
1496     }
1497     TextFieldModel::GetInstance()->RequestKeyboardOnFocus(jsValue->ToBoolean());
1498 }
1499 
SetSelectionMenuHidden(const JSCallbackInfo & info)1500 void JSTextField::SetSelectionMenuHidden(const JSCallbackInfo& info)
1501 {
1502     if (info.Length() < 1) {
1503         return;
1504     }
1505     auto jsValue = info[0];
1506     if (jsValue->IsUndefined() || !jsValue->IsBoolean()) {
1507         TextFieldModel::GetInstance()->SetSelectionMenuHidden(false);
1508         return;
1509     }
1510     TextFieldModel::GetInstance()->SetSelectionMenuHidden(jsValue->ToBoolean());
1511 }
1512 
ParseJsCustomKeyboardBuilder(const JSCallbackInfo & info,int32_t index,std::function<void ()> & buildFunc)1513 bool JSTextField::ParseJsCustomKeyboardBuilder(
1514     const JSCallbackInfo& info, int32_t index, std::function<void()>& buildFunc)
1515 {
1516     if (info.Length() <= static_cast<uint32_t>(index) || !info[index]->IsObject()) {
1517         return false;
1518     }
1519     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[index]);
1520     auto builder = obj->GetProperty("builder");
1521     if (!builder->IsFunction()) {
1522         return false;
1523     }
1524     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1525     CHECK_NULL_RETURN(builderFunc, false);
1526     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1527     buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = targetNode]() {
1528         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1529         ACE_SCORING_EVENT("CustomKeyboard");
1530         PipelineContext::SetCallBackNode(node);
1531         func->Execute();
1532     };
1533     return true;
1534 }
1535 
SetCustomKeyboard(const JSCallbackInfo & info)1536 void JSTextField::SetCustomKeyboard(const JSCallbackInfo& info)
1537 {
1538     if (info.Length() < 1) {
1539         return;
1540     }
1541     auto jsValue = info[0];
1542     if (jsValue->IsUndefined() || jsValue->IsNull() || !jsValue->IsObject()) {
1543         TextFieldModel::GetInstance()->SetCustomKeyboard(nullptr);
1544         return;
1545     }
1546     bool supportAvoidance = false;
1547     if (info.Length() == 2 && info[1]->IsObject()) {  //  2 here refers to the number of parameters
1548         auto paramObject = JSRef<JSObject>::Cast(info[1]);
1549         auto isSupportAvoidance = paramObject->GetProperty("supportAvoidance");
1550         if (!isSupportAvoidance->IsNull() && isSupportAvoidance->IsBoolean()) {
1551             supportAvoidance = isSupportAvoidance->ToBoolean();
1552         }
1553     }
1554     std::function<void()> buildFunc;
1555     if (ParseJsCustomKeyboardBuilder(info, 0, buildFunc)) {
1556         TextFieldModel::GetInstance()->SetCustomKeyboard(std::move(buildFunc), supportAvoidance);
1557     }
1558 }
1559 
SetPasswordRules(const JSCallbackInfo & info)1560 void JSTextField::SetPasswordRules(const JSCallbackInfo& info)
1561 {
1562     auto jsValue = info[0];
1563     if (!jsValue->IsString()) {
1564         return;
1565     }
1566     auto passwordRules = jsValue->ToString();
1567     TextFieldModel::GetInstance()->SetPasswordRules(passwordRules);
1568 }
1569 
SetEnableAutoFill(const JSCallbackInfo & info)1570 void JSTextField::SetEnableAutoFill(const JSCallbackInfo& info)
1571 {
1572     auto jsValue = info[0];
1573     if (!jsValue->IsBoolean()) {
1574         TextFieldModel::GetInstance()->SetEnableAutoFill(true);
1575         return;
1576     }
1577     TextFieldModel::GetInstance()->SetEnableAutoFill(jsValue->ToBoolean());
1578 }
1579 
ConvertStrToCleanNodeStyle(const std::string & value)1580 static CleanNodeStyle ConvertStrToCleanNodeStyle(const std::string& value)
1581 {
1582     if (value == "CONSTANT") {
1583         return CleanNodeStyle::CONSTANT;
1584     } else if (value == "INVISIBLE") {
1585         return CleanNodeStyle::INVISIBLE;
1586     } else {
1587         return CleanNodeStyle::INPUT;
1588     }
1589 }
1590 
SetCancelButton(const JSCallbackInfo & info)1591 void JSTextField::SetCancelButton(const JSCallbackInfo& info)
1592 {
1593     if (info.Length() < 1 || !info[0]->IsObject()) {
1594         ResetCancelIcon();
1595         return;
1596     }
1597     auto param = JSRef<JSObject>::Cast(info[0]);
1598     auto theme = GetTheme<TextFieldTheme>();
1599     CHECK_NULL_VOID(theme);
1600 
1601     // set style
1602     std::string styleStr;
1603     CleanNodeStyle cleanNodeStyle;
1604     auto styleProp = param->GetProperty("style");
1605     if (!styleProp->IsNull() && ParseJsString(styleProp, styleStr)) {
1606         cleanNodeStyle = ConvertStrToCleanNodeStyle(styleStr);
1607     } else {
1608         cleanNodeStyle = CleanNodeStyle::INPUT;
1609     }
1610     TextFieldModel::GetInstance()->SetCleanNodeStyle(cleanNodeStyle);
1611     TextFieldModel::GetInstance()->SetIsShowCancelButton(true);
1612 
1613     // set default icon
1614     auto iconJsVal = param->GetProperty("icon");
1615     if (iconJsVal->IsUndefined() || iconJsVal->IsNull() || !iconJsVal->IsObject()) {
1616         SetCancelDefaultIcon();
1617         return;
1618     }
1619 
1620     auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
1621     bool isSymbolIcon = iconParam->HasProperty("fontColor"); // only SymbolGlyph has fontColor property
1622     if (isSymbolIcon) {
1623         SetCancelSymbolIcon(info);
1624         return;
1625     }
1626 
1627     // set icon size
1628     CalcDimension iconSize;
1629     auto iconSizeProp = iconParam->GetProperty("size");
1630     if (!iconSizeProp->IsUndefined() && !iconSizeProp->IsNull() && ParseJsDimensionVpNG(iconSizeProp, iconSize)) {
1631         if (LessNotEqual(iconSize.Value(), 0.0) || iconSize.Unit() == DimensionUnit::PERCENT) {
1632             iconSize = theme->GetCancelIconSize();
1633         }
1634     } else {
1635         iconSize = theme->GetCancelIconSize();
1636     }
1637     TextFieldModel::GetInstance()->SetCancelIconSize(iconSize);
1638     SetCancelIconColorAndIconSrc(iconParam);
1639 }
1640 
SetCancelDefaultIcon()1641 void JSTextField::SetCancelDefaultIcon()
1642 {
1643     auto theme = GetTheme<TextFieldTheme>();
1644     CHECK_NULL_VOID(theme);
1645     if (Container::CurrentColorMode() == ColorMode::DARK) {
1646         TextFieldModel::GetInstance()->SetCancelIconColor(theme->GetCancelButtonIconColor());
1647     } else {
1648         TextFieldModel::GetInstance()->SetCancelIconColor(Color());
1649     }
1650     TextFieldModel::GetInstance()->SetCancelIconSize(theme->GetCancelIconSize());
1651     TextFieldModel::GetInstance()->SetCanacelIconSrc(std::string(), std::string(), std::string());
1652     TextFieldModel::GetInstance()->SetCancelSymbolIcon(nullptr);
1653     TextFieldModel::GetInstance()->SetCancelButtonSymbol(true);
1654 }
1655 
ResetCancelIcon()1656 void JSTextField::ResetCancelIcon()
1657 {
1658     TextFieldModel::GetInstance()->SetCleanNodeStyle(CleanNodeStyle::INPUT);
1659     TextFieldModel::GetInstance()->SetIsShowCancelButton(false);
1660     TextFieldModel::GetInstance()->SetCancelSymbolIcon(nullptr);
1661     TextFieldModel::GetInstance()->SetCancelButtonSymbol(true);
1662 }
1663 
SetCancelSymbolIcon(const JSCallbackInfo & info)1664 void JSTextField::SetCancelSymbolIcon(const JSCallbackInfo& info)
1665 {
1666     if (info[0]->IsObject()) {
1667         std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
1668         auto param = JSRef<JSObject>::Cast(info[0]);
1669         auto iconProp = param->GetProperty("icon");
1670         SetSymbolOptionApply(info, iconSymbol, iconProp);
1671         TextFieldModel::GetInstance()->SetCancelSymbolIcon(iconSymbol);
1672         TextFieldModel::GetInstance()->SetCancelButtonSymbol(true);
1673     }
1674 }
1675 
SetCancelIconColorAndIconSrc(const JSRef<JSObject> & iconParam)1676 void JSTextField::SetCancelIconColorAndIconSrc(const JSRef<JSObject>& iconParam)
1677 {
1678     auto theme = GetTheme<TextFieldTheme>();
1679     CHECK_NULL_VOID(theme);
1680     // set icon src
1681     std::string iconSrc;
1682     std::string bundleName;
1683     std::string moduleName;
1684     auto iconSrcProp = iconParam->GetProperty("src");
1685     if (iconSrcProp->IsUndefined() || iconSrcProp->IsNull() || !ParseJsMedia(iconSrcProp, iconSrc)) {
1686         iconSrc = "";
1687     }
1688     GetJsMediaBundleInfo(iconSrcProp, bundleName, moduleName);
1689     TextFieldModel::GetInstance()->SetCanacelIconSrc(iconSrc, bundleName, moduleName);
1690     TextFieldModel::GetInstance()->SetCancelButtonSymbol(false);
1691     // set icon color
1692     Color iconColor;
1693     auto iconColorProp = iconParam->GetProperty("color");
1694     if (!iconColorProp->IsUndefined() && !iconColorProp->IsNull() && ParseJsColor(iconColorProp, iconColor)) {
1695         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1696         return;
1697     }
1698     auto info = ImageSourceInfo(iconSrc, bundleName, moduleName);
1699     if (info.IsSvg() && iconSrc != "") {
1700         // svg need not default color, otherwise multi color svg will render fault
1701         return;
1702     }
1703     if (Container::CurrentColorMode() == ColorMode::DARK) {
1704         TextFieldModel::GetInstance()->SetCancelIconColor(theme->GetCancelButtonIconColor());
1705     } else {
1706         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1707     }
1708 }
1709 
SetSelectAllValue(const JSCallbackInfo & info)1710 void JSTextField::SetSelectAllValue(const JSCallbackInfo& info)
1711 {
1712     auto infoValue = info[0];
1713     if (!infoValue->IsBoolean() || infoValue->IsUndefined() || infoValue->IsNull()) {
1714         TextFieldModel::GetInstance()->SetSelectAllValue(false);
1715         return;
1716     }
1717 
1718     bool isSetSelectAllValue = infoValue->ToBoolean();
1719     TextFieldModel::GetInstance()->SetSelectAllValue(isSetSelectAllValue);
1720 }
1721 
SetKeyboardAppearance(const JSCallbackInfo & info)1722 void JSTextField::SetKeyboardAppearance(const JSCallbackInfo& info)
1723 {
1724     if (info.Length() != 1 || !info[0]->IsNumber()) {
1725         TextFieldModel::GetInstance()->SetKeyboardAppearance(
1726             static_cast<KeyboardAppearance>(KeyboardAppearance::NONE_IMMERSIVE));
1727         return;
1728     }
1729     auto keyboardAppearance = info[0]->ToNumber<uint32_t>();
1730     if (keyboardAppearance < static_cast<uint32_t>(KeyboardAppearance::NONE_IMMERSIVE) ||
1731         keyboardAppearance > static_cast<uint32_t>(KeyboardAppearance::DARK_IMMERSIVE)) {
1732         TextFieldModel::GetInstance()->SetKeyboardAppearance(
1733             static_cast<KeyboardAppearance>(KeyboardAppearance::NONE_IMMERSIVE));
1734         return;
1735     }
1736     TextFieldModel::GetInstance()->
1737         SetKeyboardAppearance(static_cast<KeyboardAppearance>(keyboardAppearance));
1738 }
1739 
SetDecoration(const JSCallbackInfo & info)1740 void JSTextField::SetDecoration(const JSCallbackInfo& info)
1741 {
1742     do {
1743         auto tmpInfo = info[0];
1744         if (!tmpInfo->IsObject()) {
1745             TextFieldModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
1746             TextFieldModel::GetInstance()->SetTextDecorationColor(Color::BLACK);
1747             TextFieldModel::GetInstance()->SetTextDecorationStyle(TextDecorationStyle::SOLID);
1748             break;
1749         }
1750         JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
1751         JSRef<JSVal> typeValue = obj->GetProperty("type");
1752         JSRef<JSVal> colorValue = obj->GetProperty("color");
1753         JSRef<JSVal> styleValue = obj->GetProperty("style");
1754 
1755         auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
1756         CHECK_NULL_VOID(pipelineContext);
1757         auto theme = pipelineContext->GetTheme<TextFieldTheme>();
1758         CHECK_NULL_VOID(theme);
1759         TextDecoration textDecoration = theme->GetTextStyle().GetTextDecoration();
1760         if (typeValue->IsNumber()) {
1761             textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
1762         }
1763         Color result = theme->GetTextStyle().GetTextDecorationColor();
1764         ParseJsColor(colorValue, result, Color::BLACK);
1765         std::optional<TextDecorationStyle> textDecorationStyle;
1766         if (styleValue->IsNumber()) {
1767             textDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
1768         } else {
1769             textDecorationStyle = DEFAULT_TEXT_DECORATION_STYLE;
1770         }
1771         TextFieldModel::GetInstance()->SetTextDecoration(textDecoration);
1772         TextFieldModel::GetInstance()->SetTextDecorationColor(result);
1773         if (textDecorationStyle) {
1774             TextFieldModel::GetInstance()->SetTextDecorationStyle(textDecorationStyle.value());
1775         }
1776     } while (false);
1777 }
1778 
SetMinFontSize(const JSCallbackInfo & info)1779 void JSTextField::SetMinFontSize(const JSCallbackInfo& info)
1780 {
1781     if (info.Length() < 1) {
1782         return;
1783     }
1784     CalcDimension minFontSize;
1785     if (!ParseJsDimensionFpNG(info[0], minFontSize, false)) {
1786         TextFieldModel::GetInstance()->SetAdaptMinFontSize(CalcDimension());
1787         return;
1788     }
1789     if (minFontSize.IsNegative()) {
1790         minFontSize = CalcDimension();
1791     }
1792     TextFieldModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
1793 }
1794 
SetMaxFontSize(const JSCallbackInfo & info)1795 void JSTextField::SetMaxFontSize(const JSCallbackInfo& info)
1796 {
1797     if (info.Length() < 1) {
1798         return;
1799     }
1800     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
1801     CHECK_NULL_VOID(pipelineContext);
1802     auto theme = pipelineContext->GetTheme<TextFieldTheme>();
1803     CHECK_NULL_VOID(theme);
1804     CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1805     if (!ParseJsDimensionFpNG(info[0], maxFontSize, false)) {
1806         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1807         TextFieldModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1808         return;
1809     }
1810     if (maxFontSize.IsNegative()) {
1811         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1812     }
1813     TextFieldModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1814 }
1815 
SetHeightAdaptivePolicy(int32_t value)1816 void JSTextField::SetHeightAdaptivePolicy(int32_t value)
1817 {
1818     if (value < 0 || value >= static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
1819         value = 0;
1820     }
1821     TextFieldModel::GetInstance()->SetHeightAdaptivePolicy(HEIGHT_ADAPTIVE_POLICY[value]);
1822 }
1823 
SetLetterSpacing(const JSCallbackInfo & info)1824 void JSTextField::SetLetterSpacing(const JSCallbackInfo& info)
1825 {
1826     CalcDimension value;
1827     if (!ParseJsDimensionFpNG(info[0], value, false)) {
1828         value.Reset();
1829         TextFieldModel::GetInstance()->SetLetterSpacing(value);
1830         return;
1831     }
1832     TextFieldModel::GetInstance()->SetLetterSpacing(value);
1833 }
1834 
SetLineHeight(const JSCallbackInfo & info)1835 void JSTextField::SetLineHeight(const JSCallbackInfo& info)
1836 {
1837     CalcDimension value;
1838     if (!ParseJsDimensionFpNG(info[0], value)) {
1839         value.Reset();
1840         TextFieldModel::GetInstance()->SetLineHeight(value);
1841         return;
1842     }
1843     if (value.IsNegative()) {
1844         value.Reset();
1845     }
1846     TextFieldModel::GetInstance()->SetLineHeight(value);
1847 }
1848 
SetHalfLeading(const JSCallbackInfo & info)1849 void JSTextField::SetHalfLeading(const JSCallbackInfo& info)
1850 {
1851     if (info.Length() < 1) {
1852         return;
1853     }
1854     auto jsValue = info[0];
1855     bool halfLeading = jsValue->IsBoolean() ? jsValue->ToBoolean() : false;
1856     TextFieldModel::GetInstance()->SetHalfLeading(halfLeading);
1857 }
1858 
SetLineSpacing(const JSCallbackInfo & info)1859 void JSTextField::SetLineSpacing(const JSCallbackInfo& info)
1860 {
1861     CalcDimension value;
1862     if (!ParseLengthMetricsToPositiveDimension(info[0], value)) {
1863         value.Reset();
1864     }
1865     if (value.IsNegative()) {
1866         value.Reset();
1867     }
1868     TextFieldModel::GetInstance()->SetLineSpacing(value);
1869 }
1870 
SetFontFeature(const JSCallbackInfo & info)1871 void JSTextField::SetFontFeature(const JSCallbackInfo& info)
1872 {
1873     if (info.Length() < 1) {
1874         return;
1875     }
1876     auto jsValue = info[0];
1877     std::string fontFeatureSettings = "";
1878     if (jsValue->IsString()) {
1879         fontFeatureSettings = jsValue->ToString();
1880     }
1881     TextFieldModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
1882 }
1883 
SetTextOverflow(const JSCallbackInfo & info)1884 void JSTextField::SetTextOverflow(const JSCallbackInfo& info)
1885 {
1886     do {
1887         if (info.Length() < 1) {
1888             break;
1889         }
1890         auto tmpInfo = info[0];
1891         int32_t overflow = 0;
1892         if (tmpInfo->IsUndefined() || tmpInfo->IsNull() || !tmpInfo->IsNumber()) {
1893             overflow = DEFAULT_OVERFLOW;
1894         } else if (tmpInfo->IsNumber()) {
1895             overflow = tmpInfo->ToNumber<int32_t>();
1896             if (overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
1897                 overflow = DEFAULT_OVERFLOW;
1898             }
1899         }
1900         TextFieldModel::GetInstance()->SetTextOverflow(TEXT_OVERFLOWS[overflow]);
1901     } while (false);
1902 
1903     info.SetReturnValue(info.This());
1904 }
1905 
SetTextIndent(const JSCallbackInfo & info)1906 void JSTextField::SetTextIndent(const JSCallbackInfo& info)
1907 {
1908     CalcDimension value;
1909     if (!ParseJsDimensionVpNG(info[0], value, true)) {
1910         value.Reset();
1911     }
1912     TextFieldModel::GetInstance()->SetTextIndent(value);
1913 }
1914 
CreateJsAboutToIMEInputObj(const InsertValueInfo & insertValue)1915 JSRef<JSVal> JSTextField::CreateJsAboutToIMEInputObj(const InsertValueInfo& insertValue)
1916 {
1917     JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1918     aboutToIMEInputObj->SetProperty<int32_t>("insertOffset", insertValue.insertOffset);
1919     aboutToIMEInputObj->SetProperty<std::u16string>("insertValue", insertValue.insertValue);
1920     return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1921 }
1922 
OnWillInsertValue(const JSCallbackInfo & info)1923 void JSTextField::OnWillInsertValue(const JSCallbackInfo& info)
1924 {
1925     auto jsValue = info[0];
1926     CHECK_NULL_VOID(jsValue->IsFunction());
1927     auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1928         JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1929     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1930                         const InsertValueInfo& insertValue) -> bool {
1931         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1932         auto ret = func->ExecuteWithValue(insertValue);
1933         if (ret->IsBoolean()) {
1934             return ret->ToBoolean();
1935         }
1936         return true;
1937     };
1938     TextFieldModel::GetInstance()->SetOnWillInsertValueEvent(std::move(callback));
1939 }
1940 
CreateJsDeleteToIMEObj(const DeleteValueInfo & deleteValueInfo)1941 JSRef<JSVal> JSTextField::CreateJsDeleteToIMEObj(const DeleteValueInfo& deleteValueInfo)
1942 {
1943     JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1944     aboutToIMEInputObj->SetProperty<int32_t>("deleteOffset", deleteValueInfo.deleteOffset);
1945     aboutToIMEInputObj->SetProperty<int32_t>("direction", static_cast<int32_t>(deleteValueInfo.direction));
1946     aboutToIMEInputObj->SetProperty<std::u16string>("deleteValue", deleteValueInfo.deleteValue);
1947     return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1948 }
1949 
OnDidInsertValue(const JSCallbackInfo & info)1950 void JSTextField::OnDidInsertValue(const JSCallbackInfo& info)
1951 {
1952     auto jsValue = info[0];
1953     CHECK_NULL_VOID(jsValue->IsFunction());
1954     auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1955         JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1956     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1957                         const InsertValueInfo& insertValue) {
1958         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1959         func->ExecuteWithValue(insertValue);
1960     };
1961     TextFieldModel::GetInstance()->SetOnDidInsertValueEvent(std::move(callback));
1962 }
1963 
OnWillDelete(const JSCallbackInfo & info)1964 void JSTextField::OnWillDelete(const JSCallbackInfo& info)
1965 {
1966     auto jsValue = info[0];
1967     CHECK_NULL_VOID(jsValue->IsFunction());
1968     auto jsAboutToIMEInputFunc =
1969         AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1970     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1971                         const DeleteValueInfo& deleteValue) {
1972         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1973         auto ret = func->ExecuteWithValue(deleteValue);
1974         if (ret->IsBoolean()) {
1975             return ret->ToBoolean();
1976         }
1977         return true;
1978     };
1979     TextFieldModel::GetInstance()->SetOnWillDeleteEvent(std::move(callback));
1980 }
1981 
OnDidDelete(const JSCallbackInfo & info)1982 void JSTextField::OnDidDelete(const JSCallbackInfo& info)
1983 {
1984     auto jsValue = info[0];
1985     CHECK_NULL_VOID(jsValue->IsFunction());
1986     auto jsAboutToIMEInputFunc =
1987         AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1988     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1989                         const DeleteValueInfo& deleteValue) {
1990         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1991         func->ExecuteWithValue(deleteValue);
1992     };
1993     TextFieldModel::GetInstance()->SetOnDidDeleteEvent(std::move(callback));
1994 }
1995 
EditMenuOptions(const JSCallbackInfo & info)1996 void JSTextField::EditMenuOptions(const JSCallbackInfo& info)
1997 {
1998     NG::OnCreateMenuCallback onCreateMenuCallback;
1999     NG::OnMenuItemClickCallback onMenuItemClick;
2000     JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick);
2001     TextFieldModel::GetInstance()->SetSelectionMenuOptions(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
2002 }
2003 
SetEnablePreviewText(const JSCallbackInfo & info)2004 void JSTextField::SetEnablePreviewText(const JSCallbackInfo& info)
2005 {
2006     auto jsValue = info[0];
2007     if (!jsValue->IsBoolean()) {
2008         TextFieldModel::GetInstance()->SetEnablePreviewText(true);
2009         return;
2010     }
2011     TextFieldModel::GetInstance()->SetEnablePreviewText(jsValue->ToBoolean());
2012 }
2013 
SetEnableHapticFeedback(const JSCallbackInfo & info)2014 void JSTextField::SetEnableHapticFeedback(const JSCallbackInfo& info)
2015 {
2016     bool state = true;
2017     if (info.Length() > 0 && info[0]->IsBoolean()) {
2018         state = info[0]->ToBoolean();
2019     }
2020     TextFieldModel::GetInstance()->SetEnableHapticFeedback(state);
2021 }
2022 
SetEllipsisMode(const JSCallbackInfo & info)2023 void JSTextField::SetEllipsisMode(const JSCallbackInfo& info)
2024 {
2025     JSRef<JSVal> args = info[0];
2026     if (!args->IsNumber()) {
2027         TextFieldModel::GetInstance()->SetEllipsisMode(EllipsisMode::TAIL);
2028         return;
2029     }
2030     uint32_t index = args->ToNumber<uint32_t>();
2031     if (index < ELLIPSIS_MODALS.size()) {
2032         TextFieldModel::GetInstance()->SetEllipsisMode(ELLIPSIS_MODALS[index]);
2033     }
2034 }
2035 
SetStopBackPress(const JSCallbackInfo & info)2036 void JSTextField::SetStopBackPress(const JSCallbackInfo& info)
2037 {
2038     bool isStopBackPress = true;
2039     if (info.Length() > 0 && info[0]->IsBoolean()) {
2040         isStopBackPress = info[0]->ToBoolean();
2041     }
2042     TextFieldModel::GetInstance()->SetStopBackPress(isStopBackPress);
2043 }
2044 
CreateJsOnWillChangeObj(const ChangeValueInfo & changeValueInfo)2045 JSRef<JSVal> JSTextField::CreateJsOnWillChangeObj(const ChangeValueInfo& changeValueInfo)
2046 {
2047     JSRef<JSObject> ChangeValueInfo = JSRef<JSObject>::New();
2048     ChangeValueInfo->SetProperty<std::u16string>("content", changeValueInfo.value);
2049 
2050     auto previewTextObj = CreateJsOnChangeObj(changeValueInfo.previewText);
2051     ChangeValueInfo->SetPropertyObject("previewText", previewTextObj);
2052 
2053     auto optionsObj = JSRef<JSObject>::New();
2054     auto rangeBeforeObj = JSRef<JSObject>::New();
2055     rangeBeforeObj->SetProperty<int32_t>("start", changeValueInfo.rangeBefore.start);
2056     rangeBeforeObj->SetProperty<int32_t>("end", changeValueInfo.rangeBefore.end);
2057     optionsObj->SetPropertyObject("rangeBefore", rangeBeforeObj);
2058     auto rangeAfterObj = JSRef<JSObject>::New();
2059     rangeAfterObj->SetProperty<int32_t>("start", changeValueInfo.rangeAfter.start);
2060     rangeAfterObj->SetProperty<int32_t>("end", changeValueInfo.rangeAfter.end);
2061     optionsObj->SetPropertyObject("rangeAfter", rangeAfterObj);
2062     optionsObj->SetProperty<std::u16string>("oldContent", changeValueInfo.oldContent);
2063     auto oldPreviewTextObj = CreateJsOnChangeObj(changeValueInfo.oldPreviewText);
2064     optionsObj->SetPropertyObject("oldPreviewText", oldPreviewTextObj);
2065 
2066     ChangeValueInfo->SetPropertyObject("options", optionsObj);
2067     return JSRef<JSVal>::Cast(ChangeValueInfo);
2068 }
2069 
SetOnWillChange(const JSCallbackInfo & info)2070 void JSTextField::SetOnWillChange(const JSCallbackInfo& info)
2071 {
2072     auto jsValue = info[0];
2073     CHECK_NULL_VOID(jsValue->IsFunction());
2074     auto jsChangeFunc = AceType::MakeRefPtr<JsEventFunction<ChangeValueInfo, 1>>(
2075         JSRef<JSFunc>::Cast(jsValue), CreateJsOnWillChangeObj);
2076     auto onWillChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
2077         const ChangeValueInfo& changeValue) {
2078         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
2079         ACE_SCORING_EVENT("onWillChange");
2080         auto ret = func->ExecuteWithValue(changeValue);
2081         if (ret->IsBoolean()) {
2082             return ret->ToBoolean();
2083         }
2084         return true;
2085     };
2086     TextFieldModel::GetInstance()->SetOnWillChangeEvent(std::move(onWillChange));
2087 }
2088 
2089 } // namespace OHOS::Ace::Framework
2090