• 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 #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<JsFunction>(JSRef<JSFunc>::Cast(jsValue));
955     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
956         const ChangeValueInfo& changeValueInfo) {
957         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
958         ACE_SCORING_EVENT("onChange");
959         JSRef<JSVal> valueObj = JSRef<JSVal>::Make(ToJSValue(changeValueInfo.value));
960         auto previewTextObj = CreateJsOnChangeObj(changeValueInfo.previewText);
961         auto optionsObj = JSRef<JSObject>::New();
962         auto rangeBeforeObj = JSRef<JSObject>::New();
963         rangeBeforeObj->SetProperty<int32_t>("start", changeValueInfo.rangeBefore.start);
964         rangeBeforeObj->SetProperty<int32_t>("end", changeValueInfo.rangeBefore.end);
965         optionsObj->SetPropertyObject("rangeBefore", rangeBeforeObj);
966         auto rangeAfterObj = JSRef<JSObject>::New();
967         rangeAfterObj->SetProperty<int32_t>("start", changeValueInfo.rangeAfter.start);
968         rangeAfterObj->SetProperty<int32_t>("end", changeValueInfo.rangeAfter.end);
969         optionsObj->SetPropertyObject("rangeAfter", rangeAfterObj);
970         optionsObj->SetProperty<std::string>("oldContent", changeValueInfo.oldContent);
971         auto oldPreviewTextObj = CreateJsOnChangeObj(changeValueInfo.oldPreviewText);
972         optionsObj->SetPropertyObject("oldPreviewText", oldPreviewTextObj);
973         JSRef<JSVal> argv[] = { valueObj, previewTextObj, optionsObj };
974         func->ExecuteJS(3, argv);
975     };
976     TextFieldModel::GetInstance()->SetOnChange(std::move(onChange));
977 }
978 
SetOnTextSelectionChange(const JSCallbackInfo & info)979 void JSTextField::SetOnTextSelectionChange(const JSCallbackInfo& info)
980 {
981     auto jsValue = info[0];
982     CHECK_NULL_VOID(jsValue->IsFunction());
983     JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
984     TextFieldModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
985 }
986 
SetOnSecurityStateChange(const JSCallbackInfo & info)987 void JSTextField::SetOnSecurityStateChange(const JSCallbackInfo& info)
988 {
989     auto jsValue = info[0];
990     CHECK_NULL_VOID(jsValue->IsFunction());
991     JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
992     TextFieldModel::GetInstance()->SetOnSecurityStateChange(std::move(callback));
993 }
994 
SetOnContentScroll(const JSCallbackInfo & info)995 void JSTextField::SetOnContentScroll(const JSCallbackInfo& info)
996 {
997     auto jsValue = info[0];
998     CHECK_NULL_VOID(jsValue->IsFunction());
999     JsEventCallback<void(float, float)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1000     TextFieldModel::GetInstance()->SetOnContentScroll(std::move(callback));
1001 }
1002 
SetOnCopy(const JSCallbackInfo & info)1003 void JSTextField::SetOnCopy(const JSCallbackInfo& info)
1004 {
1005     auto jsValue = info[0];
1006     CHECK_NULL_VOID(jsValue->IsFunction());
1007     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1008     TextFieldModel::GetInstance()->SetOnCopy(std::move(callback));
1009 }
1010 
SetOnCut(const JSCallbackInfo & info)1011 void JSTextField::SetOnCut(const JSCallbackInfo& info)
1012 {
1013     auto jsValue = info[0];
1014     CHECK_NULL_VOID(jsValue->IsFunction());
1015     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1016     TextFieldModel::GetInstance()->SetOnCut(std::move(callback));
1017 }
1018 
CreateJSTextCommonEvent(NG::TextCommonEvent & event)1019 JSRef<JSVal> JSTextField::CreateJSTextCommonEvent(NG::TextCommonEvent& event)
1020 {
1021     JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1022     objectTemplate->SetInternalFieldCount(1);
1023     JSRef<JSObject> object = objectTemplate->NewInstance();
1024     object->SetPropertyObject("preventDefault", JSRef<JSFunc>::New<FunctionCallback>(JsPreventDefault));
1025     object->Wrap<NG::TextCommonEvent>(&event);
1026     return JSRef<JSVal>::Cast(object);
1027 }
1028 
SetOnPaste(const JSCallbackInfo & info)1029 void JSTextField::SetOnPaste(const JSCallbackInfo& info)
1030 {
1031     auto jsValue = info[0];
1032     CHECK_NULL_VOID(jsValue->IsFunction());
1033     auto jsTextFunc = AceType::MakeRefPtr<JsCitedEventFunction<NG::TextCommonEvent, 2>>(
1034         JSRef<JSFunc>::Cast(jsValue), CreateJSTextCommonEvent);
1035 
1036     auto onPaste = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc)](
1037         const std::string& val, NG::TextCommonEvent& info) {
1038         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1039         ACE_SCORING_EVENT("onPaste");
1040         func->Execute(val, info);
1041     };
1042     TextFieldModel::GetInstance()->SetOnPasteWithEvent(std::move(onPaste));
1043 }
1044 
SetOnClick(const JSCallbackInfo & info)1045 void JSTextField::SetOnClick(const JSCallbackInfo& info)
1046 {
1047     if (Container::IsCurrentUseNewPipeline()) {
1048         JSInteractableView::JsOnClick(info);
1049         return;
1050     }
1051     JsEventCallback<void(const ClickInfo&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
1052     TextFieldModel::GetInstance()->SetOnClick(std::move(callback));
1053     info.ReturnSelf();
1054 }
1055 
SetCopyOption(const JSCallbackInfo & info)1056 void JSTextField::SetCopyOption(const JSCallbackInfo& info)
1057 {
1058     if (info.Length() == 0) {
1059         return;
1060     }
1061     auto jsValue = info[0];
1062     if (jsValue->IsUndefined()) {
1063         TextFieldModel::GetInstance()->SetCopyOption(CopyOptions::Local);
1064         return;
1065     }
1066     auto copyOptions = CopyOptions::None;
1067     if (jsValue->IsNumber()) {
1068         auto emunNumber = jsValue->ToNumber<int>();
1069         copyOptions = static_cast<CopyOptions>(emunNumber);
1070     }
1071     TextFieldModel::GetInstance()->SetCopyOption(copyOptions);
1072 }
1073 
SetShowUnderline(const JSCallbackInfo & info)1074 void JSTextField::SetShowUnderline(const JSCallbackInfo& info)
1075 {
1076     auto jsValue = info[0];
1077     if (!jsValue->IsBoolean()) {
1078         TextFieldModel::GetInstance()->SetShowUnderline(false);
1079         return;
1080     }
1081     TextFieldModel::GetInstance()->SetShowUnderline(jsValue->ToBoolean());
1082 }
1083 
SetUnderlineColor(const JSCallbackInfo & info)1084 void JSTextField::SetUnderlineColor(const JSCallbackInfo& info)
1085 {
1086     if (info.Length() < 1) {
1087         return;
1088     }
1089     auto jsValue = info[0];
1090     Color underlineColor;
1091     if (ParseJsColor(jsValue, underlineColor)) {
1092         TextFieldModel::GetInstance()->SetNormalUnderlineColor(underlineColor);
1093     } else if (jsValue->IsObject()) {
1094         auto param = JSRef<JSObject>::Cast(jsValue);
1095         UserUnderlineColor userColor = UserUnderlineColor();
1096         auto typingColorProp = param->GetProperty("typing");
1097         Color typing;
1098         if (ParseJsColor(typingColorProp, typing)) {
1099             userColor.typing = typing;
1100         }
1101         auto normalColorProp = param->GetProperty("normal");
1102         Color normal;
1103         if (ParseJsColor(normalColorProp, normal)) {
1104             userColor.normal = normal;
1105         }
1106         auto errorColorProp = param->GetProperty("error");
1107         Color error;
1108         if (ParseJsColor(errorColorProp, error)) {
1109             userColor.error = error;
1110         }
1111         auto disableColorProp = param->GetProperty("disable");
1112         Color disable;
1113         if (ParseJsColor(disableColorProp, disable)) {
1114             userColor.disable = disable;
1115         }
1116         TextFieldModel::GetInstance()->SetUserUnderlineColor(userColor);
1117     } else {
1118         TextFieldModel::GetInstance()->SetUserUnderlineColor(UserUnderlineColor());
1119     }
1120 }
1121 
SetPasswordIcon(const JSCallbackInfo & info)1122 void JSTextField::SetPasswordIcon(const JSCallbackInfo& info)
1123 {
1124     if (!Container::IsCurrentUseNewPipeline()) {
1125         return;
1126     }
1127     auto jsValue = info[0];
1128     if (!jsValue->IsObject()) {
1129         return;
1130     }
1131     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
1132     JSRef<JSVal> showVal = jsObj->GetProperty("onIconSrc");
1133     JSRef<JSVal> hideVal = jsObj->GetProperty("offIconSrc");
1134     PasswordIcon passwordIcon;
1135     if (showVal->IsString()) {
1136         passwordIcon.showResult = showVal->ToString();
1137     }
1138     if (hideVal->IsString()) {
1139         passwordIcon.hideResult = hideVal->ToString();
1140     }
1141     if (showVal->IsObject()) {
1142         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(showVal)->GetProperty("bundleName");
1143         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(showVal)->GetProperty("moduleName");
1144         if (bundleName->IsString()) {
1145             passwordIcon.showBundleName = bundleName->ToString();
1146         }
1147         if (moduleName->IsString()) {
1148             passwordIcon.showModuleName = moduleName->ToString();
1149         }
1150         ParseJsMedia(JSRef<JSObject>::Cast(showVal), passwordIcon.showResult);
1151     }
1152     if (hideVal->IsObject()) {
1153         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("bundleName");
1154         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("moduleName");
1155         if (bundleName->IsString()) {
1156             passwordIcon.hideBundleName = bundleName->ToString();
1157         }
1158         if (moduleName->IsString()) {
1159             passwordIcon.hideModuleName = moduleName->ToString();
1160         }
1161         ParseJsMedia(JSRef<JSObject>::Cast(hideVal), passwordIcon.hideResult);
1162     }
1163     if (!showVal->IsString() && !showVal->IsObject()) {
1164         passwordIcon.showResult = "";
1165     }
1166     if (!hideVal->IsString() && !hideVal->IsObject()) {
1167         passwordIcon.hideResult = "";
1168     }
1169     TextFieldModel::GetInstance()->SetPasswordIcon(passwordIcon);
1170 }
1171 
UpdateDecoration(const RefPtr<BoxComponent> & boxComponent,const RefPtr<TextFieldComponent> & component,const Border & boxBorder,const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme> & textFieldTheme)1172 void JSTextField::UpdateDecoration(const RefPtr<BoxComponent>& boxComponent,
1173     const RefPtr<TextFieldComponent>& component, const Border& boxBorder,
1174     const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)
1175 {
1176     if (!textFieldTheme) {
1177         return;
1178     }
1179 
1180     RefPtr<Decoration> decoration = component->GetDecoration();
1181     RefPtr<Decoration> boxDecoration = boxComponent->GetBackDecoration();
1182     if (!decoration) {
1183         decoration = AceType::MakeRefPtr<Decoration>();
1184     }
1185     if (boxDecoration) {
1186         Border border = decoration->GetBorder();
1187         border.SetLeftEdge(boxBorder.Left());
1188         border.SetRightEdge(boxBorder.Right());
1189         border.SetTopEdge(boxBorder.Top());
1190         border.SetBottomEdge(boxBorder.Bottom());
1191         border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1192         decoration->SetBorder(border);
1193         component->SetOriginBorder(decoration->GetBorder());
1194 
1195         if (boxDecoration->GetImage() || boxDecoration->GetGradient().IsValid()) {
1196             // clear box properties except background image and radius.
1197             boxDecoration->SetBackgroundColor(Color::TRANSPARENT);
1198             Border border;
1199             border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1200             boxDecoration->SetBorder(border);
1201         }
1202     } else {
1203         boxDecoration = AceType::MakeRefPtr<Decoration>();
1204         boxDecoration->SetBorderRadius(textFieldTheme->GetBorderRadius());
1205         boxComponent->SetBackDecoration(boxDecoration);
1206     }
1207 }
1208 
SetShowUnit(const JSCallbackInfo & info)1209 void JSTextField::SetShowUnit(const JSCallbackInfo& info)
1210 {
1211     auto jsValue = info[0];
1212     if (!jsValue->IsFunction()) {
1213         return;
1214     }
1215 
1216     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsValue));
1217     auto unitFunc = [builderFunc]() { builderFunc->Execute(); };
1218     TextFieldModel::GetInstance()->SetShowUnit(std::move(unitFunc));
1219 }
1220 
SetShowError(const JSCallbackInfo & info)1221 void JSTextField::SetShowError(const JSCallbackInfo& info)
1222 {
1223     auto jsValue = info[0];
1224     if (Container::IsCurrentUseNewPipeline()) {
1225         bool isVisible = false;
1226         std::string errorText;
1227         if (ParseJsString(jsValue, errorText)) {
1228             isVisible = true;
1229         }
1230         TextFieldModel::GetInstance()->SetShowError(errorText, isVisible);
1231     }
1232 }
1233 
SetShowCounter(const JSCallbackInfo & info)1234 void JSTextField::SetShowCounter(const JSCallbackInfo& info)
1235 {
1236     auto jsValue = info[0];
1237     auto secondJSValue = info[1];
1238     if ((!jsValue->IsBoolean() && !secondJSValue->IsObject())) {
1239         LOGI("The info is wrong, it is supposed to be a boolean");
1240         TextFieldModel::GetInstance()->SetShowCounter(false);
1241         return;
1242     }
1243     if (secondJSValue->IsObject()) {
1244         auto paramObject = JSRef<JSObject>::Cast(secondJSValue);
1245         auto param = paramObject->GetProperty("highlightBorder");
1246         auto isBorderShow = param->ToBoolean();
1247         if (!param->IsBoolean() || param->IsUndefined() || param->IsNull()) {
1248             TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1249         } else {
1250             TextFieldModel::GetInstance()->SetShowCounterBorder(isBorderShow);
1251         }
1252         auto parameter = paramObject->GetProperty("thresholdPercentage");
1253         auto inputNumber = parameter->ToNumber<int32_t>();
1254         TextFieldModel::GetInstance()->SetCounterType(inputNumber);
1255         if (parameter->IsNull() || parameter->IsUndefined()) {
1256             TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1257             TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1258             return;
1259         }
1260         if (static_cast<uint32_t>(inputNumber) < MINI_VAILD_VALUE ||
1261             static_cast<uint32_t>(inputNumber) > MAX_VAILD_VALUE) {
1262             LOGI("The info is wrong, it is supposed to be a right number");
1263             TextFieldModel::GetInstance()->SetCounterType(ILLEGAL_VALUE);
1264             TextFieldModel::GetInstance()->SetShowCounter(false);
1265             return;
1266         }
1267         TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1268         return;
1269     }
1270     TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1271     TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1272     TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1273 }
1274 
SetBarState(const JSCallbackInfo & info)1275 void JSTextField::SetBarState(const JSCallbackInfo& info)
1276 {
1277     if (info.Length() < 1) {
1278         TextFieldModel::GetInstance()->SetBarState(DisplayMode::AUTO);
1279         return;
1280     }
1281     auto jsValue = info[0];
1282     if (!jsValue->IsNumber()) {
1283         TextFieldModel::GetInstance()->SetBarState(DisplayMode::AUTO);
1284         return;
1285     }
1286     DisplayMode displayMode = static_cast<DisplayMode>(jsValue->ToNumber<int32_t>());
1287     TextFieldModel::GetInstance()->SetBarState(displayMode);
1288 }
1289 
SetMaxLines(const JSCallbackInfo & info)1290 void JSTextField::SetMaxLines(const JSCallbackInfo& info)
1291 {
1292     if (info.Length() < 1) {
1293         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1294         return;
1295     }
1296     auto jsValue = info[0];
1297     if (!jsValue->IsNumber() || jsValue->ToNumber<int32_t>() <= 0) {
1298         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1299         return;
1300     }
1301     TextFieldModel::GetInstance()->SetMaxViewLines(jsValue->ToNumber<uint32_t>());
1302 }
1303 
SetEnableKeyboardOnFocus(const JSCallbackInfo & info)1304 void JSTextField::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
1305 {
1306     if (info.Length() < 1) {
1307         return;
1308     }
1309     auto jsValue = info[0];
1310     if (jsValue->IsUndefined() || !jsValue->IsBoolean()) {
1311         TextFieldModel::GetInstance()->RequestKeyboardOnFocus(true);
1312         return;
1313     }
1314     TextFieldModel::GetInstance()->RequestKeyboardOnFocus(jsValue->ToBoolean());
1315 }
1316 
SetSelectionMenuHidden(const JSCallbackInfo & info)1317 void JSTextField::SetSelectionMenuHidden(const JSCallbackInfo& info)
1318 {
1319     if (info.Length() < 1) {
1320         return;
1321     }
1322     auto jsValue = info[0];
1323     if (jsValue->IsUndefined() || !jsValue->IsBoolean()) {
1324         TextFieldModel::GetInstance()->SetSelectionMenuHidden(false);
1325         return;
1326     }
1327     TextFieldModel::GetInstance()->SetSelectionMenuHidden(jsValue->ToBoolean());
1328 }
1329 
ParseJsCustomKeyboardBuilder(const JSCallbackInfo & info,int32_t index,std::function<void ()> & buildFunc)1330 bool JSTextField::ParseJsCustomKeyboardBuilder(
1331     const JSCallbackInfo& info, int32_t index, std::function<void()>& buildFunc)
1332 {
1333     if (info.Length() <= index || !info[index]->IsObject()) {
1334         return false;
1335     }
1336     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[index]);
1337     auto builder = obj->GetProperty("builder");
1338     if (!builder->IsFunction()) {
1339         return false;
1340     }
1341     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1342     CHECK_NULL_RETURN(builderFunc, false);
1343     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1344     buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = targetNode]() {
1345         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1346         ACE_SCORING_EVENT("CustomKeyboard");
1347         PipelineContext::SetCallBackNode(node);
1348         func->Execute();
1349     };
1350     return true;
1351 }
1352 
SetCustomKeyboard(const JSCallbackInfo & info)1353 void JSTextField::SetCustomKeyboard(const JSCallbackInfo& info)
1354 {
1355     if (info.Length() < 1) {
1356         return;
1357     }
1358     auto jsValue = info[0];
1359     if (jsValue->IsUndefined() || jsValue->IsNull() || !jsValue->IsObject()) {
1360         TextFieldModel::GetInstance()->SetCustomKeyboard(nullptr);
1361         return;
1362     }
1363     bool supportAvoidance = false;
1364     if (info.Length() == 2 && info[1]->IsObject()) {  //  2 here refers to the number of parameters
1365         auto paramObject = JSRef<JSObject>::Cast(info[1]);
1366         auto isSupportAvoidance = paramObject->GetProperty("supportAvoidance");
1367         if (!isSupportAvoidance->IsNull() && isSupportAvoidance->IsBoolean()) {
1368             supportAvoidance = isSupportAvoidance->ToBoolean();
1369         }
1370     }
1371     std::function<void()> buildFunc;
1372     if (ParseJsCustomKeyboardBuilder(info, 0, buildFunc)) {
1373         TextFieldModel::GetInstance()->SetCustomKeyboard(std::move(buildFunc), supportAvoidance);
1374     }
1375 }
1376 
SetPasswordRules(const JSCallbackInfo & info)1377 void JSTextField::SetPasswordRules(const JSCallbackInfo& info)
1378 {
1379     auto jsValue = info[0];
1380     if (!jsValue->IsString()) {
1381         return;
1382     }
1383     auto passwordRules = jsValue->ToString();
1384     TextFieldModel::GetInstance()->SetPasswordRules(passwordRules);
1385 }
1386 
SetEnableAutoFill(const JSCallbackInfo & info)1387 void JSTextField::SetEnableAutoFill(const JSCallbackInfo& info)
1388 {
1389     auto jsValue = info[0];
1390     if (!jsValue->IsBoolean()) {
1391         TextFieldModel::GetInstance()->SetEnableAutoFill(true);
1392         return;
1393     }
1394     TextFieldModel::GetInstance()->SetEnableAutoFill(jsValue->ToBoolean());
1395 }
1396 
ConvertStrToCleanNodeStyle(const std::string & value)1397 static CleanNodeStyle ConvertStrToCleanNodeStyle(const std::string& value)
1398 {
1399     if (value == "CONSTANT") {
1400         return CleanNodeStyle::CONSTANT;
1401     } else if (value == "INVISIBLE") {
1402         return CleanNodeStyle::INVISIBLE;
1403     } else {
1404         return CleanNodeStyle::INPUT;
1405     }
1406 }
1407 
SetCancelButton(const JSCallbackInfo & info)1408 void JSTextField::SetCancelButton(const JSCallbackInfo& info)
1409 {
1410     if (info.Length() < 1 || !info[0]->IsObject()) {
1411         return;
1412     }
1413     auto param = JSRef<JSObject>::Cast(info[0]);
1414     auto theme = GetTheme<TextFieldTheme>();
1415     CHECK_NULL_VOID(theme);
1416     std::string styleStr;
1417     CleanNodeStyle cleanNodeStyle;
1418     auto styleProp = param->GetProperty("style");
1419     if (!styleProp->IsNull() && ParseJsString(styleProp, styleStr)) {
1420         cleanNodeStyle = ConvertStrToCleanNodeStyle(styleStr);
1421     } else {
1422         cleanNodeStyle = CleanNodeStyle::INPUT;
1423     }
1424     TextFieldModel::GetInstance()->SetCleanNodeStyle(cleanNodeStyle);
1425     TextFieldModel::GetInstance()->SetIsShowCancelButton(true);
1426     auto iconJsVal = param->GetProperty("icon");
1427     if (iconJsVal->IsUndefined() || iconJsVal->IsNull() || !iconJsVal->IsObject()) {
1428         if (SystemProperties::GetColorMode() == ColorMode::DARK) {
1429             TextFieldModel::GetInstance()->SetCancelIconColor(theme->GetCancelButtonIconColor());
1430         } else {
1431             TextFieldModel::GetInstance()->SetCancelIconColor(Color());
1432         }
1433         TextFieldModel::GetInstance()->SetCancelIconSize(theme->GetIconSize());
1434         TextFieldModel::GetInstance()->SetCanacelIconSrc(std::string(), std::string(), std::string());
1435         return;
1436     }
1437     auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
1438     // set icon size
1439     CalcDimension iconSize;
1440     auto iconSizeProp = iconParam->GetProperty("size");
1441     if (!iconSizeProp->IsUndefined() && !iconSizeProp->IsNull() && ParseJsDimensionVpNG(iconSizeProp, iconSize)) {
1442         if (LessNotEqual(iconSize.Value(), 0.0) || iconSize.Unit() == DimensionUnit::PERCENT) {
1443             iconSize = theme->GetIconSize();
1444         }
1445     } else {
1446         iconSize = theme->GetIconSize();
1447     }
1448     TextFieldModel::GetInstance()->SetCancelIconSize(iconSize);
1449     SetCancelIconColorAndIconSrc(iconParam);
1450 }
1451 
SetCancelIconColorAndIconSrc(const JSRef<JSObject> & iconParam)1452 void JSTextField::SetCancelIconColorAndIconSrc(const JSRef<JSObject>& iconParam)
1453 {
1454     auto theme = GetTheme<TextFieldTheme>();
1455     CHECK_NULL_VOID(theme);
1456     // set icon src
1457     std::string iconSrc;
1458     std::string bundleName;
1459     std::string moduleName;
1460     auto iconSrcProp = iconParam->GetProperty("src");
1461     if (iconSrcProp->IsUndefined() || iconSrcProp->IsNull() || !ParseJsMedia(iconSrcProp, iconSrc)) {
1462         iconSrc = "";
1463     }
1464     GetJsMediaBundleInfo(iconSrcProp, bundleName, moduleName);
1465     TextFieldModel::GetInstance()->SetCanacelIconSrc(iconSrc, bundleName, moduleName);
1466     // set icon color
1467     Color iconColor;
1468     auto iconColorProp = iconParam->GetProperty("color");
1469     if (!iconColorProp->IsUndefined() && !iconColorProp->IsNull() && ParseJsColor(iconColorProp, iconColor)) {
1470         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1471         return;
1472     }
1473     auto info = ImageSourceInfo(iconSrc, bundleName, moduleName);
1474     if (info.IsSvg() && iconSrc != "") {
1475         // svg need not default color, otherwise multi color svg will render fault
1476         return;
1477     }
1478     if (SystemProperties::GetColorMode() == ColorMode::DARK) {
1479         TextFieldModel::GetInstance()->SetCancelIconColor(theme->GetCancelButtonIconColor());
1480     } else {
1481         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1482     }
1483 }
1484 
SetSelectAllValue(const JSCallbackInfo & info)1485 void JSTextField::SetSelectAllValue(const JSCallbackInfo& info)
1486 {
1487     auto infoValue = info[0];
1488     if (!infoValue->IsBoolean() || infoValue->IsUndefined() || infoValue->IsNull()) {
1489         TextFieldModel::GetInstance()->SetSelectAllValue(false);
1490         return;
1491     }
1492 
1493     bool isSetSelectAllValue = infoValue->ToBoolean();
1494     TextFieldModel::GetInstance()->SetSelectAllValue(isSetSelectAllValue);
1495 }
1496 
SetFontFeature(const JSCallbackInfo & info)1497 void JSTextField::SetFontFeature(const JSCallbackInfo& info)
1498 {
1499     if (info.Length() < 1) {
1500         return;
1501     }
1502     auto jsValue = info[0];
1503     std::string fontFeatureSettings = "";
1504     if (jsValue->IsString()) {
1505         fontFeatureSettings = jsValue->ToString();
1506     }
1507     TextFieldModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
1508 }
1509 
SetKeyboardAppearance(const JSCallbackInfo & info)1510 void JSTextField::SetKeyboardAppearance(const JSCallbackInfo& info)
1511 {
1512     if (info.Length() != 1 || !info[0]->IsNumber()) {
1513         TextFieldModel::GetInstance()->SetKeyboardAppearance(
1514             static_cast<KeyboardAppearance>(KeyboardAppearance::NONE_IMMERSIVE));
1515         return;
1516     }
1517     auto keyboardAppearance = info[0]->ToNumber<uint32_t>();
1518     if (keyboardAppearance < static_cast<uint32_t>(KeyboardAppearance::NONE_IMMERSIVE) ||
1519         keyboardAppearance > static_cast<uint32_t>(KeyboardAppearance::DARK_IMMERSIVE)) {
1520         TextFieldModel::GetInstance()->SetKeyboardAppearance(
1521             static_cast<KeyboardAppearance>(KeyboardAppearance::NONE_IMMERSIVE));
1522         return;
1523     }
1524     TextFieldModel::GetInstance()->
1525         SetKeyboardAppearance(static_cast<KeyboardAppearance>(keyboardAppearance));
1526 }
1527 
SetDecoration(const JSCallbackInfo & info)1528 void JSTextField::SetDecoration(const JSCallbackInfo& info)
1529 {
1530     do {
1531         auto tmpInfo = info[0];
1532         if (!tmpInfo->IsObject()) {
1533             TextFieldModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
1534             TextFieldModel::GetInstance()->SetTextDecorationColor(Color::BLACK);
1535             TextFieldModel::GetInstance()->SetTextDecorationStyle(TextDecorationStyle::SOLID);
1536             break;
1537         }
1538         JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
1539         JSRef<JSVal> typeValue = obj->GetProperty("type");
1540         JSRef<JSVal> colorValue = obj->GetProperty("color");
1541         JSRef<JSVal> styleValue = obj->GetProperty("style");
1542 
1543         auto pipelineContext = PipelineBase::GetCurrentContext();
1544         CHECK_NULL_VOID(pipelineContext);
1545         auto theme = pipelineContext->GetTheme<TextFieldTheme>();
1546         CHECK_NULL_VOID(theme);
1547         TextDecoration textDecoration = theme->GetTextStyle().GetTextDecoration();
1548         if (typeValue->IsNumber()) {
1549             textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
1550         }
1551         Color result = theme->GetTextStyle().GetTextDecorationColor();
1552         ParseJsColor(colorValue, result, Color::BLACK);
1553         std::optional<TextDecorationStyle> textDecorationStyle;
1554         if (styleValue->IsNumber()) {
1555             textDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
1556         } else {
1557             textDecorationStyle = DEFAULT_TEXT_DECORATION_STYLE;
1558         }
1559         TextFieldModel::GetInstance()->SetTextDecoration(textDecoration);
1560         TextFieldModel::GetInstance()->SetTextDecorationColor(result);
1561         if (textDecorationStyle) {
1562             TextFieldModel::GetInstance()->SetTextDecorationStyle(textDecorationStyle.value());
1563         }
1564     } while (false);
1565 }
1566 
SetMinFontSize(const JSCallbackInfo & info)1567 void JSTextField::SetMinFontSize(const JSCallbackInfo& info)
1568 {
1569     if (info.Length() < 1) {
1570         return;
1571     }
1572     CalcDimension minFontSize;
1573     if (!ParseJsDimensionFpNG(info[0], minFontSize, false)) {
1574         TextFieldModel::GetInstance()->SetAdaptMinFontSize(CalcDimension());
1575         return;
1576     }
1577     if (minFontSize.IsNegative()) {
1578         minFontSize = CalcDimension();
1579     }
1580     TextFieldModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
1581 }
1582 
SetMaxFontSize(const JSCallbackInfo & info)1583 void JSTextField::SetMaxFontSize(const JSCallbackInfo& info)
1584 {
1585     if (info.Length() < 1) {
1586         return;
1587     }
1588     auto pipelineContext = PipelineBase::GetCurrentContext();
1589     CHECK_NULL_VOID(pipelineContext);
1590     auto theme = pipelineContext->GetTheme<TextFieldTheme>();
1591     CHECK_NULL_VOID(theme);
1592     CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1593     if (!ParseJsDimensionFpNG(info[0], maxFontSize, false)) {
1594         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1595         TextFieldModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1596         return;
1597     }
1598     if (maxFontSize.IsNegative()) {
1599         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1600     }
1601     TextFieldModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1602 }
1603 
SetHeightAdaptivePolicy(int32_t value)1604 void JSTextField::SetHeightAdaptivePolicy(int32_t value)
1605 {
1606     if (value < 0 || value >= static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
1607         value = 0;
1608     }
1609     TextFieldModel::GetInstance()->SetHeightAdaptivePolicy(HEIGHT_ADAPTIVE_POLICY[value]);
1610 }
1611 
SetLetterSpacing(const JSCallbackInfo & info)1612 void JSTextField::SetLetterSpacing(const JSCallbackInfo& info)
1613 {
1614     CalcDimension value;
1615     if (!ParseJsDimensionFpNG(info[0], value, false)) {
1616         value.Reset();
1617         TextFieldModel::GetInstance()->SetLetterSpacing(value);
1618         return;
1619     }
1620     TextFieldModel::GetInstance()->SetLetterSpacing(value);
1621 }
1622 
SetLineHeight(const JSCallbackInfo & info)1623 void JSTextField::SetLineHeight(const JSCallbackInfo& info)
1624 {
1625     CalcDimension value;
1626     if (!ParseJsDimensionFpNG(info[0], value)) {
1627         value.Reset();
1628         TextFieldModel::GetInstance()->SetLineHeight(value);
1629         return;
1630     }
1631     if (value.IsNegative()) {
1632         value.Reset();
1633     }
1634     TextFieldModel::GetInstance()->SetLineHeight(value);
1635 }
1636 
SetLineSpacing(const JSCallbackInfo & info)1637 void JSTextField::SetLineSpacing(const JSCallbackInfo& info)
1638 {
1639     CalcDimension value;
1640     if (!ParseLengthMetricsToPositiveDimension(info[0], value)) {
1641         value.Reset();
1642     }
1643     if (value.IsNegative()) {
1644         value.Reset();
1645     }
1646     TextFieldModel::GetInstance()->SetLineSpacing(value);
1647 }
1648 
SetTextOverflow(const JSCallbackInfo & info)1649 void JSTextField::SetTextOverflow(const JSCallbackInfo& info)
1650 {
1651     do {
1652         auto tmpInfo = info[0];
1653         int32_t overflow = 0;
1654         if (info.Length() < 1) {
1655             break;
1656         }
1657         if (tmpInfo->IsUndefined() || tmpInfo->IsNull() || !tmpInfo->IsNumber()) {
1658             overflow = DEFAULT_OVERFLOW;
1659         } else if (tmpInfo->IsNumber()) {
1660             overflow = tmpInfo->ToNumber<int32_t>();
1661             if (overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
1662                 overflow = DEFAULT_OVERFLOW;
1663             }
1664         }
1665         TextFieldModel::GetInstance()->SetTextOverflow(TEXT_OVERFLOWS[overflow]);
1666     } while (false);
1667 
1668     info.SetReturnValue(info.This());
1669 }
1670 
SetTextIndent(const JSCallbackInfo & info)1671 void JSTextField::SetTextIndent(const JSCallbackInfo& info)
1672 {
1673     CalcDimension value;
1674     if (!ParseJsDimensionVpNG(info[0], value, true)) {
1675         value.Reset();
1676     }
1677     TextFieldModel::GetInstance()->SetTextIndent(value);
1678 }
1679 
CreateJsAboutToIMEInputObj(const InsertValueInfo & insertValue)1680 JSRef<JSVal> JSTextField::CreateJsAboutToIMEInputObj(const InsertValueInfo& insertValue)
1681 {
1682     JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1683     aboutToIMEInputObj->SetProperty<int32_t>("insertOffset", insertValue.insertOffset);
1684     aboutToIMEInputObj->SetProperty<std::string>("insertValue", insertValue.insertValue);
1685     return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1686 }
1687 
OnWillInsertValue(const JSCallbackInfo & info)1688 void JSTextField::OnWillInsertValue(const JSCallbackInfo& info)
1689 {
1690     auto jsValue = info[0];
1691     CHECK_NULL_VOID(jsValue->IsFunction());
1692     auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1693         JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1694     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1695                         const InsertValueInfo& insertValue) -> bool {
1696         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1697         auto ret = func->ExecuteWithValue(insertValue);
1698         if (ret->IsBoolean()) {
1699             return ret->ToBoolean();
1700         }
1701         return true;
1702     };
1703     TextFieldModel::GetInstance()->SetOnWillInsertValueEvent(std::move(callback));
1704 }
1705 
CreateJsDeleteToIMEObj(const DeleteValueInfo & deleteValueInfo)1706 JSRef<JSVal> JSTextField::CreateJsDeleteToIMEObj(const DeleteValueInfo& deleteValueInfo)
1707 {
1708     JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1709     aboutToIMEInputObj->SetProperty<int32_t>("deleteOffset", deleteValueInfo.deleteOffset);
1710     aboutToIMEInputObj->SetProperty<int32_t>("direction", static_cast<int32_t>(deleteValueInfo.direction));
1711     aboutToIMEInputObj->SetProperty<std::string>("deleteValue", deleteValueInfo.deleteValue);
1712     return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1713 }
1714 
OnDidInsertValue(const JSCallbackInfo & info)1715 void JSTextField::OnDidInsertValue(const JSCallbackInfo& info)
1716 {
1717     auto jsValue = info[0];
1718     CHECK_NULL_VOID(jsValue->IsFunction());
1719     auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1720         JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1721     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1722                         const InsertValueInfo& insertValue) {
1723         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1724         func->ExecuteWithValue(insertValue);
1725     };
1726     TextFieldModel::GetInstance()->SetOnDidInsertValueEvent(std::move(callback));
1727 }
1728 
OnWillDelete(const JSCallbackInfo & info)1729 void JSTextField::OnWillDelete(const JSCallbackInfo& info)
1730 {
1731     auto jsValue = info[0];
1732     CHECK_NULL_VOID(jsValue->IsFunction());
1733     auto jsAboutToIMEInputFunc =
1734         AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1735     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1736                         const DeleteValueInfo& deleteValue) {
1737         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1738         auto ret = func->ExecuteWithValue(deleteValue);
1739         if (ret->IsBoolean()) {
1740             return ret->ToBoolean();
1741         }
1742         return true;
1743     };
1744     TextFieldModel::GetInstance()->SetOnWillDeleteEvent(std::move(callback));
1745 }
1746 
OnDidDelete(const JSCallbackInfo & info)1747 void JSTextField::OnDidDelete(const JSCallbackInfo& info)
1748 {
1749     auto jsValue = info[0];
1750     CHECK_NULL_VOID(jsValue->IsFunction());
1751     auto jsAboutToIMEInputFunc =
1752         AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1753     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1754                         const DeleteValueInfo& deleteValue) {
1755         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1756         func->ExecuteWithValue(deleteValue);
1757     };
1758     TextFieldModel::GetInstance()->SetOnDidDeleteEvent(std::move(callback));
1759 }
1760 
EditMenuOptions(const JSCallbackInfo & info)1761 void JSTextField::EditMenuOptions(const JSCallbackInfo& info)
1762 {
1763     NG::OnCreateMenuCallback onCreateMenuCallback;
1764     NG::OnMenuItemClickCallback onMenuItemClick;
1765     JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick);
1766     TextFieldModel::GetInstance()->SetSelectionMenuOptions(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
1767 }
1768 
SetEnablePreviewText(const JSCallbackInfo & info)1769 void JSTextField::SetEnablePreviewText(const JSCallbackInfo& info)
1770 {
1771     auto jsValue = info[0];
1772     if (!jsValue->IsBoolean()) {
1773         TextFieldModel::GetInstance()->SetEnablePreviewText(true);
1774         return;
1775     }
1776     TextFieldModel::GetInstance()->SetEnablePreviewText(jsValue->ToBoolean());
1777 }
1778 
SetEnableHapticFeedback(const JSCallbackInfo & info)1779 void JSTextField::SetEnableHapticFeedback(const JSCallbackInfo& info)
1780 {
1781     bool state = true;
1782     if (info.Length() > 0 && info[0]->IsBoolean()) {
1783         state = info[0]->ToBoolean();
1784     }
1785     TextFieldModel::GetInstance()->SetEnableHapticFeedback(state);
1786 }
1787 
SetStopBackPress(const JSCallbackInfo & info)1788 void JSTextField::SetStopBackPress(const JSCallbackInfo& info)
1789 {
1790     bool isStopBackPress = true;
1791     if (info.Length() > 0 && info[0]->IsBoolean()) {
1792         isStopBackPress = info[0]->ToBoolean();
1793     }
1794     TextFieldModel::GetInstance()->SetStopBackPress(isStopBackPress);
1795 }
1796 
CreateJsOnWillChangeObj(const ChangeValueInfo & changeValueInfo)1797 JSRef<JSVal> JSTextField::CreateJsOnWillChangeObj(const ChangeValueInfo& changeValueInfo)
1798 {
1799     JSRef<JSObject> ChangeValueInfo = JSRef<JSObject>::New();
1800     ChangeValueInfo->SetProperty<std::string>("content", changeValueInfo.value);
1801 
1802     auto previewTextObj = CreateJsOnChangeObj(changeValueInfo.previewText);
1803     ChangeValueInfo->SetPropertyObject("previewText", previewTextObj);
1804 
1805     auto optionsObj = JSRef<JSObject>::New();
1806     auto rangeBeforeObj = JSRef<JSObject>::New();
1807     rangeBeforeObj->SetProperty<int32_t>("start", changeValueInfo.rangeBefore.start);
1808     rangeBeforeObj->SetProperty<int32_t>("end", changeValueInfo.rangeBefore.end);
1809     optionsObj->SetPropertyObject("rangeBefore", rangeBeforeObj);
1810     auto rangeAfterObj = JSRef<JSObject>::New();
1811     rangeAfterObj->SetProperty<int32_t>("start", changeValueInfo.rangeAfter.start);
1812     rangeAfterObj->SetProperty<int32_t>("end", changeValueInfo.rangeAfter.end);
1813     optionsObj->SetPropertyObject("rangeAfter", rangeAfterObj);
1814     optionsObj->SetProperty<std::string>("oldContent", changeValueInfo.oldContent);
1815     auto oldPreviewTextObj = CreateJsOnChangeObj(changeValueInfo.oldPreviewText);
1816     optionsObj->SetPropertyObject("oldPreviewText", oldPreviewTextObj);
1817 
1818     ChangeValueInfo->SetPropertyObject("options", optionsObj);
1819     return JSRef<JSVal>::Cast(ChangeValueInfo);
1820 }
1821 
SetOnWillChange(const JSCallbackInfo & info)1822 void JSTextField::SetOnWillChange(const JSCallbackInfo& info)
1823 {
1824     auto jsValue = info[0];
1825     CHECK_NULL_VOID(jsValue->IsFunction());
1826     auto jsChangeFunc = AceType::MakeRefPtr<JsEventFunction<ChangeValueInfo, 1>>(
1827         JSRef<JSFunc>::Cast(jsValue), CreateJsOnWillChangeObj);
1828     auto onWillChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
1829         const ChangeValueInfo& changeValue) {
1830         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1831         ACE_SCORING_EVENT("onWillChange");
1832         auto ret = func->ExecuteWithValue(changeValue);
1833         if (ret->IsBoolean()) {
1834             return ret->ToBoolean();
1835         }
1836         return true;
1837     };
1838     TextFieldModel::GetInstance()->SetOnWillChangeEvent(std::move(onWillChange));
1839 }
1840 
1841 } // namespace OHOS::Ace::Framework
1842