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