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