• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <cstdint>
19 #include <vector>
20 
21 #include "base/geometry/dimension.h"
22 #include "base/utils/utils.h"
23 #include "bridge/common/utils/utils.h"
24 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
25 #include "bridge/declarative_frontend/engine/functions/js_function.h"
26 #include "bridge/declarative_frontend/jsview/js_container_base.h"
27 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
28 #include "bridge/declarative_frontend/jsview/js_textarea.h"
29 #include "bridge/declarative_frontend/jsview/js_textinput.h"
30 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
31 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
32 #include "bridge/declarative_frontend/jsview/models/text_field_model_impl.h"
33 #include "bridge/declarative_frontend/jsview/models/view_abstract_model_impl.h"
34 #include "bridge/declarative_frontend/view_stack_processor.h"
35 #include "core/common/container.h"
36 #include "core/common/ime/text_input_action.h"
37 #include "core/common/ime/text_input_type.h"
38 #include "core/components/text_field/text_field_component.h"
39 #include "core/components/text_field/textfield_theme.h"
40 #include "core/components_ng/base/view_abstract.h"
41 #include "core/components_ng/pattern/text_field/text_field_model.h"
42 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
43 #include "core/pipeline/pipeline_base.h"
44 
45 namespace OHOS::Ace {
46 
47 std::unique_ptr<TextFieldModel> TextFieldModel::instance_ = nullptr;
48 
GetInstance()49 TextFieldModel* TextFieldModel::GetInstance()
50 {
51     if (!instance_) {
52 #ifdef NG_BUILD
53         instance.reset(new NG::TextFieldModelNG());
54 #else
55         if (Container::IsCurrentUseNewPipeline()) {
56             instance_.reset(new NG::TextFieldModelNG());
57         } else {
58             instance_.reset(new Framework::TextFieldModelImpl());
59         }
60 #endif
61     }
62     return instance_.get();
63 }
64 
65 } // namespace OHOS::Ace
66 
67 namespace OHOS::Ace::Framework {
68 
69 namespace {
70 
71 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END };
72 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
73 const std::vector<std::string> INPUT_FONT_FAMILY_VALUE = { "sans-serif" };
74 constexpr uint32_t TEXTAREA_MAXLENGTH_VALUE_DEFAULT = std::numeric_limits<uint32_t>::max();
75 
InitTextAreaDefaultStyle()76 void InitTextAreaDefaultStyle()
77 {
78     auto boxComponent = ViewStackProcessor::GetInstance()->GetBoxComponent();
79     auto* stack = ViewStackProcessor::GetInstance();
80     auto textAreaComponent = AceType::DynamicCast<OHOS::Ace::TextFieldComponent>(stack->GetMainComponent());
81     auto pipeline = PipelineBase::GetCurrentContext();
82     CHECK_NULL_VOID(pipeline);
83     auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
84     if (!boxComponent || !textAreaComponent || !theme) {
85         LOGE("boxComponent or textAreaComponent or theme is null");
86         return;
87     }
88 
89     textAreaComponent->SetTextMaxLines(TEXTAREA_MAXLENGTH_VALUE_DEFAULT);
90     textAreaComponent->SetCursorColor(theme->GetCursorColor());
91     textAreaComponent->SetPlaceholderColor(theme->GetPlaceholderColor());
92     textAreaComponent->SetFocusBgColor(theme->GetFocusBgColor());
93     textAreaComponent->SetFocusPlaceholderColor(theme->GetFocusPlaceholderColor());
94     textAreaComponent->SetFocusTextColor(theme->GetFocusTextColor());
95     textAreaComponent->SetBgColor(theme->GetBgColor());
96     textAreaComponent->SetTextColor(theme->GetTextColor());
97     textAreaComponent->SetSelectedColor(theme->GetSelectedColor());
98     textAreaComponent->SetHoverColor(theme->GetHoverColor());
99     textAreaComponent->SetPressColor(theme->GetPressColor());
100 
101     TextStyle textStyle = textAreaComponent->GetTextStyle();
102     textStyle.SetTextColor(theme->GetTextColor());
103     textStyle.SetFontSize(theme->GetFontSize());
104     textStyle.SetFontWeight(theme->GetFontWeight());
105     textStyle.SetFontFamilies(INPUT_FONT_FAMILY_VALUE);
106     textAreaComponent->SetTextStyle(textStyle);
107     textAreaComponent->SetEditingStyle(textStyle);
108     textAreaComponent->SetPlaceHoldStyle(textStyle);
109 
110     textAreaComponent->SetCountTextStyle(theme->GetCountTextStyle());
111     textAreaComponent->SetOverCountStyle(theme->GetOverCountStyle());
112     textAreaComponent->SetCountTextStyleOuter(theme->GetCountTextStyleOuter());
113     textAreaComponent->SetOverCountStyleOuter(theme->GetOverCountStyleOuter());
114     textAreaComponent->SetErrorBorderWidth(theme->GetErrorBorderWidth());
115     textAreaComponent->SetErrorBorderColor(theme->GetErrorBorderColor());
116 
117     RefPtr<Decoration> backDecoration = AceType::MakeRefPtr<Decoration>();
118     backDecoration->SetPadding(theme->GetPadding());
119     backDecoration->SetBackgroundColor(theme->GetBgColor());
120     backDecoration->SetBorderRadius(theme->GetBorderRadius());
121     const auto& boxDecoration = boxComponent->GetBackDecoration();
122     if (boxDecoration) {
123         backDecoration->SetImage(boxDecoration->GetImage());
124         backDecoration->SetGradient(boxDecoration->GetGradient());
125     }
126     textAreaComponent->SetOriginBorder(backDecoration->GetBorder());
127     textAreaComponent->SetDecoration(backDecoration);
128     textAreaComponent->SetIconSize(theme->GetIconSize());
129     textAreaComponent->SetIconHotZoneSize(theme->GetIconHotZoneSize());
130     textAreaComponent->SetHeight(theme->GetHeight());
131 
132     // text area need to extend height.
133     textAreaComponent->SetExtend(true);
134     boxComponent->SetHeight(-1.0, DimensionUnit::VP);
135 }
136 
137 } // namespace
138 
CreateTextInput(const JSCallbackInfo & info)139 void JSTextField::CreateTextInput(const JSCallbackInfo& info)
140 {
141     std::optional<std::string> placeholderSrc;
142     std::optional<std::string> value;
143     JSTextInputController* jsController = nullptr;
144     if (info[0]->IsObject()) {
145         auto paramObject = JSRef<JSObject>::Cast(info[0]);
146         std::string placeholder;
147         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
148             placeholderSrc = placeholder;
149         }
150         std::string text;
151         if (ParseJsString(paramObject->GetProperty("text"), text)) {
152             value = text;
153         }
154         auto controllerObj = paramObject->GetProperty("controller");
155         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
156             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextInputController>();
157         }
158     }
159 
160     auto controller = TextFieldModel::GetInstance()->CreateTextInput(placeholderSrc, value);
161     if (jsController) {
162         jsController->SetController(controller);
163     }
164 
165     if (!Container::IsCurrentUseNewPipeline()) {
166         JSInteractableView::SetFocusable(true);
167         JSInteractableView::SetFocusNode(true);
168     }
169 }
170 
CreateTextArea(const JSCallbackInfo & info)171 void JSTextField::CreateTextArea(const JSCallbackInfo& info)
172 {
173     std::optional<std::string> placeholderSrc;
174     std::optional<std::string> value;
175     JSTextAreaController* jsController = nullptr;
176     if (info[0]->IsObject()) {
177         auto paramObject = JSRef<JSObject>::Cast(info[0]);
178         std::string placeholder;
179         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
180             placeholderSrc = placeholder;
181         }
182         std::string text;
183         if (ParseJsString(paramObject->GetProperty("text"), text)) {
184             value = text;
185         }
186         auto controllerObj = paramObject->GetProperty("controller");
187         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
188             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextAreaController>();
189         }
190     }
191 
192     if (Container::IsCurrentUseNewPipeline()) {
193         auto controller = TextFieldModel::GetInstance()->CreateTextArea(placeholderSrc, value);
194         if (jsController) {
195             jsController->SetController(controller);
196         }
197         return;
198     }
199 
200     RefPtr<TextFieldComponent> textAreaComponent = AceType::MakeRefPtr<TextFieldComponent>();
201     textAreaComponent->SetTextFieldController(AceType::MakeRefPtr<TextFieldController>());
202     textAreaComponent->SetTextInputType(TextInputType::MULTILINE);
203     textAreaComponent->SetHoverAnimationType(HoverAnimationType::BOARD);
204     auto paramObject = JSRef<JSObject>::Cast(info[0]);
205 
206     ViewStackProcessor::GetInstance()->ClaimElementId(textAreaComponent);
207     ViewStackProcessor::GetInstance()->Push(textAreaComponent);
208     InitTextAreaDefaultStyle();
209     Border boxBorder;
210     auto boxComponent = ViewStackProcessor::GetInstance()->GetBoxComponent();
211     auto theme = GetTheme<TextFieldTheme>();
212     if (boxComponent->GetBackDecoration()) {
213         boxBorder = boxComponent->GetBackDecoration()->GetBorder();
214     }
215     if (value) {
216         textAreaComponent->SetValue(value.value());
217     }
218     if (placeholderSrc) {
219         textAreaComponent->SetPlaceholder(placeholderSrc.value());
220     }
221     JSTextField::UpdateDecoration(boxComponent, textAreaComponent, boxBorder, theme);
222     if (jsController) {
223         jsController->SetController(textAreaComponent->GetTextFieldController());
224     }
225 
226     JSInteractableView::SetFocusable(true);
227     JSInteractableView::SetFocusNode(true);
228 }
229 
SetType(const JSCallbackInfo & info)230 void JSTextField::SetType(const JSCallbackInfo& info)
231 {
232     if (info.Length() < 1) {
233         LOGE("SetType create error, info is non-valid");
234         return;
235     }
236     if (!info[0]->IsNumber()) {
237         LOGE("The inputType is not number");
238         return;
239     }
240     TextInputType textInputType = static_cast<TextInputType>(info[0]->ToNumber<int32_t>());
241     TextFieldModel::GetInstance()->SetType(textInputType);
242 }
243 
SetPlaceholderColor(const JSCallbackInfo & info)244 void JSTextField::SetPlaceholderColor(const JSCallbackInfo& info)
245 {
246     if (info.Length() < 1) {
247         LOGE("The arg(SetPlaceholderColor) is wrong, it is supposed to have atleast 1 argument");
248         return;
249     }
250 
251     Color color;
252     if (!ParseJsColor(info[0], color)) {
253         LOGE("the info[0] is null");
254         return;
255     }
256     TextFieldModel::GetInstance()->SetPlaceholderColor(color);
257 }
258 
SetPlaceholderFont(const JSCallbackInfo & info)259 void JSTextField::SetPlaceholderFont(const JSCallbackInfo& info)
260 {
261     if (info.Length() < 1 || !info[0]->IsObject()) {
262         LOGE("PlaceholderFont create error, info is non-valid");
263         return;
264     }
265     Font font;
266     auto paramObject = JSRef<JSObject>::Cast(info[0]);
267     auto fontSize = paramObject->GetProperty("size");
268     if (fontSize->IsNull() || fontSize->IsUndefined()) {
269         font.fontSize = Dimension(-1);
270     } else {
271         Dimension size;
272         if (fontSize->IsString()) {
273             auto result = StringUtils::StringToDimensionWithThemeValue(fontSize->ToString(), true, Dimension(-1));
274             font.fontSize = result;
275         } else if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) {
276             font.fontSize = Dimension(-1);
277             LOGW("Parse to dimension FP failed.");
278         } else {
279             font.fontSize = size;
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     if (!info[0]->IsNumber()) {
315         LOGE("Info(SetEnterKeyType) is not number");
316         return;
317     }
318     TextInputAction textInputAction = static_cast<TextInputAction>(info[0]->ToNumber<int32_t>());
319     TextFieldModel::GetInstance()->SetEnterKeyType(textInputAction);
320 }
321 
SetTextAlign(int32_t value)322 void JSTextField::SetTextAlign(int32_t value)
323 {
324     if (value >= 0 && value < static_cast<int32_t>(TEXT_ALIGNS.size())) {
325         TextFieldModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
326     } else {
327         LOGE("the value is error");
328     }
329 }
330 
SetInputStyle(const JSCallbackInfo & info)331 void JSTextField::SetInputStyle(const JSCallbackInfo& info)
332 {
333     if (info.Length() < 1) {
334         LOGE("The arg(SetInputStyle) is wrong, it is supposed to have at least 1 argument");
335         return;
336     }
337     auto styleString = info[0]->ToString();
338     if (styleString == "Inline") {
339         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::INLINE);
340     } else {
341         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::DEFAULT);
342     }
343 }
344 
SetCaretColor(const JSCallbackInfo & info)345 void JSTextField::SetCaretColor(const JSCallbackInfo& info)
346 {
347     if (info.Length() < 1) {
348         LOGE("The arg(SetCareColor) is wrong, it is supposed to have atleast 1 argument");
349         return;
350     }
351 
352     Color color;
353     if (!ParseJsColor(info[0], color)) {
354         LOGE("info[0] is null");
355         return;
356     }
357 
358     TextFieldModel::GetInstance()->SetCaretColor(color);
359 }
360 
SetMaxLength(const JSCallbackInfo & info)361 void JSTextField::SetMaxLength(const JSCallbackInfo& info)
362 {
363     if (info.Length() < 1) {
364         LOGI("The arg(SetMaxLength) is wrong, it is supposed to have atleast 1 argument");
365         return;
366     }
367     int32_t maxLength = 0;
368     if (info[0]->IsUndefined()) {
369         TextFieldModel::GetInstance()->ResetMaxLength();
370         return;
371     } else if (!info[0]->IsNumber()) {
372         LOGI("Max length should be number");
373         TextFieldModel::GetInstance()->ResetMaxLength();
374         return;
375     }
376     maxLength = info[0]->ToNumber<int32_t>();
377     if (GreatOrEqual(maxLength, 0)) {
378         TextFieldModel::GetInstance()->SetMaxLength(maxLength);
379     } else {
380         TextFieldModel::GetInstance()->ResetMaxLength();
381     }
382 }
383 
SetFontSize(const JSCallbackInfo & info)384 void JSTextField::SetFontSize(const JSCallbackInfo& info)
385 {
386     if (info.Length() < 1) {
387         LOGE("JSTextField::SetFontSize The argv is wrong, it is supposed to have at least 1 argument");
388         return;
389     }
390     Dimension fontSize;
391     if (!ParseJsDimensionFp(info[0], fontSize)) {
392         LOGE("Parse to dimension FP failed!");
393         return;
394     }
395     TextFieldModel::GetInstance()->SetFontSize(fontSize);
396 }
397 
SetFontWeight(const std::string & value)398 void JSTextField::SetFontWeight(const std::string& value)
399 {
400     TextFieldModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(value));
401 }
402 
SetTextColor(const JSCallbackInfo & info)403 void JSTextField::SetTextColor(const JSCallbackInfo& info)
404 {
405     if (info.Length() < 1) {
406         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
407         return;
408     }
409     Color textColor;
410     if (!ParseJsColor(info[0], textColor)) {
411         LOGE("Parse to dimension FP failed!");
412         return;
413     }
414     TextFieldModel::GetInstance()->SetTextColor(textColor);
415 }
416 
SetFontStyle(int32_t value)417 void JSTextField::SetFontStyle(int32_t value)
418 {
419     if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
420         TextFieldModel::GetInstance()->SetFontStyle(FONT_STYLES[value]);
421     } else {
422         LOGE("TextInput fontStyle(%{public}d) illegal value", value);
423     }
424 }
425 
SetFontFamily(const JSCallbackInfo & info)426 void JSTextField::SetFontFamily(const JSCallbackInfo& info)
427 {
428     if (info.Length() < 1) {
429         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
430         return;
431     }
432     std::vector<std::string> fontFamilies;
433     if (!ParseJsFontFamilies(info[0], fontFamilies)) {
434         LOGE("Parse FontFamilies failed");
435         return;
436     }
437     TextFieldModel::GetInstance()->SetFontFamily(fontFamilies);
438 }
439 
SetInputFilter(const JSCallbackInfo & info)440 void JSTextField::SetInputFilter(const JSCallbackInfo& info)
441 {
442     if (info.Length() < 1) {
443         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
444         return;
445     }
446     std::string inputFilter;
447     if (!ParseJsString(info[0], inputFilter)) {
448         LOGE("Parse inputFilter failed");
449         return;
450     }
451     if (info[1]->IsFunction()) {
452         auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(info[1]));
453         auto resultId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& info) {
454             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
455             func->Execute(info);
456         };
457         TextFieldModel::GetInstance()->SetInputFilter(inputFilter, resultId);
458         return;
459     }
460     TextFieldModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
461 }
462 
SetShowPasswordIcon(const JSCallbackInfo & info)463 void JSTextField::SetShowPasswordIcon(const JSCallbackInfo& info)
464 {
465     if (!info[0]->IsBoolean()) {
466         LOGE("The info is wrong, it is supposed to be an boolean");
467         return;
468     }
469 
470     bool isShowPasswordIcon = info[0]->ToBoolean();
471     TextFieldModel::GetInstance()->SetShowPasswordIcon(isShowPasswordIcon);
472 }
473 
SetBackgroundColor(const JSCallbackInfo & info)474 void JSTextField::SetBackgroundColor(const JSCallbackInfo& info)
475 {
476     if (Container::IsCurrentUseNewPipeline()) {
477         if (info.Length() < 1) {
478             LOGE("The argv is wrong, it is supposed to have at least 1 argument");
479             return;
480         }
481         Color backgroundColor;
482         if (!ParseJsColor(info[0], backgroundColor)) {
483             auto pipeline = PipelineBase::GetCurrentContext();
484             CHECK_NULL_VOID_NOLOG(pipeline);
485             auto themeManager = pipeline->GetThemeManager();
486             CHECK_NULL_VOID_NOLOG(themeManager);
487             auto theme = themeManager->GetTheme<TextFieldTheme>();
488             CHECK_NULL_VOID_NOLOG(theme);
489             backgroundColor = theme->GetBgColor();
490         }
491         ViewAbstractModel::GetInstance()->SetBackgroundColor(backgroundColor);
492         return;
493     }
494     if (info.Length() < 1) {
495         LOGE("The arg(SetBackgroundColor) is wrong, it is supposed to have atleast 1 argument");
496         return;
497     }
498 
499     Color backgroundColor;
500     if (!ParseJsColor(info[0], backgroundColor)) {
501         LOGE("the info[0] is null");
502         return;
503     }
504 
505     auto* stack = ViewStackProcessor::GetInstance();
506     auto component = AceType::DynamicCast<OHOS::Ace::TextFieldComponent>(stack->GetMainComponent());
507     if (component) {
508         component->SetBgColor(backgroundColor);
509     } else {
510         LOGE("The component(SetPlaceholderColor) is null");
511     }
512 }
513 
JsHeight(const JSCallbackInfo & info)514 void JSTextField::JsHeight(const JSCallbackInfo& info)
515 {
516     JSViewAbstract::JsHeight(info);
517     if (Container::IsCurrentUseNewPipeline()) {
518         return;
519     }
520     if (info.Length() < 1) {
521         LOGE("The arg is wrong, it is supposed to have at least 1 arguments");
522         return;
523     }
524     Dimension value;
525     if (!ParseJsDimensionVp(info[0], value)) {
526         LOGE("Parse to dimension VP failed!");
527         return;
528     }
529     if (LessNotEqual(value.Value(), 0.0)) {
530         LOGE("dimension value: %{public}f is invalid!", value.Value());
531         return;
532     }
533     auto* stack = ViewStackProcessor::GetInstance();
534     auto textInputComponent = AceType::DynamicCast<TextFieldComponent>(stack->GetMainComponent());
535     if (!textInputComponent) {
536         LOGE("JSTextInput set height failed, textInputComponent is null.");
537         return;
538     }
539     textInputComponent->SetHeight(value);
540 }
541 
JsWidth(const JSCallbackInfo & info)542 void JSTextField::JsWidth(const JSCallbackInfo& info)
543 {
544     if (info.Length() < 1) {
545         LOGW("The arg is wrong, it is supposed to have atleast 1 arguments");
546         return;
547     }
548     if (info[0]->IsString() && info[0]->ToString() == "auto") {
549         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
550         TextFieldModel::GetInstance()->SetWidthAuto(true);
551         return;
552     }
553 
554     TextFieldModel::GetInstance()->SetWidthAuto(false);
555     Dimension value;
556     if (!ParseJsDimensionVp(info[0], value)) {
557         LOGW("Parse width fail");
558         return;
559     }
560     if (LessNotEqual(value.Value(), 0.0)) {
561         return;
562     }
563     ViewAbstractModel::GetInstance()->SetWidth(value);
564 }
565 
JsPadding(const JSCallbackInfo & info)566 void JSTextField::JsPadding(const JSCallbackInfo& info)
567 {
568     if (Container::IsCurrentUseNewPipeline()) {
569         if (info[0]->IsUndefined()) {
570             auto pipeline = PipelineBase::GetCurrentContext();
571             CHECK_NULL_VOID(pipeline);
572             auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
573             CHECK_NULL_VOID_NOLOG(theme);
574             auto textFieldPadding = theme->GetPadding();
575             ViewAbstractModel::GetInstance()->SetPaddings(
576                 textFieldPadding.Top(), textFieldPadding.Bottom(), textFieldPadding.Left(), textFieldPadding.Right());
577             return;
578         }
579         JSViewAbstract::JsPadding(info);
580         return;
581     }
582     if (!info[0]->IsString() && !info[0]->IsNumber() && !info[0]->IsObject()) {
583         LOGE("arg is not a string, number or object.");
584         return;
585     }
586     Edge padding;
587     if (info[0]->IsNumber() || info[0]->IsString()) {
588         Dimension edgeValue;
589         if (ParseJsDimensionVp(info[0], edgeValue)) {
590             padding = Edge(edgeValue);
591         }
592     }
593     if (info[0]->IsObject()) {
594         JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
595         Dimension left = Dimension(0.0, DimensionUnit::VP);
596         Dimension top = Dimension(0.0, DimensionUnit::VP);
597         Dimension right = Dimension(0.0, DimensionUnit::VP);
598         Dimension bottom = Dimension(0.0, DimensionUnit::VP);
599         ParseJsDimensionVp(object->GetProperty("left"), left);
600         ParseJsDimensionVp(object->GetProperty("top"), top);
601         ParseJsDimensionVp(object->GetProperty("right"), right);
602         ParseJsDimensionVp(object->GetProperty("bottom"), bottom);
603         padding = Edge(left, top, right, bottom);
604     }
605     auto* stack = ViewStackProcessor::GetInstance();
606     auto component = AceType::DynamicCast<TextFieldComponent>(stack->GetMainComponent());
607     if (component) {
608         auto decoration = component->GetDecoration();
609         decoration->SetPadding(padding);
610     }
611 }
612 
JsBorder(const JSCallbackInfo & info)613 void JSTextField::JsBorder(const JSCallbackInfo& info)
614 {
615     if (Container::IsCurrentUseNewPipeline()) {
616         JSViewAbstract::JsBorder(info);
617         return;
618     }
619     if (!info[0]->IsObject()) {
620         LOGE("args is not a object. %s", info[0]->ToString().c_str());
621         return;
622     }
623     RefPtr<Decoration> decoration = nullptr;
624     auto component = AceType::DynamicCast<TextFieldComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
625     if (component) {
626         decoration = component->GetDecoration();
627     }
628     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
629     auto valueWidth = object->GetProperty("width");
630     if (!valueWidth->IsUndefined()) {
631         ParseBorderWidth(valueWidth);
632     }
633     auto valueColor = object->GetProperty("color");
634     if (!valueColor->IsUndefined()) {
635         ParseBorderColor(valueColor);
636     }
637     auto valueRadius = object->GetProperty("radius");
638     if (!valueRadius->IsUndefined()) {
639         ParseBorderRadius(valueRadius);
640     }
641     auto valueStyle = object->GetProperty("style");
642     if (!valueStyle->IsUndefined()) {
643         ParseBorderStyle(valueStyle);
644     }
645     ViewAbstractModelImpl::SwapBackBorder(decoration);
646     if (component) {
647         component->SetOriginBorder(decoration->GetBorder());
648     }
649     info.ReturnSelf();
650 }
651 
JsBorderWidth(const JSCallbackInfo & info)652 void JSTextField::JsBorderWidth(const JSCallbackInfo& info)
653 {
654     if (Container::IsCurrentUseNewPipeline()) {
655         JSViewAbstract::JsBorderWidth(info);
656         return;
657     }
658     if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
659         LOGE("args need a string or number or object");
660         return;
661     }
662     RefPtr<Decoration> decoration = nullptr;
663     auto component = AceType::DynamicCast<TextFieldComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
664     if (component) {
665         decoration = component->GetDecoration();
666     }
667     JSViewAbstract::ParseBorderWidth(info[0]);
668     ViewAbstractModelImpl::SwapBackBorder(decoration);
669     if (component) {
670         component->SetOriginBorder(decoration->GetBorder());
671     }
672 }
673 
JsBorderColor(const JSCallbackInfo & info)674 void JSTextField::JsBorderColor(const JSCallbackInfo& info)
675 {
676     if (Container::IsCurrentUseNewPipeline()) {
677         JSViewAbstract::JsBorderColor(info);
678         return;
679     }
680     if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
681         LOGE("args need a string or number or object");
682         return;
683     }
684     RefPtr<Decoration> decoration = nullptr;
685     auto component = AceType::DynamicCast<TextFieldComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
686     if (component) {
687         decoration = component->GetDecoration();
688     }
689     JSViewAbstract::ParseBorderColor(info[0]);
690     ViewAbstractModelImpl::SwapBackBorder(decoration);
691     if (component) {
692         component->SetOriginBorder(decoration->GetBorder());
693     }
694 }
695 
JsBorderStyle(const JSCallbackInfo & info)696 void JSTextField::JsBorderStyle(const JSCallbackInfo& info)
697 {
698     if (Container::IsCurrentUseNewPipeline()) {
699         JSViewAbstract::JsBorderStyle(info);
700         return;
701     }
702     if (!info[0]->IsObject() && !info[0]->IsNumber()) {
703         LOGE("args need a string or number or object");
704         return;
705     }
706     RefPtr<Decoration> decoration = nullptr;
707     auto component = AceType::DynamicCast<TextFieldComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
708     if (component) {
709         decoration = component->GetDecoration();
710     }
711     JSViewAbstract::ParseBorderStyle(info[0]);
712     ViewAbstractModelImpl::SwapBackBorder(decoration);
713     if (component) {
714         component->SetOriginBorder(decoration->GetBorder());
715     }
716 }
717 
JsBorderRadius(const JSCallbackInfo & info)718 void JSTextField::JsBorderRadius(const JSCallbackInfo& info)
719 {
720     if (Container::IsCurrentUseNewPipeline()) {
721         JSViewAbstract::JsBorderRadius(info);
722         return;
723     }
724     if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
725         LOGE("args need a string or number or object");
726         return;
727     }
728     RefPtr<Decoration> decoration = nullptr;
729     auto component = AceType::DynamicCast<TextFieldComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
730     if (component) {
731         decoration = component->GetDecoration();
732     }
733     JSViewAbstract::ParseBorderRadius(info[0]);
734     ViewAbstractModelImpl::SwapBackBorder(decoration);
735     if (component) {
736         component->SetOriginBorder(decoration->GetBorder());
737     }
738 }
739 
JsHoverEffect(const JSCallbackInfo & info)740 void JSTextField::JsHoverEffect(const JSCallbackInfo& info)
741 {
742     if (!info[0]->IsNumber()) {
743         LOGE("info[0] is not a number");
744         return;
745     }
746     if (Container::IsCurrentUseNewPipeline()) {
747         NG::ViewAbstract::SetHoverEffect(static_cast<HoverEffectType>(info[0]->ToNumber<int32_t>()));
748         return;
749     }
750     auto component = AceType::DynamicCast<TextFieldComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
751     if (component) {
752         component->SetHoverAnimationType(static_cast<HoverAnimationType>(info[0]->ToNumber<int32_t>()));
753     }
754 }
755 
SetOnEditChanged(const JSCallbackInfo & info)756 void JSTextField::SetOnEditChanged(const JSCallbackInfo& info)
757 {
758     CHECK_NULL_VOID(info[0]->IsFunction());
759     JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
760     TextFieldModel::GetInstance()->SetOnEditChanged(std::move(callback));
761 }
762 
SetOnSubmit(const JSCallbackInfo & info)763 void JSTextField::SetOnSubmit(const JSCallbackInfo& info)
764 {
765     CHECK_NULL_VOID(info[0]->IsFunction());
766     JsEventCallback<void(int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
767     TextFieldModel::GetInstance()->SetOnSubmit(std::move(callback));
768 }
769 
SetOnChange(const JSCallbackInfo & info)770 void JSTextField::SetOnChange(const JSCallbackInfo& info)
771 {
772     CHECK_NULL_VOID(info[0]->IsFunction());
773     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
774     TextFieldModel::GetInstance()->SetOnChange(std::move(callback));
775 }
776 
SetOnCopy(const JSCallbackInfo & info)777 void JSTextField::SetOnCopy(const JSCallbackInfo& info)
778 {
779     CHECK_NULL_VOID(info[0]->IsFunction());
780     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
781     TextFieldModel::GetInstance()->SetOnCopy(std::move(callback));
782 }
783 
SetOnCut(const JSCallbackInfo & info)784 void JSTextField::SetOnCut(const JSCallbackInfo& info)
785 {
786     CHECK_NULL_VOID(info[0]->IsFunction());
787     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
788     TextFieldModel::GetInstance()->SetOnCut(std::move(callback));
789 }
790 
SetOnPaste(const JSCallbackInfo & info)791 void JSTextField::SetOnPaste(const JSCallbackInfo& info)
792 {
793     CHECK_NULL_VOID(info[0]->IsFunction());
794     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
795     TextFieldModel::GetInstance()->SetOnPaste(std::move(callback));
796 }
797 
SetOnClick(const JSCallbackInfo & info)798 void JSTextField::SetOnClick(const JSCallbackInfo& info)
799 {
800     if (Container::IsCurrentUseNewPipeline()) {
801         JSInteractableView::JsOnClick(info);
802         return;
803     }
804     if (!JSViewBindEvent(&TextFieldComponent::SetOnClick, info)) {
805         LOGW("Failed(OnPaste) to bind event");
806     }
807     info.ReturnSelf();
808 }
809 
SetCopyOption(const JSCallbackInfo & info)810 void JSTextField::SetCopyOption(const JSCallbackInfo& info)
811 {
812     if (info.Length() == 0) {
813         return;
814     }
815     auto copyOptions = CopyOptions::None;
816     if (info[0]->IsNumber()) {
817         auto emunNumber = info[0]->ToNumber<int>();
818         copyOptions = static_cast<CopyOptions>(emunNumber);
819     }
820     TextFieldModel::GetInstance()->SetCopyOption(copyOptions);
821 }
822 
UpdateDecoration(const RefPtr<BoxComponent> & boxComponent,const RefPtr<TextFieldComponent> & component,const Border & boxBorder,const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme> & textFieldTheme)823 void JSTextField::UpdateDecoration(const RefPtr<BoxComponent>& boxComponent,
824     const RefPtr<TextFieldComponent>& component, const Border& boxBorder,
825     const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)
826 {
827     if (!textFieldTheme) {
828         LOGE("UpdateDecoration: textFieldTheme is null.");
829         return;
830     }
831 
832     RefPtr<Decoration> decoration = component->GetDecoration();
833     RefPtr<Decoration> boxDecoration = boxComponent->GetBackDecoration();
834     if (!decoration) {
835         decoration = AceType::MakeRefPtr<Decoration>();
836     }
837     if (boxDecoration) {
838         Border border = decoration->GetBorder();
839         border.SetLeftEdge(boxBorder.Left());
840         border.SetRightEdge(boxBorder.Right());
841         border.SetTopEdge(boxBorder.Top());
842         border.SetBottomEdge(boxBorder.Bottom());
843         border.SetBorderRadius(textFieldTheme->GetBorderRadius());
844         decoration->SetBorder(border);
845         component->SetOriginBorder(decoration->GetBorder());
846 
847         if (boxDecoration->GetImage() || boxDecoration->GetGradient().IsValid()) {
848             // clear box properties except background image and radius.
849             boxDecoration->SetBackgroundColor(Color::TRANSPARENT);
850             Border border;
851             border.SetBorderRadius(textFieldTheme->GetBorderRadius());
852             boxDecoration->SetBorder(border);
853         }
854     } else {
855         boxDecoration = AceType::MakeRefPtr<Decoration>();
856         boxDecoration->SetBorderRadius(textFieldTheme->GetBorderRadius());
857         boxComponent->SetBackDecoration(boxDecoration);
858     }
859 }
860 
861 } // namespace OHOS::Ace::Framework
862