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