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