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