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