• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "core/components/text_field/render_text_field.h"
17 
18 #include <regex>
19 #include <string>
20 #include <unordered_map>
21 #include <utility>
22 
23 #include "base/geometry/dimension.h"
24 #include "base/i18n/localization.h"
25 #include "base/json/json_util.h"
26 #include "base/log/ace_trace.h"
27 #include "base/log/dump_log.h"
28 #include "base/log/log_wrapper.h"
29 #include "base/mousestyle/mouse_style.h"
30 #include "base/subwindow/subwindow_manager.h"
31 #include "base/utils/string_utils.h"
32 #include "base/utils/utils.h"
33 #include "core/animation/curve_animation.h"
34 #include "core/common/clipboard/clipboard_proxy.h"
35 #include "core/common/container_scope.h"
36 #include "core/common/font_manager.h"
37 #include "core/common/ime/text_input_type.h"
38 #include "core/common/text_field_manager.h"
39 #include "core/components/stack/stack_element.h"
40 #include "core/components/text/text_utils.h"
41 #include "core/components/text_overlay/text_overlay_component.h"
42 #include "core/components/text_overlay/text_overlay_element.h"
43 #include "core/components_v2/inspector/utils.h"
44 #include "core/event/ace_event_helper.h"
45 #include "core/event/mouse_event.h"
46 #if defined(ENABLE_STANDARD_INPUT)
47 #include "core/components/text_field/on_text_changed_listener_impl.h"
48 #endif
49 
50 namespace OHOS::Ace {
51 namespace {
52 
53 constexpr uint32_t TWINKLING_INTERVAL_MS = 500;
54 // Tick count indicate how long should the naked character should be displayed while obscure_ == true.
55 constexpr uint32_t OBSCURE_SHOW_TICKS = 3;
56 constexpr double HANDLE_HOT_ZONE = 10.0;
57 
58 constexpr char16_t OBSCURING_CHARACTER = u'•';
59 constexpr char16_t OBSCURING_CHARACTER_FOR_AR = u'*';
60 
61 constexpr int32_t DEFAULT_SELECT_INDEX = 0;
62 constexpr int32_t SHOW_HANDLE_DURATION = 250;
63 constexpr int32_t DOUBLE_CLICK_FINGERS = 1;
64 constexpr int32_t DOUBLE_CLICK_COUNTS = 2;
65 constexpr double FIFTY_PERCENT = 0.5;
66 
67 constexpr Dimension OFFSET_FOCUS = 4.0_vp;
68 constexpr Dimension DEFLATE_RADIUS_FOCUS = 3.0_vp;
69 
70 const std::string DIGIT_BLACK_LIST = "[^\\d.\\-e]+";
71 const std::string PHONE_BLACK_LIST = "[^\\d\\-\\+\\*\\#]+";
72 const std::string DIGIT_WHITE_LIST = "^[0-9]*$";
73 const std::string PHONE_WHITE_LIST = "[\\d\\-\\+\\*\\#]+";
74 const std::string EMAIL_WHITE_LIST = "[\\w.]";
75 const std::string URL_WHITE_LIST = "[a-zA-z]+://[^\\s]*";
76 const std::string NEW_LINE = "\n";
77 // Whether the system is Mac or not determines which key code is selected.
78 #if defined(MAC_PLATFORM)
79 #define KEY_META_OR_CTRL_LEFT KeyCode::KEY_META_LEFT
80 #define KEY_META_OR_CTRL_RIGHT KeyCode::KEY_META_RIGHT
81 #else
82 #define KEY_META_OR_CTRL_LEFT KeyCode::KEY_CTRL_LEFT
83 #define KEY_META_OR_CTRL_RIGHT KeyCode::KEY_CTRL_RIGHT
84 #endif
85 
86 #if !defined(PREVIEW)
RemoveErrorTextFromValue(const std::string & value,const std::string & errorText,std::string & result)87 void RemoveErrorTextFromValue(const std::string& value, const std::string& errorText, std::string& result)
88 {
89     int32_t valuePtr = 0;
90     int32_t errorTextPtr = 0;
91     auto valueSize = static_cast<int32_t>(value.size());
92     auto errorTextSize = static_cast<int32_t>(errorText.size());
93     while (errorTextPtr < errorTextSize) {
94         while (value[valuePtr] != errorText[errorTextPtr] && valuePtr < valueSize) {
95             result += value[valuePtr];
96             valuePtr++;
97         }
98         // no more text left to remove in value
99         if (valuePtr >= valueSize) {
100             return;
101         }
102         // increase both value ptr and error text ptr if char in value is removed
103         valuePtr++;
104         errorTextPtr++;
105     }
106     result += value.substr(valuePtr);
107 }
108 #endif
109 
GetKeyboardFilter(TextInputType keyboard,std::string & keyboardFilterValue,bool useBlackList)110 void GetKeyboardFilter(TextInputType keyboard, std::string& keyboardFilterValue, bool useBlackList)
111 {
112     switch (keyboard) {
113         case TextInputType::NUMBER: {
114             keyboardFilterValue = useBlackList ? DIGIT_BLACK_LIST : DIGIT_WHITE_LIST;
115             break;
116         }
117         case TextInputType::PHONE: {
118             keyboardFilterValue = useBlackList ? PHONE_BLACK_LIST : PHONE_WHITE_LIST;
119             break;
120         }
121         case TextInputType::EMAIL_ADDRESS: {
122             keyboardFilterValue = EMAIL_WHITE_LIST;
123             break;
124         }
125         case TextInputType::URL: {
126             keyboardFilterValue = URL_WHITE_LIST;
127             break;
128         }
129         default: {
130             // No need limit.
131             return;
132         }
133     }
134 }
135 } // namespace
136 
137 #if defined(ENABLE_STANDARD_INPUT)
UpdateConfiguration()138 void RenderTextField::UpdateConfiguration()
139 {
140     MiscServices::Configuration configuration;
141     LOGI("UpdateConfiguration: Enter key type %{public}d", static_cast<int32_t>(action_));
142     LOGI("UpdateConfiguration: Enter keyboard type %{public}d", static_cast<int32_t>(keyboard_));
143     configuration.SetEnterKeyType(static_cast<MiscServices::EnterKeyType>((int32_t)action_));
144     configuration.SetTextInputType(static_cast<MiscServices::TextInputType>((int32_t)keyboard_));
145     MiscServices::InputMethodController::GetInstance()->OnConfigurationChange(configuration);
146 }
147 #endif
148 
RenderTextField()149 RenderTextField::RenderTextField()
150     : twinklingInterval(TWINKLING_INTERVAL_MS), controller_(AceType::MakeRefPtr<TextEditController>())
151 {}
152 
~RenderTextField()153 RenderTextField::~RenderTextField()
154 {
155     LOGI("Destruction text field.");
156     if (controller_) {
157         controller_->Clear();
158         controller_->RemoveObserver(WeakClaim(this));
159     }
160     auto pipelineContext = context_.Upgrade();
161     if (!pipelineContext) {
162         return;
163     }
164     PopTextOverlay();
165     pipelineContext->RemoveFontNode(AceType::WeakClaim(this));
166     auto fontManager = pipelineContext->GetFontManager();
167     if (fontManager) {
168         fontManager->UnRegisterCallback(AceType::WeakClaim(this));
169         fontManager->RemoveVariationNode(WeakClaim(this));
170     }
171     if (HasSurfaceChangedCallback()) {
172         LOGD("Unregister surface change callback with id %{public}d", surfaceChangedCallbackId_.value_or(-1));
173         pipelineContext->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
174     }
175     if (HasSurfacePositionChangedCallback()) {
176         LOGD("Unregister surface position change callback with id %{public}d",
177             surfacePositionChangedCallbackId_.value_or(-1));
178         pipelineContext->UnregisterSurfacePositionChangedCallback(surfacePositionChangedCallbackId_.value_or(-1));
179     }
180     // If soft keyboard is still exist, close it.
181     if (HasConnection()) {
182 #if defined(ENABLE_STANDARD_INPUT)
183         LOGI("Destruction text field, close input method.");
184         MiscServices::InputMethodController::GetInstance()->Close();
185 #else
186         connection_->Close(GetInstanceId());
187         connection_ = nullptr;
188 #endif
189     }
190 }
191 
Update(const RefPtr<Component> & component)192 void RenderTextField::Update(const RefPtr<Component>& component)
193 {
194     const RefPtr<TextFieldComponent> textField = AceType::DynamicCast<TextFieldComponent>(component);
195     if (!textField) {
196         return;
197     }
198 
199     // Clear children to avoid children increase.
200     ClearChildren();
201 
202     if (textField->IsTextLengthLimited()) {
203         maxLength_ = textField->GetMaxLength();
204     }
205 
206     copyOption_ = textField->GetCopyOption();
207     selection_ = textField->GetSelection();
208     placeholder_ = textField->GetPlaceholder();
209     inputFilter_ = textField->GetInputFilter();
210     inactivePlaceholderColor_ = textField->GetPlaceholderColor();
211     focusPlaceholderColor_ = textField->GetFocusPlaceholderColor();
212     focusBgColor_ = textField->GetFocusBgColor();
213     focusTextColor_ = textField->GetFocusTextColor();
214     selectedColor_ = textField->GetSelectedColor();
215     pressColor_ = textField->GetPressColor();
216     hoverColor_ = textField->GetHoverColor();
217     hoverAnimationType_ = textField->GetHoverAnimationType();
218     decoration_ = textField->GetDecoration();
219     inactiveBgColor_ = textField->GetBgColor();
220     if (decoration_ && (decoration_->GetImage() || decoration_->GetGradient().IsValid())) {
221         inactiveBgColor_ = Color::TRANSPARENT;
222         focusBgColor_ = Color::TRANSPARENT;
223     }
224     originBorder_ = textField->GetOriginBorder();
225     if (style_ != textField->GetTextStyle()) {
226         ResetStatus();
227     }
228     style_ = textField->GetTextStyle();
229     placeHoldStyle_ = textField->GetPlaceHoldStyle();
230     editingStyle_ = textField->GetEditingStyle();
231     fontSize_ = style_.GetFontSize();
232     errorTextStyle_ = textField->GetErrorTextStyle();
233     errorSpacingInDimension_ = textField->GetErrorSpacing();
234     errorIsInner_ = textField->GetErrorIsInner();
235     errorBorderWidth_ = textField->GetErrorBorderWidth();
236     errorBorderColor_ = textField->GetErrorBorderColor();
237     needFade_ = textField->NeedFade();
238     inactiveTextColor_ = style_.GetTextColor();
239     maxLines_ = textField->GetTextMaxLines();
240     onTextChangeEvent_ = AceAsyncEvent<void(const std::string&)>::Create(textField->GetOnTextChange(), context_);
241     onError_ = textField->GetOnError();
242     onValueChangeEvent_ = textField->GetOnTextChange().GetUiStrFunction();
243     if (textField->GetOnChange()) {
244         onChange_ = *textField->GetOnChange();
245     }
246     if (textField->GetOnEditChanged()) {
247         onEditChanged_ = *textField->GetOnEditChanged();
248     }
249     if (textField->GetOnSubmit()) {
250         onSubmit_ = *textField->GetOnSubmit();
251     }
252     if (textField->GetOnClick()) {
253         onClick_ = *textField->GetOnClick();
254     }
255     onSelectChangeEvent_ = AceAsyncEvent<void(const std::string&)>::Create(textField->GetOnSelectChange(), context_);
256     onFinishInputEvent_ = AceAsyncEvent<void(const std::string&)>::Create(textField->GetOnFinishInput(), context_);
257     onTapEvent_ = AceAsyncEvent<void()>::Create(textField->GetOnTap(), context_);
258     catchMode_ = textField->GetOnTap().IsEmpty() || textField->GetOnTap().GetCatchMode();
259     static const int32_t bubbleModeVersion = 6;
260     auto pipeline = context_.Upgrade();
261     if (!catchMode_) {
262         if (pipeline && pipeline->GetMinPlatformVersion() >= bubbleModeVersion) {
263             catchMode_ = false;
264         } else {
265             catchMode_ = true;
266         }
267     }
268     onLongPressEvent_ = AceAsyncEvent<void()>::Create(textField->GetOnLongPress(), context_);
269     textAlign_ = textField->GetTextAlign();
270     textDirection_ = textField->GetTextDirection();
271     realTextDirection_ = textDirection_;
272     showCursor_ = textField->ShowCursor();
273     UpdateObscure(textField);
274     enabled_ = textField->IsEnabled();
275     widthReserved_ = textField->GetWidthReserved();
276     blockRightShade_ = textField->GetBlockRightShade();
277     isVisible_ = textField->IsVisible();
278     showPasswordIcon_ = textField->ShowPasswordIcon();
279     if (textField->HasSetResetToStart() && textField->GetUpdateType() == UpdateType::ALL) {
280         resetToStart_ = textField->GetResetToStart();
281     }
282     if (keyboard_ != TextInputType::UNSPECIFIED && keyboard_ != textField->GetTextInputType()) {
283         LOGI("TextInput changed, close keyboard");
284         CloseKeyboard();
285     }
286     if (keyboard_ != textField->GetTextInputType()) {
287         auto context = context_.Upgrade();
288         if (context && context->GetIsDeclarative()) {
289             ClearEditingValue();
290         } else {
291             if (keyboard_ == TextInputType::VISIBLE_PASSWORD) {
292                 ClearEditingValue();
293             }
294         }
295         keyboard_ = textField->GetTextInputType();
296     }
297     if (keyboard_ == TextInputType::MULTILINE) {
298         action_ = TextInputAction::DONE;
299     } else {
300         if (action_ != TextInputAction::UNSPECIFIED && action_ != textField->GetAction()) {
301             auto context = context_.Upgrade();
302             if (context && context->GetIsDeclarative()) {
303                 LOGI("Action changed, close keyboard");
304                 CloseKeyboard();
305             }
306         }
307         if (action_ != textField->GetAction()) {
308             action_ = textField->GetAction();
309         }
310     }
311 
312     actionLabel_ = textField->GetActionLabel();
313     height_ = textField->GetHeight();
314     if (textField->IsCursorColorSet()) {
315         cursorColorIsSet_ = true;
316         cursorColor_ = textField->GetCursorColor();
317     }
318     cursorRadius_ = textField->GetCursorRadius();
319     textFieldController_ = textField->GetTextFieldController();
320     if (textFieldController_) {
321         auto weak = AceType::WeakClaim(this);
322         textFieldController_->SetCaretPosition([weak](int32_t caretPosition) {
323             auto textField = weak.Upgrade();
324             if (textField) {
325                 textField->UpdateSelection(caretPosition);
326                 textField->cursorPositionType_ = CursorPositionType::NORMAL;
327                 textField->MarkNeedLayout();
328             }
329         });
330     }
331     if (textField->GetTextEditController() && controller_ != textField->GetTextEditController()) {
332         if (controller_) {
333             controller_->RemoveObserver(WeakClaim(this));
334         }
335         controller_ = textField->GetTextEditController();
336     }
337     if (controller_) {
338         controller_->RemoveObserver(WeakClaim(this));
339         controller_->AddObserver(WeakClaim(this));
340         controller_->SetHint(placeholder_);
341         if (textField->IsValueUpdated()) {
342             if (textField->GetValue() != GetEditingValue().text) {
343                 PopTextOverlay();
344             }
345             controller_->SetText(textField->GetValue(), false);
346         }
347     }
348     // maybe change text and selection
349     ApplyRestoreInfo();
350     extend_ = textField->IsExtend();
351     softKeyboardEnabled_ = textField->IsSoftKeyboardEnabled();
352     text_ = textField->GetValue();
353     showEllipsis_ = textField->ShowEllipsis();
354     auto context = context_.Upgrade();
355     if (!clipboard_ && context) {
356         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
357     }
358 
359     if ((style_.IsAllowScale() || style_.GetFontSize().Unit() == DimensionUnit::FP) && context) {
360         context->AddFontNode(AceType::WeakClaim(this));
361     }
362 
363     showCounter_ = textField->ShowCounter();
364     countTextStyle_ = textField->GetCountTextStyle();
365     overCountStyle_ = textField->GetOverCountStyle();
366     countTextStyleOuter_ = textField->GetCountTextStyleOuter();
367     overCountStyleOuter_ = textField->GetOverCountStyleOuter();
368 
369     inputOptions_ = textField->GetInputOptions();
370     onOptionsClick_ = textField->GetOnOptionsClick();
371     onTranslate_ = textField->GetOnTranslate();
372     onShare_ = textField->GetOnShare();
373     onSearch_ = textField->GetOnSearch();
374     inputStyle_ = textField->GetInputStyle();
375     if (textField->IsSetFocusOnTouch()) {
376         isFocusOnTouch_ = textField->IsFocusOnTouch();
377     }
378     SetCallback(textField);
379     UpdateFocusStyles();
380     UpdateIcon(textField);
381     RegisterFontCallbacks();
382     MarkNeedLayout();
383     UpdateAccessibilityAttr();
384 }
385 
SetCallback(const RefPtr<TextFieldComponent> & textField)386 void RenderTextField::SetCallback(const RefPtr<TextFieldComponent>& textField)
387 {
388     if (textField->GetOnCopy()) {
389         onCopy_ = *textField->GetOnCopy();
390     }
391     if (textField->GetOnCut()) {
392         onCut_ = *textField->GetOnCut();
393     }
394     if (textField->GetOnPaste()) {
395         onPaste_ = *textField->GetOnPaste();
396     }
397     auto pipeline = GetContext().Upgrade();
398     CHECK_NULL_VOID(pipeline);
399     if (!HasSurfaceChangedCallback()) {
400         auto callbackId =
401             pipeline->RegisterSurfaceChangedCallback([weakTextField = AceType::WeakClaim(this)](int32_t newWidth,
402                                                          int32_t newHeight, int32_t prevWidth, int32_t prevHeight) {
403                 auto textfield = weakTextField.Upgrade();
404                 if (textfield) {
405                     textfield->HandleSurfaceChanged(newWidth, newHeight, prevWidth, prevHeight);
406                 }
407             });
408         LOGI("Add surface changed callback id %{public}d", callbackId);
409         UpdateSurfaceChangedCallbackId(callbackId);
410     }
411     if (!HasSurfacePositionChangedCallback()) {
412         auto callbackId = pipeline->RegisterSurfacePositionChangedCallback(
413             [weakTextField = AceType::WeakClaim(this)](int32_t posX, int32_t posY) {
414                 auto textfield = weakTextField.Upgrade();
415                 if (textfield) {
416                     textfield->HandleSurfacePositionChanged(posX, posY);
417                 }
418             });
419         LOGI("Add position changed callback id %{public}d", callbackId);
420         UpdateSurfacePositionChangedCallbackId(callbackId);
421     }
422 }
423 
HandleSurfaceChanged(int32_t newWidth,int32_t newHeight,int32_t prevWidth,int32_t prevHeight)424 void RenderTextField::HandleSurfaceChanged(int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight)
425 {
426     LOGD("Textfield handle surface change, new width %{public}d, new height %{public}d, prev width %{public}d, prev "
427          "height %{public}d",
428         newWidth, newHeight, prevWidth, prevHeight);
429     UpdateCaretInfoToController();
430 }
431 
HandleSurfacePositionChanged(int32_t posX,int32_t posY)432 void RenderTextField::HandleSurfacePositionChanged(int32_t posX, int32_t posY)
433 {
434     LOGD("Textfield handle surface position change, posX %{public}d, posY %{public}d", posX, posY);
435     UpdateCaretInfoToController();
436 }
437 
UpdateCaretInfoToController()438 void RenderTextField::UpdateCaretInfoToController()
439 {
440     auto context = context_.Upgrade();
441     CHECK_NULL_VOID(context);
442     auto manager = context->GetTextFieldManager();
443     CHECK_NULL_VOID(manager);
444     auto textFieldManager = AceType::DynamicCast<TextFieldManager>(manager);
445     CHECK_NULL_VOID(textFieldManager);
446     auto weakFocusedTextField = textFieldManager->GetOnFocusTextField();
447     auto focusedTextField = weakFocusedTextField.Upgrade();
448     if (!focusedTextField || focusedTextField != AceType::Claim(this)) {
449         return;
450     }
451 #if defined(ENABLE_STANDARD_INPUT)
452     auto globalOffset = GetGlobalOffset();
453     auto windowOffset = context->GetDisplayWindowRectInfo().GetOffset();
454     MiscServices::CursorInfo cursorInfo { .left = caretRect_.Left() + globalOffset.GetX() + windowOffset.GetX(),
455         .top = caretRect_.Top() + globalOffset.GetY() + windowOffset.GetY(),
456         .width = caretRect_.Width(),
457         .height = caretRect_.Height() };
458     LOGD("UpdateCaretInfoToController, left %{public}f, top %{public}f, width %{public}f, height %{public}f",
459         cursorInfo.left, cursorInfo.top, cursorInfo.width, cursorInfo.height);
460     MiscServices::InputMethodController::GetInstance()->OnCursorUpdate(cursorInfo);
461     auto value = GetEditingValue();
462     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
463         StringUtils::Str8ToStr16(value.text), value.selection.GetStart(), value.selection.GetEnd());
464 #endif
465 }
466 
OnPaintFinish()467 void RenderTextField::OnPaintFinish()
468 {
469     UpdateFocusAnimation();
470     UpdateOverlay();
471     InitAccessibilityEventListener();
472     UpdateAccessibilityPosition();
473     auto layoutParamChanged = lastLayoutParam_.has_value() ? lastLayoutParam_.value() == GetLayoutParam() : true;
474     if (layoutParamChanged) {
475         lastLayoutParam_ = GetLayoutParam();
476     }
477     bool needNotifyChangeEvent = !isValueFromFront_ || layoutParamChanged;
478     // If height or lines is changed, make needNotifyChangeEvent_ true to notify change event.
479     if (needNotifyChangeEvent && (!NearEqual(textHeight_, textHeightLast_) || textLines_ != textLinesLast_)) {
480         needNotifyChangeEvent_ = true;
481         textHeightLast_ = textHeight_;
482         textLinesLast_ = textLines_;
483     }
484     if (needNotifyChangeEvent_ && (onTextChangeEvent_ || onValueChangeEvent_ || onChange_)) {
485         needNotifyChangeEvent_ = false;
486         if (onValueChangeEvent_) {
487             onValueChangeEvent_(GetEditingValue().text);
488         }
489         if (onTextChangeEvent_) {
490             auto jsonResult = JsonUtil::Create(true);
491             jsonResult->Put("text", GetEditingValue().text.c_str());
492             jsonResult->Put("value", GetEditingValue().text.c_str());
493             jsonResult->Put("lines", textLines_);
494             jsonResult->Put("height", textHeight_);
495             onTextChangeEvent_(std::string(R"("change",)").append(jsonResult->ToString()));
496         }
497     }
498 }
499 
PerformLayout()500 void RenderTextField::PerformLayout()
501 {
502     if (!lastLayoutParam_.has_value()) {
503         lastLayoutParam_.emplace(GetLayoutParam());
504     }
505 
506     if (GetEditingValue().text.empty()) {
507         cursorPositionType_ = CursorPositionType::END;
508     }
509 
510     auto context = context_.Upgrade();
511     if (context && context->GetIsDeclarative()) {
512         const auto& currentText = controller_->GetValue().text;
513         showPlaceholder_ = currentText.empty();
514         if (showPlaceholder_) {
515             SetTextStyle(placeHoldStyle_);
516         } else {
517             SetTextStyle(editingStyle_);
518         }
519     }
520 
521     auto pipelineContext = GetContext().Upgrade();
522     if ((style_.IsAllowScale() || style_.GetFontSize().Unit() == DimensionUnit::FP) && pipelineContext &&
523         !NearEqual(fontScale_, pipelineContext->GetFontScale())) {
524         fontScale_ = pipelineContext->GetFontScale();
525         style_.SetFontSize(fontSize_ * fontScale_);
526     }
527 
528     iconSize_ = NormalizeToPx(iconSizeInDimension_);
529     iconHotZoneSize_ = NormalizeToPx(iconHotZoneSizeInDimension_);
530     errorSpacing_ = NormalizeToPx(errorSpacingInDimension_);
531     if (!GetChildren().empty()) {
532         auto innerLayout = GetLayoutParam();
533         innerLayout.SetMinSize(Size());
534         const auto& child = GetChildren().front();
535         child->Layout(innerLayout);
536     }
537     ApplyAspectRatio();
538     SetLayoutSize(GetLayoutParam().Constrain(Measure()));
539     UpdateFocusAnimation();
540 
541     LayoutParam layoutParam = GetLayoutParam();
542     layoutParam.SetMinSize(Size());
543     if (iconImage_) {
544         iconImage_->Layout(layoutParam);
545     }
546     if (renderShowIcon_) {
547         renderShowIcon_->Layout(layoutParam);
548     }
549     if (renderHideIcon_) {
550         renderHideIcon_->Layout(layoutParam);
551     }
552 
553     HandleDeviceOrientationChange();
554 }
555 
HandleMouseEvent(const MouseEvent & event)556 bool RenderTextField::HandleMouseEvent(const MouseEvent& event)
557 {
558     if (event.button == MouseButton::LEFT_BUTTON) {
559         if (event.action == MouseAction::PRESS) {
560             UpdateStartSelection(DEFAULT_SELECT_INDEX, event.GetOffset(), true, false);
561         } else if (event.action == MouseAction::MOVE) {
562             int32_t start = GetEditingValue().selection.baseOffset;
563             int32_t end = GetCursorPositionForClick(event.GetOffset());
564             UpdateSelection(start, end);
565             MarkNeedRender();
566         } else {
567             LOGD("on left button release");
568         }
569     }
570 
571     if (event.button == MouseButton::RIGHT_BUTTON && event.action == MouseAction::RELEASE) {
572         Offset rightClickOffset = event.GetOffset();
573         ShowTextOverlay(rightClickOffset, false, true);
574     }
575 
576     return true;
577 }
578 
HandleMouseHoverEvent(MouseState mouseState)579 void RenderTextField::HandleMouseHoverEvent(MouseState mouseState)
580 {
581     auto pipeline = context_.Upgrade();
582     if (!pipeline) {
583         return;
584     }
585     int32_t windowId = pipeline->GetWindowId();
586     auto mouseStyle = MouseStyle::CreateMouseStyle();
587     MouseFormat defaultStyle = MouseFormat::DEFAULT;
588     MouseFormat textCursorStyle = MouseFormat::TEXT_CURSOR;
589     if (mouseState == MouseState::HOVER) {
590         mouseStyle->SetPointerStyle(windowId, textCursorStyle);
591     } else {
592         mouseStyle->SetPointerStyle(windowId, defaultStyle);
593     }
594 }
595 
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)596 void RenderTextField::OnTouchTestHit(
597     const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
598 {
599     if (!enabled_) {
600         return;
601     }
602     if (!clickRecognizer_) {
603         clickRecognizer_ = AceType::MakeRefPtr<ClickRecognizer>();
604         clickRecognizer_->SetUseCatchMode(catchMode_);
605         auto weak = WeakClaim(this);
606         clickRecognizer_->SetOnClick([weak](const ClickInfo& info) {
607             auto client = weak.Upgrade();
608             if (client) {
609                 client->OnClick(info);
610             }
611         });
612         clickRecognizer_->SetPriority(GesturePriority::Low);
613     }
614     clickRecognizer_->SetCoordinateOffset(coordinateOffset);
615     result.emplace_back(clickRecognizer_);
616 
617     if (!doubleClickRecognizer_) {
618         doubleClickRecognizer_ =
619             AceType::MakeRefPtr<ClickRecognizer>(context_, DOUBLE_CLICK_FINGERS, DOUBLE_CLICK_COUNTS);
620         doubleClickRecognizer_->SetUseCatchMode(catchMode_);
621         auto weak = WeakClaim(this);
622         doubleClickRecognizer_->SetOnClick([weak](const ClickInfo& info) {
623             auto client = weak.Upgrade();
624             if (client) {
625                 client->OnDoubleClick(info);
626             }
627         });
628         doubleClickRecognizer_->SetPriority(GesturePriority::High);
629     }
630     doubleClickRecognizer_->SetCoordinateOffset(coordinateOffset);
631     result.emplace_back(doubleClickRecognizer_);
632 
633     if (!longPressRecognizer_) {
634         longPressRecognizer_ = AceType::MakeRefPtr<LongPressRecognizer>(context_);
635         auto weak = WeakClaim(this);
636         longPressRecognizer_->SetOnLongPress([weak = WeakClaim(this)](const LongPressInfo& info) {
637             auto client = weak.Upgrade();
638             if (client) {
639                 client->OnLongPress(info);
640             }
641         });
642         longPressRecognizer_->SetPriority(GesturePriority::High);
643     }
644     longPressRecognizer_->SetCoordinateOffset(coordinateOffset);
645     longPressRecognizer_->SetTouchRestrict(touchRestrict);
646     result.emplace_back(longPressRecognizer_);
647 
648     if (!rawRecognizer_) {
649         rawRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
650         auto weak = WeakClaim(this);
651         rawRecognizer_->SetOnTouchDown([weak = WeakClaim(this)](const TouchEventInfo& info) {
652             auto textField = weak.Upgrade();
653             if (textField) {
654                 textField->StartPressAnimation(true);
655             }
656         });
657 
658         rawRecognizer_->SetOnTouchUp([weak = WeakClaim(this)](const TouchEventInfo& info) {
659             auto textField = weak.Upgrade();
660             if (textField) {
661                 textField->StartPressAnimation(false);
662                 textField->OnTapCallback();
663             }
664         });
665 
666         rawRecognizer_->SetOnTouchCancel([weak = WeakClaim(this)](const TouchEventInfo& info) {
667             auto textField = weak.Upgrade();
668             if (textField) {
669                 textField->StartPressAnimation(false);
670             }
671         });
672     }
673     rawRecognizer_->SetTouchRestrict(touchRestrict);
674     rawRecognizer_->SetCoordinateOffset(coordinateOffset);
675     result.emplace_back(rawRecognizer_);
676 }
677 
StartPressAnimation(bool pressDown)678 void RenderTextField::StartPressAnimation(bool pressDown)
679 {
680     if (!pressController_) {
681         pressController_ = AceType::MakeRefPtr<Animator>(context_);
682     }
683     if (pressController_->IsRunning()) {
684         pressController_->Stop();
685     }
686     if (hoverController_ && hoverController_->IsRunning()) {
687         hoverController_->Stop();
688     }
689     pressController_->ClearInterpolators();
690     RefPtr<KeyframeAnimation<Color>> animation = AceType::MakeRefPtr<KeyframeAnimation<Color>>();
691     if (pressDown) {
692         CreateMouseAnimation(animation, GetEventEffectColor(), pressColor_);
693     } else {
694         CreateMouseAnimation(animation, GetEventEffectColor(), Color::TRANSPARENT);
695     }
696     pressController_->AddInterpolator(animation);
697     pressController_->SetDuration(PRESS_DURATION);
698     pressController_->SetFillMode(FillMode::FORWARDS);
699     pressController_->Forward();
700 }
701 
StartHoverAnimation(bool isHovered)702 void RenderTextField::StartHoverAnimation(bool isHovered)
703 {
704     if (pressController_ && pressController_->IsRunning()) {
705         return;
706     }
707     if (!hoverController_) {
708         hoverController_ = AceType::MakeRefPtr<Animator>(context_);
709     }
710     if (hoverController_->IsRunning()) {
711         hoverController_->Stop();
712     }
713     hoverController_->ClearInterpolators();
714     RefPtr<KeyframeAnimation<Color>> animation = AceType::MakeRefPtr<KeyframeAnimation<Color>>();
715     if (isHovered) {
716         CreateMouseAnimation(animation, GetEventEffectColor(), hoverColor_);
717     } else {
718         CreateMouseAnimation(animation, GetEventEffectColor(), Color::TRANSPARENT);
719     }
720     hoverController_->AddInterpolator(animation);
721     hoverController_->SetDuration(HOVER_DURATION);
722     hoverController_->SetFillMode(FillMode::FORWARDS);
723     hoverController_->Forward();
724 }
725 
AnimateMouseHoverEnter()726 void RenderTextField::AnimateMouseHoverEnter()
727 {
728     StartHoverAnimation(true);
729 }
730 
AnimateMouseHoverExit()731 void RenderTextField::AnimateMouseHoverExit()
732 {
733     StartHoverAnimation(false);
734 }
735 
OnClick(const ClickInfo & clickInfo)736 void RenderTextField::OnClick(const ClickInfo& clickInfo)
737 {
738     // Handle click on password icon when password icon is valid, switch between show and hide icon.
739     Point clickPoint = Point(clickInfo.GetLocalLocation().GetX(), clickInfo.GetLocalLocation().GetY());
740     if (showPasswordIcon_ && passwordIconRect_.IsInRegion(clickPoint)) {
741         obscure_ = !obscure_;
742         passwordRecord_ = obscure_;
743         PopTextOverlay();
744         MarkNeedLayout();
745         return;
746     }
747 
748     isValueFromRemote_ = false;
749     auto globalPosition = clickInfo.GetGlobalLocation();
750     auto globalOffset = GetGlobalOffset();
751 
752     if (SearchAction(globalPosition, globalOffset)) {
753         return;
754     }
755     if (!onTapCallbackResult_) {
756         return;
757     }
758     if (onTapEvent_) {
759         onTapEvent_();
760     }
761     if (onClick_) {
762         onClick_(clickInfo);
763     }
764     CursorMoveOnClick(globalPosition);
765     ShowError("", false);
766     UpdateStartSelection(DEFAULT_SELECT_INDEX, globalPosition, true, false);
767     if (clickInfo.GetSourceDevice() == SourceType::MOUSE) {
768         StartTwinkling();
769     } else {
770         ShowTextOverlay(globalPosition, true);
771     }
772 }
773 
OnTapCallback()774 void RenderTextField::OnTapCallback()
775 {
776     auto context = GetContext().Upgrade();
777     if (context) {
778         context->SetClickPosition(GetGlobalOffset() + Size(0, GetLayoutSize().Height()));
779     }
780     if (isFocusOnTouch_ && tapCallback_) {
781         if (isLongPressStatus_) {
782             onTapCallbackResult_ = tapCallback_(false);
783             isLongPressStatus_ = false;
784         } else {
785             onTapCallbackResult_ = tapCallback_(true);
786         }
787     }
788 }
789 
OnEditChange(bool isInEditStatus)790 void RenderTextField::OnEditChange(bool isInEditStatus)
791 {
792     CHECK_NULL_VOID(onEditChanged_);
793     if (isInEditStatus && !isInEditStatus_) {
794         isInEditStatus_ = true;
795         onEditChanged_(true);
796     } else if (!isInEditStatus && isInEditStatus_) {
797         isInEditStatus_ = false;
798         onEditChanged_(false);
799     }
800 }
801 
AddOutOfRectCallbackToContext()802 void RenderTextField::AddOutOfRectCallbackToContext()
803 {
804     auto context = GetContext().Upgrade();
805     CHECK_NULL_VOID(context);
806     OutOfRectTouchCallback outRectCallback = [weak = WeakClaim(this)]() {
807         auto render = weak.Upgrade();
808         if (render) {
809             if (render->isOverlayShowed_) {
810                 render->PopTextOverlay();
811             }
812             render->StopTwinkling();
813             LOGI("Out of rect, close keyboard");
814             render->CloseKeyboard();
815             render->OnEditChange(false);
816         }
817     };
818     OutOfRectGetRectCallback getRectCallback = [weak = WeakClaim(this)](std::vector<Rect>& resRectList) {
819         auto render = weak.Upgrade();
820         if (render) {
821             render->GetFieldAndOverlayTouchRect(resRectList);
822         }
823     };
824     context->AddRectCallback(getRectCallback, outRectCallback, outRectCallback);
825 }
826 
GetFieldAndOverlayTouchRect(std::vector<Rect> & resRectList)827 void RenderTextField::GetFieldAndOverlayTouchRect(std::vector<Rect>& resRectList)
828 {
829     auto context = GetContext().Upgrade();
830     CHECK_NULL_VOID(context);
831     resRectList.clear();
832     auto fieldTouchRectList = GetTouchRectList();
833     for (auto& rect : fieldTouchRectList) {
834         rect.SetOffset(GetGlobalOffset());
835     }
836     resRectList.insert(resRectList.end(), fieldTouchRectList.begin(), fieldTouchRectList.end());
837     auto textOverlayManager = context->GetTextOverlayManager();
838     if (textOverlayManager) {
839         auto overlayTouchRectList = textOverlayManager->GetTextOverlayRect();
840         resRectList.insert(resRectList.end(), overlayTouchRectList.begin(), overlayTouchRectList.end());
841     }
842 }
843 
SearchAction(const Offset & globalPosition,const Offset & globalOffset)844 bool RenderTextField::SearchAction(const Offset& globalPosition, const Offset& globalOffset)
845 {
846     double widthReserved = NormalizeToPx(widthReserved_);
847     if (widthReserved > 0) {
848         if (textDirection_ == TextDirection::RTL) {
849             if ((globalPosition.GetX() - globalOffset.GetX()) < widthReserved) {
850                 controller_->SetText("");
851                 return true;
852             } else if ((globalPosition.GetX() - globalOffset.GetX()) > (GetLayoutSize().Width() - iconHotZoneSize_) &&
853                        iconImage_ && action_ == TextInputAction::SEARCH) {
854                 PerformAction(action_, true);
855                 return true;
856             }
857         } else {
858             if ((globalPosition.GetX() - globalOffset.GetX()) >= (GetLayoutSize().Width() - widthReserved)) {
859                 controller_->SetText("");
860                 return true;
861             } else if ((globalPosition.GetX() - globalOffset.GetX()) < iconHotZoneSize_ && iconImage_ &&
862                        action_ == TextInputAction::SEARCH) {
863                 PerformAction(action_, true);
864                 return true;
865             }
866         }
867     }
868     return false;
869 }
870 
OnDoubleClick(const ClickInfo & clickInfo)871 void RenderTextField::OnDoubleClick(const ClickInfo& clickInfo)
872 {
873     auto clickPosition = GetCursorPositionForClick(clickInfo.GetGlobalLocation());
874     auto selection = TextUtils::GetRangeOfSameType(GetEditingValue().text, clickPosition - 1);
875     UpdateSelection(selection.GetStart(), selection.GetEnd());
876     LOGI("text field accept double click, position: %{public}d, selection: %{public}s", clickPosition,
877         selection.ToString().c_str());
878     MarkNeedRender();
879 }
880 
OnLongPress(const LongPressInfo & longPressInfo)881 void RenderTextField::OnLongPress(const LongPressInfo& longPressInfo)
882 {
883     if (isFocusOnTouch_ && tapCallback_ && !isOverlayShowed_) {
884         if (!tapCallback_(false)) {
885             return;
886         }
887     }
888 
889     if (onLongPressEvent_) {
890         onLongPressEvent_();
891     }
892 
893     ShowError("", false);
894 
895     if (longPressInfo.GetSourceDevice() == SourceType::MOUSE) {
896         return;
897     }
898 
899     isLongPressStatus_ = true;
900     Offset longPressPosition = longPressInfo.GetGlobalLocation();
901     bool isTextEnd =
902         (static_cast<size_t>(GetCursorPositionForClick(longPressPosition)) == GetEditingValue().GetWideText().length());
903     bool singleHandle = isTextEnd || GetEditingValue().text.empty();
904     bool isPassword = (keyboard_ == TextInputType::VISIBLE_PASSWORD);
905     UpdateStartSelection(DEFAULT_SELECT_INDEX, longPressPosition, singleHandle || isPassword, true);
906     ShowTextOverlay(longPressPosition, false);
907 }
908 
ShowTextOverlay(const Offset & showOffset,bool isSingleHandle,bool isUsingMouse)909 void RenderTextField::ShowTextOverlay(const Offset& showOffset, bool isSingleHandle, bool isUsingMouse)
910 {
911     if (!isVisible_) {
912         return;
913     }
914 
915     if (!IsSelectiveDevice()) {
916         StartTwinkling();
917         return;
918     }
919 
920     isSingleHandle_ = isSingleHandle;
921 
922     auto selStart = GetEditingValue().selection.GetStart();
923     auto selEnd = GetEditingValue().selection.GetEnd();
924 
925     Offset startHandleOffset = GetHandleOffset(selStart);
926     Offset endHandleOffset = isSingleHandle ? startHandleOffset : GetHandleOffset(selEnd);
927 
928     if (isOverlayShowed_ && updateHandlePosition_) {
929         Rect caretStart;
930         bool visible = GetCaretRect(selStart, caretStart) ? IsVisible(caretStart + textOffsetForShowCaret_) : false;
931         OverlayShowOption option { .showMenu = isOverlayShowed_,
932             .showStartHandle = visible,
933             .showEndHandle = visible,
934             .isSingleHandle = isSingleHandle,
935             .updateOverlayType = isSingleHandle ? UpdateOverlayType::CLICK : UpdateOverlayType::LONG_PRESS,
936             .startHandleOffset = startHandleOffset,
937             .endHandleOffset = endHandleOffset };
938         if (!isSingleHandle_ || startHandleOffset != endHandleOffset) {
939             isOverlayFocus_ = true;
940         }
941         updateHandlePosition_(option);
942 
943         // When the textOverlay is showed, restart the animation
944         if (!animator_) {
945             LOGE("Show textOverlay error, animator is nullptr");
946             return;
947         }
948         if (!animator_->IsStopped()) {
949             animator_->Stop();
950         }
951         animator_->Play();
952         return;
953     }
954 
955     // Pop text overlay before push.
956     PopTextOverlay();
957 
958     textOverlay_ =
959         AceType::MakeRefPtr<TextOverlayComponent>(GetThemeManager(), context_.Upgrade()->GetAccessibilityManager());
960     textOverlay_->SetWeakTextField(WeakClaim(this));
961     textOverlay_->SetIsSingleHandle(isSingleHandle || (keyboard_ == TextInputType::VISIBLE_PASSWORD));
962     textOverlay_->SetLineHeight(selectHeight_);
963     textOverlay_->SetClipRect(
964         innerRect_ + Size(HANDLE_HOT_ZONE, HANDLE_HOT_ZONE) + GetOffsetToPage() - Offset(HANDLE_HOT_ZONE / 2.0, 0.0));
965     textOverlay_->SetTextDirection(textDirection_);
966     textOverlay_->SetRealTextDirection(existStrongDirectionLetter_ ? realTextDirection_ : TextDirection::LTR);
967     textOverlay_->SetIsPassword(keyboard_ == TextInputType::VISIBLE_PASSWORD);
968     textOverlay_->SetStartHandleOffset(startHandleOffset);
969     textOverlay_->SetEndHandleOffset(endHandleOffset);
970     textOverlay_->SetImageFill(imageFill_);
971     textOverlay_->SetOptions(inputOptions_);
972     textOverlay_->SetOptionsClickMarker(onOptionsClick_);
973     textOverlay_->SetTranslateButtonMarker(onTranslate_);
974     textOverlay_->SetShareButtonMarker(onShare_);
975     textOverlay_->SetSearchButtonMarker(onSearch_);
976     textOverlay_->SetContext(context_);
977     textOverlay_->SetIsUsingMouse(isUsingMouse);
978     if (isUsingMouse) {
979         textOverlay_->SetMouseOffset(showOffset);
980     }
981 
982     // Add the Animation
983     InitAnimation();
984 
985     if (!isSingleHandle_ || startHandleOffset != endHandleOffset) {
986         isOverlayFocus_ = true;
987     }
988     RegisterCallbacksToOverlay();
989 }
990 
InitAnimation()991 void RenderTextField::InitAnimation()
992 {
993     if (!textOverlay_) {
994         LOGE("InitAnimation error, textOverlay is nullptr");
995         return;
996     }
997 
998     // Get the handleDiameter in theme, textoverlay is not nullptr
999     double initHandleDiameter = textOverlay_->GetHandleDiameter().Value();
1000     double initHandleDiameterInner = textOverlay_->GetHandleDiameterInner().Value();
1001 
1002     // Add the animation for handleDiameter
1003     auto diameterAnimation = AceType::MakeRefPtr<CurveAnimation<double>>(
1004         initHandleDiameter * FIFTY_PERCENT, initHandleDiameter, Curves::ELASTICS);
1005     diameterAnimation->AddListener([text = AceType::WeakClaim(this)](double value) {
1006         auto textField = text.Upgrade();
1007         if (textField && textField->updateHandleDiameter_) {
1008             textField->updateHandleDiameter_(value);
1009         }
1010     });
1011 
1012     // Add the animation for handleDiameterinner
1013     auto diameterInnerAnimation = AceType::MakeRefPtr<CurveAnimation<double>>(
1014         initHandleDiameterInner * FIFTY_PERCENT, initHandleDiameterInner, Curves::ELASTICS);
1015     diameterInnerAnimation->AddListener([text = AceType::WeakClaim(this)](double value) {
1016         auto textField = text.Upgrade();
1017         if (textField && textField->updateHandleDiameterInner_) {
1018             textField->updateHandleDiameterInner_(value);
1019         }
1020     });
1021 
1022     // Add the animation
1023     LOGD("Add animation to animator");
1024     animator_ = AceType::MakeRefPtr<Animator>(context_);
1025     animator_->AddInterpolator(diameterAnimation);
1026     animator_->AddInterpolator(diameterInnerAnimation);
1027     animator_->SetDuration(SHOW_HANDLE_DURATION);
1028     animator_->Play();
1029 }
1030 
RegisterCallbacksToOverlay()1031 void RenderTextField::RegisterCallbacksToOverlay()
1032 {
1033     if (!textOverlay_) {
1034         return;
1035     }
1036     textOverlay_->SetOnCut([weak = AceType::WeakClaim(this)] {
1037         auto textfield = weak.Upgrade();
1038         if (textfield) {
1039             textfield->HandleOnCut();
1040         }
1041     });
1042 
1043     textOverlay_->SetOnCopy([weak = AceType::WeakClaim(this)] {
1044         auto textfield = weak.Upgrade();
1045         if (textfield) {
1046             textfield->HandleOnCopy();
1047         }
1048     });
1049 
1050     textOverlay_->SetOnCopyAll(
1051         [weak = AceType::WeakClaim(this)](const std::function<void(const Offset&, const Offset&)>& callback) {
1052             auto textfield = weak.Upgrade();
1053             if (textfield) {
1054                 textfield->HandleOnCopyAll(callback);
1055             }
1056         });
1057 
1058     textOverlay_->SetOnStartHandleMove(
1059         [weak = AceType::WeakClaim(this)](int32_t end, const Offset& startHandleOffset,
1060             const std::function<void(const Offset&)>& startCallback, bool isSingleHandle) {
1061             auto textfield = weak.Upgrade();
1062             if (textfield) {
1063                 textfield->HandleOnStartHandleMove(end, startHandleOffset, startCallback, isSingleHandle);
1064             }
1065         });
1066 
1067     textOverlay_->SetOnEndHandleMove([weak = AceType::WeakClaim(this)](int32_t start, const Offset& endHandleOffset,
1068                                          const std::function<void(const Offset&)>& endCallback) {
1069         auto textfield = weak.Upgrade();
1070         if (textfield) {
1071             textfield->HandleOnEndHandleMove(start, endHandleOffset, endCallback);
1072         }
1073     });
1074 
1075     textOverlay_->SetOnPaste([weakTextField = WeakClaim(this)] {
1076         auto textfield = weakTextField.Upgrade();
1077         if (textfield) {
1078             textfield->HandleOnPaste();
1079         }
1080     });
1081     PushTextOverlayToStack();
1082     UpdateOverlay();
1083 
1084     auto onFocusChange = [weak = WeakClaim(this)](bool isFocus, bool needCloseKeyboard) {
1085         auto textField = weak.Upgrade();
1086         if (textField) {
1087             textField->OnOverlayFocusChange(isFocus, needCloseKeyboard);
1088         }
1089     };
1090     textOverlay_->SetOnFocusChange(onFocusChange);
1091 }
1092 
PushTextOverlayToStack()1093 void RenderTextField::PushTextOverlayToStack()
1094 {
1095     if (!textOverlay_) {
1096         LOGE("TextOverlay is null");
1097         return;
1098     }
1099 
1100     auto context = context_.Upgrade();
1101     CHECK_NULL_VOID(context);
1102     auto textOverlayManager = context->GetTextOverlayManager();
1103     CHECK_NULL_VOID(textOverlayManager);
1104     textOverlayManager->PushTextOverlayToStack(textOverlay_, context);
1105 
1106     hasTextOverlayPushed_ = true;
1107     isOverlayShowed_ = true;
1108     auto lastStack = GetLastStack();
1109     if (!lastStack) {
1110         LOGE("LastStack is null");
1111         return;
1112     }
1113     stackElement_ = WeakClaim(RawPtr(lastStack));
1114     MarkNeedRender();
1115 }
1116 
PopTextOverlay()1117 void RenderTextField::PopTextOverlay()
1118 {
1119     auto context = context_.Upgrade();
1120     CHECK_NULL_VOID(context);
1121     auto textOverlayManager = context->GetTextOverlayManager();
1122     CHECK_NULL_VOID(textOverlayManager);
1123     textOverlayManager->PopTextOverlay();
1124     isOverlayShowed_ = false;
1125 }
1126 
GetSlidingPanelAncest()1127 RefPtr<RenderSlidingPanel> RenderTextField::GetSlidingPanelAncest()
1128 {
1129     auto parent = GetParent().Upgrade();
1130     while (parent) {
1131         auto renderSlidingPanel = AceType::DynamicCast<RenderSlidingPanel>(parent);
1132         if (renderSlidingPanel) {
1133             return renderSlidingPanel;
1134         }
1135         parent = parent->GetParent().Upgrade();
1136     }
1137     return nullptr;
1138 }
1139 
ResetSlidingPanelParentHeight()1140 void RenderTextField::ResetSlidingPanelParentHeight()
1141 {
1142     auto context = context_.Upgrade();
1143     if (!context) {
1144         LOGE("ResetSlidingPanelParentHeight: Context is null");
1145         return;
1146     }
1147     auto manager = context->GetTextFieldManager();
1148     if (manager && AceType::InstanceOf<TextFieldManager>(manager)) {
1149         auto textFieldManager = AceType::DynamicCast<TextFieldManager>(manager);
1150         textFieldManager->ResetSlidingPanelParentHeight();
1151     }
1152 }
1153 
ResetOnFocusForTextFieldManager()1154 void RenderTextField::ResetOnFocusForTextFieldManager()
1155 {
1156     auto context = context_.Upgrade();
1157     if (!context) {
1158         LOGE("ResetOnFocusForTextFieldManager: Context is null");
1159         return;
1160     }
1161     auto manager = context->GetTextFieldManager();
1162     if (manager && AceType::InstanceOf<TextFieldManager>(manager)) {
1163         auto textFieldManager = AceType::DynamicCast<TextFieldManager>(manager);
1164         textFieldManager->ClearOnFocusTextField();
1165     }
1166 }
1167 
RequestKeyboard(bool isFocusViewChanged,bool needStartTwinkling,bool needShowSoftKeyboard)1168 bool RenderTextField::RequestKeyboard(bool isFocusViewChanged, bool needStartTwinkling, bool needShowSoftKeyboard)
1169 {
1170     if (!enabled_) {
1171         LOGW("TextField is not enabled.");
1172         return false;
1173     }
1174 
1175     instanceId_ = ContainerScope::CurrentId();
1176 
1177     if (softKeyboardEnabled_) {
1178         LOGI("Request open soft keyboard");
1179 #if defined(ENABLE_STANDARD_INPUT)
1180         UpdateConfiguration();
1181         if (textChangeListener_ == nullptr) {
1182             textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this), context_);
1183         }
1184         auto inputMethod = MiscServices::InputMethodController::GetInstance();
1185         if (!inputMethod) {
1186             LOGE("Request open soft keyboard failed because input method is null.");
1187             return false;
1188         }
1189         auto context = context_.Upgrade();
1190         if (context) {
1191             LOGI("RequestKeyboard set calling window id is : %{public}d", context->GetWindowId());
1192             inputMethod->SetCallingWindow(context->GetWindowId());
1193         }
1194         MiscServices::InputAttribute inputAttribute;
1195         inputAttribute.inputPattern = (int32_t)keyboard_;
1196         inputAttribute.enterKeyType = (int32_t)action_;
1197         inputMethod->Attach(textChangeListener_, needShowSoftKeyboard, inputAttribute);
1198 #else
1199         if (!HasConnection()) {
1200             AttachIme();
1201             if (!HasConnection()) {
1202                 LOGE("Get TextInput connection error");
1203                 return false;
1204             }
1205             connection_->SetEditingState(GetEditingValue(), GetInstanceId());
1206         }
1207         connection_->Show(isFocusViewChanged, GetInstanceId());
1208 #endif
1209     }
1210     auto context = context_.Upgrade();
1211     if (context) {
1212         auto manager = context->GetTextFieldManager();
1213         if (manager && AceType::InstanceOf<TextFieldManager>(manager)) {
1214             auto textFieldManager = AceType::DynamicCast<TextFieldManager>(manager);
1215             textFieldManager->SetOnFocusTextField(WeakClaim(this));
1216         }
1217     }
1218     if (keyboard_ != TextInputType::MULTILINE) {
1219         resetToStart_ = false;
1220         MarkNeedLayout();
1221     }
1222     if (needStartTwinkling) {
1223         StartTwinkling();
1224     }
1225     return true;
1226 }
1227 
CloseKeyboard(bool forceClose)1228 bool RenderTextField::CloseKeyboard(bool forceClose)
1229 {
1230 #if defined(OHOS_STANDARD_SYSTEM)
1231     if (!imeAttached_) {
1232         return false;
1233     }
1234 #endif
1235     if (!isOverlayShowed_ || !isOverlayFocus_ || forceClose) {
1236         if (!textFieldController_) {
1237             StopTwinkling();
1238         }
1239         LOGI("Request close soft keyboard");
1240 #if defined(ENABLE_STANDARD_INPUT)
1241         auto inputMethod = MiscServices::InputMethodController::GetInstance();
1242         if (!inputMethod) {
1243             LOGE("Request close soft keyboard failed because input method is null.");
1244             return false;
1245         }
1246         inputMethod->HideTextInput();
1247         inputMethod->Close();
1248 #else
1249         if (HasConnection()) {
1250             connection_->Close(GetInstanceId());
1251             connection_ = nullptr;
1252         }
1253 #endif
1254 
1255         if (onKeyboardClose_) {
1256             onKeyboardClose_(forceClose);
1257             onKeyboardClose_ = nullptr;
1258             UpdateSelection(GetEditingValue().selection.GetEnd());
1259             MarkNeedLayout();
1260         }
1261         ResetSlidingPanelParentHeight();
1262         if (keyboard_ != TextInputType::MULTILINE && keyboard_ != TextInputType::VISIBLE_PASSWORD) {
1263             resetToStart_ = true;
1264             MarkNeedLayout();
1265         }
1266         return true;
1267     }
1268     return false;
1269 }
1270 
AttachIme()1271 void RenderTextField::AttachIme()
1272 {
1273     auto context = context_.Upgrade();
1274     if (!context) {
1275         LOGW("No context exists, failed to request keyboard.");
1276         return;
1277     }
1278 
1279     TextInputConfiguration config;
1280     config.type = keyboard_;
1281     config.action = action_;
1282     config.actionLabel = actionLabel_;
1283     config.obscureText = obscure_;
1284     LOGI("Request keyboard configuration: type=%{private}d action=%{private}d actionLabel=%{private}s "
1285          "obscureText=%{private}d",
1286         keyboard_, action_, actionLabel_.c_str(), obscure_);
1287     connection_ =
1288         TextInputProxy::GetInstance().Attach(WeakClaim(this), config, context->GetTaskExecutor(), GetInstanceId());
1289 }
1290 
StartTwinkling()1291 void RenderTextField::StartTwinkling()
1292 {
1293     // Ignore the result because all ops are called on this same thread (ACE UI).
1294     // The only reason failed is that the task has finished.
1295     cursorTwinklingTask_.Cancel();
1296 
1297     // Show cursor right now.
1298     cursorVisibility_ = true;
1299     // Does not matter call more than one times.
1300     MarkNeedRender();
1301 
1302     ScheduleCursorTwinkling();
1303 }
1304 
StopTwinkling()1305 void RenderTextField::StopTwinkling()
1306 {
1307     obscureTickPendings_ = 0;
1308     cursorTwinklingTask_.Cancel();
1309 
1310     if (cursorVisibility_) {
1311         // Repaint only if cursor is visible for now.
1312         cursorVisibility_ = false;
1313         MarkNeedRender();
1314     }
1315 }
1316 
HandleSetSelection(int32_t start,int32_t end)1317 void RenderTextField::HandleSetSelection(int32_t start, int32_t end)
1318 {
1319     LOGI("HandleSetSelection %{public}d, %{public}d", start, end);
1320     UpdateSelection(start, end);
1321 }
1322 
HandleExtendAction(int32_t action)1323 void RenderTextField::HandleExtendAction(int32_t action)
1324 {
1325     LOGI("HandleExtendAction %{public}d", action);
1326     switch (action) {
1327         case ACTION_SELECT_ALL: {
1328             auto end = GetEditingValue().GetWideText().length();
1329             UpdateSelection(0, end);
1330             break;
1331         }
1332         case ACTION_UNDO: {
1333             HandleOnRevoke();
1334             break;
1335         }
1336         case ACTION_REDO: {
1337             HandleOnInverseRevoke();
1338             break;
1339         }
1340         case ACTION_CUT: {
1341             HandleOnCut();
1342             break;
1343         }
1344         case ACTION_COPY: {
1345             HandleOnCopy();
1346             break;
1347         }
1348         case ACTION_PASTE: {
1349             HandleOnPaste();
1350             break;
1351         }
1352         default: {
1353             break;
1354         }
1355     }
1356 }
1357 
HandleSelect(int32_t keyCode,int32_t cursorMoveSkip)1358 void RenderTextField::HandleSelect(int32_t keyCode, int32_t cursorMoveSkip)
1359 {
1360     KeyCode code = static_cast<KeyCode>(keyCode);
1361     CursorMoveSkip skip = static_cast<CursorMoveSkip>(cursorMoveSkip);
1362     HandleOnSelect(code, skip);
1363 }
1364 
GetEditingValue() const1365 const TextEditingValue& RenderTextField::GetEditingValue() const
1366 {
1367     return controller_->GetValue();
1368 }
1369 
GetPreEditingValue() const1370 const TextEditingValue& RenderTextField::GetPreEditingValue() const
1371 {
1372     return controller_->GetPreValue();
1373 }
1374 
GetEditingBoxY() const1375 double RenderTextField::GetEditingBoxY() const
1376 {
1377     return GetGlobalOffset().GetY() + height_.Value();
1378 }
1379 
GetEditingBoxTopY() const1380 double RenderTextField::GetEditingBoxTopY() const
1381 {
1382     return GetGlobalOffset().GetY();
1383 }
1384 
GetEditingBoxModel() const1385 bool RenderTextField::GetEditingBoxModel() const
1386 {
1387     bool isDeclarative = false;
1388     auto context = context_.Upgrade();
1389     if (context && context->GetIsDeclarative()) {
1390         isDeclarative = true;
1391     }
1392     return isDeclarative;
1393 }
1394 
SetEditingValue(TextEditingValue && newValue,bool needFireChangeEvent,bool isClearRecords)1395 void RenderTextField::SetEditingValue(TextEditingValue&& newValue, bool needFireChangeEvent, bool isClearRecords)
1396 {
1397     if (newValue.text != GetEditingValue().text && needFireChangeEvent) {
1398         needNotifyChangeEvent_ = true;
1399         operationRecords_.push_back(newValue);
1400         if (isClearRecords) {
1401             inverseOperationRecords_.clear();
1402         }
1403     }
1404     ChangeCounterStyle(newValue);
1405     auto context = context_.Upgrade();
1406     if (context && context->GetIsDeclarative()) {
1407         if (GetEditingValue().text.empty()) {
1408             Dimension fontSize_ = placeHoldStyle_.GetFontSize();
1409             if (fontSize_.Value() <= 0) {
1410                 Dimension fontSize_ { 14, DimensionUnit::FP };
1411                 placeHoldStyle_.SetFontSize(fontSize_);
1412             }
1413             SetTextStyle(placeHoldStyle_);
1414         }
1415     }
1416     controller_->SetValue(newValue, needFireChangeEvent);
1417     UpdateAccessibilityAttr();
1418 }
1419 
SetEditingValue(const std::string & text)1420 void RenderTextField::SetEditingValue(const std::string& text)
1421 {
1422     auto newValue = GetEditingValue();
1423     newValue.text = text;
1424     SetEditingValue(std::move(newValue));
1425 }
1426 
ClearEditingValue()1427 void RenderTextField::ClearEditingValue()
1428 {
1429     TextEditingValue emptyValue;
1430     SetEditingValue(std::move(emptyValue));
1431 }
1432 
GetTextForDisplay(const std::string & text) const1433 std::u16string RenderTextField::GetTextForDisplay(const std::string& text) const
1434 {
1435     std::u16string txtContent = StringUtils::Str8ToStr16(text);
1436     auto len = txtContent.length();
1437     if (!obscure_ || len == 0 || (obscureTickPendings_ > 0 && len == 1)) {
1438         return txtContent;
1439     }
1440 
1441     std::u16string obscured;
1442     if (Localization::GetInstance()->GetLanguage() == "ar") { // ar is the abbreviation of Arabic.
1443         obscured = std::u16string(len, OBSCURING_CHARACTER_FOR_AR);
1444     } else {
1445         obscured = std::u16string(len, OBSCURING_CHARACTER);
1446     }
1447     int32_t posBeforeCursor = GetEditingValue().selection.extentOffset - 1;
1448     if (obscureTickPendings_ > 0 && posBeforeCursor >= 0 && static_cast<size_t>(posBeforeCursor) < obscured.length()) {
1449         // Let the last commit character naked.
1450         obscured[posBeforeCursor] = txtContent[posBeforeCursor];
1451     }
1452 
1453     return obscured;
1454 }
1455 
UpdateObscure(const RefPtr<TextFieldComponent> & textField)1456 void RenderTextField::UpdateObscure(const RefPtr<TextFieldComponent>& textField)
1457 {
1458     auto context = context_.Upgrade();
1459     if (context && context->GetIsDeclarative()) {
1460         if (!passwordRecord_) {
1461             if (keyboard_ != textField->GetTextInputType()) {
1462                 passwordRecord_ = true;
1463                 obscure_ = textField->NeedObscure();
1464             } else {
1465                 obscure_ = !textField->NeedObscure();
1466             }
1467         } else {
1468             obscure_ = textField->NeedObscure();
1469         }
1470     } else {
1471         obscure_ = textField->NeedObscure();
1472     }
1473 }
1474 
UpdateFormatters()1475 void RenderTextField::UpdateFormatters()
1476 {
1477     textInputFormatters_.clear();
1478 
1479     if (maxLength_ < std::numeric_limits<uint32_t>::max()) {
1480         textInputFormatters_.emplace_back(std::make_unique<LengthLimitingFormatter>(maxLength_));
1481     }
1482 
1483     if (maxLines_ == 1) {
1484         textInputFormatters_.emplace_back(std::make_unique<SingleLineFormatter>());
1485     }
1486 
1487     switch (keyboard_) {
1488         case TextInputType::NUMBER: {
1489             textInputFormatters_.emplace_back(std::make_unique<NumberFormatter>());
1490             break;
1491         }
1492         case TextInputType::PHONE: {
1493             textInputFormatters_.emplace_back(std::make_unique<PhoneNumberFormatter>());
1494             break;
1495         }
1496         case TextInputType::EMAIL_ADDRESS: {
1497             textInputFormatters_.emplace_back(std::make_unique<EmailFormatter>());
1498             break;
1499         }
1500         case TextInputType::URL: {
1501             textInputFormatters_.emplace_back(std::make_unique<UriFormatter>());
1502             break;
1503         }
1504         default: {
1505             // No need limit.
1506         }
1507     }
1508 
1509     TextEditingValue temp = GetEditingValue();
1510     for (const auto& formatter : textInputFormatters_) {
1511         if (formatter) {
1512             formatter->Format(GetEditingValue(), temp);
1513         }
1514     }
1515     SetEditingValue(std::move(temp));
1516 }
1517 
WstringSearch(std::wstring wideText,const std::wregex & regex)1518 std::wstring WstringSearch(std::wstring wideText, const std::wregex& regex)
1519 {
1520     std::wstring result;
1521     std::wsmatch matchResults;
1522     while (std::regex_search(wideText, matchResults, regex)) {
1523         for (auto&& mr : matchResults) {
1524             result.append(mr);
1525         }
1526         wideText = matchResults.suffix();
1527     }
1528     return result;
1529 }
1530 
FilterWithRegex(std::string & valueToUpdate,const std::string & filter,bool needToEscape)1531 bool RenderTextField::FilterWithRegex(std::string& valueToUpdate, const std::string& filter, bool needToEscape)
1532 {
1533     if (filter.empty() || valueToUpdate.empty()) {
1534         LOGD("Text is empty or filter is empty");
1535         return false;
1536     }
1537     std::string escapeFilter;
1538     if (needToEscape && !TextFieldControllerBase::EscapeString(filter, escapeFilter)) {
1539         LOGE("Filter %{public}s is not legal", filter.c_str());
1540         return false;
1541     }
1542     if (!needToEscape) {
1543         escapeFilter = filter;
1544     }
1545 #if defined(PREVIEW)
1546     if (keyboard_ == TextInputType::EMAIL_ADDRESS) {
1547         std::string tmpValue;
1548         std::string errorText;
1549         std::string checkedList = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_@.";
1550         for (auto value : valueToUpdate) {
1551             if (checkedList.find(value) != std::string::npos) {
1552                 tmpValue += value;
1553             } else {
1554                 errorText += value;
1555             }
1556         }
1557         valueToUpdate = tmpValue;
1558         if (!errorText.empty()) {
1559             if (onError_) {
1560                 onError_(errorText);
1561             }
1562             return true;
1563         }
1564         return false;
1565     }
1566 #else
1567     // Specialized processed for Email because of regex.
1568     if (keyboard_ == TextInputType::EMAIL_ADDRESS || keyboard_ == TextInputType::URL) {
1569         std::regex filterRegex(escapeFilter);
1570         auto errorText = regex_replace(valueToUpdate, filterRegex, "");
1571         if (!errorText.empty()) {
1572             std::string result;
1573             RemoveErrorTextFromValue(valueToUpdate, errorText, result);
1574             valueToUpdate = result;
1575             if (onError_) {
1576                 onError_(errorText);
1577             }
1578             return true;
1579         }
1580     }
1581 #endif
1582     if (keyboard_ == TextInputType::NUMBER || keyboard_ == TextInputType::PHONE) {
1583         GetKeyboardFilter(keyboard_, escapeFilter, true);
1584         std::wregex filterRegex(StringUtils::ToWstring(escapeFilter));
1585         std::wstring wValueToUpdate = StringUtils::ToWstring(valueToUpdate);
1586         auto manipulateText = std::regex_replace(wValueToUpdate, filterRegex, L"");
1587         if (manipulateText.length() != wValueToUpdate.length()) {
1588             valueToUpdate = StringUtils::ToString(manipulateText);
1589             if (onError_) {
1590                 GetKeyboardFilter(keyboard_, escapeFilter, false);
1591                 std::regex filterRegex(escapeFilter);
1592                 auto errorText = regex_replace(valueToUpdate, filterRegex, "");
1593                 onError_(errorText);
1594             }
1595             return true;
1596         }
1597     }
1598     return false;
1599 }
1600 
EditingValueFilter(TextEditingValue & valueToUpdate)1601 void RenderTextField::EditingValueFilter(TextEditingValue& valueToUpdate)
1602 {
1603     FilterWithRegex(valueToUpdate.text, inputFilter_, true);
1604     KeyboardEditingValueFilter(valueToUpdate);
1605 }
1606 
KeyboardEditingValueFilter(TextEditingValue & valueToUpdate)1607 void RenderTextField::KeyboardEditingValueFilter(TextEditingValue& valueToUpdate)
1608 {
1609     std::string keyboardFilterValue;
1610     GetKeyboardFilter(keyboard_, keyboardFilterValue, false);
1611     if (keyboardFilterValue.empty()) {
1612         return;
1613     }
1614     if (keyboard_ == TextInputType::EMAIL_ADDRESS && valueToUpdate.text == "@") {
1615         if (GetEditingValue().text.find('@') != std::string::npos) {
1616             valueToUpdate.text = "";
1617             valueToUpdate.selection.baseOffset = 0;
1618             valueToUpdate.selection.extentOffset = 0;
1619         }
1620         return;
1621     }
1622     bool textChanged = false;
1623     auto start = valueToUpdate.selection.GetStart();
1624     auto end = valueToUpdate.selection.GetEnd();
1625     // in keyboard filter, the white lists are already escaped
1626     if ((start <= 0) && (end <= 0)) {
1627         FilterWithRegex(valueToUpdate.text, keyboardFilterValue);
1628     } else {
1629         std::string strBeforeSelection;
1630         if ((start > 0) && (static_cast<size_t>(start) <= valueToUpdate.text.length())) {
1631             strBeforeSelection = valueToUpdate.text.substr(0, start);
1632             textChanged |= FilterWithRegex(strBeforeSelection, keyboardFilterValue);
1633         }
1634         std::string strInSelection;
1635         if (start < end) {
1636             strInSelection = valueToUpdate.text.substr(start, end - start);
1637             textChanged |= FilterWithRegex(strInSelection, keyboardFilterValue);
1638         }
1639         std::string strAfterSelection;
1640         if (end >= start && end <= static_cast<int32_t>(valueToUpdate.text.length())) {
1641             size_t lenLeft = valueToUpdate.text.length() - static_cast<size_t>(end);
1642             strAfterSelection = valueToUpdate.text.substr(end, lenLeft);
1643             textChanged |= FilterWithRegex(strAfterSelection, keyboardFilterValue);
1644         }
1645         if (!textChanged) {
1646             return;
1647         }
1648         valueToUpdate.text = strBeforeSelection + strInSelection + strAfterSelection;
1649         if (valueToUpdate.selection.baseOffset > valueToUpdate.selection.extentOffset) {
1650             valueToUpdate.selection.Update(static_cast<int32_t>(strBeforeSelection.length() + strInSelection.length()),
1651                 static_cast<int32_t>(strBeforeSelection.length()));
1652         } else {
1653             valueToUpdate.selection.Update(static_cast<int32_t>(strBeforeSelection.length()),
1654                 static_cast<int32_t>(strBeforeSelection.length() + strInSelection.length()));
1655         }
1656     }
1657 }
1658 
UpdateInsertText(std::string insertValue)1659 void RenderTextField::UpdateInsertText(std::string insertValue)
1660 {
1661     insertValue_ = std::move(insertValue);
1662     insertTextUpdated_ = true;
1663 }
1664 
NeedToFilter()1665 bool RenderTextField::NeedToFilter()
1666 {
1667     std::string keyboardFilterValue;
1668     GetKeyboardFilter(keyboard_, keyboardFilterValue, false);
1669     return !keyboardFilterValue.empty() || !inputFilter_.empty();
1670 }
1671 
HandleValueFilter(TextEditingValue & valueBeforeUpdate,TextEditingValue & valueNeedToUpdate)1672 void RenderTextField::HandleValueFilter(TextEditingValue& valueBeforeUpdate, TextEditingValue& valueNeedToUpdate)
1673 {
1674     if (!NeedToFilter()) {
1675         return;
1676     }
1677     if (insertTextUpdated_) {
1678         TextEditingValue textEditingValue;
1679         textEditingValue.text = insertValue_;
1680         EditingValueFilter(textEditingValue);
1681         if (!textEditingValue.text.empty()) {
1682             valueNeedToUpdate.text =
1683                 valueBeforeUpdate.GetBeforeSelection() + textEditingValue.text + valueBeforeUpdate.GetAfterSelection();
1684             valueNeedToUpdate.UpdateSelection(
1685                 std::max(valueBeforeUpdate.selection.GetStart(), 0) + textEditingValue.text.length());
1686         } else {
1687             // text inserted is filtered to empty string
1688             valueNeedToUpdate = valueBeforeUpdate;
1689         }
1690         insertTextUpdated_ = false;
1691         return;
1692     }
1693     EditingValueFilter(valueNeedToUpdate);
1694 }
1695 
UpdateEditingValue(const std::shared_ptr<TextEditingValue> & value,bool needFireChangeEvent)1696 void RenderTextField::UpdateEditingValue(const std::shared_ptr<TextEditingValue>& value, bool needFireChangeEvent)
1697 {
1698     ContainerScope scope(instanceId_);
1699     if (!value) {
1700         LOGE("the value is nullptr");
1701         return;
1702     }
1703     if (static_cast<uint32_t>(value->GetWideText().length()) > maxLength_) {
1704         LOGW("Max length reached");
1705         return;
1706     }
1707 
1708     lastKnownRemoteEditingValue_ = value;
1709     lastKnownRemoteEditingValue_->hint = placeholder_;
1710     TextEditingValue valueNeedToUpdate = *value;
1711     if (cursorPositionType_ != CursorPositionType::END ||
1712         (valueNeedToUpdate.selection.baseOffset == valueNeedToUpdate.selection.extentOffset &&
1713             valueNeedToUpdate.selection.baseOffset != static_cast<int32_t>(valueNeedToUpdate.GetWideText().length()))) {
1714         cursorPositionType_ = CursorPositionType::NORMAL;
1715         isValueFromRemote_ = true;
1716     }
1717     auto valueBeforeUpdate = GetEditingValue();
1718 
1719     ChangeCounterStyle(valueNeedToUpdate);
1720 
1721     if (lastInputAction_ != InputAction::DELETE_BACKWARD && lastInputAction_ != InputAction::DELETE_FORWARD) {
1722         HandleValueFilter(valueBeforeUpdate, valueNeedToUpdate);
1723     }
1724 
1725     if (obscure_ && (valueNeedToUpdate.text.length() == valueBeforeUpdate.text.length() + 1)) {
1726         // Reset pending.
1727         obscureTickPendings_ = OBSCURE_SHOW_TICKS;
1728     }
1729 
1730     if (valueNeedToUpdate.text != valueBeforeUpdate.text && needFireChangeEvent) {
1731         needNotifyChangeEvent_ = true;
1732     }
1733 
1734     SetEditingValue(std::move(valueNeedToUpdate), needFireChangeEvent);
1735     UpdateRemoteEditingIfNeeded(needFireChangeEvent);
1736 
1737     MarkNeedLayout();
1738 
1739     // If input or delete text when overlay is showing, pop overlay from stack.
1740     if (valueNeedToUpdate.text != valueBeforeUpdate.text) {
1741         if (onValueChange_) {
1742             onValueChange_();
1743         }
1744         if (onChange_) {
1745             onChange_(GetEditingValue().text);
1746         }
1747     }
1748 }
1749 
PerformDefaultAction()1750 void RenderTextField::PerformDefaultAction()
1751 {
1752     PerformAction(action_);
1753 }
1754 
PerformAction(TextInputAction action,bool forceCloseKeyboard)1755 void RenderTextField::PerformAction(TextInputAction action, bool forceCloseKeyboard)
1756 {
1757     LOGI("PerformAction  %{public}d", static_cast<int32_t>(action));
1758     ContainerScope scope(instanceId_);
1759     if (keyboard_ == TextInputType::MULTILINE) {
1760         auto value = GetEditingValue();
1761         auto textEditingValue = std::make_shared<TextEditingValue>();
1762         textEditingValue->text = value.GetBeforeSelection() + NEW_LINE + value.GetAfterSelection();
1763         textEditingValue->UpdateSelection(std::max(value.selection.GetStart(), 0) + 1);
1764         UpdateEditingValue(textEditingValue, true);
1765         return;
1766     }
1767     if (action == TextInputAction::NEXT && moveNextFocusEvent_) {
1768         moveNextFocusEvent_();
1769     } else {
1770         LOGI("Perform action received from input frame, close keyboard");
1771         CloseKeyboard(forceCloseKeyboard);
1772     }
1773     if (onFinishInputEvent_) {
1774         auto jsonResult = JsonUtil::Create(true);
1775         jsonResult->Put("value", static_cast<int32_t>(action));
1776         onFinishInputEvent_(std::string(R"("enterkeyclick",)").append(jsonResult->ToString()));
1777     }
1778     if (onSubmitEvent_ && controller_) {
1779         onSubmitEvent_(controller_->GetValue().text);
1780     }
1781     if (onSubmit_) {
1782         onSubmit_(static_cast<int32_t>(action));
1783     }
1784 }
1785 
Measure()1786 Size RenderTextField::Measure()
1787 {
1788     return Size();
1789 }
1790 
ScheduleCursorTwinkling()1791 void RenderTextField::ScheduleCursorTwinkling()
1792 {
1793     auto context = context_.Upgrade();
1794     if (!context) {
1795         LOGW("No context exists.");
1796         return;
1797     }
1798 
1799     if (!context->GetTaskExecutor()) {
1800         LOGW("context has no task executor.");
1801         return;
1802     }
1803 
1804     auto weak = WeakClaim(this);
1805     cursorTwinklingTask_.Reset([weak] {
1806         auto client = weak.Upgrade();
1807         if (client) {
1808             client->OnCursorTwinkling();
1809         }
1810     });
1811     auto taskExecutor = context->GetTaskExecutor();
1812     if (taskExecutor) {
1813         taskExecutor->PostDelayedTask(cursorTwinklingTask_, TaskExecutor::TaskType::UI, twinklingInterval);
1814     } else {
1815         LOGE("the task executor is nullptr");
1816     }
1817 }
1818 
OnCursorTwinkling()1819 void RenderTextField::OnCursorTwinkling()
1820 {
1821     // When glyph changes from visible to invisible, layout is needed.
1822     obscureTickPendings_ == 1 ? MarkNeedLayout() : MarkNeedRender();
1823     if (obscureTickPendings_ > 0) {
1824         --obscureTickPendings_;
1825     }
1826     cursorVisibility_ = !cursorVisibility_;
1827     ScheduleCursorTwinkling();
1828 }
1829 
OnKeyEvent(const KeyEvent & event)1830 bool RenderTextField::OnKeyEvent(const KeyEvent& event)
1831 {
1832     if (!enabled_) {
1833         return false;
1834     }
1835 
1836     // If back or escape is clicked and overlay is showing, pop overlay firstly.
1837     if (event.action == KeyAction::UP && (event.code == KeyCode::KEY_BACK || event.code == KeyCode::KEY_ESCAPE)) {
1838         if (isOverlayShowed_) {
1839             PopTextOverlay();
1840             return false;
1841         }
1842     }
1843     if (event.action == KeyAction::UP &&
1844         ((event.code == KeyCode::KEY_SHIFT_LEFT || event.code == KeyCode::KEY_SHIFT_RIGHT) ||
1845             (event.code == KEY_META_OR_CTRL_LEFT || event.code == KEY_META_OR_CTRL_RIGHT))) {
1846         return HandleKeyEvent(event);
1847     }
1848 
1849     if (event.action == KeyAction::DOWN) {
1850         cursorPositionType_ = CursorPositionType::NONE;
1851         if (KeyCode::TV_CONTROL_UP <= event.code && event.code <= KeyCode::TV_CONTROL_RIGHT &&
1852             (event.IsKey({ KeyCode::KEY_SHIFT_LEFT, event.code }) ||
1853                 event.IsKey({ KeyCode::KEY_SHIFT_RIGHT, event.code }))) {
1854             HandleOnSelect(event.code);
1855             return true;
1856         }
1857         if (event.code == KeyCode::TV_CONTROL_LEFT) {
1858             CursorMoveLeft();
1859             obscureTickPendings_ = 0;
1860             return true;
1861         }
1862         if (event.code == KeyCode::TV_CONTROL_RIGHT) {
1863             CursorMoveRight();
1864             obscureTickPendings_ = 0;
1865             return true;
1866         }
1867         if (event.code == KeyCode::TV_CONTROL_UP) {
1868             CursorMoveUp();
1869             obscureTickPendings_ = 0;
1870             return true;
1871         }
1872         if (event.code == KeyCode::TV_CONTROL_DOWN) {
1873             CursorMoveDown();
1874             obscureTickPendings_ = 0;
1875             return true;
1876         }
1877         if (event.code == KeyCode::KEY_FORWARD_DEL) {
1878             int32_t startPos = GetEditingValue().selection.GetStart();
1879             int32_t endPos = GetEditingValue().selection.GetEnd();
1880             Delete(startPos, startPos == endPos ? startPos - 1 : endPos);
1881             return true;
1882         }
1883         if (event.code == KeyCode::KEY_DEL) {
1884             int32_t startPos = GetEditingValue().selection.GetStart();
1885             int32_t endPos = GetEditingValue().selection.GetEnd();
1886             Delete(startPos, startPos == endPos ? startPos + 1 : endPos);
1887             return true;
1888         }
1889     }
1890     return HandleKeyEvent(event);
1891 }
1892 
UpdateFocusStyles()1893 void RenderTextField::UpdateFocusStyles()
1894 {
1895     if (hasFocus_) {
1896         style_.SetTextColor(focusTextColor_);
1897         placeholderColor_ = focusPlaceholderColor_;
1898         if (decoration_) {
1899             decoration_->SetBackgroundColor(focusBgColor_);
1900         }
1901     } else {
1902         style_.SetTextColor(inactiveTextColor_);
1903         placeholderColor_ = inactivePlaceholderColor_;
1904         if (decoration_) {
1905             decoration_->SetBackgroundColor(inactiveBgColor_);
1906         }
1907     }
1908 }
1909 
UpdateFocusAnimation()1910 void RenderTextField::UpdateFocusAnimation()
1911 {
1912     if (hasFocus_) {
1913         auto context = context_.Upgrade();
1914         if (!context) {
1915             return;
1916         }
1917         Offset offset;
1918         Size size;
1919         Radius deflateRadius;
1920         if (IsSelectiveDevice()) {
1921             double focusOffset = NormalizeToPx(OFFSET_FOCUS);
1922             offset = Offset(focusOffset, focusOffset);
1923             size = Size(focusOffset * 2.0, focusOffset * 2.0);
1924             deflateRadius = Radius(DEFLATE_RADIUS_FOCUS, DEFLATE_RADIUS_FOCUS);
1925         }
1926         RRect rrect = RRect::MakeRect(
1927             Rect(GetPosition() + offset, GetLayoutSize() - ComputeDeflateSizeOfErrorAndCountText() - size));
1928         if (decoration_) {
1929             const auto& border = decoration_->GetBorder();
1930             rrect.SetCorner({ border.TopLeftRadius() - deflateRadius, border.TopRightRadius() - deflateRadius,
1931                 border.BottomRightRadius() - deflateRadius, border.BottomLeftRadius() - deflateRadius });
1932         }
1933         context->ShowFocusAnimation(rrect, focusBgColor_, GetGlobalOffset() + offset);
1934     }
1935 }
1936 
UpdateIcon(const RefPtr<TextFieldComponent> & textField)1937 void RenderTextField::UpdateIcon(const RefPtr<TextFieldComponent>& textField)
1938 {
1939     if (!textField) {
1940         return;
1941     }
1942     iconSizeInDimension_ = textField->GetIconSize();
1943     iconHotZoneSizeInDimension_ = textField->GetIconHotZoneSize();
1944     UpdatePasswordIcon(textField);
1945 
1946     double widthReserved = NormalizeToPx(widthReserved_);
1947     if (textField->GetIconImage() == iconSrc_ && textField->GetImageFill() == imageFill_ && widthReserved <= 0.0) {
1948         return;
1949     }
1950     imageFill_ = textField->GetImageFill();
1951     iconSrc_ = textField->GetIconImage();
1952     if (!iconSrc_.empty() || widthReserved > 0.0) {
1953         RefPtr<ImageComponent> imageComponent;
1954         if (iconSrc_.empty() && widthReserved > 0.0) {
1955             imageComponent = AceType::MakeRefPtr<ImageComponent>(InternalResource::ResourceId::SEARCH_SVG);
1956         } else {
1957             imageComponent = AceType::MakeRefPtr<ImageComponent>(iconSrc_);
1958             imageComponent->SetImageFill(imageFill_);
1959         }
1960         imageComponent->SetSyncMode(true);
1961         imageComponent->SetWidth(textField->GetIconSize());
1962         imageComponent->SetHeight(textField->GetIconSize());
1963         if (textDirection_ == TextDirection::RTL) {
1964             imageComponent->SetMatchTextDirection(true);
1965             imageComponent->SetTextDirection(TextDirection::RTL);
1966         }
1967 
1968         iconImage_ = AceType::DynamicCast<RenderImage>(imageComponent->CreateRenderNode());
1969         if (!iconImage_) {
1970             return;
1971         }
1972         iconImage_->Attach(GetContext());
1973         iconImage_->SetDirectPaint(true);
1974         iconImage_->Update(imageComponent);
1975         AddChild(iconImage_);
1976     }
1977 }
1978 
UpdatePasswordIcon(const RefPtr<TextFieldComponent> & textField)1979 void RenderTextField::UpdatePasswordIcon(const RefPtr<TextFieldComponent>& textField)
1980 {
1981     if (!IsSelectiveDevice()) {
1982         return;
1983     }
1984     if (!showPasswordIcon_) {
1985         renderShowIcon_.Reset();
1986         renderHideIcon_.Reset();
1987         return;
1988     }
1989 
1990     showIconSrc_ = textField->GetShowIconImage();
1991     hideIconSrc_ = textField->GetHideIconImage();
1992 
1993     // update show icon.
1994     RefPtr<ImageComponent> showImage;
1995     if (showIconSrc_.empty()) {
1996         showImage = AceType::MakeRefPtr<ImageComponent>(InternalResource::ResourceId::SHOW_PASSWORD_SVG);
1997     } else {
1998         showImage = AceType::MakeRefPtr<ImageComponent>(showIconSrc_);
1999     }
2000     showImage->SetSyncMode(true);
2001     showImage->SetWidth(textField->GetIconSize());
2002     showImage->SetHeight(textField->GetIconSize());
2003 
2004     renderShowIcon_ = AceType::DynamicCast<RenderImage>(showImage->CreateRenderNode());
2005     if (!renderShowIcon_) {
2006         return;
2007     }
2008     renderShowIcon_->Attach(GetContext());
2009     renderShowIcon_->SetDirectPaint(true);
2010     renderShowIcon_->Update(showImage);
2011     AddChild(renderShowIcon_);
2012 
2013     // update hide icon.
2014     RefPtr<ImageComponent> hideImage;
2015     if (hideIconSrc_.empty()) {
2016         hideImage = AceType::MakeRefPtr<ImageComponent>(InternalResource::ResourceId::HIDE_PASSWORD_SVG);
2017     } else {
2018         hideImage = AceType::MakeRefPtr<ImageComponent>(hideIconSrc_);
2019     }
2020     hideImage->SetSyncMode(true);
2021     hideImage->SetWidth(textField->GetIconSize());
2022     hideImage->SetHeight(textField->GetIconSize());
2023 
2024     renderHideIcon_ = AceType::DynamicCast<RenderImage>(hideImage->CreateRenderNode());
2025     if (!renderHideIcon_) {
2026         return;
2027     }
2028     renderHideIcon_->Attach(GetContext());
2029     renderHideIcon_->SetDirectPaint(true);
2030     renderHideIcon_->Update(hideImage);
2031     AddChild(renderHideIcon_);
2032 }
2033 
UpdateOverlay()2034 void RenderTextField::UpdateOverlay()
2035 {
2036     // When textfield PerformLayout, update overlay.
2037     if (isOverlayShowed_ && updateHandlePosition_) {
2038         auto selStart = GetEditingValue().selection.GetStart();
2039         auto selEnd = GetEditingValue().selection.GetEnd();
2040         Rect caretStart;
2041         Rect caretEnd;
2042         bool startHandleVisible =
2043             GetCaretRect(selStart, caretStart) ? IsVisible(caretStart + textOffsetForShowCaret_) : false;
2044         bool endHandleVisible =
2045             (selStart == selEnd)
2046                 ? startHandleVisible
2047                 : (GetCaretRect(selEnd, caretEnd) ? IsVisible(caretEnd + textOffsetForShowCaret_) : false);
2048 
2049         OverlayShowOption option { .showMenu = isOverlayShowed_,
2050             .showStartHandle = startHandleVisible,
2051             .showEndHandle = endHandleVisible,
2052             .isSingleHandle = isSingleHandle_,
2053             .updateOverlayType = UpdateOverlayType::SCROLL,
2054             .startHandleOffset = GetPositionForExtend(selStart, isSingleHandle_),
2055             .endHandleOffset = GetPositionForExtend(selEnd, isSingleHandle_) };
2056         updateHandlePosition_(option);
2057         if (onClipRectChanged_) {
2058             onClipRectChanged_(innerRect_ + Size(HANDLE_HOT_ZONE, HANDLE_HOT_ZONE) + GetOffsetToPage() -
2059                                Offset(HANDLE_HOT_ZONE / 2.0, 0.0));
2060         }
2061     }
2062 }
2063 
RegisterFontCallbacks()2064 void RenderTextField::RegisterFontCallbacks()
2065 {
2066     // Register callback for fonts.
2067     auto pipelineContext = context_.Upgrade();
2068     if (!pipelineContext) {
2069         return;
2070     }
2071     auto callback = [textfield = AceType::WeakClaim(this)] {
2072         auto refPtr = textfield.Upgrade();
2073         if (refPtr) {
2074             refPtr->isCallbackCalled_ = true;
2075             refPtr->MarkNeedLayout();
2076         }
2077     };
2078     auto fontManager = pipelineContext->GetFontManager();
2079     if (fontManager) {
2080         for (const auto& familyName : style_.GetFontFamilies()) {
2081             fontManager->RegisterCallback(AceType::WeakClaim(this), familyName, callback);
2082         }
2083         fontManager->AddVariationNode(WeakClaim(this));
2084     }
2085 }
2086 
OnStatusChanged(OHOS::Ace::RenderStatus renderStatus)2087 void RenderTextField::OnStatusChanged(OHOS::Ace::RenderStatus renderStatus)
2088 {
2089     hasFocus_ = renderStatus == RenderStatus::FOCUS;
2090     UpdateFocusStyles();
2091     MarkNeedLayout();
2092 
2093     if (!hasFocus_) {
2094         auto context = context_.Upgrade();
2095         if (!context) {
2096             return;
2097         }
2098         // Don't call cancel focus animation when next frame comes because then focus is switched, next node will
2099         // show focus immediately, we shouldn't cancel focus animation that time.
2100         context->CancelFocusAnimation();
2101     }
2102 }
2103 
OnValueChanged(bool needFireChangeEvent,bool needFireSelectChangeEvent)2104 void RenderTextField::OnValueChanged(bool needFireChangeEvent, bool needFireSelectChangeEvent)
2105 {
2106     isValueFromFront_ = !needFireChangeEvent;
2107     TextEditingValue temp = GetEditingValue();
2108     if (cursorPositionType_ == CursorPositionType::NORMAL && temp.selection.GetStart() == temp.selection.GetEnd()) {
2109         temp.selection.Update(AdjustCursorAndSelection(temp.selection.GetEnd()));
2110     }
2111     FireSelectChangeIfNeeded(temp, needFireSelectChangeEvent);
2112     SetEditingValue(std::move(temp), needFireChangeEvent);
2113     UpdateRemoteEditingIfNeeded(needFireChangeEvent);
2114     MarkNeedLayout();
2115 }
2116 
FireSelectChangeIfNeeded(const TextEditingValue & newValue,bool needFireSelectChangeEvent) const2117 void RenderTextField::FireSelectChangeIfNeeded(const TextEditingValue& newValue, bool needFireSelectChangeEvent) const
2118 {
2119     if (needFireSelectChangeEvent && onSelectChangeEvent_ && newValue.selection != GetPreEditingValue().selection) {
2120         auto jsonResult = JsonUtil::Create(true);
2121         jsonResult->Put("start", newValue.selection.GetStart());
2122         jsonResult->Put("end", newValue.selection.GetEnd());
2123         onSelectChangeEvent_(std::string(R"("selectchange",)").append(jsonResult->ToString()));
2124     }
2125 }
2126 
CursorMoveLeft(CursorMoveSkip skip)2127 void RenderTextField::CursorMoveLeft(CursorMoveSkip skip)
2128 {
2129     if (skip != CursorMoveSkip::CHARACTER) {
2130         // Not support yet.
2131         LOGE("move skip not support character yet");
2132         return;
2133     }
2134     isValueFromRemote_ = false;
2135     auto value = GetEditingValue();
2136     value.MoveLeft();
2137     SetEditingValue(std::move(value));
2138     cursorPositionType_ = CursorPositionType::NONE;
2139     MarkNeedLayout();
2140 }
2141 
CursorMoveRight(CursorMoveSkip skip)2142 void RenderTextField::CursorMoveRight(CursorMoveSkip skip)
2143 {
2144     if (skip != CursorMoveSkip::CHARACTER) {
2145         // Not support yet.
2146         LOGE("move skip not support character yet");
2147         return;
2148     }
2149     isValueFromRemote_ = false;
2150     auto value = GetEditingValue();
2151     value.MoveRight();
2152     SetEditingValue(std::move(value));
2153     cursorPositionType_ = CursorPositionType::NONE;
2154     MarkNeedLayout();
2155 }
2156 
CursorMoveUp()2157 void RenderTextField::CursorMoveUp()
2158 {
2159     if (keyboard_ != TextInputType::MULTILINE) {
2160         return;
2161     }
2162     isValueFromRemote_ = false;
2163     auto value = GetEditingValue();
2164     value.MoveToPosition(GetCursorPositionForMoveUp());
2165     SetEditingValue(std::move(value));
2166     cursorPositionType_ = CursorPositionType::NONE;
2167     MarkNeedLayout();
2168 }
2169 
CursorMoveDown()2170 void RenderTextField::CursorMoveDown()
2171 {
2172     if (keyboard_ != TextInputType::MULTILINE) {
2173         return;
2174     }
2175     isValueFromRemote_ = false;
2176     auto value = GetEditingValue();
2177     value.MoveToPosition(GetCursorPositionForMoveDown());
2178     SetEditingValue(std::move(value));
2179     cursorPositionType_ = CursorPositionType::NONE;
2180     MarkNeedLayout();
2181 }
2182 
HandleOnBlur()2183 void RenderTextField::HandleOnBlur()
2184 {
2185     LOGI("Textfield on blur");
2186     SetCanPaintSelection(false);
2187     auto lastPosition = static_cast<int32_t>(GetEditingValue().GetWideText().length());
2188     UpdateSelection(lastPosition, lastPosition);
2189     StopTwinkling();
2190     PopTextOverlay();
2191     OnEditChange(false);
2192     ResetOnFocusForTextFieldManager();
2193 }
2194 
CursorMoveOnClick(const Offset & offset)2195 void RenderTextField::CursorMoveOnClick(const Offset& offset)
2196 {
2197     auto value = GetEditingValue();
2198     auto position = GetCursorPositionForClick(offset);
2199     value.MoveToPosition(position);
2200     UpdateSelection(position, position);
2201     SetEditingValue(std::move(value));
2202 
2203     if (!GetEditingValue().text.empty() && position == GetEditingValue().selection.GetEnd()) {
2204         OnValueChanged(true, false);
2205     }
2206 }
2207 
UpdateSelection(int32_t both)2208 void RenderTextField::UpdateSelection(int32_t both)
2209 {
2210     UpdateSelection(both, both);
2211 }
2212 
UpdateSelection(int32_t start,int32_t end)2213 void RenderTextField::UpdateSelection(int32_t start, int32_t end)
2214 {
2215     auto value = GetEditingValue();
2216     value.UpdateSelection(start, end);
2217     SetEditingValue(std::move(value));
2218     auto refPtr = accessibilityNode_.Upgrade();
2219     if (refPtr) {
2220         refPtr->SetTextSelectionStart(start);
2221         refPtr->SetTextSelectionEnd(end);
2222     }
2223 }
2224 
UpdateRemoteEditing(bool needFireChangeEvent)2225 void RenderTextField::UpdateRemoteEditing(bool needFireChangeEvent)
2226 {
2227 #if defined(ENABLE_STANDARD_INPUT)
2228     auto value = GetEditingValue();
2229     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
2230         StringUtils::Str8ToStr16(value.text), value.selection.GetStart(), value.selection.GetEnd());
2231 #else
2232     if (!HasConnection()) {
2233         return;
2234     }
2235     connection_->SetEditingState(GetEditingValue(), GetInstanceId(), needFireChangeEvent);
2236 #endif
2237 }
2238 
UpdateRemoteEditingIfNeeded(bool needFireChangeEvent)2239 void RenderTextField::UpdateRemoteEditingIfNeeded(bool needFireChangeEvent)
2240 {
2241     if (!enabled_) {
2242         return;
2243     }
2244 #if defined(ENABLE_STANDARD_INPUT)
2245     UpdateRemoteEditing(needFireChangeEvent);
2246 #else
2247     UpdateRemoteEditing(needFireChangeEvent);
2248     if (!lastKnownRemoteEditingValue_ || GetEditingValue() != *lastKnownRemoteEditingValue_) {
2249         lastKnownRemoteEditingValue_ = std::make_shared<TextEditingValue>(GetEditingValue());
2250     }
2251 #endif
2252 }
2253 
ShowError(const std::string & errorText,bool resetToStart)2254 void RenderTextField::ShowError(const std::string& errorText, bool resetToStart)
2255 {
2256     errorText_ = errorText;
2257     if (!errorText.empty()) {
2258         auto refPtr = accessibilityNode_.Upgrade();
2259         if (refPtr) {
2260             refPtr->SetErrorText(errorText);
2261         }
2262     }
2263 
2264     if (!errorText.empty()) {
2265         ChangeBorderToErrorStyle();
2266     } else {
2267         if (decoration_) {
2268             decoration_->SetBorder(originBorder_);
2269         }
2270     }
2271     MarkNeedLayout();
2272 }
2273 
SetOnValueChange(const std::function<void ()> & onValueChange)2274 void RenderTextField::SetOnValueChange(const std::function<void()>& onValueChange)
2275 {
2276     onValueChange_ = onValueChange;
2277 }
2278 
GetOnValueChange() const2279 const std::function<void()>& RenderTextField::GetOnValueChange() const
2280 {
2281     return onValueChange_;
2282 }
2283 
SetOnKeyboardClose(const std::function<void (bool)> & onKeyboardClose)2284 void RenderTextField::SetOnKeyboardClose(const std::function<void(bool)>& onKeyboardClose)
2285 {
2286     onKeyboardClose_ = onKeyboardClose;
2287 }
2288 
SetOnClipRectChanged(const std::function<void (const Rect &)> & onClipRectChanged)2289 void RenderTextField::SetOnClipRectChanged(const std::function<void(const Rect&)>& onClipRectChanged)
2290 {
2291     onClipRectChanged_ = onClipRectChanged;
2292 }
2293 
SetUpdateHandlePosition(const std::function<void (const OverlayShowOption &)> & updateHandlePosition)2294 void RenderTextField::SetUpdateHandlePosition(const std::function<void(const OverlayShowOption&)>& updateHandlePosition)
2295 {
2296     updateHandlePosition_ = updateHandlePosition;
2297 }
2298 
SetUpdateHandleDiameter(const std::function<void (const double &)> & updateHandleDiameter)2299 void RenderTextField::SetUpdateHandleDiameter(const std::function<void(const double&)>& updateHandleDiameter)
2300 {
2301     updateHandleDiameter_ = updateHandleDiameter;
2302 }
2303 
SetUpdateHandleDiameterInner(const std::function<void (const double &)> & updateHandleDiameterInner)2304 void RenderTextField::SetUpdateHandleDiameterInner(const std::function<void(const double&)>& updateHandleDiameterInner)
2305 {
2306     updateHandleDiameterInner_ = updateHandleDiameterInner;
2307 }
2308 
SetIsOverlayShowed(bool isOverlayShowed,bool needStartTwinkling)2309 void RenderTextField::SetIsOverlayShowed(bool isOverlayShowed, bool needStartTwinkling)
2310 {
2311     isOverlayShowed_ = isOverlayShowed;
2312     // When pop overlay, reset selection and clear selected style.
2313     if (GetEditingValue().selection.GetStart() != GetEditingValue().selection.GetEnd()) {
2314         UpdateSelection(GetEditingValue().selection.GetEnd());
2315     }
2316     if (!isOverlayShowed_ && hasFocus_ && needStartTwinkling) {
2317         StartTwinkling();
2318     }
2319 }
2320 
HandleOnSelect(KeyCode keyCode,CursorMoveSkip skip)2321 void RenderTextField::HandleOnSelect(KeyCode keyCode, CursorMoveSkip skip)
2322 {
2323     if (skip != CursorMoveSkip::CHARACTER) {
2324         // Not support yet.
2325         LOGE("move skip not support character yet");
2326         return;
2327     }
2328 
2329     isValueFromRemote_ = false;
2330     auto value = GetEditingValue();
2331     int32_t startPos = value.selection.GetStart();
2332     int32_t endPos = value.selection.GetEnd();
2333     static bool isForwardSelect;
2334     switch (keyCode) {
2335         case KeyCode::KEY_DPAD_LEFT:
2336             if (startPos == endPos) {
2337                 isForwardSelect = true;
2338             }
2339             if (isForwardSelect) {
2340                 value.UpdateSelection(startPos - 1, endPos);
2341             } else {
2342                 value.UpdateSelection(startPos, endPos - 1);
2343             }
2344             break;
2345         case KeyCode::KEY_DPAD_RIGHT:
2346             if (startPos == endPos) {
2347                 isForwardSelect = false;
2348             }
2349             if (isForwardSelect) {
2350                 value.UpdateSelection(startPos + 1, endPos);
2351             } else {
2352                 value.UpdateSelection(startPos, endPos + 1);
2353             }
2354             break;
2355         default:
2356             LOGI("Currently only left and right selections are supported.");
2357             return;
2358     }
2359 
2360     SetEditingValue(std::move(value));
2361     MarkNeedLayout();
2362 }
2363 
HandleOnRevoke()2364 void RenderTextField::HandleOnRevoke()
2365 {
2366     if (operationRecords_.empty()) {
2367         return;
2368     }
2369     inverseOperationRecords_.push_back(GetEditingValue());
2370     operationRecords_.pop_back();
2371     auto value = operationRecords_.back();
2372     operationRecords_.pop_back();
2373     isValueFromRemote_ = false;
2374     SetEditingValue(std::move(value), true, false);
2375     cursorPositionType_ = CursorPositionType::NONE;
2376     MarkNeedLayout();
2377     if (onChange_) {
2378         onChange_(GetEditingValue().text);
2379     }
2380 }
2381 
HandleOnInverseRevoke()2382 void RenderTextField::HandleOnInverseRevoke()
2383 {
2384     if (inverseOperationRecords_.empty()) {
2385         return;
2386     }
2387     auto value = inverseOperationRecords_.back();
2388     inverseOperationRecords_.pop_back();
2389     isValueFromRemote_ = false;
2390     SetEditingValue(std::move(value), true, false);
2391     cursorPositionType_ = CursorPositionType::NONE;
2392     MarkNeedLayout();
2393     if (onChange_) {
2394         onChange_(GetEditingValue().text);
2395     }
2396 }
2397 
HandleOnCut()2398 void RenderTextField::HandleOnCut()
2399 {
2400     if (!clipboard_) {
2401         return;
2402     }
2403     if (GetEditingValue().GetSelectedText().empty()) {
2404         LOGW("copy value is empty");
2405         return;
2406     }
2407     if (copyOption_ != CopyOptions::None) {
2408         LOGI("copy value is %{private}s", GetEditingValue().GetSelectedText().c_str());
2409         clipboard_->SetData(GetEditingValue().GetSelectedText(), copyOption_);
2410     }
2411     if (onCut_) {
2412         onCut_(GetEditingValue().GetSelectedText());
2413     }
2414     auto value = GetEditingValue();
2415     value.text = value.GetBeforeSelection() + value.GetAfterSelection();
2416     value.UpdateSelection(GetEditingValue().selection.GetStart());
2417     SetEditingValue(std::move(value));
2418     if (onChange_) {
2419         onChange_(GetEditingValue().text);
2420     }
2421 }
2422 
HandleOnCopy()2423 void RenderTextField::HandleOnCopy()
2424 {
2425     if (!clipboard_) {
2426         return;
2427     }
2428     if (GetEditingValue().GetSelectedText().empty()) {
2429         LOGW("copy value is empty");
2430         return;
2431     }
2432     if (copyOption_ != CopyOptions::None) {
2433         LOGI("copy value is %{private}s", GetEditingValue().GetSelectedText().c_str());
2434         clipboard_->SetData(GetEditingValue().GetSelectedText(), copyOption_);
2435     }
2436     if (onCopy_) {
2437         onCopy_(GetEditingValue().GetSelectedText());
2438     }
2439     UpdateSelection(GetEditingValue().selection.GetEnd());
2440 }
2441 
HandleOnPaste()2442 void RenderTextField::HandleOnPaste()
2443 {
2444     ACE_FUNCTION_TRACE();
2445     if (!clipboard_) {
2446         return;
2447     }
2448     auto textSelection = GetEditingValue().selection;
2449     auto pasteCallback = [weak = WeakClaim(this), textSelection](const std::string& data) {
2450         if (data.empty()) {
2451             LOGW("paste value is empty");
2452             return;
2453         }
2454         LOGI("paste value is %{private}s", data.c_str());
2455         auto textfield = weak.Upgrade();
2456         if (textfield) {
2457             auto value = textfield->GetEditingValue();
2458             value.selection = textSelection;
2459             value.text = value.GetBeforeSelection() + data + value.GetAfterSelection();
2460             value.UpdateSelection(textSelection.GetStart() + StringUtils::Str8ToStr16(data).length());
2461             textfield->SetEditingValue(std::move(value));
2462             if (textfield->onPaste_) {
2463                 textfield->onPaste_(data);
2464             }
2465             if (textfield->onChange_) {
2466                 textfield->onChange_(textfield->GetEditingValue().text);
2467             }
2468         }
2469     };
2470     clipboard_->GetData(pasteCallback);
2471 }
2472 
HandleOnCopyAll(const std::function<void (const Offset &,const Offset &)> & callback)2473 void RenderTextField::HandleOnCopyAll(const std::function<void(const Offset&, const Offset&)>& callback)
2474 {
2475     isSingleHandle_ = false;
2476     cursorPositionType_ = CursorPositionType::NORMAL;
2477     auto textSize = GetEditingValue().GetWideText().length();
2478     if (textSize == 0) {
2479         isSingleHandle_ = true;
2480     }
2481     UpdateSelection(0, textSize);
2482     if (callback) {
2483         callback(GetPositionForExtend(0, isSingleHandle_),
2484             GetPositionForExtend(GetEditingValue().GetWideText().length(), isSingleHandle_));
2485     }
2486 }
2487 
HandleOnStartHandleMove(int32_t end,const Offset & startHandleOffset,const std::function<void (const Offset &)> & startCallback,bool isSingleHandle)2488 void RenderTextField::HandleOnStartHandleMove(int32_t end, const Offset& startHandleOffset,
2489     const std::function<void(const Offset&)>& startCallback, bool isSingleHandle)
2490 {
2491     Offset realOffset = startHandleOffset;
2492     if (startCallback) {
2493         UpdateStartSelection(end, realOffset, isSingleHandle, false);
2494         startCallback(GetHandleOffset(GetEditingValue().selection.GetStart()));
2495     }
2496 }
2497 
HandleOnEndHandleMove(int32_t start,const Offset & endHandleOffset,const std::function<void (const Offset &)> & endCallback)2498 void RenderTextField::HandleOnEndHandleMove(
2499     int32_t start, const Offset& endHandleOffset, const std::function<void(const Offset&)>& endCallback)
2500 {
2501     Offset realOffset = endHandleOffset;
2502     if (endCallback) {
2503         UpdateEndSelection(start, realOffset);
2504         endCallback(GetHandleOffset(GetEditingValue().selection.GetEnd()));
2505     }
2506 }
2507 
GetLastStack() const2508 RefPtr<StackElement> RenderTextField::GetLastStack() const
2509 {
2510     auto context = context_.Upgrade();
2511     if (!context) {
2512         LOGE("Context is nullptr");
2513         return nullptr;
2514     }
2515     return context->GetLastStack();
2516 }
2517 
HandleKeyEvent(const KeyEvent & event)2518 bool RenderTextField::HandleKeyEvent(const KeyEvent& event)
2519 {
2520     std::string appendElement;
2521     if (event.action == KeyAction::DOWN) {
2522         if (event.code == KeyCode::KEY_ENTER || event.code == KeyCode::KEY_NUMPAD_ENTER ||
2523             event.code == KeyCode::KEY_DPAD_CENTER) {
2524             if (keyboard_ == TextInputType::MULTILINE) {
2525                 appendElement = "\n";
2526             } else {
2527                 // normal enter should trigger onSubmit
2528                 PerformAction(action_, true);
2529             }
2530         } else if (event.IsNumberKey()) {
2531             appendElement = event.ConvertCodeToString();
2532         } else if (event.IsLetterKey()) {
2533             if (event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_SHIFT_LEFT, KeyCode::KEY_Z }) ||
2534                 event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_SHIFT_RIGHT, KeyCode::KEY_Z }) ||
2535                 event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_SHIFT_LEFT, KeyCode::KEY_Z }) ||
2536                 event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_SHIFT_RIGHT, KeyCode::KEY_Z }) ||
2537                 event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_Y }) ||
2538                 event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_Y })) {
2539                 HandleOnInverseRevoke();
2540             } else if (event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_Z }) ||
2541                        event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_Z })) {
2542                 HandleOnRevoke();
2543             } else if (event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_A }) ||
2544                        event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_A })) {
2545                 HandleOnCopyAll(nullptr);
2546             } else if (event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_C }) ||
2547                        event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_C })) {
2548                 HandleOnCopy();
2549             } else if (event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_V }) ||
2550                        event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_V })) {
2551                 HandleOnPaste();
2552             } else if (event.IsKey({ KEY_META_OR_CTRL_LEFT, KeyCode::KEY_X }) ||
2553                        event.IsKey({ KEY_META_OR_CTRL_RIGHT, KeyCode::KEY_X })) {
2554                 HandleOnCut();
2555             } else {
2556                 appendElement = event.ConvertCodeToString();
2557             }
2558         }
2559         MarkNeedLayout();
2560     }
2561     if (appendElement.empty()) {
2562         return false;
2563     }
2564 
2565     auto editingValue = std::make_shared<TextEditingValue>();
2566     editingValue->text = GetEditingValue().GetBeforeSelection() + appendElement + GetEditingValue().GetAfterSelection();
2567     editingValue->UpdateSelection(
2568         std::max(GetEditingValue().selection.GetEnd(), 0) + StringUtils::Str8ToStr16(appendElement).length());
2569     UpdateEditingValue(editingValue);
2570     MarkNeedLayout();
2571     return true;
2572 }
2573 
UpdateAccessibilityAttr()2574 void RenderTextField::UpdateAccessibilityAttr()
2575 {
2576     auto refPtr = accessibilityNode_.Upgrade();
2577     if (!refPtr) {
2578         LOGW("RenderTextField accessibilityNode is null.");
2579         return;
2580     }
2581 
2582     refPtr->SetHintText(placeholder_);
2583     refPtr->SetMaxTextLength(maxLength_);
2584     refPtr->SetEditable(enabled_);
2585     refPtr->SetClickableState(true);
2586     refPtr->SetLongClickableState(true);
2587     if (maxLines_ > 1) {
2588         refPtr->SetIsMultiLine(true);
2589     }
2590     if (controller_) {
2591         refPtr->SetText(controller_->GetText());
2592     }
2593     switch (keyboard_) {
2594         case TextInputType::TEXT:
2595             refPtr->SetTextInputType(AceTextCategory::INPUT_TYPE_TEXT);
2596             break;
2597         case TextInputType::NUMBER:
2598             refPtr->SetTextInputType(AceTextCategory::INPUT_TYPE_NUMBER);
2599             break;
2600         case TextInputType::DATETIME:
2601             refPtr->SetTextInputType(AceTextCategory::INPUT_TYPE_DATE);
2602             break;
2603         case TextInputType::EMAIL_ADDRESS:
2604             refPtr->SetTextInputType(AceTextCategory::INPUT_TYPE_EMAIL);
2605             break;
2606         case TextInputType::VISIBLE_PASSWORD:
2607             refPtr->SetTextInputType(AceTextCategory::INPUT_TYPE_PASSWORD);
2608             break;
2609         default:
2610             break;
2611     }
2612 }
2613 
InitAccessibilityEventListener()2614 void RenderTextField::InitAccessibilityEventListener()
2615 {
2616     const auto& accessibilityNode = GetAccessibilityNode().Upgrade();
2617     if (!accessibilityNode) {
2618         return;
2619     }
2620     accessibilityNode->AddSupportAction(AceAction::ACTION_CLICK);
2621     accessibilityNode->SetActionClickImpl([weakPtr = WeakClaim(this)]() {
2622         const auto& textField = weakPtr.Upgrade();
2623         if (textField) {
2624             textField->OnClick(ClickInfo(0));
2625         }
2626     });
2627 
2628     accessibilityNode->AddSupportAction(AceAction::ACTION_LONG_CLICK);
2629     accessibilityNode->SetActionLongClickImpl([weakPtr = WeakClaim(this)]() {
2630         const auto& textField = weakPtr.Upgrade();
2631         if (textField) {
2632             textField->OnLongPress(LongPressInfo(0));
2633         }
2634     });
2635 
2636     accessibilityNode->AddSupportAction(AceAction::ACTION_SET_TEXT);
2637     accessibilityNode->SetActionSetTextImpl([weakPtr = WeakClaim(this)](const std::string& text) {
2638         const auto& textField = weakPtr.Upgrade();
2639         if (textField) {
2640             textField->SetEditingValue(text);
2641         }
2642     });
2643 }
2644 
UpdateDirectionStatus()2645 void RenderTextField::UpdateDirectionStatus()
2646 {
2647     directionStatus_ = static_cast<DirectionStatus>(
2648         (static_cast<uint8_t>(textDirection_) << 1) | static_cast<uint8_t>(realTextDirection_));
2649 }
2650 
UpdateStartSelection(int32_t end,const Offset & pos,bool isSingleHandle,bool isLongPress)2651 void RenderTextField::UpdateStartSelection(int32_t end, const Offset& pos, bool isSingleHandle, bool isLongPress)
2652 {
2653     int32_t extend = GetCursorPositionForClick(pos);
2654     if (isLongPress) {
2655         // Use custom selection if exist, otherwise select content near finger.
2656         if (selection_.IsValid()) {
2657             UpdateSelection(selection_.baseOffset, selection_.extentOffset);
2658         } else {
2659             int32_t extendEnd = extend + GetGraphemeClusterLength(extend, false);
2660             UpdateSelection(extend, extendEnd);
2661         }
2662         return;
2663     }
2664     if (isSingleHandle) {
2665         UpdateSelection(extend);
2666     } else {
2667         UpdateSelection(extend, end);
2668     }
2669 }
2670 
UpdateEndSelection(int32_t start,const Offset & pos)2671 void RenderTextField::UpdateEndSelection(int32_t start, const Offset& pos)
2672 {
2673     int32_t extend = GetCursorPositionForClick(pos);
2674     UpdateSelection(start, extend);
2675 }
2676 
GetPositionForExtend(int32_t extend,bool isSingleHandle)2677 Offset RenderTextField::GetPositionForExtend(int32_t extend, bool isSingleHandle)
2678 {
2679     if (extend < 0) {
2680         extend = 0;
2681     }
2682     if (static_cast<size_t>(extend) > GetEditingValue().GetWideText().length()) {
2683         extend = static_cast<int32_t>(GetEditingValue().GetWideText().length());
2684     }
2685     return GetHandleOffset(extend);
2686 }
2687 
GetGraphemeClusterLength(int32_t extend,bool isPrefix) const2688 int32_t RenderTextField::GetGraphemeClusterLength(int32_t extend, bool isPrefix) const
2689 {
2690     auto text = GetTextForDisplay(GetEditingValue().text);
2691     char16_t aroundChar = 0;
2692     if (isPrefix) {
2693         if (static_cast<size_t>(extend) <= text.length()) {
2694             aroundChar = text[std::max(0, extend - 1)];
2695         }
2696     } else {
2697         if (static_cast<size_t>(extend) < (text.length())) {
2698             aroundChar = text[std::min(static_cast<int32_t>(text.length() - 1), extend)];
2699         }
2700     }
2701     return StringUtils::NotInUtf16Bmp(aroundChar) ? 2 : 1;
2702 }
2703 
ShowCounter() const2704 bool RenderTextField::ShowCounter() const
2705 {
2706     return showCounter_ && maxLength_ < std::numeric_limits<uint32_t>::max();
2707 }
2708 
ChangeCounterStyle(const TextEditingValue & value)2709 void RenderTextField::ChangeCounterStyle(const TextEditingValue& value)
2710 {
2711     if (!ShowCounter()) {
2712         return;
2713     }
2714     if (value.GetWideText().size() > maxLength_) {
2715         overCount_ = true;
2716         ChangeBorderToErrorStyle();
2717     } else if (value.GetWideText().size() < maxLength_) {
2718         overCount_ = false;
2719         if (decoration_) {
2720             decoration_->SetBorder(originBorder_);
2721         }
2722     }
2723 }
2724 
ChangeBorderToErrorStyle()2725 void RenderTextField::ChangeBorderToErrorStyle()
2726 {
2727     if (!decoration_) {
2728         decoration_ = AceType::MakeRefPtr<Decoration>();
2729     }
2730     const auto& border = decoration_->GetBorder();
2731     BorderEdge errorBorderEdge(errorBorderColor_, errorBorderWidth_, BorderStyle::SOLID);
2732     Border errorBorder;
2733     if (!border.Left().HasValue() && !border.Top().HasValue() && !border.Right().HasValue() &&
2734         border.Bottom().HasValue()) {
2735         // Change over count style for linear input.
2736         errorBorder = Border(BorderEdge(), BorderEdge(), BorderEdge(), errorBorderEdge);
2737     } else {
2738         errorBorder = Border(errorBorderEdge);
2739     }
2740     errorBorder.SetTopLeftRadius(decoration_->GetBorder().TopLeftRadius());
2741     errorBorder.SetTopRightRadius(decoration_->GetBorder().TopRightRadius());
2742     errorBorder.SetBottomLeftRadius(decoration_->GetBorder().BottomLeftRadius());
2743     errorBorder.SetBottomRightRadius(decoration_->GetBorder().BottomRightRadius());
2744     decoration_->SetBorder(errorBorder);
2745 }
2746 
HandleDeviceOrientationChange()2747 void RenderTextField::HandleDeviceOrientationChange()
2748 {
2749     if (deviceOrientation_ != SystemProperties::GetDeviceOrientation()) {
2750         deviceOrientation_ = SystemProperties::GetDeviceOrientation();
2751         if (isOverlayShowed_) {
2752             onKeyboardClose_ = nullptr;
2753             PopTextOverlay();
2754             StartTwinkling();
2755         }
2756     }
2757 }
2758 
OnHiddenChanged(bool hidden)2759 void RenderTextField::OnHiddenChanged(bool hidden)
2760 {
2761     if (hidden) {
2762         LOGI("On hidden change, close keyboard");
2763         CloseKeyboard();
2764         PopTextOverlay();
2765     }
2766 }
2767 
OnAppHide()2768 void RenderTextField::OnAppHide()
2769 {
2770     RenderNode::OnAppHide();
2771     OnHiddenChanged(true);
2772 }
2773 
OnOverlayFocusChange(bool isFocus,bool needCloseKeyboard)2774 void RenderTextField::OnOverlayFocusChange(bool isFocus, bool needCloseKeyboard)
2775 {
2776     isOverlayFocus_ = isFocus;
2777     if (needCloseKeyboard && onOverlayFocusChange_) {
2778         onOverlayFocusChange_(isFocus);
2779     }
2780 }
2781 
GetInstanceId() const2782 int32_t RenderTextField::GetInstanceId() const
2783 {
2784     auto context = context_.Upgrade();
2785     if (context) {
2786         return context->GetInstanceId();
2787     }
2788     return 0;
2789 }
2790 
Insert(const std::string & text)2791 void RenderTextField::Insert(const std::string& text)
2792 {
2793     auto context = context_.Upgrade();
2794     if (context) {
2795         context->GetTaskExecutor()->PostTask(
2796             [weakPtr = WeakClaim(this), text] {
2797                 const auto& textField = weakPtr.Upgrade();
2798                 auto value = textField->GetEditingValue();
2799                 auto textEditingValue = std::make_shared<TextEditingValue>();
2800                 textEditingValue->text = value.GetBeforeSelection() + text + value.GetAfterSelection();
2801                 textEditingValue->UpdateSelection(std::max(value.selection.GetStart(), 0) + text.length());
2802                 textField->UpdateInsertText(text);
2803                 textField->UpdateEditingValue(textEditingValue, true);
2804             },
2805             TaskExecutor::TaskType::UI);
2806     }
2807 }
2808 
Delete(int32_t start,int32_t end)2809 void RenderTextField::Delete(int32_t start, int32_t end)
2810 {
2811     auto value = GetEditingValue();
2812     value.Delete(start, end);
2813     SetEditingValue(std::move(value));
2814     if (onValueChange_) {
2815         onValueChange_();
2816     }
2817     if (onChange_) {
2818         onChange_(GetEditingValue().text);
2819     }
2820 }
2821 
ProvideRestoreInfo()2822 std::string RenderTextField::ProvideRestoreInfo()
2823 {
2824     auto value = GetEditingValue();
2825     auto jsonObj = JsonUtil::Create(true);
2826     if (controller_) {
2827         jsonObj->Put("text", controller_->GetText().c_str());
2828     } else {
2829         return "";
2830     }
2831     jsonObj->Put("position", value.selection.baseOffset);
2832     return jsonObj->ToString();
2833 }
2834 
ApplyRestoreInfo()2835 void RenderTextField::ApplyRestoreInfo()
2836 {
2837     if (GetRestoreInfo().empty()) {
2838         return;
2839     }
2840     auto info = JsonUtil::ParseJsonString(GetRestoreInfo());
2841     if (!info->IsValid() || !info->IsObject()) {
2842         LOGW("RenderTextField:: restore info is invalid");
2843         return;
2844     }
2845     auto jsonPosition = info->GetValue("position");
2846     auto jsonText = info->GetValue("text");
2847     if (!jsonText->GetString().empty() && controller_) {
2848         controller_->SetText(jsonText->GetString());
2849         UpdateSelection(std::max(jsonPosition->GetInt(), 0));
2850         cursorPositionType_ = CursorPositionType::NORMAL;
2851     }
2852     SetRestoreInfo("");
2853 }
2854 
ApplyAspectRatio()2855 void RenderTextField::ApplyAspectRatio()
2856 {
2857     auto parent = GetParent().Upgrade();
2858     while (parent) {
2859         auto renderBox = DynamicCast<RenderBox>(parent);
2860         if (renderBox && !NearZero(renderBox->GetAspectRatio()) && GetLayoutParam().GetMaxSize().IsValid() &&
2861             !GetLayoutParam().GetMaxSize().IsInfinite()) {
2862             height_ = Dimension(GetLayoutParam().GetMaxSize().Height());
2863             break;
2864         }
2865         parent = parent->GetParent().Upgrade();
2866     }
2867 }
2868 
Dump()2869 void RenderTextField::Dump()
2870 {
2871     DumpLog::GetInstance().AddDesc(std::string("CopyOptions: ").append(V2::ConvertWrapCopyOptionToString(copyOption_)));
2872 }
2873 
2874 } // namespace OHOS::Ace
2875