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