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