• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_ng/pattern/text_field/text_field_pattern.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <optional>
21 #include <regex>
22 #include <string>
23 #include <utility>
24 
25 #include "base/geometry/dimension.h"
26 #include "base/geometry/ng/offset_t.h"
27 #include "base/geometry/ng/rect_t.h"
28 #include "base/geometry/offset.h"
29 #include "base/i18n/localization.h"
30 #include "base/log/dump_log.h"
31 #include "base/log/log_wrapper.h"
32 #include "base/memory/referenced.h"
33 #include "base/utils/string_utils.h"
34 #include "base/utils/utils.h"
35 #include "core/common/clipboard/clipboard_proxy.h"
36 #include "core/common/container_scope.h"
37 #include "core/common/font_manager.h"
38 #include "core/common/ime/text_edit_controller.h"
39 #include "core/common/ime/text_input_client.h"
40 #include "core/common/ime/text_input_connection.h"
41 #include "core/common/ime/text_input_formatter.h"
42 #include "core/common/ime/text_input_type.h"
43 #include "core/common/ime/text_selection.h"
44 #include "core/common/recorder/node_data_cache.h"
45 #include "core/components/common/layout/constants.h"
46 #include "core/components/text_field/textfield_theme.h"
47 #include "core/components/theme/icon_theme.h"
48 #include "core/components_ng/event/focus_hub.h"
49 #include "core/components_ng/image_provider/image_loading_context.h"
50 #include "core/components_ng/pattern/overlay/modal_style.h"
51 #include "core/components_ng/pattern/search/search_event_hub.h"
52 #include "core/components_ng/pattern/search/search_pattern.h"
53 #include "core/components_ng/pattern/select_overlay/select_overlay_pattern.h"
54 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
55 #include "core/components_ng/pattern/stage/page_pattern.h"
56 #include "core/components_ng/pattern/text/text_base.h"
57 #include "core/components_ng/pattern/text/text_pattern.h"
58 #include "core/components_ng/pattern/text/text_styles.h"
59 #include "core/components_ng/pattern/text_drag/text_drag_pattern.h"
60 #include "core/components_ng/pattern/text_field/text_field_controller.h"
61 #include "core/components_ng/pattern/text_field/text_field_event_hub.h"
62 #include "core/components_ng/pattern/text_field/text_field_layout_algorithm.h"
63 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
64 #include "core/components_ng/pattern/text_field/text_field_manager.h"
65 #include "core/components_ng/pattern/text_field/text_field_model.h"
66 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
67 #include "core/components_ng/pattern/text_field/text_selector.h"
68 #include "core/components_ng/property/property.h"
69 #include "core/components_ng/render/drawing.h"
70 #include "core/components_ng/render/drawing_prop_convertor.h"
71 #include "core/components_ng/render/paragraph.h"
72 #include "core/components_v2/inspector/inspector_constants.h"
73 #include "core/components_v2/inspector/utils.h"
74 #include "core/event/ace_events.h"
75 #include "core/image/image_source_info.h"
76 #include "core/pipeline/pipeline_base.h"
77 #include "core/pipeline_ng/pipeline_context.h"
78 #if not defined(ACE_UNITTEST)
79 #if defined(ENABLE_STANDARD_INPUT)
80 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
81 #endif
82 #endif
83 #include "core/common/udmf/udmf_client.h"
84 
85 #ifdef WINDOW_SCENE_SUPPORTED
86 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
87 #endif
88 namespace OHOS::Ace::NG {
89 namespace {
90 // need to be moved to TextFieldTheme
91 constexpr Dimension BORDER_DEFAULT_WIDTH = 0.0_vp;
92 constexpr Dimension TYPING_UNDERLINE_WIDTH = 2.0_px;
93 constexpr Dimension ERROR_BORDER_WIDTH = 1.0_vp;
94 constexpr Dimension OVER_COUNT_BORDER_WIDTH = 1.0_vp;
95 constexpr Dimension INLINE_BORDER_WIDTH = 2.0_vp;
96 constexpr Dimension ERROR_UNDERLINE_WIDTH = 2.0_px;
97 constexpr Dimension UNDERLINE_WIDTH = 1.0_px;
98 constexpr Dimension UNDERLINE_NORMAL_HEIGHT = 48.0_vp;
99 constexpr uint32_t INLINE_DEFAULT_VIEW_MAXLINE = 3;
100 constexpr Dimension UNDERLINE_NORMAL_PADDING = 12.0_vp;
101 constexpr Dimension SCROLL_BAR_MIN_HEIGHT = 4.0_vp;
102 #if defined(ENABLE_STANDARD_INPUT)
103 constexpr Dimension AVOID_OFFSET = 24.0_vp;
104 #endif
105 constexpr Dimension DEFAULT_FONT = Dimension(16, DimensionUnit::FP);
106 constexpr Dimension COUNTER_BOTTOM = 22.0_vp;
107 constexpr double BOTTOM_MARGIN = 22.0;
108 constexpr float MARGIN_ZERO = 0.0f;
109 constexpr int32_t ONE_CHARACTER = 1;
110 constexpr int32_t ILLEGAL_VALUE = 0;
111 // uncertainty range when comparing selectedTextBox to contentRect
112 constexpr float BOX_EPSILON = 0.5f;
113 constexpr float DOUBLECLICK_INTERVAL_MS = 300.0f;
114 constexpr float DOUBLECLICK_MIN_INTERVAL_MS = 0.0f;
115 constexpr Dimension DOUBLECLICK_DISTANCE = 15.0_vp;
116 constexpr double VELOCITY = -1000;
117 constexpr double MASS = 1.0;
118 constexpr double STIFFNESS = 428.0;
119 constexpr double DAMPING = 10.0;
120 constexpr uint32_t TWINKLING_INTERVAL_MS = 500;
121 constexpr uint32_t SECONDS_TO_MILLISECONDS = 1000;
122 constexpr uint32_t RECORD_MAX_LENGTH = 20;
123 constexpr uint32_t OBSCURE_SHOW_TICKS = 1;
124 constexpr Dimension ERROR_TEXT_TOP_MARGIN = 8.0_vp;
125 constexpr Dimension ERROR_TEXT_BOTTOM_MARGIN = 8.0_vp;
126 constexpr uint32_t FIND_TEXT_ZERO_INDEX = 1;
127 constexpr char16_t OBSCURING_CHARACTER = u'•';
128 constexpr char16_t OBSCURING_CHARACTER_FOR_AR = u'*';
129 const std::string NEWLINE = "\n";
130 const std::wstring WIDE_NEWLINE = StringUtils::ToWstring(NEWLINE);
131 constexpr int32_t AUTO_FILL_FAILED = 1;
132 
133 // need to be moved to formatter
134 const std::string DIGIT_WHITE_LIST = "[0-9]";
135 const std::string PHONE_WHITE_LIST = "[\\d\\-\\+\\*\\#]+";
136 const std::string EMAIL_WHITE_LIST = "[\\w.\\@]";
137 const std::string URL_WHITE_LIST = "[a-zA-z]+://[^\\s]*";
138 const std::string SHOW_PASSWORD_SVG = "SYS_SHOW_PASSWORD_SVG";
139 const std::string HIDE_PASSWORD_SVG = "SYS_HIDE_PASSWORD_SVG";
140 constexpr int32_t DEFAULT_MODE = -1;
141 
SwapIfLarger(int32_t & a,int32_t & b)142 void SwapIfLarger(int32_t& a, int32_t& b)
143 {
144     if (a > b) {
145         std::swap(a, b);
146     }
147 }
148 
ConvertFontFamily(const std::vector<std::string> & fontFamily)149 std::string ConvertFontFamily(const std::vector<std::string>& fontFamily)
150 {
151     std::string result;
152     for (const auto& item : fontFamily) {
153         result += item;
154         result += ",";
155     }
156     result = result.substr(0, result.length() - 1);
157     return result;
158 }
159 
160 } // namespace
161 
CreateNodePaintMethod()162 RefPtr<NodePaintMethod> TextFieldPattern::CreateNodePaintMethod()
163 {
164     if (!textFieldContentModifier_) {
165         textFieldContentModifier_ = AceType::MakeRefPtr<TextFieldContentModifier>(WeakClaim(this));
166     }
167     auto textFieldOverlayModifier = AceType::DynamicCast<TextFieldOverlayModifier>(GetScrollBarOverlayModifier());
168     if (!textFieldOverlayModifier) {
169         textFieldOverlayModifier =
170             AceType::MakeRefPtr<TextFieldOverlayModifier>(WeakClaim(this), GetScrollEdgeEffect());
171         SetScrollBarOverlayModifier(textFieldOverlayModifier);
172     }
173     if (isCustomFont_) {
174         textFieldContentModifier_->SetIsCustomFont(true);
175     }
176     auto paint = MakeRefPtr<TextFieldPaintMethod>(WeakClaim(this), textFieldOverlayModifier, textFieldContentModifier_);
177     auto scrollBar = GetScrollBar();
178     if (scrollBar) {
179         paint->SetScrollBar(scrollBar);
180         if (scrollBar->NeedPaint()) {
181             textFieldOverlayModifier->SetRect(scrollBar->GetActiveRect());
182         } else if (IsNormalInlineState() && !HasFocus()) {
183             auto inlineScrollRect = scrollBar->GetActiveRect();
184             CalcInlineScrollRect(inlineScrollRect);
185             textFieldOverlayModifier->SetRect(inlineScrollRect);
186             textFieldOverlayModifier->SetOpacity(0);
187         }
188     }
189     auto host = GetHost();
190     CHECK_NULL_RETURN(host, paint);
191     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
192     CHECK_NULL_RETURN(layoutProperty, paint);
193     auto geometryNode = host->GetGeometryNode();
194     auto frameOffset = geometryNode->GetFrameOffset();
195     auto frameSize = geometryNode->GetFrameSize();
196     if (layoutProperty->GetShowErrorTextValue(false) && errorParagraph_) {
197         auto contentOffset = geometryNode->GetContentOffset();
198         auto errorTextWidth = errorParagraph_->GetLongestLine();
199         RectF boundsRect(contentOffset.GetX(), frameOffset.GetY(), errorTextWidth, errorParagraph_->GetHeight() +
200             ERROR_TEXT_TOP_MARGIN.ConvertToPx() + ERROR_TEXT_BOTTOM_MARGIN.ConvertToPx() + frameSize.Height());
201         textFieldOverlayModifier->SetBoundsRect(boundsRect);
202     } else {
203         if (NearEqual(maxFrameOffsetY_, 0.0f) && NearEqual(maxFrameHeight_, 0.0f)) {
204             maxFrameOffsetY_ = frameOffset.GetY();
205             maxFrameHeight_ = frameSize.Height();
206         }
207         maxFrameOffsetY_ = LessOrEqual(frameOffset.GetY(), maxFrameOffsetY_) ? frameOffset.GetY()
208                                                                              : maxFrameOffsetY_ - frameOffset.GetY();
209         maxFrameHeight_ = LessOrEqual(frameSize.Height(), maxFrameHeight_) ? maxFrameHeight_ : frameSize.Height();
210         RectF boundsRect(frameOffset.GetX(), maxFrameOffsetY_, frameSize.Width(), maxFrameHeight_);
211         textFieldOverlayModifier->SetBoundsRect(boundsRect);
212     }
213     return paint;
214 }
215 
CalcInlineScrollRect(Rect & inlineScrollRect)216 void TextFieldPattern::CalcInlineScrollRect(Rect& inlineScrollRect)
217 {
218     auto pipeline = PipelineContext::GetCurrentContext();
219     CHECK_NULL_VOID(pipeline);
220     auto scrollBar = GetScrollBar();
221     CHECK_NULL_VOID(scrollBar);
222     Size size(frameRect_.Width(), inlineMeasureItem_.inlineSizeHeight);
223     auto positionMode_ = scrollBar->GetPositionMode();
224     double mainSize = (positionMode_ == PositionMode::BOTTOM ? size.Width() : size.Height());
225     auto barRegionSize_ = mainSize;
226     double estimatedHeight = inlineMeasureItem_.inlineContentRectHeight;
227     double activeSize = barRegionSize_ * mainSize / estimatedHeight - scrollBar->GetOutBoundary();
228     auto offsetScale_ = 0.0f;
229     if (NearEqual(mainSize, estimatedHeight)) {
230         offsetScale_ = 0.0;
231     } else {
232         offsetScale_ = (barRegionSize_ - activeSize) / (estimatedHeight - mainSize);
233     }
234     double lastMainOffset = std::max(static_cast<double>(
235         std::max(inlineMeasureItem_.inlineLastOffsetY, contentRect_.GetY() - textRect_.GetY())), 0.0);
236     double activeMainOffset = std::min(offsetScale_ * lastMainOffset, barRegionSize_ - activeSize);
237     inlineScrollRect.SetLeft(inlineScrollRect.GetOffset().GetX() - inlineMeasureItem_.inlineScrollRectOffsetX);
238     inlineScrollRect.SetTop(activeMainOffset);
239     inlineScrollRect.SetHeight(activeSize);
240 }
241 
CreateObscuredText(int32_t len)242 std::u16string TextFieldPattern::CreateObscuredText(int32_t len)
243 {
244     std::u16string obscuredText;
245     if (Localization::GetInstance()->GetLanguage() == "ar") { // ar is the abbreviation of Arabic.
246         obscuredText = std::u16string(len, OBSCURING_CHARACTER_FOR_AR);
247     } else {
248         obscuredText = std::u16string(len, OBSCURING_CHARACTER);
249     }
250     return obscuredText;
251 }
252 
CreateDisplayText(const std::string & content,int32_t nakedCharPosition,bool needObscureText)253 std::u16string TextFieldPattern::CreateDisplayText(
254     const std::string& content, int32_t nakedCharPosition, bool needObscureText)
255 {
256     if (!content.empty() && needObscureText) {
257         auto text =
258             TextFieldPattern::CreateObscuredText(static_cast<int32_t>(StringUtils::ToWstring(content).length()));
259         if (nakedCharPosition >= 0 && nakedCharPosition < static_cast<int32_t>(content.length())) {
260             auto rawContent = StringUtils::Str8ToStr16(content);
261             text[nakedCharPosition] = rawContent[nakedCharPosition];
262         }
263         return text;
264     }
265     return StringUtils::Str8ToStr16(content);
266 }
267 
GetTextOrPlaceHolderFontSize()268 float TextFieldPattern::GetTextOrPlaceHolderFontSize()
269 {
270     auto tmpHost = GetHost();
271     CHECK_NULL_RETURN(tmpHost, 0.0f);
272     auto textFieldLayoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
273     CHECK_NULL_RETURN(textFieldLayoutProperty, 0.0f);
274     auto textFieldTheme = GetTheme();
275     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
276     Dimension fontSize;
277     if (textFieldLayoutProperty->HasFontSize() &&
278         textFieldLayoutProperty->GetFontSizeValue(Dimension()).IsNonNegative()) {
279         fontSize = textFieldLayoutProperty->GetFontSizeValue(Dimension());
280     } else {
281         return textFieldTheme ? static_cast<float>(textFieldTheme->GetFontSize().ConvertToPx())
282                               : static_cast<float>(DEFAULT_FONT.ConvertToPx());
283     }
284     return std::min(static_cast<float>(fontSize.ConvertToPx()), contentRect_.Height());
285 }
286 
TextFieldPattern()287 TextFieldPattern::TextFieldPattern() : twinklingInterval_(TWINKLING_INTERVAL_MS)
288 {
289     if (PipelineBase::GetCurrentContext() &&
290         // for normal app add version protection, enable keyboard as default start from API 10 or higher
291         PipelineBase::GetCurrentContext()->GetMinPlatformVersion() > 9) {
292         needToRequestKeyboardOnFocus_ = true;
293     }
294     contentController_ = MakeRefPtr<ContentController>(WeakClaim(this));
295     selectController_ = MakeRefPtr<TextSelectController>(WeakClaim(this));
296     selectController_->InitContentController(contentController_);
297     magnifierController_ = MakeRefPtr<MagnifierController>(WeakClaim(this));
298 }
299 
~TextFieldPattern()300 TextFieldPattern::~TextFieldPattern()
301 {
302     if (textEditingController_) {
303         textEditingController_->Clear();
304         textEditingController_->RemoveObserver(WeakClaim(this));
305     }
306     CloseSelectOverlay();
307     if (isCustomKeyboardAttached_) {
308         CloseCustomKeyboard();
309     }
310 }
311 
BeforeCreateLayoutWrapper()312 void TextFieldPattern::BeforeCreateLayoutWrapper()
313 {
314     while (!inputOperations_.empty()) {
315         auto operation = inputOperations_.front();
316         inputOperations_.pop();
317         switch (operation) {
318             case InputOperation::INSERT: {
319                 InsertValueOperation(insertValueOperations_.front());
320                 insertValueOperations_.pop();
321                 break;
322             }
323             case InputOperation::DELETE_BACKWARD: {
324                 DeleteBackwardOperation(deleteBackwardOperations_.front());
325                 deleteBackwardOperations_.pop();
326                 break;
327             }
328             case InputOperation::DELETE_FORWARD: {
329                 DeleteForwardOperation(deleteForwardOperations_.front());
330                 deleteForwardOperations_.pop();
331                 break;
332             }
333             case InputOperation::CURSOR_UP: {
334                 CursorMoveUpOperation();
335                 break;
336             }
337             case InputOperation::CURSOR_DOWN: {
338                 CursorMoveDownOperation();
339                 break;
340             }
341             case InputOperation::CURSOR_LEFT: {
342                 CursorMoveLeftOperation();
343                 break;
344             }
345             case InputOperation::CURSOR_RIGHT: {
346                 CursorMoveRightOperation();
347                 break;
348             }
349         }
350     }
351 }
352 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)353 bool TextFieldPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
354 {
355     if (config.skipMeasure || dirty->SkipMeasureContent()) {
356         return false;
357     }
358     contentRect_ = dirty->GetGeometryNode()->GetContentRect();
359     frameRect_ = dirty->GetGeometryNode()->GetFrameRect();
360     if (!inlineState_.saveState) {
361         inlineState_.saveState = true;
362         inlineState_.frameRect = frameRect_;
363     }
364     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
365     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
366     auto textFieldLayoutAlgorithm = DynamicCast<TextFieldLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
367     CHECK_NULL_RETURN(textFieldLayoutAlgorithm, false);
368     auto paragraph = textFieldLayoutAlgorithm->GetParagraph();
369     float paragraphWidth = 0.0f;
370     if (paragraph) {
371         paragraph_ = paragraph;
372         paragraphWidth = std::max(paragraph->GetLongestLine(), 0.0f);
373     }
374     if (!IsDragging()) {
375         dragParagraph_ = paragraph_;
376     }
377     auto textRect = textFieldLayoutAlgorithm->GetTextRect();
378     if (!(needToRefreshSelectOverlay_ &&
379             (!NearEqual(paragraphWidth, paragraphWidth_) || !NearEqual(textRect.GetSize(), textRect_.GetSize())))) {
380         needToRefreshSelectOverlay_ = false;
381     }
382     paragraphWidth_ = paragraphWidth;
383     textRect_ = textRect;
384 
385     if (textFieldContentModifier_) {
386         textFieldContentModifier_->ContentChange();
387     }
388 
389     parentGlobalOffset_ = textFieldLayoutAlgorithm->GetParentGlobalOffset();
390     inlineMeasureItem_ = textFieldLayoutAlgorithm->GetInlineMeasureItem();
391     auto isEditorValueChanged = FireOnTextChangeEvent();
392     UpdateCancelNode();
393     UpdateSelectController();
394     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
395     AdjustTextInReasonableArea();
396     UpdateCaretRect(isEditorValueChanged);
397     UpdateCaretInfoToController();
398     auto hostLayoutProperty =
399         dirty->GetHostNode() ? dirty->GetHostNode()->GetLayoutProperty<TextFieldLayoutProperty>() : nullptr;
400     if (hostLayoutProperty) {
401         hostLayoutProperty->ResetTextAlignChanged();
402     }
403     if (processOverlayDelayTask_) {
404         processOverlayDelayTask_();
405         processOverlayDelayTask_ = nullptr;
406     }
407     if (needToRefreshSelectOverlay_ && SelectOverlayIsOn()) {
408         StopTwinkling();
409         ProcessOverlay();
410         needToRefreshSelectOverlay_ = false;
411     }
412     if (inlineSelectAllFlag_) {
413         HandleOnSelectAll(false, true);
414         inlineSelectAllFlag_ = false;
415         showSelect_ = true;
416     }
417     if (needSelectAll_ && !isLongPress_) {
418         HandleOnSelectAll(true);
419         needSelectAll_ = false;
420     }
421     if (mouseStatus_ == MouseStatus::RELEASED) {
422         mouseStatus_ = MouseStatus::NONE;
423     }
424     StopScrollable();
425     CheckScrollable();
426     UpdateScrollBarOffset();
427     if (config.frameSizeChange) {
428         if (GetScrollBar() != nullptr) {
429             GetScrollBar()->ScheduleDisappearDelayTask();
430         }
431     }
432     return true;
433 }
434 
HasFocus() const435 bool TextFieldPattern::HasFocus() const
436 {
437     auto focusHub = GetFocusHub();
438 
439     CHECK_NULL_RETURN(focusHub, false);
440     return focusHub->IsCurrentFocus();
441 }
442 
UpdateCaretInfoToController() const443 void TextFieldPattern::UpdateCaretInfoToController() const
444 {
445     CHECK_NULL_VOID(HasFocus());
446 #if defined(ENABLE_STANDARD_INPUT)
447     auto miscTextConfig = GetMiscTextConfig();
448     CHECK_NULL_VOID(miscTextConfig.has_value());
449     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
450     MiscServices::InputMethodController::GetInstance()->OnCursorUpdate(cursorInfo);
451     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
452         StringUtils::Str8ToStr16(contentController_->GetTextValue()), selectController_->GetStartIndex(),
453         selectController_->GetEndIndex());
454     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
455         "Caret position update, left %{public}f, top %{public}f, width %{public}f, height %{public}f; "
456         "selectController_ Start "
457         "%{public}d, end %{public}d",
458         cursorInfo.left, cursorInfo.top, cursorInfo.width, cursorInfo.height, selectController_->GetStartIndex(),
459         selectController_->GetEndIndex());
460 
461 #else
462     if (HasConnection()) {
463         TextEditingValue value;
464         value.text = contentController_->GetTextValue();
465         value.hint = GetPlaceHolder();
466         value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
467         connection_->SetEditingState(value, GetInstanceId());
468     }
469 #endif
470 }
471 
472 // return: true if text rect offset will NOT be further changed by caret position
UpdateCaretRect(bool isEditorValueChanged)473 void TextFieldPattern::UpdateCaretRect(bool isEditorValueChanged)
474 {
475     auto focusHub = GetFocusHub();
476     if (IsSelected()) {
477         selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex());
478         selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex());
479         return;
480     }
481     if (focusHub && !focusHub->IsCurrentFocus() && !obscuredChange_) {
482         CloseSelectOverlay(true);
483         return;
484     }
485     selectController_->MoveCaretToContentRect(
486         selectController_->GetCaretIndex(), TextAffinity::DOWNSTREAM, isEditorValueChanged);
487 }
488 
AdjustTextInReasonableArea()489 void TextFieldPattern::AdjustTextInReasonableArea()
490 {
491     // Adjust y.
492     auto contentBottomBoundary = contentRect_.GetY() + contentRect_.GetSize().Height();
493     if (textRect_.Height() > contentRect_.Height()) {
494         if (textRect_.GetY() + textRect_.Height() < contentBottomBoundary) {
495             auto dy = contentBottomBoundary - textRect_.GetY() - textRect_.Height();
496             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
497         }
498         if (GreatNotEqual(textRect_.GetY(), contentRect_.GetY())) {
499             auto dy = textRect_.GetY() - contentRect_.GetY();
500             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() - dy));
501         }
502     } else {
503         if (textRect_.GetY() != contentRect_.GetY()) {
504             auto dy = contentRect_.GetY() - textRect_.GetY();
505             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
506         }
507     }
508 
509     // Adjust x.
510     auto contentRightBoundary = contentRect_.GetX() + contentRect_.GetSize().Width();
511     if (textRect_.Width() > contentRect_.Width()) {
512         if (textRect_.GetX() + textRect_.Width() < contentRightBoundary) {
513             auto dx = contentRightBoundary - textRect_.GetX() - textRect_.Width();
514             textRect_.SetLeft(textRect_.GetX() + dx);
515         }
516         if (GreatNotEqual(textRect_.GetX(), contentRect_.GetX())) {
517             auto dx = textRect_.GetX() - contentRect_.GetX();
518             textRect_.SetOffset(OffsetF(textRect_.GetX() - dx, textRect_.GetY()));
519         }
520     }
521 }
522 
IsTextArea() const523 bool TextFieldPattern::IsTextArea() const
524 {
525     auto tmpHost = GetHost();
526     CHECK_NULL_RETURN(tmpHost, false);
527     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
528     CHECK_NULL_RETURN(layoutProperty, true);
529     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(1) > 1 : true;
530 }
531 
UpdateSelectionOffset()532 void TextFieldPattern::UpdateSelectionOffset()
533 {
534     CHECK_NULL_VOID(IsSelected());
535     selectController_->CalculateHandleOffset();
536 }
537 
CalcCaretMetricsByPosition(int32_t extent,CaretMetricsF & caretCaretMetric,TextAffinity textAffinity)538 void TextFieldPattern::CalcCaretMetricsByPosition(
539     int32_t extent, CaretMetricsF& caretCaretMetric, TextAffinity textAffinity)
540 {
541     paragraph_->CalcCaretMetricsByPosition(extent, caretCaretMetric, textAffinity);
542     caretCaretMetric.offset.AddX(textRect_.GetX());
543     caretCaretMetric.offset.AddY(textRect_.GetY());
544 }
545 
CursorInContentRegion()546 bool TextFieldPattern::CursorInContentRegion()
547 {
548     if (IsTextArea()) {
549         return GreatOrEqual(selectController_->GetCaretRect().GetY(), contentRect_.GetY()) &&
550                LessOrEqual(selectController_->GetCaretRect().GetY() + GetTextOrPlaceHolderFontSize(),
551                    contentRect_.GetY() + contentRect_.Height());
552     }
553     auto theme = GetTheme();
554     CHECK_NULL_RETURN(theme, false);
555     return GreatOrEqual(selectController_->GetCaretRect().GetX(), contentRect_.GetX()) &&
556            LessOrEqual(selectController_->GetCaretRect().GetX() + theme->GetCursorWidth().ConvertToPx(),
557                contentRect_.GetX() + contentRect_.Width());
558 }
559 
OffsetInContentRegion(const Offset & offset)560 bool TextFieldPattern::OffsetInContentRegion(const Offset& offset)
561 {
562     // real content region will minus basic padding on left and right
563     return GreatOrEqual(offset.GetX(), contentRect_.GetX()) &&
564            LessOrEqual(offset.GetX(), contentRect_.GetX() + contentRect_.Width());
565 }
566 
OnScrollEndCallback()567 void TextFieldPattern::OnScrollEndCallback()
568 {
569     auto scrollBar = GetScrollBar();
570     if (scrollBar) {
571         scrollBar->ScheduleDisappearDelayTask();
572     }
573     OnParentScrollStartOrEnd(true);
574 }
575 
OnTextAreaScroll(float offset)576 void TextFieldPattern::OnTextAreaScroll(float offset)
577 {
578     if (!IsTextArea() || textRect_.Height() <= contentRect_.Height()) {
579         return;
580     }
581     if (textRect_.GetY() + offset > contentRect_.GetY()) {
582         offset = contentRect_.GetY() - textRect_.GetY();
583     } else if (textRect_.GetY() + textRect_.Height() + offset < contentRect_.GetY() + contentRect_.Height()) {
584         offset = contentRect_.GetY() + contentRect_.Height() - textRect_.GetY() - textRect_.Height();
585     }
586     currentOffset_ = textRect_.GetY() + offset;
587     textRect_.SetOffset(OffsetF(textRect_.GetX(), currentOffset_));
588     UpdateHandlesOffsetOnScroll(offset);
589     UpdateScrollBarOffset();
590 }
591 
OnTextInputScroll(float offset)592 void TextFieldPattern::OnTextInputScroll(float offset)
593 {
594     if (IsTextArea() || textRect_.Width() <= contentRect_.Width()) {
595         return;
596     }
597     if (textRect_.GetX() + offset > contentRect_.GetX()) {
598         offset = contentRect_.GetX() - textRect_.GetX();
599     } else if (textRect_.GetX() + textRect_.Width() + offset < contentRect_.GetX() + contentRect_.Width()) {
600         offset = contentRect_.GetX() + contentRect_.Width() - textRect_.GetX() - textRect_.Width();
601     }
602     currentOffset_ = textRect_.GetX() + offset;
603     textRect_.SetOffset(OffsetF(currentOffset_, textRect_.GetY()));
604     UpdateHandlesOffsetOnScroll(offset);
605     auto tmpHost = GetHost();
606     CHECK_NULL_VOID(tmpHost);
607     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
608 }
609 
ConvertTouchOffsetToCaretPosition(const Offset & localOffset)610 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPosition(const Offset& localOffset)
611 {
612     CHECK_NULL_RETURN(paragraph_, 0);
613     return paragraph_->GetGlyphIndexByCoordinate(localOffset);
614 }
615 
ConvertTouchOffsetToCaretPositionNG(const Offset & localOffset)616 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPositionNG(const Offset& localOffset)
617 {
618     CHECK_NULL_RETURN(paragraph_, 0);
619     auto offset = localOffset - Offset(textRect_.GetX(), textRect_.GetY());
620     return paragraph_->GetGlyphIndexByCoordinate(offset);
621 }
622 
623 #if defined(IOS_PLATFORM)
GetGlobalOffset() const624 Offset TextFieldPattern::GetGlobalOffset() const
625 {
626     Offset offset;
627     auto host = GetHost();
628     CHECK_NULL_RETURN(host, {});
629     auto pipeline = PipelineContext::GetCurrentContext();
630     CHECK_NULL_RETURN(pipeline, {});
631     auto rootOffset = pipeline->GetRootRect().GetOffset();
632     auto globalOffset = host->GetPaintRectOffset() - rootOffset;
633     offset = Offset(globalOffset.GetX(), globalOffset.GetY());
634     return offset;
635 }
636 
GetEditingBoxY() const637 double TextFieldPattern::GetEditingBoxY() const
638 {
639     return GetGlobalOffset().GetY() + frameRect_.Height();
640 };
641 
GetEditingBoxTopY() const642 double TextFieldPattern::GetEditingBoxTopY() const
643 {
644     return GetGlobalOffset().GetY();
645 };
646 
GetEditingBoxModel() const647 bool TextFieldPattern::GetEditingBoxModel() const
648 {
649     bool isDeclarative = false;
650     auto pipeline = PipelineContext::GetCurrentContext();
651     if (pipeline && pipeline->GetIsDeclarative()) {
652         isDeclarative = true;
653     }
654     return isDeclarative;
655 };
656 #endif
657 
HandleFocusEvent()658 void TextFieldPattern::HandleFocusEvent()
659 {
660     isFocusedBeforeClick_ = true;
661     focusIndex_ = FocuseIndex::TEXT;
662     auto host = GetHost();
663     CHECK_NULL_VOID(host);
664     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d on focus", host->GetId());
665     auto context = PipelineContext::GetCurrentContext();
666     CHECK_NULL_VOID(context);
667     auto globalOffset = host->GetPaintRectOffset() - context->GetRootRect().GetOffset();
668     UpdateTextFieldManager(Offset(globalOffset.GetX(), globalOffset.GetY()), frameRect_.Height());
669     needToRequestKeyboardInner_ = !isLongPress_ && (dragRecipientStatus_ != DragStatus::DRAGGING);
670     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
671     CHECK_NULL_VOID(paintProperty);
672     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
673     CHECK_NULL_VOID(layoutProperty);
674     auto isSelectAll = layoutProperty->GetSelectAllValueValue(false);
675     if (isSelectAll && !contentController_->IsEmpty()) {
676         needSelectAll_ = true;
677     }
678     if (IsNormalInlineState()) {
679         ApplyInlineStates();
680         inlineFocusState_ = true;
681         if (contentController_->IsEmpty()) {
682             StartTwinkling();
683         } else {
684             inlineSelectAllFlag_ = blurReason_ != BlurReason::WINDOW_BLUR;
685         }
686     } else {
687         StartTwinkling();
688     }
689     NotifyOnEditChanged(true);
690     auto visible = layoutProperty->GetShowErrorTextValue(false);
691     if (!visible && layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType() &&
692         !IsNormalInlineState()) {
693         auto renderContext = host->GetRenderContext();
694         auto textFieldTheme = GetTheme();
695         CHECK_NULL_VOID(textFieldTheme);
696         auto radius = textFieldTheme->GetBorderRadiusSize();
697         underlineColor_ = textFieldTheme->GetUnderlineTypingColor();
698         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
699         renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
700     }
701     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
702                                                                                  : PROPERTY_UPDATE_MEASURE);
703 }
704 
HandleSetSelection(int32_t start,int32_t end,bool showHandle)705 void TextFieldPattern::HandleSetSelection(int32_t start, int32_t end, bool showHandle)
706 {
707     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleSetSelection %{public}d, %{public}d", start, end);
708     StopTwinkling();
709     UpdateSelection(start, end);
710     if (showHandle) {
711         ProcessOverlay();
712     } else {
713         CloseSelectOverlay();
714     }
715     UpdateCaretInfoToController();
716     auto host = GetHost();
717     CHECK_NULL_VOID(host);
718     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
719 }
720 
HandleExtendAction(int32_t action)721 void TextFieldPattern::HandleExtendAction(int32_t action)
722 {
723     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleExtendAction %{public}d", action);
724     switch (action) {
725         case ACTION_SELECT_ALL: {
726             HandleOnSelectAll(false);
727             break;
728         }
729         case ACTION_CUT: {
730             HandleOnCut();
731             break;
732         }
733         case ACTION_COPY: {
734             HandleOnCopy();
735             break;
736         }
737         case ACTION_PASTE: {
738             HandleOnPaste();
739             break;
740         }
741         default: {
742             break;
743         }
744     }
745 }
746 
CursorMove(CaretMoveIntent direction)747 void TextFieldPattern::CursorMove(CaretMoveIntent direction)
748 {
749     switch (direction) {
750         case CaretMoveIntent::Left: {
751             CursorMoveLeft();
752             break;
753         }
754         case CaretMoveIntent::Right: {
755             CursorMoveRight();
756             break;
757         }
758         case CaretMoveIntent::Up: {
759             CursorMoveUp();
760             break;
761         }
762         case CaretMoveIntent::Down: {
763             CursorMoveDown();
764             break;
765         }
766         case CaretMoveIntent::LineBegin: {
767             CursorMoveLineBegin();
768             break;
769         }
770         case CaretMoveIntent::LineEnd: {
771             CursorMoveLineEnd();
772             break;
773         }
774         case CaretMoveIntent::LeftWord: {
775             CursorMoveLeftWord();
776             break;
777         }
778         case CaretMoveIntent::RightWord: {
779             CursorMoveRightWord();
780             break;
781         }
782         case CaretMoveIntent::ParagraghBegin: {
783             CursorMoveToParagraphBegin();
784             break;
785         }
786         case CaretMoveIntent::ParagraghEnd: {
787             CursorMoveToParagraphEnd();
788             break;
789         }
790         case CaretMoveIntent::Home: {
791             CursorMoveHome();
792             break;
793         }
794         case CaretMoveIntent::End: {
795             CursorMoveEnd();
796             break;
797         }
798     }
799 }
800 
HandleSelect(CaretMoveIntent direction)801 void TextFieldPattern::HandleSelect(CaretMoveIntent direction)
802 {
803     CloseSelectOverlay();
804     switch (direction) {
805         case CaretMoveIntent::Left: {
806             HandleSelectionLeft();
807             break;
808         }
809         case CaretMoveIntent::Right: {
810             HandleSelectionRight();
811             break;
812         }
813         case CaretMoveIntent::Up: {
814             HandleSelectionUp();
815             break;
816         }
817         case CaretMoveIntent::Down: {
818             HandleSelectionDown();
819             break;
820         }
821         case CaretMoveIntent::LineBegin: {
822             HandleSelectionLineBegin();
823             break;
824         }
825         case CaretMoveIntent::LineEnd: {
826             HandleSelectionLineEnd();
827             break;
828         }
829         case CaretMoveIntent::LeftWord: {
830             HandleSelectionLeftWord();
831             break;
832         }
833         case CaretMoveIntent::RightWord: {
834             HandleSelectionRightWord();
835             break;
836         }
837         case CaretMoveIntent::Home: {
838             HandleSelectionHome();
839             break;
840         }
841         case CaretMoveIntent::End: {
842             HandleSelectionEnd();
843             break;
844         }
845         // SelectionParagraghBegin/SelectionParagraghEnd not supported yet
846         default: {
847             LOGW("Unsupported select operation for text field");
848         }
849     }
850     UpdateRecordCaretIndex(
851         std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
852 }
853 
InitDisableColor()854 void TextFieldPattern::InitDisableColor()
855 {
856     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
857     CHECK_NULL_VOID(layoutProperty);
858     auto theme = GetTheme();
859     CHECK_NULL_VOID(theme);
860     if (layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType()) {
861         underlineWidth_ = UNDERLINE_WIDTH;
862         underlineColor_ = IsDisabled() ? theme->GetDisableUnderlineColor() : theme->GetUnderlineColor();
863         SaveUnderlineStates();
864     }
865     layoutProperty->UpdateIsDisabled(IsDisabled());
866 }
867 
InitFocusEvent()868 void TextFieldPattern::InitFocusEvent()
869 {
870     CHECK_NULL_VOID(!focusEventInitialized_);
871     auto host = GetHost();
872     CHECK_NULL_VOID(host);
873     auto focusHub = host->GetOrCreateFocusHub();
874     auto focusTask = [weak = WeakClaim(this)]() {
875         auto pattern = weak.Upgrade();
876         if (pattern) {
877             pattern->HandleFocusEvent();
878         }
879     };
880     focusHub->SetOnFocusInternal(focusTask);
881     auto blurTask = [weak = WeakClaim(this)]() {
882         auto pattern = weak.Upgrade();
883         CHECK_NULL_VOID(pattern);
884         pattern->HandleBlurEvent();
885     };
886     focusHub->SetOnBlurInternal(blurTask);
887 
888     auto keyTask = [weak = WeakClaim(this)](const KeyEvent& keyEvent) -> bool {
889         auto pattern = weak.Upgrade();
890         CHECK_NULL_RETURN(pattern, false);
891         return pattern->OnKeyEvent(keyEvent);
892     };
893     focusHub->SetOnKeyEventInternal(keyTask);
894 
895     auto getInnerPaintRectCallback = [weak = WeakClaim(this)](RoundRect& paintRect) {
896         auto pattern = weak.Upgrade();
897         if (pattern) {
898             pattern->GetInnerFocusPaintRect(paintRect);
899         }
900     };
901     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
902     auto windowFocusTask = [weak = WeakClaim(this)]() {
903         auto pattern = weak.Upgrade();
904         CHECK_NULL_VOID(pattern);
905         if (!pattern->HasFocus()) {
906             pattern->HandleBlurEvent();
907         }
908     };
909     auto context = PipelineContext::GetCurrentContext();
910     CHECK_NULL_VOID(context);
911     context->SetOnWindowFocused(windowFocusTask);
912     focusEventInitialized_ = true;
913 }
914 
CheckBlurReason()915 bool TextFieldPattern::CheckBlurReason()
916 {
917     auto curFocusHub = GetFocusHub();
918     CHECK_NULL_RETURN(curFocusHub, false);
919     auto curBlurReason = curFocusHub->GetBlurReason();
920     if (curBlurReason == BlurReason::FRAME_DESTROY) {
921         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextFieldPattern CheckBlurReason, Close Keyboard.");
922         return true;
923     }
924     return false;
925 }
926 
UpdateBlurReason()927 void TextFieldPattern::UpdateBlurReason()
928 {
929     auto focusHub = GetFocusHub();
930     CHECK_NULL_VOID(focusHub);
931     blurReason_ = focusHub->GetBlurReason();
932 }
933 
ProcNormalInlineStateInBlurEvent()934 void TextFieldPattern::ProcNormalInlineStateInBlurEvent()
935 {
936     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
937     CHECK_NULL_VOID(layoutProperty);
938     if (IsNormalInlineState()) {
939         if (IsTextArea() && isTextInput_) {
940             layoutProperty->UpdateMaxLines(1);
941             layoutProperty->UpdatePlaceholderMaxLines(1);
942         }
943         inlineSelectAllFlag_ = false;
944         inlineFocusState_ = false;
945         RestorePreInlineStates();
946     }
947 }
948 
HandleBlurEvent()949 void TextFieldPattern::HandleBlurEvent()
950 {
951     auto host = GetHost();
952     CHECK_NULL_VOID(host);
953     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d OnBlur", host->GetId());
954     auto context = PipelineContext::GetCurrentContext();
955     CHECK_NULL_VOID(context);
956     UpdateBlurReason();
957     if (!context->GetOnFoucs()) {
958         needToRequestKeyboardInner_ = false;
959         if ((customKeyboardBuilder_ && isCustomKeyboardAttached_)) {
960             CloseKeyboard(true);
961             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextFieldPattern Blur, Close Keyboard.");
962         }
963         StopTwinkling();
964         return;
965     }
966     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
967     if (textFieldManager) {
968         textFieldManager->ClearOnFocusTextField();
969     }
970     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
971     CHECK_NULL_VOID(layoutProperty);
972     auto textFieldTheme = GetTheme();
973     CHECK_NULL_VOID(textFieldTheme);
974     auto visible = layoutProperty->GetShowErrorTextValue(false);
975     if (!visible && layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType()) {
976         auto renderContext = host->GetRenderContext();
977         renderContext->UpdateBorderRadius(borderRadius_);
978         underlineColor_ = textFieldTheme->GetUnderlineColor();
979         underlineWidth_ = UNDERLINE_WIDTH;
980     }
981     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
982     CHECK_NULL_VOID(paintProperty);
983     ProcNormalInlineStateInBlurEvent();
984     needToRequestKeyboardInner_ = false;
985     isLongPress_ = false;
986     isFocusedBeforeClick_ = false;
987     UpdateShowMagnifier();
988     CloseSelectOverlay(!isKeyboardClosedByUser_);
989     StopTwinkling();
990     if ((customKeyboardBuilder_ && isCustomKeyboardAttached_)) {
991         CloseKeyboard(true);
992         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextFieldPattern Blur, Close Keyboard.");
993     }
994 #ifndef OHOS_PLATFORM
995     if (HasConnection()) {
996         CloseKeyboard(true);
997     }
998 #endif
999     selectController_->UpdateCaretIndex(selectController_->GetCaretIndex());
1000     NotifyOnEditChanged(false);
1001     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1002 }
1003 
OnKeyEvent(const KeyEvent & event)1004 bool TextFieldPattern::OnKeyEvent(const KeyEvent& event)
1005 {
1006     if (event.code == KeyCode::KEY_TAB && isFocusedBeforeClick_ && !contentController_->IsEmpty()) {
1007         isFocusedBeforeClick_ = false;
1008         HandleOnSelectAll(true);
1009     }
1010     auto pipeline = PipelineContext::GetCurrentContext();
1011     CHECK_NULL_RETURN(pipeline, false);
1012     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
1013     if (event.code == KeyCode::KEY_TAB && HasFocus() && !needToRequestKeyboardOnFocus_ && needToRequestKeyboardInner_ &&
1014         textFieldManager->GetImeShow()) {
1015         RequestKeyboard(false, true, true);
1016     }
1017     return TextInputClient::HandleKeyEvent(event);
1018 }
1019 
HandleOnEscape()1020 bool TextFieldPattern::HandleOnEscape()
1021 {
1022     CloseSelectOverlay(true);
1023     return false;
1024 }
1025 
HandleOnTab(bool backward)1026 bool TextFieldPattern::HandleOnTab(bool backward)
1027 {
1028     return backward ? UpdateFocusBackward() : UpdateFocusForward();
1029 }
1030 
HandleOnUndoAction()1031 void TextFieldPattern::HandleOnUndoAction()
1032 {
1033     if (operationRecords_.empty()) {
1034         return;
1035     }
1036     auto value = operationRecords_.back();
1037     operationRecords_.pop_back();
1038     if (redoOperationRecords_.size() >= RECORD_MAX_LENGTH) {
1039         redoOperationRecords_.erase(redoOperationRecords_.begin());
1040     }
1041     redoOperationRecords_.push_back(value);
1042     if (operationRecords_.empty()) {
1043         FireEventHubOnChange("");
1044         ClearEditingValue();
1045         return;
1046     }
1047     auto textEditingValue = operationRecords_.back(); // record应该包含光标、select状态、文本
1048     contentController_->SetTextValue(textEditingValue.text);
1049     selectController_->MoveCaretToContentRect(textEditingValue.caretPosition, TextAffinity::DOWNSTREAM);
1050     auto tmpHost = GetHost();
1051     CHECK_NULL_VOID(tmpHost);
1052     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1053 }
1054 
HandleOnRedoAction()1055 void TextFieldPattern::HandleOnRedoAction()
1056 {
1057     if (redoOperationRecords_.empty()) {
1058         return;
1059     }
1060     auto textEditingValue = redoOperationRecords_.back();
1061     redoOperationRecords_.pop_back();
1062     operationRecords_.push_back(textEditingValue);
1063     contentController_->SetTextValue(textEditingValue.text);
1064     selectController_->UpdateCaretIndex(textEditingValue.caretPosition);
1065     auto tmpHost = GetHost();
1066     CHECK_NULL_VOID(tmpHost);
1067     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1068 }
1069 
HandleOnSelectAll(bool isKeyEvent,bool inlineStyle)1070 void TextFieldPattern::HandleOnSelectAll(bool isKeyEvent, bool inlineStyle)
1071 {
1072     if (SystemProperties::GetDebugEnabled()) {
1073         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextFieldPattern::HandleOnSelectAll");
1074     }
1075     auto textSize = static_cast<int32_t>(contentController_->GetWideText().length());
1076     if (inlineStyle) {
1077         if (contentController_->GetWideText().rfind(L".") < textSize - FIND_TEXT_ZERO_INDEX) {
1078             textSize = contentController_->GetWideText().rfind(L".");
1079         }
1080         UpdateSelection(0, textSize);
1081     } else {
1082         UpdateSelection(0, textSize);
1083     }
1084     if (IsSelected()) {
1085         SetIsSingleHandle(false);
1086     }
1087     ResetObscureTickCountDown();
1088     auto tmpHost = GetHost();
1089     CHECK_NULL_VOID(tmpHost);
1090     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1091     selectController_->MoveSecondHandleToContentRect(textSize);
1092     StopTwinkling();
1093     showSelect_ = true;
1094     if (isKeyEvent || inlineSelectAllFlag_ || IsUsingMouse()) {
1095         CloseSelectOverlay(true);
1096         if (IsSelected()) {
1097             PushSelectedByMouseInfoToManager();
1098         }
1099         return;
1100     }
1101     ProcessOverlay(true, true);
1102 }
1103 
HandleOnCopy(bool isUsingExternalKeyboard)1104 void TextFieldPattern::HandleOnCopy(bool isUsingExternalKeyboard)
1105 {
1106     if (SystemProperties::GetDebugEnabled()) {
1107         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextFieldPattern::HandleOnCopy");
1108     }
1109     CHECK_NULL_VOID(clipboard_);
1110     auto tmpHost = GetHost();
1111     CHECK_NULL_VOID(tmpHost);
1112     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
1113     CHECK_NULL_VOID(layoutProperty);
1114     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) == CopyOptions::None) {
1115         return;
1116     }
1117     if (!IsSelected() || IsInPasswordMode()) {
1118         return;
1119     }
1120     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "On copy, text selector %{public}s", selectController_->ToString().c_str());
1121     auto value =
1122         contentController_->GetSelectedValue(selectController_->GetStartIndex(), selectController_->GetEndIndex());
1123     if (value.empty()) {
1124         return;
1125     }
1126     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) != CopyOptions::None) {
1127         clipboard_->SetData(value, layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed));
1128     }
1129 
1130     if (!IsUsingMouse() && !isUsingExternalKeyboard) {
1131         selectController_->MoveCaretToContentRect(selectController_->GetSecondHandleIndex(), TextAffinity::UPSTREAM);
1132         StartTwinkling();
1133     }
1134     CloseSelectOverlay(true);
1135     auto host = GetHost();
1136     CHECK_NULL_VOID(host);
1137     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1138     CHECK_NULL_VOID(eventHub);
1139     eventHub->FireOnCopy(value);
1140 }
1141 
HandleOnPaste()1142 void TextFieldPattern::HandleOnPaste()
1143 {
1144     if (SystemProperties::GetDebugEnabled()) {
1145         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextFieldPattern::HandleOnPaste");
1146     }
1147     auto pasteCallback = [weak = WeakClaim(this)](const std::string& data) {
1148         if (data.empty()) {
1149             return;
1150         }
1151         auto textfield = weak.Upgrade();
1152         auto host = textfield->GetHost();
1153         CHECK_NULL_VOID(host);
1154         auto eventHub = host->GetEventHub<TextFieldEventHub>();
1155         CHECK_NULL_VOID(eventHub);
1156         TextCommonEvent event;
1157         eventHub->FireOnPasteWithEvent(data, event);
1158         if (event.IsPreventDefault()) {
1159             textfield->CloseSelectOverlay(true);
1160             textfield->selectController_->ResetHandles();
1161             textfield->StartTwinkling();
1162             return;
1163         }
1164 
1165         CHECK_NULL_VOID(textfield);
1166         auto tmpHost = textfield->GetHost();
1167         CHECK_NULL_VOID(tmpHost);
1168         auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
1169         CHECK_NULL_VOID(layoutProperty);
1170         int32_t start = 0;
1171         int32_t end = 0;
1172         if (textfield->IsSelected()) {
1173             start = textfield->selectController_->GetStartIndex();
1174             end = textfield->selectController_->GetEndIndex();
1175         } else {
1176             start = textfield->selectController_->GetCaretIndex();
1177             end = textfield->selectController_->GetCaretIndex();
1178         }
1179         std::wstring pasteData = StringUtils::ToWstring(data);
1180         auto originLength = static_cast<int32_t>(textfield->contentController_->GetWideText().length());
1181         textfield->contentController_->ReplaceSelectedValue(start, end, StringUtils::ToString(pasteData));
1182         auto caretMoveLength =
1183             static_cast<int32_t>(textfield->contentController_->GetWideText().length()) - originLength;
1184         auto newCaretPosition = std::clamp(std::max(start, end) + caretMoveLength, 0,
1185             static_cast<int32_t>(textfield->contentController_->GetWideText().length()));
1186         textfield->ResetObscureTickCountDown();
1187         textfield->selectController_->UpdateCaretIndex(newCaretPosition);
1188         textfield->UpdateEditingValueToRecord();
1189         if (textfield->IsTextArea() && layoutProperty->HasMaxLength()) {
1190             textfield->HandleCounterBorder();
1191         }
1192         auto maxlength = textfield->GetMaxLength();
1193         textfield->HandleInputCounterBorder(caretMoveLength, maxlength);
1194         textfield->CloseSelectOverlay(true);
1195         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1196         textfield->StartTwinkling();
1197     };
1198     CHECK_NULL_VOID(clipboard_);
1199     clipboard_->GetData(pasteCallback);
1200 }
1201 
HandleOnCameraInput()1202 void TextFieldPattern::HandleOnCameraInput()
1203 {
1204 #if defined(ENABLE_STANDARD_INPUT)
1205     if (textChangeListener_ == nullptr) {
1206         textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
1207     }
1208     auto inputMethod = MiscServices::InputMethodController::GetInstance();
1209     if (!inputMethod) {
1210         return;
1211     }
1212 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
1213     if (imeShown_) {
1214         inputMethod->StartInputType(MiscServices::InputType::CAMERA_INPUT);
1215     } else {
1216         auto optionalTextConfig = GetMiscTextConfig();
1217         CHECK_NULL_VOID(optionalTextConfig.has_value());
1218         MiscServices::TextConfig textConfig = optionalTextConfig.value();
1219         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnCameraInput set calling window id is : %{public}u",
1220             textConfig.windowId);
1221 #ifdef WINDOW_SCENE_SUPPORTED
1222         auto systemWindowId = GetSCBSystemWindowId();
1223         if (systemWindowId) {
1224             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "windowId From %{public}u to %{public}u.", textConfig.windowId,
1225                 systemWindowId);
1226             textConfig.windowId = systemWindowId;
1227         }
1228 #endif
1229         inputMethod->Attach(textChangeListener_, false, textConfig);
1230         inputMethod->StartInputType(MiscServices::InputType::CAMERA_INPUT);
1231         inputMethod->ShowTextInput();
1232     }
1233 #endif
1234 #endif
1235 }
1236 
StripNextLine(std::wstring & data)1237 void TextFieldPattern::StripNextLine(std::wstring& data)
1238 {
1239     CHECK_NULL_VOID(!(data.empty() || IsTextArea()));
1240     std::wstring result;
1241     bool dataChanged = false;
1242     int32_t dataPtr = 0;
1243     while (dataPtr < static_cast<int32_t>(data.length())) {
1244         if (data[dataPtr] != WIDE_NEWLINE[0]) {
1245             result += data[dataPtr];
1246         } else {
1247             dataChanged = true;
1248         }
1249         dataPtr++;
1250     }
1251     CHECK_NULL_VOID(dataChanged);
1252     data = result;
1253 }
1254 
HandleOnCut()1255 void TextFieldPattern::HandleOnCut()
1256 {
1257 #if !defined(PREVIEW)
1258     CHECK_NULL_VOID(clipboard_);
1259 #endif
1260     auto tmpHost = GetHost();
1261     CHECK_NULL_VOID(tmpHost);
1262     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
1263     CHECK_NULL_VOID(layoutProperty);
1264 
1265     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) == CopyOptions::None) {
1266         return;
1267     }
1268     auto start = selectController_->GetStartIndex();
1269     auto end = selectController_->GetEndIndex();
1270     SwapIfLarger(start, end);
1271     if (!IsSelected() || IsInPasswordMode()) {
1272         return;
1273     }
1274     auto selectedText = contentController_->GetSelectedValue(start, end);
1275     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) != CopyOptions::None) {
1276         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Cut value is %{private}s", selectedText.c_str());
1277         clipboard_->SetData(selectedText, layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed));
1278     }
1279     contentController_->erase(start, end - start);
1280     UpdateSelection(start);
1281     CloseSelectOverlay(true);
1282     StartTwinkling();
1283     UpdateEditingValueToRecord();
1284 
1285     auto host = GetHost();
1286     CHECK_NULL_VOID(host);
1287     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1288     CHECK_NULL_VOID(eventHub);
1289     eventHub->FireOnCut(selectedText);
1290     FireEventHubOnChange(contentController_->GetTextValue());
1291     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
1292                                                                                  : PROPERTY_UPDATE_MEASURE);
1293 }
1294 
UpdateSelection(int32_t both)1295 void TextFieldPattern::UpdateSelection(int32_t both)
1296 {
1297     UpdateSelection(both, both);
1298 }
1299 
UpdateSelection(int32_t start,int32_t end)1300 void TextFieldPattern::UpdateSelection(int32_t start, int32_t end)
1301 {
1302     auto startIndex = std::min(start, end);
1303     auto endIndex = std::max(start, end);
1304     startIndex = std::clamp(startIndex, 0, static_cast<int32_t>(contentController_->GetWideText().length()));
1305     endIndex = std::clamp(endIndex, 0, static_cast<int32_t>(contentController_->GetWideText().length()));
1306     if (startIndex != selectController_->GetStartIndex() || endIndex != selectController_->GetEndIndex()) {
1307         selectController_->UpdateHandleIndex(startIndex, endIndex);
1308     }
1309 }
1310 
FireOnSelectionChange(int32_t start,int32_t end)1311 void TextFieldPattern::FireOnSelectionChange(int32_t start, int32_t end)
1312 {
1313     auto host = GetHost();
1314     CHECK_NULL_VOID(host);
1315     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1316     eventHub->FireOnSelectionChange(start, end);
1317 }
1318 
FireEventHubOnChange(const std::string & text)1319 void TextFieldPattern::FireEventHubOnChange(const std::string& text)
1320 {
1321     auto host = GetHost();
1322     CHECK_NULL_VOID(host);
1323     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1324     CHECK_NULL_VOID(layoutProperty);
1325     if (!layoutProperty->GetNeedFireOnChangeValue(false)) {
1326         return;
1327     }
1328     auto textFieldTheme = GetTheme();
1329     CHECK_NULL_VOID(textFieldTheme);
1330     auto visible = layoutProperty->GetShowErrorTextValue(false);
1331     if (!visible && layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType()) {
1332         underlineColor_ = textFieldTheme->GetUnderlineTypingColor();
1333         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
1334     }
1335     if (IsTextArea() && layoutProperty->HasMaxLength()) {
1336         HandleCounterBorder();
1337     }
1338 
1339     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1340     CHECK_NULL_VOID(eventHub);
1341     eventHub->FireOnChange(text);
1342 }
1343 
HandleTouchEvent(const TouchEventInfo & info)1344 void TextFieldPattern::HandleTouchEvent(const TouchEventInfo& info)
1345 {
1346     auto touchType = info.GetTouches().front().GetTouchType();
1347     if (touchType == TouchType::UP) {
1348         RequestKeyboardAfterLongPress();
1349     }
1350     if (SelectOverlayIsOn() && !isTouchCaret_) {
1351         return;
1352     }
1353 
1354     if (touchType == TouchType::DOWN) {
1355         HandleTouchDown(info.GetTouches().front().GetLocalLocation());
1356     } else if (touchType == TouchType::UP) {
1357         HandleTouchUp();
1358     } else if (touchType == TouchType::MOVE) {
1359         if (!isUsingMouse_) {
1360             HandleTouchMove(info);
1361         }
1362     }
1363 }
1364 
HandleTouchDown(const Offset & offset)1365 void TextFieldPattern::HandleTouchDown(const Offset& offset)
1366 {
1367     if (HasStateStyle(UI_STATE_PRESSED)) {
1368         return;
1369     }
1370     if (enableTouchAndHoverEffect_ && !isMousePressed_) {
1371         auto lastCaretIndex = selectController_->GetCaretIndex();
1372         auto lastCaretRect = selectController_->GetCaretRect();
1373         isTouchCaret_ = RepeatClickCaret(offset, lastCaretIndex, lastCaretRect);
1374         auto textfieldPaintProperty = GetPaintProperty<TextFieldPaintProperty>();
1375         CHECK_NULL_VOID(textfieldPaintProperty);
1376         auto tmpHost = GetHost();
1377         CHECK_NULL_VOID(tmpHost);
1378         auto renderContext = tmpHost->GetRenderContext();
1379         auto textFieldTheme = GetTheme();
1380         CHECK_NULL_VOID(textFieldTheme);
1381         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1382         CHECK_NULL_VOID(layoutProperty);
1383         if (layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType() && !IsNormalInlineState()) {
1384             auto radius = textFieldTheme->GetBorderRadiusSize();
1385             renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
1386         }
1387         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1388     }
1389 }
1390 
HandleTouchUp()1391 void TextFieldPattern::HandleTouchUp()
1392 {
1393     if (isTouchCaret_) {
1394         isTouchCaret_ = false;
1395         CloseSelectOverlay(true);
1396         CheckScrollable();
1397     }
1398     if (isMousePressed_) {
1399         isMousePressed_ = false;
1400     }
1401     if (GetShowMagnifier()) {
1402         UpdateShowMagnifier();
1403     }
1404     if (enableTouchAndHoverEffect_ && !HasStateStyle(UI_STATE_PRESSED)) {
1405         auto tmpHost = GetHost();
1406         CHECK_NULL_VOID(tmpHost);
1407         auto renderContext = tmpHost->GetRenderContext();
1408         if (!isOnHover_) {
1409             auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1410             CHECK_NULL_VOID(layoutProperty);
1411             if (layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType() && !IsNormalInlineState()) {
1412                 renderContext->UpdateBorderRadius(borderRadius_);
1413             }
1414             if (layoutProperty->GetShowUnderlineValue(false) && HasFocus() && IsUnspecifiedOrTextType() &&
1415                 !IsNormalInlineState()) {
1416                 auto textFieldTheme = GetTheme();
1417                 CHECK_NULL_VOID(textFieldTheme);
1418                 auto radius = textFieldTheme->GetBorderRadiusSize();
1419                 renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
1420             }
1421         }
1422     }
1423 }
1424 
HandleTouchMove(const TouchEventInfo & info)1425 void TextFieldPattern::HandleTouchMove(const TouchEventInfo& info)
1426 {
1427     if (isTouchCaret_) {
1428         UpdateCaretByTouchMove(info);
1429     }
1430 }
1431 
UpdateCaretByTouchMove(const TouchEventInfo & info)1432 void TextFieldPattern::UpdateCaretByTouchMove(const TouchEventInfo& info)
1433 {
1434     scrollable_ = false;
1435     SetScrollEnable(scrollable_);
1436     selectController_->UpdateCaretInfoByOffset(info.GetTouches().front().GetLocalLocation());
1437     auto host = GetHost();
1438     CHECK_NULL_VOID(host);
1439     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1440 }
1441 
InitDragEvent()1442 void TextFieldPattern::InitDragEvent()
1443 {
1444     auto host = GetHost();
1445     CHECK_NULL_VOID(host);
1446     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1447     CHECK_NULL_VOID(layoutProperty);
1448     if (!IsInPasswordMode() && layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None &&
1449         host->IsDraggable()) {
1450         InitDragDropEvent();
1451     } else {
1452         ClearDragDropEvent();
1453         InitDragDropEventWithOutDragStart();
1454     }
1455     AddDragFrameNodeToManager(host);
1456 }
1457 
GetThumbnailCallback()1458 std::function<void(Offset)> TextFieldPattern::GetThumbnailCallback()
1459 {
1460     auto callback = [weak = WeakClaim(this)](const Offset& point) {
1461         auto pattern = weak.Upgrade();
1462         CHECK_NULL_VOID(pattern);
1463         auto frameNode = pattern->GetHost();
1464         CHECK_NULL_VOID(frameNode);
1465         if (pattern->BetweenSelectedPosition(point)) {
1466             pattern->dragNode_ = TextDragPattern::CreateDragNode(frameNode);
1467             FrameNode::ProcessOffscreenNode(pattern->dragNode_);
1468         }
1469         auto gestureHub = frameNode->GetOrCreateGestureEventHub();
1470         CHECK_NULL_VOID(gestureHub);
1471         gestureHub->SetPixelMap(nullptr);
1472     };
1473     return callback;
1474 }
1475 
OnDragStart()1476 std::function<DragDropInfo(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragStart()
1477 {
1478     auto onDragStart = [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event,
1479                            const std::string& extraParams) -> NG::DragDropInfo {
1480         NG::DragDropInfo itemInfo;
1481         auto pattern = weakPtr.Upgrade();
1482         CHECK_NULL_RETURN(pattern, itemInfo);
1483         auto host = pattern->GetHost();
1484         CHECK_NULL_RETURN(host, itemInfo);
1485         auto hub = host->GetEventHub<EventHub>();
1486         CHECK_NULL_RETURN(hub, itemInfo);
1487         auto gestureHub = hub->GetOrCreateGestureEventHub();
1488         CHECK_NULL_RETURN(gestureHub, itemInfo);
1489         if (!gestureHub->GetIsTextDraggable()) {
1490             return itemInfo;
1491         }
1492         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1493         CHECK_NULL_RETURN(layoutProperty, itemInfo);
1494 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
1495         if (pattern->SelectOverlayIsOn() || pattern->imeAttached_ || pattern->showSelect_) {
1496             pattern->CloseHandleAndSelect();
1497             pattern->CloseKeyboard(true);
1498         }
1499 #endif
1500         pattern->dragStatus_ = DragStatus::DRAGGING;
1501         pattern->showSelect_ = false;
1502         pattern->selectionMode_ = SelectionMode::SELECT;
1503         pattern->textFieldContentModifier_->ChangeDragStatus();
1504         auto contentController = pattern->contentController_;
1505         auto selectController = pattern->selectController_;
1506         pattern->dragTextStart_ = selectController->GetStartIndex();
1507         pattern->dragTextEnd_ = selectController->GetEndIndex();
1508         std::string beforeStr = contentController->GetValueBeforeIndex(selectController->GetStartIndex());
1509         std::string selectedStr =
1510             contentController->GetSelectedValue(selectController->GetStartIndex(), selectController->GetEndIndex());
1511         std::string afterStr = contentController->GetValueAfterIndex(selectController->GetEndIndex());
1512         pattern->dragContents_ = { beforeStr, selectedStr, afterStr };
1513         itemInfo.extraInfo = selectedStr;
1514         RefPtr<UnifiedData> unifiedData = UdmfClient::GetInstance()->CreateUnifiedData();
1515         UdmfClient::GetInstance()->AddPlainTextRecord(unifiedData, selectedStr);
1516         event->SetData(unifiedData);
1517         host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
1518                                                                                      : PROPERTY_UPDATE_MEASURE);
1519         return itemInfo;
1520     };
1521     return onDragStart;
1522 }
1523 
OnDragDrop()1524 std::function<void(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragDrop()
1525 {
1526     return [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1527         auto pattern = weakPtr.Upgrade();
1528         CHECK_NULL_VOID(pattern);
1529         auto host = pattern->GetHost();
1530         CHECK_NULL_VOID(host);
1531         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1532         CHECK_NULL_VOID(layoutProperty);
1533         if (layoutProperty->GetIsDisabledValue(false) || pattern->IsNormalInlineState() || !pattern->HasFocus()) {
1534             return;
1535         }
1536         if (extraParams.empty()) {
1537             pattern->dragStatus_ = DragStatus::ON_DROP;
1538             pattern->textFieldContentModifier_->ChangeDragStatus();
1539             host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
1540                                                                                          : PROPERTY_UPDATE_MEASURE);
1541             return;
1542         }
1543         auto data = event->GetData();
1544         CHECK_NULL_VOID(data);
1545         auto records = UdmfClient::GetInstance()->GetPlainTextRecords(data);
1546         std::string str;
1547         if (records.empty()) {
1548             std::string linkUrl;
1549             std::string linkTitle;
1550             UdmfClient::GetInstance()->GetLinkRecord(data, linkUrl, linkTitle);
1551             if (!linkTitle.empty()) {
1552                 str += linkTitle;
1553             } else if (!linkUrl.empty()) {
1554                 str += linkUrl;
1555             }
1556         }
1557         for (const auto& record : records) {
1558             str += record;
1559         }
1560         pattern->needToRequestKeyboardInner_ = pattern->dragStatus_ == DragStatus::NONE;
1561         pattern->dragRecipientStatus_ = DragStatus::NONE;
1562         if (str.empty()) {
1563             return;
1564         }
1565         if (pattern->dragStatus_ == DragStatus::NONE) {
1566             pattern->InsertValue(str);
1567         } else {
1568             auto current = pattern->selectController_->GetCaretIndex();
1569             auto dragTextStart = pattern->dragTextStart_;
1570             auto dragTextEnd = pattern->dragTextEnd_;
1571             if (current < dragTextStart) {
1572                 pattern->contentController_->erase(dragTextStart, dragTextEnd - dragTextStart);
1573                 pattern->InsertValue(str);
1574             } else if (current > dragTextEnd) {
1575                 pattern->contentController_->erase(dragTextStart, dragTextEnd - dragTextStart);
1576                 pattern->selectController_->UpdateCaretIndex(current - (dragTextEnd - dragTextStart));
1577                 pattern->InsertValue(str);
1578             }
1579             pattern->dragStatus_ = DragStatus::NONE;
1580             pattern->MarkContentChange();
1581             host->MarkDirtyNode(pattern->IsTextArea() ? PROPERTY_UPDATE_MEASURE : PROPERTY_UPDATE_MEASURE_SELF);
1582         }
1583     };
1584 }
1585 
ShowSelectAfterDragEvent()1586 void TextFieldPattern::ShowSelectAfterDragEvent()
1587 {
1588     selectController_->UpdateHandleIndex(dragTextStart_, dragTextEnd_);
1589     showSelect_ = true;
1590     processOverlayDelayTask_ = [weak = WeakClaim(this)]() {
1591         auto pattern = weak.Upgrade();
1592         CHECK_NULL_VOID(pattern);
1593         pattern->ProcessOverlay(false, false, false, false);
1594     };
1595 }
1596 
InitDragDropEventWithOutDragStart()1597 void TextFieldPattern::InitDragDropEventWithOutDragStart()
1598 {
1599     auto host = GetHost();
1600     CHECK_NULL_VOID(host);
1601     auto gestureHub = host->GetOrCreateGestureEventHub();
1602     CHECK_NULL_VOID(gestureHub);
1603     gestureHub->InitDragDropEvent();
1604     auto eventHub = host->GetEventHub<EventHub>();
1605     CHECK_NULL_VOID(eventHub);
1606     InitDragDropCallBack();
1607 }
1608 
InitDragDropEvent()1609 void TextFieldPattern::InitDragDropEvent()
1610 {
1611     auto host = GetHost();
1612     CHECK_NULL_VOID(host);
1613     auto gestureHub = host->GetOrCreateGestureEventHub();
1614     CHECK_NULL_VOID(gestureHub);
1615     gestureHub->InitDragDropEvent();
1616     auto callback = GetThumbnailCallback();
1617     gestureHub->SetThumbnailCallback(std::move(callback));
1618     auto eventHub = host->GetEventHub<EventHub>();
1619     CHECK_NULL_VOID(eventHub);
1620     if (!eventHub->HasOnDragStart()) {
1621         eventHub->SetOnDragStart(OnDragStart());
1622     } else if (gestureHub->GetTextDraggable()) {
1623         gestureHub->SetTextDraggable(false);
1624     }
1625     InitDragDropCallBack();
1626     gestureHub->SetTextDraggable(true);
1627 }
1628 
InitDragDropCallBack()1629 void TextFieldPattern::InitDragDropCallBack()
1630 {
1631     auto host = GetHost();
1632     CHECK_NULL_VOID(host);
1633     auto eventHub = host->GetEventHub<EventHub>();
1634     CHECK_NULL_VOID(eventHub);
1635     auto onDragEnter = [weakPtr = WeakClaim(this)](
1636                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1637         auto pattern = weakPtr.Upgrade();
1638         CHECK_NULL_VOID(pattern);
1639         pattern->showSelect_ = false;
1640         if (pattern->dragStatus_ == DragStatus::ON_DROP) {
1641             pattern->dragStatus_ = DragStatus::NONE;
1642         }
1643         pattern->dragRecipientStatus_ = DragStatus::DRAGGING;
1644     };
1645     eventHub->SetOnDragEnter(std::move(onDragEnter));
1646 
1647     auto onDragMove = [weakPtr = WeakClaim(this)](
1648                           const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1649         auto pattern = weakPtr.Upgrade();
1650         CHECK_NULL_VOID(pattern);
1651         auto pipeline = PipelineBase::GetCurrentContext();
1652         CHECK_NULL_VOID(pipeline);
1653         auto theme = pipeline->GetTheme<TextFieldTheme>();
1654         CHECK_NULL_VOID(theme);
1655         auto touchX = event->GetX();
1656         auto touchY = event->GetY();
1657         Offset offset = Offset(touchX, touchY) - Offset(pattern->textRect_.GetX(), pattern->textRect_.GetY()) -
1658                         Offset(pattern->parentGlobalOffset_.GetX(), pattern->parentGlobalOffset_.GetY()) -
1659                         Offset(0, theme->GetInsertCursorOffset().ConvertToPx());
1660         auto position = pattern->ConvertTouchOffsetToCaretPosition(offset);
1661         pattern->SetCaretPosition(position);
1662         auto host = pattern->GetHost();
1663         CHECK_NULL_VOID(host);
1664     };
1665     eventHub->SetOnDragMove(std::move(onDragMove));
1666 
1667     auto onDragLeave = [weakPtr = WeakClaim(this)](
1668                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1669         auto pattern = weakPtr.Upgrade();
1670         CHECK_NULL_VOID(pattern);
1671         pattern->showSelect_ = false;
1672         pattern->dragRecipientStatus_ = DragStatus::NONE;
1673     };
1674     eventHub->SetOnDragLeave(std::move(onDragLeave));
1675 
1676     auto onDragEnd = [weakPtr = WeakClaim(this), id = Container::CurrentId()](
1677                          const RefPtr<OHOS::Ace::DragEvent>& event) {
1678         ContainerScope scope(id);
1679         auto pattern = weakPtr.Upgrade();
1680         CHECK_NULL_VOID(pattern);
1681         if (pattern->dragStatus_ == DragStatus::DRAGGING) {
1682             pattern->dragStatus_ = DragStatus::NONE;
1683             pattern->MarkContentChange();
1684             auto host = pattern->GetHost();
1685             CHECK_NULL_VOID(host);
1686 
1687             // Except for DRAG_SUCCESS, all of rest need to show
1688             auto paintProperty = pattern->GetPaintProperty<TextFieldPaintProperty>();
1689             CHECK_NULL_VOID(paintProperty);
1690             if (event != nullptr && event->GetResult() != DragRet::DRAG_SUCCESS &&
1691                 paintProperty->GetInputStyleValue(InputStyle::DEFAULT) != InputStyle::INLINE) {
1692                 pattern->ShowSelectAfterDragEvent();
1693             }
1694             auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1695             CHECK_NULL_VOID(layoutProperty);
1696             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1697         }
1698     };
1699     eventHub->SetOnDragEnd(std::move(onDragEnd));
1700 
1701     eventHub->SetOnDrop(OnDragDrop());
1702 }
1703 
ClearDragDropEvent()1704 void TextFieldPattern::ClearDragDropEvent()
1705 {
1706     auto host = GetHost();
1707     CHECK_NULL_VOID(host);
1708     auto gestureHub = host->GetOrCreateGestureEventHub();
1709     CHECK_NULL_VOID(gestureHub);
1710     gestureHub->SetTextDraggable(false);
1711     gestureHub->SetIsTextDraggable(false);
1712     auto eventHub = host->GetEventHub<EventHub>();
1713     CHECK_NULL_VOID(eventHub);
1714     eventHub->SetOnDragStart(nullptr);
1715     eventHub->SetOnDragEnter(nullptr);
1716     eventHub->SetOnDragMove(nullptr);
1717     eventHub->SetOnDragLeave(nullptr);
1718     eventHub->SetOnDragEnd(nullptr);
1719     eventHub->SetOnDrop(nullptr);
1720 }
1721 
InitTouchEvent()1722 void TextFieldPattern::InitTouchEvent()
1723 {
1724     CHECK_NULL_VOID(!touchListener_);
1725     auto host = GetHost();
1726     CHECK_NULL_VOID(host);
1727 
1728     auto gesture = host->GetOrCreateGestureEventHub();
1729     CHECK_NULL_VOID(gesture);
1730     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
1731         auto pattern = weak.Upgrade();
1732         CHECK_NULL_VOID(pattern);
1733         pattern->isUsingMouse_ = info.GetSourceDevice() == SourceType::MOUSE;
1734         pattern->HandleTouchEvent(info);
1735     };
1736     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
1737     gesture->AddTouchEvent(touchListener_);
1738 }
1739 
InitClickEvent()1740 void TextFieldPattern::InitClickEvent()
1741 {
1742     CHECK_NULL_VOID(!clickListener_);
1743     auto tmpHost = GetHost();
1744     CHECK_NULL_VOID(tmpHost);
1745     auto gesture = tmpHost->GetOrCreateGestureEventHub();
1746     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
1747         auto pattern = weak.Upgrade();
1748         CHECK_NULL_VOID(pattern);
1749         pattern->HandleClickEvent(info);
1750     };
1751 
1752     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
1753     gesture->AddClickEvent(clickListener_);
1754 }
1755 
HandleClickEvent(GestureEvent & info)1756 void TextFieldPattern::HandleClickEvent(GestureEvent& info)
1757 {
1758     auto focusHub = GetFocusHub();
1759     if (!focusHub->IsFocusable()) {
1760         return;
1761     }
1762     if (!HasFocus()) {
1763         if (!focusHub->IsFocusOnTouch().value_or(true) || !focusHub->RequestFocusImmediately()) {
1764             CloseSelectOverlay(true);
1765             StopTwinkling();
1766             return;
1767         }
1768     }
1769 
1770     isUsingMouse_ = info.GetSourceDevice() == SourceType::MOUSE;
1771     if (CheckClickLocation(info)) {
1772         HandleDoubleClickEvent(info); // 注册手势事件
1773     } else {
1774         HandleSingleClickEvent(info);
1775     }
1776     if (ResetObscureTickCountDown()) {
1777         auto host = GetHost();
1778         CHECK_NULL_VOID(host);
1779         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1780     }
1781     isFocusedBeforeClick_ = false;
1782 }
1783 
CheckClickLocation(GestureEvent & info)1784 bool TextFieldPattern::CheckClickLocation(GestureEvent& info)
1785 {
1786     TimeStamp clickTimeStamp = info.GetTimeStamp();
1787     std::chrono::duration<float, std::ratio<1, SECONDS_TO_MILLISECONDS>> timeout = clickTimeStamp - lastClickTimeStamp_;
1788     lastClickTimeStamp_ = info.GetTimeStamp();
1789 
1790     Offset location = info.GetLocalLocation();
1791     auto deltaOffset = location - clickLocation_;
1792     auto deltaDistance = deltaOffset.GetDistance();
1793     clickLocation_ = location;
1794 
1795     return timeout.count() >= DOUBLECLICK_MIN_INTERVAL_MS && timeout.count() < DOUBLECLICK_INTERVAL_MS &&
1796            deltaDistance < DOUBLECLICK_DISTANCE.ConvertToPx();
1797 }
1798 
HandleSingleClickEvent(GestureEvent & info)1799 void TextFieldPattern::HandleSingleClickEvent(GestureEvent& info)
1800 {
1801     if (mouseStatus_ != MouseStatus::NONE && IsNormalInlineState()) {
1802         return;
1803     }
1804     if (!isUsingMouse_ && SelectOverlayIsOn() && BetweenSelectedPosition(info.GetGlobalLocation())) {
1805         UpdateSelectMenuVisibility(true);
1806         return;
1807     }
1808     auto host = GetHost();
1809     CHECK_NULL_VOID(host);
1810     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1811     auto lastCaretIndex = selectController_->GetCaretIndex();
1812     auto lastCaretRect = selectController_->GetCaretRect();
1813     if (mouseStatus_ != MouseStatus::MOVE) {
1814         selectController_->UpdateCaretInfoByOffset(info.GetLocalLocation());
1815     }
1816     StartTwinkling();
1817     SetIsSingleHandle(true);
1818     CloseSelectOverlay(true);
1819 
1820     if (RepeatClickCaret(info.GetLocalLocation(), lastCaretIndex, lastCaretRect) &&
1821         info.GetSourceDevice() != SourceType::MOUSE) {
1822         if (needSelectAll_) {
1823             HandleOnSelectAll(true);
1824         } else if (contentController_->IsEmpty()) {
1825             ProcessOverlay(true, true, true, true);
1826         } else {
1827             ProcessOverlay(true, true);
1828         }
1829     } else if (!contentController_->IsEmpty() && info.GetSourceDevice() != SourceType::MOUSE &&
1830                !IsNormalInlineState()) {
1831         if (GetNakedCharPosition() >= 0) {
1832             DelayProcessOverlay(true, true, false);
1833         } else if (needSelectAll_) {
1834             HandleOnSelectAll(true);
1835         } else {
1836             ProcessOverlay(true, true, false);
1837         }
1838     }
1839     if (ProcessAutoFill()) {
1840         needToRequestKeyboardInner_ = false;
1841     } else if (RequestKeyboard(false, true, true)) {
1842         NotifyOnEditChanged(true);
1843     }
1844     // emulate clicking bottom of the textField
1845     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
1846     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1847 }
1848 
CheckAutoFill()1849 bool TextFieldPattern::CheckAutoFill()
1850 {
1851     auto host = GetHost();
1852     CHECK_NULL_RETURN(host, false);
1853     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1854     CHECK_NULL_RETURN(layoutProperty, false);
1855     bool isEnableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
1856     if (!isEnableAutoFill) {
1857         return false;
1858     }
1859     auto pageNode = host->GetPageNode();
1860     CHECK_NULL_RETURN(pageNode, false);
1861     auto pagePattern = pageNode->GetPattern<PagePattern>();
1862     CHECK_NULL_RETURN(pagePattern, false);
1863     auto autoFillType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
1864     if (autoFillType == TextInputType::USER_NAME || autoFillType == TextInputType::VISIBLE_PASSWORD) {
1865         return !pagePattern->IsAutoFillPasswordTriggered();
1866     } else if (autoFillType == TextInputType::NEW_PASSWORD) {
1867         return !pagePattern->IsAutoFillNewPasswordTriggered();
1868     }
1869     return false;
1870 }
1871 
ProcessAutoFill()1872 bool TextFieldPattern::ProcessAutoFill()
1873 {
1874     if (!CheckAutoFill()) {
1875         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "No nedd to auto fill.");
1876         return false;
1877     }
1878     auto host = GetHost();
1879     CHECK_NULL_RETURN(host, false);
1880     auto pageNode = host->GetPageNode();
1881     CHECK_NULL_RETURN(pageNode, false);
1882     auto pagePattern = pageNode->GetPattern<PagePattern>();
1883     CHECK_NULL_RETURN(pagePattern, false);
1884     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1885     CHECK_NULL_RETURN(layoutProperty, false);
1886     auto autoFillType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
1887     auto container = Container::Current();
1888     CHECK_NULL_RETURN(container, false);
1889     if (autoFillType == AceAutoFillType::ACE_NEW_PASSWORD) {
1890         pagePattern->SetAutoFillNewPasswordTriggered(true);
1891     } else {
1892         pagePattern->SetAutoFillPasswordTriggered(true);
1893     }
1894     return container->RequestAutoFill(host, autoFillType);
1895 }
1896 
HandleDoubleClickEvent(GestureEvent & info)1897 void TextFieldPattern::HandleDoubleClickEvent(GestureEvent& info)
1898 {
1899     if (showSelect_) {
1900         SetIsSingleHandle(true);
1901         CloseSelectOverlay();
1902     }
1903     selectController_->UpdateSelectByOffset(info.GetLocalLocation());
1904     if (IsSelected()) {
1905         StopTwinkling();
1906         SetIsSingleHandle(false);
1907     }
1908     if (info.GetSourceDevice() != SourceType::MOUSE && !contentController_->IsEmpty()) {
1909         ProcessOverlay(true, true);
1910         UpdateSelectMenuVisibility(true);
1911     }
1912     auto host = GetHost();
1913     CHECK_NULL_VOID(host);
1914     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1915 }
1916 
ScheduleCursorTwinkling()1917 void TextFieldPattern::ScheduleCursorTwinkling()
1918 {
1919     if (isTransparent_) {
1920         return;
1921     }
1922     auto context = PipelineContext::GetCurrentContext();
1923     CHECK_NULL_VOID(context);
1924 
1925     if (!context->GetTaskExecutor()) {
1926         return;
1927     }
1928 
1929     if (isCursorAlwaysDisplayed_) {
1930         return;
1931     }
1932 
1933     auto weak = WeakClaim(this);
1934     cursorTwinklingTask_.Reset([weak] {
1935         auto client = weak.Upgrade();
1936         CHECK_NULL_VOID(client);
1937         client->OnCursorTwinkling();
1938     });
1939     auto taskExecutor = context->GetTaskExecutor();
1940     CHECK_NULL_VOID(taskExecutor);
1941     taskExecutor->PostDelayedTask(cursorTwinklingTask_, TaskExecutor::TaskType::UI, twinklingInterval_);
1942 }
1943 
StartTwinkling()1944 void TextFieldPattern::StartTwinkling()
1945 {
1946     if (isTransparent_) {
1947         return;
1948     }
1949     // Ignore the result because all ops are called on this same thread (ACE UI).
1950     // The only reason failed is that the task has finished.
1951     cursorTwinklingTask_.Cancel();
1952 
1953     // Show cursor right now.
1954     cursorVisible_ = true;
1955     auto tmpHost = GetHost();
1956     CHECK_NULL_VOID(tmpHost);
1957     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1958     ScheduleCursorTwinkling();
1959 }
1960 
OnCursorTwinkling()1961 void TextFieldPattern::OnCursorTwinkling()
1962 {
1963     cursorTwinklingTask_.Cancel();
1964     cursorVisible_ = !cursorVisible_;
1965     auto shouldMeasure = !IsTextArea() && IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ == 1;
1966     if (IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ > 0) {
1967         --obscureTickCountDown_;
1968     }
1969     auto host = GetHost();
1970     CHECK_NULL_VOID(host);
1971     if (shouldMeasure) {
1972         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1973     } else {
1974         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1975     }
1976     ScheduleCursorTwinkling();
1977 }
1978 
StopTwinkling()1979 void TextFieldPattern::StopTwinkling()
1980 {
1981     cursorTwinklingTask_.Cancel();
1982 
1983     // Repaint only if cursor is visible for now.
1984     auto tmpHost = GetHost();
1985     CHECK_NULL_VOID(tmpHost);
1986     if (cursorVisible_) {
1987         cursorVisible_ = false;
1988         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1989     }
1990     if (ResetObscureTickCountDown()) {
1991         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1992     }
1993 }
1994 
CheckIfNeedToResetKeyboard()1995 void TextFieldPattern::CheckIfNeedToResetKeyboard()
1996 {
1997     auto tmpHost = GetHost();
1998     CHECK_NULL_VOID(tmpHost);
1999     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
2000     CHECK_NULL_VOID(layoutProperty);
2001     bool needToResetKeyboard = false;
2002     // check unspecified  for first time entrance
2003     if (keyboard_ != layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
2004         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Keyboard type changed to %{public}d",
2005             layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2006         keyboard_ = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
2007         needToResetKeyboard = true;
2008     }
2009     if (!needToResetKeyboard && action_ != TextInputAction::UNSPECIFIED) {
2010         needToResetKeyboard = action_ != GetTextInputActionValue(GetDefaultTextInputAction());
2011     }
2012     action_ = GetTextInputActionValue(GetDefaultTextInputAction());
2013     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Keyboard action is %{public}d", action_);
2014 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
2015     if (needToResetKeyboard) {
2016         // if keyboard attached and keyboard is shown, pull up keyboard again
2017         if (imeShown_ || isCustomKeyboardAttached_) {
2018             if (HasFocus()) {
2019                 RequestKeyboard(false, true, true);
2020             }
2021             return;
2022         }
2023 #if defined(ENABLE_STANDARD_INPUT)
2024         auto inputMethod = MiscServices::InputMethodController::GetInstance();
2025         CHECK_NULL_VOID(inputMethod);
2026         MiscServices::Configuration config;
2027         config.SetEnterKeyType(static_cast<MiscServices::EnterKeyType>(action_));
2028         config.SetTextInputType(static_cast<MiscServices::TextInputType>(keyboard_));
2029         inputMethod->OnConfigurationChange(config);
2030 #endif
2031     }
2032 #else
2033     if (needToResetKeyboard && HasConnection()) {
2034         CloseKeyboard(true);
2035         RequestKeyboard(false, true, true);
2036     }
2037 #endif
2038 }
OnModifyDone()2039 void TextFieldPattern::OnModifyDone()
2040 {
2041     Pattern::OnModifyDone();
2042     auto host = GetHost();
2043     CHECK_NULL_VOID(host);
2044     auto context = PipelineContext::GetCurrentContext();
2045     CHECK_NULL_VOID(context);
2046     instanceId_ = context->GetInstanceId();
2047     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2048     CHECK_NULL_VOID(layoutProperty);
2049     auto textFieldTheme = GetTheme();
2050     CHECK_NULL_VOID(textFieldTheme);
2051     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
2052     CHECK_NULL_VOID(paintProperty);
2053     CheckIfNeedToResetKeyboard();
2054     auto renderContext = host->GetRenderContext();
2055     CHECK_NULL_VOID(renderContext);
2056     isTransparent_ = renderContext->GetOpacityValue(1.0f) == 0.0f;
2057     if (!preErrorState_ && !restoreMarginState_) {
2058         SavePasswordModeStates();
2059     }
2060     // When switching between dark and light modes, you need to update the status of the passwordState
2061     if (colorModeChange_ && !isModifyDone_) {
2062         UpdatePasswordModeState();
2063     }
2064     InitClickEvent();
2065     InitBackGroundColorAndBorderRadius();
2066     InitLongPressEvent();
2067     InitFocusEvent();
2068     InitMouseEvent();
2069     InitTouchEvent();
2070     SetAccessibilityAction();
2071     FilterInitializeText();
2072     InitSelectOverlay();
2073     InitDisableColor();
2074     ProcessResponseArea();
2075     InitDragEvent();
2076     Register2DragDropManager();
2077     context->AddOnAreaChangeNode(host->GetId());
2078     if (!clipboard_ && context) {
2079         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
2080     }
2081     if (barState_.has_value() && barState_.value() != layoutProperty->GetDisplayModeValue(DisplayMode::AUTO) &&
2082         HasFocus() && IsNormalInlineState()) {
2083         lastTextRectY_ = textRect_.GetY();
2084     }
2085     if (!IsDisabled()) {
2086         SetShowError();
2087     }
2088     ProcessInnerPadding();
2089     // The textRect position can't be changed by only redraw.
2090     if (CheckNeedMeasure(layoutProperty->GetPropertyChangeFlag()) && !HasInputOperation() &&
2091         (!HasFocus() || !initTextRect_)) {
2092         textRect_.SetLeft(GetPaddingLeft() + GetBorderLeft());
2093         textRect_.SetTop(GetPaddingTop() + GetBorderTop());
2094         initTextRect_ = true;
2095     }
2096     CalculateDefaultCursor();
2097 
2098     auto textWidth = static_cast<int32_t>(contentController_->GetWideText().length());
2099     if (SelectOverlayIsOn()) {
2100         needToRefreshSelectOverlay_ = true;
2101         UpdateSelection(std::clamp(selectController_->GetStartIndex(), 0, textWidth),
2102             std::clamp(selectController_->GetEndIndex(), 0, textWidth));
2103     } else {
2104         needToRefreshSelectOverlay_ = false;
2105     }
2106     if (layoutProperty->GetTypeChangedValue(false)) {
2107         layoutProperty->ResetTypeChanged();
2108         operationRecords_.clear();
2109         redoOperationRecords_.clear();
2110     }
2111     if (IsTextArea() || IsNormalInlineState()) {
2112         SetAxis(Axis::VERTICAL);
2113         if (!GetScrollableEvent()) {
2114             AddScrollEvent();
2115         }
2116         auto barState = layoutProperty->GetDisplayModeValue(DisplayMode::AUTO);
2117         if (!barState_.has_value()) {
2118             barState_ = barState;
2119         }
2120         scrollBarVisible_ = barState != DisplayMode::OFF;
2121         SetScrollBar(barState == DisplayMode::OFF ? DisplayMode::ON : barState);
2122         auto scrollBar = GetScrollBar();
2123         if (scrollBar) {
2124             scrollBar->SetMinHeight(SCROLL_BAR_MIN_HEIGHT);
2125         }
2126         if (textFieldOverlayModifier_) {
2127             textFieldOverlayModifier_->SetScrollBar(scrollBar);
2128             UpdateScrollBarOffset();
2129         }
2130     } else {
2131         SetAxis(Axis::HORIZONTAL);
2132         SetScrollBar(DisplayMode::OFF);
2133         if (!GetScrollableEvent()) {
2134             AddScrollEvent();
2135             SetScrollEnable(false);
2136         }
2137     }
2138     if (IsTextArea()) {
2139         if (setBorderFlag_ && layoutProperty->HasMaxLength()) {
2140             auto textFieldTheme = GetTheme();
2141             lastDiffBorderColor_.SetColor(textFieldTheme->GetOverCountBorderColor());
2142             lastDiffBorderWidth_.SetBorderWidth(OVER_COUNT_BORDER_WIDTH);
2143             setBorderFlag_ = false;
2144         }
2145         HandleCounterBorder();
2146     } else {
2147         isTextInput_ = true;
2148     }
2149     UpdateCounterMargin();
2150     bool underline = layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType()
2151         && (!IsNormalInlineState() || !HasFocus());
2152     if (preUnderline && !underline) {
2153         RestoreUnderlineStates();
2154     }
2155     if (!underline && !preUnderlineState_.saveState) {
2156         SavePreUnderLineState();
2157     }
2158     if (!inlineState_.saveState || !HasFocus()) {
2159         SaveInlineStates();
2160     }
2161     if (HasFocus() && IsNormalInlineState()) {
2162         ApplyInlineStates();
2163     }
2164     if (underline) {
2165         ApplyUnderlineStates();
2166     }
2167     if (preInline && !IsNormalInlineState()) {
2168         if (IsTextArea() && isTextInput_) {
2169             layoutProperty->UpdateMaxLines(1);
2170         }
2171         inlineSelectAllFlag_ = false;
2172         inlineFocusState_ = false;
2173         RestorePreInlineStates();
2174         if (!GetTextBoxes().empty()) {
2175             UpdateSelection(0);
2176         }
2177         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2178     }
2179     auto maxlength = GetMaxLength();
2180     auto originLength = static_cast<int32_t>(contentController_->GetWideText().length());
2181     HandleInputCounterBorder(originLength, maxlength);
2182     preInline = IsNormalInlineState();
2183     preUnderline = underline;
2184     Register2DragDropManager();
2185     isModifyDone_ = true;
2186 }
2187 
SavePreUnderLineState()2188 void TextFieldPattern::SavePreUnderLineState()
2189 {
2190     auto host = GetHost();
2191     CHECK_NULL_VOID(host);
2192     auto renderContext = host->GetRenderContext();
2193     CHECK_NULL_VOID(renderContext);
2194     auto theme = GetTheme();
2195     CHECK_NULL_VOID(theme);
2196     preUnderlineState_.saveState = true;
2197     preUnderlineState_.bgColor = renderContext->GetBackgroundColor().value_or(theme->GetBgColor());
2198     auto radius = theme->GetBorderRadius();
2199     BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
2200     preUnderlineState_.radius = renderContext->GetBorderRadius().value_or(borderRadius);
2201 }
2202 
InitBackGroundColorAndBorderRadius()2203 void TextFieldPattern::InitBackGroundColorAndBorderRadius()
2204 {
2205     auto host = GetHost();
2206     CHECK_NULL_VOID(host);
2207     auto renderContext = host->GetRenderContext();
2208     CHECK_NULL_VOID(renderContext);
2209     auto textFieldTheme = GetTheme();
2210     CHECK_NULL_VOID(textFieldTheme);
2211     if (!renderContext->HasBackgroundColor()) {
2212         renderContext->UpdateBackgroundColor(textFieldTheme->GetBgColor());
2213     }
2214     if (!renderContext->HasBorderRadius()) {
2215         auto radius = textFieldTheme->GetBorderRadius();
2216         BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
2217         renderContext->UpdateBorderRadius(borderRadius);
2218     }
2219 }
2220 
OnAfterModifyDone()2221 void TextFieldPattern::OnAfterModifyDone()
2222 {
2223     auto host = GetHost();
2224     CHECK_NULL_VOID(host);
2225     auto inspectorId = host->GetInspectorId().value_or("");
2226     if (!inspectorId.empty()) {
2227         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2228         bool isPwdType = layoutProperty ? layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) ==
2229                                               TextInputType::VISIBLE_PASSWORD
2230                                         : false;
2231         if (!isPwdType) {
2232             Recorder::NodeDataCache::Get().PutString(inspectorId, contentController_->GetTextValue());
2233         }
2234     }
2235 }
2236 
CalculateDefaultCursor()2237 void TextFieldPattern::CalculateDefaultCursor()
2238 {
2239     auto tmpHost = GetHost();
2240     CHECK_NULL_VOID(tmpHost);
2241     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
2242     CHECK_NULL_VOID(layoutProperty);
2243     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
2244     CHECK_NULL_VOID(paintProperty);
2245     auto textFieldTheme = GetTheme();
2246     CHECK_NULL_VOID(textFieldTheme);
2247     float caretWidth = paintProperty->GetCursorWidth().has_value()
2248                            ? static_cast<float>(paintProperty->GetCursorWidthValue().ConvertToPx())
2249                            : static_cast<float>(textFieldTheme->GetCursorWidth().ConvertToPx());
2250     selectController_->UpdateCaretWidth(caretWidth);
2251     if (!contentController_->IsEmpty()) {
2252         return;
2253     }
2254     selectController_->UpdateCaretHeight(PreferredLineHeight());
2255 }
2256 
FireOnTextChangeEvent()2257 bool TextFieldPattern::FireOnTextChangeEvent()
2258 {
2259     auto host = GetHost();
2260     CHECK_NULL_RETURN(host, false);
2261     auto eventHub = host->GetEventHub<TextFieldEventHub>();
2262     CHECK_NULL_RETURN(eventHub, false);
2263     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2264     CHECK_NULL_RETURN(layoutProperty, false);
2265     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
2266     if (cleanNodeStyle == CleanNodeStyle::INPUT) {
2267         auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
2268         if (cleanNodeResponseArea && contentController_->IsEmpty() && cleanNodeResponseArea->IsShow()) {
2269             cleanNodeResponseArea->UpdateCleanNode(false);
2270         } else if (cleanNodeResponseArea && !contentController_->IsEmpty() && !cleanNodeResponseArea->IsShow()) {
2271             cleanNodeResponseArea->UpdateCleanNode(true);
2272         }
2273     }
2274     auto textCache = layoutProperty->GetValueValue("");
2275     if (textCache == contentController_->GetTextValue()) {
2276         return false;
2277     }
2278     layoutProperty->UpdateValue(contentController_->GetTextValue());
2279     host->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, textCache, contentController_->GetTextValue());
2280     eventHub->FireOnChange(contentController_->GetTextValue());
2281     auto context = PipelineContext::GetCurrentContext();
2282     CHECK_NULL_RETURN(context, false);
2283     auto taskExecutor = context->GetTaskExecutor();
2284     CHECK_NULL_RETURN(taskExecutor, false);
2285     taskExecutor->PostTask(
2286         [weak = WeakClaim(this)] {
2287             auto pattern = weak.Upgrade();
2288             CHECK_NULL_VOID(pattern);
2289             if (!pattern->HasFocus()) {
2290                 return;
2291             }
2292             pattern->ScrollToSafeArea();
2293         },
2294         TaskExecutor::TaskType::UI);
2295     return true;
2296 }
2297 
FilterInitializeText()2298 void TextFieldPattern::FilterInitializeText()
2299 {
2300     if (HasInputOperation()) {
2301         return;
2302     }
2303     if (!contentController_->IsEmpty()) {
2304         contentController_->FilterValue();
2305     }
2306     if (static_cast<int32_t>(GetWideText().length()) < GetCaretIndex()) {
2307         selectController_->UpdateCaretIndex(static_cast<int32_t>(GetWideText().length()));
2308     }
2309 }
2310 
IsDisabled()2311 bool TextFieldPattern::IsDisabled()
2312 {
2313     auto tmpHost = GetHost();
2314     CHECK_NULL_RETURN(tmpHost, true);
2315     auto eventHub = tmpHost->GetEventHub<TextFieldEventHub>();
2316     CHECK_NULL_RETURN(eventHub, true);
2317     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
2318     CHECK_NULL_RETURN(layoutProperty, true);
2319     return !eventHub->IsEnabled();
2320 }
2321 
ProcessInnerPadding()2322 void TextFieldPattern::ProcessInnerPadding()
2323 {
2324     auto tmpHost = GetHost();
2325     CHECK_NULL_VOID(tmpHost);
2326     auto textFieldTheme = GetTheme();
2327     CHECK_NULL_VOID(textFieldTheme);
2328     auto themePadding = textFieldTheme->GetPadding();
2329     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
2330     CHECK_NULL_VOID(layoutProperty);
2331 
2332     BorderWidthProperty currentBorderWidth;
2333     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
2334         currentBorderWidth = *(layoutProperty->GetBorderWidthProperty());
2335     } else {
2336         currentBorderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
2337     }
2338     auto& paddingProperty = layoutProperty->GetPaddingProperty();
2339     auto left = !paddingProperty ? CalcLength(themePadding.Left()).GetDimension()
2340                                  : paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension();
2341     utilPadding_.left = left.ConvertToPx();
2342     auto top = !paddingProperty ? CalcLength(themePadding.Top()).GetDimension()
2343                                 : paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension();
2344     utilPadding_.top = top.ConvertToPx();
2345     auto bottom = !paddingProperty ? CalcLength(themePadding.Bottom()).GetDimension()
2346                                    : paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension();
2347     utilPadding_.bottom = bottom.ConvertToPx();
2348     auto right = !paddingProperty ? CalcLength(themePadding.Right()).GetDimension()
2349                                   : paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension();
2350     utilPadding_.right = right.ConvertToPx();
2351     lastBorderWidth_ = currentBorderWidth;
2352 
2353     PaddingProperty paddings;
2354     paddings.top = NG::CalcLength(top);
2355     paddings.bottom = NG::CalcLength(bottom);
2356     paddings.left = NG::CalcLength(left);
2357     paddings.right = NG::CalcLength(right);
2358     layoutProperty->UpdatePadding(paddings);
2359 }
2360 
InitLongPressEvent()2361 void TextFieldPattern::InitLongPressEvent()
2362 {
2363     CHECK_NULL_VOID(!longPressEvent_);
2364     auto tmpHost = GetHost();
2365     CHECK_NULL_VOID(tmpHost);
2366     auto gesture = tmpHost->GetOrCreateGestureEventHub();
2367     auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
2368         auto pattern = weak.Upgrade();
2369         CHECK_NULL_VOID(pattern);
2370         pattern->isUsingMouse_ = info.GetSourceDevice() == SourceType::MOUSE;
2371         pattern->HandleLongPress(info);
2372     };
2373     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
2374     gesture->SetLongPressEvent(longPressEvent_);
2375 }
2376 
HandleLongPress(GestureEvent & info)2377 void TextFieldPattern::HandleLongPress(GestureEvent& info)
2378 {
2379     auto focusHub = GetFocusHub();
2380     CHECK_NULL_VOID(focusHub);
2381     if (!focusHub->IsFocusable()) {
2382         return;
2383     }
2384     isTouchCaret_ = false;
2385     auto host = GetHost();
2386     CHECK_NULL_VOID(host);
2387     bool shouldProcessOverlayAfterLayout = false;
2388     if (ResetObscureTickCountDown()) {
2389         shouldProcessOverlayAfterLayout = true;
2390         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2391     }
2392     if (info.GetSourceDevice() == SourceType::MOUSE) {
2393         return;
2394     }
2395     auto hub = host->GetEventHub<EventHub>();
2396     CHECK_NULL_VOID(hub);
2397     auto gestureHub = hub->GetOrCreateGestureEventHub();
2398     CHECK_NULL_VOID(gestureHub);
2399     if (BetweenSelectedPosition(info.GetGlobalLocation())) {
2400         gestureHub->SetIsTextDraggable(true);
2401         return;
2402     }
2403     gestureHub->SetIsTextDraggable(false);
2404     isLongPress_ = true;
2405     if (!focusHub->IsCurrentFocus()) {
2406         focusHub->RequestFocusImmediately();
2407     }
2408     if (isSingleHandle_) {
2409         CloseSelectOverlay(true);
2410     }
2411     selectController_->UpdateSelectByOffset(info.GetLocalLocation());
2412     if (IsSelected()) {
2413         StopTwinkling();
2414     }
2415     SetIsSingleHandle(!IsSelected());
2416     if (shouldProcessOverlayAfterLayout) {
2417         DelayProcessOverlay(true, true);
2418     } else {
2419         ProcessOverlay(true, true);
2420         UpdateSelectMenuVisibility(true);
2421     }
2422     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2423 }
2424 
UpdateCaretPositionWithClamp(const int32_t & pos)2425 void TextFieldPattern::UpdateCaretPositionWithClamp(const int32_t& pos)
2426 {
2427     selectController_->UpdateCaretIndex(
2428         std::clamp(pos, 0, static_cast<int32_t>(contentController_->GetWideText().length())));
2429 }
2430 
ProcessOverlay(bool isUpdateMenu,bool animation,bool isShowMenu,bool isHiddenHandle)2431 void TextFieldPattern::ProcessOverlay(bool isUpdateMenu, bool animation, bool isShowMenu, bool isHiddenHandle)
2432 {
2433     auto host = GetHost();
2434     CHECK_NULL_VOID(host);
2435     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2436     CHECK_NULL_VOID(layoutProperty);
2437     if (layoutProperty->HasFontSize() && NearZero(layoutProperty->GetFontSize()->Value())) {
2438         return;
2439     }
2440     selectController_->CalculateHandleOffset();
2441     ShowSelectOverlayParams showOverlayParams = {
2442         .animation = animation, .isShowMenu = isShowMenu, .isUpdateMenu = isUpdateMenu
2443     };
2444     if (IsSelected() && selectController_->IsHandleSamePosition()) {
2445         isSingleHandle_ = true;
2446         selectController_->UpdateCaretIndex(selectController_->GetFirstHandleIndex());
2447         selectController_->UpdateCaretOffset();
2448     } else if (!isSingleHandle_) {
2449         auto rects = GetTextBoxes();
2450         if (!rects.empty() && NearEqual(rects.size(), 1) && NearZero(rects[0].Width())) {
2451             isSingleHandle_ = true;
2452             selectController_->UpdateCaretIndex(selectController_->GetFirstHandleIndex());
2453             selectController_->UpdateCaretOffset();
2454         }
2455     }
2456 
2457     if (isSingleHandle_) {
2458         StartTwinkling();
2459         showOverlayParams.firstHandle = std::nullopt;
2460         showOverlayParams.secondHandle = selectController_->GetCaretRect();
2461         ShowSelectOverlay(showOverlayParams);
2462     } else {
2463         showOverlayParams.firstHandle = selectController_->GetFirstHandleRect();
2464         showOverlayParams.secondHandle = selectController_->GetSecondHandleRect();
2465         ShowSelectOverlay(showOverlayParams);
2466     }
2467     if (isHiddenHandle) {
2468         auto context = host->GetContext();
2469         CHECK_NULL_VOID(context);
2470         auto selectManager = context->GetSelectOverlayManager();
2471         CHECK_NULL_VOID(selectManager);
2472         auto selectOverlayItem = selectManager->GetSelectOverlayItem();
2473         auto selectOverlay = selectOverlayItem.Upgrade();
2474         CHECK_NULL_VOID(selectOverlay);
2475         auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
2476         CHECK_NULL_VOID(pattern);
2477         pattern->StartHiddenHandleTask(false);
2478     }
2479 }
2480 
DelayProcessOverlay(bool isUpdateMenu,bool animation,bool isShowMenu)2481 void TextFieldPattern::DelayProcessOverlay(bool isUpdateMenu, bool animation, bool isShowMenu)
2482 {
2483     processOverlayDelayTask_ = [weak = WeakClaim(this), isUpdateMenu, animation, isShowMenu]() {
2484         auto pattern = weak.Upgrade();
2485         CHECK_NULL_VOID(pattern);
2486         pattern->ProcessOverlay(isUpdateMenu, animation, isShowMenu);
2487     };
2488 }
2489 
ShowSelectOverlay(const ShowSelectOverlayParams & showOverlayParams)2490 void TextFieldPattern::ShowSelectOverlay(const ShowSelectOverlayParams& showOverlayParams)
2491 {
2492     if (isTransparent_) {
2493         return;
2494     }
2495     showSelect_ = true;
2496     auto hasDataCallback = [weak = WeakClaim(this), params = showOverlayParams](bool hasData) {
2497         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HasData callback from clipboard, data available ? %{public}d", hasData);
2498         auto pattern = weak.Upgrade();
2499         CHECK_NULL_VOID(pattern);
2500         pattern->StartRequestSelectOverlay(params, hasData);
2501     };
2502     if (showOverlayParams.isUpdateMenu) {
2503         clipboard_->HasData(hasDataCallback);
2504     } else {
2505         StartRequestSelectOverlay(showOverlayParams);
2506     }
2507 }
2508 
StartRequestSelectOverlay(const ShowSelectOverlayParams & params,bool isShowPaste)2509 void TextFieldPattern::StartRequestSelectOverlay(const ShowSelectOverlayParams& params, bool isShowPaste)
2510 {
2511     ClientOverlayInfo overlayInfo = {
2512         .animation = params.animation, .isMenuShow = params.isShowMenu, .isUpdateMenu = params.isUpdateMenu
2513     };
2514     if (params.firstHandle.has_value()) {
2515         auto handle = params.firstHandle.value();
2516         handle.SetOffset(handle.GetOffset() + GetTextPaintOffset());
2517         SelectHandleInfo firstHandleInfo;
2518         firstHandleInfo.paintRect = handle;
2519         overlayInfo.firstHandleInfo = firstHandleInfo;
2520     }
2521     if (params.secondHandle.has_value()) {
2522         auto handle = params.secondHandle.value();
2523         auto contentRect = GetContentRect();
2524         handle.SetOffset(handle.GetOffset() + GetTextPaintOffset());
2525         if (handle.Height() > contentRect.Height()) {
2526             handle.SetHeight(contentRect.Height());
2527         }
2528         SelectHandleInfo secondHandleInfo;
2529         secondHandleInfo.paintRect = handle;
2530         overlayInfo.secondHandleInfo = secondHandleInfo;
2531     }
2532     overlayInfo.isShowPaste = isShowPaste;
2533     overlayInfo.isMenuShow = params.isShowMenu;
2534     overlayInfo.isNewAvoid = true;
2535     overlayInfo.selectArea = GetSelectArea();
2536     RequestOpenSelectOverlay(overlayInfo);
2537     auto start = GetTextSelectController()->GetStartIndex();
2538     auto end = GetTextSelectController()->GetEndIndex();
2539     UpdateSelectInfo(contentController_->GetSelectedValue(start, end));
2540 }
2541 
OnPreShowSelectOverlay(SelectOverlayInfo & overlayInfo,const ClientOverlayInfo & clientInfo,bool isSelectOverlayOn)2542 bool TextFieldPattern::OnPreShowSelectOverlay(
2543     SelectOverlayInfo& overlayInfo, const ClientOverlayInfo& clientInfo, bool isSelectOverlayOn)
2544 {
2545     auto host = GetHost();
2546     CHECK_NULL_RETURN(host, false);
2547     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2548     CHECK_NULL_RETURN(layoutProperty, false);
2549     bool isHideSelectionMenu = layoutProperty->GetSelectionMenuHiddenValue(false);
2550     // right click menu
2551     if (IsUsingMouse()) {
2552         if (isHideSelectionMenu && !isSelectOverlayOn) {
2553             return false;
2554         }
2555         overlayInfo.rightClickOffset = GetRightClickOffset();
2556         overlayInfo.isUsingMouse = true;
2557     } else {
2558         if (overlayInfo.isSingleHandle && IsTextArea() && GetSelectMode() == SelectionMode::SELECT_ALL) {
2559             auto contentRect = GetContentRect();
2560             auto parentGlobalOffset = GetParentGlobalOffset();
2561             overlayInfo.menuInfo.menuOffset =
2562                 OffsetF(contentRect.GetOffset().GetX() + contentRect.Width() / 2.0 + parentGlobalOffset.GetX(),
2563                     contentRect.GetOffset().GetY() + parentGlobalOffset.GetY());
2564         }
2565         overlayInfo.singleLineHeight = PreferredLineHeight();
2566         overlayInfo.handleReverse = selectController_->HasReverse();
2567     }
2568     auto hasTextContent = !contentController_->IsEmpty();
2569     overlayInfo.menuInfo.showCopy = hasTextContent && AllowCopy() && IsSelected();
2570     overlayInfo.menuInfo.showCut = overlayInfo.menuInfo.showCopy;
2571     overlayInfo.menuInfo.showCopyAll = hasTextContent && !IsSelectAll();
2572     auto hasData = clientInfo.isShowPaste;
2573     overlayInfo.menuInfo.showPaste = hasData;
2574     overlayInfo.menuInfo.menuIsShow = (hasTextContent || hasData) && !isHideSelectionMenu && clientInfo.isMenuShow;
2575     overlayInfo.isHandleLineShow = overlayInfo.isHandleLineShow && !IsSingleHandle();
2576     overlayInfo.menuInfo.menuDisable = isHideSelectionMenu;
2577 #if defined(ENABLE_STANDARD_INPUT)
2578     auto inputMethod = MiscServices::InputMethodController::GetInstance();
2579     isSupportCameraInput_ =
2580         inputMethod && inputMethod->IsInputTypeSupported(MiscServices::InputType::CAMERA_INPUT) && !IsInPasswordMode();
2581 #else
2582     isSupportCameraInput_ = false;
2583 #endif
2584     overlayInfo.menuInfo.showCameraInput = !IsSelected() && isSupportCameraInput_ && !customKeyboardBuilder_;
2585     return true;
2586 }
2587 
UpdateSelectOverlaySecondHandle(bool needLayout)2588 void TextFieldPattern::UpdateSelectOverlaySecondHandle(bool needLayout)
2589 {
2590     auto proxy = GetSelectOverlayProxy();
2591     CHECK_NULL_VOID(proxy);
2592     SelectHandleInfo handleInfo = GetSelectHandleInfo(selectController_->GetSecondHandleOffset());
2593     handleInfo.needLayout = needLayout;
2594     proxy->UpdateSecondSelectHandleInfo(handleInfo);
2595 }
2596 
UpdateSelectOverlayDoubleHandle(bool firstNeedLayout,bool secondNeedLayout)2597 void TextFieldPattern::UpdateSelectOverlayDoubleHandle(bool firstNeedLayout, bool secondNeedLayout)
2598 {
2599     auto proxy = GetSelectOverlayProxy();
2600     CHECK_NULL_VOID(proxy);
2601     SelectHandleInfo firstHandleInfo = GetSelectHandleInfo(selectController_->GetFirstHandleOffset());
2602     firstHandleInfo.needLayout = firstNeedLayout;
2603 
2604     SelectHandleInfo secondHandleInfo = GetSelectHandleInfo(selectController_->GetSecondHandleOffset());
2605     secondHandleInfo.needLayout = secondNeedLayout;
2606     proxy->UpdateFirstAndSecondHandleInfo(firstHandleInfo, secondHandleInfo);
2607 
2608     auto selectionVisible = !firstHandleInfo.isShow && !secondHandleInfo.isShow && CheckSelectionRectVisible();
2609     proxy->SetSelectRegionVisible(selectionVisible);
2610 }
2611 
GetSelectHandleInfo(OffsetF offset)2612 SelectHandleInfo TextFieldPattern::GetSelectHandleInfo(OffsetF offset)
2613 {
2614     SizeF handlePaintSize = { SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(),
2615         selectController_->GetCaretRect().Height() };
2616     // 要将相对textRect的坐标转换为全局坐标
2617     auto paintRect = RectF(offset.GetX() + GetTextPaintOffset().GetX(), offset.GetY() + GetTextPaintOffset().GetY(),
2618         handlePaintSize.Width(), handlePaintSize.Height());
2619     return { .isShow = CheckHandleVisible(paintRect), .paintRect = paintRect };
2620 }
2621 
AllowCopy()2622 bool TextFieldPattern::AllowCopy()
2623 {
2624     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2625     CHECK_NULL_RETURN(layoutProperty, false);
2626     return layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) != CopyOptions::None && !IsInPasswordMode();
2627 }
2628 
OnDetachFromFrameNode(FrameNode * node)2629 void TextFieldPattern::OnDetachFromFrameNode(FrameNode* node)
2630 {
2631     CloseSelectOverlay();
2632     ResetSelectOverlayClient();
2633     auto pipeline = PipelineContext::GetCurrentContext();
2634     CHECK_NULL_VOID(pipeline);
2635     if (HasSurfaceChangedCallback()) {
2636         pipeline->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
2637     }
2638     if (HasSurfacePositionChangedCallback()) {
2639         pipeline->UnregisterSurfacePositionChangedCallback(surfacePositionChangedCallbackId_.value_or(-1));
2640     }
2641     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
2642     if (textFieldManager) {
2643         textFieldManager->ClearOnFocusTextField();
2644     }
2645     auto frameNode = WeakClaim(node);
2646     pipeline->RemoveFontNodeNG(frameNode);
2647     auto fontManager = pipeline->GetFontManager();
2648     if (fontManager) {
2649         fontManager->UnRegisterCallbackNG(frameNode);
2650         fontManager->RemoveVariationNodeNG(frameNode);
2651     }
2652     pipeline->RemoveOnAreaChangeNode(node->GetId());
2653 }
2654 
CloseSelectOverlay()2655 void TextFieldPattern::CloseSelectOverlay()
2656 {
2657     CloseSelectOverlay(false);
2658 }
2659 
CloseSelectOverlay(bool animation)2660 void TextFieldPattern::CloseSelectOverlay(bool animation)
2661 {
2662     RequestCloseSelectOverlay(animation);
2663     auto host = GetHost();
2664     CHECK_NULL_VOID(host);
2665     auto gesture = host->GetOrCreateGestureEventHub();
2666     gesture->AddTouchEvent(GetTouchListener());
2667 }
2668 
OnHandleMove(const RectF & handleRect,bool isFirstHandle)2669 void TextFieldPattern::OnHandleMove(const RectF& handleRect, bool isFirstHandle)
2670 {
2671     CHECK_NULL_VOID(SelectOverlayIsOn());
2672     CHECK_NULL_VOID(!contentController_->IsEmpty());
2673     auto localOffset = handleRect.GetOffset() - parentGlobalOffset_;
2674     SetLocalOffset(localOffset);
2675     if (isSingleHandle_) {
2676         selectController_->UpdateCaretInfoByOffset(Offset(localOffset.GetX(), localOffset.GetY()));
2677     } else {
2678         auto proxy = GetSelectOverlayProxy();
2679         CHECK_NULL_VOID(proxy);
2680         auto position = UpdateCaretPositionOnHandleMove(localOffset);
2681         if (isFirstHandle) {
2682             selectController_->MoveFirstHandleToContentRect(position);
2683             SelectHandleInfo handleInfo = GetSelectHandleInfo(selectController_->GetSecondHandleOffset());
2684             proxy->UpdateSecondSelectHandleInfo(handleInfo);
2685         } else {
2686             selectController_->MoveSecondHandleToContentRect(position);
2687             SelectHandleInfo handleInfo = GetSelectHandleInfo(selectController_->GetFirstHandleOffset());
2688             proxy->UpdateFirstSelectHandleInfo(handleInfo);
2689         }
2690         proxy->SetHandleReverse(selectController_->HasReverse());
2691     }
2692     UpdateRecordCaretIndex(selectController_->GetCaretIndex());
2693     auto tmpHost = GetHost();
2694     CHECK_NULL_VOID(tmpHost);
2695     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2696 }
2697 
UpdateCaretPositionOnHandleMove(const OffsetF & localOffset)2698 int32_t TextFieldPattern::UpdateCaretPositionOnHandleMove(const OffsetF& localOffset)
2699 {
2700     int32_t position = 0;
2701     if (!IsTextArea()) {
2702         if (LessNotEqual(localOffset.GetX(), contentRect_.GetX())) {
2703             position = std::max(static_cast<int32_t>(selectController_->GetStartIndex() -
2704                                                      GetGraphemeClusterLength(contentController_->GetWideText(),
2705                                                          selectController_->GetStartIndex(), true)),
2706                 0);
2707         } else if (GreatOrEqual(localOffset.GetX(), contentRect_.GetX() + contentRect_.Width())) {
2708             position = std::min(static_cast<int32_t>(selectController_->GetEndIndex() +
2709                                                      GetGraphemeClusterLength(contentController_->GetWideText(),
2710                                                          selectController_->GetEndIndex())),
2711                 static_cast<int32_t>(contentController_->GetWideText().length()));
2712         } else {
2713             Offset offset(localOffset.GetX() - textRect_.GetX(), 0.0f);
2714             position = ConvertTouchOffsetToCaretPosition(offset);
2715         }
2716         return position;
2717     }
2718     if (LessNotEqual(localOffset.GetY(), contentRect_.GetY())) {
2719         position = ConvertTouchOffsetToCaretPosition(Offset(
2720             localOffset.GetX() - GetPaddingLeft(), localOffset.GetY() - textRect_.GetY() - PreferredLineHeight()));
2721     } else if (GreatOrEqual(localOffset.GetY(), contentRect_.GetY() + contentRect_.Height())) {
2722         position = ConvertTouchOffsetToCaretPosition(Offset(
2723             localOffset.GetX() - GetPaddingLeft(), localOffset.GetY() - textRect_.GetY() + PreferredLineHeight()));
2724     } else {
2725         position = ConvertTouchOffsetToCaretPosition(
2726             Offset(localOffset.GetX() - GetPaddingLeft(), localOffset.GetY() - textRect_.GetY()));
2727     }
2728     return position;
2729 }
2730 
UpdateCopyAllStatus()2731 void TextFieldPattern::UpdateCopyAllStatus()
2732 {
2733     auto host = GetHost();
2734     CHECK_NULL_VOID(host);
2735     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2736     CHECK_NULL_VOID(layoutProperty);
2737     if (!layoutProperty->GetSelectionMenuHiddenValue(false)) {
2738         UpdateSelectMenuInfo([weak = WeakClaim(this)](SelectMenuInfo& menuInfo) {
2739             auto pattern = weak.Upgrade();
2740             CHECK_NULL_VOID(pattern);
2741             menuInfo.showCopyAll = !pattern->IsSelectAll();
2742         });
2743     }
2744 }
2745 
OnHandleMoveDone(const RectF &,bool isFirstHandle)2746 void TextFieldPattern::OnHandleMoveDone(const RectF& /* handleRect */, bool isFirstHandle)
2747 {
2748     UpdateCopyAllStatus();
2749     UpdateShowMagnifier();
2750     auto proxy = GetSelectOverlayProxy();
2751     CHECK_NULL_VOID(proxy);
2752     if (!isSingleHandle_) {
2753         if (selectController_->GetFirstHandleIndex() == selectController_->GetSecondHandleIndex()) {
2754             UpdateSelectMenuVisibility(false);
2755             CloseSelectOverlay(true);
2756             StartTwinkling();
2757             selectController_->MoveCaretToContentRect(GetCaretIndex());
2758         } else {
2759             auto firstHandleInfo = GetSelectHandleInfo(selectController_->GetFirstHandleOffset());
2760             auto secondHandleInfo = GetSelectHandleInfo(selectController_->GetSecondHandleOffset());
2761             proxy->UpdateFirstAndSecondHandleInfo(firstHandleInfo, secondHandleInfo);
2762             proxy->SetHandleReverse(selectController_->HasReverse());
2763         }
2764     } else {
2765         auto handleInfo = GetSelectHandleInfo(selectController_->GetCaretRect().GetOffset());
2766         handleInfo.paintRect.SetWidth(selectController_->GetCaretRect().Width());
2767         proxy->UpdateSecondSelectHandleInfo(handleInfo);
2768     }
2769     UpdateOverlaySelectArea();
2770     UpdateSelectMenuVisibility(true);
2771     auto tmpHost = GetHost();
2772     CHECK_NULL_VOID(tmpHost);
2773     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2774 }
2775 
OnHandleClosed(bool closedByGlobalEvent)2776 void TextFieldPattern::OnHandleClosed(bool closedByGlobalEvent)
2777 {
2778     SelectOverlayClient::OnHandleClosed(closedByGlobalEvent);
2779     if (closedByGlobalEvent) {
2780         UpdateSelectMenuVisibility(false);
2781     }
2782     if (GetShowMagnifier()) {
2783         UpdateShowMagnifier();
2784     }
2785 }
2786 
InitEditingValueText(std::string content)2787 void TextFieldPattern::InitEditingValueText(std::string content)
2788 {
2789     if (HasInputOperation()) {
2790         return;
2791     }
2792     contentController_->SetTextValueOnly(std::move(content));
2793     selectController_->UpdateCaretIndex(GetWideText().length());
2794     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
2795 }
2796 
InitValueText(std::string content)2797 void TextFieldPattern::InitValueText(std::string content)
2798 {
2799     if (HasInputOperation() && content != "") {
2800         return;
2801     }
2802     contentController_->SetTextValueOnly(std::move(content));
2803     selectController_->UpdateCaretIndex(GetWideText().length());
2804     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
2805 }
2806 
InitMouseEvent()2807 void TextFieldPattern::InitMouseEvent()
2808 {
2809     CHECK_NULL_VOID(!mouseEvent_ || !hoverEvent_);
2810     auto tmpHost = GetHost();
2811     CHECK_NULL_VOID(tmpHost);
2812     auto eventHub = tmpHost->GetEventHub<TextFieldEventHub>();
2813     auto inputHub = eventHub->GetOrCreateInputEventHub();
2814 
2815     auto mouseTask = [weak = WeakClaim(this)](MouseInfo& info) {
2816         auto pattern = weak.Upgrade();
2817         if (pattern) {
2818             pattern->HandleMouseEvent(info);
2819         }
2820     };
2821     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
2822     inputHub->AddOnMouseEvent(mouseEvent_);
2823 
2824     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
2825         auto pattern = weak.Upgrade();
2826         if (pattern) {
2827             pattern->OnHover(isHover);
2828         }
2829     };
2830     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
2831     inputHub->AddOnHoverEvent(hoverEvent_);
2832 }
2833 
OnHover(bool isHover)2834 void TextFieldPattern::OnHover(bool isHover)
2835 {
2836     auto tmpHost = GetHost();
2837     CHECK_NULL_VOID(tmpHost);
2838     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield %{public}d %{public}s", tmpHost->GetId(),
2839         isHover ? "on hover" : "exit hover");
2840     auto frameId = tmpHost->GetId();
2841     auto pipeline = PipelineContext::GetCurrentContext();
2842     CHECK_NULL_VOID(pipeline);
2843     auto textFieldTheme = GetTheme();
2844     CHECK_NULL_VOID(textFieldTheme);
2845     if (isHover) {
2846         pipeline->SetMouseStyleHoldNode(frameId);
2847     } else {
2848         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT);
2849         pipeline->FreeMouseStyleHoldNode(frameId);
2850     }
2851     isOnHover_ = isHover;
2852     if (enableTouchAndHoverEffect_) {
2853         auto textfieldPaintProperty = GetPaintProperty<TextFieldPaintProperty>();
2854         CHECK_NULL_VOID(textfieldPaintProperty);
2855         auto renderContext = tmpHost->GetRenderContext();
2856         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2857         CHECK_NULL_VOID(layoutProperty);
2858         if (isOnHover_) {
2859             if (layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType()) {
2860                 auto radius = textFieldTheme->GetBorderRadiusSize();
2861                 renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
2862             }
2863             tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2864             return;
2865         }
2866         isOnHover_ = false;
2867         if (!isMousePressed_) {
2868             if (layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType()) {
2869                 renderContext->UpdateBorderRadius(borderRadius_);
2870             }
2871             if (layoutProperty->GetShowUnderlineValue(false) && HasFocus() && IsUnspecifiedOrTextType()) {
2872                 auto radius = textFieldTheme->GetBorderRadiusSize();
2873                 renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
2874             }
2875         }
2876         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2877     }
2878 }
2879 
ChangeMouseState(const Offset location,const RefPtr<PipelineContext> & pipeline,int32_t frameId)2880 void TextFieldPattern::ChangeMouseState(const Offset location, const RefPtr<PipelineContext>& pipeline, int32_t frameId)
2881 {
2882     auto responseAreaWidth = (responseArea_ ? responseArea_->GetAreaRect().Width() : 0.0f) +
2883                              (cleanNodeResponseArea_ ? cleanNodeResponseArea_->GetAreaRect().Width() : 0.0f);
2884     auto x = location.GetX();
2885     auto y = location.GetY();
2886     if (GreatNotEqual(x, 0) && LessNotEqual(x, frameRect_.Width()) && GreatNotEqual(y, 0) &&
2887         LessNotEqual(y, frameRect_.Height())) {
2888         if (GreatNotEqual(location.GetX(), frameRect_.Width() - responseAreaWidth)) {
2889             pipeline->SetMouseStyleHoldNode(frameId);
2890             pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT);
2891         } else {
2892             pipeline->SetMouseStyleHoldNode(frameId);
2893             pipeline->ChangeMouseStyle(frameId, MouseFormat::TEXT_CURSOR);
2894         }
2895     } else {
2896         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT);
2897         pipeline->FreeMouseStyleHoldNode(frameId);
2898     }
2899 }
2900 
HandleMouseEvent(MouseInfo & info)2901 void TextFieldPattern::HandleMouseEvent(MouseInfo& info)
2902 {
2903     auto tmpHost = GetHost();
2904     CHECK_NULL_VOID(tmpHost);
2905     auto frameId = tmpHost->GetId();
2906     auto pipeline = PipelineContext::GetCurrentContext();
2907     CHECK_NULL_VOID(pipeline);
2908     info.SetStopPropagation(true);
2909     auto scrollBar = GetScrollBar();
2910     if (scrollBar && (scrollBar->IsPressed() || scrollBar->IsHover())) {
2911         pipeline->SetMouseStyleHoldNode(frameId);
2912         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT);
2913         return;
2914     }
2915     ChangeMouseState(info.GetLocalLocation(), pipeline, frameId);
2916 
2917     isUsingMouse_ = true;
2918     if (info.GetButton() == MouseButton::RIGHT_BUTTON) {
2919         HandleRightMouseEvent(info);
2920     } else if (info.GetButton() == MouseButton::LEFT_BUTTON) {
2921         HandleLeftMouseEvent(info);
2922         if (IsSelected()) {
2923             PushSelectedByMouseInfoToManager();
2924         }
2925     }
2926     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
2927         isUsingMouse_ = false;
2928     }
2929 }
2930 
PushSelectedByMouseInfoToManager()2931 void TextFieldPattern::PushSelectedByMouseInfoToManager()
2932 {
2933     SelectedByMouseInfo selectedByMouseInfo;
2934     selectedByMouseInfo.selectedNode = GetHost();
2935     selectedByMouseInfo.onResetSelection = [weak = WeakClaim(this)]() {
2936         auto pattern = weak.Upgrade();
2937         CHECK_NULL_VOID(pattern);
2938         pattern->SetCaretPosition(pattern->GetTextSelectController()->GetEndIndex());
2939     };
2940     SetSelectionNode(selectedByMouseInfo);
2941 }
2942 
HandleRightMouseEvent(MouseInfo & info)2943 void TextFieldPattern::HandleRightMouseEvent(MouseInfo& info)
2944 {
2945     if (info.GetAction() == OHOS::Ace::MouseAction::PRESS) {
2946         HandleRightMousePressEvent(info);
2947         return;
2948     }
2949     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
2950         HandleRightMouseReleaseEvent(info);
2951     }
2952 }
2953 
HandleRightMousePressEvent(MouseInfo & info)2954 void TextFieldPattern::HandleRightMousePressEvent(MouseInfo& info)
2955 {
2956     if (IsSelected()) {
2957         return;
2958     }
2959     auto focusHub = GetFocusHub();
2960     if (!focusHub->IsFocusable()) {
2961         return;
2962     }
2963     FocusAndUpdateCaretByMouse(info);
2964 }
2965 
HandleRightMouseReleaseEvent(MouseInfo & info)2966 void TextFieldPattern::HandleRightMouseReleaseEvent(MouseInfo& info)
2967 {
2968     auto focusHub = GetFocusHub();
2969     if (focusHub->IsCurrentFocus()) {
2970         rightClickOffset_ = OffsetF(
2971             static_cast<float>(info.GetGlobalLocation().GetX()), static_cast<float>(info.GetGlobalLocation().GetY()));
2972         if (SelectOverlayIsOn()) {
2973             CloseSelectOverlay(true);
2974         }
2975         ProcessOverlay();
2976     }
2977 }
2978 
HandleLeftMouseEvent(MouseInfo & info)2979 void TextFieldPattern::HandleLeftMouseEvent(MouseInfo& info)
2980 {
2981     switch (info.GetAction()) {
2982         case OHOS::Ace::MouseAction::PRESS: {
2983             HandleLeftMousePressEvent(info);
2984             break;
2985         }
2986         case OHOS::Ace::MouseAction::MOVE: {
2987             HandleLeftMouseMoveEvent(info); // 注意鼠标拖拽的滚动效果
2988             break;
2989         }
2990         case OHOS::Ace::MouseAction::RELEASE: {
2991             HandleLeftMouseReleaseEvent(info);
2992             break;
2993         }
2994         default: {
2995         }
2996     }
2997 }
2998 
HandleLeftMousePressEvent(MouseInfo & info)2999 void TextFieldPattern::HandleLeftMousePressEvent(MouseInfo& info)
3000 {
3001     if (IsSelected() && BetweenSelectedPosition(info.GetGlobalLocation())) {
3002         blockPress_ = true;
3003         return;
3004     }
3005     auto focusHub = GetFocusHub();
3006     if (!focusHub->IsFocusable()) {
3007         return;
3008     }
3009     mouseStatus_ = MouseStatus::PRESSED;
3010     blockPress_ = false;
3011     leftMouseCanMove_ = true;
3012     FocusAndUpdateCaretByMouse(info);
3013 }
3014 
FocusAndUpdateCaretByMouse(MouseInfo & info)3015 void TextFieldPattern::FocusAndUpdateCaretByMouse(MouseInfo& info)
3016 {
3017     auto focusHub = GetFocusHub();
3018     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
3019     CHECK_NULL_VOID(paintProperty);
3020     if (!focusHub->IsFocusOnTouch().value_or(true) || !focusHub->RequestFocusImmediately()) {
3021         StopTwinkling();
3022         return;
3023     }
3024     selectController_->UpdateCaretInfoByOffset(info.GetLocalLocation());
3025     StartTwinkling();
3026     auto tmpHost = GetHost();
3027     CHECK_NULL_VOID(tmpHost);
3028     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3029 }
3030 
HandleLeftMouseMoveEvent(MouseInfo & info)3031 void TextFieldPattern::HandleLeftMouseMoveEvent(MouseInfo& info)
3032 {
3033     if (!leftMouseCanMove_ || blockPress_) {
3034         return;
3035     }
3036     auto focusHub = GetFocusHub();
3037     if (!focusHub->IsCurrentFocus()) {
3038         return;
3039     }
3040     mouseStatus_ = MouseStatus::MOVE;
3041     selectController_->UpdateSecondHandleInfoByMouseOffset(info.GetLocalLocation()); // 更新时上报事件
3042     UpdateRecordCaretIndex(
3043         std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
3044     showSelect_ = true;
3045     auto tmpHost = GetHost();
3046     CHECK_NULL_VOID(tmpHost);
3047     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3048 }
3049 
HandleLeftMouseReleaseEvent(MouseInfo & info)3050 void TextFieldPattern::HandleLeftMouseReleaseEvent(MouseInfo& info)
3051 {
3052     auto tmpHost = GetHost();
3053     CHECK_NULL_VOID(tmpHost);
3054     if (blockPress_ && mouseStatus_ == MouseStatus::PRESSED) {
3055         selectController_->UpdateCaretInfoByOffset(info.GetLocalLocation());
3056         StartTwinkling();
3057         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3058     }
3059     mouseStatus_ = MouseStatus::NONE;
3060     blockPress_ = false;
3061     leftMouseCanMove_ = false;
3062     if (HasFocus() && RequestKeyboard(false, true, true)) {
3063         NotifyOnEditChanged(true);
3064         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3065     }
3066 }
3067 
UpdateTextFieldManager(const Offset & offset,float height)3068 void TextFieldPattern::UpdateTextFieldManager(const Offset& offset, float height)
3069 {
3070     auto tmpHost = GetHost();
3071     CHECK_NULL_VOID(tmpHost);
3072     auto context = tmpHost->GetContext();
3073     CHECK_NULL_VOID(context);
3074     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
3075     CHECK_NULL_VOID(textFieldManager);
3076     textFieldManager->UpdateScrollableParentViewPort(tmpHost);
3077     if (!HasFocus()) {
3078         return;
3079     }
3080     textFieldManager->SetClickPosition({ offset.GetX() + selectController_->GetCaretRect().GetX(),
3081         offset.GetY() + selectController_->GetCaretRect().GetY() });
3082     textFieldManager->SetHeight(selectController_->GetCaretRect().Height());
3083     textFieldManager->SetOnFocusTextField(WeakClaim(this));
3084 }
3085 
GetDefaultTextInputAction() const3086 TextInputAction TextFieldPattern::GetDefaultTextInputAction() const
3087 {
3088     TextInputAction defaultTextInputAction = TextInputAction::DONE;
3089     if (IsTextArea() && !isTextInput_) {
3090         defaultTextInputAction = TextInputAction::NEW_LINE;
3091     } else {
3092         defaultTextInputAction = TextInputAction::DONE;
3093     }
3094     return defaultTextInputAction;
3095 }
3096 
3097 #ifdef WINDOW_SCENE_SUPPORTED
GetSCBSystemWindowId()3098 uint32_t TextFieldPattern::GetSCBSystemWindowId()
3099 {
3100     RefPtr<FrameNode> frameNode = GetHost();
3101     CHECK_NULL_RETURN(frameNode, {});
3102     auto focusSystemWindowId = WindowSceneHelper::GetFocusSystemWindowId(frameNode);
3103     return focusSystemWindowId;
3104 }
3105 #endif
3106 
RequestKeyboard(bool isFocusViewChanged,bool needStartTwinkling,bool needShowSoftKeyboard)3107 bool TextFieldPattern::RequestKeyboard(bool isFocusViewChanged, bool needStartTwinkling, bool needShowSoftKeyboard)
3108 {
3109     auto tmpHost = GetHost();
3110     CHECK_NULL_RETURN(tmpHost, false);
3111     auto context = tmpHost->GetContext();
3112     CHECK_NULL_RETURN(context, false);
3113 
3114     if (needShowSoftKeyboard) {
3115         if (customKeyboardBuilder_) {
3116             return RequestCustomKeyboard();
3117         }
3118 #if defined(ENABLE_STANDARD_INPUT)
3119         if (textChangeListener_ == nullptr) {
3120             textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
3121         }
3122         auto inputMethod = MiscServices::InputMethodController::GetInstance();
3123         if (!inputMethod) {
3124             return false;
3125         }
3126         auto optionalTextConfig = GetMiscTextConfig();
3127         CHECK_NULL_RETURN(optionalTextConfig.has_value(), false);
3128         MiscServices::TextConfig textConfig = optionalTextConfig.value();
3129         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
3130             "RequestKeyboard set calling window id:%{public}u"
3131             "inputType: %{public}d",
3132             textConfig.windowId, textConfig.inputAttribute.inputPattern);
3133 #ifdef WINDOW_SCENE_SUPPORTED
3134         auto systemWindowId = GetSCBSystemWindowId();
3135         if (systemWindowId) {
3136             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "windowId From %{public}u to %{public}u.", textConfig.windowId,
3137                 systemWindowId);
3138             textConfig.windowId = systemWindowId;
3139         }
3140 #endif
3141         if (customKeyboardBuilder_ && isCustomKeyboardAttached_) {
3142             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Request Softkeyboard,Close CustomKeyboard.");
3143             CloseCustomKeyboard();
3144         }
3145         inputMethod->Attach(textChangeListener_, needShowSoftKeyboard, textConfig);
3146         UpdateKeyboardOffset(textConfig.positionY, textConfig.height);
3147 #else
3148         if (!HasConnection()) {
3149             TextInputConfiguration config;
3150             config.type = keyboard_;
3151             config.action = GetTextInputActionValue(GetDefaultTextInputAction());
3152             config.inputFilter = GetInputFilter();
3153             config.maxLength = GetMaxLength();
3154             if (keyboard_ == TextInputType::VISIBLE_PASSWORD || keyboard_ == TextInputType::NEW_PASSWORD) {
3155                 config.obscureText = textObscured_;
3156             }
3157             connection_ = TextInputProxy::GetInstance().Attach(
3158                 WeakClaim(this), config, context->GetTaskExecutor(), GetInstanceId());
3159 
3160             if (!HasConnection()) {
3161                 return false;
3162             }
3163             TextEditingValue value;
3164             value.text = contentController_->GetTextValue();
3165             value.hint = GetPlaceHolder();
3166             value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
3167             connection_->SetEditingState(value, GetInstanceId());
3168         }
3169         connection_->Show(isFocusViewChanged, GetInstanceId());
3170 #endif
3171     }
3172     return true;
3173 }
3174 
3175 #if defined(ENABLE_STANDARD_INPUT)
GetMiscTextConfig() const3176 std::optional<MiscServices::TextConfig> TextFieldPattern::GetMiscTextConfig() const
3177 {
3178     auto tmpHost = GetHost();
3179     CHECK_NULL_RETURN(tmpHost, {});
3180     auto pipeline = tmpHost->GetContext();
3181     CHECK_NULL_RETURN(pipeline, {});
3182     auto theme = GetTheme();
3183     CHECK_NULL_RETURN(theme, {});
3184     auto windowRect = pipeline->GetCurrentWindowRect();
3185     double positionY = (tmpHost->GetPaintRectOffset() - pipeline->GetRootRect().GetOffset()).GetY() + windowRect.Top();
3186     double height = frameRect_.Height();
3187     auto offset = AVOID_OFFSET.ConvertToPx();
3188     height = selectController_->GetCaretRect().Bottom() + windowRect.Top() + parentGlobalOffset_.GetY() + offset
3189         - positionY;
3190 
3191     if (IsNormalInlineState()) {
3192         auto safeBoundary = theme->GetInlineBorderWidth().ConvertToPx() * 2;
3193         positionY += static_cast<double>(inlineMeasureItem_.inlineSizeHeight) + safeBoundary;
3194         height = offset;
3195     }
3196 
3197     MiscServices::CursorInfo cursorInfo { .left = selectController_->GetCaretRect().Left() + windowRect.Left() +
3198                                                   parentGlobalOffset_.GetX(),
3199         .top = selectController_->GetCaretRect().Top() + windowRect.Top() + parentGlobalOffset_.GetY(),
3200         .width = theme->GetCursorWidth().ConvertToPx(),
3201         .height = selectController_->GetCaretRect().Height() };
3202     MiscServices::InputAttribute inputAttribute = { .inputPattern = (int32_t)keyboard_,
3203         .enterKeyType = (int32_t)GetTextInputActionValue(GetDefaultTextInputAction()) };
3204     MiscServices::TextConfig textConfig = { .inputAttribute = inputAttribute,
3205         .cursorInfo = cursorInfo,
3206         .range = { .start = selectController_->GetStartIndex(), .end = selectController_->GetEndIndex() },
3207         .windowId = pipeline->GetFocusWindowId(),
3208         .positionY = positionY,
3209         .height = height };
3210 
3211     if (keyboard_ == TextInputType::NUMBER_DECIMAL) {
3212         textConfig.inputAttribute.inputPattern = (int32_t)TextInputType::NUMBER;
3213     }
3214     return textConfig;
3215 }
3216 #endif
3217 
ConvertToAceAutoFillType(TextInputType type)3218 AceAutoFillType TextFieldPattern::ConvertToAceAutoFillType(TextInputType type)
3219 {
3220     static std::unordered_map<TextInputType, AceAutoFillType> convertMap = {
3221         { TextInputType::VISIBLE_PASSWORD, AceAutoFillType::ACE_PASSWORD },
3222         { TextInputType::USER_NAME, AceAutoFillType::ACE_USER_NAME },
3223         { TextInputType::NEW_PASSWORD, AceAutoFillType::ACE_NEW_PASSWORD } };
3224     if (convertMap.find(type) != convertMap.end()) {
3225         return convertMap[type];
3226     }
3227     return AceAutoFillType::ACE_UNSPECIFIED;
3228 }
3229 
CloseKeyboard(bool forceClose)3230 bool TextFieldPattern::CloseKeyboard(bool forceClose)
3231 {
3232     return CloseKeyboard(forceClose, forceClose);
3233 }
3234 
CloseKeyboard(bool forceClose,bool isStopTwinkling)3235 bool TextFieldPattern::CloseKeyboard(bool forceClose, bool isStopTwinkling)
3236 {
3237     if (forceClose) {
3238         if (isStopTwinkling) {
3239             StopTwinkling();
3240         }
3241         CloseSelectOverlay(true);
3242         if (customKeyboardBuilder_ && isCustomKeyboardAttached_) {
3243             return CloseCustomKeyboard();
3244         }
3245         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Request close soft keyboard.");
3246 #if defined(ENABLE_STANDARD_INPUT)
3247         auto inputMethod = MiscServices::InputMethodController::GetInstance();
3248         if (!inputMethod) {
3249             return false;
3250         }
3251         inputMethod->Close();
3252 #else
3253         if (HasConnection()) {
3254             connection_->Close(GetInstanceId());
3255             connection_ = nullptr;
3256         }
3257 #endif
3258         return true;
3259     }
3260     return false;
3261 }
3262 
RequestCustomKeyboard()3263 bool TextFieldPattern::RequestCustomKeyboard()
3264 {
3265 #if defined(ENABLE_STANDARD_INPUT)
3266     auto inputMethod = MiscServices::InputMethodController::GetInstance();
3267     if (inputMethod) {
3268         inputMethod->RequestHideInput();
3269         inputMethod->Close();
3270     }
3271 #else
3272     if (HasConnection()) {
3273         connection_->Close(GetInstanceId());
3274         connection_ = nullptr;
3275     }
3276 #endif
3277 
3278     if (isCustomKeyboardAttached_) {
3279         return true;
3280     }
3281     CHECK_NULL_RETURN(customKeyboardBuilder_, false);
3282     auto frameNode = GetHost();
3283     CHECK_NULL_RETURN(frameNode, false);
3284     auto pipeline = PipelineContext::GetCurrentContext();
3285     CHECK_NULL_RETURN(pipeline, false);
3286     auto overlayManager = pipeline->GetOverlayManager();
3287     CHECK_NULL_RETURN(overlayManager, false);
3288     overlayManager->BindKeyboard(customKeyboardBuilder_, frameNode->GetId());
3289     isCustomKeyboardAttached_ = true;
3290     keyboardOverlay_ = overlayManager;
3291     return true;
3292 }
3293 
CloseCustomKeyboard()3294 bool TextFieldPattern::CloseCustomKeyboard()
3295 {
3296     auto frameNode = GetHost();
3297     CHECK_NULL_RETURN(frameNode, false);
3298     CHECK_NULL_RETURN(keyboardOverlay_, false);
3299     keyboardOverlay_->CloseKeyboard(frameNode->GetId());
3300     isCustomKeyboardAttached_ = false;
3301     return true;
3302 }
3303 
OnTextInputActionUpdate(TextInputAction value)3304 void TextFieldPattern::OnTextInputActionUpdate(TextInputAction value) {}
3305 
InsertValueOperation(const std::string & insertValue)3306 void TextFieldPattern::InsertValueOperation(const std::string& insertValue)
3307 {
3308     auto caretStart = 0;
3309     auto host = GetHost();
3310     CHECK_NULL_VOID(host);
3311     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3312     CHECK_NULL_VOID(layoutProperty);
3313     auto start = selectController_->GetStartIndex();
3314     auto end = selectController_->GetEndIndex();
3315     if (IsSelected()) {
3316         caretStart = start;
3317     } else {
3318         caretStart = selectController_->GetCaretIndex();
3319     }
3320     int32_t caretMoveLength = 0;
3321     bool hasInsertValue = false;
3322     if (IsSelected()) {
3323         auto originLength = static_cast<int32_t>(contentController_->GetWideText().length()) - (end - start);
3324         hasInsertValue = contentController_->ReplaceSelectedValue(start, end, insertValue);
3325         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetWideText().length()) - originLength);
3326     } else {
3327         auto originLength = static_cast<int32_t>(contentController_->GetWideText().length());
3328         hasInsertValue = contentController_->InsertValue(selectController_->GetCaretIndex(), insertValue);
3329         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetWideText().length()) - originLength);
3330     }
3331     auto wideInsertValue = StringUtils::ToWstring(insertValue);
3332     selectController_->UpdateCaretIndex(caretStart + caretMoveLength);
3333     if (!IsTextArea() && IsInPasswordMode() && GetTextObscured()) {
3334         if (wideInsertValue.length() == 1 &&
3335             (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) != TextInputType::NUMBER_PASSWORD ||
3336                 std::isdigit(insertValue[0])) && hasInsertValue) {
3337             auto content = contentController_->GetWideText();
3338             auto insertIndex = selectController_->GetCaretIndex() - 1;
3339             insertIndex = std::clamp(insertIndex, 0, static_cast<int32_t>(content.length()));
3340             auto strBeforeCaret = content.empty() ? "" : StringUtils::ToString(content.substr(insertIndex, 1));
3341             obscureTickCountDown_ = strBeforeCaret == insertValue ? OBSCURE_SHOW_TICKS : 0;
3342             nakedCharPosition_ = strBeforeCaret == insertValue ? insertIndex : -1;
3343         } else {
3344             obscureTickCountDown_ = 0;
3345             nakedCharPosition_ = -1;
3346         }
3347     }
3348     UpdateEditingValueToRecord();
3349     if (HasFocus()) {
3350         cursorVisible_ = true;
3351         StartTwinkling();
3352     } else {
3353         cursorVisible_ = false;
3354         StopTwinkling();
3355     }
3356 }
3357 
InsertValue(const std::string & insertValue)3358 void TextFieldPattern::InsertValue(const std::string& insertValue)
3359 {
3360     if (focusIndex_ != FocuseIndex::TEXT && insertValue == " ") {
3361         HandleSpaceEvent();
3362         return;
3363     }
3364     focusIndex_ = FocuseIndex::TEXT;
3365     if (SystemProperties::GetDebugEnabled()) {
3366         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Insert value '%{public}s'", insertValue.c_str());
3367     }
3368     auto host = GetHost();
3369     CHECK_NULL_VOID(host);
3370     auto maxlength = GetMaxLength();
3371     auto originLength = static_cast<int32_t>(contentController_->GetWideText().length());
3372     auto pattern = host->GetPattern<TextFieldPattern>();
3373     CHECK_NULL_VOID(pattern);
3374     auto textFieldLayoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3375     CHECK_NULL_VOID(textFieldLayoutProperty);
3376     auto inputValue = textFieldLayoutProperty->GetSetCounterValue(DEFAULT_MODE);
3377     auto pipeline = PipelineBase::GetCurrentContext();
3378     CHECK_NULL_VOID(pipeline);
3379     auto theme = pipeline->GetTheme<TextFieldTheme>();
3380     CHECK_NULL_VOID(theme);
3381     if (inputValue == DEFAULT_MODE) {
3382         originLength = originLength + ONE_CHARACTER;
3383     }
3384     if (textFieldLayoutProperty->GetShowCounterValue(false) && originLength == static_cast<int32_t>(maxlength) &&
3385         inputValue == DEFAULT_MODE) {
3386         UpdateCounterBorderStyle(originLength, maxlength);
3387     }
3388     bool noDeleteOperation = deleteBackwardOperations_.empty() && deleteForwardOperations_.empty();
3389     if (!IsShowPasswordIcon() && originLength == static_cast<int32_t>(maxlength) && noDeleteOperation &&
3390         !IsSelected() && textFieldLayoutProperty->GetShowCounterValue(false) && inputValue != DEFAULT_MODE &&
3391         inputValue != ILLEGAL_VALUE && !IsNormalInlineState()) {
3392         counterChange_ = true;
3393         UpdateOverCounterColor();
3394         UltralimitShake();
3395         return;
3396     }
3397     inputOperations_.emplace(InputOperation::INSERT);
3398     insertValueOperations_.emplace(insertValue);
3399     CloseSelectOverlay(true);
3400     ScrollToSafeArea();
3401     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
3402 }
3403 
HandleInputCounterBorder(int32_t & textLength,uint32_t & maxLength)3404 void TextFieldPattern::HandleInputCounterBorder(int32_t& textLength, uint32_t& maxLength)
3405 {
3406     auto host = GetHost();
3407     auto textFieldLayoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3408     CHECK_NULL_VOID(textFieldLayoutProperty);
3409     if (!textFieldLayoutProperty->GetShowCounterValue(false) || IsNormalInlineState() || IsShowPasswordIcon() ||
3410         !textFieldLayoutProperty->HasMaxLength()) {
3411         return;
3412     }
3413     auto inputValue = textFieldLayoutProperty->GetSetCounterValue(DEFAULT_MODE);
3414     if (textLength >= static_cast<int32_t>(maxLength) && inputValue == DEFAULT_MODE) {
3415         UpdateCounterBorderStyle(textLength, maxLength);
3416     }
3417 }
3418 
UpdateOverCounterColor()3419 void TextFieldPattern::UpdateOverCounterColor()
3420 {
3421     auto tmpHost = GetHost();
3422     CHECK_NULL_VOID(tmpHost);
3423     auto pipeline = PipelineBase::GetCurrentContext();
3424     CHECK_NULL_VOID(pipeline);
3425     auto theme = pipeline->GetTheme<TextFieldTheme>();
3426     CHECK_NULL_VOID(theme);
3427     auto counterNode = counterTextNode_.Upgrade();
3428     CHECK_NULL_VOID(counterNode);
3429     auto textFieldLayoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3430     CHECK_NULL_VOID(textFieldLayoutProperty);
3431     auto textLayoutProperty = DynamicCast<TextLayoutProperty>(counterNode->GetLayoutProperty());
3432     CHECK_NULL_VOID(textLayoutProperty);
3433     auto showBorder = textFieldLayoutProperty->GetShowHighlightBorderValue(true);
3434     TextStyle countTextStyle = theme->GetOverCountTextStyle();
3435     countTextStyle = theme->GetOverCountTextStyle();
3436     countTextStyle.SetTextColor(theme->GetOverCounterColor());
3437     textLayoutProperty->UpdateTextColor(countTextStyle.GetTextColor());
3438     auto host = counterNode->GetHostNode();
3439     CHECK_NULL_VOID(host);
3440     auto context = host->GetRenderContext();
3441     CHECK_NULL_VOID(context);
3442     if (IsTextArea() && showBorder == true) {
3443         HandleCounterBorder();
3444     } else if (!IsTextArea() && showBorder == true) {
3445         underlineColor_ = theme->GetErrorUnderlineColor();
3446     }
3447     context->UpdateForegroundColor(countTextStyle.GetTextColor());
3448     host->MarkDirtyNode();
3449 }
3450 
UpdateCounterBorderStyle(int32_t & textLength,uint32_t & maxLength)3451 void TextFieldPattern::UpdateCounterBorderStyle(int32_t& textLength, uint32_t& maxLength)
3452 {
3453     auto frameNode = GetHost();
3454     CHECK_NULL_VOID(frameNode);
3455     auto pattern = frameNode->GetPattern<TextFieldPattern>();
3456     CHECK_NULL_VOID(pattern);
3457     auto pipeline = PipelineBase::GetCurrentContext();
3458     CHECK_NULL_VOID(pipeline);
3459     auto theme = pipeline->GetTheme<TextFieldTheme>();
3460     CHECK_NULL_VOID(theme);
3461     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
3462     CHECK_NULL_VOID(textFieldLayoutProperty);
3463     counterChange_ = true;
3464     auto showBorder = textFieldLayoutProperty->GetShowHighlightBorderValue(true);
3465     if (static_cast<uint32_t>(textLength) >= (maxLength - ONE_CHARACTER) && !IsTextArea() && showBorder == true) {
3466         SetUnderlineColor(theme->GetErrorUnderlineColor());
3467     } else if (textLength >= static_cast<int32_t>(maxLength) && IsTextArea() && showBorder == true) {
3468         HandleCounterBorder();
3469     }
3470     return;
3471 }
3472 
UltralimitShake()3473 void TextFieldPattern::UltralimitShake()
3474 {
3475     auto frameNode = GetHost();
3476     CHECK_NULL_VOID(frameNode);
3477     auto context = frameNode->GetRenderContext();
3478     CHECK_NULL_VOID(context);
3479     AnimationOption option;
3480     context->UpdateTranslateInXY({ -1.0, 0.0 });
3481     const RefPtr<InterpolatingSpring> curve =
3482         AceType::MakeRefPtr<InterpolatingSpring>(VELOCITY, MASS, STIFFNESS, DAMPING);
3483     option.SetCurve(curve);
3484     option.SetFillMode(FillMode::FORWARDS);
3485     auto pipelineContext = PipelineContext::GetCurrentContext();
3486     CHECK_NULL_VOID(pipelineContext);
3487     AnimationUtils::Animate(
3488         option,
3489         [context]() {
3490             if (context) {
3491                 context->UpdateTranslateInXY({ 0.0f, 0.0f });
3492             }
3493         },
3494         option.GetOnFinishEvent());
3495 }
3496 
UpdateCounterMargin()3497 void TextFieldPattern::UpdateCounterMargin()
3498 {
3499     auto host = GetHost();
3500     CHECK_NULL_VOID(host);
3501     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3502     CHECK_NULL_VOID(layoutProperty);
3503     if (!IsTextArea() && layoutProperty->GetShowCounterValue(false) && !IsNormalInlineState() &&
3504         !IsShowPasswordIcon()) {
3505         MarginProperty margin;
3506         const auto& getMargin = layoutProperty->GetMarginProperty();
3507         if (!getMargin || GetMarginBottom() == MARGIN_ZERO) {
3508             margin.bottom = CalcLength(COUNTER_BOTTOM);
3509             layoutProperty->UpdateMargin(margin);
3510             return;
3511         }
3512         Dimension marginProperty { BOTTOM_MARGIN, DimensionUnit::VP };
3513         auto systemMargin = getMargin->bottom->GetDimension();
3514         if (systemMargin < marginProperty) {
3515             margin.bottom = CalcLength(marginProperty);
3516             margin.left = CalcLength(getMargin->left->GetDimension());
3517             margin.top = CalcLength(getMargin->top->GetDimension());
3518             margin.right = CalcLength(getMargin->right->GetDimension());
3519             layoutProperty->UpdateMargin(margin);
3520         } else {
3521             margin.bottom = CalcLength(systemMargin);
3522             margin.left = CalcLength(getMargin->left->GetDimension());
3523             margin.top = CalcLength(getMargin->top->GetDimension());
3524             margin.right = CalcLength(getMargin->right->GetDimension());
3525             layoutProperty->UpdateMargin(margin);
3526         }
3527     }
3528 }
3529 
CleanCounterNode()3530 void TextFieldPattern::CleanCounterNode()
3531 {
3532     auto frameNode = GetHost();
3533     CHECK_NULL_VOID(frameNode);
3534     auto pattern = frameNode->GetPattern<TextFieldPattern>();
3535     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
3536     CHECK_NULL_VOID(textFieldLayoutProperty);
3537     auto counterNode = DynamicCast<UINode>(counterTextNode_.Upgrade());
3538     CHECK_NULL_VOID(counterNode);
3539     frameNode->RemoveChild(counterNode);
3540     frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
3541 }
3542 
UpdateEditingValueToRecord()3543 void TextFieldPattern::UpdateEditingValueToRecord()
3544 {
3545     if (operationRecords_.size() >= RECORD_MAX_LENGTH) {
3546         operationRecords_.erase(operationRecords_.begin());
3547     }
3548     TextEditingValueNG record {
3549         .text = contentController_->GetTextValue(),
3550         .caretPosition = selectController_->GetCaretIndex(),
3551     };
3552     operationRecords_.emplace_back(record);
3553 }
3554 
PreferredTextHeight(bool isPlaceholder,bool isAlgorithmMeasure)3555 float TextFieldPattern::PreferredTextHeight(bool isPlaceholder, bool isAlgorithmMeasure)
3556 {
3557     if (!isAlgorithmMeasure && paragraph_ && paragraph_->GetHeight() != 0.0f && paragraph_->GetLineCount() > 0) {
3558         return paragraph_->GetHeight() / paragraph_->GetLineCount();
3559     }
3560     RefPtr<Paragraph> paragraph;
3561     std::string textContent;
3562     TextStyle textStyle;
3563     auto tmpHost = GetHost();
3564     CHECK_NULL_RETURN(tmpHost, 0.0f);
3565     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3566     CHECK_NULL_RETURN(layoutProperty, 0.0f);
3567     auto textFieldTheme = GetTheme();
3568     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
3569     // use text or placeHolder value if exists, space otherwise
3570     if (!isPlaceholder) {
3571         TextFieldLayoutAlgorithm::UpdateTextStyle(tmpHost, layoutProperty, textFieldTheme, textStyle, false);
3572         textContent = "a";
3573     } else {
3574         TextFieldLayoutAlgorithm::UpdatePlaceholderTextStyle(tmpHost, layoutProperty, textFieldTheme, textStyle, false);
3575         textContent = "b";
3576     }
3577     if (textStyle.GetFontSize().IsNonPositive()) {
3578         textStyle.SetFontSize(DEFAULT_FONT);
3579     }
3580     ParagraphStyle paraStyle { .direction =
3581                                    TextFieldLayoutAlgorithm::GetTextDirection(contentController_->GetTextValue()),
3582         .align = textStyle.GetTextAlign(),
3583         .maxLines = textStyle.GetMaxLines(),
3584         .fontLocale = Localization::GetInstance()->GetFontLocale(),
3585         .wordBreak = textStyle.GetWordBreak(),
3586         .textOverflow = textStyle.GetTextOverflow(),
3587         .fontSize = textStyle.GetFontSize().ConvertToPx() };
3588     paragraph = Paragraph::Create(paraStyle, FontCollection::Current());
3589     CHECK_NULL_RETURN(paragraph, 0.0f);
3590     paragraph->AddText(StringUtils::Str8ToStr16(textContent));
3591     paragraph->Build();
3592     paragraph->Layout(std::numeric_limits<double>::infinity());
3593     return paragraph->GetHeight();
3594 }
3595 
PreferredLineHeight(bool isAlgorithmMeasure)3596 float TextFieldPattern::PreferredLineHeight(bool isAlgorithmMeasure)
3597 {
3598     return PreferredTextHeight(contentController_->IsEmpty(), isAlgorithmMeasure);
3599 }
3600 
OnCursorMoveDone(TextAffinity textAffinity)3601 void TextFieldPattern::OnCursorMoveDone(TextAffinity textAffinity)
3602 {
3603     auto tmpHost = GetHost();
3604     CHECK_NULL_VOID(tmpHost);
3605     StartTwinkling();
3606     CloseSelectOverlay();
3607     selectController_->MoveCaretToContentRect(GetCaretIndex(), textAffinity);
3608     if (ResetObscureTickCountDown()) {
3609         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3610     } else {
3611         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3612     }
3613 }
3614 
GetWordLength(int32_t originCaretPosition,int32_t directionMove)3615 int32_t TextFieldPattern::GetWordLength(int32_t originCaretPosition, int32_t directionMove)
3616 {
3617     if (contentController_->IsEmpty()) {
3618         return 0;
3619     }
3620     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
3621     if (originCaretPosition < 0 || originCaretPosition > textLength) {
3622         return 0;
3623     }
3624     // directionMove == 0 left, directionMove == 1 right
3625     // cannot get word length by current caret position and direction
3626     if ((directionMove == 0 && originCaretPosition == 0) || (directionMove == 1 && originCaretPosition == textLength)) {
3627         return 0;
3628     }
3629     int32_t offset = 0;
3630     int32_t strIndex = directionMove == 0 ? (originCaretPosition - 1) : originCaretPosition;
3631     auto wideTextValue = contentController_->GetWideText();
3632     if (wideTextValue[strIndex] == L' ') {
3633         int32_t wordStart = 0;
3634         int32_t wordEnd = 0;
3635         if (!paragraph_->GetWordBoundary(strIndex, wordStart, wordEnd)) {
3636             return 0;
3637         }
3638         if (directionMove == 1) {
3639             offset += (wordEnd - strIndex);
3640             return offset;
3641         } else {
3642             offset += (strIndex - wordStart + 1); // when move left, actual offset should add 1
3643             strIndex = (wordStart - 1);           // when move left, actual index should minus 1
3644         }
3645     }
3646     bool hasJumpBlank = false;
3647     for (; directionMove == 0 ? strIndex >= 0 : strIndex <= textLength;) {
3648         auto chr = wideTextValue[strIndex];
3649         if (StringUtils::IsLetterOrNumberForWchar(chr) || (chr == L' ' && directionMove == 1)) {
3650             if (directionMove == 1 && hasJumpBlank && chr != L' ') {
3651                 return offset;
3652             } else if (directionMove == 1 && !hasJumpBlank && chr == L' ') {
3653                 hasJumpBlank = true;
3654             }
3655             offset++;
3656         } else {
3657             if (offset <= 0) {
3658                 offset = 1;
3659             }
3660             break;
3661         }
3662         if (directionMove == 0) {
3663             strIndex--;
3664         } else {
3665             strIndex++;
3666         }
3667     }
3668     return offset;
3669 }
3670 
GetLineBeginPosition(int32_t originCaretPosition,bool needToCheckLineChanged)3671 int32_t TextFieldPattern::GetLineBeginPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
3672 {
3673     if (contentController_->IsEmpty()) {
3674         return 0;
3675     }
3676     auto wideTextValue = contentController_->GetWideText();
3677     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
3678     if (originCaretPosition < 0 || originCaretPosition > textLength) {
3679         return 0;
3680     }
3681     if (originCaretPosition == 0) {
3682         return originCaretPosition;
3683     }
3684     int32_t moveLineBeginOffset = 0;
3685     int32_t strIndex = originCaretPosition;
3686     do {
3687         moveLineBeginOffset++;
3688         strIndex--;
3689         // stop moving caret if reaches \n, text head or caret line changed
3690     } while (((strIndex > 0) && (wideTextValue[strIndex] != L'\n')) ||
3691              (needToCheckLineChanged && !CharLineChanged(strIndex)));
3692     if (strIndex < 0 || strIndex >= static_cast<int32_t>(wideTextValue.length())) {
3693         return 0;
3694     }
3695     if (wideTextValue[strIndex] == L'\n') {
3696         moveLineBeginOffset--;
3697     }
3698     if (moveLineBeginOffset > originCaretPosition) {
3699         return 0;
3700     }
3701     return originCaretPosition - moveLineBeginOffset;
3702 }
3703 
GetLineEndPosition(int32_t originCaretPosition,bool needToCheckLineChanged)3704 int32_t TextFieldPattern::GetLineEndPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
3705 {
3706     if (contentController_->IsEmpty()) {
3707         return 0;
3708     }
3709     auto wideTextValue = contentController_->GetWideText();
3710     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
3711     if (originCaretPosition < 0 || originCaretPosition > textLength) {
3712         return originCaretPosition;
3713     }
3714     if (originCaretPosition == textLength) {
3715         return originCaretPosition;
3716     }
3717     int32_t moveLineEndOffset = 0;
3718     int32_t strIndex = 0;
3719     for (strIndex = originCaretPosition; (strIndex <= textLength && wideTextValue[strIndex] != L'\n') ||
3720                                          (needToCheckLineChanged && !CharLineChanged(strIndex));
3721          strIndex++) {
3722         moveLineEndOffset++;
3723     }
3724     if (moveLineEndOffset > textLength - originCaretPosition) {
3725         return textLength;
3726     }
3727     return originCaretPosition + moveLineEndOffset;
3728 }
3729 
CharLineChanged(int32_t caretPosition)3730 bool TextFieldPattern::CharLineChanged(int32_t caretPosition)
3731 {
3732     if (caretPosition < 0 || caretPosition > static_cast<int32_t>(contentController_->GetWideText().length())) {
3733         return true;
3734     }
3735     CaretMetricsF caretMetrics;
3736     CalcCaretMetricsByPosition(selectController_->GetStartIndex(), caretMetrics);
3737     return !NearEqual(caretMetrics.offset.GetY(), selectController_->GetCaretRect().GetY());
3738 }
3739 
CursorMoveLeftOperation()3740 bool TextFieldPattern::CursorMoveLeftOperation()
3741 {
3742     if (focusIndex_ != FocuseIndex::TEXT) {
3743         return UpdateFocusBackward();
3744     }
3745     auto originCaretPosition = selectController_->GetCaretIndex();
3746     if (IsSelected()) {
3747         selectController_->UpdateCaretIndex(selectController_->GetStartIndex());
3748         CloseSelectOverlay();
3749     } else {
3750         UpdateCaretPositionWithClamp(
3751             selectController_->GetCaretIndex() -
3752             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetCaretIndex(), true));
3753     }
3754     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
3755     return originCaretPosition != selectController_->GetCaretIndex();
3756 }
3757 
CursorMoveLeft()3758 bool TextFieldPattern::CursorMoveLeft()
3759 {
3760     if (inputOperations_.empty()) {
3761         return CursorMoveLeftOperation();
3762     }
3763 
3764     inputOperations_.emplace(InputOperation::CURSOR_LEFT);
3765     return false;
3766 }
3767 
CursorMoveLeftWord()3768 bool TextFieldPattern::CursorMoveLeftWord()
3769 {
3770     if (selectController_->GetCaretIndex() == 0) {
3771         return true;
3772     }
3773     int32_t originCaretPosition = selectController_->GetCaretIndex();
3774     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
3775     int32_t leftWordLength = GetWordLength(originCaretPosition, 0);
3776     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
3777         return false;
3778     }
3779     if (IsSelected()) {
3780         selectController_->UpdateCaretIndex(selectController_->GetSecondHandleIndex() - leftWordLength);
3781         CloseSelectOverlay();
3782     } else {
3783         UpdateCaretPositionWithClamp(originCaretPosition - leftWordLength);
3784     }
3785     OnCursorMoveDone();
3786     return originCaretPosition != selectController_->GetCaretIndex();
3787 }
3788 
CursorMoveLineBegin()3789 bool TextFieldPattern::CursorMoveLineBegin()
3790 {
3791     if (selectController_->GetCaretIndex() == 0) {
3792         return true;
3793     }
3794     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
3795     int32_t originCaretPosition = selectController_->GetCaretIndex();
3796     int32_t lineBeginPosition = GetLineBeginPosition(originCaretPosition);
3797     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
3798         return false;
3799     }
3800     if (selectController_->IsSelectedAll()) {
3801         selectController_->UpdateCaretIndex(0);
3802     } else if (IsTextArea()) {
3803         UpdateCaretPositionWithClamp(lineBeginPosition);
3804     } else {
3805         UpdateCaretPositionWithClamp(0);
3806     }
3807     OnCursorMoveDone();
3808     return originCaretPosition != selectController_->GetCaretIndex();
3809 }
3810 
CursorMoveToParagraphBegin()3811 bool TextFieldPattern::CursorMoveToParagraphBegin()
3812 {
3813     if (selectController_->GetCaretIndex() == 0) {
3814         return true;
3815     }
3816     auto originCaretPosition = selectController_->GetCaretIndex();
3817     auto newPos = GetLineBeginPosition(originCaretPosition, false);
3818     if (newPos == originCaretPosition && originCaretPosition > 0) {
3819         newPos = GetLineBeginPosition(originCaretPosition - 1, false);
3820     }
3821     UpdateCaretPositionWithClamp(newPos);
3822     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
3823     return originCaretPosition != selectController_->GetCaretIndex();
3824 }
3825 
CursorMoveHome()3826 bool TextFieldPattern::CursorMoveHome()
3827 {
3828     // ctrl + home, caret move to position 0
3829     if (selectController_->GetCaretIndex() == 0) {
3830         return true;
3831     }
3832     int32_t originCaretPosition = selectController_->GetCaretIndex();
3833     UpdateCaretPositionWithClamp(0);
3834     OnCursorMoveDone();
3835     return originCaretPosition != selectController_->GetCaretIndex();
3836 }
3837 
CursorMoveRightOperation()3838 bool TextFieldPattern::CursorMoveRightOperation()
3839 {
3840     if (focusIndex_ != FocuseIndex::TEXT) {
3841         return UpdateFocusForward();
3842     }
3843     auto originCaretPosition = selectController_->GetCaretIndex();
3844     if (IsSelected()) {
3845         CloseSelectOverlay();
3846         selectController_->UpdateCaretIndex(selectController_->GetEndIndex());
3847     } else {
3848         UpdateCaretPositionWithClamp(
3849             selectController_->GetCaretIndex() +
3850             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetCaretIndex()));
3851     }
3852     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
3853     return originCaretPosition != selectController_->GetCaretIndex();
3854 }
3855 
CursorMoveRight()3856 bool TextFieldPattern::CursorMoveRight()
3857 {
3858     if (inputOperations_.empty()) {
3859         return CursorMoveRightOperation();
3860     }
3861     inputOperations_.emplace(InputOperation::CURSOR_RIGHT);
3862     return false;
3863 }
3864 
CursorMoveRightWord()3865 bool TextFieldPattern::CursorMoveRightWord()
3866 {
3867     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
3868         return true;
3869     }
3870     int32_t originCaretPosition = selectController_->GetCaretIndex();
3871     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
3872     int32_t rightWordLength = GetWordLength(originCaretPosition, 1);
3873     if (rightWordLength < 0 || rightWordLength > textLength ||
3874         rightWordLength + selectController_->GetCaretIndex() > textLength) {
3875         return false;
3876     }
3877     if (selectController_->IsSelectedAll()) {
3878         selectController_->UpdateCaretIndex(textLength);
3879     } else {
3880         UpdateCaretPositionWithClamp(originCaretPosition + rightWordLength);
3881     }
3882     OnCursorMoveDone();
3883     return originCaretPosition != selectController_->GetCaretIndex();
3884 }
3885 
CursorMoveLineEnd()3886 bool TextFieldPattern::CursorMoveLineEnd()
3887 {
3888     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
3889         return true;
3890     }
3891     int32_t originCaretPosition = selectController_->GetCaretIndex();
3892     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
3893     int32_t lineEndPosition = GetLineEndPosition(originCaretPosition);
3894     if (lineEndPosition < 0 || lineEndPosition > textLength) {
3895         return false;
3896     }
3897     if (selectController_->IsSelectedAll()) {
3898         selectController_->UpdateCaretIndex(textLength);
3899     } else if (IsTextArea()) {
3900         UpdateCaretPositionWithClamp(lineEndPosition);
3901     } else {
3902         UpdateCaretPositionWithClamp(textLength);
3903     }
3904     OnCursorMoveDone();
3905     return originCaretPosition != selectController_->GetCaretIndex();
3906 }
3907 
CursorMoveToParagraphEnd()3908 bool TextFieldPattern::CursorMoveToParagraphEnd()
3909 {
3910     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
3911         return true;
3912     }
3913     auto originCaretPosition = selectController_->GetCaretIndex();
3914     auto newPos = GetLineEndPosition(originCaretPosition, false);
3915     if (newPos == originCaretPosition && originCaretPosition > 0) {
3916         newPos = GetLineEndPosition(originCaretPosition + 1, false);
3917     }
3918     UpdateCaretPositionWithClamp(newPos);
3919     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
3920     return originCaretPosition != selectController_->GetCaretIndex();
3921 }
3922 
CursorMoveEnd()3923 bool TextFieldPattern::CursorMoveEnd()
3924 {
3925     // ctrl end, caret to the very end
3926     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
3927         return true;
3928     }
3929     int32_t originCaretPosition = selectController_->GetCaretIndex();
3930     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
3931     UpdateCaretPositionWithClamp(textLength);
3932     OnCursorMoveDone();
3933     return originCaretPosition != selectController_->GetCaretIndex();
3934 }
3935 
CursorMoveUpOperation()3936 bool TextFieldPattern::CursorMoveUpOperation()
3937 {
3938     CHECK_NULL_RETURN(IsTextArea(), false);
3939     auto originCaretPosition = selectController_->GetCaretIndex();
3940     if (IsSelected()) {
3941         selectController_->UpdateCaretIndex(selectController_->GetStartIndex());
3942     } else {
3943         auto offsetX = selectController_->GetCaretRect().GetX() - contentRect_.GetX();
3944         auto offsetY = selectController_->GetCaretRect().GetY() - textRect_.GetY();
3945         // multiply by 0.5f to convert to the grapheme center point of the previous line.
3946         float verticalOffset = offsetY - PreferredLineHeight() * 0.5f;
3947         selectController_->UpdateCaretIndex(
3948             static_cast<int32_t>(paragraph_->GetGlyphIndexByCoordinate(Offset(offsetX, verticalOffset))));
3949     }
3950     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
3951     return originCaretPosition != selectController_->GetCaretIndex();
3952 }
3953 
CursorMoveUp()3954 bool TextFieldPattern::CursorMoveUp()
3955 {
3956     if (inputOperations_.empty()) {
3957         return CursorMoveUpOperation();
3958     }
3959 
3960     inputOperations_.emplace(InputOperation::CURSOR_UP);
3961     return false;
3962 }
3963 
CursorMoveDownOperation()3964 bool TextFieldPattern::CursorMoveDownOperation()
3965 {
3966     CHECK_NULL_RETURN(IsTextArea(), false);
3967     auto originCaretPosition = selectController_->GetCaretIndex();
3968     if (IsSelected()) {
3969         selectController_->UpdateCaretIndex(selectController_->GetEndIndex());
3970     } else {
3971         auto offsetX = selectController_->GetCaretRect().GetX() - contentRect_.GetX();
3972         auto offsetY = selectController_->GetCaretRect().GetY() - textRect_.GetY();
3973         // multiply by 1.5f to convert to the grapheme center point of the next line.
3974         float verticalOffset = offsetY + PreferredLineHeight() * 1.5f;
3975         selectController_->UpdateCaretIndex(
3976             static_cast<int32_t>(paragraph_->GetGlyphIndexByCoordinate(Offset(offsetX, verticalOffset))));
3977     }
3978     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
3979     return originCaretPosition != selectController_->GetCaretIndex();
3980 }
3981 
CursorMoveDown()3982 bool TextFieldPattern::CursorMoveDown()
3983 {
3984     if (inputOperations_.empty()) {
3985         return CursorMoveDownOperation();
3986     }
3987 
3988     inputOperations_.emplace(InputOperation::CURSOR_DOWN);
3989     return false;
3990 }
3991 
Delete(int32_t start,int32_t end)3992 void TextFieldPattern::Delete(int32_t start, int32_t end)
3993 {
3994     SwapIfLarger(start, end);
3995     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Handle Delete within [%{public}d, %{public}d]", start, end);
3996     contentController_->erase(start, end - start);
3997     UpdateSelection(start);
3998     selectController_->MoveCaretToContentRect(start);
3999     CloseSelectOverlay(true);
4000     StartTwinkling();
4001     UpdateEditingValueToRecord();
4002     auto tmpHost = GetHost();
4003     CHECK_NULL_VOID(tmpHost);
4004     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4005     CHECK_NULL_VOID(layoutProperty);
4006     if (layoutProperty->HasMaxLength()) {
4007         HandleCounterBorder();
4008     }
4009     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4010 }
4011 
ClearEditingValue()4012 void TextFieldPattern::ClearEditingValue()
4013 {
4014     contentController_->Reset();
4015     selectController_->UpdateCaretIndex(0);
4016     UpdateEditingValueToRecord();
4017     auto tmpHost = GetHost();
4018     CHECK_NULL_VOID(tmpHost);
4019     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4020     CHECK_NULL_VOID(layoutProperty);
4021     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4022 }
4023 
HandleCounterBorder()4024 void TextFieldPattern::HandleCounterBorder()
4025 {
4026     auto tmpHost = GetHost();
4027     CHECK_NULL_VOID(tmpHost);
4028     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4029     CHECK_NULL_VOID(layoutProperty);
4030     if ((HasFocus() && IsNormalInlineState())) {
4031         return;
4032     }
4033     auto textFieldTheme = GetTheme();
4034     CHECK_NULL_VOID(textFieldTheme);
4035     auto maxLength = GetMaxLength();
4036     auto currentLength = static_cast<uint32_t>(contentController_->GetWideText().length());
4037     BorderWidthProperty currentBorderWidth;
4038     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
4039         currentBorderWidth = *(layoutProperty->GetBorderWidthProperty());
4040     } else {
4041         currentBorderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
4042     }
4043     BorderWidthProperty overCountBorderWidth;
4044     overCountBorderWidth.SetBorderWidth(OVER_COUNT_BORDER_WIDTH);
4045     BorderColorProperty currentBorderColor;
4046     auto renderContext = tmpHost->GetRenderContext();
4047     CHECK_NULL_VOID(renderContext);
4048     if (renderContext->HasBorderColor()) {
4049         currentBorderColor = renderContext->GetBorderColor().value();
4050     }
4051     BorderColorProperty overCountBorderColor;
4052     overCountBorderColor.SetColor(textFieldTheme->GetOverCounterColor());
4053     UpdateAreaBorderStyle(currentBorderWidth, overCountBorderWidth,
4054         overCountBorderColor, currentBorderColor);
4055     if (currentLength == maxLength) {
4056         if (!(currentBorderWidth == overCountBorderWidth)) {
4057             lastDiffBorderWidth_ = currentBorderWidth;
4058             layoutProperty->UpdateBorderWidth(overCountBorderWidth);
4059             renderContext->UpdateBorderWidth(overCountBorderWidth);
4060         }
4061         if (!(currentBorderColor == overCountBorderColor)) {
4062             lastDiffBorderColor_ = currentBorderColor;
4063             renderContext->UpdateBorderColor(overCountBorderColor);
4064         }
4065     } else {
4066         if (currentBorderWidth == overCountBorderWidth) {
4067             layoutProperty->UpdateBorderWidth(lastDiffBorderWidth_);
4068             renderContext->UpdateBorderWidth(lastDiffBorderWidth_);
4069         }
4070         if (currentBorderColor == overCountBorderColor) {
4071             renderContext->UpdateBorderColor(lastDiffBorderColor_);
4072         }
4073     }
4074 }
4075 
UpdateAreaBorderStyle(BorderWidthProperty & currentBorderWidth,BorderWidthProperty & overCountBorderWidth,BorderColorProperty & overCountBorderColor,BorderColorProperty & currentBorderColor)4076 void TextFieldPattern::UpdateAreaBorderStyle(BorderWidthProperty& currentBorderWidth,
4077     BorderWidthProperty& overCountBorderWidth, BorderColorProperty& overCountBorderColor,
4078     BorderColorProperty& currentBorderColor)
4079 {
4080     auto tmpHost = GetHost();
4081     CHECK_NULL_VOID(tmpHost);
4082     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4083     CHECK_NULL_VOID(layoutProperty);
4084     auto renderContext = tmpHost->GetRenderContext();
4085     CHECK_NULL_VOID(renderContext);
4086     auto maxLength = GetMaxLength();
4087     auto currentLength = static_cast<uint32_t>(contentController_->GetWideText().length());
4088     auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
4089     if ((currentLength + ONE_CHARACTER) == maxLength && showBorder == true && counterChange_ == true && IsTextArea()) {
4090         if (!(currentBorderWidth == overCountBorderWidth)) {
4091             lastDiffBorderWidth_ = currentBorderWidth;
4092             layoutProperty->UpdateBorderWidth(overCountBorderWidth);
4093             renderContext->UpdateBorderWidth(overCountBorderWidth);
4094         }
4095         if (!(currentBorderColor == overCountBorderColor)) {
4096             lastDiffBorderColor_ = currentBorderColor;
4097             renderContext->UpdateBorderColor(overCountBorderColor);
4098         }
4099     }
4100 }
4101 
PerformAction(TextInputAction action,bool forceCloseKeyboard)4102 void TextFieldPattern::PerformAction(TextInputAction action, bool forceCloseKeyboard)
4103 {
4104     if (focusIndex_ == FocuseIndex::CANCEL) {
4105         CleanNodeResponseKeyEvent();
4106         return;
4107     } else if (focusIndex_ == FocuseIndex::UNIT) {
4108         if (IsShowPasswordIcon()) {
4109             PasswordResponseKeyEvent();
4110         }
4111         if (IsShowUnit()) {
4112             UnitResponseKeyEvent();
4113         }
4114         return;
4115     }
4116     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "PerformAction  %{public}d", static_cast<int32_t>(action));
4117     auto host = GetHost();
4118     CHECK_NULL_VOID(host);
4119     // If the parent node is a Search, the Search callback is executed.
4120     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4121     CHECK_NULL_VOID(paintProperty);
4122     auto eventHub = host->GetEventHub<TextFieldEventHub>();
4123     TextFieldCommonEvent event;
4124     event.SetText(contentController_->GetTextValue());
4125     if (IsNormalInlineState() && action != TextInputAction::NEW_LINE) {
4126         auto host = GetHost();
4127         CHECK_NULL_VOID(host);
4128         RecordSubmitEvent();
4129         eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
4130         if (event.IsKeepEditable()) {
4131             return;
4132         }
4133         auto focusHub = host->GetOrCreateFocusHub();
4134         focusHub->LostFocus();
4135         return;
4136     }
4137     if (IsTextArea() && action == TextInputAction::NEW_LINE) {
4138         if (GetInputFilter() != "\n") {
4139             InsertValue("\n");
4140         }
4141         return;
4142     }
4143     eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
4144     RecordSubmitEvent();
4145     if (event.IsKeepEditable()) {
4146         return;
4147     }
4148     // LostFocusToViewRoot may not cause current lost focus, only stop twinkling when it is truly lost focus,
4149     // which will call StopTwinkling on HandleBlurEvent method.
4150     CloseKeyboard(forceCloseKeyboard, false);
4151     FocusHub::LostFocusToViewRoot();
4152 }
4153 
RecordSubmitEvent() const4154 void TextFieldPattern::RecordSubmitEvent() const
4155 {
4156     if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
4157         return;
4158     }
4159     auto host = GetHost();
4160     CHECK_NULL_VOID(host);
4161     auto inspectorId = host->GetInspectorId().value_or("");
4162     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4163     bool isPwdType = layoutProperty ? layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) ==
4164                                           TextInputType::VISIBLE_PASSWORD
4165                                     : false;
4166     Recorder::EventParamsBuilder builder;
4167     builder.SetId(inspectorId)
4168         .SetType(host->GetTag())
4169         .SetEventType(Recorder::EventType::SEARCH_SUBMIT)
4170         .SetDescription(host->GetAutoEventParamValue(""));
4171     if (!isPwdType) {
4172         builder.SetText(contentController_->GetTextValue());
4173     }
4174     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
4175 }
4176 
UpdateEditingValue(const std::shared_ptr<TextEditingValue> & value,bool needFireChangeEvent)4177 void TextFieldPattern::UpdateEditingValue(const std::shared_ptr<TextEditingValue>& value, bool needFireChangeEvent)
4178 {
4179     contentController_->SetTextValue(value->text);
4180     selectController_->UpdateCaretIndex(value->selection.baseOffset);
4181     ContainerScope scope(GetInstanceId());
4182     UpdateEditingValueToRecord();
4183     CloseSelectOverlay();
4184     StartTwinkling();
4185     auto host = GetHost();
4186     CHECK_NULL_VOID(host);
4187 
4188     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
4189     CHECK_NULL_VOID(layoutProperty);
4190     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4191 }
4192 
UpdateInputFilterErrorText(const std::string & errorText)4193 void TextFieldPattern::UpdateInputFilterErrorText(const std::string& errorText)
4194 {
4195     if (!errorText.empty()) {
4196         auto tmpHost = GetHost();
4197         CHECK_NULL_VOID(tmpHost);
4198         auto textFieldEventHub = tmpHost->GetEventHub<TextFieldEventHub>();
4199         CHECK_NULL_VOID(textFieldEventHub);
4200         textFieldEventHub->FireOnInputFilterError(errorText);
4201     }
4202 }
4203 
OnValueChanged(bool needFireChangeEvent,bool needFireSelectChangeEvent)4204 void TextFieldPattern::OnValueChanged(bool needFireChangeEvent, bool needFireSelectChangeEvent) {}
4205 
OnAreaChangedInner()4206 void TextFieldPattern::OnAreaChangedInner()
4207 {
4208     auto parentGlobalOffset = GetTextPaintOffset();
4209     if (parentGlobalOffset != parentGlobalOffset_) {
4210         parentGlobalOffset_ = parentGlobalOffset;
4211         UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
4212         selectController_->CalculateHandleOffset();
4213         if (SelectOverlayIsOn()) {
4214             if (IsUsingMouse()) {
4215                 CloseSelectOverlay();
4216             } else {
4217                 ProcessOverlay(false);
4218                 UpdateSelectMenuVisibility(false);
4219             }
4220         }
4221     }
4222     RequestKeyboardOnFocus();
4223 }
4224 
RequestKeyboardOnFocus()4225 void TextFieldPattern::RequestKeyboardOnFocus()
4226 {
4227     if (!needToRequestKeyboardOnFocus_ || !needToRequestKeyboardInner_) {
4228         return;
4229     }
4230     if (!RequestKeyboard(false, true, true)) {
4231         return;
4232     }
4233     NotifyOnEditChanged(true);
4234     needToRequestKeyboardInner_ = false;
4235 }
4236 
OnVisibleChange(bool isVisible)4237 void TextFieldPattern::OnVisibleChange(bool isVisible)
4238 {
4239     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "visible change to %{public}d", isVisible);
4240     if (!isVisible && HasFocus()) {
4241         CloseKeyboard(true);
4242         if (SelectOverlayIsOn()) {
4243             StartTwinkling();
4244         }
4245     }
4246 }
4247 
HandleSurfaceChanged(int32_t newWidth,int32_t newHeight,int32_t prevWidth,int32_t prevHeight)4248 void TextFieldPattern::HandleSurfaceChanged(int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight)
4249 {
4250     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
4251         "Textfield handleSurface change, new width %{public}d, new height %{public}d, prev width %{public}d, prev "
4252         "height %{public}d",
4253         newWidth, newHeight, prevWidth, prevHeight);
4254     if (SelectOverlayIsOn()) {
4255         auto proxy = GetSelectOverlayProxy();
4256         auto overlayInfo = proxy->GetSelectOverlayMangerInfo();
4257         if (!overlayInfo.isUsingMouse) {
4258             proxy->ShowOrHiddenMenu(true);
4259             UpdateOriginIsMenuShow(false);
4260             processOverlayDelayTask_ = [weak = WeakClaim(this)]() {
4261                 auto pattern = weak.Upgrade();
4262                 CHECK_NULL_VOID(pattern);
4263                 pattern->ProcessOverlay(false);
4264             };
4265         } else {
4266             CloseSelectOverlay();
4267         }
4268     }
4269     auto tmpHost = GetHost();
4270     CHECK_NULL_VOID(tmpHost);
4271     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4272     UpdateCaretInfoToController();
4273 }
4274 
HandleSurfacePositionChanged(int32_t posX,int32_t posY) const4275 void TextFieldPattern::HandleSurfacePositionChanged(int32_t posX, int32_t posY) const
4276 {
4277     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield handleSurface position change, posX %{public}d, posY %{public}d",
4278         posX, posY);
4279     UpdateCaretInfoToController();
4280 }
4281 
InitSurfaceChangedCallback()4282 void TextFieldPattern::InitSurfaceChangedCallback()
4283 {
4284     auto pipeline = PipelineContext::GetCurrentContext();
4285     CHECK_NULL_VOID(pipeline);
4286     if (!HasSurfaceChangedCallback()) {
4287         auto callbackId = pipeline->RegisterSurfaceChangedCallback(
4288             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
4289                 WindowSizeChangeReason type) {
4290                 auto pattern = weak.Upgrade();
4291                 if (pattern) {
4292                     pattern->HandleSurfaceChanged(newWidth, newHeight, prevWidth, prevHeight);
4293                 }
4294             });
4295         UpdateSurfaceChangedCallbackId(callbackId);
4296     }
4297 }
4298 
InitSurfacePositionChangedCallback()4299 void TextFieldPattern::InitSurfacePositionChangedCallback()
4300 {
4301     auto pipeline = PipelineContext::GetCurrentContext();
4302     CHECK_NULL_VOID(pipeline);
4303     if (!HasSurfacePositionChangedCallback()) {
4304         auto callbackId =
4305             pipeline->RegisterSurfacePositionChangedCallback([weak = WeakClaim(this)](int32_t posX, int32_t posY) {
4306                 auto pattern = weak.Upgrade();
4307                 if (pattern) {
4308                     pattern->HandleSurfacePositionChanged(posX, posY);
4309                 }
4310             });
4311         UpdateSurfacePositionChangedCallbackId(callbackId);
4312     }
4313 }
4314 
HandleOnDelete(bool backward)4315 void TextFieldPattern::HandleOnDelete(bool backward)
4316 {
4317     if (backward) {
4318 #if defined(PREVIEW)
4319         DeleteForward(GetGraphemeClusterLength(GetWideText(), GetCaretIndex()));
4320 #else
4321         DeleteBackward(GetGraphemeClusterLength(GetWideText(), GetCaretIndex(), true));
4322 #endif
4323     } else {
4324 #if defined(PREVIEW)
4325         DeleteBackward(GetGraphemeClusterLength(GetWideText(), GetCaretIndex(), true));
4326 #else
4327         DeleteForward(GetGraphemeClusterLength(GetWideText(), GetCaretIndex()));
4328 #endif
4329     }
4330 }
4331 
DeleteBackward(int32_t length)4332 void TextFieldPattern::DeleteBackward(int32_t length)
4333 {
4334     auto tmpHost = GetHost();
4335     CHECK_NULL_VOID(tmpHost);
4336     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4337     CHECK_NULL_VOID(layoutProperty);
4338     ResetObscureTickCountDown();
4339     if (IsSelected()) {
4340         lockRecord_ = true;
4341         Delete(selectController_->GetStartIndex(), selectController_->GetEndIndex());
4342         lockRecord_ = false;
4343         return;
4344     }
4345     if (selectController_->GetCaretIndex() <= 0) {
4346         return;
4347     }
4348     inputOperations_.emplace(InputOperation::DELETE_BACKWARD);
4349     deleteBackwardOperations_.emplace(length);
4350     if (layoutProperty->HasMaxLength()) {
4351         if (layoutProperty->GetShowUnderlineValue(false) && !IsTextArea()) {
4352             auto textFieldTheme = GetTheme();
4353             CHECK_NULL_VOID(textFieldTheme);
4354             underlineColor_ = textFieldTheme->GetUnderlineColor();
4355         }
4356         counterChange_ = false;
4357         HandleCounterBorder();
4358     }
4359     CloseSelectOverlay();
4360     ScrollToSafeArea();
4361     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4362 }
4363 
DeleteBackwardOperation(int32_t length)4364 void TextFieldPattern::DeleteBackwardOperation(int32_t length)
4365 {
4366     auto start = std::max(selectController_->GetCaretIndex() - length, 0);
4367     contentController_->erase(start, length);
4368     lockRecord_ = true;
4369     selectController_->UpdateCaretIndex(start);
4370     lockRecord_ = false;
4371     StartTwinkling();
4372     UpdateEditingValueToRecord();
4373     auto tmpHost = GetHost();
4374     CHECK_NULL_VOID(tmpHost);
4375     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4376     CHECK_NULL_VOID(layoutProperty);
4377     if (layoutProperty->HasMaxLength()) {
4378         HandleCounterBorder();
4379     }
4380 }
4381 
DeleteForwardOperation(int32_t length)4382 void TextFieldPattern::DeleteForwardOperation(int32_t length)
4383 {
4384     contentController_->erase(selectController_->GetCaretIndex(), length);
4385     StartTwinkling();
4386     UpdateEditingValueToRecord();
4387     auto tmpHost = GetHost();
4388     CHECK_NULL_VOID(tmpHost);
4389     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4390     CHECK_NULL_VOID(layoutProperty);
4391     if (IsTextArea() && layoutProperty->HasMaxLength()) {
4392         HandleCounterBorder();
4393     }
4394 }
4395 
DeleteForward(int32_t length)4396 void TextFieldPattern::DeleteForward(int32_t length)
4397 {
4398     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Handle DeleteForward %{public}d characters", length);
4399     ResetObscureTickCountDown();
4400     if (IsSelected()) {
4401         Delete(selectController_->GetStartIndex(), selectController_->GetEndIndex());
4402         return;
4403     }
4404     if (selectController_->GetCaretIndex() >= static_cast<int32_t>(contentController_->GetWideText().length())) {
4405         return;
4406     }
4407     inputOperations_.emplace(InputOperation::DELETE_FORWARD);
4408     deleteForwardOperations_.emplace(length);
4409     CloseSelectOverlay();
4410     auto tmpHost = GetHost();
4411     CHECK_NULL_VOID(tmpHost);
4412     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4413     CHECK_NULL_VOID(layoutProperty);
4414     if (layoutProperty->HasMaxLength()) {
4415         HandleCounterBorder();
4416     }
4417     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4418 }
4419 
GetLeftTextOfCursor(int32_t number)4420 std::u16string TextFieldPattern::GetLeftTextOfCursor(int32_t number)
4421 {
4422     auto start = selectController_->GetCaretIndex();
4423     if (IsSelected()) {
4424         start = selectController_->GetStartIndex();
4425     }
4426     auto stringText = contentController_->GetSelectedValue(start - number, start);
4427     return StringUtils::Str8ToStr16(stringText);
4428 }
4429 
GetRightTextOfCursor(int32_t number)4430 std::u16string TextFieldPattern::GetRightTextOfCursor(int32_t number)
4431 {
4432     auto end = selectController_->GetCaretIndex();
4433     if (IsSelected()) {
4434         end = selectController_->GetEndIndex();
4435     }
4436     auto stringText = contentController_->GetSelectedValue(end, end + number);
4437     return StringUtils::Str8ToStr16(stringText);
4438 }
4439 
GetTextIndexAtCursor()4440 int32_t TextFieldPattern::GetTextIndexAtCursor()
4441 {
4442     return selectController_->GetCaretIndex();
4443 }
4444 
AfterSelection()4445 void TextFieldPattern::AfterSelection()
4446 {
4447     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Selection %{public}s, caret position %{public}d",
4448         selectController_->ToString().c_str(), selectController_->GetCaretIndex());
4449     ResetObscureTickCountDown();
4450     auto tmpHost = GetHost();
4451     CHECK_NULL_VOID(tmpHost);
4452     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4453     showSelect_ = IsSelected();
4454 }
4455 
HandleSelectionUp()4456 void TextFieldPattern::HandleSelectionUp()
4457 {
4458     if (!IsTextArea()) {
4459         return;
4460     }
4461     if (!IsSelected()) {
4462         UpdateSelection(selectController_->GetCaretIndex());
4463     }
4464     auto newOffsetY = selectController_->GetCaretRect().GetY() - PreferredLineHeight() * 0.5 - textRect_.GetY();
4465     if (GreatOrEqual(newOffsetY, 0.0)) {
4466         selectController_->MoveSecondHandleByKeyBoard(paragraph_->GetGlyphIndexByCoordinate(
4467             Offset(selectController_->GetCaretRect().GetX() - contentRect_.GetX(), newOffsetY)));
4468     } else {
4469         selectController_->MoveSecondHandleByKeyBoard(0);
4470     }
4471     AfterSelection();
4472 }
4473 
HandleSelectionDown()4474 void TextFieldPattern::HandleSelectionDown()
4475 {
4476     if (!IsTextArea()) {
4477         return;
4478     }
4479     if (!IsSelected()) {
4480         UpdateSelection(selectController_->GetCaretIndex());
4481     }
4482     auto newOffsetY = selectController_->GetCaretRect().GetY() + PreferredLineHeight() * 1.5 - textRect_.GetY();
4483     if (LessOrEqual(newOffsetY, textRect_.Height())) {
4484         selectController_->MoveSecondHandleByKeyBoard(paragraph_->GetGlyphIndexByCoordinate(
4485             Offset(selectController_->GetCaretRect().GetX() - contentRect_.GetX(), newOffsetY)));
4486     } else {
4487         selectController_->MoveSecondHandleByKeyBoard(static_cast<int32_t>(contentController_->GetWideText().length()));
4488     }
4489     AfterSelection();
4490 }
4491 
HandleSelectionLeft()4492 void TextFieldPattern::HandleSelectionLeft()
4493 {
4494     if (!IsSelected()) {
4495         if (selectController_->GetCaretIndex() == 0) {
4496             return;
4497         }
4498         UpdateSelection(selectController_->GetCaretIndex());
4499         selectController_->MoveSecondHandleByKeyBoard(
4500             selectController_->GetSecondHandleIndex() -
4501             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetCaretIndex(), true));
4502     } else {
4503         selectController_->MoveSecondHandleByKeyBoard(
4504             selectController_->GetSecondHandleIndex() - GetGraphemeClusterLength(contentController_->GetWideText(),
4505                                                             selectController_->GetSecondHandleIndex(), true));
4506     }
4507     AfterSelection();
4508 }
4509 
HandleSelectionLeftWord()4510 void TextFieldPattern::HandleSelectionLeftWord()
4511 {
4512     if (selectController_->GetCaretIndex() == 0) {
4513         return;
4514     }
4515     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4516     int32_t leftWordLength = GetWordLength(selectController_->GetCaretIndex(), 0);
4517     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
4518         return;
4519     }
4520     if (!IsSelected()) {
4521         UpdateSelection(selectController_->GetCaretIndex());
4522         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
4523     } else {
4524         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
4525     }
4526     AfterSelection();
4527 }
4528 
HandleSelectionLineBegin()4529 void TextFieldPattern::HandleSelectionLineBegin()
4530 {
4531     if (selectController_->GetCaretIndex() == 0) {
4532         return;
4533     }
4534     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4535     int32_t lineBeginPosition = GetLineBeginPosition(selectController_->GetCaretIndex());
4536     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
4537         return;
4538     }
4539     if (!IsSelected()) {
4540         UpdateSelection(selectController_->GetCaretIndex());
4541         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
4542     } else {
4543         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
4544     }
4545     AfterSelection();
4546 }
4547 
HandleSelectionHome()4548 void TextFieldPattern::HandleSelectionHome()
4549 {
4550     if (selectController_->GetCaretIndex() == 0) {
4551         return;
4552     }
4553     if (!IsSelected()) {
4554         UpdateSelection(selectController_->GetCaretIndex());
4555         selectController_->MoveSecondHandleByKeyBoard(0);
4556     } else {
4557         selectController_->MoveSecondHandleByKeyBoard(0);
4558     }
4559     AfterSelection();
4560 }
4561 
HandleSelectionRight()4562 void TextFieldPattern::HandleSelectionRight()
4563 {
4564     // if currently not in select mode, reset baseOffset and move destinationOffset and caret position
4565     if (!IsSelected()) {
4566         if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
4567             return;
4568         }
4569         UpdateSelection(selectController_->GetCaretIndex());
4570         selectController_->MoveSecondHandleByKeyBoard(
4571             selectController_->GetSecondHandleIndex() +
4572             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetSecondHandleIndex()));
4573     } else {
4574         // if currently not in select mode, move destinationOffset and caret position only
4575         selectController_->MoveSecondHandleByKeyBoard(
4576             selectController_->GetSecondHandleIndex() +
4577             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetSecondHandleIndex()));
4578     }
4579     AfterSelection();
4580 }
4581 
HandleSelectionRightWord()4582 void TextFieldPattern::HandleSelectionRightWord()
4583 {
4584     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4585     if (selectController_->GetCaretIndex() == textLength) {
4586         return;
4587     }
4588     int32_t rightWordLength = GetWordLength(selectController_->GetCaretIndex(), 1);
4589     if (rightWordLength < 0 || rightWordLength > textLength ||
4590         rightWordLength + selectController_->GetCaretIndex() > textLength) {
4591         return;
4592     }
4593     if (!IsSelected()) {
4594         UpdateSelection(selectController_->GetCaretIndex());
4595         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
4596     } else {
4597         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
4598         AfterSelection();
4599     }
4600 }
4601 
HandleSelectionLineEnd()4602 void TextFieldPattern::HandleSelectionLineEnd()
4603 {
4604     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4605     if (selectController_->GetCaretIndex() == textLength) {
4606         return;
4607     }
4608     int32_t lineEndPosition = GetLineEndPosition(selectController_->GetCaretIndex());
4609     if (lineEndPosition < 0 || lineEndPosition > textLength) {
4610         return;
4611     }
4612     if (!IsSelected()) {
4613         UpdateSelection(selectController_->GetCaretIndex());
4614         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
4615     } else {
4616         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
4617     }
4618     AfterSelection();
4619 }
4620 
HandleSelectionEnd()4621 void TextFieldPattern::HandleSelectionEnd()
4622 {
4623     // shift end, select to the end of current line
4624     int32_t endPos = static_cast<int32_t>(contentController_->GetWideText().length());
4625     if (selectController_->GetCaretIndex() == endPos) {
4626         return;
4627     }
4628     if (!IsSelected()) {
4629         UpdateSelection(selectController_->GetCaretIndex());
4630         selectController_->MoveSecondHandleByKeyBoard(endPos);
4631     } else {
4632         selectController_->MoveSecondHandleByKeyBoard(endPos);
4633     }
4634     AfterSelection();
4635 }
4636 
SetCaretPosition(int32_t position)4637 void TextFieldPattern::SetCaretPosition(int32_t position)
4638 {
4639     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Set caret position to %{public}d", position);
4640     selectController_->MoveCaretToContentRect(position, TextAffinity::DOWNSTREAM);
4641     if (HasFocus() && !GetShowMagnifier()) {
4642         StartTwinkling();
4643         FireOnSelectionChange(position, position);
4644     }
4645     CloseSelectOverlay();
4646     auto tmpHost = GetHost();
4647     CHECK_NULL_VOID(tmpHost);
4648     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4649 }
4650 
SetSelectionFlag(int32_t selectionStart,int32_t selectionEnd)4651 void TextFieldPattern::SetSelectionFlag(int32_t selectionStart, int32_t selectionEnd)
4652 {
4653     if (!HasFocus()) {
4654         return;
4655     }
4656     if (selectionStart == selectionEnd) {
4657         selectController_->MoveCaretToContentRect(selectionEnd, TextAffinity::DOWNSTREAM);
4658         StartTwinkling();
4659     } else {
4660         cursorVisible_ = false;
4661         showSelect_ = true;
4662         HandleSetSelection(selectionStart, selectionEnd, false);
4663         selectController_->MoveFirstHandleToContentRect(selectionStart);
4664         selectController_->MoveSecondHandleToContentRect(selectionEnd);
4665     }
4666     if (RequestKeyboard(false, true, true)) {
4667         NotifyOnEditChanged(true);
4668     }
4669     auto host = GetHost();
4670     CHECK_NULL_VOID(host);
4671     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4672 }
4673 
OnBackPressed()4674 bool TextFieldPattern::OnBackPressed()
4675 {
4676     auto tmpHost = GetHost();
4677     CHECK_NULL_RETURN(tmpHost, false);
4678     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield %{public}d receives back press event", tmpHost->GetId());
4679     if (SelectOverlayIsOn()) {
4680         selectController_->UpdateCaretIndex(
4681             std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
4682         auto selectOverlayProxy = GetSelectOverlayProxy();
4683         CHECK_NULL_RETURN(selectOverlayProxy, false);
4684         bool closeKeyboard = !selectOverlayProxy->IsMenuShow();
4685         CloseSelectOverlay();
4686         StartTwinkling();
4687         if (!closeKeyboard) {
4688             return true;
4689         }
4690     }
4691 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
4692     if (!imeShown_ && !isCustomKeyboardAttached_) {
4693 #else
4694     if (!isCustomKeyboardAttached_) {
4695 #endif
4696         return false;
4697     }
4698 
4699     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4700     CloseKeyboard(true);
4701     FocusHub::LostFocusToViewRoot();
4702 #if defined(ANDROID_PLATFORM)
4703     return false;
4704 #else
4705     return true;
4706 #endif
4707 }
4708 
4709 int32_t TextFieldPattern::GetNakedCharPosition() const
4710 {
4711     if (IsTextArea() || !IsInPasswordMode() || obscureTickCountDown_ <= 0 || !GetTextObscured()) {
4712         return -1;
4713     }
4714     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4715     CHECK_NULL_RETURN(layoutProperty, -1);
4716     auto content = contentController_->GetTextValue();
4717     if (content.empty()) {
4718         return -1;
4719     }
4720     return nakedCharPosition_;
4721 }
4722 
4723 std::string TextFieldPattern::TextInputTypeToString() const
4724 {
4725     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4726     CHECK_NULL_RETURN(layoutProperty, "");
4727     switch (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
4728         case TextInputType::NUMBER:
4729             return "InputType.Number";
4730         case TextInputType::EMAIL_ADDRESS:
4731             return "InputType.Email";
4732         case TextInputType::VISIBLE_PASSWORD:
4733             return "InputType.Password";
4734         case TextInputType::USER_NAME:
4735             return "InputType.USER_NAME";
4736         case TextInputType::NEW_PASSWORD:
4737             return "InputType.NEW_PASSWORD";
4738         default:
4739             return "InputType.Normal";
4740     }
4741 }
4742 
4743 std::string TextFieldPattern::TextInputActionToString() const
4744 {
4745     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4746     CHECK_NULL_RETURN(layoutProperty, "");
4747     switch (GetTextInputActionValue(GetDefaultTextInputAction())) {
4748         case TextInputAction::GO:
4749             return "EnterKeyType.Go";
4750         case TextInputAction::SEARCH:
4751             return "EnterKeyType.Search";
4752         case TextInputAction::SEND:
4753             return "EnterKeyType.Send";
4754         case TextInputAction::NEXT:
4755             return "EnterKeyType.Next";
4756         default:
4757             return "EnterKeyType.Done";
4758     }
4759 }
4760 
4761 std::string TextFieldPattern::GetPlaceholderFont() const
4762 {
4763     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4764     CHECK_NULL_RETURN(layoutProperty, "");
4765     auto theme = GetTheme();
4766     CHECK_NULL_RETURN(theme, "");
4767     auto jsonValue = JsonUtil::Create(true);
4768     if (layoutProperty->GetPlaceholderItalicFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL) {
4769         jsonValue->Put("style", "FontStyle.Normal");
4770     } else {
4771         jsonValue->Put("style", "FontStyle.Italic");
4772     }
4773     // placeholder font size not exist in theme, use normal font size by default
4774     if (!layoutProperty->GetPlaceholderFontSize()) {
4775         jsonValue->Put("size", GetFontSize().c_str());
4776     } else {
4777         jsonValue->Put("size", layoutProperty->GetPlaceholderFontSize()->ToString().c_str());
4778     }
4779     auto weight = layoutProperty->GetPlaceholderFontWeightValue(theme->GetFontWeight());
4780     switch (weight) {
4781         case FontWeight::W100:
4782             jsonValue->Put("weight", "100");
4783             break;
4784         case FontWeight::W200:
4785             jsonValue->Put("weight", "200");
4786             break;
4787         case FontWeight::W300:
4788             jsonValue->Put("weight", "300");
4789             break;
4790         case FontWeight::W400:
4791             jsonValue->Put("weight", "400");
4792             break;
4793         case FontWeight::W500:
4794             jsonValue->Put("weight", "500");
4795             break;
4796         case FontWeight::W600:
4797             jsonValue->Put("weight", "600");
4798             break;
4799         case FontWeight::W700:
4800             jsonValue->Put("weight", "700");
4801             break;
4802         case FontWeight::W800:
4803             jsonValue->Put("weight", "800");
4804             break;
4805         case FontWeight::W900:
4806             jsonValue->Put("weight", "900");
4807             break;
4808         default:
4809             jsonValue->Put("fontWeight", V2::ConvertWrapFontWeightToStirng(weight).c_str());
4810     }
4811     auto family = layoutProperty->GetPlaceholderFontFamilyValue({ "sans-serif" });
4812     std::string jsonFamily = ConvertFontFamily(family);
4813     jsonValue->Put("fontFamily", jsonFamily.c_str());
4814     return jsonValue->ToString();
4815 }
4816 
4817 RefPtr<TextFieldTheme> TextFieldPattern::GetTheme() const
4818 {
4819     auto context = PipelineBase::GetCurrentContext();
4820     CHECK_NULL_RETURN(context, nullptr);
4821     auto theme = context->GetTheme<TextFieldTheme>();
4822     return theme;
4823 }
4824 
4825 std::string TextFieldPattern::GetTextColor() const
4826 {
4827     auto theme = GetTheme();
4828     CHECK_NULL_RETURN(theme, "");
4829     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4830     CHECK_NULL_RETURN(layoutProperty, "");
4831     return layoutProperty->GetTextColorValue(theme->GetTextColor()).ColorToString();
4832 }
4833 
4834 std::string TextFieldPattern::GetCaretColor() const
4835 {
4836     auto theme = GetTheme();
4837     CHECK_NULL_RETURN(theme, "");
4838     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4839     CHECK_NULL_RETURN(paintProperty, "");
4840     return paintProperty->GetCursorColorValue(theme->GetCursorColor()).ColorToString();
4841 }
4842 
4843 std::string TextFieldPattern::GetPlaceholderColor() const
4844 {
4845     auto theme = GetTheme();
4846     CHECK_NULL_RETURN(theme, "");
4847     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4848     CHECK_NULL_RETURN(layoutProperty, "");
4849     return layoutProperty->GetPlaceholderTextColorValue(theme->GetTextColor()).ColorToString();
4850 }
4851 
4852 std::string TextFieldPattern::GetFontSize() const
4853 {
4854     auto theme = GetTheme();
4855     CHECK_NULL_RETURN(theme, "");
4856     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4857     CHECK_NULL_RETURN(layoutProperty, "");
4858     return layoutProperty->GetFontSizeValue(theme->GetFontSize()).ToString();
4859 }
4860 
4861 Ace::FontStyle TextFieldPattern::GetItalicFontStyle() const
4862 {
4863     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4864     CHECK_NULL_RETURN(layoutProperty, Ace::FontStyle::NORMAL);
4865     return layoutProperty->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL);
4866 }
4867 
4868 std::string TextFieldPattern::GetShowPasswordIconString() const
4869 {
4870     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4871     CHECK_NULL_RETURN(layoutProperty, "false");
4872     return layoutProperty->GetShowPasswordIconValue(false) ? "true" : "false";
4873 }
4874 
4875 std::string TextFieldPattern::GetInputStyleString() const
4876 {
4877     std::string result = isTextInput_ ? "TextInputStyle.Default" : "TextContentStyle.DEFAULT";
4878     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4879     CHECK_NULL_RETURN(paintProperty, result);
4880     switch (paintProperty->GetInputStyleValue(InputStyle::DEFAULT)) {
4881         case InputStyle::INLINE:
4882             result = isTextInput_ ? "TextInputStyle.Inline" : "TextContentStyle.INLINE";
4883             break;
4884         case InputStyle::DEFAULT:
4885         default:
4886             break;
4887     }
4888     return result;
4889 }
4890 
4891 FontWeight TextFieldPattern::GetFontWeight() const
4892 {
4893     auto theme = GetTheme();
4894     CHECK_NULL_RETURN(theme, FontWeight::NORMAL);
4895     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4896     CHECK_NULL_RETURN(layoutProperty, FontWeight::NORMAL);
4897     return layoutProperty->GetFontWeightValue(theme->GetFontWeight());
4898 }
4899 
4900 std::string TextFieldPattern::GetFontFamily() const
4901 {
4902     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4903     CHECK_NULL_RETURN(layoutProperty, "HarmonyOS Sans");
4904     auto family = layoutProperty->GetFontFamilyValue({ "HarmonyOS Sans" });
4905     return ConvertFontFamily(family);
4906 }
4907 
4908 TextAlign TextFieldPattern::GetTextAlign() const
4909 {
4910     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4911     CHECK_NULL_RETURN(layoutProperty, TextAlign::START);
4912     return layoutProperty->GetTextAlign().value_or(TextAlign::START);
4913 }
4914 
4915 uint32_t TextFieldPattern::GetMaxLength() const
4916 {
4917     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4918     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
4919     return layoutProperty->HasMaxLength() ? layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())
4920                                           : Infinity<uint32_t>();
4921 }
4922 
4923 uint32_t TextFieldPattern::GetMaxLines() const
4924 {
4925     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4926     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
4927     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4928     CHECK_NULL_RETURN(paintProperty, Infinity<uint32_t>());
4929     if (IsNormalInlineState()) {
4930         return layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE);
4931     }
4932     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(Infinity<uint32_t>())
4933                                          : Infinity<uint32_t>();
4934 }
4935 
4936 std::string TextFieldPattern::GetPlaceHolder() const
4937 {
4938     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4939     CHECK_NULL_RETURN(layoutProperty, "");
4940     return layoutProperty->GetPlaceholderValue("");
4941 }
4942 
4943 std::string TextFieldPattern::GetInputFilter() const
4944 {
4945     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4946     CHECK_NULL_RETURN(layoutProperty, "");
4947     return layoutProperty->GetInputFilterValue("");
4948 }
4949 
4950 std::string TextFieldPattern::GetErrorTextString() const
4951 {
4952     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4953     CHECK_NULL_RETURN(layoutProperty, "");
4954     return layoutProperty->GetErrorTextValue("");
4955 }
4956 
4957 bool TextFieldPattern::GetErrorTextState() const
4958 {
4959     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4960     CHECK_NULL_RETURN(layoutProperty, false);
4961     return layoutProperty->GetShowErrorTextValue(false);
4962 }
4963 
4964 void TextFieldPattern::SearchRequestKeyboard()
4965 {
4966     StartTwinkling();
4967     if (RequestKeyboard(false, true, true)) {
4968         NotifyOnEditChanged(true);
4969     }
4970 }
4971 
4972 std::string TextFieldPattern::GetCopyOptionString() const
4973 {
4974     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4975     CHECK_NULL_RETURN(layoutProperty, "");
4976     std::string copyOptionString = "CopyOptions.None";
4977     switch (layoutProperty->GetCopyOptionsValue(CopyOptions::None)) {
4978         case CopyOptions::InApp:
4979             copyOptionString = "CopyOptions.InApp";
4980             break;
4981         case CopyOptions::Local:
4982             copyOptionString = "CopyOptions.Local";
4983             break;
4984         case CopyOptions::Distributed:
4985             copyOptionString = "CopyOptions.Distributed";
4986             break;
4987         case CopyOptions::None:
4988         default:
4989             break;
4990     }
4991     return copyOptionString;
4992 }
4993 
4994 std::string TextFieldPattern::GetBarStateString() const
4995 {
4996     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4997     CHECK_NULL_RETURN(layoutProperty, "");
4998     std::string displayModeString;
4999     switch (layoutProperty->GetDisplayModeValue(DisplayMode::AUTO)) {
5000         case DisplayMode::OFF:
5001             displayModeString = "BarState.OFF";
5002             break;
5003         case DisplayMode::ON:
5004             displayModeString = "BarState.ON";
5005             break;
5006         case DisplayMode::AUTO:
5007         default:
5008             displayModeString = "BarState.AUTO";
5009             break;
5010     }
5011     return displayModeString;
5012 }
5013 
5014 void TextFieldPattern::UpdateScrollBarOffset()
5015 {
5016     if (!GetScrollBar() && !GetScrollBarProxy()) {
5017         return;
5018     }
5019     auto paddingHeight = GetPaddingTop() + GetPaddingBottom();
5020     auto paddingRight = GetPaddingRight();
5021     auto contentHeight = contentRect_.Height();
5022     if (inlineFocusState_) {
5023         paddingHeight = 0.0f;
5024         paddingRight = 0.0f;
5025         contentHeight = GetSingleLineHeight() * GetMaxLines();
5026     }
5027     Size size(frameRect_.Width(), contentHeight + paddingHeight);
5028     UpdateScrollBarRegion(
5029         contentRect_.GetY() - textRect_.GetY(), textRect_.Height() + paddingHeight, size, Offset(0.0, 0.0));
5030     auto tmpHost = GetHost();
5031     CHECK_NULL_VOID(tmpHost);
5032     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5033 }
5034 
5035 bool TextFieldPattern::OnScrollCallback(float offset, int32_t source)
5036 {
5037     if (source == SCROLL_FROM_START) {
5038         auto scrollBar = GetScrollBar();
5039         if (scrollBar) {
5040             scrollBar->PlayScrollBarAppearAnimation();
5041         }
5042         OnParentScrollStartOrEnd(false, true);
5043         return true;
5044     }
5045     if (IsReachedBoundary(offset)) {
5046         return false;
5047     }
5048     OnTextInputScroll(offset);
5049     OnTextAreaScroll(offset);
5050     return true;
5051 }
5052 
5053 void TextFieldPattern::CheckScrollable()
5054 {
5055     if (IsTextArea()) {
5056         if (contentController_->IsEmpty()) {
5057             scrollable_ = false;
5058         } else {
5059             scrollable_ = GreatNotEqual(textRect_.Height(), contentRect_.Height());
5060         }
5061         SetScrollEnable(scrollable_);
5062     } else {
5063         SetScrollEnable(GreatNotEqual(textRect_.Width(), contentRect_.Width()));
5064     }
5065 }
5066 
5067 bool TextFieldPattern::HasStateStyle(UIState state) const
5068 {
5069     auto host = GetHost();
5070     CHECK_NULL_RETURN(host, false);
5071     auto hub = host->GetEventHub<EventHub>();
5072     CHECK_NULL_RETURN(hub, false);
5073     return hub->HasStateStyle(state);
5074 }
5075 
5076 double TextFieldPattern::GetScrollBarWidth()
5077 {
5078     auto scrollBar = GetScrollBar();
5079     double scrollBarWidth = 0.0;
5080     if (scrollBar) {
5081         scrollBarWidth = scrollBar->GetBarRect().Width();
5082     }
5083     return scrollBarWidth;
5084 }
5085 
5086 void TextFieldPattern::AddCounterNode()
5087 {
5088     auto host = GetHost();
5089     CHECK_NULL_VOID(host);
5090     auto counterNode = DynamicCast<UINode>(counterTextNode_.Upgrade());
5091     if (counterNode && (IsShowPasswordIcon() || IsNormalInlineState())) {
5092         CleanCounterNode();
5093         return;
5094     }
5095     if (!counterNode) {
5096         auto counterTextNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG,
5097             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
5098         counterTextNode_ = counterTextNode;
5099         counterTextNode->MountToParent(host);
5100         counterTextNode->MarkModifyDone();
5101         counterTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
5102     }
5103 }
5104 
5105 void TextFieldPattern::ClearCounterNode()
5106 {
5107     auto host = GetHost();
5108     if (!host->GetChildren().empty()) {
5109         host->Clean();
5110     }
5111 }
5112 
5113 void TextFieldPattern::SetShowError()
5114 {
5115     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5116     CHECK_NULL_VOID(layoutProperty);
5117     auto passWordMode = IsInPasswordMode();
5118     auto textFieldTheme = GetTheme();
5119     CHECK_NULL_VOID(textFieldTheme);
5120     auto tmpHost = GetHost();
5121     CHECK_NULL_VOID(tmpHost);
5122     auto renderContext = tmpHost->GetRenderContext();
5123     CHECK_NULL_VOID(renderContext);
5124     auto isUnderLine = layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType();
5125     auto errorText = layoutProperty->GetErrorTextValue("");
5126     auto preErrorState = preErrorState_;
5127     preErrorState_ = layoutProperty->GetShowErrorTextValue(false) && !errorText.empty()
5128                         && !IsNormalInlineState();
5129     if (preErrorState_) { // update error state
5130         if (isUnderLine) {
5131             underlineColor_ = textFieldTheme->GetErrorUnderlineColor();
5132             underlineWidth_ = ERROR_UNDERLINE_WIDTH;
5133         } else if (passWordMode) {
5134             BorderWidthProperty borderWidth;
5135             BorderColorProperty borderColor;
5136             borderWidth.SetBorderWidth(ERROR_BORDER_WIDTH);
5137             layoutProperty->UpdateBorderWidth(borderWidth);
5138             borderColor.SetColor(textFieldTheme->GetPasswordErrorBorderColor());
5139             renderContext->UpdateBorderColor(borderColor);
5140             renderContext->UpdateBackgroundColor(textFieldTheme->GetPasswordErrorInputColor());
5141             layoutProperty->UpdateTextColor(textFieldTheme->GetPasswordErrorTextColor());
5142         } else { // only show error text, reset border
5143             layoutProperty->UpdateBorderWidth(passwordModeStyle_.borderwidth);
5144             renderContext->UpdateBorderColor(passwordModeStyle_.borderColor);
5145             renderContext->UpdateBackgroundColor(passwordModeStyle_.bgColor);
5146             layoutProperty->UpdateTextColor(passwordModeStyle_.textColor);
5147         }
5148     } else if (preErrorState) { // need to clean error state
5149         underlineColor_ = textFieldTheme->GetUnderlineColor();
5150         underlineWidth_ = UNDERLINE_WIDTH;
5151         layoutProperty->UpdateBorderWidth(passwordModeStyle_.borderwidth);
5152         renderContext->UpdateBorderColor(passwordModeStyle_.borderColor);
5153         renderContext->UpdateBackgroundColor(passwordModeStyle_.bgColor);
5154         layoutProperty->UpdateTextColor(passwordModeStyle_.textColor);
5155     }
5156     UpdateErrorTextMargin();
5157 }
5158 
5159 void TextFieldPattern::CreateErrorParagraph(const std::string& content)
5160 {
5161     auto theme = GetTheme();
5162     CHECK_NULL_VOID(theme);
5163     TextStyle errorTextStyle = theme->GetErrorTextStyle();
5164     std::string errorText = content;
5165     ParagraphStyle paraStyle { .align = TextAlign::START,
5166         .maxLines = 1,
5167         .fontLocale = Localization::GetInstance()->GetFontLocale(),
5168         .textOverflow = TextOverflow::ELLIPSIS,
5169         .fontSize = errorTextStyle.GetFontSize().ConvertToPx() };
5170     errorParagraph_ = Paragraph::Create(paraStyle, FontCollection::Current());
5171     CHECK_NULL_VOID(errorParagraph_);
5172     errorParagraph_->PushStyle(errorTextStyle);
5173     StringUtils::TransformStrCase(errorText, static_cast<int32_t>(errorTextStyle.GetTextCase()));
5174     errorParagraph_->AddText(StringUtils::Str8ToStr16(errorText));
5175     errorParagraph_->Build();
5176 }
5177 
5178 void TextFieldPattern::UpdateErrorTextMargin()
5179 {
5180     auto tmpHost = GetHost();
5181     CHECK_NULL_VOID(tmpHost);
5182     auto renderContext = tmpHost->GetRenderContext();
5183     CHECK_NULL_VOID(renderContext);
5184     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5185     CHECK_NULL_VOID(layoutProperty);
5186     auto theme = GetTheme();
5187     CHECK_NULL_VOID(theme);
5188     MarginProperty errorMargin;
5189     auto errorText = layoutProperty->GetErrorTextValue("");
5190     if (layoutProperty->GetShowErrorTextValue(false) && !IsNormalInlineState() && !errorText.empty()) {
5191         CreateErrorParagraph(errorText);
5192         if (errorParagraph_) {
5193             errorParagraph_->Layout(std::numeric_limits<double>::infinity());
5194             auto errorTextMargin = ERROR_TEXT_TOP_MARGIN.ConvertToPx() +
5195                 ERROR_TEXT_BOTTOM_MARGIN.ConvertToPx() + errorParagraph_->GetHeight();
5196             if (preErrorMargin_ < errorTextMargin) {
5197                 errorMargin.bottom = CalcLength(errorTextMargin);
5198             }
5199         }
5200         errorMargin.right = CalcLength(passwordModeStyle_.margin.right->GetDimension());
5201         errorMargin.left = CalcLength(passwordModeStyle_.margin.left->GetDimension());
5202         errorMargin.top = CalcLength(passwordModeStyle_.margin.top->GetDimension());
5203         layoutProperty->UpdateMargin(errorMargin);
5204         restoreMarginState_ = true;
5205     } else if (restoreMarginState_ == true) {
5206         errorMargin.bottom = CalcLength(preErrorMargin_);
5207         errorMargin.right = CalcLength(passwordModeStyle_.margin.right->GetDimension());
5208         errorMargin.left = CalcLength(passwordModeStyle_.margin.left->GetDimension());
5209         errorMargin.top = CalcLength(passwordModeStyle_.margin.top->GetDimension());
5210         layoutProperty->UpdateMargin(errorMargin);
5211         restoreMarginState_ = false;
5212     }
5213 }
5214 
5215 void TextFieldPattern::SavePasswordModeStates()
5216 {
5217     auto tmpHost = GetHost();
5218     CHECK_NULL_VOID(tmpHost);
5219     auto renderContext = tmpHost->GetRenderContext();
5220     CHECK_NULL_VOID(renderContext);
5221     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5222     CHECK_NULL_VOID(layoutProperty);
5223     auto textFieldTheme = GetTheme();
5224     CHECK_NULL_VOID(textFieldTheme);
5225     preErrorMargin_ = GetMarginBottom();
5226     passwordModeStyle_.bgColor = renderContext->GetBackgroundColor().value_or(textFieldTheme->GetBgColor());
5227     passwordModeStyle_.textColor = layoutProperty->GetTextColorValue(textFieldTheme->GetTextColor());
5228     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
5229         passwordModeStyle_.borderwidth = *(layoutProperty->GetBorderWidthProperty());
5230     } else {
5231         BorderWidthProperty borderWidth;
5232         borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
5233         passwordModeStyle_.borderwidth = borderWidth;
5234     }
5235     BorderColorProperty borderColor;
5236     borderColor.SetColor(Color::TRANSPARENT);
5237     passwordModeStyle_.borderColor = renderContext->GetBorderColor().value_or(borderColor);
5238     auto radius = textFieldTheme->GetBorderRadius();
5239     BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
5240     passwordModeStyle_.radius = renderContext->GetBorderRadius().value_or(borderRadius);
5241 
5242     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
5243     if (paddingProperty) {
5244         passwordModeStyle_.padding.left = CalcLength(paddingProperty->left->GetDimension().ConvertToPx());
5245         passwordModeStyle_.padding.top = CalcLength(paddingProperty->top->GetDimension().ConvertToPx());
5246         passwordModeStyle_.padding.bottom = CalcLength(paddingProperty->bottom->GetDimension().ConvertToPx());
5247         passwordModeStyle_.padding.right = CalcLength(paddingProperty->right->GetDimension().ConvertToPx());
5248     } else {
5249         passwordModeStyle_.padding.left = CalcLength(0.0);
5250         passwordModeStyle_.padding.top = CalcLength(0.0);
5251         passwordModeStyle_.padding.bottom = CalcLength(0.0);
5252         passwordModeStyle_.padding.right = CalcLength(0.0);
5253     }
5254     const auto& marginProperty = layoutProperty->GetMarginProperty();
5255     if (marginProperty) {
5256         passwordModeStyle_.margin.left = CalcLength(marginProperty->left->GetDimension().ConvertToPx());
5257         passwordModeStyle_.margin.top = CalcLength(marginProperty->top->GetDimension().ConvertToPx());
5258         passwordModeStyle_.margin.bottom = CalcLength(marginProperty->bottom->GetDimension().ConvertToPx());
5259         passwordModeStyle_.margin.right = CalcLength(marginProperty->right->GetDimension().ConvertToPx());
5260     } else {
5261         passwordModeStyle_.margin.left = CalcLength(0.0_vp);
5262         passwordModeStyle_.margin.top = CalcLength(0.0_vp);
5263         passwordModeStyle_.margin.bottom = CalcLength(0.0_vp);
5264         passwordModeStyle_.margin.right = CalcLength(0.0_vp);
5265     }
5266 }
5267 
5268 void TextFieldPattern::SaveUnderlineStates()
5269 {
5270     auto tmpHost = GetHost();
5271     CHECK_NULL_VOID(tmpHost);
5272     auto renderContext = tmpHost->GetRenderContext();
5273     CHECK_NULL_VOID(renderContext);
5274     Radius radius;
5275     BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
5276     borderRadius_ = renderContext->GetBorderRadius().value_or(borderRadius);
5277 }
5278 
5279 void TextFieldPattern::ApplyUnderlineStates()
5280 {
5281     auto tmpHost = GetHost();
5282     CHECK_NULL_VOID(tmpHost);
5283     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5284     CHECK_NULL_VOID(layoutProperty);
5285     auto renderContext = tmpHost->GetRenderContext();
5286     CHECK_NULL_VOID(renderContext);
5287     auto theme = GetTheme();
5288     CHECK_NULL_VOID(theme);
5289     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5290     CHECK_NULL_VOID(paintProperty);
5291     if (!paintProperty->HasBackgroundColor()) {
5292         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
5293     }
5294     CalcSize idealSize;
5295     layoutProperty->UpdatePadding({ CalcLength(UNDERLINE_NORMAL_PADDING), CalcLength(UNDERLINE_NORMAL_PADDING),
5296         CalcLength(0.0_vp), CalcLength(0.0_vp) });
5297     ProcessInnerPadding();
5298     if (layoutProperty->GetPropertyChangeFlag() == PROPERTY_UPDATE_NORMAL) {
5299         std::optional<CalcLength> height(UNDERLINE_NORMAL_HEIGHT);
5300         idealSize.SetHeight(height);
5301         layoutProperty->UpdateUserDefinedIdealSize(idealSize);
5302     }
5303     if (!layoutProperty->HasFontSize()) {
5304         layoutProperty->UpdateFontSize(theme->GetUnderlineFontSize());
5305     }
5306     if (!layoutProperty->HasTextColor()) {
5307         layoutProperty->UpdateTextColor(theme->GetUnderlineTextColor());
5308     }
5309     Radius radius;
5310     renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
5311 }
5312 
5313 float TextFieldPattern::GetMarginBottom() const
5314 {
5315     auto tmpHost = GetHost();
5316     CHECK_NULL_RETURN(tmpHost, 0.0f);
5317     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5318     CHECK_NULL_RETURN(layoutProperty, 0.0f);
5319     const auto& getMargin = layoutProperty->GetMarginProperty();
5320     if (getMargin && getMargin->bottom.has_value()) {
5321         return getMargin->bottom->GetDimension().ConvertToPx();
5322     }
5323     return 0.0f;
5324 }
5325 
5326 std::string TextFieldPattern::GetShowResultImageSrc() const
5327 {
5328     auto tmpHost = GetHost();
5329     CHECK_NULL_RETURN(tmpHost, "");
5330     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5331     CHECK_NULL_RETURN(layoutProperty, "");
5332     auto showImageSource = layoutProperty->GetShowPasswordSourceInfo();
5333     if (showImageSource && !showImageSource->GetSrc().empty()) {
5334         return showImageSource->GetSrc();
5335     }
5336     return SHOW_PASSWORD_SVG;
5337 }
5338 
5339 std::string TextFieldPattern::GetHideResultImageSrc() const
5340 {
5341     auto tmpHost = GetHost();
5342     CHECK_NULL_RETURN(tmpHost, "");
5343     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5344     CHECK_NULL_RETURN(layoutProperty, "");
5345     auto hideSourceInfo = layoutProperty->GetHidePasswordSourceInfo();
5346     if (hideSourceInfo && !hideSourceInfo->GetSrc().empty()) {
5347         return hideSourceInfo->GetSrc();
5348     }
5349     return HIDE_PASSWORD_SVG;
5350 }
5351 
5352 void TextFieldPattern::SaveInlineStates()
5353 {
5354     auto tmpHost = GetHost();
5355     CHECK_NULL_VOID(tmpHost);
5356     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5357     CHECK_NULL_VOID(layoutProperty);
5358     auto renderContext = tmpHost->GetRenderContext();
5359     CHECK_NULL_VOID(renderContext);
5360     auto theme = GetTheme();
5361     CHECK_NULL_VOID(theme);
5362     inlineState_.textColor = layoutProperty->GetTextColorValue(theme->GetTextColor());
5363     inlineState_.bgColor = renderContext->GetBackgroundColor().value_or(theme->GetBgColor());
5364     auto radius = theme->GetBorderRadius();
5365     BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
5366     inlineState_.radius = renderContext->GetBorderRadius().value_or(borderRadius);
5367     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
5368         inlineState_.borderWidth = *(layoutProperty->GetBorderWidthProperty());
5369     } else {
5370         inlineState_.borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
5371     }
5372     if (renderContext->HasBorderColor()) {
5373         inlineState_.borderColor = renderContext->GetBorderColor().value();
5374         inlineState_.hasBorderColor = true;
5375     }
5376     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
5377     if (paddingProperty) {
5378         inlineState_.padding.left = CalcLength(paddingProperty->left->GetDimension().ConvertToPx());
5379         inlineState_.padding.top = CalcLength(paddingProperty->top->GetDimension().ConvertToPx());
5380         inlineState_.padding.bottom = CalcLength(paddingProperty->bottom->GetDimension().ConvertToPx());
5381         inlineState_.padding.right = CalcLength(paddingProperty->right->GetDimension().ConvertToPx());
5382     } else {
5383         inlineState_.padding.left = CalcLength(0.0_vp);
5384         inlineState_.padding.top = CalcLength(0.0_vp);
5385         inlineState_.padding.bottom = CalcLength(0.0_vp);
5386         inlineState_.padding.right = CalcLength(0.0_vp);
5387     }
5388     const auto& marginProperty = layoutProperty->GetMarginProperty();
5389     if (marginProperty) {
5390         inlineState_.margin.left = CalcLength(marginProperty->left->GetDimension().ConvertToPx());
5391         inlineState_.margin.top = CalcLength(marginProperty->top->GetDimension().ConvertToPx());
5392         inlineState_.margin.bottom = CalcLength(marginProperty->bottom->GetDimension().ConvertToPx());
5393         inlineState_.margin.right = CalcLength(marginProperty->right->GetDimension().ConvertToPx());
5394     } else {
5395         inlineState_.margin.left = CalcLength(0.0_vp);
5396         inlineState_.margin.top = CalcLength(0.0_vp);
5397         inlineState_.margin.bottom = CalcLength(0.0_vp);
5398         inlineState_.margin.right = CalcLength(0.0_vp);
5399     }
5400     if (inlineState_.saveState) {
5401         inlineState_.frameRect = frameRect_;
5402     }
5403 }
5404 
5405 void TextFieldPattern::TextAreaInputRectUpdate(RectF& rect)
5406 {
5407     auto tmpHost = GetHost();
5408     CHECK_NULL_VOID(tmpHost);
5409     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5410     CHECK_NULL_VOID(layoutProperty);
5411     auto theme = GetTheme();
5412     CHECK_NULL_VOID(theme);
5413     if (IsTextArea() && !contentController_->IsEmpty()) {
5414         auto inputContentWidth = GetParagraph()->GetMaxIntrinsicWidth();
5415         switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
5416             case TextAlign::START:
5417                 if (inputContentWidth < contentRect_.Width()) {
5418                     rect.SetWidth(inputContentWidth);
5419                 }
5420                 break;
5421             case TextAlign::CENTER:
5422                 if (inputContentWidth < contentRect_.Width()) {
5423                     rect.SetLeft(
5424                         static_cast<float>(rect.GetX()) + contentRect_.Width() / 2.0f - inputContentWidth / 2.0f);
5425                     rect.SetWidth(inputContentWidth);
5426                 }
5427                 break;
5428             case TextAlign::END:
5429                 if (inputContentWidth < contentRect_.Width()) {
5430                     rect.SetLeft(static_cast<float>(rect.GetX()) + contentRect_.Width() -
5431                                  static_cast<float>(theme->GetCursorWidth().ConvertToPx()) - inputContentWidth);
5432                     rect.SetWidth(inputContentWidth);
5433                 }
5434                 break;
5435             default:
5436                 break;
5437         }
5438     }
5439 }
5440 
5441 void TextFieldPattern::TextIsEmptyRect(RectF& rect)
5442 {
5443     rect = selectController_->CalculateEmptyValueCaretRect();
5444 }
5445 
5446 void TextFieldPattern::UpdateRectByTextAlign(RectF& rect)
5447 {
5448     auto tmpHost = GetHost();
5449     CHECK_NULL_VOID(tmpHost);
5450     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5451     CHECK_NULL_VOID(layoutProperty);
5452     if (!layoutProperty->HasTextAlign()) {
5453         return;
5454     }
5455     switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
5456         case TextAlign::START:
5457             return;
5458         case TextAlign::CENTER:
5459             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()) * 0.5f);
5460             return;
5461         case TextAlign::END:
5462             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()));
5463             return;
5464         default:
5465             return;
5466     }
5467 }
5468 
5469 void TextFieldPattern::ApplyInlineStates()
5470 {
5471     auto tmpHost = GetHost();
5472     CHECK_NULL_VOID(tmpHost);
5473     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5474     CHECK_NULL_VOID(layoutProperty);
5475     auto renderContext = tmpHost->GetRenderContext();
5476     CHECK_NULL_VOID(renderContext);
5477     auto theme = GetTheme();
5478     CHECK_NULL_VOID(theme);
5479     layoutProperty->UpdateTextColor(theme->GetInlineTextColor());
5480     auto radius = theme->GetInlineRadiusSize();
5481     renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
5482     renderContext->UpdateBackgroundColor(theme->GetInlineBgColor());
5483     BorderWidthProperty inlineBorderWidth;
5484     inlineBorderWidth.SetBorderWidth(INLINE_BORDER_WIDTH);
5485     layoutProperty->UpdateBorderWidth(inlineBorderWidth);
5486     renderContext->UpdateBorderWidth(inlineBorderWidth);
5487     BorderColorProperty inlineBorderColor;
5488     inlineBorderColor.SetColor(theme->GetInlineBorderColor());
5489     renderContext->UpdateBorderColor(inlineBorderColor);
5490     layoutProperty->UpdatePadding({ CalcLength(0.0f), CalcLength(0.0f), CalcLength(0.0f), CalcLength(0.0f) });
5491     ProcessInnerPadding();
5492     textRect_.SetLeft(GetPaddingLeft() + GetBorderLeft());
5493     textRect_.SetTop(GetPaddingTop() + GetBorderTop());
5494     MarginProperty margin;
5495     margin.bottom =
5496         CalcLength(inlineState_.padding.bottom->GetDimension() + inlineState_.margin.bottom->GetDimension());
5497     margin.right = CalcLength(inlineState_.padding.right->GetDimension() + inlineState_.margin.right->GetDimension());
5498     margin.left = CalcLength(inlineState_.padding.left->GetDimension() + inlineState_.margin.left->GetDimension());
5499     margin.top = CalcLength(inlineState_.padding.top->GetDimension() + inlineState_.margin.top->GetDimension());
5500     layoutProperty->UpdateMargin(margin);
5501     if (!IsTextArea()) {
5502         layoutProperty->UpdatePlaceholderMaxLines(layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
5503         layoutProperty->ResetMaxLines();
5504     }
5505     needApplyInlineSize_ = true;
5506 }
5507 
5508 bool TextFieldPattern::ResetObscureTickCountDown()
5509 {
5510     auto oldTickCountDown_ = obscureTickCountDown_;
5511     if (!IsTextArea() && GetTextObscured() && IsInPasswordMode()) {
5512         obscureTickCountDown_ = 0;
5513     }
5514     return oldTickCountDown_ != obscureTickCountDown_;
5515 }
5516 
5517 bool TextFieldPattern::IsInPasswordMode() const
5518 {
5519     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5520     CHECK_NULL_RETURN(layoutProperty, false);
5521     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
5522     return inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
5523            inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
5524 }
5525 
5526 void TextFieldPattern::RestorePreInlineStates()
5527 {
5528     auto tmpHost = GetHost();
5529     CHECK_NULL_VOID(tmpHost);
5530     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5531     CHECK_NULL_VOID(layoutProperty);
5532     auto renderContext = tmpHost->GetRenderContext();
5533     CHECK_NULL_VOID(renderContext);
5534     auto pipeline = PipelineContext::GetCurrentContext();
5535     CHECK_NULL_VOID(pipeline);
5536     layoutProperty->UpdateTextColor(inlineState_.textColor);
5537     layoutProperty->UpdatePadding(inlineState_.padding);
5538     inlinePadding_ = 0.0f;
5539     BorderWidthProperty currentBorderWidth;
5540     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
5541         currentBorderWidth = *(layoutProperty->GetBorderWidthProperty());
5542     } else {
5543         currentBorderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
5544     }
5545     textRect_.SetOffset(OffsetF((GetPaddingLeft() + (float)(currentBorderWidth.leftDimen->ConvertToPx())),
5546         (GetPaddingTop() + (float)currentBorderWidth.topDimen->ConvertToPx())));
5547     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN) || IsNormalInlineState()) {
5548         textRect_.SetOffset(OffsetF(GetPaddingLeft(), GetPaddingTop()));
5549     }
5550     layoutProperty->UpdateMargin(inlineState_.margin);
5551     renderContext->UpdateBackgroundColor(inlineState_.bgColor);
5552     layoutProperty->UpdateBorderWidth(inlineState_.borderWidth);
5553     renderContext->UpdateBorderWidth(inlineState_.borderWidth);
5554     renderContext->UpdateBorderRadius(inlineState_.radius);
5555     if (inlineState_.hasBorderColor) {
5556         renderContext->UpdateBorderColor(inlineState_.borderColor);
5557     }
5558     ProcessInnerPadding();
5559     if (layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType()) {
5560         ApplyUnderlineStates();
5561     }
5562 }
5563 
5564 void TextFieldPattern::RestoreUnderlineStates()
5565 {
5566     auto host = GetHost();
5567     CHECK_NULL_VOID(host);
5568     auto renderContext = host->GetRenderContext();
5569     CHECK_NULL_VOID(renderContext);
5570     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5571     CHECK_NULL_VOID(paintProperty);
5572 
5573     if (!preUnderlineState_.saveState) {
5574         auto theme = GetTheme();
5575         CHECK_NULL_VOID(theme);
5576         renderContext->UpdateBackgroundColor(theme->GetBgColor());
5577         auto radius = theme->GetBorderRadius();
5578         BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
5579         renderContext->UpdateBorderRadius(borderRadius);
5580         return;
5581     }
5582 
5583     if (!paintProperty->HasBackgroundColor()) {
5584         renderContext->UpdateBackgroundColor(preUnderlineState_.bgColor);
5585     }
5586     renderContext->UpdateBorderRadius(preUnderlineState_.radius);
5587     preUnderlineState_.saveState = false;
5588 }
5589 
5590 bool TextFieldPattern::IsNormalInlineState() const
5591 {
5592     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5593     CHECK_NULL_RETURN(paintProperty, false);
5594     auto tmpHost = GetHost();
5595     CHECK_NULL_RETURN(tmpHost, false);
5596     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5597     CHECK_NULL_RETURN(layoutProperty, false);
5598     return paintProperty->GetInputStyleValue(InputStyle::DEFAULT) == InputStyle::INLINE &&
5599            (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::UNSPECIFIED ||
5600                layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::TEXT);
5601 }
5602 
5603 bool TextFieldPattern::IsUnspecifiedOrTextType() const
5604 {
5605     auto tmpHost = GetHost();
5606     CHECK_NULL_RETURN(tmpHost, false);
5607     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5608     CHECK_NULL_RETURN(layoutProperty, false);
5609     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
5610     return inputType == TextInputType::UNSPECIFIED || inputType == TextInputType::TEXT;
5611 }
5612 
5613 void TextFieldPattern::ToJsonValue(std::unique_ptr<JsonValue>& json) const
5614 {
5615     json->Put("placeholder", GetPlaceHolder().c_str());
5616     json->Put("text", contentController_->GetTextValue().c_str());
5617     json->Put("fontSize", GetFontSize().c_str());
5618     json->Put("fontColor", GetTextColor().c_str());
5619     json->Put("fontStyle", GetItalicFontStyle() == Ace::FontStyle::NORMAL ? "FontStyle.Normal" : "FontStyle.Italic");
5620     json->Put("fontWeight", V2::ConvertWrapFontWeightToStirng(GetFontWeight()).c_str());
5621     json->Put("fontFamily", GetFontFamily().c_str());
5622     json->Put("textAlign", V2::ConvertWrapTextAlignToString(GetTextAlign()).c_str());
5623     json->Put("caretColor", GetCaretColor().c_str());
5624     json->Put("type", TextInputTypeToString().c_str());
5625     json->Put("placeholderColor", GetPlaceholderColor().c_str());
5626     json->Put("placeholderFont", GetPlaceholderFont().c_str());
5627     json->Put("enterKeyType", TextInputActionToString().c_str());
5628     auto maxLength = GetMaxLength();
5629     json->Put("maxLength", GreatOrEqual(maxLength, Infinity<uint32_t>()) ? "INF" : std::to_string(maxLength).c_str());
5630     json->Put("inputFilter", GetInputFilter().c_str());
5631     json->Put("copyOption", GetCopyOptionString().c_str());
5632     json->Put("style", GetInputStyleString().c_str());
5633     auto jsonValue = JsonUtil::Create(true);
5634     jsonValue->Put("onIconSrc", GetShowResultImageSrc().c_str());
5635     jsonValue->Put("offIconSrc", GetHideResultImageSrc().c_str());
5636     json->Put("passwordIcon", jsonValue->ToString().c_str());
5637     json->Put("showError", GetErrorTextState() ? GetErrorTextString().c_str() : "undefined");
5638     auto maxLines = GetMaxLines();
5639     json->Put("maxLines", GreatOrEqual(maxLines, Infinity<uint32_t>()) ? "INF" : std::to_string(maxLines).c_str());
5640     json->Put("barState", GetBarStateString().c_str());
5641     json->Put("caretPosition", std::to_string(GetCaretIndex()).c_str());
5642     auto host = GetHost();
5643     CHECK_NULL_VOID(host);
5644     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5645     CHECK_NULL_VOID(layoutProperty);
5646     auto jsonShowCounter = JsonUtil::Create(true);
5647     jsonShowCounter->Put("value", layoutProperty->GetShowCounterValue(false));
5648     auto jsonShowCounterOptions = JsonUtil::Create(true);
5649     auto counterType = layoutProperty->GetSetCounterValue(DEFAULT_MODE);
5650     auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
5651     jsonShowCounterOptions->Put("thresholdPercentage", counterType);
5652     jsonShowCounterOptions->Put("highlightBorder", showBorder);
5653     jsonShowCounter->Put("options", jsonShowCounterOptions);
5654     json->Put("showCounter", jsonShowCounter);
5655 }
5656 
5657 void TextFieldPattern::FromJson(const std::unique_ptr<JsonValue>& json)
5658 {
5659     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5660     layoutProperty->UpdatePlaceholder(json->GetString("placeholder"));
5661     UpdateEditingValue(json->GetString("text"), StringUtils::StringToInt(json->GetString("caretPosition")));
5662     FireOnTextChangeEvent();
5663     UpdateSelection(GetCaretIndex());
5664     auto maxLines = json->GetString("maxLines");
5665     if (!maxLines.empty() && maxLines != "INF") {
5666         layoutProperty->UpdateMaxLines(StringUtils::StringToUint(maxLines));
5667     }
5668     static const std::unordered_map<std::string, CopyOptions> uMap = {
5669         { "CopyOptions.None", CopyOptions::None },
5670         { "CopyOptions.InApp", CopyOptions::InApp },
5671         { "CopyOptions.Local", CopyOptions::Local },
5672         { "CopyOptions.Distributed", CopyOptions::Distributed },
5673     };
5674     auto copyOption = json->GetString("copyOption");
5675     layoutProperty->UpdateCopyOptions(uMap.count(copyOption) ? uMap.at(copyOption) : CopyOptions::None);
5676     Pattern::FromJson(json);
5677 }
5678 
5679 void TextFieldPattern::SetAccessibilityAction()
5680 {
5681     auto host = GetHost();
5682     CHECK_NULL_VOID(host);
5683     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
5684     CHECK_NULL_VOID(accessibilityProperty);
5685     accessibilityProperty->SetActionSetText([weakPtr = WeakClaim(this)](const std::string& value) {
5686         const auto& pattern = weakPtr.Upgrade();
5687         CHECK_NULL_VOID(pattern);
5688         pattern->InsertValue(value);
5689     });
5690 
5691     accessibilityProperty->SetActionSetSelection([weakPtr = WeakClaim(this)](int32_t start, int32_t end) {
5692         const auto& pattern = weakPtr.Upgrade();
5693         CHECK_NULL_VOID(pattern);
5694         pattern->SetSelectionFlag(start, end);
5695     });
5696 
5697     accessibilityProperty->SetActionCopy([weakPtr = WeakClaim(this)]() {
5698         const auto& pattern = weakPtr.Upgrade();
5699         CHECK_NULL_VOID(pattern);
5700         if (pattern->AllowCopy()) {
5701             pattern->HandleOnCopy();
5702             pattern->CloseSelectOverlay(true);
5703         }
5704     });
5705 
5706     accessibilityProperty->SetActionCut([weakPtr = WeakClaim(this)]() {
5707         const auto& pattern = weakPtr.Upgrade();
5708         CHECK_NULL_VOID(pattern);
5709         if (pattern->AllowCopy()) {
5710             pattern->HandleOnCut();
5711             pattern->CloseSelectOverlay(true);
5712         }
5713     });
5714 
5715     accessibilityProperty->SetActionPaste([weakPtr = WeakClaim(this)]() {
5716         const auto& pattern = weakPtr.Upgrade();
5717         CHECK_NULL_VOID(pattern);
5718         pattern->HandleOnPaste();
5719         pattern->CloseSelectOverlay(true);
5720     });
5721 
5722     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
5723         const auto& pattern = weakPtr.Upgrade();
5724         CHECK_NULL_VOID(pattern);
5725         auto current = pattern->selectController_->GetEndIndex();
5726         pattern->SetInSelectMode(SelectionMode::NONE);
5727         pattern->UpdateSelection(current);
5728         pattern->SetSelectionFlag(current, current);
5729         pattern->CloseSelectOverlay(true);
5730         pattern->StartTwinkling();
5731     });
5732     SetAccessibilityScrollAction();
5733     SetAccessibilityMoveTextAction();
5734 }
5735 
5736 void TextFieldPattern::SetAccessibilityMoveTextAction()
5737 {
5738     auto host = GetHost();
5739     CHECK_NULL_VOID(host);
5740     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
5741     CHECK_NULL_VOID(accessibilityProperty);
5742     accessibilityProperty->SetActionMoveText([weakPtr = WeakClaim(this)](int32_t moveUnit, bool forward) {
5743         const auto& pattern = weakPtr.Upgrade();
5744         CHECK_NULL_VOID(pattern);
5745         auto host = pattern->GetHost();
5746         CHECK_NULL_VOID(host);
5747         if (pattern->contentController_->IsEmpty()) {
5748             return;
5749         }
5750         int range = 0;
5751         if (moveUnit == 1) {
5752             range = 1;
5753         }
5754         auto caretPosition = forward ? pattern->selectController_->GetCaretIndex() + range
5755                                      : pattern->selectController_->GetCaretIndex() - range;
5756         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5757         pattern->SetCaretPosition(caretPosition);
5758     });
5759 }
5760 
5761 void TextFieldPattern::SetAccessibilityScrollAction()
5762 {
5763     auto host = GetHost();
5764     CHECK_NULL_VOID(host);
5765     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
5766     CHECK_NULL_VOID(accessibilityProperty);
5767     accessibilityProperty->SetActionScrollForward([weakPtr = WeakClaim(this)]() {
5768         const auto& pattern = weakPtr.Upgrade();
5769         CHECK_NULL_VOID(pattern);
5770         if (pattern->IsScrollable()) {
5771             auto frameNode = pattern->GetHost();
5772             CHECK_NULL_VOID(frameNode);
5773             auto offset = pattern->GetTextContentRect().Height();
5774             float scrollDistance =
5775                 pattern->GetTextRect().Height() - (std::abs((pattern->GetTextRect().GetY() - offset)));
5776             if (offset > scrollDistance) {
5777                 pattern->OnTextAreaScroll(-scrollDistance);
5778                 // AccessibilityEventType::SCROLL_END
5779                 return;
5780             }
5781             pattern->OnTextAreaScroll(-offset);
5782             // AccessibilityEventType::SCROLL_END
5783         }
5784     });
5785 
5786     accessibilityProperty->SetActionScrollBackward([weakPtr = WeakClaim(this)]() {
5787         const auto& pattern = weakPtr.Upgrade();
5788         CHECK_NULL_VOID(pattern);
5789         if (pattern->IsScrollable()) {
5790             auto frameNode = pattern->GetHost();
5791             CHECK_NULL_VOID(frameNode);
5792             auto offset = pattern->GetTextContentRect().Height();
5793             float scrollDistance = std::abs(pattern->GetTextRect().GetY() - pattern->GetTextContentRect().GetY());
5794             if (offset > scrollDistance) {
5795                 pattern->OnTextAreaScroll(scrollDistance);
5796                 // AccessibilityEventType::SCROLL_END
5797                 return;
5798             }
5799             pattern->OnTextAreaScroll(offset);
5800             // AccessibilityEventType::SCROLL_END
5801         }
5802     });
5803 }
5804 
5805 void TextFieldPattern::StopEditing()
5806 {
5807     if (!HasFocus()) {
5808         return;
5809     }
5810 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
5811     if (HasConnection() || isCustomKeyboardAttached_) {
5812 #else
5813     if (isCustomKeyboardAttached_) {
5814 #endif
5815         NotifyOnEditChanged(false);
5816     }
5817     UpdateSelection(selectController_->GetCaretIndex());
5818     StopTwinkling();
5819     CloseKeyboard(true);
5820     auto host = GetHost();
5821     CHECK_NULL_VOID(host);
5822     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5823 }
5824 
5825 bool TextFieldPattern::CheckHandleVisible(const RectF& paintRect)
5826 {
5827     auto host = GetHost();
5828     CHECK_NULL_RETURN(host, false);
5829     // use global offset.
5830     RectF visibleContentRect(contentRect_.GetOffset() + parentGlobalOffset_, contentRect_.GetSize());
5831     auto parent = host->GetAncestorNodeOfFrame();
5832     visibleContentRect = GetVisibleContentRect(parent, visibleContentRect);
5833     if (!IsTextArea()) {
5834         auto verticalEpsilon = std::max(0.0f, paintRect.Height() - contentRect_.Height());
5835         return GreatOrEqual(paintRect.Top() + verticalEpsilon, visibleContentRect.Top()) &&
5836                LessOrEqual(paintRect.Bottom() - verticalEpsilon, visibleContentRect.Bottom()) &&
5837                LessOrEqual(paintRect.Left(), visibleContentRect.Right()) &&
5838                GreatOrEqual(paintRect.Right(), visibleContentRect.Left());
5839     }
5840     PointF bottomPoint = { paintRect.Left(), paintRect.Bottom() - BOX_EPSILON };
5841     PointF topPoint = { paintRect.Left(), paintRect.Top() + BOX_EPSILON };
5842     visibleContentRect.SetLeft(visibleContentRect.GetX() - BOX_EPSILON);
5843     visibleContentRect.SetWidth(visibleContentRect.Width() + 2 * BOX_EPSILON);
5844     visibleContentRect.SetTop(visibleContentRect.GetY() - BOX_EPSILON);
5845     visibleContentRect.SetHeight(visibleContentRect.Height() + 2 * BOX_EPSILON);
5846     return visibleContentRect.IsInRegion(bottomPoint) && visibleContentRect.IsInRegion(topPoint);
5847 }
5848 
5849 void TextFieldPattern::DumpInfo()
5850 {
5851     auto host = GetHost();
5852     CHECK_NULL_VOID(host);
5853     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5854     CHECK_NULL_VOID(layoutProperty);
5855     DumpLog::GetInstance().AddDesc(std::string("Content:").append(GetTextValue()));
5856     DumpLog::GetInstance().AddDesc(std::string("MaxLength:").append(std::to_string(GetMaxLength())));
5857     DumpLog::GetInstance().AddDesc(std::string("InputFilter:").append(GetInputFilter()));
5858     DumpLog::GetInstance().AddDesc(std::string("CopyOption:").append(GetCopyOptionString()));
5859     DumpLog::GetInstance().AddDesc(std::string("TextAlign:").append(std::to_string((int32_t)GetTextAlign())));
5860     DumpLog::GetInstance().AddDesc(std::string("CaretPosition:").append(std::to_string(GetCaretIndex())));
5861     DumpLog::GetInstance().AddDesc(std::string("enableKeyboardOnFocus:")
5862                             .append(std::to_string(needToRequestKeyboardOnFocus_)));
5863     DumpLog::GetInstance().AddDesc(std::string("enableAutoFill:")
5864                             .append(std::to_string(layoutProperty->GetEnableAutoFillValue(true))));
5865     DumpLog::GetInstance().AddDesc(std::string("HasFocus:").append(std::to_string(HasFocus())));
5866 #if defined(ENABLE_STANDARD_INPUT)
5867     auto miscTextConfig = GetMiscTextConfig();
5868     CHECK_NULL_VOID(miscTextConfig.has_value());
5869     MiscServices::TextConfig textConfig = miscTextConfig.value();
5870     DumpLog::GetInstance().AddDesc(std::string("RequestKeyboard calling window :")
5871                                         .append(std::to_string(textConfig.windowId))
5872                                         .append(std::string("inputType:"))
5873                                         .append(std::to_string(textConfig.inputAttribute.inputPattern))
5874                                         .append(std::string("enterKeyType:"))
5875                                         .append(std::to_string(textConfig.inputAttribute.enterKeyType)));
5876 #endif
5877     DumpLog::GetInstance().AddDesc(textSelector_.ToString());
5878     if (customKeyboardBuilder_) {
5879         DumpLog::GetInstance().AddDesc(std::string("CustomKeyboard: true")
5880                                             .append(", Attached: ")
5881                                             .append(std::to_string(isCustomKeyboardAttached_)));
5882     }
5883 }
5884 
5885 void TextFieldPattern::DumpAdvanceInfo()
5886 {
5887     if (customKeyboardBuilder_) {
5888         DumpLog::GetInstance().AddDesc(std::string("CustomKeyboard: true")
5889                                            .append(", Attached: ")
5890                                            .append(std::to_string(isCustomKeyboardAttached_)));
5891     }
5892 #if defined(ENABLE_STANDARD_INPUT)
5893     auto miscTextConfig = GetMiscTextConfig();
5894     CHECK_NULL_VOID(miscTextConfig.has_value());
5895     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
5896     DumpLog::GetInstance().AddDesc(std::string("cursorInfo")
5897                                        .append(", left:")
5898                                        .append(std::to_string(cursorInfo.left))
5899                                        .append(", top:")
5900                                        .append(std::to_string(cursorInfo.top))
5901                                        .append(", width:")
5902                                        .append(std::to_string(cursorInfo.width))
5903                                        .append(", height:")
5904                                        .append(std::to_string(cursorInfo.height)));
5905 #endif
5906     DumpLog::GetInstance().AddDesc(std::string("textRect-->x:")
5907                                        .append(std::to_string(textRect_.GetX()))
5908                                        .append(" y:")
5909                                        .append(std::to_string(textRect_.GetY())));
5910     DumpLog::GetInstance().AddDesc(std::string("contentRect-->x:")
5911                                        .append(std::to_string(contentRect_.GetX()))
5912                                        .append(" y:")
5913                                        .append(std::to_string(contentRect_.GetY())));
5914     DumpLog::GetInstance().AddDesc(textSelector_.ToString());
5915 }
5916 
5917 void TextFieldPattern::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap)
5918 {
5919     CHECK_NULL_VOID(viewDataWrap);
5920     auto host = GetHost();
5921     CHECK_NULL_VOID(host);
5922     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5923     CHECK_NULL_VOID(layoutProperty);
5924     auto autoFillType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
5925     auto info = PageNodeInfoWrap::CreatePageNodeInfoWrap();
5926     CHECK_NULL_VOID(info);
5927     info->SetId(host->GetId());
5928     info->SetDepth(host->GetDepth());
5929     info->SetAutoFillType(autoFillType);
5930     info->SetTag(host->GetTag());
5931     info->SetValue(contentController_->GetTextValue());
5932     info->SetPlaceholder(GetPlaceHolder());
5933     info->SetPasswordRules(layoutProperty->GetPasswordRulesValue(""));
5934     info->SetEnableAutoFill(layoutProperty->GetEnableAutoFillValue(true));
5935     viewDataWrap->AddPageNodeInfoWrap(info);
5936 }
5937 
5938 void TextFieldPattern::NotifyFillRequestSuccess(RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
5939 {
5940     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "autoFillType:%{public}d", static_cast<int32_t>(autoFillType));
5941     CHECK_NULL_VOID(nodeWrap);
5942     if (!contentController_ || contentController_->GetTextValue() == nodeWrap->GetValue()) {
5943         return;
5944     }
5945     contentController_->SetTextValue(nodeWrap->GetValue());
5946     auto host = GetHost();
5947     CHECK_NULL_VOID(host);
5948     NotifyOnEditChanged(true);
5949     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
5950     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5951     CHECK_NULL_VOID(layoutProperty);
5952     auto type = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
5953     if (!(type == AceAutoFillType::ACE_NEW_PASSWORD && type == autoFillType)) {
5954         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "Set last auto fill text value.");
5955         lastAutoFillPasswordTextValue_ = nodeWrap->GetValue();
5956     }
5957 }
5958 
5959 void TextFieldPattern::NotifyFillRequestFailed(int32_t errCode)
5960 {
5961     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "errCode:%{public}d", errCode);
5962     if (errCode == AUTO_FILL_FAILED) {
5963         return;
5964     }
5965     if (RequestKeyboard(false, true, true)) {
5966         NotifyOnEditChanged(true);
5967     }
5968     auto host = GetHost();
5969     CHECK_NULL_VOID(host);
5970     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5971 }
5972 
5973 bool TextFieldPattern::CheckAutoSave()
5974 {
5975     auto host = GetHost();
5976     CHECK_NULL_RETURN(host, false);
5977     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5978     CHECK_NULL_RETURN(layoutProperty, false);
5979     if (!layoutProperty->GetEnableAutoFillValue(true)) {
5980         return false;
5981     }
5982     if (!contentController_ || contentController_->GetTextValue().empty()) {
5983         return false;
5984     }
5985     auto autoFillType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
5986     if (autoFillType == TextInputType::USER_NAME) {
5987         if (!lastAutoFillPasswordTextValue_.empty() &&
5988             contentController_->GetTextValue() != lastAutoFillPasswordTextValue_) {
5989             return true;
5990         }
5991     }
5992     if ((autoFillType == TextInputType::VISIBLE_PASSWORD || autoFillType == TextInputType::NEW_PASSWORD)) {
5993         if (contentController_->GetTextValue() != lastAutoFillPasswordTextValue_) {
5994             return true;
5995         }
5996     }
5997     return false;
5998 }
5999 
6000 bool TextFieldPattern::IsTouchAtLeftOffset(float currentOffsetX)
6001 {
6002     return LessNotEqual(currentOffsetX, contentRect_.GetX() + contentRect_.Width() * 0.5);
6003 }
6004 
6005 OffsetF TextFieldPattern::GetDragUpperLeftCoordinates()
6006 {
6007     if (!IsSelected()) {
6008         return { 0.0f, 0.0f };
6009     }
6010     auto selectRects = selectController_->GetSelectedRects();
6011     auto startY = selectRects.front().Top();
6012     auto startX = selectRects.front().Left();
6013     auto endY = selectRects.back().Top();
6014     OffsetF startOffset;
6015     if (NearEqual(startY, endY)) {
6016         startOffset = { (IsTextArea() ? contentRect_.GetX() : textRect_.GetX()) + startX,
6017             startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
6018     } else {
6019         startOffset = { contentRect_.GetX(), startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
6020     }
6021 
6022     if (startOffset.GetY() < contentRect_.GetY()) {
6023         startOffset.SetY(contentRect_.GetY());
6024     }
6025     if (startOffset.GetX() < contentRect_.GetX()) {
6026         startOffset.SetX(contentRect_.GetX());
6027     }
6028     return startOffset + parentGlobalOffset_;
6029 }
6030 
6031 void TextFieldPattern::OnColorConfigurationUpdate()
6032 {
6033     colorModeChange_ = true;
6034     auto host = GetHost();
6035     CHECK_NULL_VOID(host);
6036     auto context = PipelineContext::GetCurrentContext();
6037     CHECK_NULL_VOID(context);
6038     auto theme = context->GetTheme<TextTheme>();
6039     CHECK_NULL_VOID(theme);
6040     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6041     CHECK_NULL_VOID(layoutProperty);
6042     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6043     CHECK_NULL_VOID(paintProperty);
6044     if (!paintProperty->GetTextColorFlagByUserValue(false)) {
6045         layoutProperty->UpdateTextColor(theme->GetTextStyle().GetTextColor());
6046     }
6047     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6048 }
6049 
6050 bool TextFieldPattern::IsReachedBoundary(float offset)
6051 {
6052     if (IsTextArea()) {
6053         return (NearEqual(textRect_.GetY(), contentRect_.GetY()) && GreatNotEqual(offset, 0.0f)) ||
6054                (NearEqual(textRect_.GetY() + textRect_.Height(), contentRect_.GetY() + contentRect_.Height()) &&
6055                    LessNotEqual(offset, 0.0f));
6056     }
6057 
6058     return (NearEqual(textRect_.GetX(), contentRect_.GetX()) && GreatNotEqual(offset, 0.0f)) ||
6059            (NearEqual(textRect_.GetX() + textRect_.Width(), contentRect_.GetX() + contentRect_.Width()) &&
6060                LessNotEqual(offset, 0.0f));
6061 }
6062 
6063 OffsetF TextFieldPattern::GetTextPaintOffset() const
6064 {
6065     auto host = GetHost();
6066     CHECK_NULL_RETURN(host, OffsetF(0.0f, 0.0f));
6067     auto pipeline = host->GetContext();
6068     CHECK_NULL_RETURN(pipeline, OffsetF(0.0f, 0.0f));
6069     auto rootOffset = pipeline->GetRootRect().GetOffset();
6070     auto textPaintOffset = host->GetPaintRectOffset();
6071     return textPaintOffset - rootOffset;
6072 }
6073 
6074 void TextFieldPattern::UpdateSelectController()
6075 {
6076     selectController_->UpdateContentRect(contentRect_);
6077     selectController_->UpdateParagraph(paragraph_);
6078 }
6079 
6080 bool TextFieldPattern::RepeatClickCaret(const Offset& offset, int32_t lastCaretIndex, const RectF& lastCaretRect)
6081 {
6082     auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset);
6083     if (!selectController_->CaretAtLast()) {
6084         return lastCaretIndex == touchDownIndex && HasFocus();
6085     }
6086     // Increase the cursor area if there is no text
6087     auto caretRect = lastCaretRect;
6088     caretRect.SetLeft(caretRect.GetX() - caretRect.Height() / 2);
6089     caretRect.SetWidth(caretRect.Height());
6090     return caretRect.IsInRegion(PointF(offset.GetX(), offset.GetY()));
6091 }
6092 
6093 bool TextFieldPattern::IsSingleHandle() const
6094 {
6095     return contentController_->IsEmpty() || !IsSelected();
6096 }
6097 
6098 void TextFieldPattern::OnAttachToFrameNode()
6099 {
6100     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6101     CHECK_NULL_VOID(layoutProperty);
6102     layoutProperty->UpdateCopyOptions(CopyOptions::Distributed);
6103     auto onTextSelectorChange = [weak = WeakClaim(this)]() {
6104         auto pattern = weak.Upgrade();
6105         CHECK_NULL_VOID(pattern);
6106         auto frameNode = pattern->GetHost();
6107         CHECK_NULL_VOID(frameNode);
6108         frameNode->OnAccessibilityEvent(AccessibilityEventType::TEXT_SELECTION_UPDATE);
6109     };
6110     selectController_->SetOnAccessibility(std::move(onTextSelectorChange));
6111 }
6112 
6113 bool TextFieldPattern::NeedPaintSelect()
6114 {
6115     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6116     CHECK_NULL_RETURN(paintProperty, false);
6117     auto firstHandle = paintProperty->GetFirstHandleInfo();
6118     auto secondHandle = paintProperty->GetSecondHandleInfo();
6119     auto caretInfo = selectController_->GetCaretInfo();
6120     if (!IsSelected()) {
6121         if (!firstHandle.has_value() || !secondHandle.has_value()) {
6122             paintProperty->UpdateFirstHandleInfo(caretInfo);
6123             paintProperty->UpdateSecondHandleInfo(caretInfo);
6124             return false;
6125         }
6126 
6127         if (firstHandle->index != secondHandle->index || firstHandle->index != caretInfo.index) {
6128             paintProperty->UpdateFirstHandleInfo(caretInfo);
6129             paintProperty->UpdateSecondHandleInfo(caretInfo);
6130             return true;
6131         }
6132         return false;
6133     }
6134     auto needPaint = firstHandle != selectController_->GetFirstHandleInfo() ||
6135                      secondHandle != selectController_->GetSecondHandleInfo();
6136     paintProperty->UpdateFirstHandleInfo(selectController_->GetFirstHandleInfo());
6137     paintProperty->UpdateSecondHandleInfo(selectController_->GetSecondHandleInfo());
6138     return needPaint;
6139 }
6140 
6141 RefPtr<FocusHub> TextFieldPattern::GetFocusHub() const
6142 {
6143     auto host = GetHost();
6144     CHECK_NULL_RETURN(host, nullptr);
6145     auto focusHub = host->GetOrCreateFocusHub();
6146     return focusHub;
6147 }
6148 
6149 void TextFieldPattern::UpdateRecordCaretIndex(int32_t index)
6150 {
6151     if (lockRecord_ || operationRecords_.empty()) {
6152         return;
6153     }
6154     operationRecords_.back().caretPosition = index;
6155 }
6156 
6157 void TextFieldPattern::OnObscuredChanged(bool isObscured)
6158 {
6159     ResetObscureTickCountDown();
6160     obscuredChange_ = textObscured_ != isObscured;
6161     textObscured_ = isObscured;
6162     CloseSelectOverlay(false);
6163     selectController_->UpdateCaretIndex(static_cast<int32_t>(contentController_->GetWideText().length()));
6164     auto host = GetHost();
6165     CHECK_NULL_VOID(host);
6166     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
6167 }
6168 
6169 void TextFieldPattern::CreateHandles()
6170 {
6171     if (IsDragging()) {
6172         return;
6173     }
6174     auto host = GetHost();
6175     CHECK_NULL_VOID(host);
6176     showSelect_ = true;
6177     ProcessOverlay(true, false, false);
6178     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6179 }
6180 
6181 void TextFieldPattern::NotifyOnEditChanged(bool isChanged)
6182 {
6183     auto host = GetHost();
6184     CHECK_NULL_VOID(host);
6185     auto eventHub = host->GetEventHub<TextFieldEventHub>();
6186     CHECK_NULL_VOID(eventHub);
6187     eventHub->FireOnEditChanged(isChanged);
6188 }
6189 
6190 int32_t TextFieldPattern::GetLineCount() const
6191 {
6192     return paragraph_ ? paragraph_->GetLineCount() : 0;
6193 }
6194 
6195 void TextFieldPattern::UpdateHandlesOffsetOnScroll(float offset)
6196 {
6197     if (SelectOverlayIsOn()) {
6198         selectController_->UpdateSecondHandleOffset();
6199         if (!IsSingleHandle()) {
6200             selectController_->UpdateFirstHandleOffset();
6201             selectController_->UpdateCaretOffset();
6202             UpdateSelectOverlayDoubleHandle();
6203         } else {
6204             auto carectOffset = selectController_->GetCaretRect().GetOffset() +
6205                                 (IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
6206             selectController_->UpdateCaretOffset(carectOffset);
6207             UpdateSelectOverlaySecondHandle();
6208         }
6209         UpdateOverlaySelectArea();
6210     } else {
6211         auto caretOffset = selectController_->GetCaretRect().GetOffset() +
6212                            (IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
6213         selectController_->UpdateCaretOffset(caretOffset);
6214     }
6215 }
6216 
6217 void TextFieldPattern::CloseHandleAndSelect()
6218 {
6219     CloseSelectOverlay(true);
6220     showSelect_ = false;
6221 }
6222 
6223 bool TextFieldPattern::IsShowUnit() const
6224 {
6225     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6226     CHECK_NULL_RETURN(layoutProperty, false);
6227     return layoutProperty->GetShowUnderlineValue(false) &&
6228            layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::UNSPECIFIED;
6229 }
6230 
6231 bool TextFieldPattern::IsShowPasswordIcon() const
6232 {
6233     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6234     CHECK_NULL_RETURN(layoutProperty, false);
6235     return layoutProperty->GetShowPasswordIconValue(true) && IsInPasswordMode();
6236 }
6237 
6238 bool TextFieldPattern::IsShowCancelButtonMode() const
6239 {
6240     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6241     CHECK_NULL_RETURN(layoutProperty, false);
6242     return !IsNormalInlineState() && !IsTextArea() && layoutProperty->GetIsShowCancelButton().value_or(false);
6243 }
6244 
6245 void TextFieldPattern::ProcessResponseArea()
6246 {
6247     if (IsShowCancelButtonMode()) {
6248         auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
6249         if (cleanNodeResponseArea) {
6250             cleanNodeResponseArea->Refresh();
6251             cleanNodeResponseArea->UpdateCleanNode(cleanNodeResponseArea->IsShow());
6252         } else {
6253             cleanNodeResponseArea_ = AceType::MakeRefPtr<CleanNodeResponseArea>(WeakClaim(this));
6254             cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
6255             cleanNodeResponseArea->InitResponseArea();
6256             UpdateCancelNode();
6257         }
6258     } else {
6259         if (cleanNodeResponseArea_) {
6260             cleanNodeResponseArea_->ClearArea();
6261             cleanNodeResponseArea_.Reset();
6262         }
6263     }
6264 
6265     if (IsShowPasswordIcon()) {
6266         auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
6267         if (passwordArea) {
6268             passwordArea->Refresh();
6269             return;
6270         }
6271         responseArea_ = AceType::MakeRefPtr<PasswordResponseArea>(WeakClaim(this), GetTextObscured());
6272         responseArea_->InitResponseArea();
6273         return;
6274     }
6275 
6276     if (IsShowUnit()) {
6277         responseArea_ = AceType::MakeRefPtr<UnitResponseArea>(WeakClaim(this), unitNode_);
6278         responseArea_->InitResponseArea();
6279         return;
6280     }
6281 
6282     if (responseArea_) {
6283         responseArea_->ClearArea();
6284     }
6285 }
6286 
6287 void TextFieldPattern::UpdateCancelNode()
6288 {
6289     auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
6290     CHECK_NULL_VOID(cleanNodeResponseArea);
6291     auto host = GetHost();
6292     CHECK_NULL_VOID(host);
6293     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
6294     CHECK_NULL_VOID(layoutProperty);
6295     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
6296     if (cleanNodeStyle == CleanNodeStyle::CONSTANT ||
6297         (cleanNodeStyle == CleanNodeStyle::INPUT && !contentController_->IsEmpty())) {
6298         if (!cleanNodeResponseArea->IsShow()) {
6299             cleanNodeResponseArea->UpdateCleanNode(true);
6300         }
6301     } else if (cleanNodeStyle == CleanNodeStyle::INVISIBLE ||
6302                (cleanNodeStyle == CleanNodeStyle::INPUT && contentController_->IsEmpty())) {
6303         if (cleanNodeResponseArea->IsShow()) {
6304             cleanNodeResponseArea->UpdateCleanNode(false);
6305         }
6306     }
6307 }
6308 
6309 bool TextFieldPattern::HasInputOperation()
6310 {
6311     return !deleteBackwardOperations_.empty() || !deleteForwardOperations_.empty() || !insertValueOperations_.empty();
6312 }
6313 
6314 bool TextFieldPattern::UpdateFocusForward()
6315 {
6316     if (focusIndex_ == FocuseIndex::TEXT && HasFocus()) {
6317         if (!CancelNodeIsShow() && responseArea_ == nullptr) {
6318             return false;
6319         }
6320         if (!CancelNodeIsShow()) {
6321             focusIndex_ = FocuseIndex::UNIT;
6322             PaintResponseAreaRect();
6323             return true;
6324         }
6325         focusIndex_ = FocuseIndex::CANCEL;
6326         PaintCancelRect();
6327         return true;
6328     } else if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
6329         if (responseArea_ == nullptr) {
6330             return false;
6331         }
6332         focusIndex_ = FocuseIndex::UNIT;
6333         PaintResponseAreaRect();
6334         return true;
6335     }
6336     return false;
6337 }
6338 
6339 bool TextFieldPattern::UpdateFocusBackward()
6340 {
6341     if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
6342         focusIndex_ = FocuseIndex::TEXT;
6343         PaintTextRect();
6344         return true;
6345     } else if (focusIndex_ == FocuseIndex::UNIT && HasFocus()) {
6346         if (!CancelNodeIsShow()) {
6347             focusIndex_ = FocuseIndex::TEXT;
6348             PaintTextRect();
6349             return true;
6350         }
6351         focusIndex_ = FocuseIndex::CANCEL;
6352         PaintCancelRect();
6353         return true;
6354     }
6355     return false;
6356 }
6357 
6358 bool TextFieldPattern::HandleSpaceEvent()
6359 {
6360     if (focusIndex_ == FocuseIndex::CANCEL) {
6361         CleanNodeResponseKeyEvent();
6362         return true;
6363     } else if (focusIndex_ == FocuseIndex::UNIT) {
6364         if (IsShowPasswordIcon()) {
6365             PasswordResponseKeyEvent();
6366         }
6367         if (IsShowUnit()) {
6368             UnitResponseKeyEvent();
6369         }
6370         return true;
6371     }
6372     return false;
6373 }
6374 
6375 void TextFieldPattern::PaintTextRect()
6376 {
6377     RoundRect focusRect;
6378     auto host = GetHost();
6379     CHECK_NULL_VOID(host);
6380     auto focusHub = host->GetFocusHub();
6381     CHECK_NULL_VOID(focusHub);
6382     focusHub->PaintInnerFocusState(focusRect);
6383 }
6384 
6385 void TextFieldPattern::GetIconPaintRect(const RefPtr<TextInputResponseArea>& responseArea, RoundRect& paintRect)
6386 {
6387     auto stackNode = responseArea->GetFrameNode();
6388     CHECK_NULL_VOID(stackNode);
6389     auto stackRect = stackNode->GetGeometryNode()->GetFrameRect();
6390     auto imageNode = stackNode->GetFirstChild();
6391     CHECK_NULL_VOID(imageNode);
6392     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
6393     CHECK_NULL_VOID(imageFrameNode);
6394     auto imageRect = imageFrameNode->GetGeometryNode()->GetFrameRect();
6395     RectF rect(stackRect.GetX(), imageRect.GetY(), imageRect.Width(), imageRect.Height());
6396     paintRect.SetRect(rect);
6397 }
6398 
6399 void TextFieldPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
6400 {
6401     if (focusIndex_ == FocuseIndex::CANCEL) {
6402         CHECK_NULL_VOID(cleanNodeResponseArea_);
6403         GetIconPaintRect(cleanNodeResponseArea_, paintRect);
6404     } else if (focusIndex_ == FocuseIndex::UNIT) {
6405         if (IsShowPasswordIcon()) {
6406             CHECK_NULL_VOID(responseArea_);
6407             GetIconPaintRect(responseArea_, paintRect);
6408         }
6409         if (IsShowUnit()) {
6410             CHECK_NULL_VOID(responseArea_);
6411             auto unitResponseArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
6412             CHECK_NULL_VOID(unitResponseArea);
6413             auto unitNode = unitResponseArea->GetFrameNode();
6414             CHECK_NULL_VOID(unitNode);
6415             auto unitRect = unitNode->GetGeometryNode()->GetFrameRect();
6416             paintRect.SetRect(unitRect);
6417         }
6418     }
6419 }
6420 
6421 void TextFieldPattern::PaintCancelRect()
6422 {
6423     RoundRect focusRect;
6424     GetInnerFocusPaintRect(focusRect);
6425     auto host = GetHost();
6426     CHECK_NULL_VOID(host);
6427     auto focusHub = host->GetFocusHub();
6428     CHECK_NULL_VOID(focusHub);
6429     focusHub->PaintInnerFocusState(focusRect);
6430 }
6431 
6432 void TextFieldPattern::PaintResponseAreaRect()
6433 {
6434     if (IsShowPasswordIcon()) {
6435         PaintPasswordRect();
6436     }
6437     if (IsShowUnit()) {
6438         PaintUnitRect();
6439     }
6440 }
6441 
6442 void TextFieldPattern::PaintPasswordRect()
6443 {
6444     RoundRect focusRect;
6445     GetInnerFocusPaintRect(focusRect);
6446     auto host = GetHost();
6447     CHECK_NULL_VOID(host);
6448     auto focusHub = host->GetFocusHub();
6449     CHECK_NULL_VOID(focusHub);
6450     focusHub->PaintInnerFocusState(focusRect);
6451 }
6452 
6453 void TextFieldPattern::PaintUnitRect()
6454 {
6455     RoundRect focusRect;
6456     GetInnerFocusPaintRect(focusRect);
6457     auto host = GetHost();
6458     CHECK_NULL_VOID(host);
6459     auto focusHub = host->GetFocusHub();
6460     CHECK_NULL_VOID(focusHub);
6461     focusHub->PaintInnerFocusState(focusRect);
6462 }
6463 
6464 void TextFieldPattern::CleanNodeResponseKeyEvent()
6465 {
6466     CHECK_NULL_VOID(!IsDragging());
6467     auto host = GetHost();
6468     CHECK_NULL_VOID(host);
6469     InitEditingValueText("");
6470     CloseSelectOverlay();
6471     StartTwinkling();
6472     if (!HasFocus()) {
6473         auto focusHub = host->GetOrCreateFocusHub();
6474         focusHub->RequestFocusImmediately();
6475     }
6476     host->MarkModifyDone();
6477     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6478 }
6479 
6480 void TextFieldPattern::OnVirtualKeyboardAreaChanged()
6481 {
6482     CHECK_NULL_VOID(SelectOverlayIsOn());
6483     selectController_->CalculateHandleOffset();
6484     ProcessOverlay(false);
6485 }
6486 
6487 void TextFieldPattern::PasswordResponseKeyEvent()
6488 {
6489     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
6490     CHECK_NULL_VOID(passwordArea);
6491     passwordArea->OnPasswordIconClicked();
6492 }
6493 
6494 void TextFieldPattern::UnitResponseKeyEvent()
6495 {
6496     auto unitArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
6497     CHECK_NULL_VOID(unitArea);
6498     auto frameNode = unitArea->GetFrameNode();
6499     if (frameNode->GetTag() == V2::SELECT_ETS_TAG) {
6500         auto selectPattern = frameNode->GetPattern<SelectPattern>();
6501         CHECK_NULL_VOID(selectPattern);
6502         selectPattern->ShowSelectMenu();
6503     }
6504 }
6505 
6506 void TextFieldPattern::ScrollToSafeArea() const
6507 {
6508     auto pipeline = PipelineContext::GetCurrentContext();
6509     CHECK_NULL_VOID(pipeline);
6510     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
6511     CHECK_NULL_VOID(textFieldManager);
6512     textFieldManager->ScrollTextFieldToSafeArea();
6513 }
6514 
6515 RefPtr<PixelMap> TextFieldPattern::GetPixelMap()
6516 {
6517     auto pipeline = PipelineContext::GetCurrentContext();
6518     CHECK_NULL_RETURN(pipeline, NULL);
6519     auto overlayManager = pipeline->GetOverlayManager();
6520     CHECK_NULL_RETURN(overlayManager, NULL);
6521     auto rootUINode = overlayManager->GetRootNode().Upgrade();
6522     CHECK_NULL_RETURN(rootUINode, NULL);
6523     auto rootFrameNode = DynamicCast<FrameNode>(rootUINode);
6524     CHECK_NULL_RETURN(rootFrameNode, NULL);
6525 
6526     auto context = rootFrameNode->GetRenderContext();
6527     if (!context) {
6528         UpdateShowMagnifier();
6529     }
6530     CHECK_NULL_RETURN(context, NULL);
6531     auto pixelMap = context->GetThumbnailPixelMap();
6532     if (!pixelMap) {
6533         UpdateShowMagnifier();
6534     }
6535     CHECK_NULL_RETURN(pixelMap, NULL);
6536     return pixelMap;
6537 }
6538 
6539 void TextFieldPattern::ShowMenu()
6540 {
6541     auto selectOverlayProxy = GetSelectOverlayProxy();
6542     if (selectOverlayProxy && selectOverlayProxy->IsMenuShow()) {
6543         return;
6544     }
6545     CloseSelectOverlay(true);
6546     if (IsSingleHandle()) {
6547         SetIsSingleHandle(true);
6548     } else {
6549         SetIsSingleHandle(false);
6550     }
6551     ProcessOverlay(true, true, true);
6552 }
6553 
6554 void TextFieldPattern::HandleCursorOnDragMoved(const RefPtr<NotifyDragEvent>& notifyDragEvent)
6555 {
6556     if (IsNormalInlineState()) {
6557         return;
6558     }
6559     auto host = GetHost();
6560     CHECK_NULL_VOID(host);
6561     if (isCursorAlwaysDisplayed_) {
6562         if (SystemProperties::GetDebugEnabled()) {
6563             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
6564                 "In OnDragMoved, the cursor has always Displayed in the textField, id:%{public}d", host->GetId());
6565         }
6566         return;
6567     }
6568     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "In OnDragMoved, the dragging node is moving in the textField, id:%{public}d",
6569         host->GetId());
6570     auto focusHub = GetFocusHub();
6571     CHECK_NULL_VOID(focusHub);
6572     focusHub->RequestFocusImmediately();
6573     if (focusHub->IsCurrentFocus()) {
6574         isCursorAlwaysDisplayed_ = true;
6575         StartTwinkling();
6576     }
6577 };
6578 
6579 void TextFieldPattern::HandleCursorOnDragLeaved(const RefPtr<NotifyDragEvent>& notifyDragEvent)
6580 {
6581     auto host = GetHost();
6582     CHECK_NULL_VOID(host);
6583     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "In OnDragLeaved, the dragging node has left from the textField, id:%{public}d",
6584         host->GetId());
6585     auto focusHub = GetFocusHub();
6586     CHECK_NULL_VOID(focusHub);
6587     focusHub->LostFocus();
6588     isCursorAlwaysDisplayed_ = false;
6589     StopTwinkling();
6590 };
6591 
6592 void TextFieldPattern::HandleCursorOnDragEnded(const RefPtr<NotifyDragEvent>& notifyDragEvent)
6593 {
6594     if (IsNormalInlineState()) {
6595         return;
6596     }
6597     auto host = GetHost();
6598     CHECK_NULL_VOID(host);
6599     auto focusHub = GetFocusHub();
6600     CHECK_NULL_VOID(focusHub);
6601     if (!isCursorAlwaysDisplayed_) {
6602         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
6603             "In OnDragEnded,"
6604             " the released location is not in the current textField, id:%{public}d",
6605             host->GetId());
6606         focusHub->LostFocus();
6607         StopTwinkling();
6608         return;
6609     }
6610     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
6611         "In OnDragEnded, the released location is in the current TextField, id:%{public}d", host->GetId());
6612     focusHub->RequestFocusImmediately();
6613     isCursorAlwaysDisplayed_ = false;
6614     StartTwinkling();
6615 };
6616 
6617 void TextFieldPattern::HandleOnDragStatusCallback(
6618     const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent)
6619 {
6620     ScrollablePattern::HandleOnDragStatusCallback(dragEventType, notifyDragEvent);
6621     switch (dragEventType) {
6622         case DragEventType::MOVE:
6623             HandleCursorOnDragMoved(notifyDragEvent);
6624             break;
6625         case DragEventType::LEAVE:
6626             HandleCursorOnDragLeaved(notifyDragEvent);
6627             break;
6628         case DragEventType::DROP:
6629             HandleCursorOnDragEnded(notifyDragEvent);
6630             break;
6631         default:
6632             break;
6633     }
6634 }
6635 
6636 void TextFieldPattern::CheckTextAlignByDirection(TextAlign& textAlign, TextDirection direction)
6637 {
6638     if (direction == TextDirection::RTL) {
6639         if (textAlign == TextAlign::START) {
6640             textAlign = TextAlign::END;
6641         } else if (textAlign == TextAlign::END) {
6642             textAlign = TextAlign::START;
6643         }
6644     }
6645 }
6646 
6647 void TextFieldPattern::RequestKeyboardAfterLongPress()
6648 {
6649 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
6650     if (isLongPress_ && HasFocus() && RequestKeyboard(false, true, true)) {
6651         NotifyOnEditChanged(true);
6652     }
6653     isLongPress_ = false;
6654 #endif
6655 }
6656 
6657 void TextFieldPattern::GetCaretMetrics(CaretMetricsF& caretCaretMetric)
6658 {
6659     OffsetF offset = selectController_->GetCaretRect().GetOffset();
6660     float height = selectController_->GetCaretRect().Height();
6661     float width = selectController_->GetCaretRect().Width();
6662     auto host = GetHost();
6663     CHECK_NULL_VOID(host);
6664     auto textPaintOffset = host->GetPaintRectOffset();
6665     caretCaretMetric.offset = offset + textPaintOffset + OffsetF(width / 2.0f, 0.0f);
6666     caretCaretMetric.height = height;
6667 }
6668 
6669 void TextFieldPattern::UpdatePasswordModeState()
6670 {
6671     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6672     CHECK_NULL_VOID(paintProperty);
6673     auto textfieldTheme = GetTheme();
6674     CHECK_NULL_VOID(textfieldTheme);
6675     if (paintProperty->HasBackgroundColor()) {
6676         passwordModeStyle_.bgColor = paintProperty->GetBackgroundColorValue();
6677     } else {
6678         passwordModeStyle_.bgColor = textfieldTheme->GetBgColor();
6679     }
6680     if (!paintProperty->GetTextColorFlagByUserValue(false)) {
6681         passwordModeStyle_.textColor = textfieldTheme->GetTextColor();
6682     } else {
6683         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6684         CHECK_NULL_VOID(layoutProperty);
6685         passwordModeStyle_.textColor = layoutProperty->GetTextColorValue(textfieldTheme->GetTextColor());
6686     }
6687 }
6688 
6689 RectF TextFieldPattern::GetSelectArea()
6690 {
6691     auto selectRects = selectController_->GetSelectedRects();
6692     RectF res(selectController_->GetCaretRect());
6693     if (selectRects.empty()) {
6694         res.SetOffset(res.GetOffset() + GetTextPaintOffset());
6695         return res;
6696     }
6697     auto frontRect = selectRects.front();
6698     auto backRect = selectRects.back();
6699     if (GreatNotEqual(backRect.Bottom(), frontRect.Bottom())) {
6700         res.SetRect(contentRect_.GetX() + GetTextPaintOffset().GetX(),
6701             frontRect.GetY() + textRect_.GetY() + GetTextPaintOffset().GetY(), contentRect_.Width(),
6702             backRect.Bottom() - frontRect.Top());
6703     } else {
6704         res.SetRect(frontRect.GetX() + textRect_.GetX() + GetTextPaintOffset().GetX(),
6705             frontRect.GetY() + textRect_.GetY() + GetTextPaintOffset().GetY(), backRect.Right() - frontRect.Left(),
6706             backRect.Bottom() - frontRect.Top());
6707     }
6708     auto contentRect = contentRect_;
6709     contentRect.SetOffset(contentRect.GetOffset() + GetTextPaintOffset());
6710     auto host = GetHost();
6711     CHECK_NULL_RETURN(host, RectF(0, 0, 0, 0));
6712     auto parent = host->GetAncestorNodeOfFrame();
6713     contentRect = GetVisibleContentRect(parent, contentRect);
6714     return res.IntersectRectT(contentRect);
6715 }
6716 
6717 void TextFieldPattern::UpdateOverlaySelectArea()
6718 {
6719     auto proxy = GetSelectOverlayProxy();
6720     CHECK_NULL_VOID(proxy);
6721     proxy->UpdateSelectArea(GetSelectArea());
6722 }
6723 } // namespace OHOS::Ace::NG
6724