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