• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 <atomic>
20 #include <cstdint>
21 #include <optional>
22 #include <ratio>
23 #include <regex>
24 #include <string>
25 #include <utility>
26 #include "base/geometry/dimension.h"
27 #include "core/common/ime/constant.h"
28 #include "core/components/common/properties/text_style.h"
29 #include "core/components_ng/pattern/text/text_layout_property.h"
30 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
31 #include "core/components_ng/property/layout_constraint.h"
32 #include "core/pipeline/pipeline_base.h"
33 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
34 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
35 #endif
36 #include "base/geometry/dimension.h"
37 #include "base/geometry/ng/offset_t.h"
38 #include "base/geometry/ng/rect_t.h"
39 #include "base/geometry/offset.h"
40 #include "base/i18n/localization.h"
41 #include "base/log/dump_log.h"
42 #include "base/log/log_wrapper.h"
43 #include "base/memory/referenced.h"
44 #include "base/utils/string_utils.h"
45 #include "base/utils/utils.h"
46 #include "core/common/clipboard/clipboard_proxy.h"
47 #include "core/common/container_scope.h"
48 #include "core/common/font_manager.h"
49 #include "core/common/ime/text_edit_controller.h"
50 #include "core/common/ime/text_input_client.h"
51 #include "core/common/ime/text_input_connection.h"
52 #include "core/common/ime/text_input_formatter.h"
53 #include "core/common/ime/text_input_type.h"
54 #include "core/common/ime/text_selection.h"
55 #include "core/common/recorder/node_data_cache.h"
56 #include "core/common/stylus/stylus_detector_mgr.h"
57 #include "core/common/vibrator/vibrator_utils.h"
58 #include "core/components/common/layout/constants.h"
59 #include "core/components/text_field/textfield_theme.h"
60 #include "core/components/theme/icon_theme.h"
61 #include "core/components_ng/base/inspector_filter.h"
62 #include "core/components_ng/event/focus_hub.h"
63 #include "core/components_ng/image_provider/image_loading_context.h"
64 #include "core/components_ng/layout/layout_property.h"
65 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
66 #include "core/components_ng/pattern/overlay/modal_style.h"
67 #include "core/components_ng/pattern/stage/page_pattern.h"
68 #include "core/components_ng/pattern/search/search_event_hub.h"
69 #include "core/components_ng/pattern/search/search_pattern.h"
70 #include "core/components_ng/pattern/stage/page_pattern.h"
71 #include "core/components_ng/pattern/text/span/span_string.h"
72 #include "core/components_ng/pattern/text/text_base.h"
73 #include "core/components_ng/pattern/text/text_pattern.h"
74 #include "core/components_ng/pattern/text/text_styles.h"
75 #include "core/components_ng/pattern/text_drag/text_drag_pattern.h"
76 #include "core/components_ng/pattern/text_field/text_content_type.h"
77 #include "core/components_ng/pattern/text_field/text_field_controller.h"
78 #include "core/components_ng/pattern/text_field/text_field_event_hub.h"
79 #include "core/components_ng/pattern/text_field/text_field_layout_algorithm.h"
80 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
81 #include "core/components_ng/pattern/text_field/text_field_manager.h"
82 #include "core/components_ng/pattern/text_field/text_field_model.h"
83 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
84 #include "core/components_ng/pattern/text_field/text_field_paint_property.h"
85 #include "core/components_ng/pattern/text_field/text_field_select_overlay.h"
86 #include "core/components_ng/pattern/text_field/text_selector.h"
87 #include "core/components_ng/property/border_property.h"
88 #include "core/components_ng/property/calc_length.h"
89 #include "core/components_ng/property/measure_property.h"
90 #include "core/components_ng/property/property.h"
91 #include "core/components_ng/render/drawing.h"
92 #include "core/components_ng/render/drawing_prop_convertor.h"
93 #include "core/components_ng/render/paint_property.h"
94 #include "core/components_ng/render/paragraph.h"
95 #include "core/components_v2/inspector/inspector_constants.h"
96 #include "core/components_v2/inspector/utils.h"
97 #include "core/event/ace_events.h"
98 #include "core/image/image_source_info.h"
99 #include "core/pipeline/pipeline_base.h"
100 #include "core/pipeline_ng/pipeline_context.h"
101 #include "core/text/text_emoji_processor.h"
102 #ifndef ACE_UNITTEST
103 #ifdef ENABLE_STANDARD_INPUT
104 #include "parameters.h"
105 
106 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
107 #endif
108 #endif
109 #include "core/common/udmf/udmf_client.h"
110 #ifdef WINDOW_SCENE_SUPPORTED
111 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
112 #endif
113 
114 namespace OHOS::Ace::NG {
115 namespace {
116 
117 const BorderRadiusProperty ZERO_BORDER_RADIUS_PROPERTY(0.0_vp);
118 // need to be moved to TextFieldTheme
119 constexpr Dimension BORDER_DEFAULT_WIDTH = 0.0_vp;
120 constexpr Dimension TYPING_UNDERLINE_WIDTH = 2.0_px;
121 constexpr Dimension ERROR_BORDER_WIDTH = 1.0_vp;
122 constexpr Dimension OVER_COUNT_BORDER_WIDTH = 1.0_vp;
123 constexpr Dimension INLINE_BORDER_WIDTH = 2.0_vp;
124 constexpr Dimension ERROR_UNDERLINE_WIDTH = 2.0_px;
125 constexpr Dimension UNDERLINE_WIDTH = 1.0_px;
126 constexpr uint32_t INLINE_DEFAULT_VIEW_MAXLINE = 3;
127 constexpr Dimension SCROLL_BAR_MIN_HEIGHT = 4.0_vp;
128 #if defined(ENABLE_STANDARD_INPUT)
129 constexpr Dimension AVOID_OFFSET = 24.0_vp;
130 #endif
131 constexpr Dimension DEFAULT_FONT = Dimension(16, DimensionUnit::FP);
132 constexpr int32_t ILLEGAL_VALUE = 0;
133 constexpr float ERROR_TEXT_MAX_FONT_SCALE = 2.0f;
134 constexpr double VELOCITY = -1000;
135 constexpr double MASS = 1.0;
136 constexpr double STIFFNESS = 428.0;
137 constexpr double DAMPING = 10.0;
138 constexpr uint32_t TWINKLING_INTERVAL_MS = 500;
139 constexpr uint32_t RECORD_MAX_LENGTH = 20;
140 constexpr uint32_t OBSCURE_SHOW_TICKS = 1;
141 constexpr Dimension ERROR_TEXT_TOP_MARGIN = 8.0_vp;
142 constexpr Dimension ERROR_TEXT_BOTTOM_MARGIN = 8.0_vp;
143 constexpr Dimension COUNTER_TEXT_TOP_MARGIN = 8.0_vp;
144 constexpr Dimension COUNTER_TEXT_BOTTOM_MARGIN = 8.0_vp;
145 constexpr Dimension STANDARD_COUNTER_TEXT_MARGIN = 22.0_vp;
146 constexpr uint32_t COUNTER_TEXT_MAXLINE = 1;
147 constexpr uint32_t ERROR_TEXT_MAXLINE = 1;
148 constexpr int32_t FIND_TEXT_ZERO_INDEX = 1;
149 constexpr char16_t OBSCURING_CHARACTER = u'•';
150 constexpr char16_t OBSCURING_CHARACTER_FOR_AR = u'*';
151 const std::string NEWLINE = "\n";
152 const std::wstring WIDE_NEWLINE = StringUtils::ToWstring(NEWLINE);
153 const std::string INSPECTOR_PREFIX = "__SearchField__";
154 const std::string ERRORNODE_PREFIX = "ErrorNodeField__";
155 const OffsetF DEFAULT_NEGATIVE_CARET_OFFSET { -1.0f, -1.0f };
156 #if defined(ENABLE_STANDARD_INPUT)
157 constexpr int32_t AUTO_FILL_CANCEL = 2;
158 #endif
159 
160 // need to be moved to formatter
161 const std::string DIGIT_WHITE_LIST = "[0-9]";
162 const std::string PHONE_WHITE_LIST = "[\\d\\-\\+\\*\\#]+";
163 const std::string EMAIL_WHITE_LIST = "[\\w.\\@]";
164 const std::string URL_WHITE_LIST = "[a-zA-z]+://[^\\s]*";
165 const std::string SHOW_PASSWORD_SVG = "SYS_SHOW_PASSWORD_SVG";
166 const std::string HIDE_PASSWORD_SVG = "SYS_HIDE_PASSWORD_SVG";
167 const std::string AUTO_FILL_PARAMS_USERNAME = "com.autofill.params.userName";
168 const std::string AUTO_FILL_PARAMS_NEWPASSWORD = "com.autofill.params.newPassword";
169 constexpr int32_t DEFAULT_MODE = -1;
170 constexpr int32_t PREVIEW_TEXT_RANGE_DEFAULT = -1;
171 const std::string PREVIEW_STYLE_NORMAL = "normal";
172 const std::string PREVIEW_STYLE_UNDERLINE = "underline";
173 
174 constexpr int32_t PREVIEW_NO_ERROR = 0;
175 constexpr int32_t PREVIEW_NULL_POINTER = 1;
176 constexpr int32_t PREVIEW_BAD_PARAMETERS = -1;
177 constexpr double MINIMAL_OFFSET = 0.01f;
178 constexpr int32_t KEYBOARD_DEFAULT_API = 9;
179 constexpr float RICH_DEFAULT_SHADOW_COLOR = 0x33000000;
180 constexpr float RICH_DEFAULT_ELEVATION = 120.0f;
181 
182 static std::unordered_map<AceAutoFillType, TextInputType> keyBoardMap_ = {
183     { AceAutoFillType::ACE_PASSWORD, TextInputType::VISIBLE_PASSWORD},
184     { AceAutoFillType::ACE_USER_NAME, TextInputType::USER_NAME },
185     { AceAutoFillType::ACE_NEW_PASSWORD, TextInputType::NEW_PASSWORD },
186     { AceAutoFillType::ACE_FULL_STREET_ADDRESS, TextInputType::TEXT },
187     { AceAutoFillType::ACE_HOUSE_NUMBER, TextInputType::TEXT },
188     { AceAutoFillType::ACE_DISTRICT_ADDRESS, TextInputType::TEXT },
189     { AceAutoFillType::ACE_CITY_ADDRESS, TextInputType::TEXT },
190     { AceAutoFillType::ACE_PROVINCE_ADDRESS, TextInputType::TEXT },
191     { AceAutoFillType::ACE_COUNTRY_ADDRESS, TextInputType::TEXT },
192     { AceAutoFillType::ACE_PERSON_FULL_NAME, TextInputType::TEXT },
193     { AceAutoFillType::ACE_PERSON_LAST_NAME, TextInputType::TEXT },
194     { AceAutoFillType::ACE_PERSON_FIRST_NAME, TextInputType::TEXT },
195     { AceAutoFillType::ACE_PHONE_NUMBER, TextInputType::PHONE },
196     { AceAutoFillType::ACE_PHONE_COUNTRY_CODE, TextInputType::PHONE },
197     { AceAutoFillType::ACE_FULL_PHONE_NUMBER, TextInputType::PHONE },
198     { AceAutoFillType::ACE_EMAIL_ADDRESS, TextInputType::EMAIL_ADDRESS },
199     { AceAutoFillType::ACE_BANK_CARD_NUMBER, TextInputType::NUMBER },
200     { AceAutoFillType::ACE_ID_CARD_NUMBER, TextInputType::NUMBER },
201     { AceAutoFillType::ACE_PRECISE_TIME, TextInputType::NUMBER },
202     { AceAutoFillType::ACE_HOUR_AND_MINUTE, TextInputType::NUMBER },
203     { AceAutoFillType::ACE_DATE, TextInputType::NUMBER },
204     { AceAutoFillType::ACE_MONTH, TextInputType::NUMBER },
205     { AceAutoFillType::ACE_YEAR, TextInputType::NUMBER },
206     { AceAutoFillType::ACE_NICKNAME, TextInputType::TEXT },
207     { AceAutoFillType::ACE_DETAIL_INFO_WITHOUT_STREET, TextInputType::TEXT },
208     { AceAutoFillType::ACE_FORMAT_ADDRESS, TextInputType::TEXT }};
209 
210 static std::unordered_map<TextContentType, std::pair<AceAutoFillType, std::string>> contentTypeMap_ = {
211     {TextContentType::VISIBLE_PASSWORD,
212         std::make_pair(AceAutoFillType::ACE_PASSWORD, "TextContentType.VISIBLE_PASSWORD")},
213     {TextContentType::USER_NAME, std::make_pair(AceAutoFillType::ACE_USER_NAME, "TextContentType.USER_NAME")},
214     {TextContentType::NEW_PASSWORD, std::make_pair(AceAutoFillType::ACE_NEW_PASSWORD, "TextContentType.NEW_PASSWORD")},
215     {TextContentType::FULL_STREET_ADDRESS,
216         std::make_pair(AceAutoFillType::ACE_FULL_STREET_ADDRESS, "TextContentType.FULL_STREET_ADDRESS")},
217     {TextContentType::HOUSE_NUMBER, std::make_pair(AceAutoFillType::ACE_HOUSE_NUMBER, "TextContentType.HOUSE_NUMBER")},
218     {TextContentType::DISTRICT_ADDRESS,
219         std::make_pair(AceAutoFillType::ACE_DISTRICT_ADDRESS, "TextContentType.DISTRICT_ADDRESS")},
220     {TextContentType::CITY_ADDRESS, std::make_pair(AceAutoFillType::ACE_CITY_ADDRESS, "TextContentType.CITY_ADDRESS")},
221     {TextContentType::PROVINCE_ADDRESS,
222         std::make_pair(AceAutoFillType::ACE_PROVINCE_ADDRESS, "TextContentType.PROVINCE_ADDRESS")},
223     {TextContentType::COUNTRY_ADDRESS,
224         std::make_pair(AceAutoFillType::ACE_COUNTRY_ADDRESS, "TextContentType.COUNTRY_ADDRESS")},
225     {TextContentType::PERSON_FULL_NAME,
226         std::make_pair(AceAutoFillType::ACE_PERSON_FULL_NAME, "TextContentType.PERSON_FULL_NAME")},
227     {TextContentType::PERSON_LAST_NAME,
228         std::make_pair(AceAutoFillType::ACE_PERSON_LAST_NAME, "TextContentType.PERSON_LAST_NAME")},
229     {TextContentType::PERSON_FIRST_NAME,
230         std::make_pair(AceAutoFillType::ACE_PERSON_FIRST_NAME, "TextContentType.PERSON_FIRST_NAME")},
231     {TextContentType::PHONE_NUMBER, std::make_pair(AceAutoFillType::ACE_PHONE_NUMBER, "TextContentType.PHONE_NUMBER")},
232     {TextContentType::PHONE_COUNTRY_CODE,
233         std::make_pair(AceAutoFillType::ACE_PHONE_COUNTRY_CODE, "TextContentType.PHONE_COUNTRY_CODE")},
234     {TextContentType::FULL_PHONE_NUMBER,
235         std::make_pair(AceAutoFillType::ACE_FULL_PHONE_NUMBER, "TextContentType.FULL_PHONE_NUMBER")},
236     {TextContentType::EMAIL_ADDRESS,
237         std::make_pair(AceAutoFillType::ACE_EMAIL_ADDRESS, "TextContentType.EMAIL_ADDRESS")},
238     {TextContentType::BANK_CARD_NUMBER,
239         std::make_pair(AceAutoFillType::ACE_BANK_CARD_NUMBER, "TextContentType.BANK_CARD_NUMBER")},
240     {TextContentType::ID_CARD_NUMBER,
241         std::make_pair(AceAutoFillType::ACE_ID_CARD_NUMBER, "TextContentType.ID_CARD_NUMBER")},
242     {TextContentType::PRECISE_TIME, std::make_pair(AceAutoFillType::ACE_PRECISE_TIME, "TextContentType.PRECISE_TIME")},
243     {TextContentType::HOUR_AND_MINUTE,
244         std::make_pair(AceAutoFillType::ACE_HOUR_AND_MINUTE, "TextContentType.HOUR_AND_MINUTE")},
245     {TextContentType::DATE, std::make_pair(AceAutoFillType::ACE_DATE, "TextContentType.DATE")},
246     {TextContentType::MONTH, std::make_pair(AceAutoFillType::ACE_MONTH, "TextContentType.MONTH")},
247     {TextContentType::YEAR, std::make_pair(AceAutoFillType::ACE_YEAR, "TextContentType.YEAR")},
248     {TextContentType::NICKNAME, std::make_pair(AceAutoFillType::ACE_NICKNAME, "TextContentType.NICKNAME")},
249     {TextContentType::DETAIL_INFO_WITHOUT_STREET,
250         std::make_pair(AceAutoFillType::ACE_DETAIL_INFO_WITHOUT_STREET, "TextContentType.DETAIL_INFO_WITHOUT_STREET")},
251     {TextContentType::FORMAT_ADDRESS,
252         std::make_pair(AceAutoFillType::ACE_FORMAT_ADDRESS, "TextContentType.FORMAT_ADDRESS")},
253     {TextContentType::UNSPECIFIED, std::make_pair(AceAutoFillType::ACE_UNSPECIFIED, "TextContentType.UNSPECIFIED")}};
254 
SwapIfLarger(int32_t & a,int32_t & b)255 void SwapIfLarger(int32_t& a, int32_t& b)
256 {
257     if (a > b) {
258         std::swap(a, b);
259     }
260 }
261 
ConvertFontFamily(const std::vector<std::string> & fontFamily)262 std::string ConvertFontFamily(const std::vector<std::string>& fontFamily)
263 {
264     std::string result;
265     for (const auto& item : fontFamily) {
266         result += item;
267         result += ",";
268     }
269     result = result.substr(0, result.length() ? static_cast<int32_t>(result.length()) - 1 : 0);
270     return result;
271 }
272 
273 } // namespace
274 
OnAttachContext(PipelineContext * context)275 void TextFieldPattern::OnAttachContext(PipelineContext* context)
276 {
277     CHECK_NULL_VOID(context);
278     SetInstanceId(context->GetInstanceId());
279 }
280 
OnDetachContext(PipelineContext * context)281 void TextFieldPattern::OnDetachContext(PipelineContext* context)
282 {
283     SetInstanceId(INSTANCE_ID_UNDEFINED);
284 }
285 
CalcCounterBoundHeight()286 double TextFieldPattern::CalcCounterBoundHeight() {
287     auto counterNode = GetCounterNode().Upgrade();
288     CHECK_NULL_RETURN(counterNode, 0.0);
289     auto counterFrameNode = counterNode->GetHostNode();
290     CHECK_NULL_RETURN(counterFrameNode, 0.0);
291     auto geometryNode = counterFrameNode->GetGeometryNode();
292     CHECK_NULL_RETURN(geometryNode, 0.0);
293     return COUNTER_TEXT_TOP_MARGIN.ConvertToPx() + COUNTER_TEXT_BOTTOM_MARGIN.ConvertToPx() +
294         geometryNode->GetFrameRect().Height();
295 }
296 
CreateNodePaintMethod()297 RefPtr<NodePaintMethod> TextFieldPattern::CreateNodePaintMethod()
298 {
299     if (!textFieldContentModifier_) {
300         textFieldContentModifier_ = AceType::MakeRefPtr<TextFieldContentModifier>(WeakClaim(this));
301     }
302     auto textFieldOverlayModifier = AceType::DynamicCast<TextFieldOverlayModifier>(GetScrollBarOverlayModifier());
303     if (!textFieldOverlayModifier) {
304         textFieldOverlayModifier_ =
305             AceType::MakeRefPtr<TextFieldOverlayModifier>(WeakClaim(this), GetScrollEdgeEffect());
306         SetScrollBarOverlayModifier(textFieldOverlayModifier_);
307     }
308     if (!textFieldForegroundModifier_) {
309         textFieldForegroundModifier_ = AceType::MakeRefPtr<TextFieldForegroundModifier>(WeakClaim(this));
310     }
311     if (isCustomFont_) {
312         textFieldContentModifier_->SetIsCustomFont(true);
313     }
314     auto paint = AceType::MakeRefPtr<TextFieldPaintMethod>(
315         WeakClaim(this), textFieldOverlayModifier_, textFieldContentModifier_, textFieldForegroundModifier_);
316     auto scrollBar = GetScrollBar();
317     if (scrollBar) {
318         paint->SetScrollBar(scrollBar);
319         if (scrollBar->NeedPaint()) {
320             textFieldOverlayModifier_->SetRect(scrollBar->GetActiveRect());
321         } else if (IsNormalInlineState() && !HasFocus()) {
322             auto inlineScrollRect = scrollBar->GetActiveRect();
323             CalcInlineScrollRect(inlineScrollRect);
324             textFieldOverlayModifier_->SetRect(inlineScrollRect);
325             textFieldOverlayModifier_->SetOpacity(0);
326         }
327     }
328     auto host = GetHost();
329     CHECK_NULL_RETURN(host, paint);
330     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
331     CHECK_NULL_RETURN(layoutProperty, paint);
332     auto geometryNode = host->GetGeometryNode();
333     auto frameOffset = geometryNode->GetFrameOffset();
334     auto frameSize = geometryNode->GetFrameSize();
335     bool isShowCount = IsShowCount() && !IsTextArea();
336     auto errorTextNode = errorTextNode_.Upgrade();
337     bool isShowError = layoutProperty->GetShowErrorTextValue(false) && errorTextNode;
338     if (isShowCount && isShowError) {
339         auto textWidth = std::max(CalcDecoratorWidth(errorTextNode), frameSize.Width());
340         auto errorHeight = CalcDecoratorHeight(errorTextNode) + ERROR_TEXT_TOP_MARGIN.ConvertToPx() +
341                                            ERROR_TEXT_BOTTOM_MARGIN.ConvertToPx();
342         auto countHeight = std::max(CalcCounterBoundHeight(),
343             COUNTER_TEXT_TOP_MARGIN.ConvertToPx() + COUNTER_TEXT_BOTTOM_MARGIN.ConvertToPx());
344         auto bottomHeight = std::max(errorHeight, countHeight);
345         RectF boundsRect(0.0f, 0.0f, textWidth, bottomHeight + frameSize.Height());
346         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
347         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
348     } else if (isShowCount) {
349         auto countHeight = std::max(CalcCounterBoundHeight(),
350             COUNTER_TEXT_TOP_MARGIN.ConvertToPx() + COUNTER_TEXT_BOTTOM_MARGIN.ConvertToPx());
351         RectF boundsRect(0.0f, 0.0f, frameSize.Width(), countHeight + frameSize.Height());
352         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
353         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
354     } else if (isShowError) {
355         auto textWidth = std::max(CalcDecoratorWidth(errorTextNode), frameSize.Width());
356         auto errorHeight = CalcDecoratorHeight(errorTextNode) + ERROR_TEXT_TOP_MARGIN.ConvertToPx() +
357                                            ERROR_TEXT_BOTTOM_MARGIN.ConvertToPx();
358         RectF boundsRect(0.0f, 0.0f, textWidth, errorHeight + frameSize.Height());
359         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
360         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
361     } else {
362         if (NearEqual(maxFrameOffsetY_, 0.0f) && NearEqual(maxFrameHeight_, 0.0f)) {
363             maxFrameOffsetY_ = frameOffset.GetY();
364             maxFrameHeight_ = frameSize.Height();
365         }
366         maxFrameOffsetY_ = LessOrEqual(frameOffset.GetY(), maxFrameOffsetY_) ? frameOffset.GetY()
367                                                                              : maxFrameOffsetY_ - frameOffset.GetY();
368         maxFrameHeight_ = LessOrEqual(frameSize.Height(), maxFrameHeight_) ? maxFrameHeight_ : frameSize.Height();
369         RectF boundsRect(0.0f, 0.0f, frameSize.Width(), maxFrameHeight_ + UNDERLINE_WIDTH.ConvertToPx());
370         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
371         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
372     }
373     return paint;
374 }
375 
CalcInlineScrollRect(Rect & inlineScrollRect)376 void TextFieldPattern::CalcInlineScrollRect(Rect& inlineScrollRect)
377 {
378     auto pipeline = PipelineContext::GetCurrentContext();
379     CHECK_NULL_VOID(pipeline);
380     auto scrollBar = GetScrollBar();
381     CHECK_NULL_VOID(scrollBar);
382     Size size(frameRect_.Width(), inlineMeasureItem_.inlineSizeHeight);
383     auto positionMode_ = scrollBar->GetPositionMode();
384     double mainSize = (positionMode_ == PositionMode::BOTTOM ? size.Width() : size.Height());
385     auto barRegionSize = mainSize;
386     double estimatedHeight = inlineMeasureItem_.inlineContentRectHeight;
387     double activeSize = barRegionSize * mainSize / estimatedHeight - scrollBar->GetOutBoundary();
388     auto offsetScale = 0.0f;
389     if (NearEqual(mainSize, estimatedHeight)) {
390         offsetScale = 0.0;
391     } else {
392         offsetScale = (barRegionSize - activeSize) / (estimatedHeight - mainSize);
393     }
394     double lastMainOffset = std::max(
395         static_cast<double>(std::max(inlineMeasureItem_.inlineLastOffsetY, contentRect_.GetY() - textRect_.GetY())),
396         0.0);
397     double activeMainOffset = std::min(offsetScale * lastMainOffset, barRegionSize - activeSize);
398     inlineScrollRect.SetLeft(inlineScrollRect.GetOffset().GetX() - inlineMeasureItem_.inlineScrollRectOffsetX);
399     inlineScrollRect.SetTop(activeMainOffset);
400     inlineScrollRect.SetHeight(activeSize);
401 }
402 
CreateObscuredText(int32_t len)403 std::u16string TextFieldPattern::CreateObscuredText(int32_t len)
404 {
405     std::u16string obscuredText;
406     if (Localization::GetInstance()->GetLanguage() == "ar") { // ar is the abbreviation of Arabic.
407         obscuredText = std::u16string(len, OBSCURING_CHARACTER_FOR_AR);
408     } else {
409         obscuredText = std::u16string(len, OBSCURING_CHARACTER);
410     }
411     return obscuredText;
412 }
413 
CreateDisplayText(const std::string & content,int32_t nakedCharPosition,bool needObscureText,bool showPasswordDirectly)414 std::u16string TextFieldPattern::CreateDisplayText(
415     const std::string& content, int32_t nakedCharPosition, bool needObscureText, bool showPasswordDirectly)
416 {
417     if (!content.empty() && needObscureText) {
418         auto text =
419             TextFieldPattern::CreateObscuredText(static_cast<int32_t>(StringUtils::ToWstring(content).length()));
420         if (nakedCharPosition >= 0 && nakedCharPosition < static_cast<int32_t>(content.length())) {
421             if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TWELVE) || !showPasswordDirectly) {
422                 auto rawContent = StringUtils::Str8ToStr16(content);
423                 text[nakedCharPosition] = rawContent[nakedCharPosition];
424             }
425         }
426         return text;
427     }
428     return StringUtils::Str8ToStr16(content);
429 }
430 
GetTextOrPlaceHolderFontSize()431 float TextFieldPattern::GetTextOrPlaceHolderFontSize()
432 {
433     auto tmpHost = GetHost();
434     CHECK_NULL_RETURN(tmpHost, 0.0f);
435     auto textFieldLayoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
436     CHECK_NULL_RETURN(textFieldLayoutProperty, 0.0f);
437     auto textFieldTheme = GetTheme();
438     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
439     Dimension fontSize;
440     if (textFieldLayoutProperty->HasFontSize() &&
441         textFieldLayoutProperty->GetFontSizeValue(Dimension()).IsNonNegative()) {
442         fontSize = textFieldLayoutProperty->GetFontSizeValue(Dimension());
443     } else {
444         return textFieldTheme ? static_cast<float>(textFieldTheme->GetFontSize().ConvertToPx())
445                               : static_cast<float>(DEFAULT_FONT.ConvertToPx());
446     }
447     return std::min(static_cast<float>(fontSize.ConvertToPx()), contentRect_.Height());
448 }
449 
TextFieldPattern()450 TextFieldPattern::TextFieldPattern() : twinklingInterval_(TWINKLING_INTERVAL_MS)
451 {
452     if (PipelineBase::GetCurrentContext() &&
453         // for normal app add version protection, enable keyboard as default start from API 10 or higher
454         PipelineBase::GetCurrentContext()->GetMinPlatformVersion() > KEYBOARD_DEFAULT_API) {
455         needToRequestKeyboardOnFocus_ = true;
456     }
457     contentController_ = MakeRefPtr<ContentController>(WeakClaim(this));
458     selectController_ = MakeRefPtr<TextSelectController>(WeakClaim(this));
459     selectController_->InitContentController(contentController_);
460     magnifierController_ = MakeRefPtr<MagnifierController>(WeakClaim(this));
461     selectOverlay_ = MakeRefPtr<TextFieldSelectOverlay>(WeakClaim(this));
462     ResetOriginCaretPosition();
463 }
464 
~TextFieldPattern()465 TextFieldPattern::~TextFieldPattern()
466 {
467     if (textEditingController_) {
468         textEditingController_->Clear();
469         textEditingController_->RemoveObserver(WeakClaim(this));
470     }
471     CloseSelectOverlay();
472     if (isCustomKeyboardAttached_) {
473         CloseCustomKeyboard();
474     }
475     RemoveTextFieldInfo();
476     auto host = GetHost();
477     CHECK_NULL_VOID(host);
478     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Pattern Destructor", host->GetId());
479 }
480 
CheckAndUpdateRecordBeforeOperation()481 void TextFieldPattern::CheckAndUpdateRecordBeforeOperation()
482 {
483     if (operationRecords_.size() == 0 ||
484         operationRecords_.back().caretPosition != selectController_->GetCaretIndex()) {
485         // record the state before the operation
486         // or caret position change
487         UpdateEditingValueToRecord();
488     }
489 }
490 
BeforeCreateLayoutWrapper()491 void TextFieldPattern::BeforeCreateLayoutWrapper()
492 {
493     while (!inputOperations_.empty()) {
494         auto operation = inputOperations_.front();
495         inputOperations_.pop();
496         CheckAndUpdateRecordBeforeOperation();
497         switch (operation) {
498             case InputOperation::INSERT: {
499                 ExecuteInsertValueCommand(insertCommands_.front());
500                 insertCommands_.pop();
501                 break;
502             }
503             case InputOperation::DELETE_BACKWARD: {
504                 DeleteBackwardOperation(deleteBackwardOperations_.front());
505                 deleteBackwardOperations_.pop();
506                 HandleDeleteOnCounterScene();
507                 break;
508             }
509             case InputOperation::DELETE_FORWARD: {
510                 DeleteForwardOperation(deleteForwardOperations_.front());
511                 deleteForwardOperations_.pop();
512                 HandleDeleteOnCounterScene();
513                 break;
514             }
515             case InputOperation::CURSOR_UP: {
516                 CursorMoveUpOperation();
517                 break;
518             }
519             case InputOperation::CURSOR_DOWN: {
520                 CursorMoveDownOperation();
521                 break;
522             }
523             case InputOperation::CURSOR_LEFT: {
524                 CursorMoveLeftOperation();
525                 break;
526             }
527             case InputOperation::CURSOR_RIGHT: {
528                 CursorMoveRightOperation();
529                 break;
530             }
531             case InputOperation::SET_PREVIEW_TEXT:
532                 SetPreviewTextOperation(previewTextOperation_.front());
533                 previewTextOperation_.pop();
534                 break;
535             case InputOperation::SET_PREVIEW_FINISH:
536                 FinishTextPreviewOperation();
537                 break;
538             case InputOperation::INPUT:
539                 ExecuteInputCommand(inputCommands_.front());
540                 inputCommands_.pop();
541                 break;
542         }
543     }
544     selectOverlay_->MarkOverlayDirty();
545 }
546 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)547 bool TextFieldPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
548 {
549     if (config.skipMeasure || dirty->SkipMeasureContent()) {
550         return false;
551     }
552     contentRect_ = dirty->GetGeometryNode()->GetContentRect();
553     frameRect_ = dirty->GetGeometryNode()->GetFrameRect();
554     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
555     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
556     auto textFieldLayoutAlgorithm = DynamicCast<TextFieldLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
557     CHECK_NULL_RETURN(textFieldLayoutAlgorithm, false);
558     auto paragraph = textFieldLayoutAlgorithm->GetParagraph();
559     float paragraphWidth = 0.0f;
560     if (paragraph) {
561         paragraph_ = paragraph;
562         paragraphWidth = std::max(paragraph->GetLongestLine(), 0.0f);
563     }
564     if (!IsDragging()) {
565         dragParagraph_ = paragraph_;
566         do {
567             if (!dragNode_) {
568                 break;
569             }
570             auto dragNodePattern = AceType::DynamicCast<TextDragPattern>(dragNode_->GetPattern());
571             if (!dragNodePattern) {
572                 break;
573             }
574             dragNodePattern->UpdateParagraph(paragraph_);
575         } while (false);
576     }
577     auto textRect = textFieldLayoutAlgorithm->GetTextRect();
578     if (!needToRefreshSelectOverlay_ ||
579         (NearEqual(paragraphWidth, paragraphWidth_) && NearEqual(textRect.GetSize(), textRect_.GetSize()))) {
580         needToRefreshSelectOverlay_ = false;
581     }
582     paragraphWidth_ = paragraphWidth;
583     HandleContentSizeChange(textRect);
584     textRect_ = textRect;
585 
586     if (textFieldContentModifier_) {
587         textFieldContentModifier_->ContentChange();
588     }
589 
590     if (textFieldOverlayModifier_) {
591         textFieldOverlayModifier_->ContentChange();
592     }
593 
594     auto oldParentGlobalOffset = parentGlobalOffset_;
595     parentGlobalOffset_ = GetPaintRectGlobalOffset();
596     inlineMeasureItem_ = textFieldLayoutAlgorithm->GetInlineMeasureItem();
597     auto isEditorValueChanged = FireOnTextChangeEvent();
598     UpdateCancelNode();
599     UpdateSelectController();
600     AdjustTextInReasonableArea();
601     UpdateCaretRect(isEditorValueChanged);
602     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
603     UpdateCaretInfoToController();
604     auto hostLayoutProperty =
605         dirty->GetHostNode() ? dirty->GetHostNode()->GetLayoutProperty<TextFieldLayoutProperty>() : nullptr;
606     if (hostLayoutProperty) {
607         hostLayoutProperty->ResetTextAlignChanged();
608     }
609     ProcessOverlayAfterLayout(oldParentGlobalOffset);
610     if (inlineSelectAllFlag_) {
611         HandleOnSelectAll(false, true);
612         inlineSelectAllFlag_ = false;
613         showSelect_ = true;
614     }
615     if (needSelectAll_ && !isLongPress_) {
616         HandleOnSelectAll(false);
617         needSelectAll_ = false;
618     }
619     if (mouseStatus_ == MouseStatus::RELEASED) {
620         mouseStatus_ = MouseStatus::NONE;
621     }
622     StopScrollable();
623     CheckScrollable();
624     UpdateScrollBarOffset();
625     if (config.frameSizeChange) {
626         ScheduleDisappearDelayTask();
627     }
628     SetAccessibilityClearAction();
629     SetAccessibilityPasswordIconAction();
630     SetAccessibilityUnitAction();
631     return true;
632 }
633 
SetAccessibilityPasswordIconAction()634 void TextFieldPattern::SetAccessibilityPasswordIconAction()
635 {
636     if (IsInPasswordMode() && IsShowPasswordIcon()) {
637         auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
638         CHECK_NULL_VOID(passwordArea);
639         auto node = passwordArea->GetFrameNode();
640         CHECK_NULL_VOID(node);
641         auto textAccessibilityProperty = node->GetAccessibilityProperty<AccessibilityProperty>();
642         CHECK_NULL_VOID(textAccessibilityProperty);
643         textAccessibilityProperty->SetAccessibilityLevel("yes");
644         textAccessibilityProperty->SetAccessibilityText(GetPasswordIconPromptInformation(passwordArea->IsObscured()));
645     }
646 }
647 
SetAccessibilityClearAction()648 void TextFieldPattern::SetAccessibilityClearAction()
649 {
650     if (IsShowCancelButtonMode()) {
651         auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
652         if (cleanNodeResponseArea) {
653             auto stackNode = cleanNodeResponseArea->GetFrameNode();
654             CHECK_NULL_VOID(stackNode);
655             auto textAccessibilityProperty = stackNode->GetAccessibilityProperty<AccessibilityProperty>();
656             CHECK_NULL_VOID(textAccessibilityProperty);
657             textAccessibilityProperty->SetAccessibilityLevel("yes");
658             auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
659             CHECK_NULL_VOID(layoutProperty);
660             auto cleanNodeStyle = layoutProperty->GetCleanNodeStyleValue(CleanNodeStyle::INPUT);
661             auto hasContent = cleanNodeStyle == CleanNodeStyle::CONSTANT ||
662                               (cleanNodeStyle == CleanNodeStyle::INPUT && IsOperation());
663             textAccessibilityProperty->SetAccessibilityText(hasContent ? GetCancelImageText() : "");
664         }
665     }
666 }
667 
SetAccessibilityUnitAction()668 void TextFieldPattern::SetAccessibilityUnitAction()
669 {
670     if (unitNode_ && responseArea_) {
671         auto unitNode = AceType::DynamicCast<FrameNode>(unitNode_);
672         CHECK_NULL_VOID(unitNode);
673         auto unitAccessibilityProperty = unitNode->GetAccessibilityProperty<AccessibilityProperty>();
674         CHECK_NULL_VOID(unitAccessibilityProperty);
675         unitAccessibilityProperty->SetAccessibilityLevel("yes");
676     }
677 }
678 
HandleContentSizeChange(const RectF & textRect)679 void TextFieldPattern::HandleContentSizeChange(const RectF& textRect)
680 {
681     if (textRect_ == textRect) {
682         return;
683     }
684     auto host = GetHost();
685     CHECK_NULL_VOID(host);
686     if (!NearEqual(textRect.Height(), textRect_.Height())) {
687         PlayScrollBarAppearAnimation();
688         ScheduleDisappearDelayTask();
689     }
690     auto eventHub = host->GetEventHub<TextFieldEventHub>();
691     CHECK_NULL_VOID(eventHub);
692     if (eventHub->GetOnContentSizeChange()) {
693         auto pipeline = PipelineContext::GetCurrentContextSafely();
694         CHECK_NULL_VOID(pipeline);
695         pipeline->AddAfterLayoutTask([textRect, eventHub]() {
696             eventHub->FireOnContentSizeChange(std::max(0.0f, textRect.Width()), textRect.Height());
697         });
698     }
699 }
700 
ProcessOverlayAfterLayout(const OffsetF & prevOffset)701 void TextFieldPattern::ProcessOverlayAfterLayout(const OffsetF& prevOffset)
702 {
703     auto pipeline = PipelineContext::GetCurrentContextSafely();
704     CHECK_NULL_VOID(pipeline);
705     pipeline->AddAfterLayoutTask([weak = WeakClaim(this), prevOffset]() {
706         auto pattern = weak.Upgrade();
707         CHECK_NULL_VOID(pattern);
708         pattern->parentGlobalOffset_ = pattern->GetPaintRectGlobalOffset();
709         if (pattern->SelectOverlayIsOn()) {
710             if (pattern->IsSelected()) {
711                 pattern->selectOverlay_->UpdateAllHandlesOffset();
712             } else {
713                 pattern->selectOverlay_->UpdateSecondHandleOffset();
714             }
715         }
716         if (pattern->processOverlayDelayTask_) {
717             CHECK_NULL_VOID(pattern->HasFocus());
718             pattern->processOverlayDelayTask_();
719             pattern->processOverlayDelayTask_ = nullptr;
720         } else if (prevOffset != pattern->parentGlobalOffset_) {
721             pattern->HandleParentGlobalOffsetChange();
722         } else if (pattern->needToRefreshSelectOverlay_ && pattern->SelectOverlayIsOn()) {
723             if (pattern->IsSelected()) {
724                 pattern->StopTwinkling();
725             } else {
726                 pattern->StartTwinkling();
727             }
728             pattern->ProcessOverlay({ .menuIsShow = pattern->selectOverlay_->IsCurrentMenuVisibile() });
729             pattern->needToRefreshSelectOverlay_ = false;
730         }
731     });
732 }
733 
HasFocus() const734 bool TextFieldPattern::HasFocus() const
735 {
736     auto focusHub = GetFocusHub();
737 
738     CHECK_NULL_RETURN(focusHub, false);
739     return focusHub->IsCurrentFocus();
740 }
741 
UpdateCaretInfoToController(bool forceUpdate)742 void TextFieldPattern::UpdateCaretInfoToController(bool forceUpdate)
743 {
744     CHECK_NULL_VOID(HasFocus());
745 #if defined(ENABLE_STANDARD_INPUT)
746     auto miscTextConfig = GetMiscTextConfig();
747     CHECK_NULL_VOID(miscTextConfig.has_value());
748     PreviewRange miscTextConfigRange {
749         miscTextConfig.value().range.start,
750         miscTextConfig.value().range.end
751     };
752     if (!forceUpdate && lastCursorRange_ == miscTextConfigRange &&
753         lastTextValue_ == contentController_->GetTextValue() &&
754         NearEqual(miscTextConfig.value().cursorInfo.top, lastCursorTop_)) {
755         return;
756     }
757     lastCursorRange_.Set(miscTextConfig.value().range.start, miscTextConfig.value().range.end);
758     lastTextValue_ = contentController_->GetTextValue();
759     lastCursorTop_ = miscTextConfig.value().cursorInfo.top;
760     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
761     MiscServices::InputMethodController::GetInstance()->OnCursorUpdate(cursorInfo);
762     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
763         StringUtils::Str8ToStr16(contentController_->GetTextValue()), selectController_->GetStartIndex(),
764         selectController_->GetEndIndex());
765     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
766         "UpdateCaretInfoToController, left %{public}f, top %{public}f, width %{public}f, height %{public}f, "
767         "selectController_ Start %{public}d, end %{public}d",
768         cursorInfo.left, cursorInfo.top, cursorInfo.width, cursorInfo.height, selectController_->GetStartIndex(),
769         selectController_->GetEndIndex());
770 #else
771     if (HasConnection()) {
772         TextEditingValue value;
773         value.text = contentController_->GetTextValue();
774         value.hint = GetPlaceHolder();
775         value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
776         connection_->SetEditingState(value, GetInstanceId());
777     }
778 #endif
779 }
780 
781 // return: true if text rect offset will NOT be further changed by caret position
UpdateCaretRect(bool isEditorValueChanged)782 void TextFieldPattern::UpdateCaretRect(bool isEditorValueChanged)
783 {
784     auto focusHub = GetFocusHub();
785     if (IsSelected()) {
786         selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex());
787         selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex());
788         return;
789     }
790     if (focusHub && !focusHub->IsCurrentFocus() && !obscuredChange_) {
791         CloseSelectOverlay(true);
792         return;
793     }
794     selectController_->MoveCaretToContentRect(
795         selectController_->GetCaretIndex(), TextAffinity::DOWNSTREAM, isEditorValueChanged);
796 }
797 
AdjustTextInReasonableArea()798 void TextFieldPattern::AdjustTextInReasonableArea()
799 {
800     // Adjust y.
801     auto contentBottomBoundary = contentRect_.GetY() + contentRect_.GetSize().Height();
802     if (textRect_.Height() > contentRect_.Height()) {
803         if (textRect_.GetY() + textRect_.Height() < contentBottomBoundary) {
804             auto dy = contentBottomBoundary - textRect_.GetY() - textRect_.Height();
805             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
806         }
807         if (GreatNotEqual(textRect_.GetY(), contentRect_.GetY())) {
808             auto dy = textRect_.GetY() - contentRect_.GetY();
809             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() - dy));
810         }
811     } else {
812         if (textRect_.GetY() != contentRect_.GetY()) {
813             auto dy = contentRect_.GetY() - textRect_.GetY();
814             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
815         }
816     }
817 
818     // Adjust x.
819     auto contentRightBoundary = contentRect_.GetX() + contentRect_.GetSize().Width();
820     if (textRect_.Width() > contentRect_.Width()) {
821         if (textRect_.GetX() + textRect_.Width() < contentRightBoundary) {
822             auto dx = contentRightBoundary - textRect_.GetX() - textRect_.Width();
823             textRect_.SetLeft(textRect_.GetX() + dx);
824         }
825         if (GreatNotEqual(textRect_.GetX(), contentRect_.GetX())) {
826             auto dx = textRect_.GetX() - contentRect_.GetX();
827             textRect_.SetOffset(OffsetF(textRect_.GetX() - dx, textRect_.GetY()));
828         }
829     }
830 }
831 
IsTextArea() const832 bool TextFieldPattern::IsTextArea() const
833 {
834     CHECK_NULL_RETURN(GetHost(), false);
835     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
836     CHECK_NULL_RETURN(layoutProperty, true);
837     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(1) > 1 : true;
838 }
839 
UpdateSelectionOffset()840 void TextFieldPattern::UpdateSelectionOffset()
841 {
842     CHECK_NULL_VOID(IsSelected());
843     selectController_->CalculateHandleOffset();
844 }
845 
CalcCaretMetricsByPosition(int32_t extent,CaretMetricsF & caretCaretMetric,TextAffinity textAffinity)846 void TextFieldPattern::CalcCaretMetricsByPosition(
847     int32_t extent, CaretMetricsF& caretCaretMetric, TextAffinity textAffinity)
848 {
849     paragraph_->CalcCaretMetricsByPosition(extent, caretCaretMetric, textAffinity);
850     caretCaretMetric.offset.AddX(textRect_.GetX());
851     caretCaretMetric.offset.AddY(textRect_.GetY());
852 }
853 
CursorInContentRegion()854 bool TextFieldPattern::CursorInContentRegion()
855 {
856     if (IsTextArea()) {
857         return GreatOrEqual(selectController_->GetCaretRect().GetY(), contentRect_.GetY()) &&
858                LessOrEqual(selectController_->GetCaretRect().GetY() + GetTextOrPlaceHolderFontSize(),
859                    contentRect_.GetY() + contentRect_.Height());
860     }
861     auto theme = GetTheme();
862     CHECK_NULL_RETURN(theme, false);
863     return GreatOrEqual(selectController_->GetCaretRect().GetX(), contentRect_.GetX()) &&
864            LessOrEqual(selectController_->GetCaretRect().GetX() + theme->GetCursorWidth().ConvertToPx(),
865                contentRect_.GetX() + contentRect_.Width());
866 }
867 
OffsetInContentRegion(const Offset & offset)868 bool TextFieldPattern::OffsetInContentRegion(const Offset& offset)
869 {
870     // real content region will minus basic padding on left and right
871     return GreatOrEqual(offset.GetX(), contentRect_.GetX()) &&
872            LessOrEqual(offset.GetX(), contentRect_.GetX() + contentRect_.Width());
873 }
874 
CheckSelectAreaVisible()875 bool TextFieldPattern::CheckSelectAreaVisible()
876 {
877     auto tmpHost = GetHost();
878     CHECK_NULL_RETURN(tmpHost, false);
879     auto pipeline = tmpHost->GetContextRefPtr();
880     CHECK_NULL_RETURN(pipeline, false);
881     auto keyboardInset = pipeline->GetSafeAreaManager()->GetKeyboardInset();
882     auto selectArea = selectOverlay_->GetSelectArea();
883     auto globalOffset = GetPaintRectGlobalOffset();
884     auto globalContentRect = contentRect_;
885     globalContentRect.SetOffset(globalContentRect.GetOffset() + globalOffset);
886     if (selectArea.Bottom() < 0) {
887         return false;
888     } else if (!globalContentRect.IsInnerIntersectWith(selectArea)) {
889         return false;
890     } else if (keyboardInset.Length() > 0 && selectArea.Top() >= keyboardInset.start) {
891         return false;
892     }
893     return true;
894 }
895 
OnScrollEndCallback()896 void TextFieldPattern::OnScrollEndCallback()
897 {
898     ScheduleDisappearDelayTask();
899     if (!IsUsingMouse() && SelectOverlayIsOn() && isTextSelectionMenuShow_ && CheckSelectAreaVisible()) {
900         selectOverlay_->ShowMenu();
901     }
902 }
903 
OnTextAreaScroll(float offset)904 void TextFieldPattern::OnTextAreaScroll(float offset)
905 {
906     if (!IsTextArea() || textRect_.Height() <= contentRect_.Height()) {
907         return;
908     }
909     if (textRect_.GetY() + offset > contentRect_.GetY()) {
910         offset = contentRect_.GetY() - textRect_.GetY();
911     } else if (textRect_.GetY() + textRect_.Height() + offset < contentRect_.GetY() + contentRect_.Height()) {
912         offset = contentRect_.GetY() + contentRect_.Height() - textRect_.GetY() - textRect_.Height();
913     }
914     currentOffset_ = textRect_.GetY() + offset;
915     textRect_.SetOffset(OffsetF(textRect_.GetX(), currentOffset_));
916     UpdateHandlesOffsetOnScroll(offset);
917     UpdateScrollBarOffset();
918 }
919 
OnTextInputScroll(float offset)920 void TextFieldPattern::OnTextInputScroll(float offset)
921 {
922     if (IsTextArea() || textRect_.Width() <= contentRect_.Width()) {
923         return;
924     }
925     if (textRect_.GetX() + offset > contentRect_.GetX()) {
926         offset = contentRect_.GetX() - textRect_.GetX();
927     } else if (textRect_.GetX() + textRect_.Width() + offset < contentRect_.GetX() + contentRect_.Width()) {
928         offset = contentRect_.GetX() + contentRect_.Width() - textRect_.GetX() - textRect_.Width();
929     }
930     currentOffset_ = textRect_.GetX() + offset;
931     textRect_.SetOffset(OffsetF(currentOffset_, textRect_.GetY()));
932     UpdateHandlesOffsetOnScroll(offset);
933     auto tmpHost = GetHost();
934     CHECK_NULL_VOID(tmpHost);
935     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
936 }
937 
ConvertTouchOffsetToCaretPosition(const Offset & localOffset)938 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPosition(const Offset& localOffset)
939 {
940     CHECK_NULL_RETURN(paragraph_, 0);
941     int32_t caretPositionIndex = 0;
942     if (!contentController_->IsEmpty()) {
943         caretPositionIndex = paragraph_->GetGlyphIndexByCoordinate(localOffset);
944     }
945     return caretPositionIndex;
946 }
947 
ConvertTouchOffsetToCaretPositionNG(const Offset & localOffset)948 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPositionNG(const Offset& localOffset)
949 {
950     CHECK_NULL_RETURN(paragraph_, 0);
951     auto offset = localOffset - Offset(textRect_.GetX(), textRect_.GetY());
952     return paragraph_->GetGlyphIndexByCoordinate(offset);
953 }
954 
955 #if defined(IOS_PLATFORM)
GetGlobalOffset() const956 Offset TextFieldPattern::GetGlobalOffset() const
957 {
958     Offset offset;
959     auto host = GetHost();
960     CHECK_NULL_RETURN(host, {});
961     auto pipeline = PipelineContext::GetCurrentContext();
962     CHECK_NULL_RETURN(pipeline, {});
963     auto rootOffset = pipeline->GetRootRect().GetOffset();
964     auto globalOffset = host->GetPaintRectOffset(false, true) - rootOffset;
965     offset = Offset(globalOffset.GetX(), globalOffset.GetY());
966     return offset;
967 }
968 
GetEditingBoxY() const969 double TextFieldPattern::GetEditingBoxY() const
970 {
971     return GetGlobalOffset().GetY() + frameRect_.Height();
972 };
973 
GetEditingBoxTopY() const974 double TextFieldPattern::GetEditingBoxTopY() const
975 {
976     return GetGlobalOffset().GetY();
977 };
978 
GetEditingBoxModel() const979 bool TextFieldPattern::GetEditingBoxModel() const
980 {
981     bool isDeclarative = false;
982     auto pipeline = PipelineContext::GetCurrentContext();
983     if (pipeline && pipeline->GetIsDeclarative()) {
984         isDeclarative = true;
985     }
986     return isDeclarative;
987 };
988 #endif
989 
HandleFocusEvent()990 void TextFieldPattern::HandleFocusEvent()
991 {
992     isFocusedBeforeClick_ = true;
993     focusIndex_ = FocuseIndex::TEXT;
994     auto host = GetHost();
995     CHECK_NULL_VOID(host);
996     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d on focus", host->GetId());
997     ACE_LAYOUT_SCOPED_TRACE("[TextField:%d] on focus", host->GetId());
998     auto context = host->GetContextRefPtr();
999     CHECK_NULL_VOID(context);
1000     auto globalOffset = GetHost()->GetPaintRectOffset(false, true) - context->GetRootRect().GetOffset();
1001     UpdateTextFieldManager(Offset(globalOffset.GetX(), globalOffset.GetY()), frameRect_.Height());
1002     needToRequestKeyboardInner_ = !isLongPress_ && (dragRecipientStatus_ != DragStatus::DRAGGING) &&
1003                                     (dragStatus_ != DragStatus::DRAGGING);
1004     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
1005     CHECK_NULL_VOID(paintProperty);
1006     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1007     CHECK_NULL_VOID(layoutProperty);
1008     auto isSelectAll = layoutProperty->GetSelectAllValueValue(false);
1009     if (isSelectAll && !contentController_->IsEmpty()) {
1010         needSelectAll_ = true;
1011     }
1012     ProcessFocusStyle();
1013     RequestKeyboardByFocusSwitch();
1014     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ?
1015         PROPERTY_UPDATE_MEASURE_SELF : PROPERTY_UPDATE_MEASURE);
1016 }
1017 
ProcessFocusStyle()1018 void TextFieldPattern::ProcessFocusStyle()
1019 {
1020     bool needTwinkling = true;
1021     if (IsNormalInlineState()) {
1022         ApplyInlineTheme();
1023         inlineFocusState_ = true;
1024         if (!contentController_->IsEmpty()) {
1025             inlineSelectAllFlag_ = blurReason_ != BlurReason::WINDOW_BLUR;
1026             if (inlineSelectAllFlag_) {
1027                 needTwinkling = false;
1028             }
1029         }
1030         ProcessResponseArea();
1031     }
1032     if (needTwinkling) {
1033         StartTwinkling();
1034     }
1035     NotifyOnEditChanged(true);
1036     if (!IsShowError() && IsUnderlineMode()) {
1037         auto textFieldTheme = GetTheme();
1038         CHECK_NULL_VOID(textFieldTheme);
1039         underlineColor_ = userUnderlineColor_.typing.value_or(textFieldTheme->GetUnderlineTypingColor());
1040         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
1041     }
1042 }
1043 
HandleSetSelection(int32_t start,int32_t end,bool showHandle)1044 void TextFieldPattern::HandleSetSelection(int32_t start, int32_t end, bool showHandle)
1045 {
1046     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleSetSelection %{public}d, %{public}d", start, end);
1047     StopTwinkling();
1048     UpdateSelection(start, end);
1049     if (showHandle) {
1050         ProcessOverlay();
1051     } else {
1052         CloseSelectOverlay();
1053     }
1054     UpdateCaretInfoToController();
1055     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1056 }
1057 
HandleExtendAction(int32_t action)1058 void TextFieldPattern::HandleExtendAction(int32_t action)
1059 {
1060     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleExtendAction %{public}d", action);
1061     switch (action) {
1062         case ACTION_SELECT_ALL: {
1063             HandleOnSelectAll(false);
1064             break;
1065         }
1066         case ACTION_CUT: {
1067             HandleOnCut();
1068             break;
1069         }
1070         case ACTION_COPY: {
1071             HandleOnCopy();
1072             break;
1073         }
1074         case ACTION_PASTE: {
1075             HandleOnPaste();
1076             break;
1077         }
1078         default: {
1079             break;
1080         }
1081     }
1082 }
1083 
CursorMove(CaretMoveIntent direction)1084 void TextFieldPattern::CursorMove(CaretMoveIntent direction)
1085 {
1086     switch (direction) {
1087         case CaretMoveIntent::Left: {
1088             CursorMoveLeft();
1089             break;
1090         }
1091         case CaretMoveIntent::Right: {
1092             CursorMoveRight();
1093             break;
1094         }
1095         case CaretMoveIntent::Up: {
1096             CursorMoveUp();
1097             break;
1098         }
1099         case CaretMoveIntent::Down: {
1100             CursorMoveDown();
1101             break;
1102         }
1103         case CaretMoveIntent::LineBegin: {
1104             CursorMoveLineBegin();
1105             break;
1106         }
1107         case CaretMoveIntent::LineEnd: {
1108             CursorMoveLineEnd();
1109             break;
1110         }
1111         case CaretMoveIntent::LeftWord: {
1112             CursorMoveLeftWord();
1113             break;
1114         }
1115         case CaretMoveIntent::RightWord: {
1116             CursorMoveRightWord();
1117             break;
1118         }
1119         case CaretMoveIntent::ParagraghBegin: {
1120             CursorMoveToParagraphBegin();
1121             break;
1122         }
1123         case CaretMoveIntent::ParagraghEnd: {
1124             CursorMoveToParagraphEnd();
1125             break;
1126         }
1127         case CaretMoveIntent::Home: {
1128             CursorMoveHome();
1129             break;
1130         }
1131         case CaretMoveIntent::End: {
1132             CursorMoveEnd();
1133             break;
1134         }
1135     }
1136 }
1137 
HandleSelect(CaretMoveIntent direction)1138 void TextFieldPattern::HandleSelect(CaretMoveIntent direction)
1139 {
1140     CloseSelectOverlay();
1141     switch (direction) {
1142         case CaretMoveIntent::Left: {
1143             HandleSelectionLeft();
1144             break;
1145         }
1146         case CaretMoveIntent::Right: {
1147             HandleSelectionRight();
1148             break;
1149         }
1150         case CaretMoveIntent::Up: {
1151             HandleSelectionUp();
1152             break;
1153         }
1154         case CaretMoveIntent::Down: {
1155             HandleSelectionDown();
1156             break;
1157         }
1158         case CaretMoveIntent::LineBegin: {
1159             HandleSelectionLineBegin();
1160             break;
1161         }
1162         case CaretMoveIntent::LineEnd: {
1163             HandleSelectionLineEnd();
1164             break;
1165         }
1166         case CaretMoveIntent::LeftWord: {
1167             HandleSelectionLeftWord();
1168             break;
1169         }
1170         case CaretMoveIntent::RightWord: {
1171             HandleSelectionRightWord();
1172             break;
1173         }
1174         case CaretMoveIntent::Home: {
1175             HandleSelectionHome();
1176             break;
1177         }
1178         case CaretMoveIntent::End: {
1179             HandleSelectionEnd();
1180             break;
1181         }
1182         // SelectionParagraghBegin/SelectionParagraghEnd not supported yet
1183         default: {
1184             LOGW("Unsupported select operation for text field");
1185         }
1186     }
1187     UpdateRecordCaretIndex(
1188         std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
1189 }
1190 
InitDisableColor()1191 void TextFieldPattern::InitDisableColor()
1192 {
1193     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1194     CHECK_NULL_VOID(layoutProperty);
1195     auto theme = GetTheme();
1196     CHECK_NULL_VOID(theme);
1197     if (IsUnderlineMode()) {
1198         underlineWidth_ = HasFocus() ? TYPING_UNDERLINE_WIDTH : UNDERLINE_WIDTH;
1199         Color underlineColor = HasFocus() ? userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor())
1200                                           : userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
1201         if (IsShowError()) {
1202             underlineColor = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
1203         }
1204         if (userUnderlineColor_.disable) {
1205             underlineColor_ = IsDisabled() ? userUnderlineColor_.disable.value() : underlineColor;
1206         } else {
1207             underlineColor_ = IsDisabled() ? theme->GetDisableUnderlineColor() : underlineColor;
1208         }
1209     }
1210     layoutProperty->UpdateIsDisabled(IsDisabled());
1211 }
1212 
InitFocusEvent()1213 void TextFieldPattern::InitFocusEvent()
1214 {
1215     CHECK_NULL_VOID(!focusEventInitialized_);
1216     auto host = GetHost();
1217     CHECK_NULL_VOID(host);
1218     auto focusHub = host->GetOrCreateFocusHub();
1219     auto focusTask = [weak = WeakClaim(this)]() {
1220         auto pattern = weak.Upgrade();
1221         if (pattern) {
1222             pattern->HandleFocusEvent();
1223         }
1224     };
1225     focusHub->SetOnFocusInternal(focusTask);
1226     auto blurTask = [weak = WeakClaim(this)]() {
1227         auto pattern = weak.Upgrade();
1228         CHECK_NULL_VOID(pattern);
1229         pattern->HandleBlurEvent();
1230     };
1231     focusHub->SetOnBlurInternal(blurTask);
1232 
1233     auto keyTask = [weak = WeakClaim(this)](const KeyEvent& keyEvent) -> bool {
1234         auto pattern = weak.Upgrade();
1235         CHECK_NULL_RETURN(pattern, false);
1236         return pattern->OnKeyEvent(keyEvent);
1237     };
1238     focusHub->SetOnKeyEventInternal(keyTask);
1239 
1240     auto getInnerPaintRectCallback = [weak = WeakClaim(this)](RoundRect& paintRect) {
1241         auto pattern = weak.Upgrade();
1242         if (pattern) {
1243             pattern->GetInnerFocusPaintRect(paintRect);
1244         }
1245     };
1246     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
1247     focusEventInitialized_ = true;
1248 }
1249 
CheckBlurReason()1250 bool TextFieldPattern::CheckBlurReason()
1251 {
1252     auto curFocusHub = GetFocusHub();
1253     CHECK_NULL_RETURN(curFocusHub, false);
1254     auto curBlurReason = curFocusHub->GetBlurReason();
1255     if (curBlurReason == BlurReason::FRAME_DESTROY) {
1256         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextFieldPattern CheckBlurReason, Close Keyboard.");
1257         return true;
1258     }
1259     return false;
1260 }
1261 
UpdateBlurReason()1262 void TextFieldPattern::UpdateBlurReason()
1263 {
1264     auto focusHub = GetFocusHub();
1265     CHECK_NULL_VOID(focusHub);
1266     blurReason_ = focusHub->GetBlurReason();
1267 }
1268 
ProcNormalInlineStateInBlurEvent()1269 void TextFieldPattern::ProcNormalInlineStateInBlurEvent()
1270 {
1271     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1272     CHECK_NULL_VOID(layoutProperty);
1273     if (IsNormalInlineState()) {
1274         if (IsTextArea() && isTextInput_) {
1275             layoutProperty->UpdateMaxLines(1);
1276             layoutProperty->UpdatePlaceholderMaxLines(1);
1277         }
1278         layoutProperty->ResetTextOverflowMaxLines();
1279         inlineSelectAllFlag_ = false;
1280         inlineFocusState_ = false;
1281         RestorePreInlineStates();
1282     }
1283 }
1284 
ProcBorderAndUnderlineInBlurEvent()1285 void TextFieldPattern::ProcBorderAndUnderlineInBlurEvent()
1286 {
1287     auto host = GetHost();
1288     CHECK_NULL_VOID(host);
1289     auto textFieldTheme = GetTheme();
1290     CHECK_NULL_VOID(textFieldTheme);
1291     bool isShowError = IsShowError();
1292     bool isUnderlineMode = IsUnderlineMode();
1293     if (!isShowError && isUnderlineMode) {
1294         underlineColor_ = userUnderlineColor_.normal.value_or(textFieldTheme->GetUnderlineColor());
1295         underlineWidth_ = UNDERLINE_WIDTH;
1296     }
1297     if (showCountBorderStyle_) {
1298         showCountBorderStyle_ = false;
1299         if (isShowError) {
1300             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1301         }
1302     }
1303     if (!isShowError || (isShowError && !isUnderlineMode && !IsInPasswordMode())) {
1304         HandleCounterBorder();
1305     }
1306 }
1307 
HandleBlurEvent()1308 void TextFieldPattern::HandleBlurEvent()
1309 {
1310     auto host = GetHost();
1311     CHECK_NULL_VOID(host);
1312     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d OnBlur", host->GetId());
1313     auto context = host->GetContextRefPtr();
1314     CHECK_NULL_VOID(context);
1315     UpdateBlurReason();
1316     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
1317     if (textFieldManager) {
1318         textFieldManager->ClearOnFocusTextField(host->GetId());
1319     }
1320     ResetOriginCaretPosition();
1321 
1322     ProcBorderAndUnderlineInBlurEvent();
1323     ProcNormalInlineStateInBlurEvent();
1324     ModifyInnerStateInBlurEvent();
1325     CloseSelectOverlay(!isKeyboardClosedByUser_ && blurReason_ == BlurReason::FOCUS_SWITCH);
1326     if (magnifierController_) {
1327         magnifierController_->RemoveMagnifierFrameNode();
1328     }
1329     StopTwinkling();
1330     if (((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_)) {
1331         CloseKeyboard(true);
1332         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "textfield %{public}d on blur, close custom keyboard", host->GetId());
1333     }
1334     HandleCrossPlatformInBlurEvent();
1335     selectController_->UpdateCaretIndex(selectController_->GetCaretIndex());
1336     NotifyOnEditChanged(false);
1337     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1338     if (isOnHover_) {
1339         RestoreDefaultMouseState();
1340     }
1341     needToRequestKeyboardInner_ = false;
1342     ReportEvent();
1343     ScheduleDisappearDelayTask();
1344 }
1345 
ModifyInnerStateInBlurEvent()1346 void TextFieldPattern::ModifyInnerStateInBlurEvent()
1347 {
1348     needToRequestKeyboardInner_ = false;
1349     isLongPress_ = false;
1350     isMoveCaretAnywhere_ = false;
1351     isFocusedBeforeClick_ = false;
1352 }
1353 
HandleCrossPlatformInBlurEvent()1354 void TextFieldPattern::HandleCrossPlatformInBlurEvent()
1355 {
1356 #ifndef OHOS_PLATFORM
1357     if (HasConnection()) {
1358         CloseKeyboard(true);
1359     }
1360 #endif
1361 }
1362 
OnKeyEvent(const KeyEvent & event)1363 bool TextFieldPattern::OnKeyEvent(const KeyEvent& event)
1364 {
1365     if (event.code == KeyCode::KEY_TAB && isFocusedBeforeClick_ && !contentController_->IsEmpty()) {
1366         isFocusedBeforeClick_ = false;
1367         HandleOnSelectAll(false);
1368     }
1369     auto pipeline = GetContext();
1370     CHECK_NULL_RETURN(pipeline, false);
1371     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
1372     if (event.code == KeyCode::KEY_TAB && HasFocus() && !needToRequestKeyboardOnFocus_ && needToRequestKeyboardInner_ &&
1373         textFieldManager->GetImeShow()) {
1374         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::ON_KEY_EVENT);
1375     }
1376     return TextInputClient::HandleKeyEvent(event);
1377 }
1378 
HandleOnEscape()1379 bool TextFieldPattern::HandleOnEscape()
1380 {
1381     CloseSelectOverlay(true);
1382     return false;
1383 }
1384 
HandleOnTab(bool backward)1385 bool TextFieldPattern::HandleOnTab(bool backward)
1386 {
1387     return backward ? UpdateFocusBackward() : UpdateFocusForward();
1388 }
1389 
HandleOnUndoAction()1390 void TextFieldPattern::HandleOnUndoAction()
1391 {
1392     if (operationRecords_.empty()) {
1393         return;
1394     }
1395     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnUndoAction");
1396     if (operationRecords_.size() == 1) {
1397         FireEventHubOnChange("");
1398         return;
1399     }
1400     auto value = operationRecords_.back();
1401     operationRecords_.pop_back();
1402     auto textEditingValue = operationRecords_.back(); // each record includes text and caret
1403     bool isWillChange = OnWillChangePreSetValue(textEditingValue.text);
1404     if (!isWillChange) {
1405         operationRecords_.emplace_back(value);
1406         return;
1407     }
1408     if (redoOperationRecords_.size() >= RECORD_MAX_LENGTH) {
1409         redoOperationRecords_.erase(redoOperationRecords_.begin());
1410     }
1411     redoOperationRecords_.emplace_back(value); // the initial status is not recorded
1412     contentController_->SetTextValue(textEditingValue.text);
1413     selectController_->MoveCaretToContentRect(textEditingValue.caretPosition, TextAffinity::DOWNSTREAM);
1414     auto tmpHost = GetHost();
1415     CHECK_NULL_VOID(tmpHost);
1416     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1417 }
1418 
HandleOnRedoAction()1419 void TextFieldPattern::HandleOnRedoAction()
1420 {
1421     if (redoOperationRecords_.empty()) {
1422         return;
1423     }
1424     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnRedoAction");
1425     auto textEditingValue = redoOperationRecords_.back();
1426     bool isWillChange = OnWillChangePreSetValue(textEditingValue.text);
1427     if (!isWillChange) {
1428         return;
1429     }
1430     redoOperationRecords_.pop_back();
1431     operationRecords_.emplace_back(textEditingValue);
1432     contentController_->SetTextValue(textEditingValue.text);
1433     selectController_->UpdateCaretIndex(textEditingValue.caretPosition);
1434     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1435     CHECK_NULL_VOID(layoutProperty);
1436     auto tmpHost = GetHost();
1437     CHECK_NULL_VOID(tmpHost);
1438     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1439 }
1440 
CanUndo()1441 bool TextFieldPattern::CanUndo()
1442 {
1443     return operationRecords_.size() > 1;
1444 }
1445 
CanRedo()1446 bool TextFieldPattern::CanRedo()
1447 {
1448     return !redoOperationRecords_.empty();
1449 }
1450 
HandleOnSelectAll(bool isKeyEvent,bool inlineStyle,bool showMenu)1451 void TextFieldPattern::HandleOnSelectAll(bool isKeyEvent, bool inlineStyle, bool showMenu)
1452 {
1453     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnSelectAll");
1454     auto textSize = static_cast<int32_t>(contentController_->GetWideText().length());
1455     if (inlineStyle) {
1456         auto dotPos = contentController_->GetWideText().rfind(L'.');
1457         if (dotPos != std::string::npos && static_cast<int32_t>(dotPos) < textSize - FIND_TEXT_ZERO_INDEX) {
1458             textSize = static_cast<int32_t>(dotPos);
1459         }
1460         UpdateSelection(0, textSize);
1461     } else {
1462         UpdateSelection(0, textSize);
1463     }
1464     if (IsSelected()) {
1465         SetIsSingleHandle(false);
1466     }
1467     ResetObscureTickCountDown();
1468     auto tmpHost = GetHost();
1469     CHECK_NULL_VOID(tmpHost);
1470     parentGlobalOffset_ = GetPaintRectGlobalOffset();
1471     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1472     selectController_->MoveSecondHandleToContentRect(textSize);
1473     StopTwinkling();
1474     showSelect_ = true;
1475     if (!IsShowHandle() || isKeyEvent || inlineSelectAllFlag_ || IsUsingMouse()) {
1476         CloseSelectOverlay(true);
1477         if (inlineSelectAllFlag_ && !isKeyEvent && !IsUsingMouse()) {
1478             return;
1479         }
1480         if (IsSelected()) {
1481             selectOverlay_->SetSelectionHoldCallback();
1482         }
1483         return;
1484     }
1485     selectOverlay_->ProcessSelectAllOverlay({ .menuIsShow = showMenu, .animation = true });
1486 }
1487 
HandleOnCopy(bool isUsingExternalKeyboard)1488 void TextFieldPattern::HandleOnCopy(bool isUsingExternalKeyboard)
1489 {
1490     CHECK_NULL_VOID(clipboard_);
1491     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
1492     CHECK_NULL_VOID(layoutProperty);
1493     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) == CopyOptions::None) {
1494         return;
1495     }
1496     if (!IsSelected() || IsInPasswordMode()) {
1497         return;
1498     }
1499     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "On copy, text selector %{public}s", selectController_->ToString().c_str());
1500     auto start = selectController_->GetStartIndex();
1501     auto end = selectController_->GetEndIndex();
1502     GetEmojiSubStringRange(start, end);
1503     auto value = contentController_->GetSelectedValue(start, end);
1504     if (value.empty()) {
1505         return;
1506     }
1507     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) != CopyOptions::None) {
1508         clipboard_->SetData(value, layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed));
1509     }
1510 
1511     if (isUsingExternalKeyboard || selectOverlay_->IsShowMouseMenu()) {
1512         CloseSelectOverlay(true);
1513     } else {
1514         selectOverlay_->HideMenu();
1515     }
1516     auto host = GetHost();
1517     CHECK_NULL_VOID(host);
1518     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1519     CHECK_NULL_VOID(eventHub);
1520     eventHub->FireOnCopy(value);
1521 }
1522 
IsShowHandle()1523 bool TextFieldPattern::IsShowHandle()
1524 {
1525     auto theme = GetTheme();
1526     CHECK_NULL_RETURN(theme, false);
1527     return !theme->IsTextFieldShowHandle();
1528 }
1529 
GetCancelButton()1530 std::string TextFieldPattern::GetCancelButton()
1531 {
1532     auto theme = GetTheme();
1533     CHECK_NULL_RETURN(theme, "");
1534     return theme->GetCancelButton();
1535 }
1536 
GetCancelImageText()1537 std::string TextFieldPattern::GetCancelImageText()
1538 {
1539     auto theme = GetTheme();
1540     CHECK_NULL_RETURN(theme, "");
1541     return theme->GetCancelImageText();
1542 }
1543 
GetPasswordIconPromptInformation(bool show)1544 std::string TextFieldPattern::GetPasswordIconPromptInformation(bool show)
1545 {
1546     auto theme = GetTheme();
1547     CHECK_NULL_RETURN(theme, "");
1548     return show ? theme->GetShowPasswordPromptInformation() : theme->GetHiddenPasswordPromptInformation();
1549 }
1550 
UpdateShowCountBorderStyle()1551 void TextFieldPattern::UpdateShowCountBorderStyle()
1552 {
1553     auto host = GetHost();
1554     CHECK_NULL_VOID(host);
1555     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1556     CHECK_NULL_VOID(layoutProperty);
1557     if (layoutProperty->HasMaxLength()) {
1558         auto textLength = static_cast<int32_t>(contentController_->GetWideText().length());
1559         auto maxLength = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
1560         // if equal, the showCountBorderStyle_ is not changed
1561         if (textLength != maxLength) {
1562             showCountBorderStyle_ = textLength > maxLength;
1563         }
1564     }
1565 }
1566 
HandleOnPaste()1567 void TextFieldPattern::HandleOnPaste()
1568 {
1569     auto pasteCallback = [weak = WeakClaim(this)](const std::string& data) {
1570         if (data.empty()) {
1571             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "HandleOnPaste fail, because data is empty");
1572             return;
1573         }
1574         auto textfield = weak.Upgrade();
1575         CHECK_NULL_VOID(textfield);
1576         auto host = textfield->GetHost();
1577         CHECK_NULL_VOID(host);
1578         auto eventHub = host->GetEventHub<TextFieldEventHub>();
1579         CHECK_NULL_VOID(eventHub);
1580         TextCommonEvent event;
1581         eventHub->FireOnPasteWithEvent(data, event);
1582         if (event.IsPreventDefault()) {
1583             textfield->CloseSelectOverlay(true);
1584             textfield->selectController_->ResetHandles();
1585             textfield->StartTwinkling();
1586             return;
1587         }
1588         std::wstring pasteData = StringUtils::ToWstring(data);
1589         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnPaste len:%{public}d", static_cast<int32_t>(pasteData.length()));
1590         textfield->AddInsertCommand(data, InputReason::PASTE);
1591     };
1592     CHECK_NULL_VOID(clipboard_);
1593     clipboard_->GetData(pasteCallback);
1594 }
1595 
IsShowTranslate()1596 bool TextFieldPattern::IsShowTranslate()
1597 {
1598     auto container = Container::Current();
1599     if (container && container->IsScenceBoardWindow()) {
1600         return false;
1601     }
1602 
1603     auto host = GetHost();
1604     CHECK_NULL_RETURN(host, false);
1605     auto textFieldTheme = GetTheme();
1606     CHECK_NULL_RETURN(textFieldTheme, false);
1607     return textFieldTheme->GetTranslateIsSupport();
1608 }
1609 
HandleOnCameraInput()1610 void TextFieldPattern::HandleOnCameraInput()
1611 {
1612     LOGI("TextFieldPattern::HandleOnCameraInput");
1613 #if defined(ENABLE_STANDARD_INPUT)
1614     if (textChangeListener_ == nullptr) {
1615         textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
1616     }
1617     auto inputMethod = MiscServices::InputMethodController::GetInstance();
1618     if (!inputMethod) {
1619         LOGE("HandleOnCameraInput input method is null.");
1620         return;
1621     }
1622 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
1623     if (imeShown_) {
1624         inputMethod->StartInputType(MiscServices::InputType::CAMERA_INPUT);
1625     } else {
1626         auto optionalTextConfig = GetMiscTextConfig();
1627         CHECK_NULL_VOID(optionalTextConfig.has_value());
1628         MiscServices::TextConfig textConfig = optionalTextConfig.value();
1629         LOGI("HandleOnCameraInput set calling window id is : %{public}u", textConfig.windowId);
1630 #ifdef WINDOW_SCENE_SUPPORTED
1631         auto systemWindowId = GetSCBSystemWindowId();
1632         if (systemWindowId) {
1633             TAG_LOGI(AceLogTag::ACE_KEYBOARD,
1634                 "windowId From %{public}u to %{public}u.", textConfig.windowId, systemWindowId);
1635             textConfig.windowId = systemWindowId;
1636         }
1637 #endif
1638         auto ret = inputMethod->Attach(textChangeListener_, false, textConfig);
1639         if (ret == MiscServices::ErrorCode::NO_ERROR) {
1640             auto pipeline = GetContext();
1641             CHECK_NULL_VOID(pipeline);
1642             auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
1643             CHECK_NULL_VOID(textFieldManager);
1644             textFieldManager->SetIsImeAttached(true);
1645         }
1646         inputMethod->StartInputType(MiscServices::InputType::CAMERA_INPUT);
1647         inputMethod->ShowTextInput();
1648     }
1649     CloseSelectOverlay(true);
1650 #endif
1651 #endif
1652 }
1653 
1654 
StripNextLine(std::wstring & data)1655 void TextFieldPattern::StripNextLine(std::wstring& data)
1656 {
1657     CHECK_NULL_VOID(!(data.empty() || IsTextArea()));
1658     std::wstring result;
1659     bool dataChanged = false;
1660     int32_t dataPtr = 0;
1661     while (dataPtr < static_cast<int32_t>(data.length())) {
1662         if (data[dataPtr] != WIDE_NEWLINE[0]) {
1663             result += data[dataPtr];
1664         } else {
1665             dataChanged = true;
1666         }
1667         dataPtr++;
1668     }
1669     CHECK_NULL_VOID(dataChanged);
1670     data = result;
1671 }
1672 
HandleOnCut()1673 void TextFieldPattern::HandleOnCut()
1674 {
1675 #if !defined(PREVIEW)
1676     CHECK_NULL_VOID(clipboard_);
1677 #endif
1678     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1679     CHECK_NULL_VOID(layoutProperty);
1680 
1681     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) == CopyOptions::None) {
1682         return;
1683     }
1684     auto start = selectController_->GetStartIndex();
1685     auto end = selectController_->GetEndIndex();
1686     GetEmojiSubStringRange(start, end);
1687     SwapIfLarger(start, end);
1688     if (!IsSelected() || IsInPasswordMode()) {
1689         return;
1690     }
1691     auto selectedText = contentController_->GetSelectedValue(start, end);
1692     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) != CopyOptions::None) {
1693         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Cut value is %{private}s", selectedText.c_str());
1694         clipboard_->SetData(selectedText, layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed));
1695     }
1696     DeleteRange(start, end);
1697     auto host = GetHost();
1698     CHECK_NULL_VOID(host);
1699     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1700     CHECK_NULL_VOID(eventHub);
1701     eventHub->FireOnCut(selectedText);
1702     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
1703                                                                                  : PROPERTY_UPDATE_MEASURE);
1704 }
1705 
UpdateSelection(int32_t both)1706 void TextFieldPattern::UpdateSelection(int32_t both)
1707 {
1708     UpdateSelection(both, both);
1709 }
1710 
UpdateSelection(int32_t start,int32_t end)1711 void TextFieldPattern::UpdateSelection(int32_t start, int32_t end)
1712 {
1713     auto startIndex = std::min(start, end);
1714     auto endIndex = std::max(start, end);
1715     startIndex = std::clamp(startIndex, 0, static_cast<int32_t>(contentController_->GetWideText().length()));
1716     endIndex = std::clamp(endIndex, 0, static_cast<int32_t>(contentController_->GetWideText().length()));
1717     if (startIndex != selectController_->GetStartIndex() || endIndex != selectController_->GetEndIndex()) {
1718         selectController_->UpdateHandleIndex(startIndex, endIndex);
1719     }
1720 }
1721 
FireEventHubOnChange(const std::string & text)1722 void TextFieldPattern::FireEventHubOnChange(const std::string& text)
1723 {
1724     auto host = GetHost();
1725     CHECK_NULL_VOID(host);
1726     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1727     CHECK_NULL_VOID(layoutProperty);
1728     if (!layoutProperty->GetNeedFireOnChangeValue(false)) {
1729         return;
1730     }
1731     auto textFieldTheme = GetTheme();
1732     CHECK_NULL_VOID(textFieldTheme);
1733     auto visible = layoutProperty->GetShowErrorTextValue(false);
1734     if (!visible && IsUnderlineMode()) {
1735         underlineColor_ = userUnderlineColor_.typing.value_or(textFieldTheme->GetUnderlineTypingColor());
1736         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
1737     }
1738 
1739     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1740     CHECK_NULL_VOID(eventHub);
1741     ChangeValueInfo changeValueInfo;
1742     changeValueInfo.value = text;
1743     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
1744     changeValueInfo.previewText.value = GetPreviewTextValue();
1745     changeValueInfo.oldPreviewText = callbackOldPreviewText_;
1746     changeValueInfo.oldContent = callbackOldContent_;
1747     changeValueInfo.rangeBefore = callbackRangeBefore_;
1748     changeValueInfo.rangeAfter = callbackRangeAfter_;
1749     eventHub->FireOnChange(changeValueInfo);
1750 }
1751 
HandleTouchEvent(const TouchEventInfo & info)1752 void TextFieldPattern::HandleTouchEvent(const TouchEventInfo& info)
1753 {
1754     CHECK_NULL_VOID(!IsDragging());
1755     CHECK_NULL_VOID(!info.GetTouches().empty());
1756     if (selectOverlay_->IsTouchAtHandle(info)) {
1757         return;
1758     }
1759     auto touchInfo = GetAcceptedTouchLocationInfo(info);
1760     CHECK_NULL_VOID(touchInfo);
1761     DoGestureSelection(info);
1762     ResetOriginCaretPosition();
1763     auto touchType = touchInfo->GetTouchType();
1764     if (touchType == TouchType::DOWN) {
1765         HandleTouchDown(touchInfo->GetLocalLocation());
1766     } else if (touchType == TouchType::UP) {
1767         OnCaretMoveDone(info);
1768         RequestKeyboardAfterLongPress();
1769         isLongPress_ = false;
1770         isMoveCaretAnywhere_ = false;
1771         HandleTouchUp();
1772     } else if (touchType == TouchType::MOVE) {
1773         if (isMoveCaretAnywhere_) {
1774             // edit + longpress + move, show caret anywhere on fonts.
1775             selectController_->MoveCaretAnywhere(info.GetTouches().front().GetLocalLocation());
1776             ShowCaretAndStopTwinkling();
1777             selectOverlay_->HideMenu();
1778             selectOverlay_->SetIsSingleHandle(false);
1779             return;
1780         }
1781         if (SelectOverlayIsOn() && !moveCaretState_.isTouchCaret) {
1782             return;
1783         }
1784         if (!IsUsingMouse() && HasFocus()) {
1785             HandleTouchMove(touchInfo.value());
1786         }
1787     } else if (touchType == TouchType::CANCEL) {
1788         if (magnifierController_ && magnifierController_->GetMagnifierNodeExist()) {
1789             magnifierController_->RemoveMagnifierFrameNode();
1790         }
1791     }
1792 }
1793 
HandleTouchDown(const Offset & offset)1794 void TextFieldPattern::HandleTouchDown(const Offset& offset)
1795 {
1796     moveCaretState_.touchDownOffset = offset;
1797     if (HasStateStyle(UI_STATE_PRESSED)) {
1798         return;
1799     }
1800     if (enableTouchAndHoverEffect_ && !isMousePressed_) {
1801         auto lastCaretRect = selectController_->GetCaretRect();
1802         moveCaretState_.isTouchCaret = HasFocus() && !IsSelected() && RepeatClickCaret(offset, lastCaretRect);
1803         isTouchPreviewText_ = GetTouchInnerPreviewText(offset);
1804     }
1805 }
1806 
HandleTouchUp()1807 void TextFieldPattern::HandleTouchUp()
1808 {
1809     if (GetIsPreviewText() && isTouchPreviewText_) {
1810         StartTwinkling();
1811     }
1812     if (moveCaretState_.isTouchCaret) {
1813         moveCaretState_.isTouchCaret = false;
1814         CheckScrollable();
1815         StartTwinkling();
1816     }
1817     if (moveCaretState_.isMoveCaret) {
1818         moveCaretState_.isMoveCaret = false;
1819         if (HasFocus()) {
1820             StartTwinkling();
1821         } else {
1822             StopTwinkling();
1823         }
1824     }
1825     if (isMousePressed_) {
1826         isMousePressed_ = false;
1827     }
1828     if (magnifierController_) {
1829         magnifierController_->RemoveMagnifierFrameNode();
1830     }
1831     ScheduleDisappearDelayTask();
1832 }
1833 
HandleTouchMove(const TouchLocationInfo & info)1834 void TextFieldPattern::HandleTouchMove(const TouchLocationInfo& info)
1835 {
1836     if (moveCaretState_.isTouchCaret && !moveCaretState_.isMoveCaret) {
1837         auto offset = info.GetLocalLocation();
1838         auto moveDistance = (offset - moveCaretState_.touchDownOffset).GetDistance();
1839         moveCaretState_.isMoveCaret = GreatNotEqual(moveDistance, moveCaretState_.minDinstance.ConvertToPx());
1840         if (moveCaretState_.isMoveCaret) {
1841             moveCaretState_.touchFingerId = info.GetFingerId();
1842         }
1843     }
1844     if (SelectOverlayIsOn() && moveCaretState_.isMoveCaret) {
1845         CloseSelectOverlay(false);
1846     }
1847     if (moveCaretState_.isMoveCaret || (GetIsPreviewText() && isTouchPreviewText_)) {
1848         ShowCaretAndStopTwinkling();
1849         UpdateCaretByTouchMove(info);
1850     }
1851 }
1852 
StartVibratorByIndexChange(int32_t currentIndex,int32_t preIndex)1853 void TextFieldPattern::StartVibratorByIndexChange(int32_t currentIndex, int32_t preIndex)
1854 {
1855     CHECK_NULL_VOID(isEnableHapticFeedback_ && (currentIndex != preIndex));
1856     VibratorUtils::StartVibraFeedback("slide");
1857 }
1858 
UpdateCaretByTouchMove(const TouchLocationInfo & info)1859 void TextFieldPattern::UpdateCaretByTouchMove(const TouchLocationInfo& info)
1860 {
1861     scrollable_ = false;
1862     SetScrollEnabled(scrollable_);
1863     // limit move when preview text is shown
1864     auto touchOffset = info.GetLocalLocation();
1865     int32_t preCaretIndex = selectController_->GetCaretIndex();
1866     if (GetIsPreviewText()) {
1867         TAG_LOGI(ACE_TEXT_FIELD, "UpdateCaretByTouchMove when has previewText");
1868         float offsetY = IsTextArea() ? GetTextRect().GetY() : contentRect_.GetY();
1869         std::vector<RectF> previewTextRects = GetPreviewTextRects();
1870         if (previewTextRects.empty()) {
1871             TAG_LOGI(ACE_TEXT_FIELD, "preview text rect error");
1872             return;
1873         }
1874 
1875         double limitL;
1876         double limitR;
1877         double limitT = previewTextRects.front().Top() + offsetY + MINIMAL_OFFSET;
1878         double limitB = previewTextRects.back().Bottom() + offsetY - MINIMAL_OFFSET;
1879 
1880         Offset previewTextTouchOffset;
1881         CalculatePreviewingTextMovingLimit(touchOffset, limitL, limitR);
1882 
1883         previewTextTouchOffset.SetX(std::clamp(touchOffset.GetX(), limitL, limitR));
1884         previewTextTouchOffset.SetY(std::clamp(touchOffset.GetY(), limitT, limitB));
1885         selectController_->UpdateCaretInfoByOffset(previewTextTouchOffset);
1886         if (moveCaretState_.isMoveCaret) {
1887             StartVibratorByIndexChange(selectController_->GetCaretIndex(), preCaretIndex);
1888         }
1889     } else {
1890         selectController_->UpdateCaretInfoByOffset(touchOffset);
1891         if (magnifierController_) {
1892             magnifierController_->SetLocalOffset({ touchOffset.GetX(), touchOffset.GetY() });
1893         }
1894         StartVibratorByIndexChange(selectController_->GetCaretIndex(), preCaretIndex);
1895     }
1896 
1897     UpdateCaretInfoToController();
1898     auto host = GetHost();
1899     CHECK_NULL_VOID(host);
1900     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1901 }
1902 
InitDragEvent()1903 void TextFieldPattern::InitDragEvent()
1904 {
1905     auto host = GetHost();
1906     CHECK_NULL_VOID(host);
1907     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1908     CHECK_NULL_VOID(layoutProperty);
1909     if (!IsInPasswordMode() &&
1910         layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None && host->IsDraggable()) {
1911         InitDragDropEvent();
1912     } else {
1913         ClearDragDropEvent();
1914         InitDragDropEventWithOutDragStart();
1915     }
1916     AddDragFrameNodeToManager(host);
1917 }
1918 
GetThumbnailCallback()1919 std::function<void(Offset)> TextFieldPattern::GetThumbnailCallback()
1920 {
1921     auto callback = [weak = WeakClaim(this)](const Offset& point) {
1922         auto pattern = weak.Upgrade();
1923         CHECK_NULL_VOID(pattern);
1924         auto frameNode = pattern->GetHost();
1925         CHECK_NULL_VOID(frameNode);
1926         if (pattern->BetweenSelectedPosition(point)) {
1927             pattern->dragNode_ = TextDragPattern::CreateDragNode(frameNode);
1928             auto textDragPattern = pattern->dragNode_->GetPattern<TextDragPattern>();
1929             if (textDragPattern) {
1930                 auto option = pattern->GetHost()->GetDragPreviewOption();
1931                 option.options.shadowPath = textDragPattern->GetBackgroundPath()->ConvertToSVGString();
1932                 option.options.shadow = Shadow(RICH_DEFAULT_ELEVATION, {0.0, 0.0}, Color(RICH_DEFAULT_SHADOW_COLOR),
1933                     ShadowStyle::OuterFloatingSM);
1934                 pattern->GetHost()->SetDragPreviewOptions(option);
1935             }
1936             FrameNode::ProcessOffscreenNode(pattern->dragNode_);
1937         }
1938         auto gestureHub = frameNode->GetOrCreateGestureEventHub();
1939         CHECK_NULL_VOID(gestureHub);
1940         gestureHub->SetPixelMap(nullptr);
1941     };
1942     return callback;
1943 }
1944 
OnDragStart()1945 std::function<DragDropInfo(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragStart()
1946 {
1947     auto onDragStart = [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event,
1948                            const std::string& extraParams) -> NG::DragDropInfo {
1949         NG::DragDropInfo itemInfo;
1950         auto pattern = weakPtr.Upgrade();
1951         CHECK_NULL_RETURN(pattern, itemInfo);
1952         auto host = pattern->GetHost();
1953         CHECK_NULL_RETURN(host, itemInfo);
1954         auto hub = host->GetEventHub<EventHub>();
1955         CHECK_NULL_RETURN(hub, itemInfo);
1956         auto gestureHub = hub->GetOrCreateGestureEventHub();
1957         CHECK_NULL_RETURN(gestureHub, itemInfo);
1958         if (!gestureHub->GetIsTextDraggable()) {
1959             return itemInfo;
1960         }
1961         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
1962             "%{public}d TextField OnDragStart, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
1963             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
1964             static_cast<int32_t>(pattern->dragRecipientStatus_));
1965         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1966         CHECK_NULL_RETURN(layoutProperty, itemInfo);
1967 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
1968         pattern->CloseHandleAndSelect();
1969         pattern->CloseKeyboard(true);
1970 #endif
1971         pattern->dragStatus_ = DragStatus::DRAGGING;
1972         pattern->dragRecipientStatus_ = DragStatus::DRAGGING;
1973         pattern->showSelect_ = false;
1974         pattern->selectionMode_ = SelectionMode::SELECT;
1975         pattern->textFieldContentModifier_->ChangeDragStatus();
1976         auto contentController = pattern->contentController_;
1977         auto selectController = pattern->selectController_;
1978         auto start = selectController->GetStartIndex();
1979         auto end = selectController->GetEndIndex();
1980         pattern->GetEmojiSubStringRange(start, end);
1981         pattern->dragTextStart_ = start;
1982         pattern->dragTextEnd_ = end;
1983         std::string beforeStr = contentController->GetValueBeforeIndex(start);
1984         std::string selectedStr = contentController->GetSelectedValue(start, end);
1985         pattern->dragValue_ = selectedStr;
1986         std::string afterStr = contentController->GetValueAfterIndex(end);
1987         pattern->dragContents_ = { beforeStr, selectedStr, afterStr };
1988         itemInfo.extraInfo = selectedStr;
1989         RefPtr<UnifiedData> unifiedData = UdmfClient::GetInstance()->CreateUnifiedData();
1990         UdmfClient::GetInstance()->AddPlainTextRecord(unifiedData, selectedStr);
1991         event->SetData(unifiedData);
1992         host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
1993                                                                                      : PROPERTY_UPDATE_MEASURE);
1994         return itemInfo;
1995     };
1996     return onDragStart;
1997 }
1998 
OnDragDrop()1999 std::function<void(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragDrop()
2000 {
2001     return [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2002         auto pattern = weakPtr.Upgrade();
2003         CHECK_NULL_VOID(pattern);
2004         auto host = pattern->GetHost();
2005         CHECK_NULL_VOID(host);
2006         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2007         CHECK_NULL_VOID(layoutProperty);
2008 
2009         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2010             "%{public}d TextField OnDragDrop, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2011             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2012             static_cast<int32_t>(pattern->dragRecipientStatus_));
2013         if (layoutProperty->GetIsDisabledValue(false) || pattern->IsNormalInlineState() || !pattern->HasFocus()) {
2014             return;
2015         }
2016         if (extraParams.empty()) {
2017             pattern->dragStatus_ = DragStatus::ON_DROP;
2018             pattern->textFieldContentModifier_->ChangeDragStatus();
2019             host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
2020                                                                                          : PROPERTY_UPDATE_MEASURE);
2021             return;
2022         }
2023         auto data = event->GetData();
2024         CHECK_NULL_VOID(data);
2025         std::string str;
2026         auto arr = UdmfClient::GetInstance()->GetSpanStringRecord(data);
2027         if (arr.size() > 0) {
2028             auto spanStr = SpanString::DecodeTlv(arr);
2029             str += spanStr->GetString();
2030         } else {
2031             auto records = UdmfClient::GetInstance()->GetPlainTextRecords(data);
2032             if (records.empty()) {
2033                 std::string linkUrl;
2034                 std::string linkTitle;
2035                 UdmfClient::GetInstance()->GetLinkRecord(data, linkUrl, linkTitle);
2036                 if (!linkTitle.empty()) {
2037                     str += linkTitle;
2038                 } else if (!linkUrl.empty()) {
2039                     str += linkUrl;
2040                 }
2041             }
2042             for (const auto& record : records) {
2043                 str += record;
2044             }
2045         }
2046         pattern->dragRecipientStatus_ = DragStatus::NONE;
2047         if (str.empty()) {
2048             return;
2049         }
2050         if (pattern->dragStatus_ == DragStatus::NONE) {
2051             pattern->AddInsertCommand(str, InputReason::DRAG);
2052         } else {
2053             InputCommandInfo inputCommandInfo;
2054             inputCommandInfo.deleteRange = { pattern->dragTextStart_, pattern->dragTextEnd_ };
2055             inputCommandInfo.insertOffset = pattern->selectController_->GetCaretIndex();
2056             inputCommandInfo.insertValue = str;
2057             inputCommandInfo.reason = InputReason::DRAG;
2058             pattern->AddInputCommand(inputCommandInfo);
2059             pattern->dragStatus_ = DragStatus::NONE;
2060             pattern->MarkContentChange();
2061             host->MarkDirtyNode(pattern->IsTextArea() ? PROPERTY_UPDATE_MEASURE : PROPERTY_UPDATE_MEASURE_SELF);
2062         }
2063         FocusHub::LostFocusToViewRoot();
2064     };
2065 }
2066 
ShowSelectAfterDragEvent()2067 void TextFieldPattern::ShowSelectAfterDragEvent()
2068 {
2069     selectController_->UpdateHandleIndex(dragTextStart_, dragTextEnd_);
2070     showSelect_ = true;
2071     if (!IsUsingMouse()) {
2072         DelayProcessOverlay({ .menuIsShow = false });
2073     }
2074 }
2075 
InitDragDropEventWithOutDragStart()2076 void TextFieldPattern::InitDragDropEventWithOutDragStart()
2077 {
2078     auto host = GetHost();
2079     CHECK_NULL_VOID(host);
2080     auto gestureHub = host->GetOrCreateGestureEventHub();
2081     CHECK_NULL_VOID(gestureHub);
2082     gestureHub->InitDragDropEvent();
2083     auto eventHub = host->GetEventHub<EventHub>();
2084     CHECK_NULL_VOID(eventHub);
2085     InitDragDropCallBack();
2086 }
2087 
InitDragDropEvent()2088 void TextFieldPattern::InitDragDropEvent()
2089 {
2090     auto host = GetHost();
2091     CHECK_NULL_VOID(host);
2092     auto gestureHub = host->GetOrCreateGestureEventHub();
2093     CHECK_NULL_VOID(gestureHub);
2094     gestureHub->InitDragDropEvent();
2095     auto callback = GetThumbnailCallback();
2096     gestureHub->SetThumbnailCallback(std::move(callback));
2097     auto eventHub = host->GetEventHub<EventHub>();
2098     CHECK_NULL_VOID(eventHub);
2099     eventHub->SetDefaultOnDragStart(OnDragStart());
2100     InitDragDropCallBack();
2101     gestureHub->SetTextDraggable(true);
2102 }
2103 
InitDragDropCallBack()2104 void TextFieldPattern::InitDragDropCallBack()
2105 {
2106     auto host = GetHost();
2107     CHECK_NULL_VOID(host);
2108     auto eventHub = host->GetEventHub<EventHub>();
2109     CHECK_NULL_VOID(eventHub);
2110     auto onDragEnter = [weakPtr = WeakClaim(this)](
2111                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2112         auto pattern = weakPtr.Upgrade();
2113         CHECK_NULL_VOID(pattern);
2114         auto host = pattern->GetHost();
2115         CHECK_NULL_VOID(host);
2116         if (pattern->IsNormalInlineState()) {
2117             return;
2118         }
2119         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2120             "%{public}d TextField onDragEnter, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2121             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2122             static_cast<int32_t>(pattern->dragRecipientStatus_));
2123         pattern->dragRecipientStatus_ = DragStatus::DRAGGING;
2124         pattern->ResetPreviewTextState();
2125         auto pipeline = pattern->GetContext();
2126         CHECK_NULL_VOID(pipeline);
2127         auto dragManager = pipeline->GetDragDropManager();
2128         CHECK_NULL_VOID(dragManager);
2129         if (!dragManager->IsDropAllowed(host)) {
2130             return;
2131         }
2132         auto focusHub = pattern->GetFocusHub();
2133         CHECK_NULL_VOID(focusHub);
2134         if (focusHub->RequestFocusImmediately()) {
2135             pattern->StartTwinkling();
2136             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2137                 "%{public}d TextField onDragEnter Request Focus Success", host->GetId());
2138         }
2139     };
2140     eventHub->SetOnDragEnter(std::move(onDragEnter));
2141 
2142     auto onDragMove = [weakPtr = WeakClaim(this)](
2143                           const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2144         auto pattern = weakPtr.Upgrade();
2145         CHECK_NULL_VOID(pattern);
2146         auto pipeline = PipelineBase::GetCurrentContext();
2147         CHECK_NULL_VOID(pipeline);
2148         auto theme = pipeline->GetTheme<TextFieldTheme>();
2149         CHECK_NULL_VOID(theme);
2150         auto host = pattern->GetHost();
2151         CHECK_NULL_VOID(host);
2152 
2153         if (pattern->IsNormalInlineState()) {
2154             return;
2155         }
2156         if (!pattern->HasFocus()) {
2157             auto focusHub = pattern->GetFocusHub();
2158             CHECK_NULL_VOID(focusHub);
2159             if (focusHub->RequestFocusImmediately()) {
2160                 pattern->StartTwinkling();
2161                 TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2162                     "%{public}d TextField onDragMove Request Focus Success", host->GetId());
2163             }
2164         }
2165         auto touchX = event->GetX();
2166         auto touchY = event->GetY();
2167         Offset offset = Offset(touchX, touchY) - Offset(pattern->textRect_.GetX(), pattern->textRect_.GetY()) -
2168                         Offset(pattern->parentGlobalOffset_.GetX(), pattern->parentGlobalOffset_.GetY()) -
2169                         Offset(0, theme->GetInsertCursorOffset().ConvertToPx());
2170         auto position = pattern->ConvertTouchOffsetToCaretPosition(offset);
2171         pattern->SetCaretPosition(position);
2172     };
2173     eventHub->SetOnDragMove(std::move(onDragMove));
2174 
2175     auto onDragLeave = [weakPtr = WeakClaim(this)](
2176                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2177         auto pattern = weakPtr.Upgrade();
2178         CHECK_NULL_VOID(pattern);
2179         auto host = pattern->GetHost();
2180         CHECK_NULL_VOID(host);
2181         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2182             "%{public}d TextField onDragLeave, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2183             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2184             static_cast<int32_t>(pattern->dragRecipientStatus_));
2185         pattern->dragRecipientStatus_ = DragStatus::NONE;
2186         auto focusHub = pattern->GetFocusHub();
2187         CHECK_NULL_VOID(focusHub);
2188         focusHub->LostFocus();
2189         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2190             "%{public}d TextField onDragLeave Lost Focus", host->GetId());
2191         pattern->StopTwinkling();
2192     };
2193     eventHub->SetOnDragLeave(std::move(onDragLeave));
2194 
2195     auto onDragEnd = [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event) {
2196         auto pattern = weakPtr.Upgrade();
2197         CHECK_NULL_VOID(pattern);
2198         pattern->ScheduleDisappearDelayTask();
2199         ContainerScope scope(pattern->GetHostInstanceId());
2200         if (pattern->dragStatus_ == DragStatus::DRAGGING && !pattern->isDetachFromMainTree_) {
2201             pattern->dragStatus_ = DragStatus::NONE;
2202             pattern->MarkContentChange();
2203             auto host = pattern->GetHost();
2204             CHECK_NULL_VOID(host);
2205 
2206             // Except for DRAG_SUCCESS, all of rest need to show
2207             auto paintProperty = pattern->GetPaintProperty<TextFieldPaintProperty>();
2208             CHECK_NULL_VOID(paintProperty);
2209             auto newDragValue =
2210                 pattern->contentController_->GetSelectedValue(pattern->dragTextStart_, pattern->dragTextEnd_);
2211             auto focusHub = pattern->GetFocusHub();
2212             CHECK_NULL_VOID(focusHub);
2213             if (event != nullptr && event->GetResult() != DragRet::DRAG_SUCCESS &&
2214                 newDragValue == pattern->dragValue_ &&
2215                 paintProperty->GetInputStyleValue(InputStyle::DEFAULT) != InputStyle::INLINE &&
2216                 focusHub->IsFocusable()) {
2217                 pattern->ShowSelectAfterDragEvent();
2218                 pattern->TextFieldRequestFocus(RequestFocusReason::DRAG_END);
2219             }
2220             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2221         }
2222         FocusHub::LostFocusToViewRoot();
2223     };
2224     eventHub->SetOnDragEnd(std::move(onDragEnd));
2225 
2226     eventHub->SetOnDrop(OnDragDrop());
2227 }
2228 
ClearDragDropEvent()2229 void TextFieldPattern::ClearDragDropEvent()
2230 {
2231     auto host = GetHost();
2232     CHECK_NULL_VOID(host);
2233     auto gestureHub = host->GetOrCreateGestureEventHub();
2234     CHECK_NULL_VOID(gestureHub);
2235     gestureHub->SetTextDraggable(false);
2236     gestureHub->SetIsTextDraggable(false);
2237     auto eventHub = host->GetEventHub<EventHub>();
2238     CHECK_NULL_VOID(eventHub);
2239     eventHub->SetOnDragStart(nullptr);
2240     eventHub->SetDefaultOnDragStart(nullptr);
2241     eventHub->SetOnDragEnter(nullptr);
2242     eventHub->SetOnDragMove(nullptr);
2243     eventHub->SetOnDragLeave(nullptr);
2244     eventHub->SetOnDragEnd(nullptr);
2245     eventHub->SetOnDrop(nullptr);
2246 }
2247 
InitTouchEvent()2248 void TextFieldPattern::InitTouchEvent()
2249 {
2250     CHECK_NULL_VOID(!touchListener_);
2251     auto host = GetHost();
2252     CHECK_NULL_VOID(host);
2253 
2254     auto gesture = host->GetOrCreateGestureEventHub();
2255     CHECK_NULL_VOID(gesture);
2256     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
2257         auto pattern = weak.Upgrade();
2258         CHECK_NULL_VOID(pattern);
2259         pattern->selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
2260         pattern->selectOverlay_->SetLastSourceType(info.GetSourceDevice());
2261         pattern->HandleTouchEvent(info);
2262     };
2263     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
2264     gesture->AddTouchEvent(touchListener_);
2265 }
2266 
IsHandleDragging()2267 bool TextFieldPattern::IsHandleDragging()
2268 {
2269     CHECK_NULL_RETURN(selectOverlay_, false);
2270     return selectOverlay_->GetIsHandleDragging();
2271 }
2272 
InitClickEvent()2273 void TextFieldPattern::InitClickEvent()
2274 {
2275     CHECK_NULL_VOID(!clickListener_);
2276     auto tmpHost = GetHost();
2277     CHECK_NULL_VOID(tmpHost);
2278     auto gesture = tmpHost->GetOrCreateGestureEventHub();
2279     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
2280         auto pattern = weak.Upgrade();
2281         CHECK_NULL_VOID(pattern);
2282         pattern->HandleClickEvent(info);
2283     };
2284 
2285     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
2286     gesture->AddClickEvent(clickListener_);
2287 }
2288 
HandleClickEvent(GestureEvent & info)2289 void TextFieldPattern::HandleClickEvent(GestureEvent& info)
2290 {
2291     CHECK_NULL_VOID(!IsDragging());
2292     CHECK_NULL_VOID(!IsHandleDragging());
2293     parentGlobalOffset_ = GetPaintRectGlobalOffset();
2294     if (selectOverlay_->IsClickAtHandle(info) && !multipleClickRecognizer_->IsRunning()) {
2295         return;
2296     }
2297     auto focusHub = GetFocusHub();
2298     if (!focusHub->IsFocusable()) {
2299         return;
2300     }
2301     focusIndex_ = FocuseIndex::TEXT;
2302     auto firstGetFocus = false;
2303     if (!HasFocus()) {
2304         auto host = GetHost();
2305         CHECK_NULL_VOID(host);
2306         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d request focus currently", host->GetId());
2307         firstGetFocus = true;
2308         if (!focusHub->IsFocusOnTouch().value_or(true) || !TextFieldRequestFocus(RequestFocusReason::CLICK)) {
2309             CloseSelectOverlay(true);
2310             StopTwinkling();
2311             return;
2312         }
2313     }
2314     if (CheckMousePressedOverScrollBar(info)) {
2315         return;
2316     }
2317     selectOverlay_->SetLastSourceType(info.GetSourceDevice());
2318     selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
2319     lastClickTimeStamp_ = info.GetTimeStamp();
2320     multipleClickRecognizer_->Start(info);
2321     if (multipleClickRecognizer_->IsTripleClick()) {
2322         HandleTripleClickEvent(info);  // triple click event
2323     } else if (multipleClickRecognizer_->IsDoubleClick()) {
2324         HandleDoubleClickEvent(info); // 注册手势事件
2325     } else {
2326         HandleSingleClickEvent(info, firstGetFocus);
2327     }
2328     if (ResetObscureTickCountDown()) {
2329         auto host = GetHost();
2330         CHECK_NULL_VOID(host);
2331         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2332     }
2333     isFocusedBeforeClick_ = false;
2334 }
2335 
CheckMousePressedOverScrollBar(GestureEvent & info)2336 bool TextFieldPattern::CheckMousePressedOverScrollBar(GestureEvent& info)
2337 {
2338     if (IsMouseOverScrollBar(info) && hasMousePressed_) {
2339         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2340         CHECK_NULL_RETURN(layoutProperty, false);
2341         if (layoutProperty->GetDisplayModeValue(DisplayMode::AUTO) != DisplayMode::OFF) {
2342             Point point(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY());
2343             bool reverse = false;
2344             if (GetScrollBar()->AnalysisUpOrDown(point, reverse)) {
2345                 ScrollPage(reverse);
2346             }
2347             return true;
2348         }
2349     }
2350     return false;
2351 }
2352 
HandleBetweenSelectedPosition(const GestureEvent & info)2353 bool TextFieldPattern::HandleBetweenSelectedPosition(const GestureEvent& info)
2354 {
2355     if (!IsUsingMouse() && SelectOverlayIsOn() && BetweenSelectedPosition(info.GetGlobalLocation())) {
2356         // click selected area to switch show/hide state
2357         selectOverlay_->ToggleMenu();
2358         return true;
2359     }
2360     return false;
2361 }
2362 
HandleSingleClickEvent(GestureEvent & info,bool firstGetFocus)2363 void TextFieldPattern::HandleSingleClickEvent(GestureEvent& info, bool firstGetFocus)
2364 {
2365     if (mouseStatus_ != MouseStatus::NONE && IsNormalInlineState()) {
2366         return;
2367     }
2368     if (HandleBetweenSelectedPosition(info)) {
2369         selectOverlay_->SwitchToOverlayMode();
2370         return;
2371     }
2372     auto host = GetHost();
2373     CHECK_NULL_VOID(host);
2374     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2375     auto lastCaretIndex = selectController_->GetCaretIndex();
2376     if (mouseStatus_ != MouseStatus::MOVE) {
2377         UpdateCaretByClick(info.GetLocalLocation());
2378         UpdateCaretInfoToController();
2379     }
2380     StartTwinkling();
2381     SetIsSingleHandle(true);
2382     bool needCloseOverlay = true;
2383     bool isRepeatClickCaret =
2384         RepeatClickCaret(info.GetLocalLocation(), lastCaretIndex) && !firstGetFocus;
2385     bool isInlineSelectAllOrEmpty = inlineSelectAllFlag_ || contentController_->IsEmpty();
2386     auto clickBlank = contentController_->IsEmpty() || selectController_->IsTouchAtLineEnd(info.GetLocalLocation());
2387     auto closeHandleAtBlank =
2388         clickBlank && isRepeatClickCaret && SelectOverlayIsOn() && selectOverlay_->IsSingleHandle();
2389     do {
2390         if (info.GetSourceDevice() == SourceType::MOUSE || (!isRepeatClickCaret && isInlineSelectAllOrEmpty) ||
2391             IsContentRectNonPositive() || closeHandleAtBlank) {
2392             break;
2393         }
2394         if (isRepeatClickCaret) {
2395             if (IsAccessibilityClick()) {
2396                 break;
2397             }
2398             StopTwinkling();
2399             ProcessOverlay({ .animation = true });
2400             needCloseOverlay = false;
2401         } else if (needSelectAll_) {
2402             HandleOnSelectAll(false);
2403         }
2404     } while (false);
2405     if (needCloseOverlay || GetIsPreviewText()) {
2406         CloseSelectOverlay(true);
2407     }
2408     DoProcessAutoFill();
2409     // emulate clicking bottom of the textField
2410     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
2411     TriggerAvoidOnCaretChange();
2412     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2413 }
2414 
DoProcessAutoFill()2415 void TextFieldPattern::DoProcessAutoFill()
2416 {
2417     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "DoProcessAutoFill");
2418     if (!IsNeedProcessAutoFill()) {
2419         if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SINGLE_CLICK)) {
2420             NotifyOnEditChanged(true);
2421         }
2422         return;
2423     }
2424     bool isPopup = false;
2425     auto isSuccess = ProcessAutoFill(isPopup);
2426     if (!isPopup && isSuccess) {
2427         needToRequestKeyboardInner_ = false;
2428     } else if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SINGLE_CLICK)) {
2429         NotifyOnEditChanged(true);
2430     }
2431 }
2432 
IsAutoFillPasswordType(const AceAutoFillType & autoFillType)2433 bool TextFieldPattern::IsAutoFillPasswordType(const AceAutoFillType& autoFillType)
2434 {
2435     return (autoFillType == AceAutoFillType::ACE_USER_NAME || autoFillType == AceAutoFillType::ACE_PASSWORD ||
2436             autoFillType == AceAutoFillType::ACE_NEW_PASSWORD);
2437 }
2438 
GetHintType()2439 HintToTypeWrap TextFieldPattern::GetHintType()
2440 {
2441     HintToTypeWrap hintToTypeWrap;
2442     auto container = Container::Current();
2443     CHECK_NULL_RETURN(container, hintToTypeWrap);
2444     auto onePlaceHolder = GetPlaceHolder();
2445     if (onePlaceHolder.empty()) {
2446         return hintToTypeWrap;
2447     }
2448     return container->PlaceHolderToType(onePlaceHolder);
2449 }
2450 
CheckAutoFillType(const AceAutoFillType & autoFillType,bool isFromKeyBoard)2451 bool TextFieldPattern::CheckAutoFillType(const AceAutoFillType& autoFillType, bool isFromKeyBoard)
2452 {
2453     if (isFromKeyBoard) {
2454         return true;
2455     }
2456 
2457     auto container = Container::Current();
2458     CHECK_NULL_RETURN(container, false);
2459     auto isTriggerPassword = IsTriggerAutoFillPassword();
2460     if (autoFillType == AceAutoFillType::ACE_UNSPECIFIED && !isTriggerPassword) {
2461         TAG_LOGE(AceLogTag::ACE_AUTO_FILL, "CheckAutoFillType :autoFillType is ACE_UNSPECIFIED.");
2462         return false;
2463     } else if (isTriggerPassword) {
2464         auto tempAutoFillType = IsAutoFillUserName(autoFillType) ? AceAutoFillType::ACE_USER_NAME : autoFillType;
2465         if (!container->IsNeedToCreatePopupWindow(tempAutoFillType)) {
2466             return GetAutoFillTriggeredStateByType(autoFillType);
2467         }
2468     }
2469     return true;
2470 }
2471 
GetAutoFillTriggeredStateByType(const AceAutoFillType & autoFillType)2472 bool TextFieldPattern::GetAutoFillTriggeredStateByType(const AceAutoFillType& autoFillType)
2473 {
2474     auto host = GetHost();
2475     CHECK_NULL_RETURN(host, false);
2476     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
2477     CHECK_NULL_RETURN(autoFillContainerNode, false);
2478     auto stateHolder = autoFillContainerNode->GetPattern<AutoFillTriggerStateHolder>();
2479     CHECK_NULL_RETURN(stateHolder, false);
2480     if (IsAutoFillUserName(autoFillType) || autoFillType == AceAutoFillType::ACE_PASSWORD) {
2481         return !stateHolder->IsAutoFillPasswordTriggered();
2482     }
2483     if (autoFillType == AceAutoFillType::ACE_NEW_PASSWORD) {
2484         return !stateHolder->IsAutoFillNewPasswordTriggered();
2485     }
2486     return false;
2487 }
2488 
SetAutoFillTriggeredStateByType(const AceAutoFillType & autoFillType)2489 void TextFieldPattern::SetAutoFillTriggeredStateByType(const AceAutoFillType& autoFillType)
2490 {
2491     auto host = GetHost();
2492     CHECK_NULL_VOID(host);
2493     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
2494     CHECK_NULL_VOID(autoFillContainerNode);
2495     auto stateHolder = autoFillContainerNode->GetPattern<AutoFillTriggerStateHolder>();
2496     CHECK_NULL_VOID(stateHolder);
2497     if (IsAutoFillUserName(autoFillType) || autoFillType == AceAutoFillType::ACE_PASSWORD) {
2498         stateHolder->SetAutoFillPasswordTriggered(true);
2499     } else if (autoFillType == AceAutoFillType::ACE_NEW_PASSWORD) {
2500         stateHolder->SetAutoFillNewPasswordTriggered(true);
2501     }
2502 }
2503 
GetAutoFillType(bool isNeedToHitType)2504 AceAutoFillType TextFieldPattern::GetAutoFillType(bool isNeedToHitType)
2505 {
2506     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2507     CHECK_NULL_RETURN(layoutProperty, AceAutoFillType::ACE_UNSPECIFIED);
2508     auto aceContentType =
2509         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
2510     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2511     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
2512         return aceContentType;
2513     }
2514     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
2515         return aceInputType;
2516     }
2517     if (isNeedToHitType && !IsTriggerAutoFillPassword()) {
2518         auto hintToTypeWrap = GetHintType();
2519         return hintToTypeWrap.autoFillType;
2520     }
2521     return AceAutoFillType::ACE_UNSPECIFIED;
2522 }
2523 
GetAutoFillTypeAndMetaData(bool isNeedToHitType)2524 HintToTypeWrap TextFieldPattern::GetAutoFillTypeAndMetaData(bool isNeedToHitType)
2525 {
2526     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2527     HintToTypeWrap hintToTypeWrap;
2528     CHECK_NULL_RETURN(layoutProperty, hintToTypeWrap);
2529     auto aceContentType =
2530         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
2531     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2532     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
2533         hintToTypeWrap.autoFillType = aceContentType;
2534         return hintToTypeWrap;
2535     }
2536     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
2537         hintToTypeWrap.autoFillType = aceInputType;
2538         return hintToTypeWrap;
2539     }
2540     if (isNeedToHitType && !IsTriggerAutoFillPassword()) {
2541         hintToTypeWrap = GetHintType();
2542         return hintToTypeWrap;
2543     }
2544     auto jsonValue = JsonUtil::Create(true);
2545     jsonValue->Put("type", TextInputTypeToString().c_str());
2546     hintToTypeWrap.metadata = jsonValue->ToString();
2547     return hintToTypeWrap;
2548 }
2549 
CheckAutoFill(bool isFromKeyBoard)2550 bool TextFieldPattern::CheckAutoFill(bool isFromKeyBoard)
2551 {
2552     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2553     CHECK_NULL_RETURN(layoutProperty, false);
2554     bool isEnableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
2555     if (!isEnableAutoFill) {
2556         return false;
2557     }
2558     return CheckAutoFillType(GetAutoFillType(), isFromKeyBoard);
2559 }
2560 
ProcessAutoFill(bool & isPopup,bool isFromKeyBoard,bool isNewPassWord)2561 bool TextFieldPattern::ProcessAutoFill(bool& isPopup, bool isFromKeyBoard, bool isNewPassWord)
2562 {
2563     if (!CheckAutoFill(isFromKeyBoard)) {
2564         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "No need to auto fill.");
2565         return false;
2566     }
2567     auto host = GetHost();
2568     CHECK_NULL_RETURN(host, false);
2569     auto autoFillType = GetAutoFillType();
2570     auto container = Container::Current();
2571     if (container == nullptr) {
2572         TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "Get current container is nullptr.");
2573         return false;
2574     }
2575     SetAutoFillTriggeredStateByType(autoFillType);
2576     SetFillRequestFinish(false);
2577     if (IsTriggerAutoFillPassword() && autoFillType == AceAutoFillType::ACE_UNSPECIFIED) {
2578         autoFillType = AceAutoFillType::ACE_USER_NAME;
2579     }
2580     return (container->RequestAutoFill(host, autoFillType, isNewPassWord, isPopup, autoFillSessionId_));
2581 }
2582 
HandleDoubleClickEvent(GestureEvent & info)2583 void TextFieldPattern::HandleDoubleClickEvent(GestureEvent& info)
2584 {
2585     if (GetIsPreviewText()) {
2586         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "refuse double click when has preview text.");
2587         return;
2588     }
2589 
2590     if (showSelect_) {
2591         SetIsSingleHandle(true);
2592     }
2593     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::DOUBLE_CLICK)) {
2594         NotifyOnEditChanged(true);
2595     }
2596     if (CanChangeSelectState()) {
2597         selectController_->UpdateSelectByOffset(info.GetLocalLocation());
2598     }
2599     if (IsSelected()) {
2600         StopTwinkling();
2601         SetIsSingleHandle(false);
2602     }
2603     if (info.GetSourceDevice() != SourceType::MOUSE && !IsContentRectNonPositive()) {
2604         ProcessOverlay({ .animation = true });
2605     }
2606     auto host = GetHost();
2607     CHECK_NULL_VOID(host);
2608     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2609 }
2610 
HandleTripleClickEvent(GestureEvent & info)2611 void TextFieldPattern::HandleTripleClickEvent(GestureEvent& info)
2612 {
2613     if (GetIsPreviewText()) {
2614         return;
2615     }
2616 
2617     if (showSelect_) {
2618         SetIsSingleHandle(true);
2619         CloseSelectOverlay();
2620     }
2621     if (CanChangeSelectState()) {
2622         selectController_->UpdateSelectPragraphByOffset(info.GetLocalLocation());
2623     }
2624     if (IsSelected()) {
2625         StopTwinkling();
2626         SetIsSingleHandle(false);
2627     }
2628     if (info.GetSourceDevice() != SourceType::MOUSE && !contentController_->IsEmpty() && !IsContentRectNonPositive()) {
2629         ProcessOverlay({ .animation = true });
2630     }
2631     auto host = GetHost();
2632     CHECK_NULL_VOID(host);
2633     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2634 }
2635 
ScheduleCursorTwinkling()2636 void TextFieldPattern::ScheduleCursorTwinkling()
2637 {
2638     if (isTransparent_) {
2639         return;
2640     }
2641     auto context = PipelineContext::GetCurrentContext();
2642     CHECK_NULL_VOID(context);
2643 
2644     if (!context->GetTaskExecutor()) {
2645         return;
2646     }
2647 
2648     if (dragRecipientStatus_ == DragStatus::DRAGGING) {
2649         return;
2650     }
2651 
2652     auto weak = WeakClaim(this);
2653     cursorTwinklingTask_.Reset([weak] {
2654         auto client = weak.Upgrade();
2655         CHECK_NULL_VOID(client);
2656         client->OnCursorTwinkling();
2657     });
2658     auto taskExecutor = context->GetTaskExecutor();
2659     CHECK_NULL_VOID(taskExecutor);
2660     taskExecutor->PostDelayedTask(cursorTwinklingTask_, TaskExecutor::TaskType::UI, twinklingInterval_,
2661         "ArkUITextFieldCursorTwinkling");
2662 }
2663 
StartTwinkling()2664 void TextFieldPattern::StartTwinkling()
2665 {
2666     if (isTransparent_ || !HasFocus()) {
2667         return;
2668     }
2669     // Ignore the result because all ops are called on this same thread (ACE UI).
2670     // The only reason failed is that the task has finished.
2671     cursorTwinklingTask_.Cancel();
2672 
2673     // Show cursor right now.
2674     isCaretTwinkling_ = true;
2675     cursorVisible_ = true;
2676     auto tmpHost = GetHost();
2677     CHECK_NULL_VOID(tmpHost);
2678     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2679     ScheduleCursorTwinkling();
2680 }
2681 
OnCursorTwinkling()2682 void TextFieldPattern::OnCursorTwinkling()
2683 {
2684     cursorTwinklingTask_.Cancel();
2685     cursorVisible_ = !cursorVisible_;
2686     auto shouldMeasure = !IsTextArea() && IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ == 1;
2687     if (IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ > 0) {
2688         --obscureTickCountDown_;
2689     }
2690     auto host = GetHost();
2691     CHECK_NULL_VOID(host);
2692     if (shouldMeasure) {
2693         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2694     } else {
2695         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2696     }
2697     ScheduleCursorTwinkling();
2698 }
2699 
StopTwinkling()2700 void TextFieldPattern::StopTwinkling()
2701 {
2702     cursorTwinklingTask_.Cancel();
2703 
2704     // Repaint only if cursor is visible for now.
2705     isCaretTwinkling_ = false;
2706     if (cursorVisible_) {
2707         cursorVisible_ = false;
2708         GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2709     }
2710     if (ResetObscureTickCountDown()) {
2711         GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2712     }
2713     caretStatus_ = CaretStatus::HIDE;
2714 }
2715 
ShowCaretAndStopTwinkling()2716 void TextFieldPattern::ShowCaretAndStopTwinkling()
2717 {
2718     cursorTwinklingTask_.Cancel();
2719 
2720     // Repaint and make cursor visible.
2721     isCaretTwinkling_ = false;
2722     auto tmpHost = GetHost();
2723     CHECK_NULL_VOID(tmpHost);
2724     cursorVisible_ = true;
2725     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2726     if (ResetObscureTickCountDown()) {
2727         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2728     }
2729 }
2730 
CheckIfNeedToResetKeyboard()2731 void TextFieldPattern::CheckIfNeedToResetKeyboard()
2732 {
2733     auto tmpHost = GetHost();
2734     CHECK_NULL_VOID(tmpHost);
2735     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
2736     CHECK_NULL_VOID(layoutProperty);
2737     bool needToResetKeyboard = false;
2738     // check unspecified  for first time entrance
2739     if (keyboard_ != layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
2740         auto autoFillType = GetAutoFillType(false);
2741         if (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) != TextInputType::UNSPECIFIED ||
2742             keyBoardMap_.find(autoFillType) == keyBoardMap_.end() || keyboard_ != keyBoardMap_[autoFillType]) {
2743             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Keyboard type %{public}d changed to %{public}d",
2744                 tmpHost->GetId(), (int)keyboard_, layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2745             keyboard_ = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
2746             ResetPreviewTextState();
2747             needToResetKeyboard = true;
2748         }
2749     }
2750     if (!needToResetKeyboard && action_ != TextInputAction::UNSPECIFIED) {
2751         needToResetKeyboard = action_ != GetTextInputActionValue(GetDefaultTextInputAction());
2752     }
2753     action_ = GetTextInputActionValue(GetDefaultTextInputAction());
2754 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
2755     if (needToResetKeyboard && HasFocus()) {
2756         if (isCustomKeyboardAttached_) {
2757             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::RESET_KEYBOARD);
2758             return;
2759         }
2760 #if defined(ENABLE_STANDARD_INPUT)
2761         auto inputMethod = MiscServices::InputMethodController::GetInstance();
2762         CHECK_NULL_VOID(inputMethod);
2763         MiscServices::Configuration config;
2764         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Keyboard action is %{public}d",
2765             tmpHost->GetId(), action_);
2766         config.SetEnterKeyType(static_cast<MiscServices::EnterKeyType>(action_));
2767         config.SetTextInputType(static_cast<MiscServices::TextInputType>(keyboard_));
2768         inputMethod->OnConfigurationChange(config);
2769 #endif
2770     }
2771 #else
2772     if (needToResetKeyboard && HasConnection()) {
2773         CloseKeyboard(true);
2774         RequestKeyboard(false, true, true);
2775     }
2776 #endif
2777 }
2778 
ProcessScroll()2779 void TextFieldPattern::ProcessScroll()
2780 {
2781     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2782     CHECK_NULL_VOID(layoutProperty);
2783     if (IsTextArea() || IsNormalInlineState()) {
2784         SetAxis(Axis::VERTICAL);
2785         if (!GetScrollableEvent()) {
2786             AddScrollEvent();
2787         }
2788         auto barState = layoutProperty->GetDisplayModeValue(DisplayMode::AUTO);
2789         if (!barState_.has_value()) {
2790             barState_ = barState;
2791         }
2792         scrollBarVisible_ = barState != DisplayMode::OFF;
2793         SetScrollBar(barState == DisplayMode::OFF ? DisplayMode::ON : barState);
2794         auto scrollBar = GetScrollBar();
2795         if (scrollBar) {
2796             scrollBar->SetMinHeight(SCROLL_BAR_MIN_HEIGHT);
2797         }
2798         if (textFieldOverlayModifier_) {
2799             textFieldOverlayModifier_->SetScrollBar(scrollBar);
2800             UpdateScrollBarOffset();
2801         }
2802     } else {
2803         SetAxis(Axis::HORIZONTAL);
2804         SetScrollBar(DisplayMode::OFF);
2805         if (!GetScrollableEvent()) {
2806             AddScrollEvent();
2807             SetScrollEnabled(false);
2808         }
2809     }
2810 }
2811 
HandleDeleteOnCounterScene()2812 void TextFieldPattern::HandleDeleteOnCounterScene()
2813 {
2814     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2815     CHECK_NULL_VOID(layoutProperty);
2816     if (layoutProperty->HasMaxLength()) {
2817         showCountBorderStyle_ = false;
2818         HandleCountStyle();
2819     }
2820 }
2821 
HandleCountStyle()2822 void TextFieldPattern::HandleCountStyle()
2823 {
2824     bool noDeleteOperation = deleteBackwardOperations_.empty() && deleteForwardOperations_.empty();
2825     if (!IsShowCount() || !noDeleteOperation) {
2826         return;
2827     }
2828     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2829     CHECK_NULL_VOID(layoutProperty);
2830     auto inputValue = layoutProperty->GetSetCounterValue(DEFAULT_MODE);
2831     if (inputValue == DEFAULT_MODE) {
2832         HandleCounterBorder();
2833     } else if (inputValue != ILLEGAL_VALUE) {
2834         auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
2835         if (showBorder) {
2836             HandleCounterBorder();
2837         }
2838         if (showCountBorderStyle_) {
2839             UltralimitShake();
2840         }
2841     }
2842 }
2843 
ProcessUnderlineColorOnModifierDone()2844 void TextFieldPattern::ProcessUnderlineColorOnModifierDone()
2845 {
2846     if (IsShowError()) {
2847         return;
2848     }
2849     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2850     auto inputValue = layoutProperty->GetSetCounterValue(DEFAULT_MODE);
2851     if (inputValue == ILLEGAL_VALUE) {
2852         return;
2853     }
2854     auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
2855     if (inputValue != DEFAULT_MODE && !showBorder) {
2856         return;
2857     }
2858     if (showCountBorderStyle_ && IsUnderlineMode() && HasFocus()) {
2859         auto theme = GetTheme();
2860         CHECK_NULL_VOID(theme);
2861         SetUnderlineColor(
2862             userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor()));
2863     }
2864 }
2865 
ProcessCounter()2866 void TextFieldPattern::ProcessCounter()
2867 {
2868     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2869     CHECK_NULL_VOID(layoutProperty);
2870     if (IsShowCount()) {
2871         AddCounterNode();
2872     } else {
2873         CleanCounterNode();
2874     }
2875     UpdateCounterMargin();
2876 }
2877 
ProcessSelection()2878 void TextFieldPattern::ProcessSelection()
2879 {
2880     auto textWidth = static_cast<int32_t>(contentController_->GetWideText().length());
2881     if (SelectOverlayIsOn()) {
2882         needToRefreshSelectOverlay_ = textWidth > 0;
2883         UpdateSelection(std::clamp(selectController_->GetStartIndex(), 0, textWidth),
2884             std::clamp(selectController_->GetEndIndex(), 0, textWidth));
2885         SetIsSingleHandle(!IsSelected());
2886         if (isTextChangedAtCreation_ && textWidth == 0) {
2887             CloseSelectOverlay();
2888             StartTwinkling();
2889         }
2890     } else if (HasFocus() && !IsSelected()) {
2891         StartTwinkling();
2892     } else {
2893         needToRefreshSelectOverlay_ = false;
2894     }
2895 }
2896 
OnModifyDone()2897 void TextFieldPattern::OnModifyDone()
2898 {
2899     Pattern::OnModifyDone();
2900     auto host = GetHost();
2901     CHECK_NULL_VOID(host);
2902     auto context = host->GetContext();
2903     CHECK_NULL_VOID(context);
2904     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2905     CHECK_NULL_VOID(layoutProperty);
2906     auto textFieldTheme = GetTheme();
2907     CHECK_NULL_VOID(textFieldTheme);
2908     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
2909     CHECK_NULL_VOID(paintProperty);
2910     CheckIfNeedToResetKeyboard();
2911     auto renderContext = host->GetRenderContext();
2912     CHECK_NULL_VOID(renderContext);
2913     isTransparent_ = renderContext->GetOpacityValue(1.0f) == 0.0f;
2914     ApplyNormalTheme();
2915     ApplyUnderlineTheme();
2916     ApplyInlineTheme();
2917     ProcessInnerPadding();
2918     ProcessNumberOfLines();
2919 
2920     InitClickEvent();
2921     InitLongPressEvent();
2922     InitFocusEvent();
2923     InitMouseEvent();
2924     InitTouchEvent();
2925 
2926     SetAccessibilityAction();
2927     FilterInitializeText();
2928     InitDisableColor();
2929     ProcessResponseArea();
2930     if (!shiftFlag_) {
2931         InitDragEvent();
2932     }
2933     Register2DragDropManager();
2934     context->AddOnAreaChangeNode(host->GetId());
2935     ProcessUnderlineColorOnModifierDone();
2936     if (!clipboard_ && context) {
2937         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
2938     }
2939     if (barState_.has_value() && barState_.value() != layoutProperty->GetDisplayModeValue(DisplayMode::AUTO) &&
2940         HasFocus() && IsNormalInlineState()) {
2941         lastTextRectY_ = textRect_.GetY();
2942     }
2943     if (!IsDisabled() && IsShowError()) {
2944         SetShowError();
2945     } else {
2946         CleanErrorNode();
2947     }
2948     // The textRect position can't be changed by only redraw.
2949     if (CheckNeedMeasure(layoutProperty->GetPropertyChangeFlag()) && !HasInputOperation() &&
2950         (!HasFocus() || !initTextRect_) && isTextChangedAtCreation_) {
2951         auto border = GetBorderWidthProperty();
2952         textRect_.SetLeft(GetPaddingLeft() + GetBorderLeft(border));
2953         textRect_.SetTop(GetPaddingTop() + GetBorderTop(border));
2954         initTextRect_ = true;
2955     }
2956     CalculateDefaultCursor();
2957 
2958     ProcessSelection();
2959     isTextChangedAtCreation_ = false;
2960     if (layoutProperty->GetTypeChangedValue(false)) {
2961         layoutProperty->ResetTypeChanged();
2962         operationRecords_.clear();
2963         redoOperationRecords_.clear();
2964     }
2965     ProcessScroll();
2966     ProcessCounter();
2967     Register2DragDropManager();
2968     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
2969     if (autoFillContainerNode) {
2970         UpdateTextFieldInfo();
2971     }
2972     TriggerAvoidWhenCaretGoesDown();
2973     selectOverlay_->SetMenuTranslateIsSupport(IsShowTranslate());
2974     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2975     isModifyDone_ = true;
2976 }
2977 
TriggerAvoidWhenCaretGoesDown()2978 void TextFieldPattern::TriggerAvoidWhenCaretGoesDown()
2979 {
2980     auto host = GetHost();
2981     CHECK_NULL_VOID(host);
2982     auto context = host->GetContext();
2983     CHECK_NULL_VOID(context);
2984     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
2985     if (context->UsingCaretAvoidMode() && HasFocus() && textFieldManager) {
2986         context->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
2987             auto textField = weak.Upgrade();
2988             CHECK_NULL_VOID(textField);
2989             auto textFieldManager = manager.Upgrade();
2990             CHECK_NULL_VOID(textFieldManager);
2991             auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
2992             if (caretPos > textField->GetLastCaretPos()) {
2993                 TAG_LOGI(ACE_KEYBOARD, "Caret Position Goes Down, Retrigger Avoid");
2994                 textField->TriggerAvoidOnCaretChange();
2995             }
2996         });
2997     }
2998 }
2999 
ApplyNormalTheme()3000 void TextFieldPattern::ApplyNormalTheme()
3001 {
3002     if (IsUnderlineMode() || IsInlineMode()) {
3003         return;
3004     }
3005     SetThemeAttr();
3006 }
3007 
OnAfterModifyDone()3008 void TextFieldPattern::OnAfterModifyDone()
3009 {
3010     auto host = GetHost();
3011     CHECK_NULL_VOID(host);
3012     auto inspectorId = host->GetInspectorId().value_or("");
3013     if (!inspectorId.empty()) {
3014         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3015         bool isPwdType = false;
3016         if (layoutProperty) {
3017             auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
3018             isPwdType = inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
3019                         inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
3020         }
3021         if (!isPwdType) {
3022             Recorder::NodeDataCache::Get().PutString(host, inspectorId, contentController_->GetTextValue());
3023         }
3024     }
3025 }
3026 
CalculateDefaultCursor()3027 void TextFieldPattern::CalculateDefaultCursor()
3028 {
3029     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
3030     CHECK_NULL_VOID(layoutProperty);
3031     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
3032     CHECK_NULL_VOID(paintProperty);
3033     auto textFieldTheme = GetTheme();
3034     CHECK_NULL_VOID(textFieldTheme);
3035     float caretWidth = paintProperty->GetCursorWidth().has_value()
3036                            ? static_cast<float>(paintProperty->GetCursorWidthValue().ConvertToPx())
3037                            : static_cast<float>(textFieldTheme->GetCursorWidth().ConvertToPx());
3038     selectController_->UpdateCaretWidth(caretWidth);
3039     if (!contentController_->IsEmpty()) {
3040         return;
3041     }
3042     selectController_->UpdateCaretHeight(PreferredLineHeight());
3043 }
3044 
AutoFillValueChanged()3045 void TextFieldPattern::AutoFillValueChanged()
3046 {
3047     if (IsFillRequestFinish()) {
3048         return;
3049     }
3050     auto host = GetHost();
3051     CHECK_NULL_VOID(host);
3052     auto aceContentType = GetAutoFillType();
3053     auto container = Container::Current();
3054     CHECK_NULL_VOID(container);
3055     if (aceContentType >= AceAutoFillType::ACE_PASSWORD && aceContentType <= AceAutoFillType::ACE_FORMAT_ADDRESS
3056         && CheckAutoFill()) {
3057         container->UpdatePopupUIExtension(host, autoFillSessionId_);
3058     }
3059 }
3060 
FireOnTextChangeEvent()3061 bool TextFieldPattern::FireOnTextChangeEvent()
3062 {
3063     auto host = GetHost();
3064     CHECK_NULL_RETURN(host, false);
3065     auto eventHub = host->GetEventHub<TextFieldEventHub>();
3066     CHECK_NULL_RETURN(eventHub, false);
3067     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3068     CHECK_NULL_RETURN(layoutProperty, false);
3069     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
3070     if (cleanNodeStyle == CleanNodeStyle::INPUT) {
3071         auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
3072         if (cleanNodeResponseArea && contentController_->IsEmpty() && cleanNodeResponseArea->IsShow()) {
3073             cleanNodeResponseArea->UpdateCleanNode(false);
3074         } else if (cleanNodeResponseArea && !contentController_->IsEmpty() && !cleanNodeResponseArea->IsShow()) {
3075             cleanNodeResponseArea->UpdateCleanNode(true);
3076         }
3077     }
3078     auto textCache = layoutProperty->GetValueValue("");
3079     auto previewTextCache = layoutProperty->GetPreviewTextValue({GetPreviewTextStart(), ""});
3080     PreviewText curPreviewText = {GetPreviewTextStart(), GetPreviewTextValue()};
3081     if (textCache == contentController_->GetTextValue() && previewTextCache.value == curPreviewText.value) {
3082         return false;
3083     }
3084     ResetOriginCaretPosition();
3085     host->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, textCache, contentController_->GetTextValue());
3086     AutoFillValueChanged();
3087     auto pipeline = GetContext();
3088     CHECK_NULL_RETURN(pipeline, false);
3089     AddTextFireOnChange();
3090     auto context = host->GetContextRefPtr();
3091     CHECK_NULL_RETURN(context, false);
3092     auto taskExecutor = context->GetTaskExecutor();
3093     CHECK_NULL_RETURN(taskExecutor, false);
3094     taskExecutor->PostTask(
3095         [weak = WeakClaim(this)] {
3096             auto pattern = weak.Upgrade();
3097             CHECK_NULL_VOID(pattern);
3098             if (!pattern->HasFocus()) {
3099                 return;
3100             }
3101             pattern->ScrollToSafeArea();
3102             pattern->TriggerAvoidOnCaretChange();
3103             if (pattern->customKeyboard_ || pattern->customKeyboardBuilder_) {
3104                 pattern->StartTwinkling();
3105             }
3106         },
3107         TaskExecutor::TaskType::UI, "ArkUITextFieldScrollToSafeArea");
3108     return true;
3109 }
3110 
AddTextFireOnChange()3111 void TextFieldPattern::AddTextFireOnChange()
3112 {
3113     auto host = GetHost();
3114     CHECK_NULL_VOID(host);
3115     auto context = host->GetContextRefPtr();
3116     CHECK_NULL_VOID(context);
3117     context->AddAfterLayoutTask([weak = AceType::WeakClaim(this)] {
3118         auto pattern = weak.Upgrade();
3119         CHECK_NULL_VOID(pattern);
3120         auto host = pattern->GetHost();
3121         CHECK_NULL_VOID(host);
3122         auto eventHub = host->GetEventHub<TextFieldEventHub>();
3123         CHECK_NULL_VOID(eventHub);
3124         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3125         CHECK_NULL_VOID(layoutProperty);
3126         layoutProperty->UpdateValue(pattern->GetTextContentController()->GetTextValue());
3127         ChangeValueInfo changeValueInfo;
3128         changeValueInfo.value = pattern->GetBodyTextValue();
3129         changeValueInfo.previewText.offset = pattern->hasPreviewText_ ? pattern->GetPreviewTextStart() : -1;
3130         changeValueInfo.previewText.value = pattern->GetPreviewTextValue();
3131         changeValueInfo.oldPreviewText = pattern->callbackOldPreviewText_;
3132         changeValueInfo.oldContent = pattern->callbackOldContent_;
3133         changeValueInfo.rangeBefore = pattern->callbackRangeBefore_;
3134         changeValueInfo.rangeAfter = pattern->callbackRangeAfter_;
3135         layoutProperty->UpdatePreviewText(changeValueInfo.previewText);
3136         eventHub->FireOnChange(changeValueInfo);
3137     });
3138 }
3139 
FilterInitializeText()3140 void TextFieldPattern::FilterInitializeText()
3141 {
3142     if (HasInputOperation()) {
3143         return;
3144     }
3145     if (HasFocus()) {
3146         UpdateShowCountBorderStyle();
3147         if (showCountBorderStyle_) {
3148             HandleCountStyle();
3149         }
3150     }
3151     if (!contentController_->IsEmpty()) {
3152         auto originCaretIndex =
3153             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
3154         ChangeValueInfo changeValueInfo;
3155         changeValueInfo.oldContent = GetBodyTextValue();
3156         changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3157         changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
3158         changeValueInfo.rangeBefore = TextRange { 0, StringUtils::ToWstring(changeValueInfo.oldContent).length() };
3159         contentController_->FilterValue();
3160         changeValueInfo.value = GetBodyTextValue();
3161         changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3162         changeValueInfo.previewText.value = GetPreviewTextValue();
3163         changeValueInfo.rangeAfter = TextRange { 0, StringUtils::ToWstring(changeValueInfo.value).length() };
3164         if (isFilterChanged_) {
3165             bool isWillChange = FireOnWillChange(changeValueInfo);
3166             isFilterChanged_ = false;
3167             if (!isWillChange) {
3168                 RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
3169                 return;
3170             }
3171         }
3172     }
3173     if (static_cast<int32_t>(GetWideText().length()) < GetCaretIndex()) {
3174         selectController_->UpdateCaretIndex(static_cast<int32_t>(GetWideText().length()));
3175     }
3176     UpdateShowCountBorderStyle();
3177 }
3178 
IsDisabled()3179 bool TextFieldPattern::IsDisabled()
3180 {
3181     auto eventHub = GetHost()->GetEventHub<TextFieldEventHub>();
3182     CHECK_NULL_RETURN(eventHub, true);
3183     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
3184     CHECK_NULL_RETURN(layoutProperty, true);
3185     return !eventHub->IsEnabled();
3186 }
3187 
ProcessInnerPadding()3188 void TextFieldPattern::ProcessInnerPadding()
3189 {
3190     auto textFieldTheme = GetTheme();
3191     CHECK_NULL_VOID(textFieldTheme);
3192     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
3193     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3194     CHECK_NULL_VOID(layoutProperty);
3195 
3196     PaddingPropertyF utilPadding;
3197     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
3198     auto left = !paddingProperty ? CalcLength(themePadding.Left()).GetDimension()
3199                                  : paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension();
3200     utilPadding.left = left.ConvertToPx();
3201     auto top = !paddingProperty ? CalcLength(themePadding.Top()).GetDimension()
3202                                 : paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension();
3203     utilPadding.top = top.ConvertToPx();
3204     auto bottom = !paddingProperty ? CalcLength(themePadding.Bottom()).GetDimension()
3205                                    : paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension();
3206     utilPadding.bottom = bottom.ConvertToPx();
3207     auto right = !paddingProperty ? CalcLength(themePadding.Right()).GetDimension()
3208                                   : paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension();
3209     utilPadding.right = right.ConvertToPx();
3210     utilPadding_ = utilPadding;
3211     PaddingProperty paddings;
3212     paddings.top = NG::CalcLength(top);
3213     paddings.bottom = NG::CalcLength(bottom);
3214     paddings.left = NG::CalcLength(left);
3215     paddings.right = NG::CalcLength(right);
3216     layoutProperty->UpdatePadding(paddings);
3217 }
3218 
ProcessNumberOfLines()3219 void TextFieldPattern::ProcessNumberOfLines()
3220 {
3221     auto tmpHost = GetHost();
3222     CHECK_NULL_VOID(tmpHost);
3223     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3224     CHECK_NULL_VOID(layoutProperty && layoutProperty->HasNumberOfLines());
3225     auto numberOfLines = layoutProperty->GetNumberOfLines().value();
3226     CHECK_NULL_VOID(numberOfLines > 0);
3227     auto lineHeight = layoutProperty->GetLineHeight().value_or(0.0_vp).ConvertToPx();
3228     if (LessOrEqual(lineHeight, 0.f)) {
3229         lineHeight = PreferredLineHeight(false);
3230     }
3231     auto lineSpacing = layoutProperty->GetLineSpacing().value_or(0.0_vp).ConvertToPx();
3232     auto contentHeight = numberOfLines * lineHeight + numberOfLines * lineSpacing;
3233     auto height = contentHeight + GetVerticalPaddingAndBorderSum();
3234 
3235     // get previously user defined ideal width
3236     std::optional<CalcLength> width = std::nullopt;
3237     auto &&layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
3238     if (layoutConstraint && layoutConstraint->selfIdealSize) {
3239         width = layoutConstraint->selfIdealSize->Width();
3240     }
3241     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(width, CalcLength(height)));
3242 }
3243 
InitLongPressEvent()3244 void TextFieldPattern::InitLongPressEvent()
3245 {
3246     CHECK_NULL_VOID(!longPressEvent_);
3247     auto gesture = GetHost()->GetOrCreateGestureEventHub();
3248     auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
3249         auto pattern = weak.Upgrade();
3250         CHECK_NULL_VOID(pattern);
3251         pattern->selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
3252         pattern->selectOverlay_->SetLastSourceType(info.GetSourceDevice());
3253         pattern->HandleLongPress(info);
3254     };
3255     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
3256     gesture->SetLongPressEvent(longPressEvent_);
3257 }
3258 
StartVibratorByLongPress()3259 void TextFieldPattern::StartVibratorByLongPress()
3260 {
3261     CHECK_NULL_VOID(isEnableHapticFeedback_);
3262     VibratorUtils::StartVibraFeedback("longPress.light");
3263 }
3264 
HandleLongPress(GestureEvent & info)3265 void TextFieldPattern::HandleLongPress(GestureEvent& info)
3266 {
3267     CHECK_NULL_VOID(!IsDragging());
3268     CHECK_NULL_VOID(!IsHandleDragging());
3269     auto focusHub = GetFocusHub();
3270     CHECK_NULL_VOID(focusHub);
3271     if (!focusHub->IsFocusable() || IsOnUnitByPosition(info.GetGlobalLocation()) || GetIsPreviewText() ||
3272         IsOnPasswordByPosition(info.GetGlobalLocation()) || IsOnCleanNodeByPosition(info.GetGlobalLocation())) {
3273         return;
3274     }
3275     moveCaretState_.isTouchCaret = false;
3276     auto host = GetHost();
3277     CHECK_NULL_VOID(host);
3278     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleLongPress %{public}d", host->GetId());
3279     if (ResetObscureTickCountDown()) {
3280         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3281     }
3282     if (info.GetSourceDevice() == SourceType::MOUSE) {
3283         return;
3284     }
3285     auto hub = host->GetEventHub<EventHub>();
3286     CHECK_NULL_VOID(hub);
3287     auto gestureHub = hub->GetOrCreateGestureEventHub();
3288     CHECK_NULL_VOID(gestureHub);
3289     StartVibratorByLongPress();
3290     if (BetweenSelectedPosition(info.GetGlobalLocation())) {
3291         gestureHub->SetIsTextDraggable(true);
3292         return;
3293     }
3294     gestureHub->SetIsTextDraggable(false);
3295     isLongPress_ = true;
3296     if (!focusHub->IsCurrentFocus()) {
3297         TextFieldRequestFocus(RequestFocusReason::LONG_PRESS);
3298     }
3299 
3300     auto localOffset = ConvertGlobalToLocalOffset(info.GetGlobalLocation());
3301     if (CanChangeSelectState()) {
3302         selectController_->UpdateSelectWithBlank(localOffset);
3303     }
3304     StopTwinkling();
3305     SetIsSingleHandle(!IsSelected());
3306     auto start = selectController_->GetStartIndex();
3307     auto end = selectController_->GetEndIndex();
3308     CloseSelectOverlay();
3309     longPressFingerNum_ = info.GetFingerList().size();
3310     if (magnifierController_ && IsOperation() && (longPressFingerNum_ == 1)) {
3311         magnifierController_->SetLocalOffset({ localOffset.GetX(), localOffset.GetY() });
3312     }
3313     StartGestureSelection(start, end, localOffset);
3314     TriggerAvoidOnCaretChange();
3315     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3316 }
3317 
CanChangeSelectState()3318 bool TextFieldPattern::CanChangeSelectState()
3319 {
3320     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3321     CHECK_NULL_RETURN(layoutProperty, false);
3322     auto theme = GetTheme();
3323     CHECK_NULL_RETURN(theme, false);
3324     Dimension fontSize = layoutProperty->GetFontSizeValue(theme->GetFontSize());
3325     // fontSize == 0 can not change
3326     return !NearZero(fontSize.Value()) && !IsContentRectNonPositive();
3327 }
3328 
IsAccessibilityClick()3329 bool TextFieldPattern::IsAccessibilityClick()
3330 {
3331     auto host = GetHost();
3332     CHECK_NULL_RETURN(host, false);
3333     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
3334     CHECK_NULL_RETURN(accessibilityProperty, false);
3335     return accessibilityProperty->GetAccessibilityFocusState();
3336 }
3337 
IsOnUnitByPosition(const Offset & globalOffset)3338 bool TextFieldPattern::IsOnUnitByPosition(const Offset& globalOffset)
3339 {
3340     if (!IsShowUnit()) {
3341         return false;
3342     }
3343     auto unitArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
3344     CHECK_NULL_RETURN(unitArea, false);
3345     auto frameNode = unitArea->GetFrameNode();
3346     CHECK_NULL_RETURN(frameNode, false);
3347     auto localOffset = ConvertGlobalToLocalOffset(globalOffset);
3348     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3349 }
3350 
IsMouseOverScrollBar(const GestureEvent & info)3351 bool TextFieldPattern::IsMouseOverScrollBar(const GestureEvent& info)
3352 {
3353     CHECK_NULL_RETURN(GetScrollBar(), false);
3354     Point point(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY());
3355     return GetScrollBar()->InBarRectRegion(point);
3356 }
3357 
UpdateCaretPositionWithClamp(const int32_t & pos)3358 void TextFieldPattern::UpdateCaretPositionWithClamp(const int32_t& pos)
3359 {
3360     selectController_->UpdateCaretIndex(
3361         std::clamp(pos, 0, static_cast<int32_t>(contentController_->GetWideText().length())));
3362 }
3363 
IsOnPasswordByPosition(const Offset & globalOffset)3364 bool TextFieldPattern::IsOnPasswordByPosition(const Offset& globalOffset)
3365 {
3366     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
3367     CHECK_NULL_RETURN(passwordArea, false);
3368     auto frameNode = passwordArea->GetFrameNode();
3369     CHECK_NULL_RETURN(frameNode, false);
3370     auto localOffset = ConvertGlobalToLocalOffset(globalOffset);
3371     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3372 }
3373 
IsOnCleanNodeByPosition(const Offset & globalOffset)3374 bool TextFieldPattern::IsOnCleanNodeByPosition(const Offset& globalOffset)
3375 {
3376     auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
3377     CHECK_NULL_RETURN(cleanNodeResponseArea, false);
3378     auto frameNode = cleanNodeResponseArea->GetFrameNode();
3379     CHECK_NULL_RETURN(frameNode, false);
3380     auto localOffset = ConvertGlobalToLocalOffset(globalOffset);
3381     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3382 }
3383 
ProcessOverlay(const OverlayRequest & request)3384 void TextFieldPattern::ProcessOverlay(const OverlayRequest& request)
3385 {
3386     selectOverlay_->ProcessOverlay(request);
3387 }
3388 
DelayProcessOverlay(const OverlayRequest & request)3389 void TextFieldPattern::DelayProcessOverlay(const OverlayRequest& request)
3390 {
3391     processOverlayDelayTask_ = [weak = WeakClaim(this), request]() {
3392         auto pattern = weak.Upgrade();
3393         CHECK_NULL_VOID(pattern);
3394         pattern->ProcessOverlay(request);
3395     };
3396 }
3397 
AllowCopy()3398 bool TextFieldPattern::AllowCopy()
3399 {
3400     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3401     CHECK_NULL_RETURN(layoutProperty, false);
3402     return layoutProperty->GetCopyOptionsValue(CopyOptions::Distributed) != CopyOptions::None && !IsInPasswordMode();
3403 }
3404 
OnDetachFromFrameNode(FrameNode * node)3405 void TextFieldPattern::OnDetachFromFrameNode(FrameNode* node)
3406 {
3407     CloseSelectOverlay();
3408     auto pipeline = GetContext();
3409     CHECK_NULL_VOID(pipeline);
3410     if (HasSurfaceChangedCallback()) {
3411         pipeline->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
3412     }
3413     if (HasSurfacePositionChangedCallback()) {
3414         pipeline->UnregisterSurfacePositionChangedCallback(surfacePositionChangedCallbackId_.value_or(-1));
3415     }
3416     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
3417     if (textFieldManager) {
3418         textFieldManager->ClearOnFocusTextField(node->GetId());
3419     }
3420     auto frameNode = WeakClaim(node);
3421     pipeline->RemoveFontNodeNG(frameNode);
3422     auto fontManager = pipeline->GetFontManager();
3423     if (fontManager) {
3424         fontManager->UnRegisterCallbackNG(frameNode);
3425         fontManager->RemoveVariationNodeNG(frameNode);
3426     }
3427     pipeline->RemoveWindowSizeChangeCallback(node->GetId());
3428     pipeline->RemoveOnAreaChangeNode(node->GetId());
3429 }
3430 
CloseSelectOverlay()3431 void TextFieldPattern::CloseSelectOverlay()
3432 {
3433     CloseSelectOverlay(false);
3434 }
3435 
CloseSelectOverlay(bool animation)3436 void TextFieldPattern::CloseSelectOverlay(bool animation)
3437 {
3438     selectOverlay_->CloseOverlay(animation, CloseReason::CLOSE_REASON_NORMAL);
3439     auto host = GetHost();
3440     CHECK_NULL_VOID(host);
3441     auto gesture = host->GetOrCreateGestureEventHub();
3442     gesture->AddTouchEvent(GetTouchListener());
3443 }
3444 
InitEditingValueText(std::string content)3445 void TextFieldPattern::InitEditingValueText(std::string content)
3446 {
3447     if (HasInputOperation()) {
3448         return;
3449     }
3450     contentController_->SetTextValueOnly(std::move(content));
3451     selectController_->UpdateCaretIndex(GetWideText().length());
3452     if (GetIsPreviewText() && GetWideText().empty()) {
3453         FinishTextPreviewOperation();
3454     }
3455     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
3456 }
3457 
InitValueText(std::string content)3458 bool TextFieldPattern::InitValueText(std::string content)
3459 {
3460     if (GetIsPreviewText()) {
3461         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Init when has previewText");
3462         return false;
3463     }
3464     if (HasInputOperation() && content != "") {
3465         return false;
3466     }
3467     ChangeValueInfo changeValueInfo;
3468     changeValueInfo.oldContent = GetBodyTextValue();
3469     changeValueInfo.value = content;
3470     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3471     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
3472     changeValueInfo.previewText = changeValueInfo.oldPreviewText;
3473     changeValueInfo.rangeBefore = TextRange { 0, StringUtils::ToWstring(changeValueInfo.oldContent).length() };
3474     changeValueInfo.rangeAfter = TextRange { 0, StringUtils::ToWstring(content).length() };
3475     bool isWillChange = FireOnWillChange(changeValueInfo);
3476     if (!isWillChange) {
3477         return false;
3478     }
3479     contentController_->SetTextValueOnly(std::move(content));
3480     selectController_->UpdateCaretIndex(GetWideText().length());
3481     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
3482     return true;
3483 }
3484 
InitMouseEvent()3485 void TextFieldPattern::InitMouseEvent()
3486 {
3487     CHECK_NULL_VOID(!mouseEvent_ || !hoverEvent_);
3488     auto host = GetHost();
3489     CHECK_NULL_VOID(host);
3490     auto eventHub = host->GetEventHub<TextFieldEventHub>();
3491     auto inputHub = eventHub->GetOrCreateInputEventHub();
3492 
3493     auto mouseTask = [weak = WeakClaim(this)](MouseInfo& info) {
3494         auto pattern = weak.Upgrade();
3495         if (pattern) {
3496             pattern->HandleMouseEvent(info);
3497             if (info.GetButton() == MouseButton::LEFT_BUTTON && info.GetAction() == MouseAction::PRESS) {
3498                 pattern->hasMousePressed_ = true;
3499             } else {
3500                 pattern->hasMousePressed_ = false;
3501             }
3502         }
3503     };
3504     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
3505     inputHub->AddOnMouseEvent(mouseEvent_);
3506 
3507     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
3508         auto pattern = weak.Upgrade();
3509         if (pattern) {
3510             pattern->OnHover(isHover);
3511         }
3512     };
3513     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
3514     inputHub->AddOnHoverEvent(hoverEvent_);
3515     InitPanEvent();
3516 }
3517 
InitPanEvent()3518 void TextFieldPattern::InitPanEvent()
3519 {
3520     auto host = GetHost();
3521     CHECK_NULL_VOID(host);
3522     auto gestureHub = host->GetOrCreateGestureEventHub();
3523     CHECK_NULL_VOID(gestureHub);
3524     if (!boxSelectPanEvent_) {
3525         auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
3526         auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
3527         auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
3528         GestureEventNoParameter actionCancelTask;
3529         boxSelectPanEvent_ = MakeRefPtr<PanEvent>(std::move(actionStartTask), std::move(actionUpdateTask),
3530             std::move(actionEndTask), std::move(actionCancelTask));
3531     }
3532     PanDirection panDirection = { .type = PanDirection::ALL };
3533     gestureHub->AddPanEvent(boxSelectPanEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
3534     gestureHub->SetPanEventType(GestureTypeName::TEXTFIELD_BOXSELECT);
3535     gestureHub->SetOnGestureJudgeNativeBegin([weak = WeakClaim(this)](const RefPtr<NG::GestureInfo>& gestureInfo,
3536                                                  const std::shared_ptr<BaseGestureEvent>& info) -> GestureJudgeResult {
3537         if (gestureInfo->GetType() == GestureTypeName::BOXSELECT &&
3538             gestureInfo->GetInputEventType()== InputEventType::MOUSE_BUTTON) {
3539             return GestureJudgeResult::REJECT;
3540         }
3541         auto pattern = weak.Upgrade();
3542         CHECK_NULL_RETURN(pattern, GestureJudgeResult::CONTINUE);
3543         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
3544             gestureInfo->GetInputEventType() == InputEventType::TOUCH_SCREEN &&
3545             pattern->moveCaretState_.isMoveCaret) {
3546             return GestureJudgeResult::CONTINUE;
3547         }
3548         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
3549             gestureInfo->GetInputEventType() != InputEventType::MOUSE_BUTTON) {
3550             return GestureJudgeResult::REJECT;
3551         }
3552         auto host = pattern->GetHost();
3553         CHECK_NULL_RETURN(host, GestureJudgeResult::CONTINUE);
3554         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
3555             gestureInfo->GetInputEventType() == InputEventType::MOUSE_BUTTON &&
3556             host->IsDraggable() && pattern->IsPressSelectedBox()) {
3557             return GestureJudgeResult::REJECT;
3558         }
3559         return GestureJudgeResult::CONTINUE;
3560     });
3561 }
3562 
OnHover(bool isHover)3563 void TextFieldPattern::OnHover(bool isHover)
3564 {
3565     LOGI("Textfield %{public}d %{public}s", GetHost()->GetId(), isHover ? "on hover" : "exit hover");
3566     auto frame = GetHost();
3567     CHECK_NULL_VOID(frame);
3568     auto frameId = frame->GetId();
3569     auto pipeline = PipelineContext::GetCurrentContextSafely();
3570     CHECK_NULL_VOID(pipeline);
3571     auto textFieldTheme = GetTheme();
3572     CHECK_NULL_VOID(textFieldTheme);
3573     if (isHover) {
3574         pipeline->SetMouseStyleHoldNode(frameId);
3575     } else {
3576         int32_t windowId = 0;
3577 #ifdef WINDOW_SCENE_SUPPORTED
3578         windowId = static_cast<int32_t>(GetSCBSystemWindowId());
3579 #endif
3580         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT, windowId);
3581         pipeline->FreeMouseStyleHoldNode(frameId);
3582     }
3583     isOnHover_ = isHover;
3584 }
3585 
RestoreDefaultMouseState()3586 void TextFieldPattern::RestoreDefaultMouseState()
3587 {
3588     int32_t windowId = 0;
3589 #ifdef WINDOW_SCENE_SUPPORTED
3590     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
3591 #endif
3592     auto host = GetHost();
3593     CHECK_NULL_VOID(host);
3594     auto pipeline = host->GetContextRefPtr();
3595     CHECK_NULL_VOID(pipeline);
3596     auto id = host->GetId();
3597     pipeline->SetMouseStyleHoldNode(id);
3598     pipeline->ChangeMouseStyle(id, MouseFormat::DEFAULT, windowId);
3599 }
3600 
ChangeMouseState(const Offset location,const RefPtr<PipelineContext> & pipeline,int32_t frameId,bool isByPass)3601 void TextFieldPattern::ChangeMouseState(
3602     const Offset location, const RefPtr<PipelineContext>& pipeline, int32_t frameId, bool isByPass)
3603 {
3604     auto responseAreaWidth = (responseArea_ ? responseArea_->GetAreaRect().Width() : 0.0f) +
3605                              (cleanNodeResponseArea_ ? cleanNodeResponseArea_->GetAreaRect().Width() : 0.0f);
3606     auto x = location.GetX();
3607     auto y = location.GetY();
3608     int32_t windowId = 0;
3609 #ifdef WINDOW_SCENE_SUPPORTED
3610     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
3611 #endif
3612     if (GreatNotEqual(x, 0) && LessNotEqual(x, frameRect_.Width()) && GreatNotEqual(y, 0) &&
3613         LessNotEqual(y, frameRect_.Height())) {
3614         if (GreatNotEqual(location.GetX(), frameRect_.Width() - responseAreaWidth)) {
3615             RestoreDefaultMouseState();
3616         } else {
3617             pipeline->SetMouseStyleHoldNode(frameId);
3618             pipeline->ChangeMouseStyle(frameId, MouseFormat::TEXT_CURSOR, windowId, isByPass);
3619         }
3620     } else {
3621         RestoreDefaultMouseState();
3622     }
3623 }
3624 
HandleMouseEvent(MouseInfo & info)3625 void TextFieldPattern::HandleMouseEvent(MouseInfo& info)
3626 {
3627     CHECK_NULL_VOID(!IsDragging());
3628     auto frame = GetHost();
3629     CHECK_NULL_VOID(frame);
3630     auto frameId = frame->GetId();
3631     auto pipeline = PipelineContext::GetCurrentContextSafely();
3632     CHECK_NULL_VOID(pipeline);
3633     info.SetStopPropagation(true);
3634     selectOverlay_->SetLastSourceType(info.GetSourceDevice());
3635     auto scrollBar = GetScrollBar();
3636     int32_t windowId = 0;
3637 #ifdef WINDOW_SCENE_SUPPORTED
3638     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
3639 #endif
3640     Point point(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY());
3641     if (scrollBar && (scrollBar->IsPressed() || scrollBar->IsHover() || scrollBar->InBarRectRegion(point))) {
3642         pipeline->SetMouseStyleHoldNode(frameId);
3643         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT, windowId);
3644         return;
3645     }
3646     ChangeMouseState(info.GetLocalLocation(), pipeline, frameId, info.GetAction() == MouseAction::WINDOW_LEAVE);
3647 
3648     selectOverlay_->SetUsingMouse(true);
3649     if (info.GetButton() == MouseButton::RIGHT_BUTTON) {
3650         HandleRightMouseEvent(info);
3651     } else if (info.GetButton() == MouseButton::LEFT_BUTTON) {
3652         HandleLeftMouseEvent(info);
3653         if (IsSelected()) {
3654             selectOverlay_->SetSelectionHoldCallback();
3655         }
3656     }
3657     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
3658         selectOverlay_->SetUsingMouse(false);
3659     }
3660     if (!IsSelected()) {
3661         ResetOriginCaretPosition();
3662     }
3663 }
3664 
HandleRightMouseEvent(MouseInfo & info)3665 void TextFieldPattern::HandleRightMouseEvent(MouseInfo& info)
3666 {
3667     if (info.GetAction() == OHOS::Ace::MouseAction::PRESS) {
3668         HandleRightMousePressEvent(info);
3669         return;
3670     }
3671     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
3672         HandleRightMouseReleaseEvent(info);
3673     }
3674 }
3675 
HandleRightMousePressEvent(MouseInfo & info)3676 void TextFieldPattern::HandleRightMousePressEvent(MouseInfo& info)
3677 {
3678     if (IsSelected() || GetIsPreviewText()) {
3679         return;
3680     }
3681     auto focusHub = GetFocusHub();
3682     if (!focusHub->IsFocusable()) {
3683         return;
3684     }
3685     FocusAndUpdateCaretByMouse(info);
3686 }
3687 
HandleRightMouseReleaseEvent(MouseInfo & info)3688 void TextFieldPattern::HandleRightMouseReleaseEvent(MouseInfo& info)
3689 {
3690     if (GetIsPreviewText()) {
3691         return;
3692     }
3693     auto focusHub = GetFocusHub();
3694     if (focusHub->IsCurrentFocus()) {
3695         OffsetF rightClickOffset = OffsetF(
3696             static_cast<float>(info.GetGlobalLocation().GetX()), static_cast<float>(info.GetGlobalLocation().GetY()));
3697         selectOverlay_->SetMouseMenuOffset(rightClickOffset);
3698         ProcessOverlay();
3699     }
3700 }
3701 
HandleLeftMouseEvent(MouseInfo & info)3702 void TextFieldPattern::HandleLeftMouseEvent(MouseInfo& info)
3703 {
3704     switch (info.GetAction()) {
3705         case OHOS::Ace::MouseAction::PRESS: {
3706             HandleLeftMousePressEvent(info);
3707             break;
3708         }
3709         case OHOS::Ace::MouseAction::MOVE: {
3710             HandleLeftMouseMoveEvent(info); // 注意鼠标拖拽的滚动效果
3711             break;
3712         }
3713         case OHOS::Ace::MouseAction::RELEASE: {
3714             HandleLeftMouseReleaseEvent(info);
3715             break;
3716         }
3717         default: {
3718         }
3719     }
3720 }
3721 
HandleLeftMousePressEvent(MouseInfo & info)3722 void TextFieldPattern::HandleLeftMousePressEvent(MouseInfo& info)
3723 {
3724     isPressSelectedBox_ =
3725         (IsSelected() && BetweenSelectedPosition(info.GetGlobalLocation()) && !shiftFlag_);
3726     if (isPressSelectedBox_ || GetIsPreviewText()) {
3727         blockPress_ = true;
3728         return;
3729     }
3730     auto focusHub = GetFocusHub();
3731     if (!focusHub->IsFocusable()) {
3732         return;
3733     }
3734     mouseStatus_ = MouseStatus::PRESSED;
3735     blockPress_ = false;
3736     leftMouseCanMove_ = true;
3737     FocusAndUpdateCaretByMouse(info);
3738 }
3739 
FocusAndUpdateCaretByMouse(MouseInfo & info)3740 void TextFieldPattern::FocusAndUpdateCaretByMouse(MouseInfo& info)
3741 {
3742     auto focusHub = GetFocusHub();
3743     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
3744     CHECK_NULL_VOID(paintProperty);
3745     if (!focusHub->IsFocusOnTouch().value_or(true) || !TextFieldRequestFocus(RequestFocusReason::MOUSE)) {
3746         StopTwinkling();
3747         return;
3748     }
3749     UpdateCaretByClick(info.GetLocalLocation());
3750     auto tmpHost = GetHost();
3751     CHECK_NULL_VOID(tmpHost);
3752     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3753 }
3754 
UpdateShiftFlag(const KeyEvent & keyEvent)3755 void TextFieldPattern::UpdateShiftFlag(const KeyEvent& keyEvent)
3756 {
3757     bool flag = false;
3758     if (keyEvent.HasKey(KeyCode::KEY_SHIFT_LEFT) || keyEvent.HasKey(KeyCode::KEY_SHIFT_RIGHT)) {
3759         flag = true;
3760     }
3761     if (flag != shiftFlag_) {
3762         shiftFlag_ = flag;
3763         if (!shiftFlag_) {
3764             // open drag
3765             InitDragEvent();
3766         } else  {
3767             // close drag
3768             ClearDragDropEvent();
3769         }
3770     }
3771 }
3772 
UpdateCaretByClick(const Offset & localOffset)3773 void TextFieldPattern::UpdateCaretByClick(const Offset& localOffset)
3774 {
3775     if (shiftFlag_) {
3776         selectController_->UpdateSecondHandleInfoByMouseOffset(localOffset);
3777         StopTwinkling();
3778     } else {
3779         selectController_->UpdateCaretInfoByOffset(localOffset);
3780         StartTwinkling();
3781     }
3782 }
3783 
HandleLeftMouseMoveEvent(MouseInfo & info)3784 void TextFieldPattern::HandleLeftMouseMoveEvent(MouseInfo& info)
3785 {
3786     if (!leftMouseCanMove_ || blockPress_) {
3787         return;
3788     }
3789     auto focusHub = GetFocusHub();
3790     if (!focusHub->IsCurrentFocus()) {
3791         return;
3792     }
3793     mouseStatus_ = MouseStatus::MOVE;
3794     selectController_->UpdateSecondHandleInfoByMouseOffset(info.GetLocalLocation()); // 更新时上报事件
3795     UpdateRecordCaretIndex(
3796         std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
3797     showSelect_ = true;
3798     auto tmpHost = GetHost();
3799     CHECK_NULL_VOID(tmpHost);
3800     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3801 }
3802 
HandleLeftMouseReleaseEvent(MouseInfo & info)3803 void TextFieldPattern::HandleLeftMouseReleaseEvent(MouseInfo& info)
3804 {
3805     auto tmpHost = GetHost();
3806     CHECK_NULL_VOID(tmpHost);
3807     if (blockPress_ && mouseStatus_ == MouseStatus::PRESSED) {
3808         selectController_->UpdateCaretInfoByOffset(info.GetLocalLocation());
3809         StartTwinkling();
3810         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3811     }
3812     auto frameId = tmpHost->GetId();
3813     auto pipeline = GetContext();
3814     CHECK_NULL_VOID(pipeline);
3815     pipeline->FreeMouseStyleHoldNode(frameId);
3816     mouseStatus_ = MouseStatus::NONE;
3817     blockPress_ = false;
3818     leftMouseCanMove_ = false;
3819     if (HasFocus() && RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::MOUSE_RELEASE)) {
3820         NotifyOnEditChanged(true);
3821         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3822     }
3823 }
3824 
UpdateTextFieldManager(const Offset & offset,float height)3825 void TextFieldPattern::UpdateTextFieldManager(const Offset& offset, float height)
3826 {
3827     auto tmpHost = GetHost();
3828     CHECK_NULL_VOID(tmpHost);
3829     auto context = tmpHost->GetContextRefPtr();
3830     CHECK_NULL_VOID(context);
3831     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
3832     CHECK_NULL_VOID(textFieldManager);
3833     auto safeAreaManager = context->GetSafeAreaManager();
3834     CHECK_NULL_VOID(safeAreaManager);
3835     textFieldManager->UpdateScrollableParentViewPort(tmpHost);
3836     if (!HasFocus()) {
3837         return;
3838     }
3839     textFieldManager->SetClickPosition({ offset.GetX() + selectController_->GetCaretRect().GetX(),
3840         offset.GetY() + selectController_->GetCaretRect().GetY() });
3841     textFieldManager->SetHeight(selectController_->GetCaretRect().Height());
3842     textFieldManager->SetClickPositionOffset(safeAreaManager->GetKeyboardOffset());
3843     textFieldManager->SetOnFocusTextField(WeakClaim(this));
3844     textFieldManager->SetUsingCustomKeyboardAvoid(keyboardAvoidance_);
3845     textFieldManager->SetIfFocusTextFieldIsInline(IsNormalInlineState());
3846 }
3847 
GetDefaultTextInputAction() const3848 TextInputAction TextFieldPattern::GetDefaultTextInputAction() const
3849 {
3850     TextInputAction defaultTextInputAction = TextInputAction::DONE;
3851     if (IsTextArea() && !isTextInput_) {
3852         defaultTextInputAction = TextInputAction::NEW_LINE;
3853     } else {
3854         defaultTextInputAction = TextInputAction::DONE;
3855     }
3856     return defaultTextInputAction;
3857 }
3858 
3859 #ifdef WINDOW_SCENE_SUPPORTED
GetSCBSystemWindowId()3860 uint32_t TextFieldPattern::GetSCBSystemWindowId()
3861 {
3862     RefPtr<FrameNode> frameNode = GetHost();
3863     CHECK_NULL_RETURN(frameNode, {});
3864     auto focusSystemWindowId = WindowSceneHelper::GetFocusSystemWindowId(frameNode);
3865     TAG_LOGD(AceLogTag::ACE_KEYBOARD, "TextField Find SCBSystemWindowId End,(%{public}u).", focusSystemWindowId);
3866     return focusSystemWindowId;
3867 }
3868 #endif
3869 
KeyboardContentTypeToInputType()3870 void TextFieldPattern::KeyboardContentTypeToInputType()
3871 {
3872     if (keyboard_ != TextInputType::UNSPECIFIED) {
3873         return;
3874     }
3875     auto autoFillType = GetAutoFillType(false);
3876     if (keyBoardMap_.find(autoFillType) != keyBoardMap_.end()) {
3877         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
3878             "Set InputType to %{public}d because of contentType", keyBoardMap_[autoFillType]);
3879         keyboard_ = keyBoardMap_[autoFillType];
3880     }
3881 }
3882 
GetRequestKeyboardId()3883 int32_t TextFieldPattern::GetRequestKeyboardId()
3884 {
3885     auto host = GetHost();
3886     CHECK_NULL_RETURN(host, -1);
3887     return host->GetId();
3888 }
3889 
RequestKeyboard(bool isFocusViewChanged,bool needStartTwinkling,bool needShowSoftKeyboard)3890 bool TextFieldPattern::RequestKeyboard(bool isFocusViewChanged, bool needStartTwinkling, bool needShowSoftKeyboard)
3891 {
3892     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield to request keyboard"
3893         "showsoftkeyboard: %{public}d", needShowSoftKeyboard);
3894     if (!showKeyBoardOnFocus_ || !HasFocus()) {
3895         return false;
3896     }
3897     auto tmpHost = GetHost();
3898     CHECK_NULL_RETURN(tmpHost, false);
3899     if (customKeyboard_ || customKeyboardBuilder_) {
3900         CHECK_NULL_RETURN(needShowSoftKeyboard, true);
3901         return RequestCustomKeyboard();
3902     }
3903     bool ok = true;
3904     KeyboardContentTypeToInputType();
3905 #if defined(ENABLE_STANDARD_INPUT)
3906     if (textChangeListener_ == nullptr) {
3907         textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
3908     }
3909     auto inputMethod = MiscServices::InputMethodController::GetInstance();
3910     if (!inputMethod) {
3911         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "inputMethod is null");
3912         return false;
3913     }
3914     auto optionalTextConfig = GetMiscTextConfig();
3915     CHECK_NULL_RETURN(optionalTextConfig.has_value(), false);
3916     MiscServices::TextConfig textConfig = optionalTextConfig.value();
3917     ACE_LAYOUT_SCOPED_TRACE("RequestKeyboard[id:%d][WId:%u]", tmpHost->GetId(), textConfig.windowId);
3918     TAG_LOGI(
3919         AceLogTag::ACE_TEXT_FIELD, "node %{public}d RequestKeyboard set calling window id:%{public}u"
3920         " inputType: %{public}d enterKeyType: %{public}d", tmpHost->GetId(), textConfig.windowId,
3921         textConfig.inputAttribute.inputPattern, textConfig.inputAttribute.enterKeyType);
3922 #ifdef WINDOW_SCENE_SUPPORTED
3923     auto systemWindowId = GetSCBSystemWindowId();
3924     if (systemWindowId) {
3925         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "windowId From %{public}u to %{public}u.", textConfig.windowId,
3926             systemWindowId);
3927         textConfig.windowId = systemWindowId;
3928     }
3929 #endif
3930     if ((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_) {
3931         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Request Softkeyboard, Close CustomKeyboard.");
3932         CloseCustomKeyboard();
3933     }
3934     auto context = tmpHost->GetContextRefPtr();
3935     if (context && context->GetTextFieldManager()) {
3936         auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
3937         textFieldManager->SetImeAttached(true);
3938         textFieldManager->SetLastRequestKeyboardId(GetRequestKeyboardId());
3939     }
3940     auto ret = inputMethod->Attach(textChangeListener_, needShowSoftKeyboard, textConfig);
3941     if (ret == MiscServices::ErrorCode::NO_ERROR) {
3942         auto pipeline = GetContext();
3943         CHECK_NULL_RETURN(pipeline, false);
3944         auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
3945         CHECK_NULL_RETURN(textFieldManager, false);
3946         textFieldManager->SetIsImeAttached(true);
3947     }
3948     UpdateCaretInfoToController(true);
3949     if (!fillContentMap_.empty()) {
3950         inputMethod->SendPrivateCommand(fillContentMap_);
3951         fillContentMap_.clear();
3952     }
3953 #else
3954     ok = RequestKeyboardCrossPlatForm(isFocusViewChanged);
3955 #endif
3956     return ok;
3957 }
3958 
RequestKeyboardCrossPlatForm(bool isFocusViewChanged)3959 bool TextFieldPattern::RequestKeyboardCrossPlatForm(bool isFocusViewChanged)
3960 {
3961 #if !defined(ENABLE_STANDARD_INPUT)
3962     auto tmpHost = GetHost();
3963     CHECK_NULL_RETURN(tmpHost, false);
3964     auto context = tmpHost->GetContextRefPtr();
3965     CHECK_NULL_RETURN(context, false);
3966     if (!HasConnection()) {
3967         TextInputConfiguration config;
3968         config.type = keyboard_;
3969         config.action = GetTextInputActionValue(GetDefaultTextInputAction());
3970         config.inputFilter = GetInputFilter();
3971         config.maxLength = GetMaxLength();
3972         if (keyboard_ == TextInputType::VISIBLE_PASSWORD || keyboard_ == TextInputType::NEW_PASSWORD) {
3973             config.obscureText = textObscured_;
3974         }
3975         connection_ = TextInputProxy::GetInstance().Attach(
3976             WeakClaim(this), config, context->GetTaskExecutor(), GetInstanceId());
3977 
3978         if (!HasConnection()) {
3979             return false;
3980         }
3981     }
3982     TextEditingValue value;
3983     value.text = contentController_->GetTextValue();
3984     value.hint = GetPlaceHolder();
3985     value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
3986     connection_->SetEditingState(value, GetInstanceId());
3987     connection_->Show(isFocusViewChanged, GetInstanceId());
3988 #endif
3989     return true;
3990 }
3991 
3992 #if defined(ENABLE_STANDARD_INPUT)
GetMiscTextConfig() const3993 std::optional<MiscServices::TextConfig> TextFieldPattern::GetMiscTextConfig() const
3994 {
3995     auto tmpHost = GetHost();
3996     CHECK_NULL_RETURN(tmpHost, {});
3997     auto pipeline = tmpHost->GetContextRefPtr();
3998     CHECK_NULL_RETURN(pipeline, {});
3999     auto theme = GetTheme();
4000     CHECK_NULL_RETURN(theme, {});
4001     auto windowRect = pipeline->GetCurrentWindowRect();
4002     double positionY = (tmpHost->GetPaintRectOffset(false, true) - pipeline->GetRootRect().GetOffset()).GetY() +
4003         windowRect.Top();
4004     auto offset = AVOID_OFFSET.ConvertToPx();
4005     auto textPaintOffset = GetPaintRectGlobalOffset();
4006     double height = selectController_->GetCaretRect().Bottom() + windowRect.Top() +
4007              textPaintOffset.GetY() + offset - positionY;
4008 
4009     GetInlinePositionYAndHeight(positionY, height);
4010 
4011     auto manager = pipeline->GetSafeAreaManager();
4012     if (manager) {
4013         auto keyboardOffset = manager->GetKeyboardOffset();
4014         positionY -= keyboardOffset;
4015     }
4016 
4017     TAG_LOGI(
4018         AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d positionY: %{public}f, height: %{public}f,"
4019         "paintOffset: %{public}s, windowRect: %{public}f",
4020         tmpHost->GetId(), positionY, height, textPaintOffset.ToString().c_str(), windowRect.Top());
4021 
4022     MiscServices::CursorInfo cursorInfo { .left = selectController_->GetCaretRect().Left() + windowRect.Left() +
4023                                                   textPaintOffset.GetX(),
4024         .top = selectController_->GetCaretRect().Top() + windowRect.Top() + textPaintOffset.GetY(),
4025         .width = theme->GetCursorWidth().ConvertToPx(),
4026         .height = selectController_->GetCaretRect().Height() };
4027     MiscServices::InputAttribute inputAttribute = { .inputPattern = (int32_t)keyboard_,
4028         .enterKeyType = (int32_t)GetTextInputActionValue(GetDefaultTextInputAction()),
4029         .isTextPreviewSupported = hasSupportedPreviewText_,
4030         .immersiveMode = static_cast<int32_t>(keyboardAppearance_)};
4031     MiscServices::TextConfig textConfig = { .inputAttribute = inputAttribute,
4032         .cursorInfo = cursorInfo,
4033         .range = { .start = selectController_->GetStartIndex(), .end = selectController_->GetEndIndex() },
4034         .windowId = pipeline->GetFocusWindowId(),
4035         .positionY = positionY,
4036         .height = height };
4037 
4038     if (keyboard_ == TextInputType::NUMBER_DECIMAL) {
4039         textConfig.inputAttribute.inputPattern = (int32_t)TextInputType::NUMBER;
4040     }
4041     return textConfig;
4042 }
4043 
GetInlinePositionYAndHeight(double & positionY,double & height) const4044 void TextFieldPattern::GetInlinePositionYAndHeight(double& positionY, double& height) const
4045 {
4046     if (IsNormalInlineState()) {
4047         auto theme = GetTheme();
4048         CHECK_NULL_VOID(theme);
4049         auto offset = AVOID_OFFSET.ConvertToPx();
4050         auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4051         PaddingProperty userPadding;
4052         if (paintProperty->HasPaddingByUser()) {
4053             userPadding = paintProperty->GetPaddingByUserValue();
4054         } else {
4055             userPadding.top = CalcLength(theme->GetPadding().Top());
4056         }
4057         auto topPadding = userPadding.top->GetDimension().ConvertToPx();
4058         auto safeBoundary = theme->GetInlineBorderWidth().ConvertToPx() * 2;
4059         positionY += static_cast<double>(inlineMeasureItem_.inlineSizeHeight) + safeBoundary + topPadding;
4060         height = offset;
4061 
4062         auto tmpHost = GetHost();
4063         CHECK_NULL_VOID(tmpHost);
4064         auto pipeline = tmpHost->GetContextRefPtr();
4065         CHECK_NULL_VOID(pipeline);
4066         auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
4067         CHECK_NULL_VOID(textFieldManager);
4068         TAG_LOGI(ACE_TEXT_FIELD, "SetInlineAvoidInfo positionY:%{public}f height:%{public}f sizeHeight:%{public}f",
4069             positionY, height, inlineMeasureItem_.inlineSizeHeight);
4070         textFieldManager->SetInlineTextFieldAvoidPositionYAndHeight(positionY, height);
4071     }
4072 }
4073 
4074 #endif
4075 
ConvertToAceAutoFillType(TextInputType type)4076 AceAutoFillType TextFieldPattern::ConvertToAceAutoFillType(TextInputType type)
4077 {
4078     static std::unordered_map<TextInputType, AceAutoFillType> convertMap = {
4079         { TextInputType::VISIBLE_PASSWORD, AceAutoFillType::ACE_PASSWORD },
4080         { TextInputType::USER_NAME, AceAutoFillType::ACE_USER_NAME },
4081         { TextInputType::NEW_PASSWORD, AceAutoFillType::ACE_NEW_PASSWORD },
4082         { TextInputType::NUMBER_PASSWORD, AceAutoFillType::ACE_PASSWORD } };
4083     auto it = convertMap.find(type);
4084     if (it != convertMap.end()) {
4085         return it->second;
4086     }
4087     return AceAutoFillType::ACE_UNSPECIFIED;
4088 }
4089 
TextContentTypeToAceAutoFillType(const TextContentType & type)4090 AceAutoFillType TextFieldPattern::TextContentTypeToAceAutoFillType(const TextContentType& type)
4091 {
4092     if (contentTypeMap_.find(type) != contentTypeMap_.end()) {
4093         return contentTypeMap_[type].first;
4094     }
4095     return contentTypeMap_[TextContentType::UNSPECIFIED].first;
4096 }
4097 
CloseKeyboard(bool forceClose)4098 bool TextFieldPattern::CloseKeyboard(bool forceClose)
4099 {
4100     return CloseKeyboard(forceClose, forceClose);
4101 }
4102 
CloseKeyboard(bool forceClose,bool isStopTwinkling)4103 bool TextFieldPattern::CloseKeyboard(bool forceClose, bool isStopTwinkling)
4104 {
4105     if (forceClose) {
4106         if (isStopTwinkling) {
4107             StopTwinkling();
4108         }
4109         CloseSelectOverlay(true);
4110         auto host = GetHost();
4111         CHECK_NULL_RETURN(host, false);
4112         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Will Close Soft keyboard.", host->GetId());
4113         if ((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_) {
4114             return CloseCustomKeyboard();
4115         }
4116 #if defined(ENABLE_STANDARD_INPUT)
4117         auto inputMethod = MiscServices::InputMethodController::GetInstance();
4118         if (!inputMethod) {
4119             return false;
4120         }
4121         inputMethod->Close();
4122 #else
4123         if (HasConnection()) {
4124             connection_->Close(GetInstanceId());
4125             connection_ = nullptr;
4126         }
4127 #endif
4128         return true;
4129     }
4130     return false;
4131 }
4132 
SetCustomKeyboardOption(bool supportAvoidance)4133 void TextFieldPattern::SetCustomKeyboardOption(bool supportAvoidance)
4134 {
4135     keyboardAvoidance_ = supportAvoidance;
4136 }
4137 
RequestCustomKeyboard()4138 bool TextFieldPattern::RequestCustomKeyboard()
4139 {
4140 #if defined(ENABLE_STANDARD_INPUT)
4141     auto inputMethod = MiscServices::InputMethodController::GetInstance();
4142     if (inputMethod) {
4143         TAG_LOGD(AceLogTag::ACE_KEYBOARD, "TextField Request CustomKeyboard, Close keyboard Successfully.");
4144         inputMethod->RequestHideInput();
4145         inputMethod->Close();
4146     }
4147 #else
4148     if (HasConnection()) {
4149         connection_->Close(GetInstanceId());
4150         connection_ = nullptr;
4151     }
4152 #endif
4153 
4154     if (isCustomKeyboardAttached_) {
4155         return true;
4156     }
4157     CHECK_NULL_RETURN(customKeyboard_ || customKeyboardBuilder_, false);
4158     auto frameNode = GetHost();
4159     CHECK_NULL_RETURN(frameNode, false);
4160     ACE_LAYOUT_SCOPED_TRACE("RequestCustomKeyboard[id:%d]", frameNode->GetId());
4161     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "RequestCustomKeyboard, id:%{public}d", frameNode->GetId());
4162     auto pipeline = PipelineContext::GetCurrentContextSafely();
4163     CHECK_NULL_RETURN(pipeline, false);
4164     auto overlayManager = pipeline->GetOverlayManager();
4165     CHECK_NULL_RETURN(overlayManager, false);
4166     overlayManager->SetCustomKeyboardOption(keyboardAvoidance_);
4167     if (customKeyboardBuilder_) {
4168         overlayManager->BindKeyboard(customKeyboardBuilder_, frameNode->GetId());
4169     } else {
4170         overlayManager->BindKeyboardWithNode(customKeyboard_, frameNode->GetId());
4171     }
4172     isCustomKeyboardAttached_ = true;
4173     keyboardOverlay_ = overlayManager;
4174     auto caretHeight = selectController_->GetCaretRect().Height();
4175     auto safeHeight = caretHeight + selectController_->GetCaretRect().GetY();
4176     if (selectController_->GetCaretRect().GetY() > caretHeight) {
4177         safeHeight = caretHeight;
4178     }
4179     keyboardOverlay_->AvoidCustomKeyboard(frameNode->GetId(), safeHeight);
4180     return true;
4181 }
4182 
CloseCustomKeyboard()4183 bool TextFieldPattern::CloseCustomKeyboard()
4184 {
4185     auto frameNode = GetHost();
4186     CHECK_NULL_RETURN(frameNode, false);
4187     CHECK_NULL_RETURN(keyboardOverlay_, false);
4188     keyboardOverlay_->CloseKeyboard(frameNode->GetId());
4189     isCustomKeyboardAttached_ = false;
4190     return true;
4191 }
4192 
OnTextInputActionUpdate(TextInputAction value)4193 void TextFieldPattern::OnTextInputActionUpdate(TextInputAction value) {}
4194 
BeforeIMEInsertValue(const std::string & insertValue,int32_t offset)4195 bool TextFieldPattern::BeforeIMEInsertValue(const std::string& insertValue, int32_t offset)
4196 {
4197     auto host = GetHost();
4198     CHECK_NULL_RETURN(host, true);
4199     auto eventHub = host->GetEventHub<TextFieldEventHub>();
4200     CHECK_NULL_RETURN(eventHub, true);
4201     InsertValueInfo insertValueInfo;
4202     insertValueInfo.insertOffset = offset;
4203     insertValueInfo.insertValue = insertValue;
4204     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "BeforeIMEInsertValue len:%{public}d,offset:%{public}d",
4205         static_cast<int32_t>(insertValue.length()), offset);
4206     return eventHub->FireOnWillInsertValueEvent(insertValueInfo);
4207 }
4208 
AfterIMEInsertValue(const std::string & insertValue)4209 void TextFieldPattern::AfterIMEInsertValue(const std::string& insertValue)
4210 {
4211     auto host = GetHost();
4212     CHECK_NULL_VOID(host);
4213     auto eventHub = host->GetEventHub<TextFieldEventHub>();
4214     CHECK_NULL_VOID(eventHub);
4215     InsertValueInfo insertValueInfo;
4216     auto offset = selectController_->GetCaretIndex();
4217     insertValueInfo.insertOffset = offset;
4218     insertValueInfo.insertValue = insertValue;
4219     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "AfterIMEInsertValue len:%{public}d,offset:%{public}d",
4220         static_cast<int32_t>(insertValue.length()), offset);
4221     return eventHub->FireOnDidInsertValueEvent(insertValueInfo);
4222 }
4223 
CalcCounterAfterFilterInsertValue(int32_t curLength,const std::string insertValue,int32_t maxLength)4224 void TextFieldPattern::CalcCounterAfterFilterInsertValue(
4225     int32_t curLength, const std::string insertValue, int32_t maxLength)
4226 {
4227     bool textChange = false;
4228     auto result = insertValue;
4229     contentController_->FilterTextInputStyle(textChange, result);
4230     int32_t sum = curLength + static_cast<int32_t>(StringUtils::ToWstring(result).length());
4231     showCountBorderStyle_ = sum > maxLength;
4232     HandleCountStyle();
4233 }
4234 
NotifyImfFinishTextPreview()4235 void TextFieldPattern::NotifyImfFinishTextPreview()
4236 {
4237     if (!HasFocus()) {
4238         return;
4239     }
4240 #if defined(ENABLE_STANDARD_INPUT)
4241     int32_t caretIndex = selectController_->GetCaretIndex();
4242     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
4243         u"", caretIndex, caretIndex);
4244     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "notify imf that textfield exit textPreview");
4245 #endif
4246 }
4247 
InsertValueByController(const std::string & insertValue,int32_t offset)4248 int32_t TextFieldPattern::InsertValueByController(const std::string& insertValue, int32_t offset)
4249 {
4250     auto host = GetHost();
4251     CHECK_NULL_RETURN(host, offset);
4252     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4253     CHECK_NULL_RETURN(layoutProperty, offset);
4254     NotifyImfFinishTextPreview();
4255     int32_t originLength =
4256         static_cast<int32_t>(contentController_->GetTextValue().length());
4257     bool hasInsertValue =
4258         contentController_->InsertValue(offset, insertValue);
4259     int32_t caretMoveLength =
4260         abs(static_cast<int32_t>(contentController_->GetTextValue().length()) - originLength);
4261     if (layoutProperty->HasMaxLength()) {
4262         CalcCounterAfterFilterInsertValue(originLength, insertValue,
4263             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
4264     }
4265     int32_t newCaretIndex = offset + caretMoveLength;
4266     selectController_->UpdateCaretIndex(newCaretIndex);
4267     auto pipeline = host->GetContext();
4268     CHECK_NULL_RETURN(pipeline, offset);
4269     pipeline->AddAfterLayoutTask([weak = WeakClaim(Referenced::RawPtr(selectController_))]() {
4270         auto selectController = weak.Upgrade();
4271         CHECK_NULL_VOID(selectController);
4272         int32_t index = selectController->GetCaretIndex();
4273         selectController->MoveCaretToContentRect(index);
4274     });
4275     UpdateObscure(insertValue, hasInsertValue);
4276     UpdateEditingValueToRecord();
4277     TwinklingByFocus();
4278     CloseSelectOverlay(true);
4279     ScrollToSafeArea();
4280     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4281     return selectController_->GetCaretIndex();
4282 }
4283 
ExecuteInsertValueCommand(const InsertCommandInfo & info)4284 void TextFieldPattern::ExecuteInsertValueCommand(const InsertCommandInfo& info)
4285 {
4286     auto insertValue = info.insertValue;
4287     auto isIME = (info.reason == InputReason::IME);
4288     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4289     CHECK_NULL_VOID(layoutProperty);
4290     auto start = selectController_->GetStartIndex();
4291     auto end = selectController_->GetEndIndex();
4292     GetEmojiSubStringRange(start, end);
4293     auto caretStart = IsSelected() ? start : selectController_->GetCaretIndex();
4294     if (isIME) {
4295         auto isInsert = BeforeIMEInsertValue(insertValue, caretStart);
4296         CHECK_NULL_VOID(isInsert);
4297     }
4298     int32_t caretMoveLength = 0;
4299     bool hasInsertValue = false;
4300     int32_t originLength = 0;
4301     auto oldContent = contentController_->GetTextValue();
4302     auto originCaretIndex =
4303             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
4304     if (IsSelected()) {
4305         auto value = contentController_->GetSelectedValue(start, end);
4306         auto isDelete = true;
4307         if (isIME) {
4308             isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::BACKWARD, end);
4309         }
4310         end = isDelete ? end : start;
4311         originLength = static_cast<int32_t>(contentController_->GetWideText().length()) - (end - start);
4312         hasInsertValue = contentController_->ReplaceSelectedValue(start, end, insertValue);
4313         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetWideText().length()) - originLength);
4314         bool isWillChange = OnWillChangePreInsert(contentController_->GetInsertValue(), oldContent, start, end);
4315         if (!isWillChange) {
4316             RecoverTextValueAndCaret(oldContent, originCaretIndex);
4317             return;
4318         }
4319         if (isIME && isDelete) {
4320             selectController_->UpdateCaretIndex(start);
4321             AfterIMEDeleteValue(value, TextDeleteDirection::BACKWARD);
4322         }
4323     } else {
4324         originLength = static_cast<int32_t>(contentController_->GetWideText().length());
4325         hasInsertValue = contentController_->InsertValue(selectController_->GetCaretIndex(), insertValue);
4326         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetWideText().length()) - originLength);
4327         bool isWillChange = OnWillChangePreInsert(contentController_->GetInsertValue(), oldContent, start, end);
4328         if (!isWillChange) {
4329             RecoverTextValueAndCaret(oldContent, originCaretIndex);
4330             return;
4331         }
4332     }
4333     if (layoutProperty->HasMaxLength()) {
4334         CalcCounterAfterFilterInsertValue(originLength, insertValue,
4335             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
4336     }
4337     selectController_->UpdateCaretIndex(caretStart + caretMoveLength);
4338     UpdateObscure(insertValue, hasInsertValue);
4339     UpdateEditingValueToRecord();
4340     if (isIME) {
4341         AfterIMEInsertValue(contentController_->GetInsertValue());
4342     }
4343     TwinklingByFocus();
4344 }
4345 
TwinklingByFocus()4346 void TextFieldPattern::TwinklingByFocus()
4347 {
4348     if (HasFocus()) {
4349         cursorVisible_ = true;
4350         StartTwinkling();
4351     } else {
4352         cursorVisible_ = false;
4353         StopTwinkling();
4354     }
4355 }
4356 
FinishTextPreviewByPreview(const std::string & insertValue)4357 bool TextFieldPattern::FinishTextPreviewByPreview(const std::string& insertValue)
4358 {
4359     if (GetIsPreviewText()) {
4360         PreviewTextInfo info = {
4361             .text = insertValue,
4362             .range = { -1, -1 },
4363             .isIme = false
4364         };
4365         inputOperations_.emplace(InputOperation::SET_PREVIEW_TEXT);
4366         previewTextOperation_.emplace(info);
4367         FinishTextPreview();
4368         return true;
4369     }
4370     return false;
4371 }
4372 
UpdateObscure(const std::string & insertValue,bool hasInsertValue)4373 void TextFieldPattern::UpdateObscure(const std::string& insertValue, bool hasInsertValue)
4374 {
4375     if (!IsTextArea() && IsInPasswordMode() && GetTextObscured()) {
4376         auto host = GetHost();
4377         CHECK_NULL_VOID(host);
4378         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
4379         CHECK_NULL_VOID(layoutProperty);
4380         auto wideInsertValue = StringUtils::ToWstring(insertValue);
4381         if (wideInsertValue.length() == 1 &&
4382             (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) != TextInputType::NUMBER_PASSWORD ||
4383                 std::isdigit(insertValue[0])) &&
4384             hasInsertValue) {
4385             auto content = contentController_->GetWideText();
4386             auto insertIndex = selectController_->GetCaretIndex() - 1;
4387             insertIndex = std::clamp(insertIndex, 0, static_cast<int32_t>(content.length()));
4388             auto strBeforeCaret = content.empty() ? "" : StringUtils::ToString(content.substr(insertIndex, 1));
4389             obscureTickCountDown_ = strBeforeCaret == insertValue ? OBSCURE_SHOW_TICKS : 0;
4390             nakedCharPosition_ = strBeforeCaret == insertValue ? insertIndex : -1;
4391         } else {
4392             obscureTickCountDown_ = 0;
4393             nakedCharPosition_ = -1;
4394         }
4395     }
4396 }
4397 
InsertValue(const std::string & insertValue,bool isIME)4398 void TextFieldPattern::InsertValue(const std::string& insertValue, bool isIME)
4399 {
4400     InputReason reason = isIME ? InputReason::IME : InputReason::NONE;
4401     AddInsertCommand(insertValue, reason);
4402 }
4403 
UltralimitShake()4404 void TextFieldPattern::UltralimitShake()
4405 {
4406     auto frameNode = GetHost();
4407     CHECK_NULL_VOID(frameNode);
4408     auto context = frameNode->GetRenderContext();
4409     CHECK_NULL_VOID(context);
4410     AnimationOption option;
4411     context->UpdateTranslateInXY({ -1.0, 0.0 });
4412     const RefPtr<InterpolatingSpring> curve =
4413         AceType::MakeRefPtr<InterpolatingSpring>(VELOCITY, MASS, STIFFNESS, DAMPING);
4414     option.SetCurve(curve);
4415     option.SetFillMode(FillMode::FORWARDS);
4416     auto pipelineContext = PipelineContext::GetCurrentContext();
4417     CHECK_NULL_VOID(pipelineContext);
4418     AnimationUtils::Animate(
4419         option,
4420         [weak = WeakClaim(context.GetRawPtr())]() {
4421             auto context = weak.Upgrade();
4422             CHECK_NULL_VOID(context);
4423             context->UpdateTranslateInXY({ 0.0f, 0.0f });
4424         },
4425         option.GetOnFinishEvent());
4426 }
4427 
MeasureCounterNodeHeight()4428 float TextFieldPattern::MeasureCounterNodeHeight()
4429 {
4430     auto frameNode = GetHost();
4431     CHECK_NULL_RETURN(frameNode, 0.0);
4432     auto theme = GetTheme();
4433     CHECK_NULL_RETURN(theme, 0.0);
4434     auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
4435     CHECK_NULL_RETURN(layoutProperty, 0.0);
4436     auto pattern = frameNode->GetPattern<TextFieldPattern>();
4437     CHECK_NULL_RETURN(pattern, 0.0);
4438     auto counterNode = pattern->GetCounterNode().Upgrade();
4439     CHECK_NULL_RETURN(counterNode, 0.0);
4440     auto counterFrameNode = counterNode->GetHostNode();
4441     CHECK_NULL_RETURN(counterFrameNode, 0.0);
4442     auto counterNodeLayoutProperty = DynamicCast<TextLayoutProperty>(counterNode->GetLayoutProperty());
4443     CHECK_NULL_RETURN(counterNodeLayoutProperty, 0.0);
4444 
4445     auto textContent = contentController_->GetTextValue();
4446     auto textLength = static_cast<uint32_t>(StringUtils::ToWstring(textContent).length());
4447     auto maxLength = static_cast<uint32_t>(layoutProperty->GetMaxLength().value_or(INT32_MAX));
4448     std::string counterText = std::to_string(textLength) + "/" + std::to_string(maxLength);
4449 
4450     TextStyle countTextStyle = (this->GetShowCounterStyleValue() && this->HasFocus()) ?
4451                                 theme->GetOverCountTextStyle() :
4452                                 theme->GetCountTextStyle();
4453 
4454     counterNodeLayoutProperty->UpdateContent(counterText);
4455     counterNodeLayoutProperty->UpdateFontSize(countTextStyle.GetFontSize());
4456     counterNodeLayoutProperty->UpdateFontWeight(countTextStyle.GetFontWeight());
4457     counterNodeLayoutProperty->UpdateMaxLines(COUNTER_TEXT_MAXLINE);
4458     ScopedLayout scope(frameNode->GetContext());
4459     counterFrameNode->Measure(LayoutConstraintF());
4460     auto counterGeometryNode = counterFrameNode->GetGeometryNode();
4461     CHECK_NULL_RETURN(counterGeometryNode, 0.0);
4462     return counterGeometryNode->GetFrameRect().Height();
4463 }
4464 
UpdateCounterMargin()4465 void TextFieldPattern::UpdateCounterMargin()
4466 {
4467     auto host = GetHost();
4468     CHECK_NULL_VOID(host);
4469     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
4470     CHECK_NULL_VOID(layoutProperty);
4471     auto pipeline = host->GetContext();
4472     CHECK_NULL_VOID(pipeline);
4473     if (!IsTextArea() && IsShowCount()) {
4474         MarginProperty margin;
4475         const auto& getMargin = layoutProperty->GetMarginProperty();
4476         auto counterHeight = MeasureCounterNodeHeight();
4477         auto curFontScale = pipeline->GetFontScale();
4478         auto marginHeight = (NearEqual(curFontScale, 1.0f)) ? STANDARD_COUNTER_TEXT_MARGIN.ConvertToPx() :
4479             (COUNTER_TEXT_TOP_MARGIN.ConvertToPx() + COUNTER_TEXT_BOTTOM_MARGIN.ConvertToPx() + counterHeight);
4480         Dimension marginProperty(marginHeight, DimensionUnit::PX);
4481         if (!getMargin) {
4482             margin.bottom = CalcLength(marginProperty);
4483             layoutProperty->UpdateMargin(margin);
4484             return;
4485         }
4486         auto systemMargin = getMargin->bottom->GetDimension();
4487         if (LessNotEqual(systemMargin.ConvertToPx(), marginProperty.ConvertToPx())) {
4488             margin.bottom = CalcLength(marginProperty);
4489             margin.left = CalcLength(getMargin->left->GetDimension());
4490             margin.top = CalcLength(getMargin->top->GetDimension());
4491             margin.right = CalcLength(getMargin->right->GetDimension());
4492             layoutProperty->UpdateMargin(margin);
4493         } else {
4494             margin.bottom = CalcLength(systemMargin);
4495             margin.left = CalcLength(getMargin->left->GetDimension());
4496             margin.top = CalcLength(getMargin->top->GetDimension());
4497             margin.right = CalcLength(getMargin->right->GetDimension());
4498             layoutProperty->UpdateMargin(margin);
4499         }
4500     }
4501 }
4502 
CleanCounterNode()4503 void TextFieldPattern::CleanCounterNode()
4504 {
4505     auto frameNode = GetHost();
4506     CHECK_NULL_VOID(frameNode);
4507     auto pattern = frameNode->GetPattern<TextFieldPattern>();
4508     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
4509     CHECK_NULL_VOID(textFieldLayoutProperty);
4510     auto counterNode = DynamicCast<UINode>(counterTextNode_.Upgrade());
4511     CHECK_NULL_VOID(counterNode);
4512     frameNode->RemoveChild(counterNode);
4513     frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
4514 }
4515 
CleanErrorNode()4516 void TextFieldPattern::CleanErrorNode()
4517 {
4518     auto frameNode = GetHost();
4519     CHECK_NULL_VOID(frameNode);
4520     auto errorTextNode = errorTextNode_.Upgrade();
4521     CHECK_NULL_VOID(errorTextNode);
4522     auto errorNode = DynamicCast<UINode>(errorTextNode);
4523     CHECK_NULL_VOID(errorNode);
4524     frameNode->RemoveChild(errorNode);
4525     frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
4526     errorTextNode_.Reset();
4527 }
4528 
UpdateEditingValueToRecord()4529 void TextFieldPattern::UpdateEditingValueToRecord()
4530 {
4531     if (operationRecords_.size() >= RECORD_MAX_LENGTH) {
4532         operationRecords_.erase(operationRecords_.begin());
4533     }
4534     TextEditingValueNG record {
4535         .text = contentController_->GetTextValue(),
4536         .caretPosition = selectController_->GetCaretIndex(),
4537     };
4538     operationRecords_.emplace_back(record);
4539 }
4540 
PreferredTextHeight(bool isPlaceholder,bool isAlgorithmMeasure)4541 float TextFieldPattern::PreferredTextHeight(bool isPlaceholder, bool isAlgorithmMeasure)
4542 {
4543     if (!isAlgorithmMeasure && paragraph_ && paragraph_->GetHeight() != 0.0f && paragraph_->GetLineCount() > 0) {
4544         return paragraph_->GetHeight() / paragraph_->GetLineCount();
4545     }
4546     RefPtr<Paragraph> paragraph;
4547     std::string textContent;
4548     TextStyle textStyle;
4549     auto tmpHost = GetHost();
4550     CHECK_NULL_RETURN(tmpHost, 0.0f);
4551     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
4552     CHECK_NULL_RETURN(layoutProperty, 0.0f);
4553     auto textFieldTheme = GetTheme();
4554     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
4555     // use text or placeHolder value if exists, space otherwise
4556     if (!isPlaceholder) {
4557         TextFieldLayoutAlgorithm::UpdateTextStyle(GetHost(), layoutProperty, textFieldTheme, textStyle, false);
4558         textContent = "a";
4559     } else {
4560         TextFieldLayoutAlgorithm::UpdatePlaceholderTextStyle(
4561             GetHost(), layoutProperty, textFieldTheme, textStyle, false);
4562         textContent = "b";
4563     }
4564     if (adaptFontSize_.has_value()) {
4565         textStyle.SetFontSize(adaptFontSize_.value());
4566     }
4567     if (textStyle.GetFontSize().IsNonPositive()) {
4568         textStyle.SetFontSize(DEFAULT_FONT);
4569     }
4570     ParagraphStyle paraStyle { .direction =
4571                                    TextFieldLayoutAlgorithm::GetTextDirection(contentController_->GetTextValue()),
4572         .align = textStyle.GetTextAlign(),
4573         .maxLines = textStyle.GetMaxLines(),
4574         .fontLocale = Localization::GetInstance()->GetFontLocale(),
4575         .wordBreak = textStyle.GetWordBreak(),
4576         .lineBreakStrategy = textStyle.GetLineBreakStrategy(),
4577         .textOverflow = textStyle.GetTextOverflow(),
4578         .fontSize = FontSizeConvertToPx(textStyle.GetFontSize()) };
4579     paragraph = Paragraph::Create(paraStyle, FontCollection::Current());
4580     CHECK_NULL_RETURN(paragraph, 0.0f);
4581     paragraph->AddText(StringUtils::Str8ToStr16(textContent));
4582     paragraph->Build();
4583     paragraph->Layout(std::numeric_limits<double>::infinity());
4584     return paragraph->GetHeight();
4585 }
4586 
FontSizeConvertToPx(const Dimension & fontSize)4587 float TextFieldPattern::FontSizeConvertToPx(const Dimension& fontSize)
4588 {
4589     return fontSize.ConvertToPx();
4590 }
4591 
PreferredLineHeight(bool isAlgorithmMeasure)4592 float TextFieldPattern::PreferredLineHeight(bool isAlgorithmMeasure)
4593 {
4594     return PreferredTextHeight(contentController_->IsEmpty(), isAlgorithmMeasure);
4595 }
4596 
OnCursorMoveDone(TextAffinity textAffinity,std::optional<Offset> offset)4597 void TextFieldPattern::OnCursorMoveDone(TextAffinity textAffinity, std::optional<Offset> offset)
4598 {
4599     auto tmpHost = GetHost();
4600     CHECK_NULL_VOID(tmpHost);
4601     StartTwinkling();
4602     CloseSelectOverlay();
4603     if (offset.has_value()) {
4604         selectController_->UpdateCaretInfoByOffset(offset.value());
4605     } else {
4606         selectController_->MoveCaretToContentRect(GetCaretIndex(), textAffinity);
4607     }
4608     if (ResetObscureTickCountDown()) {
4609         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4610     } else {
4611         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4612     }
4613     UpdateCaretInfoToController();
4614 }
4615 
GetWordLength(int32_t originCaretPosition,int32_t directionMove,bool skipNewLineChar)4616 int32_t TextFieldPattern::GetWordLength(int32_t originCaretPosition, int32_t directionMove, bool skipNewLineChar)
4617 {
4618     if (contentController_->IsEmpty()) {
4619         return 0;
4620     }
4621     int32_t textLength = static_cast<int32_t>(contentController_->GetTextValue().length());
4622     if (originCaretPosition < 0 || originCaretPosition > textLength) {
4623         return 0;
4624     }
4625     // directionMove == 0 left, directionMove == 1 right
4626     // cannot get word length by current caret position and direction
4627     if ((directionMove == 0 && originCaretPosition == 0) || (directionMove == 1 && originCaretPosition == textLength)) {
4628         return 0;
4629     }
4630     int32_t offset = 0;
4631     int32_t strIndex = directionMove == 0 ? (originCaretPosition - 1) : originCaretPosition;
4632     auto wideTextValue = contentController_->GetTextValue();
4633     int32_t wordStart = 0;
4634     int32_t wordEnd = 0;
4635     while (directionMove == 0 ? strIndex >= 0 : strIndex <= textLength) {
4636         auto chr = wideTextValue[strIndex];
4637         // skip the special character
4638         if (chr == L' ' || (chr == L'\n' && skipNewLineChar)) {
4639             if (directionMove == 0) {
4640                 strIndex--;
4641             } else {
4642                 strIndex++;
4643             }
4644             offset++;
4645             continue;
4646         }
4647         // cal word length
4648         if (paragraph_ && paragraph_->GetWordBoundary(strIndex, wordStart, wordEnd)) {
4649             if (directionMove == 1) {
4650                 offset += (wordEnd - strIndex);
4651             } else {
4652                 offset += (strIndex - wordStart + 1); // when move left, actual offset should add 1
4653             }
4654             return std::clamp(offset, 0, textLength);
4655         }
4656         // GetWordBoundary fail
4657         return 0;
4658     }
4659     return std::clamp(offset, 0, textLength);
4660 }
4661 
GetLineBeginPosition(int32_t originCaretPosition,bool needToCheckLineChanged)4662 int32_t TextFieldPattern::GetLineBeginPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
4663 {
4664     if (contentController_->IsEmpty()) {
4665         return 0;
4666     }
4667     auto wideTextValue = contentController_->GetWideText();
4668     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
4669     if (originCaretPosition < 0 || originCaretPosition > textLength) {
4670         return 0;
4671     }
4672     if (originCaretPosition == 0) {
4673         return originCaretPosition;
4674     }
4675     int32_t moveLineBeginOffset = 0;
4676     int32_t strIndex = originCaretPosition;
4677     do {
4678         moveLineBeginOffset++;
4679         strIndex--;
4680         // stop moving caret if reaches \n, text head or caret line changed
4681     } while (((strIndex > 0) && (wideTextValue[strIndex] != L'\n')) ||
4682              (needToCheckLineChanged && !CharLineChanged(strIndex)));
4683     if (strIndex < 0 || strIndex >= static_cast<int32_t>(wideTextValue.length())) {
4684         return 0;
4685     }
4686     if (wideTextValue[strIndex] == L'\n') {
4687         moveLineBeginOffset--;
4688     }
4689     if (moveLineBeginOffset > originCaretPosition) {
4690         return 0;
4691     }
4692     return originCaretPosition - moveLineBeginOffset;
4693 }
4694 
GetLineEndPosition(int32_t originCaretPosition,bool needToCheckLineChanged)4695 int32_t TextFieldPattern::GetLineEndPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
4696 {
4697     if (contentController_->IsEmpty()) {
4698         return 0;
4699     }
4700     auto wideTextValue = contentController_->GetWideText();
4701     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
4702     if (originCaretPosition < 0 || originCaretPosition > textLength) {
4703         return originCaretPosition;
4704     }
4705     if (originCaretPosition == textLength) {
4706         return originCaretPosition;
4707     }
4708     int32_t moveLineEndOffset = 0;
4709     int32_t strIndex = 0;
4710     for (strIndex = originCaretPosition; (strIndex <= textLength && wideTextValue[strIndex] != L'\n') ||
4711                                          (needToCheckLineChanged && !CharLineChanged(strIndex));
4712          strIndex++) {
4713         moveLineEndOffset++;
4714     }
4715     if (moveLineEndOffset > textLength - originCaretPosition) {
4716         return textLength;
4717     }
4718     return originCaretPosition + moveLineEndOffset;
4719 }
4720 
CharLineChanged(int32_t caretPosition)4721 bool TextFieldPattern::CharLineChanged(int32_t caretPosition)
4722 {
4723     if (caretPosition < 0 || caretPosition > static_cast<int32_t>(contentController_->GetWideText().length())) {
4724         return true;
4725     }
4726     CaretMetricsF caretMetrics;
4727     CalcCaretMetricsByPosition(selectController_->GetStartIndex(), caretMetrics);
4728     // the cursor is aligned with the text at the bottom
4729     return !NearEqual(caretMetrics.offset.GetY() + caretMetrics.height,
4730         selectController_->GetCaretRect().GetY() + selectController_->GetCaretRect().Height());
4731 }
4732 
CursorMoveLeftOperation()4733 bool TextFieldPattern::CursorMoveLeftOperation()
4734 {
4735     if (focusIndex_ != FocuseIndex::TEXT) {
4736         return UpdateFocusBackward();
4737     }
4738     auto originCaretPosition = selectController_->GetCaretIndex();
4739     if (IsSelected()) {
4740         selectController_->UpdateCaretIndex(selectController_->GetStartIndex());
4741         CloseSelectOverlay();
4742     } else {
4743         UpdateCaretPositionWithClamp(
4744             selectController_->GetCaretIndex() -
4745             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetCaretIndex(), true));
4746     }
4747     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
4748     return originCaretPosition != selectController_->GetCaretIndex();
4749 }
4750 
CursorMoveLeft()4751 bool TextFieldPattern::CursorMoveLeft()
4752 {
4753     if (inputOperations_.empty()) {
4754         return CursorMoveLeftOperation();
4755     }
4756 
4757     inputOperations_.emplace(InputOperation::CURSOR_LEFT);
4758     return false;
4759 }
4760 
CursorMoveLeftWord()4761 bool TextFieldPattern::CursorMoveLeftWord()
4762 {
4763     if (selectController_->GetCaretIndex() == 0) {
4764         return true;
4765     }
4766     int32_t originCaretPosition = selectController_->GetCaretIndex();
4767     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4768     int32_t leftWordLength = GetWordLength(originCaretPosition, 0);
4769     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
4770         return false;
4771     }
4772     if (IsSelected()) {
4773         selectController_->UpdateCaretIndex(selectController_->GetSecondHandleIndex() - leftWordLength);
4774         CloseSelectOverlay();
4775     } else {
4776         UpdateCaretPositionWithClamp(originCaretPosition - leftWordLength);
4777     }
4778     OnCursorMoveDone();
4779     return originCaretPosition != selectController_->GetCaretIndex();
4780 }
4781 
CursorMoveLineBegin()4782 bool TextFieldPattern::CursorMoveLineBegin()
4783 {
4784     if (selectController_->GetCaretIndex() == 0) {
4785         return true;
4786     }
4787     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4788     int32_t originCaretPosition = selectController_->GetCaretIndex();
4789     int32_t lineBeginPosition = GetLineBeginPosition(originCaretPosition);
4790     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
4791         return false;
4792     }
4793     if (selectController_->IsSelectedAll()) {
4794         selectController_->UpdateCaretIndex(0);
4795     } else if (IsTextArea()) {
4796         UpdateCaretPositionWithClamp(lineBeginPosition);
4797     } else {
4798         UpdateCaretPositionWithClamp(0);
4799     }
4800     OnCursorMoveDone();
4801     return originCaretPosition != selectController_->GetCaretIndex();
4802 }
4803 
CursorMoveToParagraphBegin()4804 bool TextFieldPattern::CursorMoveToParagraphBegin()
4805 {
4806     if (selectController_->GetCaretIndex() == 0) {
4807         return true;
4808     }
4809     auto originCaretPosition = selectController_->GetCaretIndex();
4810     auto newPos = GetLineBeginPosition(originCaretPosition, false);
4811     if (newPos == originCaretPosition && originCaretPosition > 0) {
4812         newPos = GetLineBeginPosition(originCaretPosition - 1, false);
4813     }
4814     UpdateCaretPositionWithClamp(newPos);
4815     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
4816     return originCaretPosition != selectController_->GetCaretIndex();
4817 }
4818 
CursorMoveHome()4819 bool TextFieldPattern::CursorMoveHome()
4820 {
4821     // ctrl + home, caret move to position 0
4822     if (selectController_->GetCaretIndex() == 0) {
4823         return true;
4824     }
4825     int32_t originCaretPosition = selectController_->GetCaretIndex();
4826     UpdateCaretPositionWithClamp(0);
4827     OnCursorMoveDone();
4828     return originCaretPosition != selectController_->GetCaretIndex();
4829 }
4830 
CursorMoveRightOperation()4831 bool TextFieldPattern::CursorMoveRightOperation()
4832 {
4833     if (focusIndex_ != FocuseIndex::TEXT) {
4834         return UpdateFocusForward();
4835     }
4836     auto originCaretPosition = selectController_->GetCaretIndex();
4837     if (IsSelected()) {
4838         CloseSelectOverlay();
4839         selectController_->UpdateCaretIndex(selectController_->GetEndIndex());
4840     } else {
4841         UpdateCaretPositionWithClamp(
4842             selectController_->GetCaretIndex() +
4843             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetCaretIndex()));
4844     }
4845     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
4846     return originCaretPosition != selectController_->GetCaretIndex();
4847 }
4848 
CursorMoveRight()4849 bool TextFieldPattern::CursorMoveRight()
4850 {
4851     if (inputOperations_.empty()) {
4852         return CursorMoveRightOperation();
4853     }
4854     inputOperations_.emplace(InputOperation::CURSOR_RIGHT);
4855     return false;
4856 }
4857 
CursorMoveRightWord()4858 bool TextFieldPattern::CursorMoveRightWord()
4859 {
4860     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
4861         return true;
4862     }
4863     int32_t originCaretPosition = selectController_->GetCaretIndex();
4864     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4865     int32_t rightWordLength = GetWordLength(originCaretPosition, 1);
4866     if (rightWordLength < 0 || rightWordLength > textLength ||
4867         rightWordLength + selectController_->GetCaretIndex() > textLength) {
4868         return false;
4869     }
4870     if (selectController_->IsSelectedAll()) {
4871         selectController_->UpdateCaretIndex(textLength);
4872     } else {
4873         UpdateCaretPositionWithClamp(originCaretPosition + rightWordLength);
4874     }
4875     OnCursorMoveDone();
4876     return originCaretPosition != selectController_->GetCaretIndex();
4877 }
4878 
CursorMoveLineEnd()4879 bool TextFieldPattern::CursorMoveLineEnd()
4880 {
4881     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
4882         return true;
4883     }
4884     int32_t originCaretPosition = selectController_->GetCaretIndex();
4885     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4886     int32_t lineEndPosition = GetLineEndPosition(originCaretPosition);
4887     if (lineEndPosition < 0 || lineEndPosition > textLength) {
4888         return false;
4889     }
4890     if (selectController_->IsSelectedAll()) {
4891         selectController_->UpdateCaretIndex(textLength);
4892     } else if (IsTextArea()) {
4893         UpdateCaretPositionWithClamp(lineEndPosition);
4894     } else {
4895         UpdateCaretPositionWithClamp(textLength);
4896     }
4897     OnCursorMoveDone();
4898     return originCaretPosition != selectController_->GetCaretIndex();
4899 }
4900 
CursorMoveToParagraphEnd()4901 bool TextFieldPattern::CursorMoveToParagraphEnd()
4902 {
4903     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
4904         return true;
4905     }
4906     auto originCaretPosition = selectController_->GetCaretIndex();
4907     auto newPos = GetLineEndPosition(originCaretPosition, false);
4908     if (newPos == originCaretPosition && originCaretPosition > 0) {
4909         newPos = GetLineEndPosition(originCaretPosition + 1, false);
4910     }
4911     UpdateCaretPositionWithClamp(newPos);
4912     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
4913     return originCaretPosition != selectController_->GetCaretIndex();
4914 }
4915 
CursorMoveEnd()4916 bool TextFieldPattern::CursorMoveEnd()
4917 {
4918     // ctrl end, caret to the very end
4919     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
4920         return true;
4921     }
4922     int32_t originCaretPosition = selectController_->GetCaretIndex();
4923     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
4924     UpdateCaretPositionWithClamp(textLength);
4925     OnCursorMoveDone();
4926     return originCaretPosition != selectController_->GetCaretIndex();
4927 }
4928 
GetFontSizePx()4929 float TextFieldPattern::GetFontSizePx()
4930 {
4931     auto theme = GetTheme();
4932     CHECK_NULL_RETURN(theme, 0.0f);
4933     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4934     CHECK_NULL_RETURN(layoutProperty, 0.0f);
4935     return layoutProperty->GetFontSizeValue(theme->GetFontSize()).ConvertToPx();
4936 }
4937 
CursorMoveUpOperation()4938 bool TextFieldPattern::CursorMoveUpOperation()
4939 {
4940     if (!IsTextArea()) {
4941         return CursorMoveToParagraphBegin();
4942     }
4943     auto originCaretPosition = selectController_->GetCaretIndex();
4944     auto offsetX = selectController_->GetCaretRect().GetX();
4945     float fontSize = GetFontSizePx();
4946     float lineHeight = 0.0f;
4947     if (fontSize > selectController_->GetCaretRect().Height()) {
4948         lineHeight = fontSize;
4949     } else {
4950         // multiply by 0.5f to convert to the grapheme center point of the previous line.
4951         lineHeight = PreferredLineHeight() * 0.5f;
4952     }
4953     auto offsetY = selectController_->GetCaretRect().GetY() - lineHeight;
4954     if (offsetY < textRect_.GetY()) {
4955         return CursorMoveToParagraphBegin();
4956     }
4957     std::optional<Offset> offset;
4958     offset.emplace(Offset(offsetX, offsetY));
4959     OnCursorMoveDone(TextAffinity::DOWNSTREAM, offset);
4960     return originCaretPosition != selectController_->GetCaretIndex();
4961 }
4962 
CursorMoveUp()4963 bool TextFieldPattern::CursorMoveUp()
4964 {
4965     if (inputOperations_.empty()) {
4966         return CursorMoveUpOperation();
4967     }
4968 
4969     inputOperations_.emplace(InputOperation::CURSOR_UP);
4970     return false;
4971 }
4972 
CursorMoveDownOperation()4973 bool TextFieldPattern::CursorMoveDownOperation()
4974 {
4975     if (!IsTextArea()) {
4976         return CursorMoveToParagraphEnd();
4977     }
4978     auto originCaretPosition = selectController_->GetCaretIndex();
4979     auto offsetX = selectController_->GetCaretRect().GetX();
4980     float fontSize = GetFontSizePx();
4981     float lineHeight = 0.0f;
4982     if (fontSize > selectController_->GetCaretRect().Height()) {
4983         lineHeight = fontSize;
4984     } else {
4985         // multiply by 1.5f to convert to the grapheme center point of the next line.
4986         lineHeight = PreferredLineHeight() * 1.5f;
4987     }
4988     auto offsetY = selectController_->GetCaretRect().GetY() + lineHeight;
4989     if (offsetY > textRect_.GetY() + textRect_.Height()) {
4990         return CursorMoveToParagraphEnd();
4991     }
4992     std::optional<Offset> offset;
4993     offset.emplace(Offset(offsetX, offsetY));
4994     OnCursorMoveDone(TextAffinity::DOWNSTREAM, offset);
4995     return originCaretPosition != selectController_->GetCaretIndex();
4996 }
4997 
CursorMoveDown()4998 bool TextFieldPattern::CursorMoveDown()
4999 {
5000     if (inputOperations_.empty()) {
5001         return CursorMoveDownOperation();
5002     }
5003 
5004     inputOperations_.emplace(InputOperation::CURSOR_DOWN);
5005     return false;
5006 }
5007 
Delete(int32_t start,int32_t end)5008 void TextFieldPattern::Delete(int32_t start, int32_t end)
5009 {
5010     SwapIfLarger(start, end);
5011     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Handle Delete within [%{public}d, %{public}d]", start, end);
5012     contentController_->erase(start, end - start);
5013     UpdateSelection(start);
5014     selectController_->MoveCaretToContentRect(start);
5015     CloseSelectOverlay(true);
5016     StartTwinkling();
5017     UpdateEditingValueToRecord();
5018     auto tmpHost = GetHost();
5019     CHECK_NULL_VOID(tmpHost);
5020     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5021 }
5022 
ClearEditingValue()5023 void TextFieldPattern::ClearEditingValue()
5024 {
5025     contentController_->Reset();
5026     selectController_->UpdateCaretIndex(0);
5027     UpdateEditingValueToRecord();
5028     auto tmpHost = GetHost();
5029     CHECK_NULL_VOID(tmpHost);
5030     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5031     CHECK_NULL_VOID(layoutProperty);
5032     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5033 }
5034 
HandleCounterBorder()5035 void TextFieldPattern::HandleCounterBorder()
5036 {
5037     auto theme = GetTheme();
5038     CHECK_NULL_VOID(theme);
5039     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5040     CHECK_NULL_VOID(paintProperty);
5041     auto host = GetHost();
5042     CHECK_NULL_VOID(host);
5043     auto renderContext = host->GetRenderContext();
5044     CHECK_NULL_VOID(renderContext);
5045     if (showCountBorderStyle_) {
5046         if (IsUnderlineMode()) {
5047             underlineWidth_ = ERROR_UNDERLINE_WIDTH;
5048             SetUnderlineColor(userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor()));
5049         } else {
5050             if (!paintProperty->HasBorderWidthFlagByUser()) {
5051                 paintProperty->UpdateInnerBorderWidth(OVER_COUNT_BORDER_WIDTH);
5052                 paintProperty->UpdateInnerBorderColor(theme->GetOverCounterColor());
5053             } else {
5054                 BorderColorProperty overCountBorderColor;
5055                 overCountBorderColor.SetColor(theme->GetOverCounterColor());
5056                 renderContext->UpdateBorderColor(overCountBorderColor);
5057             }
5058         }
5059     } else {
5060         if (IsUnderlineMode() && !IsShowError()) {
5061             ApplyUnderlineTheme();
5062             UpdateCounterMargin();
5063         } else {
5064             SetThemeBorderAttr();
5065         }
5066     }
5067 }
5068 
ProcessFocusIndexAction()5069 bool TextFieldPattern::ProcessFocusIndexAction()
5070 {
5071     if (focusIndex_ == FocuseIndex::CANCEL) {
5072         CleanNodeResponseKeyEvent();
5073         return false;
5074     }
5075     if (focusIndex_ == FocuseIndex::UNIT) {
5076         if (IsShowPasswordIcon()) {
5077             PasswordResponseKeyEvent();
5078         }
5079         if (IsShowUnit()) {
5080             UnitResponseKeyEvent();
5081         }
5082         return false;
5083     }
5084     return true;
5085 }
5086 
PerformAction(TextInputAction action,bool forceCloseKeyboard)5087 void TextFieldPattern::PerformAction(TextInputAction action, bool forceCloseKeyboard)
5088 {
5089     if (!ProcessFocusIndexAction()) {
5090         return;
5091     }
5092     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField PerformAction  %{public}d", static_cast<int32_t>(action));
5093     auto host = GetHost();
5094     CHECK_NULL_VOID(host);
5095     // If the parent node is a Search, the Search callback is executed.
5096     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5097     CHECK_NULL_VOID(paintProperty);
5098     auto eventHub = host->GetEventHub<TextFieldEventHub>();
5099     CHECK_NULL_VOID(eventHub);
5100     TextFieldCommonEvent event;
5101     event.SetText(contentController_->GetTextValue());
5102     if (IsNormalInlineState() && action != TextInputAction::NEW_LINE) {
5103         eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
5104         RecordSubmitEvent();
5105         if (event.IsKeepEditable()) {
5106             return;
5107         }
5108         FocusHub::LostFocusToViewRoot();
5109         return;
5110     }
5111     if (IsTextArea() && action == TextInputAction::NEW_LINE) {
5112         if (!textAreaBlurOnSubmit_) {
5113             if (GetInputFilter() != "\n") {
5114                 InsertValue("\n", true);
5115             }
5116         } else {
5117             CloseKeyboard(forceCloseKeyboard, false);
5118             FocusHub::LostFocusToViewRoot();
5119         }
5120         return;
5121     }
5122     eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
5123     RecordSubmitEvent();
5124     if (event.IsKeepEditable()) {
5125         return;
5126     }
5127     // LostFocusToViewRoot may not cause current lost focus, only stop twinkling when it is truly lost focus,
5128     // which will call StopTwinkling on HandleBlurEvent method.
5129     if (textInputBlurOnSubmit_) {
5130         CloseKeyboard(forceCloseKeyboard, false);
5131         FocusHub::LostFocusToViewRoot();
5132     }
5133 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
5134     UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "Textfield.onSubmit");
5135 #endif
5136 }
5137 
RecordSubmitEvent() const5138 void TextFieldPattern::RecordSubmitEvent() const
5139 {
5140     if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
5141         return;
5142     }
5143     auto host = GetHost();
5144     CHECK_NULL_VOID(host);
5145     auto inspectorId = host->GetInspectorId().value_or("");
5146     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5147     bool isPwdType = layoutProperty ? layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) ==
5148                                           TextInputType::VISIBLE_PASSWORD
5149                                     : false;
5150     Recorder::EventParamsBuilder builder;
5151     builder.SetId(inspectorId)
5152         .SetType(host->GetTag())
5153         .SetEventType(Recorder::EventType::SEARCH_SUBMIT)
5154         .SetDescription(host->GetAutoEventParamValue(""));
5155     if (!isPwdType) {
5156         builder.SetText(contentController_->GetTextValue());
5157     }
5158     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
5159 }
5160 
UpdateEditingValue(const std::shared_ptr<TextEditingValue> & value,bool needFireChangeEvent)5161 void TextFieldPattern::UpdateEditingValue(const std::shared_ptr<TextEditingValue>& value, bool needFireChangeEvent)
5162 {
5163 #if !defined(ENABLE_STANDARD_INPUT)
5164     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5165     if (layoutProperty && layoutProperty->HasMaxLength()) {
5166         bool textChange = false;
5167         auto result = value->text;
5168         contentController_->FilterTextInputStyle(textChange, result);
5169         auto resultLen = static_cast<int32_t>(StringUtils::ToWstring(result).length());
5170         auto maxLen = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
5171         if (resultLen != maxLen) {
5172             showCountBorderStyle_ = resultLen > maxLen;
5173             HandleCountStyle();
5174         }
5175     }
5176 #endif
5177     contentController_->SetTextValue(value->text);
5178     selectController_->UpdateCaretIndex(value->selection.baseOffset);
5179     ContainerScope scope(GetInstanceId());
5180     UpdateEditingValueToRecord();
5181     CloseSelectOverlay();
5182     StartTwinkling();
5183     auto host = GetHost();
5184     CHECK_NULL_VOID(host);
5185 
5186     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5187 }
5188 
UpdateInputFilterErrorText(const std::string & errorText)5189 void TextFieldPattern::UpdateInputFilterErrorText(const std::string& errorText)
5190 {
5191     if (!errorText.empty()) {
5192         auto tmpHost = GetHost();
5193         CHECK_NULL_VOID(tmpHost);
5194         auto textFieldEventHub = tmpHost->GetEventHub<TextFieldEventHub>();
5195         CHECK_NULL_VOID(textFieldEventHub);
5196         textFieldEventHub->FireOnInputFilterError(errorText);
5197     }
5198 }
5199 
OnValueChanged(bool needFireChangeEvent,bool needFireSelectChangeEvent)5200 void TextFieldPattern::OnValueChanged(bool needFireChangeEvent, bool needFireSelectChangeEvent) {}
5201 
OnHandleAreaChanged()5202 void TextFieldPattern::OnHandleAreaChanged()
5203 {
5204     auto parentGlobalOffset = GetPaintRectGlobalOffset();
5205     if (parentGlobalOffset != parentGlobalOffset_) {
5206         parentGlobalOffset_ = parentGlobalOffset;
5207         UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
5208         HandleParentGlobalOffsetChange();
5209     }
5210 }
5211 
HandleParentGlobalOffsetChange()5212 void TextFieldPattern::HandleParentGlobalOffsetChange()
5213 {
5214     selectController_->CalculateHandleOffset();
5215     CHECK_NULL_VOID(SelectOverlayIsOn() || selectOverlay_->SelectOverlayIsCreating());
5216     if (selectOverlay_->IsShowMouseMenu()) {
5217         CloseSelectOverlay();
5218     } else {
5219         selectOverlay_->ProcessOverlayOnAreaChanged({ .menuIsShow = false });
5220     }
5221 }
5222 
RequestKeyboardByFocusSwitch()5223 void TextFieldPattern::RequestKeyboardByFocusSwitch()
5224 {
5225     auto host = GetHost();
5226     CHECK_NULL_VOID(host);
5227     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
5228         "%{public}d RequestKeyboardByFocusSwitch: onFocus_: %{public}d Inner: %{public}d modalCovered: %{public}d",
5229         host->GetId(), needToRequestKeyboardOnFocus_, needToRequestKeyboardInner_, IsModalCovered());
5230     if (!needToRequestKeyboardInner_ || IsModalCovered()) {
5231         return;
5232     }
5233     auto pipeline = host->GetContextRefPtr();
5234     CHECK_NULL_VOID(pipeline);
5235     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
5236     CHECK_NULL_VOID(textFieldManager);
5237     textFieldManager->SetNeedToRequestKeyboard(true);
5238     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d add requestkeyboard task", host->GetId());
5239     pipeline->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)]() {
5240         auto textField = weak.Upgrade();
5241         CHECK_NULL_VOID(textField);
5242         auto textFieldManager = manager.Upgrade();
5243         if (textFieldManager && !textFieldManager->GetNeedToRequestKeyboard()) {
5244             // already call close/attach keyboard after text field get focus, so dont request keyboard now
5245             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Already call close/attach before attach, no need attach this time");
5246             return;
5247         }
5248         if (!textField->needToRequestKeyboardInner_) {
5249             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Not need to requestKeyboard inner");
5250             return;
5251         }
5252         if (!textField->RequestKeyboard(false, true, textField->needToRequestKeyboardOnFocus_)) {
5253             return;
5254         }
5255         textField->NotifyOnEditChanged(true);
5256         textField->needToRequestKeyboardInner_ = false;
5257     });
5258 }
5259 
5260 // to distiguish request keyboard not by focus switching
RequestKeyboardNotByFocusSwitch(RequestKeyboardReason reason)5261 bool TextFieldPattern::RequestKeyboardNotByFocusSwitch(RequestKeyboardReason reason)
5262 {
5263     auto tmpHost = GetHost();
5264     CHECK_NULL_RETURN(tmpHost, false);
5265     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d requestKeyboard With Reason %{public}s",
5266         tmpHost->GetId(), TextFieldPattern::RequestKeyboardReasonToString(reason).c_str());
5267     if (!RequestKeyboard(false, true, true)) {
5268         return false;
5269     }
5270     auto context = tmpHost->GetContextRefPtr();
5271     CHECK_NULL_RETURN(context, true);
5272     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
5273     CHECK_NULL_RETURN(textFieldManager, true);
5274     textFieldManager->SetNeedToRequestKeyboard(false);
5275     return true;
5276 }
5277 
TextFieldRequestFocus(RequestFocusReason reason)5278 bool TextFieldPattern::TextFieldRequestFocus(RequestFocusReason reason)
5279 {
5280     if (HasFocus()) {
5281         return true;
5282     }
5283     auto host = GetHost();
5284     CHECK_NULL_RETURN(host, false);
5285     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d Request Focus With Reason %{public}s",
5286         host->GetId(), TextFieldPattern::RequestFocusReasonToString(reason).c_str());
5287     auto focusHub = GetFocusHub();
5288     CHECK_NULL_RETURN(focusHub, false);
5289     return focusHub->RequestFocusImmediately();
5290 }
5291 
RequestFocusReasonToString(RequestFocusReason reason)5292 std::string TextFieldPattern::RequestFocusReasonToString(RequestFocusReason reason)
5293 {
5294     switch (reason) {
5295         case RequestFocusReason::DRAG_END: {
5296             return "DragEnd";
5297         }
5298         case RequestFocusReason::DRAG_MOVE: {
5299             return "DragMove";
5300         }
5301         case RequestFocusReason::CLICK: {
5302             return "Click";
5303         }
5304         case RequestFocusReason::LONG_PRESS: {
5305             return "LongPress";
5306         }
5307         case RequestFocusReason::AUTO_FILL: {
5308             return "AutoFill";
5309         }
5310         case RequestFocusReason::CLEAN_NODE: {
5311             return "CleanNode";
5312         }
5313         case RequestFocusReason::MOUSE: {
5314             return "Mouse";
5315         }
5316         case RequestFocusReason::UNKNOWN:
5317         default: {
5318             break;
5319         }
5320     }
5321     return "Unknown";
5322 }
5323 
RequestKeyboardReasonToString(RequestKeyboardReason reason)5324 std::string TextFieldPattern::RequestKeyboardReasonToString(RequestKeyboardReason reason)
5325 {
5326     switch (reason) {
5327         case RequestKeyboardReason::ON_KEY_EVENT: {
5328             return "KeyEvent";
5329         }
5330         case RequestKeyboardReason::SINGLE_CLICK: {
5331             return "SingleClick";
5332         }
5333         case RequestKeyboardReason::DOUBLE_CLICK: {
5334             return "DoubleClick";
5335         }
5336         case RequestKeyboardReason::LONG_PRESS: {
5337             return "LongPress";
5338         }
5339         case RequestKeyboardReason::RESET_KEYBOARD: {
5340             return "ResetKeyboard";
5341         }
5342         case RequestKeyboardReason::MOUSE_RELEASE: {
5343             return "MouseRelease";
5344         }
5345         case RequestKeyboardReason::SET_SELECTION: {
5346             return "SetSelection";
5347         }
5348         case RequestKeyboardReason::SEARCH_REQUEST: {
5349             return "SearchRequest";
5350         }
5351         case RequestKeyboardReason::AUTO_FILL_REQUEST_FAIL: {
5352             return "AutoFillRequestFail";
5353         }
5354         case RequestKeyboardReason::SHOW_KEYBOARD_ON_FOCUS: {
5355             return "ShowKeyboardOnFocus";
5356         }
5357         case RequestKeyboardReason::STYLUS_DETECTOR: {
5358             return "StylusDetector";
5359         }
5360         case RequestKeyboardReason::CUSTOM_KEYBOARD: {
5361             return "CustomKeyboard";
5362         }
5363         case RequestKeyboardReason::UNKNOWN:
5364         default: {
5365             break;
5366         }
5367     }
5368     return "Unknown";
5369 }
5370 
IsModalCovered()5371 bool TextFieldPattern::IsModalCovered()
5372 {
5373     auto host = GetHost();
5374     CHECK_NULL_RETURN(host, false);
5375     auto pageNode = host->GetPageNode();
5376     CHECK_NULL_RETURN(pageNode, false);
5377     auto pagePattern = pageNode->GetPattern<PagePattern>();
5378     CHECK_NULL_RETURN(pagePattern, false);
5379     return pagePattern->GetIsModalCovered();
5380 }
5381 
OnVisibleChange(bool isVisible)5382 void TextFieldPattern::OnVisibleChange(bool isVisible)
5383 {
5384     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "visible change to %{public}d", isVisible);
5385     if (!isVisible && HasFocus()) {
5386         CloseKeyboard(true);
5387         if (SelectOverlayIsOn()) {
5388             StartTwinkling();
5389         }
5390     }
5391 }
5392 
HandleSurfaceChanged(int32_t newWidth,int32_t newHeight,int32_t prevWidth,int32_t prevHeight)5393 void TextFieldPattern::HandleSurfaceChanged(int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight)
5394 {
5395     if (newWidth == prevWidth && newHeight == prevHeight) {
5396         return;
5397     }
5398     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
5399         "Textfield handleSurface change, new width %{public}d, new height %{public}d, prev width %{public}d, prev "
5400         "height %{public}d",
5401         newWidth, newHeight, prevWidth, prevHeight);
5402     if (SelectOverlayIsOn()) {
5403         if (selectOverlay_->IsShowMouseMenu()) {
5404             CloseSelectOverlay();
5405         } else if (newWidth != prevWidth || newHeight != prevHeight) {
5406             DelayProcessOverlay({ .menuIsShow = false });
5407         }
5408     }
5409     auto tmpHost = GetHost();
5410     CHECK_NULL_VOID(tmpHost);
5411     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5412     UpdateCaretInfoToController(true);
5413     if (magnifierController_->GetShowMagnifier()) {
5414         magnifierController_->RemoveMagnifierFrameNode();
5415     }
5416 }
5417 
HandleSurfacePositionChanged(int32_t posX,int32_t posY)5418 void TextFieldPattern::HandleSurfacePositionChanged(int32_t posX, int32_t posY)
5419 {
5420     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield handleSurface position change, posX %{public}d, posY %{public}d",
5421         posX, posY);
5422     UpdateCaretInfoToController();
5423 }
5424 
InitSurfaceChangedCallback()5425 void TextFieldPattern::InitSurfaceChangedCallback()
5426 {
5427     auto pipeline = PipelineContext::GetCurrentContext();
5428     CHECK_NULL_VOID(pipeline);
5429     if (!HasSurfaceChangedCallback()) {
5430         auto callbackId = pipeline->RegisterSurfaceChangedCallback(
5431             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
5432                 WindowSizeChangeReason type) {
5433                 auto pattern = weak.Upgrade();
5434                 if (pattern) {
5435                     pattern->HandleSurfaceChanged(newWidth, newHeight, prevWidth, prevHeight);
5436                 }
5437             });
5438         UpdateSurfaceChangedCallbackId(callbackId);
5439     }
5440 }
5441 
InitSurfacePositionChangedCallback()5442 void TextFieldPattern::InitSurfacePositionChangedCallback()
5443 {
5444     auto pipeline = PipelineContext::GetCurrentContext();
5445     CHECK_NULL_VOID(pipeline);
5446     if (!HasSurfacePositionChangedCallback()) {
5447         auto callbackId =
5448             pipeline->RegisterSurfacePositionChangedCallback([weak = WeakClaim(this)](int32_t posX, int32_t posY) {
5449                 auto pattern = weak.Upgrade();
5450                 if (pattern) {
5451                     pattern->HandleSurfacePositionChanged(posX, posY);
5452                 }
5453             });
5454         UpdateSurfacePositionChangedCallbackId(callbackId);
5455     }
5456 }
5457 
HandleOnDelete(bool backward)5458 void TextFieldPattern::HandleOnDelete(bool backward)
5459 {
5460     if (backward) {
5461 #if defined(PREVIEW)
5462         DeleteForward(1);
5463 #else
5464         DeleteBackward(1);
5465 #endif
5466     } else {
5467 #if defined(PREVIEW)
5468         DeleteBackward(1);
5469 #else
5470         DeleteForward(1);
5471 #endif
5472     }
5473 }
5474 
HandleOnDeleteComb(bool backward)5475 bool TextFieldPattern::HandleOnDeleteComb(bool backward)
5476 {
5477     if (backward) {
5478         DeleteBackwardWord(); // LTR is left word,RTL is right word
5479     } else {
5480         DeleteForwardWord(); // LTR is right word,RTL is left word
5481     }
5482     return true;
5483 }
5484 
DeleteBackwardWord()5485 void TextFieldPattern::DeleteBackwardWord()
5486 {
5487     int32_t originCaretPosition = selectController_->GetCaretIndex();
5488     int32_t textLength = static_cast<int32_t>(contentController_->GetTextValue().length());
5489     int32_t leftWordLength = GetWordLength(originCaretPosition, 0, false);
5490     if (leftWordLength < 0) {
5491         // delete 1 char
5492         leftWordLength = 1;
5493     }
5494     if (leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
5495         // delete left
5496         leftWordLength = std::max(1, originCaretPosition);
5497     }
5498     DeleteBackward(leftWordLength);
5499 }
5500 
DeleteForwardWord()5501 void TextFieldPattern::DeleteForwardWord()
5502 {
5503     int32_t originCaretPosition = selectController_->GetCaretIndex();
5504     int32_t textLength = static_cast<int32_t>(contentController_->GetTextValue().length());
5505     int32_t rightWordLength = GetWordLength(originCaretPosition, 1, false);
5506     if (rightWordLength < 0) {
5507         // delete 1 char
5508         rightWordLength = 1;
5509     }
5510     if (rightWordLength > textLength || rightWordLength + selectController_->GetCaretIndex() > textLength) {
5511         // delete right
5512         rightWordLength = std::max(1, textLength - originCaretPosition);
5513     }
5514     DeleteForward(rightWordLength);
5515 }
5516 
HandleOnPageUp()5517 void TextFieldPattern::HandleOnPageUp()
5518 {
5519     if (!IsTextArea()) {
5520         return;
5521     }
5522     auto border = GetBorderWidthProperty();
5523     float frameRectHeight = std::max(frameRect_.Height(), GetFontSizePx());
5524     float maxFrameHeight =
5525         frameRectHeight - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
5526     OnScrollCallback(maxFrameHeight, SCROLL_FROM_JUMP);
5527     auto caretRectOffset = selectController_->GetCaretRect().GetOffset();
5528     Offset offset(caretRectOffset.GetX(), GetPaddingTop() + GetBorderTop(border));
5529     selectController_->UpdateCaretInfoByOffset(offset);
5530     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5531 }
5532 
HandleOnPageDown()5533 void TextFieldPattern::HandleOnPageDown()
5534 {
5535     if (!IsTextArea()) {
5536         return;
5537     }
5538     auto border = GetBorderWidthProperty();
5539     float frameRectHeight = std::max(frameRect_.Height(), GetFontSizePx());
5540     float maxFrameHeight =
5541         frameRectHeight - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
5542     OnScrollCallback(-maxFrameHeight, SCROLL_FROM_JUMP);
5543     auto caretRectOffset = selectController_->GetCaretRect().GetOffset();
5544     Offset offset(caretRectOffset.GetX(), maxFrameHeight);
5545     selectController_->UpdateCaretInfoByOffset(offset);
5546     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5547 }
5548 
GetEmojiSubStringRange(int32_t & start,int32_t & end)5549 void TextFieldPattern::GetEmojiSubStringRange(int32_t& start, int32_t& end)
5550 {
5551     TextEmojiSubStringRange range = TextEmojiProcessor::CalSubWstringRange(
5552         start, end - start, GetWideText(), true);
5553     start = range.startIndex;
5554     end = range.endIndex;
5555 }
5556 
DeleteBackward(int32_t length)5557 void TextFieldPattern::DeleteBackward(int32_t length)
5558 {
5559     ResetObscureTickCountDown();
5560     if (IsSelected()) {
5561         auto start = selectController_->GetStartIndex();
5562         auto end = selectController_->GetEndIndex();
5563         GetEmojiSubStringRange(start, end);
5564         DeleteRange(start, end);
5565         return;
5566     }
5567     if (selectController_->GetCaretIndex() <= 0) {
5568         auto isDelete = BeforeIMEDeleteValue("", TextDeleteDirection::BACKWARD, 0);
5569         CHECK_NULL_VOID(isDelete);
5570         AfterIMEDeleteValue("", TextDeleteDirection::BACKWARD);
5571         return;
5572     }
5573     inputOperations_.emplace(InputOperation::DELETE_BACKWARD);
5574     deleteBackwardOperations_.emplace(length);
5575     CloseSelectOverlay();
5576     ScrollToSafeArea();
5577     auto tmpHost = GetHost();
5578     CHECK_NULL_VOID(tmpHost);
5579     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5580 }
5581 
DeleteBackwardOperation(int32_t length)5582 void TextFieldPattern::DeleteBackwardOperation(int32_t length)
5583 {
5584     int32_t idx = selectController_->GetCaretIndex();
5585     auto willDeleteLength = contentController_->GetDeleteLength(idx, length, true);
5586     auto value = contentController_->GetSelectedValue(idx - willDeleteLength, idx);
5587     auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::BACKWARD, idx);
5588     CHECK_NULL_VOID(isDelete);
5589     auto oldContent = contentController_->GetTextValue();
5590     int32_t count = contentController_->Delete(selectController_->GetCaretIndex(), length, true);
5591     auto isOnWillChange = OnWillChangePreDelete(oldContent, std::max(idx - count, 0), idx);
5592     if (!isOnWillChange) {
5593         contentController_->SetTextValue(oldContent);
5594         return;
5595     }
5596     selectController_->UpdateCaretIndex(std::max(idx - count, 0));
5597     if (GetIsPreviewText()) {
5598         UpdatePreviewIndex(GetPreviewTextStart(), GetPreviewTextEnd() - length);
5599     }
5600     AfterIMEDeleteValue(value, TextDeleteDirection::BACKWARD);
5601     StartTwinkling();
5602     UpdateEditingValueToRecord();
5603 }
5604 
DeleteForwardOperation(int32_t length)5605 void TextFieldPattern::DeleteForwardOperation(int32_t length)
5606 {
5607     auto caretIndex = selectController_->GetCaretIndex();
5608     auto willDeleteLength = contentController_->GetDeleteLength(caretIndex, length, false);
5609     auto value = contentController_->GetSelectedValue(caretIndex, caretIndex + willDeleteLength);
5610     auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::FORWARD, caretIndex);
5611     CHECK_NULL_VOID(isDelete);
5612     ResetObscureTickCountDown();
5613     auto oldContent = contentController_->GetTextValue();
5614     contentController_->Delete(caretIndex, length, false);
5615     if (GetIsPreviewText()) {
5616         UpdatePreviewIndex(GetPreviewTextStart(), GetPreviewTextEnd() - length);
5617     }
5618     auto isOnWillChange = OnWillChangePreDelete(oldContent, caretIndex, caretIndex + willDeleteLength);
5619     if (!isOnWillChange) {
5620         contentController_->SetTextValue(oldContent);
5621         return;
5622     }
5623     AfterIMEDeleteValue(value, TextDeleteDirection::FORWARD);
5624     StartTwinkling();
5625     UpdateEditingValueToRecord();
5626 }
5627 
DeleteForward(int32_t length)5628 void TextFieldPattern::DeleteForward(int32_t length)
5629 {
5630     if (IsSelected()) {
5631         auto start = selectController_->GetStartIndex();
5632         auto end = selectController_->GetEndIndex();
5633         GetEmojiSubStringRange(start, end);
5634         DeleteRange(start, end);
5635         return;
5636     }
5637     auto contentLength = static_cast<int32_t>(contentController_->GetWideText().length());
5638     if (selectController_->GetCaretIndex() >= contentLength) {
5639         auto isDelete = BeforeIMEDeleteValue("", TextDeleteDirection::FORWARD, contentLength);
5640         CHECK_NULL_VOID(isDelete);
5641         AfterIMEDeleteValue("", TextDeleteDirection::FORWARD);
5642         return;
5643     }
5644     inputOperations_.emplace(InputOperation::DELETE_FORWARD);
5645     deleteForwardOperations_.emplace(length);
5646     CloseSelectOverlay();
5647     auto tmpHost = GetHost();
5648     CHECK_NULL_VOID(tmpHost);
5649     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5650 }
5651 
BeforeIMEDeleteValue(const std::string & deleteValue,TextDeleteDirection direction,int32_t offset)5652 bool TextFieldPattern::BeforeIMEDeleteValue(
5653     const std::string& deleteValue, TextDeleteDirection direction, int32_t offset)
5654 {
5655     auto host = GetHost();
5656     CHECK_NULL_RETURN(host, true);
5657     auto eventHub = host->GetEventHub<TextFieldEventHub>();
5658     CHECK_NULL_RETURN(eventHub, true);
5659     DeleteValueInfo deleteValueInfo;
5660     deleteValueInfo.deleteOffset = offset;
5661     deleteValueInfo.deleteValue = deleteValue;
5662     deleteValueInfo.direction = direction;
5663     return eventHub->FireOnWillDeleteEvent(deleteValueInfo);
5664 }
5665 
AfterIMEDeleteValue(const std::string & deleteValue,TextDeleteDirection direction)5666 void TextFieldPattern::AfterIMEDeleteValue(const std::string& deleteValue, TextDeleteDirection direction)
5667 {
5668     auto host = GetHost();
5669     CHECK_NULL_VOID(host);
5670     auto eventHub = host->GetEventHub<TextFieldEventHub>();
5671     CHECK_NULL_VOID(eventHub);
5672     DeleteValueInfo deleteValueInfo;
5673     deleteValueInfo.deleteOffset = selectController_->GetCaretIndex();
5674     deleteValueInfo.deleteValue = deleteValue;
5675     deleteValueInfo.direction = direction;
5676     return eventHub->FireOnDidDeleteValueEvent(deleteValueInfo);
5677 }
5678 
GetLeftTextOfCursor(int32_t number)5679 std::u16string TextFieldPattern::GetLeftTextOfCursor(int32_t number)
5680 {
5681     auto start = selectController_->GetCaretIndex();
5682     if (IsSelected()) {
5683         start = selectController_->GetStartIndex();
5684     }
5685     auto stringText = contentController_->GetSelectedValue(start - number, start);
5686     return StringUtils::Str8ToStr16(stringText);
5687 }
5688 
GetRightTextOfCursor(int32_t number)5689 std::u16string TextFieldPattern::GetRightTextOfCursor(int32_t number)
5690 {
5691     auto end = selectController_->GetCaretIndex();
5692     if (IsSelected()) {
5693         end = selectController_->GetEndIndex();
5694     }
5695     auto stringText = contentController_->GetSelectedValue(end, end + number);
5696     return StringUtils::Str8ToStr16(stringText);
5697 }
5698 
GetTextIndexAtCursor()5699 int32_t TextFieldPattern::GetTextIndexAtCursor()
5700 {
5701     return selectController_->GetCaretIndex();
5702 }
5703 
AfterSelection()5704 void TextFieldPattern::AfterSelection()
5705 {
5706     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Selection %{public}s, caret position %{public}d",
5707         selectController_->ToString().c_str(), selectController_->GetCaretIndex());
5708     ResetObscureTickCountDown();
5709     auto tmpHost = GetHost();
5710     CHECK_NULL_VOID(tmpHost);
5711     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5712     showSelect_ = IsSelected();
5713 }
5714 
HandleSelectionUp()5715 void TextFieldPattern::HandleSelectionUp()
5716 {
5717     if (!IsSelected()) {
5718         UpdateSelection(selectController_->GetCaretIndex());
5719     }
5720     auto newOffsetY = selectController_->GetCaretRect().GetY() - PreferredLineHeight() * 0.5 - textRect_.GetY();
5721     if (GreatOrEqual(newOffsetY, 0.0)) {
5722         OffsetF originCaretPosition;
5723         auto caretXPosition = GetOriginCaretPosition(originCaretPosition) &&
5724             GreatNotEqual(selectController_->GetCaretRect().GetX() - contentRect_.GetX(), 0) ? // handle when line head
5725             originCaretPosition.GetX() : selectController_->GetCaretRect().GetX();
5726         selectController_->MoveSecondHandleByKeyBoard(paragraph_->GetGlyphIndexByCoordinate(
5727             Offset(caretXPosition - contentRect_.GetX(), newOffsetY)));
5728     } else {
5729         selectController_->MoveSecondHandleByKeyBoard(0);
5730     }
5731     AfterSelection();
5732 }
5733 
HandleSelectionDown()5734 void TextFieldPattern::HandleSelectionDown()
5735 {
5736     if (!IsTextArea()) {
5737         return;
5738     }
5739     if (!IsSelected()) {
5740         UpdateSelection(selectController_->GetCaretIndex());
5741     }
5742     auto newOffsetY = selectController_->GetCaretRect().GetY() + PreferredLineHeight() * 1.5 - textRect_.GetY();
5743     if (LessOrEqual(newOffsetY, textRect_.Height())) {
5744         OffsetF originCaretPosition;
5745         auto caretXPosition = GetOriginCaretPosition(originCaretPosition) ?
5746             originCaretPosition.GetX() : selectController_->GetCaretRect().GetX();
5747         selectController_->MoveSecondHandleByKeyBoard(paragraph_->GetGlyphIndexByCoordinate(
5748             Offset(caretXPosition - contentRect_.GetX(), newOffsetY)));
5749     } else {
5750         selectController_->MoveSecondHandleByKeyBoard(static_cast<int32_t>(contentController_->GetWideText().length()));
5751     }
5752     AfterSelection();
5753 }
5754 
HandleSelectionLeft()5755 void TextFieldPattern::HandleSelectionLeft()
5756 {
5757     if (!IsSelected()) {
5758         if (selectController_->GetCaretIndex() == 0) {
5759             return;
5760         }
5761         UpdateSelection(selectController_->GetCaretIndex());
5762         selectController_->MoveSecondHandleByKeyBoard(
5763             selectController_->GetSecondHandleIndex() -
5764             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetCaretIndex(), true));
5765     } else {
5766         selectController_->MoveSecondHandleByKeyBoard(
5767             selectController_->GetSecondHandleIndex() - GetGraphemeClusterLength(contentController_->GetWideText(),
5768                                                             selectController_->GetSecondHandleIndex(), true));
5769     }
5770     AfterSelection();
5771 }
5772 
HandleSelectionLeftWord()5773 void TextFieldPattern::HandleSelectionLeftWord()
5774 {
5775     if (selectController_->GetCaretIndex() == 0) {
5776         return;
5777     }
5778     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
5779     int32_t leftWordLength = GetWordLength(selectController_->GetCaretIndex(), 0);
5780     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
5781         return;
5782     }
5783     if (!IsSelected()) {
5784         UpdateSelection(selectController_->GetCaretIndex());
5785         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
5786     } else {
5787         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
5788     }
5789     AfterSelection();
5790 }
5791 
HandleSelectionLineBegin()5792 void TextFieldPattern::HandleSelectionLineBegin()
5793 {
5794     if (selectController_->GetCaretIndex() == 0) {
5795         return;
5796     }
5797     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
5798     int32_t lineBeginPosition = GetLineBeginPosition(selectController_->GetCaretIndex());
5799     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
5800         return;
5801     }
5802     if (!IsSelected()) {
5803         UpdateSelection(selectController_->GetCaretIndex());
5804         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
5805     } else {
5806         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
5807     }
5808     AfterSelection();
5809 }
5810 
HandleSelectionHome()5811 void TextFieldPattern::HandleSelectionHome()
5812 {
5813     if (selectController_->GetCaretIndex() == 0) {
5814         return;
5815     }
5816     if (!IsSelected()) {
5817         UpdateSelection(selectController_->GetCaretIndex());
5818         selectController_->MoveSecondHandleByKeyBoard(0);
5819     } else {
5820         selectController_->MoveSecondHandleByKeyBoard(0);
5821     }
5822     AfterSelection();
5823 }
5824 
HandleSelectionRight()5825 void TextFieldPattern::HandleSelectionRight()
5826 {
5827     // if currently not in select mode, reset baseOffset and move destinationOffset and caret position
5828     if (!IsSelected()) {
5829         if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetWideText().length())) {
5830             return;
5831         }
5832         UpdateSelection(selectController_->GetCaretIndex());
5833         selectController_->MoveSecondHandleByKeyBoard(
5834             selectController_->GetSecondHandleIndex() +
5835             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetSecondHandleIndex()));
5836     } else {
5837         // if currently not in select mode, move destinationOffset and caret position only
5838         selectController_->MoveSecondHandleByKeyBoard(
5839             selectController_->GetSecondHandleIndex() +
5840             GetGraphemeClusterLength(contentController_->GetWideText(), selectController_->GetSecondHandleIndex()));
5841     }
5842     AfterSelection();
5843 }
5844 
HandleSelectionRightWord()5845 void TextFieldPattern::HandleSelectionRightWord()
5846 {
5847     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
5848     if (selectController_->GetCaretIndex() == textLength) {
5849         return;
5850     }
5851     int32_t rightWordLength = GetWordLength(selectController_->GetCaretIndex(), 1);
5852     if (rightWordLength < 0 || rightWordLength > textLength ||
5853         rightWordLength + selectController_->GetCaretIndex() > textLength) {
5854         return;
5855     }
5856     if (!IsSelected()) {
5857         UpdateSelection(selectController_->GetCaretIndex());
5858         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
5859     } else {
5860         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
5861         AfterSelection();
5862     }
5863 }
5864 
HandleSelectionLineEnd()5865 void TextFieldPattern::HandleSelectionLineEnd()
5866 {
5867     int32_t textLength = static_cast<int32_t>(contentController_->GetWideText().length());
5868     if (selectController_->GetCaretIndex() == textLength) {
5869         return;
5870     }
5871     int32_t lineEndPosition = GetLineEndPosition(selectController_->GetCaretIndex());
5872     if (lineEndPosition < 0 || lineEndPosition > textLength) {
5873         return;
5874     }
5875     if (!IsSelected()) {
5876         UpdateSelection(selectController_->GetCaretIndex());
5877         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
5878     } else {
5879         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
5880     }
5881     AfterSelection();
5882 }
5883 
HandleSelectionEnd()5884 void TextFieldPattern::HandleSelectionEnd()
5885 {
5886     // shift end, select to the end of current line
5887     int32_t endPos = static_cast<int32_t>(contentController_->GetWideText().length());
5888     if (selectController_->GetCaretIndex() == endPos) {
5889         return;
5890     }
5891     if (!IsSelected()) {
5892         UpdateSelection(selectController_->GetCaretIndex());
5893         selectController_->MoveSecondHandleByKeyBoard(endPos);
5894     } else {
5895         selectController_->MoveSecondHandleByKeyBoard(endPos);
5896     }
5897     AfterSelection();
5898 }
5899 
SetCaretPosition(int32_t position)5900 void TextFieldPattern::SetCaretPosition(int32_t position)
5901 {
5902     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Set caret position to %{public}d", position);
5903     selectController_->MoveCaretToContentRect(position, TextAffinity::DOWNSTREAM);
5904     UpdateCaretInfoToController();
5905     if (HasFocus() && !magnifierController_->GetShowMagnifier()) {
5906         StartTwinkling();
5907     }
5908     CloseSelectOverlay();
5909     TriggerAvoidOnCaretChange();
5910     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5911 }
5912 
SetCaretOffset(int32_t caretPostion)5913 bool TextFieldPattern::SetCaretOffset(int32_t caretPostion)
5914 {
5915     SetCaretPosition(caretPostion);
5916     return true;
5917 }
5918 
SetSelectionFlag(int32_t selectionStart,int32_t selectionEnd,const std::optional<SelectionOptions> & options,bool isForward)5919 void TextFieldPattern::SetSelectionFlag(
5920     int32_t selectionStart, int32_t selectionEnd, const std::optional<SelectionOptions>& options, bool isForward)
5921 {
5922     if (!HasFocus() || GetIsPreviewText()) {
5923         return;
5924     }
5925     auto length = static_cast<int32_t>(contentController_->GetWideText().length());
5926     selectionStart = std::clamp(selectionStart, 0, length);
5927     selectionEnd = std::clamp(selectionEnd, 0, length);
5928     moveCaretState_.isTouchCaret = false;
5929     bool isShowMenu = selectOverlay_->IsCurrentMenuVisibile();
5930     isTouchPreviewText_ = false;
5931     if (selectionStart == selectionEnd) {
5932         selectController_->MoveCaretToContentRect(selectionEnd, TextAffinity::DOWNSTREAM);
5933         StartTwinkling();
5934     } else {
5935         cursorVisible_ = false;
5936         showSelect_ = true;
5937         HandleSetSelection(selectionStart, selectionEnd, false);
5938         if (isForward) {
5939             selectController_->MoveSecondHandleToContentRect(selectionEnd);
5940             selectController_->MoveFirstHandleToContentRect(selectionStart, false);
5941         } else {
5942             selectController_->MoveFirstHandleToContentRect(selectionStart);
5943             selectController_->MoveSecondHandleToContentRect(selectionEnd);
5944         }
5945     }
5946     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SET_SELECTION)) {
5947         NotifyOnEditChanged(true);
5948     }
5949     SetIsSingleHandle(!IsSelected());
5950     if (!IsShowHandle()) {
5951         CloseSelectOverlay(true);
5952     } else {
5953         isShowMenu = IsShowMenu(options, isShowMenu);
5954         if (!isShowMenu && IsUsingMouse()) {
5955             CloseSelectOverlay();
5956         } else {
5957             ProcessOverlay({ .menuIsShow = isShowMenu, .animation = true });
5958         }
5959     }
5960     TriggerAvoidWhenCaretGoesDown();
5961     auto host = GetHost();
5962     CHECK_NULL_VOID(host);
5963     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5964 }
5965 
SetSelection(int32_t start,int32_t end,const std::optional<SelectionOptions> & options,bool isForward)5966 void TextFieldPattern::SetSelection(int32_t start, int32_t end,
5967     const std::optional<SelectionOptions>& options, bool isForward)
5968 {
5969     SetSelectionFlag(start, end, options, isForward);
5970 }
5971 
IsShowMenu(const std::optional<SelectionOptions> & options,bool defaultValue)5972 bool TextFieldPattern::IsShowMenu(const std::optional<SelectionOptions>& options, bool defaultValue)
5973 {
5974     if (!options.has_value()) {
5975         return false;
5976     }
5977     if (options.value().menuPolicy == MenuPolicy::HIDE) {
5978         return false;
5979     }
5980     if (options.value().menuPolicy == MenuPolicy::SHOW) {
5981         return true;
5982     }
5983     return defaultValue;
5984 }
5985 
OnBackPressed()5986 bool TextFieldPattern::OnBackPressed()
5987 {
5988     auto tmpHost = GetHost();
5989     CHECK_NULL_RETURN(tmpHost, false);
5990     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d receives back press event, %{public}d",
5991         tmpHost->GetId(), isCustomKeyboardAttached_);
5992     if (SelectOverlayIsOn()) {
5993         selectController_->UpdateCaretIndex(
5994             std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
5995         bool closeKeyboard = !selectOverlay_->IsCurrentMenuVisibile();
5996         CloseSelectOverlay();
5997         StartTwinkling();
5998         if (!closeKeyboard) {
5999             return IsStopBackPress();
6000         }
6001     }
6002 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
6003     if (!imeShown_ && !isCustomKeyboardAttached_) {
6004 #else
6005     if (!isCustomKeyboardAttached_) {
6006 #endif
6007         return false;
6008     }
6009     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6010     CloseKeyboard(true);
6011     FocusHub::LostFocusToViewRoot();
6012 #if defined(ANDROID_PLATFORM)
6013     return false;
6014 #else
6015     return IsStopBackPress();
6016 #endif
6017 }
6018 
6019 bool TextFieldPattern::IsStopBackPress() const
6020 {
6021     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6022     CHECK_NULL_RETURN(layoutProperty, true);
6023     return layoutProperty->GetStopBackPressValue(true);
6024 }
6025 
6026 int32_t TextFieldPattern::GetNakedCharPosition() const
6027 {
6028     if (IsTextArea() || !IsInPasswordMode() || obscureTickCountDown_ <= 0 || !GetTextObscured()) {
6029         return -1;
6030     }
6031     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6032     CHECK_NULL_RETURN(layoutProperty, -1);
6033     auto content = contentController_->GetTextValue();
6034     if (content.empty()) {
6035         return -1;
6036     }
6037     return nakedCharPosition_;
6038 }
6039 
6040 std::string TextFieldPattern::TextInputTypeToString() const
6041 {
6042     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6043     CHECK_NULL_RETURN(layoutProperty, "");
6044     switch (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
6045         case TextInputType::NUMBER:
6046             return IsTextArea() ? "TextAreaType.NUMBER" : "InputType.Number";
6047         case TextInputType::EMAIL_ADDRESS:
6048             return IsTextArea() ? "TextAreaType.EMAIL" : "InputType.Email";
6049         case TextInputType::PHONE:
6050             return IsTextArea() ? "TextAreaType.PHONE_NUMBER" : "InputType.PhoneNumber";
6051         case TextInputType::URL:
6052             return IsTextArea() ? "TextAreaType.URL" : "InputType.URL";
6053         case TextInputType::VISIBLE_PASSWORD:
6054             return "InputType.Password";
6055         case TextInputType::USER_NAME:
6056             return "InputType.USER_NAME";
6057         case TextInputType::NEW_PASSWORD:
6058             return "InputType.NEW_PASSWORD";
6059         case TextInputType::NUMBER_PASSWORD:
6060             return "InputType.NUMBER_PASSWORD";
6061         case TextInputType::NUMBER_DECIMAL:
6062             return IsTextArea() ? "TextAreaType.NUMBER_DECIMAL" : "InputType.NUMBER_DECIMAL";
6063         default:
6064             return isTextInput_ ? "InputType.Normal" : "TextAreaType.NORMAL";
6065     }
6066 }
6067 
6068 std::string TextFieldPattern::TextContentTypeToString() const
6069 {
6070     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6071     CHECK_NULL_RETURN(layoutProperty, "");
6072     auto contentType = layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED);
6073     if (contentTypeMap_.find(contentType) != contentTypeMap_.end()) {
6074         return contentTypeMap_[contentType].second;
6075     }
6076     return contentTypeMap_[TextContentType::UNSPECIFIED].second;
6077 }
6078 
6079 std::string TextFieldPattern::TextInputActionToString() const
6080 {
6081     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6082     CHECK_NULL_RETURN(layoutProperty, "");
6083     switch (GetTextInputActionValue(GetDefaultTextInputAction())) {
6084         case TextInputAction::GO:
6085             return "EnterKeyType.Go";
6086         case TextInputAction::SEARCH:
6087             return "EnterKeyType.Search";
6088         case TextInputAction::SEND:
6089             return "EnterKeyType.Send";
6090         case TextInputAction::NEXT:
6091             return "EnterKeyType.Next";
6092         default:
6093             return "EnterKeyType.Done";
6094     }
6095 }
6096 
6097 std::string TextFieldPattern::GetPlaceholderFont() const
6098 {
6099     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6100     CHECK_NULL_RETURN(layoutProperty, "");
6101     auto theme = GetTheme();
6102     CHECK_NULL_RETURN(theme, "");
6103     auto jsonValue = JsonUtil::Create(true);
6104     if (layoutProperty->GetPlaceholderItalicFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL) {
6105         jsonValue->Put("style", "FontStyle.Normal");
6106     } else {
6107         jsonValue->Put("style", "FontStyle.Italic");
6108     }
6109     // placeholder font size not exist in theme, use normal font size by default
6110     if (!layoutProperty->GetPlaceholderFontSize()) {
6111         jsonValue->Put("size", GetFontSize().c_str());
6112     } else {
6113         jsonValue->Put("size", layoutProperty->GetPlaceholderFontSize()->ToString().c_str());
6114     }
6115     auto weight = layoutProperty->GetPlaceholderFontWeightValue(theme->GetFontWeight());
6116     switch (weight) {
6117         case FontWeight::W100:
6118             jsonValue->Put("weight", "100");
6119             break;
6120         case FontWeight::W200:
6121             jsonValue->Put("weight", "200");
6122             break;
6123         case FontWeight::W300:
6124             jsonValue->Put("weight", "300");
6125             break;
6126         case FontWeight::W400:
6127             jsonValue->Put("weight", "400");
6128             break;
6129         case FontWeight::W500:
6130             jsonValue->Put("weight", "500");
6131             break;
6132         case FontWeight::W600:
6133             jsonValue->Put("weight", "600");
6134             break;
6135         case FontWeight::W700:
6136             jsonValue->Put("weight", "700");
6137             break;
6138         case FontWeight::W800:
6139             jsonValue->Put("weight", "800");
6140             break;
6141         case FontWeight::W900:
6142             jsonValue->Put("weight", "900");
6143             break;
6144         default:
6145             jsonValue->Put("fontWeight", V2::ConvertWrapFontWeightToStirng(weight).c_str());
6146     }
6147     auto family = layoutProperty->GetPlaceholderFontFamilyValue({ "sans-serif" });
6148     std::string jsonFamily = ConvertFontFamily(family);
6149     jsonValue->Put("fontFamily", jsonFamily.c_str());
6150     return jsonValue->ToString();
6151 }
6152 
6153 RefPtr<TextFieldTheme> TextFieldPattern::GetTheme() const
6154 {
6155     if (textFieldTheme_.Upgrade()) {
6156         return textFieldTheme_.Upgrade();
6157     }
6158     auto tmpHost = GetHost();
6159     CHECK_NULL_RETURN(tmpHost, nullptr);
6160     auto context = tmpHost->GetContext();
6161     CHECK_NULL_RETURN(context, nullptr);
6162     auto theme = context->GetTheme<TextFieldTheme>();
6163     return theme;
6164 }
6165 
6166 void TextFieldPattern::InitTheme()
6167 {
6168     auto tmpHost = GetHost();
6169     CHECK_NULL_VOID(tmpHost);
6170     auto context = tmpHost->GetContext();
6171     CHECK_NULL_VOID(context);
6172     textFieldTheme_ = context->GetTheme<TextFieldTheme>();
6173 }
6174 
6175 std::string TextFieldPattern::GetTextColor() const
6176 {
6177     auto theme = GetTheme();
6178     CHECK_NULL_RETURN(theme, "");
6179     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6180     CHECK_NULL_RETURN(layoutProperty, "");
6181     return layoutProperty->GetTextColorValue(theme->GetTextColor()).ColorToString();
6182 }
6183 
6184 std::string TextFieldPattern::GetCaretColor() const
6185 {
6186     auto theme = GetTheme();
6187     CHECK_NULL_RETURN(theme, "");
6188     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6189     CHECK_NULL_RETURN(paintProperty, "");
6190     return paintProperty->GetCursorColorValue(theme->GetCursorColor()).ColorToString();
6191 }
6192 
6193 std::string TextFieldPattern::GetPlaceholderColor() const
6194 {
6195     auto theme = GetTheme();
6196     CHECK_NULL_RETURN(theme, "");
6197     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6198     CHECK_NULL_RETURN(layoutProperty, "");
6199     return layoutProperty->GetPlaceholderTextColorValue(theme->GetTextColor()).ColorToString();
6200 }
6201 
6202 std::string TextFieldPattern::GetFontSize() const
6203 {
6204     auto theme = GetTheme();
6205     CHECK_NULL_RETURN(theme, "");
6206     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6207     CHECK_NULL_RETURN(layoutProperty, "");
6208     return layoutProperty->GetFontSizeValue(theme->GetFontSize()).ToString();
6209 }
6210 
6211 std::string TextFieldPattern::GetMinFontSize() const
6212 {
6213     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6214     CHECK_NULL_RETURN(layoutProperty, "");
6215     return layoutProperty->GetAdaptMinFontSize()->ToString();
6216 }
6217 
6218 std::string TextFieldPattern::GetMaxFontSize() const
6219 {
6220     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6221     CHECK_NULL_RETURN(layoutProperty, "");
6222     return layoutProperty->GetAdaptMaxFontSize()->ToString();
6223 }
6224 
6225 std::string TextFieldPattern::GetTextIndent() const
6226 {
6227     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6228     CHECK_NULL_RETURN(layoutProperty, "");
6229     return layoutProperty->GetTextIndent()->ToString();
6230 }
6231 
6232 Ace::FontStyle TextFieldPattern::GetItalicFontStyle() const
6233 {
6234     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6235     CHECK_NULL_RETURN(layoutProperty, Ace::FontStyle::NORMAL);
6236     return layoutProperty->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL);
6237 }
6238 
6239 std::string TextFieldPattern::GetShowPasswordIconString() const
6240 {
6241     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6242     CHECK_NULL_RETURN(layoutProperty, "false");
6243     return layoutProperty->GetShowPasswordIconValue(false) ? "true" : "false";
6244 }
6245 
6246 std::string TextFieldPattern::GetInputStyleString() const
6247 {
6248     std::string result = isTextInput_ ? "TextInputStyle.Default" : "TextContentStyle.DEFAULT";
6249     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6250     CHECK_NULL_RETURN(paintProperty, result);
6251     switch (paintProperty->GetInputStyleValue(InputStyle::DEFAULT)) {
6252         case InputStyle::INLINE:
6253             result = isTextInput_ ? "TextInputStyle.Inline" : "TextContentStyle.INLINE";
6254             break;
6255         case InputStyle::DEFAULT:
6256         default:
6257             break;
6258     }
6259     return result;
6260 }
6261 
6262 FontWeight TextFieldPattern::GetFontWeight() const
6263 {
6264     auto theme = GetTheme();
6265     CHECK_NULL_RETURN(theme, FontWeight::NORMAL);
6266     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6267     CHECK_NULL_RETURN(layoutProperty, FontWeight::NORMAL);
6268     return layoutProperty->GetFontWeightValue(theme->GetFontWeight());
6269 }
6270 
6271 std::string TextFieldPattern::GetFontFamily() const
6272 {
6273     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6274     CHECK_NULL_RETURN(layoutProperty, "HarmonyOS Sans");
6275     auto family = layoutProperty->GetFontFamilyValue({ "HarmonyOS Sans" });
6276     return ConvertFontFamily(family);
6277 }
6278 
6279 TextAlign TextFieldPattern::GetTextAlign() const
6280 {
6281     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6282     CHECK_NULL_RETURN(layoutProperty, TextAlign::START);
6283     return layoutProperty->GetTextAlign().value_or(TextAlign::START);
6284 }
6285 
6286 uint32_t TextFieldPattern::GetMaxLength() const
6287 {
6288     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6289     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
6290     return layoutProperty->HasMaxLength() ? layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())
6291                                           : Infinity<uint32_t>();
6292 }
6293 
6294 uint32_t TextFieldPattern::GetMaxLines() const
6295 {
6296     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6297     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
6298     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6299     CHECK_NULL_RETURN(paintProperty, Infinity<uint32_t>());
6300     if (IsNormalInlineState()) {
6301         return layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE);
6302     }
6303     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(Infinity<uint32_t>())
6304                                          : Infinity<uint32_t>();
6305 }
6306 
6307 std::string TextFieldPattern::GetPlaceHolder() const
6308 {
6309     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6310     CHECK_NULL_RETURN(layoutProperty, "");
6311     return layoutProperty->GetPlaceholderValue("");
6312 }
6313 
6314 std::string TextFieldPattern::GetInputFilter() const
6315 {
6316     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6317     CHECK_NULL_RETURN(layoutProperty, "");
6318     return layoutProperty->GetInputFilterValue("");
6319 }
6320 
6321 std::string TextFieldPattern::GetErrorTextString() const
6322 {
6323     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6324     CHECK_NULL_RETURN(layoutProperty, "");
6325     return layoutProperty->GetErrorTextValue("");
6326 }
6327 
6328 bool TextFieldPattern::GetErrorTextState() const
6329 {
6330     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6331     CHECK_NULL_RETURN(layoutProperty, false);
6332     return layoutProperty->GetShowErrorTextValue(false);
6333 }
6334 
6335 void TextFieldPattern::SearchRequestKeyboard()
6336 {
6337     StartTwinkling();
6338     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SEARCH_REQUEST)) {
6339         NotifyOnEditChanged(true);
6340     }
6341 }
6342 
6343 std::string TextFieldPattern::GetCopyOptionString() const
6344 {
6345     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6346     CHECK_NULL_RETURN(layoutProperty, "");
6347     std::string copyOptionString = "CopyOptions.None";
6348     switch (layoutProperty->GetCopyOptionsValue(CopyOptions::None)) {
6349         case CopyOptions::InApp:
6350             copyOptionString = "CopyOptions.InApp";
6351             break;
6352         case CopyOptions::Local:
6353             copyOptionString = "CopyOptions.Local";
6354             break;
6355         case CopyOptions::Distributed:
6356             copyOptionString = "CopyOptions.Distributed";
6357             break;
6358         case CopyOptions::None:
6359         default:
6360             break;
6361     }
6362     return copyOptionString;
6363 }
6364 
6365 std::string TextFieldPattern::GetBarStateString() const
6366 {
6367     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6368     CHECK_NULL_RETURN(layoutProperty, "");
6369     std::string displayModeString;
6370     switch (layoutProperty->GetDisplayModeValue(DisplayMode::AUTO)) {
6371         case DisplayMode::OFF:
6372             displayModeString = "BarState.OFF";
6373             break;
6374         case DisplayMode::ON:
6375             displayModeString = "BarState.ON";
6376             break;
6377         case DisplayMode::AUTO:
6378         default:
6379             displayModeString = "BarState.AUTO";
6380             break;
6381     }
6382     return displayModeString;
6383 }
6384 
6385 void TextFieldPattern::UpdateScrollBarOffset()
6386 {
6387     if (!GetScrollBar() && !GetScrollBarProxy()) {
6388         return;
6389     }
6390     auto paddingHeight = GetPaddingTop() + GetPaddingBottom();
6391     auto paddingRight = GetPaddingRight();
6392     auto contentHeight = contentRect_.Height();
6393     if (inlineFocusState_) {
6394         paddingHeight = 0.0f;
6395         paddingRight = 0.0f;
6396         contentHeight = GetSingleLineHeight() * GetMaxLines();
6397     }
6398     Size size(frameRect_.Width(), contentHeight + paddingHeight);
6399     UpdateScrollBarRegion(
6400         contentRect_.GetY() - textRect_.GetY(), textRect_.Height() + paddingHeight, size, Offset(0.0, 0.0));
6401     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6402 }
6403 
6404 void TextFieldPattern::PlayScrollBarAppearAnimation()
6405 {
6406     auto scrollBar = GetScrollBar();
6407     if (scrollBar) {
6408         scrollBar->PlayScrollBarAppearAnimation();
6409     }
6410 }
6411 
6412 void TextFieldPattern::ScheduleDisappearDelayTask()
6413 {
6414     auto scrollBar = GetScrollBar();
6415     if (scrollBar) {
6416         scrollBar->SetPressed(false);
6417         scrollBar->PlayScrollBarShrinkAnimation();
6418         scrollBar->ScheduleDisappearDelayTask();
6419     }
6420 }
6421 
6422 bool TextFieldPattern::OnScrollCallback(float offset, int32_t source)
6423 {
6424     if (source == SCROLL_FROM_START) {
6425         PlayScrollBarAppearAnimation();
6426         if (selectOverlay_->IsCurrentMenuVisibile()) {
6427             isTextSelectionMenuShow_ = true;
6428         } else if (CheckSelectAreaVisible()) {
6429             isTextSelectionMenuShow_ = false;
6430         }
6431         selectOverlay_->HideMenu(true);
6432         return true;
6433     }
6434     if (IsReachedBoundary(offset)) {
6435         return false;
6436     }
6437     PlayScrollBarAppearAnimation();
6438     OnTextInputScroll(offset);
6439     OnTextAreaScroll(offset);
6440     return true;
6441 }
6442 
6443 void TextFieldPattern::CheckScrollable()
6444 {
6445     if (IsTextArea()) {
6446         if (contentController_->IsEmpty()) {
6447             scrollable_ = false;
6448         } else {
6449             scrollable_ = GreatNotEqual(textRect_.Height(), contentRect_.Height());
6450         }
6451         SetScrollEnabled(scrollable_);
6452     } else {
6453         SetScrollEnabled(GreatNotEqual(textRect_.Width(), contentRect_.Width()));
6454     }
6455 }
6456 
6457 bool TextFieldPattern::HasStateStyle(UIState state) const
6458 {
6459     auto host = GetHost();
6460     CHECK_NULL_RETURN(host, false);
6461     auto hub = host->GetEventHub<EventHub>();
6462     CHECK_NULL_RETURN(hub, false);
6463     return hub->HasStateStyle(state);
6464 }
6465 
6466 double TextFieldPattern::GetScrollBarWidth()
6467 {
6468     auto scrollBar = GetScrollBar();
6469     double scrollBarWidth = 0.0;
6470     if (scrollBar) {
6471         scrollBarWidth = scrollBar->GetBarRect().Width();
6472     }
6473     return scrollBarWidth;
6474 }
6475 
6476 void TextFieldPattern::AddCounterNode()
6477 {
6478     auto host = GetHost();
6479     CHECK_NULL_VOID(host);
6480     auto counterNode = DynamicCast<UINode>(counterTextNode_.Upgrade());
6481     if (counterNode && (IsShowPasswordIcon() || IsNormalInlineState())) {
6482         CleanCounterNode();
6483         return;
6484     }
6485     if (!counterNode) {
6486         auto counterTextNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG,
6487             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
6488         counterTextNode_ = counterTextNode;
6489         counterTextNode->MountToParent(host);
6490         counterTextNode->MarkModifyDone();
6491         counterTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6492         auto counterNodeLayoutProperty = DynamicCast<TextLayoutProperty>(counterTextNode->GetLayoutProperty());
6493         CHECK_NULL_VOID(counterNodeLayoutProperty);
6494         counterNodeLayoutProperty->UpdateIsAnimationNeeded(false);
6495     }
6496 }
6497 
6498 void TextFieldPattern::ClearCounterNode()
6499 {
6500     auto host = GetHost();
6501     if (!host->GetChildren().empty()) {
6502         host->Clean();
6503     }
6504 }
6505 
6506 void TextFieldPattern::SetShowError()
6507 {
6508     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6509     CHECK_NULL_VOID(layoutProperty);
6510     auto passWordMode = IsInPasswordMode();
6511     auto textFieldTheme = GetTheme();
6512     CHECK_NULL_VOID(textFieldTheme);
6513     auto renderContext = GetHost()->GetRenderContext();
6514     CHECK_NULL_VOID(renderContext);
6515     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6516     CHECK_NULL_VOID(paintProperty);
6517     auto isUnderLine = IsUnderlineMode();
6518     auto errorText = layoutProperty->GetErrorTextValue("");
6519     if (IsShowError()) { // update error state
6520         if (isUnderLine) {
6521             underlineColor_ = userUnderlineColor_.error.value_or(textFieldTheme->GetErrorUnderlineColor());
6522             underlineWidth_ = ERROR_UNDERLINE_WIDTH;
6523         } else if (passWordMode) {
6524             if (!paintProperty->HasBorderWidthFlagByUser()) {
6525                 paintProperty->UpdateInnerBorderWidth(ERROR_BORDER_WIDTH);
6526                 paintProperty->UpdateInnerBorderColor(textFieldTheme->GetPasswordErrorBorderColor());
6527             } else {
6528                 BorderColorProperty borderColor;
6529                 borderColor.SetColor(textFieldTheme->GetPasswordErrorBorderColor());
6530                 renderContext->UpdateBorderColor(borderColor);
6531             }
6532             renderContext->UpdateBackgroundColor(textFieldTheme->GetPasswordErrorInputColor());
6533             layoutProperty->UpdateTextColor(textFieldTheme->GetPasswordErrorTextColor());
6534         }
6535     }
6536     UpdateErrorTextMargin();
6537 }
6538 
6539 float TextFieldPattern::CalcDecoratorWidth(const RefPtr<FrameNode>& decoratorNode)
6540 {
6541     float decoratorWidth = 0.0f;
6542     CHECK_NULL_RETURN(decoratorNode, 0.0f);
6543     auto textPattern = decoratorNode->GetPattern<TextPattern>();
6544     CHECK_NULL_RETURN(textPattern, 0.0f);
6545     auto paragraphs = textPattern->GetParagraphs();
6546     for (auto &&info : paragraphs) {
6547         if (info.paragraph) {
6548             float width = info.paragraph->GetLongestLine();
6549             decoratorWidth = std::max(decoratorWidth, width);
6550         }
6551     }
6552     return decoratorWidth;
6553 }
6554 
6555 float TextFieldPattern::CalcDecoratorHeight(const RefPtr<FrameNode>& decoratorNode)
6556 {
6557     CHECK_NULL_RETURN(decoratorNode, 0.0f);
6558     auto geometryNode = decoratorNode->GetGeometryNode();
6559     CHECK_NULL_RETURN(geometryNode, 0.0f);
6560     return geometryNode->GetFrameRect().Height();
6561 }
6562 
6563 void TextFieldPattern::CreateErrorParagraph(const std::string& content)
6564 {
6565     auto host = GetHost();
6566     CHECK_NULL_VOID(host);
6567     auto theme = GetTheme();
6568     CHECK_NULL_VOID(theme);
6569     auto errorTextNode = errorTextNode_.Upgrade();
6570     if (!errorTextNode) {
6571         auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG,
6572             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
6573         errorTextNode_ = textNode;
6574         errorTextNode = errorTextNode_.Upgrade();
6575         textNode->MountToParent(host);
6576     }
6577     if (errorTextNode) {
6578         TextStyle errorTextStyle = theme->GetErrorTextStyle();
6579         std::string errorText = content;
6580         StringUtils::TransformStrCase(errorText, static_cast<int32_t>(errorTextStyle.GetTextCase()));
6581         auto textColor = errorTextStyle.GetTextColor();
6582         auto textNodeLayoutProperty = DynamicCast<TextLayoutProperty>(errorTextNode->GetLayoutProperty());
6583         CHECK_NULL_VOID(textNodeLayoutProperty);
6584         textNodeLayoutProperty->UpdateContent(errorText);
6585         textNodeLayoutProperty->UpdateTextColor(textColor);
6586         textNodeLayoutProperty->UpdateFontWeight(errorTextStyle.GetFontWeight());
6587         textNodeLayoutProperty->UpdateFontSize(errorTextStyle.GetFontSize());
6588         textNodeLayoutProperty->UpdateMaxFontScale(ERROR_TEXT_MAX_FONT_SCALE);
6589         textNodeLayoutProperty->UpdateTextAlign(TextAlign::START);
6590         textNodeLayoutProperty->UpdateMaxLines(ERROR_TEXT_MAXLINE);
6591         textNodeLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
6592         textNodeLayoutProperty->UpdateIsAnimationNeeded(false);
6593         auto layoutProperty = host->GetLayoutProperty();
6594         auto isRTL = layoutProperty && (layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL);
6595         if (isRTL) {
6596             textNodeLayoutProperty->UpdateLayoutDirection(TextDirection::RTL);
6597         } else {
6598             textNodeLayoutProperty->UpdateLayoutDirection(TextDirection::LTR);
6599         }
6600 
6601         auto accessibilityProperty = errorTextNode->GetAccessibilityProperty<AccessibilityProperty>();
6602         CHECK_NULL_VOID(accessibilityProperty);
6603         accessibilityProperty->SetAccessibilityLevel("yes");
6604         auto parentID = host->GetInspectorIdValue("");
6605         errorTextNode->UpdateInspectorId(INSPECTOR_PREFIX + ERRORNODE_PREFIX + parentID);
6606         errorTextNode->SetIsCalculateInnerClip(true);
6607         errorTextNode->MarkModifyDone();
6608         errorTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6609         auto context = errorTextNode->GetRenderContext();
6610         CHECK_NULL_VOID(context);
6611         context->UpdateForegroundColor(errorTextStyle.GetTextColor());
6612     }
6613 }
6614 
6615 void TextFieldPattern::UpdateErrorTextMargin()
6616 {
6617     auto tmpHost = GetHost();
6618     CHECK_NULL_VOID(tmpHost);
6619     auto renderContext = tmpHost->GetRenderContext();
6620     CHECK_NULL_VOID(renderContext);
6621     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
6622     CHECK_NULL_VOID(layoutProperty);
6623     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6624     CHECK_NULL_VOID(paintProperty);
6625     auto theme = GetTheme();
6626     CHECK_NULL_VOID(theme);
6627     MarginProperty errorMargin;
6628     auto errorText = layoutProperty->GetErrorTextValue("");
6629     if (IsShowError()) {
6630         CreateErrorParagraph(errorText);
6631         auto errorTextNode = errorTextNode_.Upgrade();
6632         if (errorTextNode) {
6633             ScopedLayout scope(tmpHost->GetContext());
6634             errorTextNode->Measure(LayoutConstraintF());
6635             auto geometryNode = errorTextNode->GetGeometryNode();
6636             auto errorHeight = geometryNode ? geometryNode->GetFrameRect().Height() : 0.0f;
6637             auto errorTextMargin = ERROR_TEXT_TOP_MARGIN.ConvertToPx() +
6638                 ERROR_TEXT_BOTTOM_MARGIN.ConvertToPx() + errorHeight;
6639 
6640             if (GetMarginBottom() < errorTextMargin) {
6641                 errorMargin.bottom = CalcLength(errorTextMargin);
6642             }
6643             if (paintProperty->HasMarginByUser()) {
6644                 auto userMargin = paintProperty->GetMarginByUserValue();
6645                 userMargin.bottom = GetMarginBottom() < errorTextMargin ?
6646                     errorMargin.bottom : userMargin.bottom;
6647                 layoutProperty->UpdateMargin(userMargin);
6648             } else {
6649                 layoutProperty->UpdateMargin(errorMargin);
6650             }
6651         }
6652     }
6653 }
6654 
6655 void TextFieldPattern::ApplyUnderlineTheme()
6656 {
6657     if (!IsUnderlineMode()) {
6658         return;
6659     }
6660     SetThemeAttr();
6661     auto theme = GetTheme();
6662     CHECK_NULL_VOID(theme);
6663     if (IsShowError()) {
6664         underlineColor_ = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
6665     } else {
6666         underlineColor_ = HasFocus() ? userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor())
6667             : userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
6668     }
6669     underlineWidth_ = HasFocus() ? TYPING_UNDERLINE_WIDTH : UNDERLINE_WIDTH;
6670 }
6671 
6672 float TextFieldPattern::GetMarginBottom() const
6673 {
6674     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
6675     CHECK_NULL_RETURN(layoutProperty, 0.0f);
6676     const auto& getMargin = layoutProperty->GetMarginProperty();
6677     if (getMargin && getMargin->bottom.has_value()) {
6678         return getMargin->bottom->GetDimension().ConvertToPx();
6679     }
6680     return 0.0f;
6681 }
6682 
6683 std::string TextFieldPattern::GetShowResultImageSrc() const
6684 {
6685     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
6686     CHECK_NULL_RETURN(layoutProperty, "");
6687     auto showImageSource = layoutProperty->GetShowPasswordSourceInfo();
6688     if (showImageSource && !showImageSource->GetSrc().empty()) {
6689         return showImageSource->GetSrc();
6690     }
6691     return SHOW_PASSWORD_SVG;
6692 }
6693 
6694 std::string TextFieldPattern::GetNormalUnderlineColorStr() const
6695 {
6696     auto theme = GetTheme();
6697     CHECK_NULL_RETURN(theme, "");
6698     Color normal = userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
6699     return normal.ColorToString();
6700 }
6701 
6702 std::string TextFieldPattern::GetTypingUnderlineColorStr() const
6703 {
6704     auto theme = GetTheme();
6705     CHECK_NULL_RETURN(theme, "");
6706     Color typing = userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor());
6707     return typing.ColorToString();
6708 }
6709 
6710 std::string TextFieldPattern::GetDisableUnderlineColorStr() const
6711 {
6712     auto theme = GetTheme();
6713     CHECK_NULL_RETURN(theme, "");
6714     Color disable = userUnderlineColor_.disable.value_or(theme->GetDisableUnderlineColor());
6715     return disable.ColorToString();
6716 }
6717 
6718 std::string TextFieldPattern::GetErrorUnderlineColorStr() const
6719 {
6720     auto theme = GetTheme();
6721     CHECK_NULL_RETURN(theme, "");
6722     Color error = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
6723     return error.ColorToString();
6724 }
6725 
6726 std::string TextFieldPattern::GetHideResultImageSrc() const
6727 {
6728     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
6729     CHECK_NULL_RETURN(layoutProperty, "");
6730     auto hideSourceInfo = layoutProperty->GetHidePasswordSourceInfo();
6731     if (hideSourceInfo && !hideSourceInfo->GetSrc().empty()) {
6732         return hideSourceInfo->GetSrc();
6733     }
6734     return HIDE_PASSWORD_SVG;
6735 }
6736 
6737 void TextFieldPattern::RestorePreInlineStates()
6738 {
6739     ResetContextAttr();
6740     ApplyNormalTheme();
6741     ApplyUnderlineTheme();
6742     ProcessInnerPadding();
6743     ProcessResponseArea();
6744     ProcessRectPadding();
6745 }
6746 
6747 void TextFieldPattern::ProcessRectPadding()
6748 {
6749     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6750     CHECK_NULL_VOID(layoutProperty);
6751     auto& paddingProperty = layoutProperty->GetPaddingProperty();
6752     CHECK_NULL_VOID(paddingProperty);
6753     auto top = paddingProperty->top.has_value() ? paddingProperty->top->GetDimension().ConvertToPx() : 0.0f;
6754     textRect_.SetTop(top);
6755 }
6756 
6757 void TextFieldPattern::TextAreaInputRectUpdate(RectF& rect)
6758 {
6759     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
6760     CHECK_NULL_VOID(layoutProperty);
6761     auto theme = GetTheme();
6762     CHECK_NULL_VOID(theme);
6763     if (IsTextArea() && !contentController_->IsEmpty()) {
6764         auto inputContentWidth = GetParagraph()->GetMaxIntrinsicWidth();
6765         switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
6766             case TextAlign::START:
6767                 if (inputContentWidth < contentRect_.Width()) {
6768                     rect.SetWidth(inputContentWidth);
6769                 }
6770                 break;
6771             case TextAlign::CENTER:
6772                 if (inputContentWidth < contentRect_.Width()) {
6773                     rect.SetLeft(
6774                         static_cast<float>(rect.GetX()) + contentRect_.Width() / 2.0f - inputContentWidth / 2.0f);
6775                     rect.SetWidth(inputContentWidth);
6776                 }
6777                 break;
6778             case TextAlign::END:
6779                 if (inputContentWidth < contentRect_.Width()) {
6780                     rect.SetLeft(static_cast<float>(rect.GetX()) + contentRect_.Width() -
6781                                  static_cast<float>(theme->GetCursorWidth().ConvertToPx()) - inputContentWidth);
6782                     rect.SetWidth(inputContentWidth);
6783                 }
6784                 break;
6785             default:
6786                 break;
6787         }
6788     }
6789 }
6790 
6791 void TextFieldPattern::TextIsEmptyRect(RectF& rect)
6792 {
6793     rect = selectController_->CalculateEmptyValueCaretRect();
6794 }
6795 
6796 void TextFieldPattern::UpdateRectByTextAlign(RectF& rect)
6797 {
6798     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
6799     CHECK_NULL_VOID(layoutProperty);
6800     if (!layoutProperty->HasTextAlign()) {
6801         return;
6802     }
6803     switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
6804         case TextAlign::START:
6805             return;
6806         case TextAlign::CENTER:
6807             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()) * 0.5f);
6808             return;
6809         case TextAlign::END:
6810             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()));
6811             return;
6812         default:
6813             return;
6814     }
6815 }
6816 
6817 void TextFieldPattern::ProcessInlinePaddingAndMargin()
6818 {
6819     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6820     CHECK_NULL_VOID(layoutProperty);
6821     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6822     auto theme = GetTheme();
6823     CHECK_NULL_VOID(theme);
6824     PaddingProperty userPadding;
6825     MarginProperty userMargin;
6826     if (paintProperty->HasPaddingByUser()) {
6827         userPadding = paintProperty->GetPaddingByUserValue();
6828     } else {
6829         auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
6830         userPadding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
6831         userPadding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
6832         userPadding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
6833         userPadding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
6834     }
6835     if (paintProperty->HasMarginByUser()) {
6836         userMargin = paintProperty->GetMarginByUserValue();
6837     }
6838     MarginProperty margin;
6839     margin.bottom = CalcLength(userMargin.bottom->GetDimension() + userPadding.bottom->GetDimension());
6840     margin.right = CalcLength(userMargin.right->GetDimension() + userPadding.right->GetDimension());
6841     margin.left = CalcLength(userMargin.left->GetDimension() + userPadding.left->GetDimension());
6842     margin.top = CalcLength(userMargin.top->GetDimension() + userPadding.top->GetDimension());
6843     layoutProperty->UpdateMargin(margin);
6844     if (!IsTextArea()) {
6845         layoutProperty->UpdatePlaceholderMaxLines(layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
6846         layoutProperty->ResetMaxLines();
6847     }
6848     if (layoutProperty->HasTextOverflow()) {
6849         layoutProperty->UpdateTextOverflowMaxLines(layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
6850     }
6851 }
6852 
6853 void TextFieldPattern::ApplyInlineTheme()
6854 {
6855     if (!IsInlineMode()) {
6856         return;
6857     }
6858     auto tmpHost = GetHost();
6859     CHECK_NULL_VOID(tmpHost);
6860     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
6861     CHECK_NULL_VOID(layoutProperty);
6862     auto renderContext = GetHost()->GetRenderContext();
6863     CHECK_NULL_VOID(renderContext);
6864     auto theme = GetTheme();
6865     CHECK_NULL_VOID(theme);
6866     layoutProperty->UpdateTextColor(theme->GetInlineTextColor());
6867     auto radius = theme->GetInlineRadiusSize();
6868     renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
6869     renderContext->UpdateBackgroundColor(theme->GetInlineBgColor());
6870     BorderWidthProperty inlineBorderWidth;
6871     inlineBorderWidth.SetBorderWidth(INLINE_BORDER_WIDTH);
6872     layoutProperty->UpdateBorderWidth(inlineBorderWidth);
6873     renderContext->UpdateBorderWidth(inlineBorderWidth);
6874     BorderColorProperty inlineBorderColor;
6875     inlineBorderColor.SetColor(theme->GetInlineBorderColor());
6876     renderContext->UpdateBorderColor(inlineBorderColor);
6877 
6878     if (layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL) {
6879         layoutProperty->UpdatePadding({ CalcLength(theme->getInlinePaddingRight()), CalcLength(0.0f), CalcLength(0.0f),
6880             CalcLength(0.0f) });
6881     } else {
6882         layoutProperty->UpdatePadding({ CalcLength(0.0f), CalcLength(theme->getInlinePaddingRight()), CalcLength(0.0f),
6883             CalcLength(0.0f) });
6884     }
6885     ProcessInnerPadding();
6886     ProcessInlinePaddingAndMargin();
6887 }
6888 
6889 bool TextFieldPattern::ResetObscureTickCountDown()
6890 {
6891     auto oldTickCountDown_ = obscureTickCountDown_;
6892     if (!IsTextArea() && GetTextObscured() && IsInPasswordMode()) {
6893         obscureTickCountDown_ = 0;
6894     }
6895     return oldTickCountDown_ != obscureTickCountDown_;
6896 }
6897 
6898 bool TextFieldPattern::IsInPasswordMode() const
6899 {
6900     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6901     CHECK_NULL_RETURN(layoutProperty, false);
6902     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
6903     return inputType == TextInputType::VISIBLE_PASSWORD
6904         || inputType == TextInputType::NUMBER_PASSWORD
6905         || inputType == TextInputType::SCREEN_LOCK_PASSWORD
6906         || inputType == TextInputType::NEW_PASSWORD;
6907 }
6908 
6909 bool TextFieldPattern::IsNormalInlineState() const
6910 {
6911     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6912     CHECK_NULL_RETURN(paintProperty, false);
6913     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
6914     CHECK_NULL_RETURN(layoutProperty, false);
6915     return paintProperty->GetInputStyleValue(InputStyle::DEFAULT) == InputStyle::INLINE &&
6916            (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::UNSPECIFIED ||
6917                layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::TEXT);
6918 }
6919 
6920 bool TextFieldPattern::IsUnspecifiedOrTextType() const
6921 {
6922     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
6923     CHECK_NULL_RETURN(layoutProperty, false);
6924     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
6925     return inputType == TextInputType::UNSPECIFIED || inputType == TextInputType::TEXT;
6926 }
6927 
6928 void TextFieldPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
6929 {
6930     /* no fixed attr below, just return */
6931     if (filter.IsFastFilter()) {
6932         return;
6933     }
6934     json->PutExtAttr("placeholder", GetPlaceHolder().c_str(), filter);
6935     json->PutExtAttr("text", contentController_->GetTextValue().c_str(), filter);
6936     json->PutExtAttr("fontSize", GetFontSize().c_str(), filter);
6937     json->PutExtAttr("fontColor", GetTextColor().c_str(), filter);
6938     json->PutExtAttr("fontStyle",
6939         GetItalicFontStyle() == Ace::FontStyle::NORMAL ? "FontStyle.Normal" : "FontStyle.Italic", filter);
6940     json->PutExtAttr("fontWeight", V2::ConvertWrapFontWeightToStirng(GetFontWeight()).c_str(), filter);
6941     json->PutExtAttr("fontFamily", GetFontFamily().c_str(), filter);
6942     json->PutExtAttr("textAlign", V2::ConvertWrapTextAlignToString(GetTextAlign()).c_str(), filter);
6943     json->PutExtAttr("caretColor", GetCaretColor().c_str(), filter);
6944     json->PutExtAttr("type", TextInputTypeToString().c_str(), filter);
6945     json->PutExtAttr("contentType", TextContentTypeToString().c_str(), filter);
6946     json->PutExtAttr("placeholderColor", GetPlaceholderColor().c_str(), filter);
6947     json->PutExtAttr("placeholderFont", GetPlaceholderFont().c_str(), filter);
6948     json->PutExtAttr("enterKeyType", TextInputActionToString().c_str(), filter);
6949     json->PutExtAttr("maxLength", GreatOrEqual(GetMaxLength(),
6950         Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLength()).c_str(), filter);
6951     json->PutExtAttr("inputFilter", GetInputFilter().c_str(), filter);
6952     json->PutExtAttr("copyOption", GetCopyOptionString().c_str(), filter);
6953     json->PutExtAttr("style", GetInputStyleString().c_str(), filter);
6954     auto jsonValue = JsonUtil::Create(true);
6955     jsonValue->Put("onIconSrc", GetShowResultImageSrc().c_str());
6956     jsonValue->Put("offIconSrc", GetHideResultImageSrc().c_str());
6957     json->PutExtAttr("passwordIcon", jsonValue->ToString().c_str(), filter);
6958     json->PutExtAttr("showError", GetErrorTextState() ? GetErrorTextString().c_str() : "undefined", filter);
6959     json->PutExtAttr("maxLines", GreatOrEqual(GetMaxLines(),
6960         Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLines()).c_str(), filter);
6961     json->PutExtAttr("barState", GetBarStateString().c_str(), filter);
6962     json->PutExtAttr("caretPosition", std::to_string(GetCaretIndex()).c_str(), filter);
6963     json->PutExtAttr("enablePreviewText", GetSupportPreviewText(), filter);
6964     ToJsonValueForOption(json, filter);
6965     ToJsonValueSelectOverlay(json, filter);
6966 }
6967 
6968 void TextFieldPattern::ToJsonValueForOption(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
6969 {
6970     auto underlineColorJsonValue = JsonUtil::Create(true);
6971     underlineColorJsonValue->Put("normal", GetNormalUnderlineColorStr().c_str());
6972     underlineColorJsonValue->Put("typing", GetTypingUnderlineColorStr().c_str());
6973     underlineColorJsonValue->Put("error", GetErrorUnderlineColorStr().c_str());
6974     underlineColorJsonValue->Put("disable", GetDisableUnderlineColorStr().c_str());
6975     json->PutExtAttr("underlineColor", underlineColorJsonValue->ToString().c_str(), filter);
6976 
6977     auto host = GetHost();
6978     CHECK_NULL_VOID(host);
6979     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
6980     CHECK_NULL_VOID(layoutProperty);
6981     auto jsonShowCounter = JsonUtil::Create(true);
6982     jsonShowCounter->Put("value", layoutProperty->GetShowCounterValue(false));
6983     auto jsonShowCounterOptions = JsonUtil::Create(true);
6984     jsonShowCounterOptions->Put("thresholdPercentage", layoutProperty->GetSetCounterValue(DEFAULT_MODE));
6985     jsonShowCounterOptions->Put("highlightBorder", layoutProperty->GetShowHighlightBorderValue(true));
6986     jsonShowCounter->Put("options", jsonShowCounterOptions);
6987     json->PutExtAttr("showCounter", jsonShowCounter, filter);
6988     json->PutExtAttr("keyboardAppearance", static_cast<int32_t>(keyboardAppearance_), filter);
6989 }
6990 
6991 void TextFieldPattern::ToJsonValueSelectOverlay(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
6992 {
6993     json->PutExtAttr("CaretStatus", cursorVisible_ ? "show" : "hide", filter);
6994     json->PutExtAttr("CaretTwinkling", isCaretTwinkling_ ? "true" : "false", filter);
6995     json->PutExtAttr("caretRect", selectController_->GetCaretRect().ToString().c_str(), filter);
6996     json->PutExtAttr("caretWidth", std::to_string(selectController_->GetCaretRect().Width()).c_str(), filter);
6997     json->PutExtAttr("isShowMagnifier", magnifierController_->GetShowMagnifier() ? "true" : "false", filter);
6998     json->PutExtAttr("MagnifierPosition", magnifierController_->GetLocalOffset().ToString().c_str(), filter);
6999 
7000     auto manager = selectOverlay_->GetManager<SelectContentOverlayManager>();
7001     CHECK_NULL_VOID(manager);
7002     auto selectOverlayInfo = manager->GetSelectOverlayInfo();
7003     CHECK_NULL_VOID(selectOverlayInfo);
7004 
7005     //handle info
7006     json->PutExtAttr("IsSingleHandle", selectOverlayInfo->isSingleHandle ? "true" : "false", filter);
7007     json->PutExtAttr("IsHandleReverse", selectOverlayInfo->handleReverse ? "true" : "false", filter);
7008     json->PutExtAttr("FirstHandleRect", selectOverlayInfo->firstHandle.paintRect.ToString().c_str(), filter);
7009     json->PutExtAttr("FirstHandleStartPoint",
7010         selectOverlayInfo->firstHandle.paintInfo.startPoint.ToString().c_str(), filter);
7011     json->PutExtAttr("FirstHandleEndPoint",
7012         selectOverlayInfo->firstHandle.paintInfo.endPoint.ToString().c_str(), filter);
7013     json->PutExtAttr("IsFirstHandlePaintByPoints",
7014         selectOverlayInfo->firstHandle.isPaintHandleWithPoints ? "true" : "false", filter);
7015     json->PutExtAttr("SecondHandleRect", selectOverlayInfo->secondHandle.paintRect.ToString().c_str(), filter);
7016     json->PutExtAttr("SecondHandleStartPoint",
7017         selectOverlayInfo->secondHandle.paintInfo.startPoint.ToString().c_str(), filter);
7018     json->PutExtAttr("SecondHandleEndPoint",
7019         selectOverlayInfo->secondHandle.paintInfo.endPoint.ToString().c_str(), filter);
7020     json->PutExtAttr("IsSecondHandlePaintByPoints",
7021         selectOverlayInfo->secondHandle.isPaintHandleWithPoints ? "true" : "false", filter);
7022 
7023     //menu
7024     auto menuNode = manager->GetSelectOverlayNode();
7025     CHECK_NULL_VOID(menuNode);
7026     json->PutExtAttr("MenuNode", menuNode->GetTag().c_str(), filter);
7027     if (menuNode->GetAncestorNodeOfFrame(true)) {
7028         json->PutExtAttr("MountOn", menuNode->GetAncestorNodeOfFrame(true)->GetTag().c_str(), filter);
7029     }
7030     auto menuLayoutProperty = menuNode->GetLayoutProperty();
7031     CHECK_NULL_VOID(menuLayoutProperty);
7032     auto menuVisible = static_cast<int32_t>(menuLayoutProperty->GetVisibility().value_or(VisibleType::VISIBLE));
7033     json->PutExtAttr("Visible", std::to_string(menuVisible).c_str(), filter);
7034     auto menuGeometryNode = menuNode->GetGeometryNode();
7035     CHECK_NULL_VOID(menuGeometryNode);
7036     json->PutExtAttr("MenuFrameRect", menuGeometryNode->GetFrameRect().ToString().c_str(), filter);
7037     json->PutExtAttr("MenuItemCount", std::to_string(selectOverlayInfo->menuOptionItems.size()).c_str(), filter);
7038     for (auto menuItme : selectOverlayInfo->menuOptionItems) {
7039         json->PutExtAttr("MenuItme", menuItme.content.value_or("").c_str(), filter);
7040     }
7041 }
7042 
7043 void TextFieldPattern::FromJson(const std::unique_ptr<JsonValue>& json)
7044 {
7045     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7046     layoutProperty->UpdatePlaceholder(json->GetString("placeholder"));
7047     UpdateEditingValue(json->GetString("text"), StringUtils::StringToInt(json->GetString("caretPosition")));
7048     FireOnTextChangeEvent();
7049     UpdateSelection(GetCaretIndex());
7050     auto maxLines = json->GetString("maxLines");
7051     if (!maxLines.empty() && maxLines != "INF") {
7052         layoutProperty->UpdateMaxLines(StringUtils::StringToUint(maxLines));
7053     }
7054     static const std::unordered_map<std::string, CopyOptions> uMap = {
7055         { "CopyOptions.None", CopyOptions::None },
7056         { "CopyOptions.InApp", CopyOptions::InApp },
7057         { "CopyOptions.Local", CopyOptions::Local },
7058         { "CopyOptions.Distributed", CopyOptions::Distributed },
7059     };
7060     auto copyOption = json->GetString("copyOption");
7061     CopyOptions copyOptionsEnum = CopyOptions::None;
7062     auto iter = uMap.find(copyOption);
7063     if (iter != uMap.end()) {
7064         copyOptionsEnum = iter->second;
7065     }
7066     layoutProperty->UpdateCopyOptions(copyOptionsEnum);
7067     Pattern::FromJson(json);
7068 }
7069 
7070 void TextFieldPattern::SetAccessibilityAction()
7071 {
7072     auto host = GetHost();
7073     CHECK_NULL_VOID(host);
7074     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7075     CHECK_NULL_VOID(accessibilityProperty);
7076     accessibilityProperty->SetAccessibilityGroup(true);
7077     SetAccessibilityActionOverlayAndSelection();
7078     SetAccessibilityActionGetAndSetCaretPosition();
7079     SetAccessibilityScrollAction();
7080     SetAccessibilityMoveTextAction();
7081     SetAccessibilityErrotText();
7082 }
7083 
7084 void TextFieldPattern::SetAccessibilityActionOverlayAndSelection()
7085 {
7086     auto host = GetHost();
7087     CHECK_NULL_VOID(host);
7088     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7089     CHECK_NULL_VOID(accessibilityProperty);
7090     accessibilityProperty->SetActionSetText([weakPtr = WeakClaim(this)](const std::string& value) {
7091         const auto& pattern = weakPtr.Upgrade();
7092         CHECK_NULL_VOID(pattern);
7093         pattern->InsertValue(value);
7094     });
7095 
7096     accessibilityProperty->SetActionSetSelection([weakPtr = WeakClaim(this)](int32_t start,
7097                                                                              int32_t end, bool isForward) {
7098             const auto& pattern = weakPtr.Upgrade();
7099             CHECK_NULL_VOID(pattern);
7100             pattern->SetSelectionFlag(start, end, std::nullopt, isForward);
7101         });
7102 
7103     accessibilityProperty->SetActionCopy([weakPtr = WeakClaim(this)]() {
7104         const auto& pattern = weakPtr.Upgrade();
7105         CHECK_NULL_VOID(pattern);
7106         if (pattern->AllowCopy()) {
7107             pattern->HandleOnCopy();
7108             pattern->CloseSelectOverlay(true);
7109         }
7110     });
7111 
7112     accessibilityProperty->SetActionCut([weakPtr = WeakClaim(this)]() {
7113         const auto& pattern = weakPtr.Upgrade();
7114         CHECK_NULL_VOID(pattern);
7115         if (pattern->AllowCopy()) {
7116             pattern->HandleOnCut();
7117             pattern->CloseSelectOverlay(true);
7118         }
7119     });
7120 
7121     accessibilityProperty->SetActionPaste([weakPtr = WeakClaim(this)]() {
7122         const auto& pattern = weakPtr.Upgrade();
7123         CHECK_NULL_VOID(pattern);
7124         pattern->HandleOnPaste();
7125         pattern->CloseSelectOverlay(true);
7126     });
7127 
7128     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
7129         const auto& pattern = weakPtr.Upgrade();
7130         CHECK_NULL_VOID(pattern);
7131         auto current = pattern->selectController_->GetEndIndex();
7132         pattern->SetInSelectMode(SelectionMode::NONE);
7133         pattern->UpdateSelection(current);
7134         pattern->SetSelectionFlag(current, current, std::nullopt);
7135         pattern->CloseSelectOverlay(true);
7136         pattern->StartTwinkling();
7137     });
7138 }
7139 
7140 void TextFieldPattern::SetAccessibilityActionGetAndSetCaretPosition()
7141 {
7142     auto host = GetHost();
7143     CHECK_NULL_VOID(host);
7144     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7145     CHECK_NULL_VOID(accessibilityProperty);
7146     accessibilityProperty->SetActionSetIndex([weakPtr = WeakClaim(this)](int32_t index) {
7147         const auto& pattern = weakPtr.Upgrade();
7148         CHECK_NULL_VOID(pattern);
7149         pattern->SetCaretPosition(index);
7150     });
7151 
7152     accessibilityProperty->SetActionGetIndex([weakPtr = WeakClaim(this)]() -> int32_t {
7153         const auto& pattern = weakPtr.Upgrade();
7154         CHECK_NULL_RETURN(pattern, -1);
7155         auto index = pattern->selectController_->GetCaretIndex();
7156         return index;
7157     });
7158 }
7159 
7160 void TextFieldPattern::SetAccessibilityMoveTextAction()
7161 {
7162     auto host = GetHost();
7163     CHECK_NULL_VOID(host);
7164     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7165     CHECK_NULL_VOID(accessibilityProperty);
7166     accessibilityProperty->SetActionMoveText([weakPtr = WeakClaim(this)](int32_t moveUnit, bool forward) {
7167         const auto& pattern = weakPtr.Upgrade();
7168         CHECK_NULL_VOID(pattern);
7169         auto host = pattern->GetHost();
7170         CHECK_NULL_VOID(host);
7171         if (pattern->contentController_->IsEmpty()) {
7172             return;
7173         }
7174         int range = 0;
7175         if (moveUnit == 1) {
7176             range = 1;
7177         }
7178         auto caretPosition = forward ? pattern->selectController_->GetCaretIndex() + range
7179                                      : pattern->selectController_->GetCaretIndex() - range;
7180         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7181         pattern->SetCaretPosition(caretPosition);
7182     });
7183 }
7184 
7185 void TextFieldPattern::SetAccessibilityScrollAction()
7186 {
7187     auto host = GetHost();
7188     CHECK_NULL_VOID(host);
7189     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7190     CHECK_NULL_VOID(accessibilityProperty);
7191     accessibilityProperty->SetActionScrollForward([weakPtr = WeakClaim(this)]() {
7192         const auto& pattern = weakPtr.Upgrade();
7193         CHECK_NULL_VOID(pattern);
7194         if (pattern->IsScrollable()) {
7195             auto frameNode = pattern->GetHost();
7196             CHECK_NULL_VOID(frameNode);
7197             auto offset = pattern->GetTextContentRect().Height();
7198             float scrollDistance =
7199                 pattern->GetTextRect().Height() - (std::abs((pattern->GetTextRect().GetY() - offset)));
7200             if (offset > scrollDistance) {
7201                 pattern->OnTextAreaScroll(-scrollDistance);
7202                 // AccessibilityEventType::SCROLL_END
7203                 return;
7204             }
7205             pattern->OnTextAreaScroll(-offset);
7206             // AccessibilityEventType::SCROLL_END
7207         }
7208     });
7209 
7210     accessibilityProperty->SetActionScrollBackward([weakPtr = WeakClaim(this)]() {
7211         const auto& pattern = weakPtr.Upgrade();
7212         CHECK_NULL_VOID(pattern);
7213         if (pattern->IsScrollable()) {
7214             auto frameNode = pattern->GetHost();
7215             CHECK_NULL_VOID(frameNode);
7216             auto offset = pattern->GetTextContentRect().Height();
7217             float scrollDistance = std::abs(pattern->GetTextRect().GetY() - pattern->GetTextContentRect().GetY());
7218             if (offset > scrollDistance) {
7219                 pattern->OnTextAreaScroll(scrollDistance);
7220                 // AccessibilityEventType::SCROLL_END
7221                 return;
7222             }
7223             pattern->OnTextAreaScroll(offset);
7224             // AccessibilityEventType::SCROLL_END
7225         }
7226     });
7227 }
7228 
7229 void TextFieldPattern::SetAccessibilityErrotText()
7230 {
7231     auto host = GetHost();
7232     CHECK_NULL_VOID(host);
7233     auto accessibilityProperty = host->GetAccessibilityProperty<TextFieldAccessibilityProperty>();
7234     CHECK_NULL_VOID(accessibilityProperty);
7235     accessibilityProperty->SetErrorText(GetErrorTextString());
7236 }
7237 
7238 void TextFieldPattern::StopEditing()
7239 {
7240     if (!HasFocus()) {
7241         return;
7242     }
7243     auto host = GetHost();
7244     CHECK_NULL_VOID(host);
7245     ContainerScope scope(host->GetInstanceId());
7246     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Stop Editing", host->GetId());
7247     FocusHub::LostFocusToViewRoot();
7248     UpdateSelection(selectController_->GetCaretIndex());
7249     StopTwinkling();
7250     CloseKeyboard(true);
7251     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
7252 }
7253 
7254 void TextFieldPattern::DumpInfo()
7255 {
7256     auto host = GetHost();
7257     CHECK_NULL_VOID(host);
7258     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7259     CHECK_NULL_VOID(layoutProperty);
7260     auto& dumpLog = DumpLog::GetInstance();
7261     dumpLog.AddDesc(std::string("Content:").append(GetDumpTextValue()));
7262     dumpLog.AddDesc(std::string("autoWidth: ").append(std::to_string(layoutProperty->GetWidthAutoValue(false))));
7263     dumpLog.AddDesc(std::string("MaxLength:").append(std::to_string(GetMaxLength())));
7264     dumpLog.AddDesc(std::string("fontSize:").append(GetFontSize()));
7265     dumpLog.AddDesc(std::string("fontWeight:").append(V2::ConvertWrapFontWeightToStirng(GetFontWeight())));
7266     dumpLog.AddDesc(std::string("fontFamily:").append(GetFontFamily()));
7267     auto flag = GetItalicFontStyle() == Ace::FontStyle::NORMAL;
7268     dumpLog.AddDesc(std::string("fontStyle:").append(flag ? "FontStyle.Normal" : "FontStyle.Italic"));
7269     dumpLog.AddDesc(std::string("InputFilter:").append(GetInputFilter()));
7270     auto lineHeight = layoutProperty->GetLineHeight().value_or(0.0_vp).ConvertToPx();
7271     dumpLog.AddDesc(std::string("lineHeight:").append(std::to_string(lineHeight)));
7272     auto maxLines = GreatOrEqual(GetMaxLines(), Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLines());
7273     dumpLog.AddDesc(std::string("MaxLines:").append(maxLines));
7274     dumpLog.AddDesc(std::string("TextIndent:").append(GetTextIndent()));
7275     dumpLog.AddDesc(std::string("showError:").append(GetErrorTextState() ? GetErrorTextString() : "undefined"));
7276     dumpLog.AddDesc(std::string("CopyOption:").append(GetCopyOptionString()));
7277     dumpLog.AddDesc(std::string("TextAlign:").append(V2::ConvertWrapTextAlignToString(GetTextAlign())));
7278     dumpLog.AddDesc(std::string("CaretPosition:").append(std::to_string(GetCaretIndex())));
7279     dumpLog.AddDesc(std::string("type:").append(TextInputTypeToString()));
7280     dumpLog.AddDesc(std::string("enterKeyType:").append(TextInputActionToString()));
7281     dumpLog.AddDesc(std::string("HasFocus:").append(std::to_string(HasFocus())));
7282     dumpLog.AddDesc(std::string("enableKeyboardOnFocus:").append(std::to_string(needToRequestKeyboardOnFocus_)));
7283     dumpLog.AddDesc(std::string("supportPreviewText:").append(std::to_string(GetSupportPreviewText())));
7284     dumpLog.AddDesc(
7285         std::string("enableAutoFill:").append(std::to_string(layoutProperty->GetEnableAutoFillValue(true))));
7286     dumpLog.AddDesc(std::string("contentType:").append(TextContentTypeToString()));
7287     dumpLog.AddDesc(std::string("style:").append(GetInputStyleString()));
7288     dumpLog.AddDesc(std::string("PreviewTextStart:").append(std::to_string(GetPreviewTextStart())));
7289     dumpLog.AddDesc(std::string("PreviewTextEnd:").append(std::to_string(GetPreviewTextEnd())));
7290     dumpLog.AddDesc(std::string("PreTextValue:").append(GetPreviewTextValue()));
7291     dumpLog.AddDesc(textSelector_.ToString());
7292     dumpLog.AddDesc(std::string("wordBreak:")
7293         .append(V2::ConvertWrapWordBreakToString(layoutProperty->GetWordBreak().value_or(WordBreak::BREAK_WORD))));
7294     dumpLog.AddDesc(
7295         std::string("HeightAdaptivePolicy: ")
7296             .append(V2::ConvertWrapTextHeightAdaptivePolicyToString(
7297                 layoutProperty->GetHeightAdaptivePolicy().value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST))));
7298     dumpLog.AddDesc(std::string("IsAIWrite: ").append(std::to_string(IsShowAIWrite())));
7299     DumpPlaceHolderInfo();
7300     DumpScaleInfo();
7301     DumpTextEngineInfo();
7302     DumpAdvanceInfo();
7303 }
7304 
7305 void TextFieldPattern::DumpTextEngineInfo()
7306 {
7307     auto& dumpLog = DumpLog::GetInstance();
7308     dumpLog.AddDesc(std::string("-----TextEngine paragraphs_ info-----"));
7309     CHECK_NULL_VOID(paragraph_);
7310     dumpLog.AddDesc(std::string("GetTextWidth:")
7311         .append(std::to_string(paragraph_->GetTextWidth()))
7312         .append(" GetHeight:")
7313         .append(std::to_string(paragraph_->GetHeight()))
7314         .append(" GetMaxWidth:")
7315         .append(std::to_string(paragraph_->GetMaxWidth()))
7316         .append(" GetMaxIntrinsicWidth:")
7317         .append(std::to_string(paragraph_->GetMaxIntrinsicWidth())));
7318     dumpLog.AddDesc(std::string("GetLineCount:")
7319         .append(std::to_string(paragraph_->GetLineCount()))
7320         .append(" GetLongestLine:")
7321         .append(std::to_string(paragraph_->GetLongestLine()))
7322         .append(" GetLongestLineWithIndent:")
7323         .append(std::to_string(paragraph_->GetLongestLineWithIndent())));
7324 }
7325 
7326 void TextFieldPattern::DumpAdvanceInfo()
7327 {
7328     if (customKeyboard_ || customKeyboardBuilder_) {
7329         DumpLog::GetInstance().AddDesc(
7330             std::string("CustomKeyboard: true, Attached:").append(std::to_string(isCustomKeyboardAttached_)));
7331     }
7332     DumpLog::GetInstance().AddDesc(std::string("FontColor: ").append(GetTextColor()));
7333 #if defined(ENABLE_STANDARD_INPUT)
7334     auto miscTextConfig = GetMiscTextConfig();
7335     CHECK_NULL_VOID(miscTextConfig.has_value());
7336     MiscServices::TextConfig textConfig = miscTextConfig.value();
7337     DumpLog::GetInstance().AddDesc(
7338         std::string("RequestKeyboard calling window :").append(std::to_string(textConfig.windowId)));
7339     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
7340     DumpLog::GetInstance().AddDesc(std::string("cursorInfo, left:")
7341                                        .append(std::to_string(cursorInfo.left))
7342                                        .append(", top:")
7343                                        .append(std::to_string(cursorInfo.top))
7344                                        .append(", width:")
7345                                        .append(std::to_string(cursorInfo.width))
7346                                        .append(", height:")
7347                                        .append(std::to_string(cursorInfo.height)));
7348 #endif
7349     DumpLog::GetInstance().AddDesc(std::string("textRect: ").append(contentRect_.ToString()));
7350     DumpLog::GetInstance().AddDesc(std::string("contentRect: ").append(contentRect_.ToString()));
7351 }
7352 
7353 void TextFieldPattern::DumpPlaceHolderInfo()
7354 {
7355     DumpLog::GetInstance().AddDesc(std::string("placeholder: ").append(GetPlaceHolder()));
7356     DumpLog::GetInstance().AddDesc(std::string("placeholderColor: ").append(GetPlaceholderColor()));
7357     DumpLog::GetInstance().AddDesc(std::string("placeholderFont: ").append(GetPlaceholderFont()));
7358 }
7359 
7360 void TextFieldPattern::DumpScaleInfo()
7361 {
7362     auto& dumpLog = DumpLog::GetInstance();
7363     dumpLog.AddDesc(std::string("-----DumpScaleInfo-----"));
7364     dumpLog.AddDesc(std::string("MinFontSize:").append(GetMinFontSize()));
7365     dumpLog.AddDesc(std::string("MaxFontSize:").append(GetMaxFontSize()));
7366     auto pipeline = PipelineContext::GetCurrentContext();
7367     CHECK_NULL_VOID(pipeline);
7368     auto fontScale = pipeline->GetFontScale();
7369     auto fontWeightScale = pipeline->GetFontWeightScale();
7370     auto followSystem = pipeline->IsFollowSystem();
7371     float maxFontScale = pipeline->GetMaxAppFontScale();
7372     auto halfLeading = pipeline->GetHalfLeading();
7373     dumpLog.AddDesc(std::string("fontScale: ").append(std::to_string(fontScale)));
7374     dumpLog.AddDesc(std::string("fontWeightScale: ").append(std::to_string(fontWeightScale)));
7375     dumpLog.AddDesc(std::string("IsFollowSystem: ").append(std::to_string(followSystem)));
7376     dumpLog.AddDesc(std::string("maxFontScale: ").append(std::to_string(maxFontScale)));
7377     dumpLog.AddDesc(std::string("halfLeading: ").append(std::to_string(halfLeading)));
7378 }
7379 
7380 std::string TextFieldPattern::GetDumpTextValue() const
7381 {
7382     if (IsInPasswordMode()) {
7383         auto len = GetTextValue().length();
7384         auto passwordLen = "passwordLen:" + std::to_string(len);
7385         return passwordLen;
7386     } else {
7387         return GetTextValue();
7388     }
7389 }
7390 
7391 void TextFieldPattern::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap, bool needsRecordData)
7392 {
7393     CHECK_NULL_VOID(viewDataWrap);
7394     auto host = GetHost();
7395     CHECK_NULL_VOID(host);
7396     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7397     CHECK_NULL_VOID(layoutProperty);
7398     auto autoFillTypeAndMetaData = GetAutoFillTypeAndMetaData();
7399     auto info = PageNodeInfoWrap::CreatePageNodeInfoWrap();
7400     CHECK_NULL_VOID(info);
7401     info->SetId(host->GetId());
7402     info->SetDepth(host->GetDepth());
7403     info->SetAutoFillType(autoFillTypeAndMetaData.autoFillType);
7404     info->SetMetadata(autoFillTypeAndMetaData.metadata);
7405     info->SetTag(host->GetTag());
7406     if (autoFillOtherAccount_) {
7407         viewDataWrap->SetOtherAccount(true);
7408         info->SetValue(contentController_->GetTextValue());
7409         autoFillOtherAccount_ = false;
7410     } else {
7411         info->SetValue(contentController_->GetTextValue());
7412     }
7413     if (needsRecordData) {
7414         lastAutoFillTextValue_ = contentController_->GetTextValue();
7415     }
7416     info->SetPlaceholder(GetPlaceHolder());
7417     info->SetPasswordRules(layoutProperty->GetPasswordRulesValue(""));
7418     info->SetEnableAutoFill(layoutProperty->GetEnableAutoFillValue(true));
7419     auto offsetToWindow = host->GetOffsetRelativeToWindow();
7420     auto geometryNode = host->GetGeometryNode();
7421     CHECK_NULL_VOID(geometryNode);
7422     auto pageNodeRect = geometryNode->GetFrameRect();
7423     pageNodeRect.SetLeft(offsetToWindow.GetX());
7424     pageNodeRect.SetTop(offsetToWindow.GetY());
7425     info->SetPageNodeRect(pageNodeRect);
7426     info->SetIsFocus(HasFocus());
7427     viewDataWrap->AddPageNodeInfoWrap(info);
7428     auto pipeline = PipelineContext::GetCurrentContext();
7429     CHECK_NULL_VOID(pipeline);
7430     viewDataWrap->SetPageRect(pipeline->GetRootRect());
7431 }
7432 
7433 void TextFieldPattern::NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,
7434     RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
7435 {
7436     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "autoFillType:%{public}d", static_cast<int32_t>(autoFillType));
7437     SetFillRequestFinish(true);
7438     auto host = GetHost();
7439     CHECK_NULL_VOID(host);
7440     CHECK_NULL_VOID(viewDataWrap);
7441     CHECK_NULL_VOID(nodeWrap);
7442     auto isFocus = nodeWrap->GetIsFocus();
7443     if (isFocus && !HasFocus()) {
7444         TextFieldRequestFocus(RequestFocusReason::AUTO_FILL);
7445         bool isPopup = false;
7446         ProcessAutoFill(isPopup);
7447         DoProcessAutoFill();
7448     }
7449     auto type = GetAutoFillType();
7450     bool formOtherAccount = (viewDataWrap->GetOtherAccount() && IsTriggerAutoFillPassword());
7451     if (!(type == AceAutoFillType::ACE_NEW_PASSWORD && type == autoFillType) && !formOtherAccount) {
7452         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "Set last auto fill text value.");
7453         lastAutoFillTextValue_ = nodeWrap->GetValue();
7454     }
7455 
7456     if (!contentController_ || contentController_->GetTextValue() == nodeWrap->GetValue()) {
7457         return;
7458     }
7459     bool isWillChange = OnWillChangePreSetValue(nodeWrap->GetValue());
7460     if (!isWillChange) {
7461         return;
7462     }
7463     contentController_->SetTextValue(nodeWrap->GetValue());
7464     auto textLength = static_cast<int32_t>(contentController_->GetWideText().length());
7465     selectController_->UpdateCaretIndex(textLength);
7466     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
7467 }
7468 
7469 bool TextFieldPattern::ParseFillContentJsonValue(const std::unique_ptr<JsonValue>& jsonObject,
7470     std::unordered_map<std::string, std::variant<std::string, bool, int32_t>>& map)
7471 {
7472     if (!jsonObject->IsValid() || jsonObject->IsArray() || !jsonObject->IsObject()) {
7473         TAG_LOGE(AceLogTag::ACE_AUTO_FILL, "fillContent format is not right");
7474         return false;
7475     }
7476     auto child = jsonObject->GetChild();
7477 
7478     while (child && child->IsValid()) {
7479         if (!child->IsObject() && child->IsString()) {
7480             std::string strKey = child->GetKey();
7481             std::string strVal = child->GetString();
7482             if (strKey.empty()) {
7483                 continue;
7484             }
7485             if (map.size() < 5) {
7486                 map.insert(std::pair<std::string, std::variant<std::string, bool, int32_t> >(strKey, strVal));
7487             } else {
7488                 TAG_LOGE(AceLogTag::ACE_AUTO_FILL, "fillContent is more than 5");
7489                 break;
7490             }
7491         }
7492         child = child->GetNext();
7493     }
7494     return true;
7495 }
7496 
7497 void TextFieldPattern::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
7498 {
7499     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "errCode:%{public}d", errCode);
7500     SetFillRequestFinish(true);
7501 
7502 #if defined(ENABLE_STANDARD_INPUT)
7503     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "fillContent is : %{private}s", fillContent.c_str());
7504     if (errCode == AUTO_FILL_CANCEL) {
7505         if (!fillContent.empty() && IsTriggerAutoFillPassword()) {
7506             auto jsonObject = JsonUtil::ParseJsonString(fillContent);
7507             CHECK_NULL_VOID(jsonObject);
7508             fillContentMap_.clear();
7509             ParseFillContentJsonValue(jsonObject, fillContentMap_);
7510         }
7511     }
7512     if (!isPopup || (isPopup && errCode == AUTO_FILL_CANCEL)) {
7513         if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::AUTO_FILL_REQUEST_FAIL)) {
7514             NotifyOnEditChanged(true);
7515         }
7516     }
7517 #endif
7518 }
7519 
7520 bool TextFieldPattern::CheckAutoSave()
7521 {
7522     auto host = GetHost();
7523     CHECK_NULL_RETURN(host, false);
7524     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7525     CHECK_NULL_RETURN(layoutProperty, false);
7526     if (!layoutProperty->GetEnableAutoFillValue(true)) {
7527         return false;
7528     }
7529     if (!contentController_ || contentController_->GetTextValue().empty()) {
7530         return false;
7531     }
7532     auto autoFillType = GetAutoFillType();
7533     if (IsAutoFillUserName(autoFillType)) {
7534         if (!lastAutoFillTextValue_.empty() && contentController_->GetTextValue() != lastAutoFillTextValue_) {
7535             return true;
7536         }
7537     }
7538     if (AceAutoFillType::ACE_UNSPECIFIED < autoFillType && autoFillType <= AceAutoFillType::ACE_FORMAT_ADDRESS &&
7539         !IsAutoFillUserName(autoFillType)) {
7540         if (contentController_->GetTextValue() != lastAutoFillTextValue_) {
7541             return true;
7542         }
7543     }
7544     return false;
7545 }
7546 
7547 bool TextFieldPattern::IsTouchAtLeftOffset(float currentOffsetX)
7548 {
7549     return LessNotEqual(currentOffsetX, contentRect_.GetX() + contentRect_.Width() * 0.5);
7550 }
7551 
7552 OffsetF TextFieldPattern::GetDragUpperLeftCoordinates()
7553 {
7554     if (!IsSelected()) {
7555         return { 0.0f, 0.0f };
7556     }
7557     auto selectRects = selectController_->GetSelectedRects();
7558     auto startY = selectRects.front().Top();
7559     auto startX = selectRects.front().Left();
7560     auto endY = selectRects.back().Top();
7561     OffsetF startOffset;
7562     if (NearEqual(startY, endY)) {
7563         startOffset = { (IsTextArea() ? contentRect_.GetX() : textRect_.GetX()) + startX,
7564             startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
7565     } else {
7566         startOffset = { contentRect_.GetX(), startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
7567     }
7568 
7569     if (startOffset.GetY() < contentRect_.GetY()) {
7570         startOffset.SetY(contentRect_.GetY());
7571     }
7572     if (startOffset.GetX() < contentRect_.GetX()) {
7573         startOffset.SetX(contentRect_.GetX());
7574     }
7575     return startOffset + parentGlobalOffset_;
7576 }
7577 
7578 void TextFieldPattern::OnColorConfigurationUpdate()
7579 {
7580     colorModeChange_ = true;
7581     auto host = GetHost();
7582     CHECK_NULL_VOID(host);
7583     auto theme = GetTheme();
7584     CHECK_NULL_VOID(theme);
7585     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7586     CHECK_NULL_VOID(layoutProperty);
7587     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7588     CHECK_NULL_VOID(paintProperty);
7589     if (!paintProperty->HasTextColorFlagByUser()) {
7590         layoutProperty->UpdateTextColor(theme->GetTextColor());
7591     }
7592     if (magnifierController_) {
7593         magnifierController_->SetColorModeChange(true);
7594     }
7595     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
7596 }
7597 
7598 bool TextFieldPattern::IsReachedBoundary(float offset)
7599 {
7600     if (IsTextArea()) {
7601         return (NearEqual(textRect_.GetY(), contentRect_.GetY()) && GreatNotEqual(offset, 0.0f)) ||
7602                (NearEqual(textRect_.GetY() + textRect_.Height(), contentRect_.GetY() + contentRect_.Height()) &&
7603                    LessNotEqual(offset, 0.0f));
7604     }
7605 
7606     return (NearEqual(textRect_.GetX(), contentRect_.GetX()) && GreatNotEqual(offset, 0.0f)) ||
7607            (NearEqual(textRect_.GetX() + textRect_.Width(), contentRect_.GetX() + contentRect_.Width()) &&
7608                LessNotEqual(offset, 0.0f));
7609 }
7610 
7611 OffsetF TextFieldPattern::GetTextPaintOffset() const
7612 {
7613     if (selectOverlay_->HasRenderTransform()) {
7614         return selectOverlay_->GetPaintRectOffsetWithTransform();
7615     }
7616     return GetPaintRectGlobalOffset();
7617 }
7618 
7619 OffsetF TextFieldPattern::GetPaintRectGlobalOffset() const
7620 {
7621     auto host = GetHost();
7622     CHECK_NULL_RETURN(host, OffsetF(0.0f, 0.0f));
7623     auto pipeline = host->GetContextRefPtr();
7624     CHECK_NULL_RETURN(pipeline, OffsetF(0.0f, 0.0f));
7625     auto rootOffset = pipeline->GetRootRect().GetOffset();
7626     OffsetF textPaintOffset;
7627     textPaintOffset = host->GetPaintRectOffset(false, true);
7628     return textPaintOffset - rootOffset;
7629 }
7630 
7631 void TextFieldPattern::UpdateSelectController()
7632 {
7633     selectController_->UpdateContentRect(contentRect_);
7634     selectController_->UpdateParagraph(paragraph_);
7635 }
7636 
7637 bool TextFieldPattern::RepeatClickCaret(const Offset& offset, int32_t lastCaretIndex)
7638 {
7639     auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset);
7640     return lastCaretIndex == touchDownIndex && HasFocus();
7641 }
7642 
7643 bool TextFieldPattern::RepeatClickCaret(const Offset& offset, const RectF& lastCaretRect)
7644 {
7645     auto caretRect = lastCaretRect;
7646     caretRect.SetLeft(caretRect.GetX() - caretRect.Height() / 2);
7647     caretRect.SetWidth(caretRect.Height());
7648     return caretRect.IsInRegion(PointF(offset.GetX(), offset.GetY()));
7649 }
7650 
7651 void TextFieldPattern::OnAttachToFrameNode()
7652 {
7653     auto frameNode = GetHost();
7654     CHECK_NULL_VOID(frameNode);
7655     StylusDetectorMgr::GetInstance()->AddTextFieldFrameNode(frameNode, WeakClaim(this));
7656 
7657     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7658     CHECK_NULL_VOID(layoutProperty);
7659     layoutProperty->UpdateCopyOptions(CopyOptions::Distributed);
7660     auto pipeline = PipelineContext::GetCurrentContextSafely();
7661     CHECK_NULL_VOID(pipeline);
7662     auto fontManager = pipeline->GetFontManager();
7663     if (fontManager) {
7664         auto host = GetHost();
7665         fontManager->AddFontNodeNG(host);
7666     }
7667     auto onTextSelectorChange = [weak = WeakClaim(this)]() {
7668         auto pattern = weak.Upgrade();
7669         CHECK_NULL_VOID(pattern);
7670         auto frameNode = pattern->GetHost();
7671         CHECK_NULL_VOID(frameNode);
7672         frameNode->OnAccessibilityEvent(AccessibilityEventType::TEXT_SELECTION_UPDATE);
7673     };
7674     selectController_->SetOnAccessibility(std::move(onTextSelectorChange));
7675 }
7676 
7677 bool TextFieldPattern::NeedPaintSelect()
7678 {
7679     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7680     CHECK_NULL_RETURN(paintProperty, false);
7681     auto firstHandle = paintProperty->GetFirstHandleInfo();
7682     auto secondHandle = paintProperty->GetSecondHandleInfo();
7683     auto caretInfo = selectController_->GetCaretInfo();
7684     if (!IsSelected()) {
7685         if (!firstHandle.has_value() || !secondHandle.has_value()) {
7686             paintProperty->UpdateFirstHandleInfo(caretInfo);
7687             paintProperty->UpdateSecondHandleInfo(caretInfo);
7688             return false;
7689         }
7690 
7691         if (firstHandle->index != secondHandle->index || firstHandle->index != caretInfo.index) {
7692             paintProperty->UpdateFirstHandleInfo(caretInfo);
7693             paintProperty->UpdateSecondHandleInfo(caretInfo);
7694             return true;
7695         }
7696         return false;
7697     }
7698     auto needPaint = firstHandle != selectController_->GetFirstHandleInfo() ||
7699                      secondHandle != selectController_->GetSecondHandleInfo();
7700     paintProperty->UpdateFirstHandleInfo(selectController_->GetFirstHandleInfo());
7701     paintProperty->UpdateSecondHandleInfo(selectController_->GetSecondHandleInfo());
7702     return needPaint;
7703 }
7704 
7705 RefPtr<FocusHub> TextFieldPattern::GetFocusHub() const
7706 {
7707     auto host = GetHost();
7708     CHECK_NULL_RETURN(host, nullptr);
7709     auto focusHub = host->GetOrCreateFocusHub();
7710     return focusHub;
7711 }
7712 
7713 void TextFieldPattern::UpdateRecordCaretIndex(int32_t index)
7714 {
7715     if (lockRecord_ || operationRecords_.empty()) {
7716         return;
7717     }
7718     operationRecords_.back().caretPosition = index;
7719 }
7720 
7721 void TextFieldPattern::OnObscuredChanged(bool isObscured)
7722 {
7723     ResetObscureTickCountDown();
7724     obscuredChange_ = textObscured_ != isObscured;
7725     textObscured_ = isObscured;
7726     CloseSelectOverlay(false);
7727     if (obscuredChange_) {
7728         selectController_->UpdateCaretIndex(static_cast<int32_t>(contentController_->GetWideText().length()));
7729     }
7730     auto host = GetHost();
7731     CHECK_NULL_VOID(host);
7732     if (obscuredChange_) {
7733         auto eventHub = host->GetEventHub<TextFieldEventHub>();
7734         CHECK_NULL_VOID(eventHub);
7735         eventHub->FireOnSecurityStateChanged(!isObscured);
7736     }
7737     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
7738 }
7739 
7740 void TextFieldPattern::CreateHandles()
7741 {
7742     if (IsDragging() || !HasFocus()) {
7743         return;
7744     }
7745     auto host = GetHost();
7746     CHECK_NULL_VOID(host);
7747     showSelect_ = true;
7748     if (selectOverlay_->IsUseTouchAtLast()) {
7749         SetIsSingleHandle(!IsSelected());
7750         ProcessOverlay({ .menuIsShow = false });
7751     }
7752     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
7753 }
7754 
7755 void TextFieldPattern::NotifyOnEditChanged(bool isChanged)
7756 {
7757     auto host = GetHost();
7758     CHECK_NULL_VOID(host);
7759     auto eventHub = host->GetEventHub<TextFieldEventHub>();
7760     CHECK_NULL_VOID(eventHub);
7761     if (isChanged != isEdit_) {
7762         isEdit_ = isChanged;
7763         eventHub->FireOnEditChanged(isChanged);
7764     }
7765 }
7766 
7767 size_t TextFieldPattern::GetLineCount() const
7768 {
7769     return paragraph_ ? paragraph_->GetLineCount() : 0;
7770 }
7771 
7772 void TextFieldPattern::UpdateHandlesOffsetOnScroll(float offset)
7773 {
7774     if (SelectOverlayIsOn()) {
7775         selectController_->UpdateSecondHandleOffset();
7776         if (!selectOverlay_->IsSingleHandle()) {
7777             selectController_->UpdateFirstHandleOffset();
7778             selectController_->UpdateCaretOffset(TextAffinity::DOWNSTREAM, false);
7779             selectOverlay_->UpdateAllHandlesOffset();
7780         } else {
7781             auto carectOffset = selectController_->GetCaretRect().GetOffset() +
7782                                 (IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
7783             selectController_->UpdateCaretOffset(carectOffset);
7784             selectOverlay_->UpdateSecondHandleOffset();
7785         }
7786     } else {
7787         auto caretOffset = selectController_->GetCaretRect().GetOffset() +
7788                            (IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
7789         selectController_->UpdateCaretOffset(caretOffset);
7790     }
7791 }
7792 
7793 void TextFieldPattern::CloseHandleAndSelect()
7794 {
7795     CloseSelectOverlay(true);
7796     showSelect_ = false;
7797 }
7798 
7799 bool TextFieldPattern::IsShowUnit() const
7800 {
7801     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7802     CHECK_NULL_RETURN(layoutProperty, false);
7803     auto typeValue = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
7804     return layoutProperty->GetShowUnderlineValue(false) &&
7805            (typeValue == TextInputType::UNSPECIFIED || typeValue == TextInputType::TEXT);
7806 }
7807 
7808 bool TextFieldPattern::IsShowPasswordIcon() const
7809 {
7810     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7811     CHECK_NULL_RETURN(layoutProperty, false);
7812     return layoutProperty->GetShowPasswordIconValue(true) && IsInPasswordMode();
7813 }
7814 
7815 std::optional<bool> TextFieldPattern::IsShowPasswordText() const
7816 {
7817     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7818     CHECK_NULL_RETURN(layoutProperty, false);
7819     return layoutProperty->GetShowPasswordText();
7820 }
7821 
7822 bool TextFieldPattern::IsShowCancelButtonMode() const
7823 {
7824     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7825     CHECK_NULL_RETURN(layoutProperty, false);
7826     return !IsNormalInlineState() && !IsTextArea() && layoutProperty->GetIsShowCancelButton().value_or(false);
7827 }
7828 
7829 void TextFieldPattern::CheckPasswordAreaState()
7830 {
7831     auto showPasswordState = IsShowPasswordText();
7832     if (!showPasswordState.has_value()) {
7833         return;
7834     }
7835     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
7836     CHECK_NULL_VOID(passwordArea);
7837     passwordArea->SetObscured(!showPasswordState.value());
7838 }
7839 
7840 void TextFieldPattern::AfterLayoutProcessCleanResponse(
7841     const RefPtr<CleanNodeResponseArea>& cleanNodeResponseArea)
7842 {
7843     auto pipeline = PipelineContext::GetCurrentContextSafely();
7844     CHECK_NULL_VOID(pipeline);
7845     pipeline->AddAfterLayoutTask([weak = WeakClaim(cleanNodeResponseArea.GetRawPtr())]() {
7846         auto cleanNodeResponseArea = weak.Upgrade();
7847         CHECK_NULL_VOID(cleanNodeResponseArea);
7848         cleanNodeResponseArea->UpdateCleanNode(cleanNodeResponseArea->IsShow());
7849     });
7850 }
7851 
7852 void TextFieldPattern::ProcessCancelButton()
7853 {
7854     if (IsShowCancelButtonMode()) {
7855         auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
7856         if (cleanNodeResponseArea) {
7857             cleanNodeResponseArea->Refresh();
7858             if (cleanNodeResponseArea->IsShow()) {
7859                 AfterLayoutProcessCleanResponse(cleanNodeResponseArea);
7860             } else {
7861                 UpdateCancelNode();
7862             }
7863         } else {
7864             cleanNodeResponseArea_ = AceType::MakeRefPtr<CleanNodeResponseArea>(WeakClaim(this));
7865             cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
7866             cleanNodeResponseArea->InitResponseArea();
7867             UpdateCancelNode();
7868         }
7869     } else {
7870         if (cleanNodeResponseArea_) {
7871             cleanNodeResponseArea_->ClearArea();
7872             cleanNodeResponseArea_.Reset();
7873         }
7874     }
7875 }
7876 
7877 void TextFieldPattern::ProcessResponseArea()
7878 {
7879     ProcessCancelButton();
7880     if (IsInPasswordMode()) {
7881         auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
7882         if (passwordArea) {
7883             if (IsShowPasswordIcon()) {
7884                 passwordArea->Refresh();
7885             } else {
7886                 passwordArea->ClearArea();
7887             }
7888             CheckPasswordAreaState();
7889             return;
7890         }
7891         // responseArea_ may not be a password area.
7892         responseArea_ = AceType::MakeRefPtr<PasswordResponseArea>(WeakClaim(this), GetTextObscured());
7893         if (IsShowPasswordIcon()) {
7894             responseArea_->InitResponseArea();
7895         } else {
7896             responseArea_->ClearArea();
7897         }
7898         CheckPasswordAreaState();
7899         return;
7900     }
7901 
7902     if (IsUnderlineMode()) {
7903         responseArea_ = AceType::MakeRefPtr<UnitResponseArea>(WeakClaim(this), unitNode_);
7904         responseArea_->InitResponseArea();
7905         auto host = GetHost();
7906         CHECK_NULL_VOID(host);
7907         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
7908         return;
7909     }
7910 
7911     if (responseArea_) {
7912         responseArea_->ClearArea();
7913     }
7914 }
7915 
7916 void TextFieldPattern::UpdateCancelNode()
7917 {
7918     auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
7919     CHECK_NULL_VOID(cleanNodeResponseArea);
7920     auto host = GetHost();
7921     CHECK_NULL_VOID(host);
7922     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7923     CHECK_NULL_VOID(layoutProperty);
7924     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
7925     if (cleanNodeStyle == CleanNodeStyle::CONSTANT ||
7926         (cleanNodeStyle == CleanNodeStyle::INPUT && !contentController_->IsEmpty())) {
7927         if (!cleanNodeResponseArea->IsShow()) {
7928             cleanNodeResponseArea->UpdateCleanNode(true);
7929         }
7930     } else if (cleanNodeStyle == CleanNodeStyle::INVISIBLE ||
7931                (cleanNodeStyle == CleanNodeStyle::INPUT && contentController_->IsEmpty())) {
7932         if (cleanNodeResponseArea->IsShow()) {
7933             cleanNodeResponseArea->UpdateCleanNode(false);
7934         }
7935     }
7936 }
7937 
7938 bool TextFieldPattern::HasInputOperation()
7939 {
7940     return !deleteBackwardOperations_.empty() || !deleteForwardOperations_.empty() || !insertCommands_.empty();
7941 }
7942 
7943 void TextFieldPattern::FocusForwardStopTwinkling()
7944 {
7945     auto host = GetHost();
7946     CHECK_NULL_VOID(host);
7947     UpdateSelection(selectController_->GetCaretIndex());
7948     StopTwinkling();
7949     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
7950 }
7951 
7952 bool TextFieldPattern::UpdateFocusForward()
7953 {
7954     if (focusIndex_ == FocuseIndex::TEXT && HasFocus()) {
7955         FocusForwardStopTwinkling();
7956         if (!CancelNodeIsShow()) {
7957             if (responseArea_ == nullptr || (!IsShowUnit() && !IsShowPasswordIcon())) {
7958                 return false;
7959             }
7960             focusIndex_ = FocuseIndex::UNIT;
7961             PaintResponseAreaRect();
7962             return true;
7963         }
7964         focusIndex_ = FocuseIndex::CANCEL;
7965         PaintCancelRect();
7966         return true;
7967     }
7968     if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
7969         FocusForwardStopTwinkling();
7970         if (responseArea_ == nullptr) {
7971             return false;
7972         }
7973         focusIndex_ = FocuseIndex::UNIT;
7974         PaintResponseAreaRect();
7975         return true;
7976     }
7977     return false;
7978 }
7979 
7980 bool TextFieldPattern::UpdateFocusBackward()
7981 {
7982     if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
7983         focusIndex_ = FocuseIndex::TEXT;
7984         PaintTextRect();
7985         StartTwinkling();
7986         return true;
7987     } else if (focusIndex_ == FocuseIndex::UNIT && HasFocus()) {
7988         if (!CancelNodeIsShow()) {
7989             focusIndex_ = FocuseIndex::TEXT;
7990             PaintTextRect();
7991             StartTwinkling();
7992             return true;
7993         }
7994         focusIndex_ = FocuseIndex::CANCEL;
7995         PaintCancelRect();
7996         return true;
7997     }
7998     return false;
7999 }
8000 
8001 bool TextFieldPattern::HandleSpaceEvent()
8002 {
8003     if (focusIndex_ == FocuseIndex::CANCEL) {
8004         CleanNodeResponseKeyEvent();
8005         return true;
8006     } else if (focusIndex_ == FocuseIndex::UNIT) {
8007         if (IsShowPasswordIcon()) {
8008             PasswordResponseKeyEvent();
8009         }
8010         if (IsShowUnit()) {
8011             UnitResponseKeyEvent();
8012         }
8013         return true;
8014     }
8015     return false;
8016 }
8017 
8018 void TextFieldPattern::PaintTextRect()
8019 {
8020     RoundRect focusRect;
8021     auto host = GetHost();
8022     CHECK_NULL_VOID(host);
8023     auto focusHub = host->GetFocusHub();
8024     CHECK_NULL_VOID(focusHub);
8025     focusHub->PaintInnerFocusState(focusRect);
8026 }
8027 
8028 void TextFieldPattern::GetIconPaintRect(const RefPtr<TextInputResponseArea>& responseArea, RoundRect& paintRect)
8029 {
8030     auto stackNode = responseArea->GetFrameNode();
8031     CHECK_NULL_VOID(stackNode);
8032     auto stackRect = stackNode->GetGeometryNode()->GetFrameRect();
8033     auto imageNode = stackNode->GetFirstChild();
8034     CHECK_NULL_VOID(imageNode);
8035     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
8036     CHECK_NULL_VOID(imageFrameNode);
8037     auto imageRect = imageFrameNode->GetGeometryNode()->GetFrameRect();
8038     RectF rect(stackRect.GetX(), stackRect.GetY(), imageRect.Width(), imageRect.Height());
8039     paintRect.SetRect(rect);
8040 }
8041 
8042 void TextFieldPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
8043 {
8044     if (focusIndex_ == FocuseIndex::CANCEL) {
8045         CHECK_NULL_VOID(cleanNodeResponseArea_);
8046         GetIconPaintRect(cleanNodeResponseArea_, paintRect);
8047     } else if (focusIndex_ == FocuseIndex::UNIT) {
8048         if (IsShowPasswordIcon()) {
8049             CHECK_NULL_VOID(responseArea_);
8050             GetIconPaintRect(responseArea_, paintRect);
8051         }
8052         if (IsShowUnit()) {
8053             CHECK_NULL_VOID(responseArea_);
8054             auto unitResponseArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
8055             CHECK_NULL_VOID(unitResponseArea);
8056             auto unitNode = unitResponseArea->GetFrameNode();
8057             CHECK_NULL_VOID(unitNode);
8058             auto unitRect = unitNode->GetGeometryNode()->GetFrameRect();
8059             paintRect.SetRect(unitRect);
8060         }
8061     }
8062 }
8063 
8064 void TextFieldPattern::PaintCancelRect()
8065 {
8066     RoundRect focusRect;
8067     GetInnerFocusPaintRect(focusRect);
8068     auto host = GetHost();
8069     CHECK_NULL_VOID(host);
8070     auto focusHub = host->GetFocusHub();
8071     CHECK_NULL_VOID(focusHub);
8072     focusHub->PaintInnerFocusState(focusRect);
8073 }
8074 
8075 void TextFieldPattern::PaintResponseAreaRect()
8076 {
8077     if (IsShowPasswordIcon()) {
8078         PaintPasswordRect();
8079     }
8080     if (IsShowUnit()) {
8081         PaintUnitRect();
8082     }
8083 }
8084 
8085 void TextFieldPattern::PaintPasswordRect()
8086 {
8087     RoundRect focusRect;
8088     GetInnerFocusPaintRect(focusRect);
8089     float cornerRadius = focusRect.GetRect().Width() / 2;
8090     focusRect.SetCornerRadius(cornerRadius);
8091     auto host = GetHost();
8092     CHECK_NULL_VOID(host);
8093     auto focusHub = host->GetFocusHub();
8094     CHECK_NULL_VOID(focusHub);
8095     focusHub->PaintInnerFocusState(focusRect);
8096 }
8097 
8098 void TextFieldPattern::PaintUnitRect()
8099 {
8100     RoundRect focusRect;
8101     GetInnerFocusPaintRect(focusRect);
8102     auto host = GetHost();
8103     CHECK_NULL_VOID(host);
8104     auto focusHub = host->GetFocusHub();
8105     CHECK_NULL_VOID(focusHub);
8106     focusHub->PaintInnerFocusState(focusRect);
8107 }
8108 
8109 void TextFieldPattern::CleanNodeResponseKeyEvent()
8110 {
8111     CHECK_NULL_VOID(!IsDragging());
8112     auto host = GetHost();
8113     CHECK_NULL_VOID(host);
8114     ClearTextContent();
8115     CloseSelectOverlay();
8116     StartTwinkling();
8117     UpdateCaretInfoToController();
8118     if (!HasFocus()) {
8119         auto focusHub = host->GetOrCreateFocusHub();
8120         TextFieldRequestFocus(RequestFocusReason::CLEAN_NODE);
8121     }
8122     host->MarkModifyDone();
8123     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8124 }
8125 
8126 void TextFieldPattern::RegisterWindowSizeCallback()
8127 {
8128     if (isOritationListenerRegisted_) {
8129         return;
8130     }
8131     isOritationListenerRegisted_ = true;
8132     auto host = GetHost();
8133     CHECK_NULL_VOID(host);
8134     auto pipeline = PipelineContext::GetCurrentContext();
8135     CHECK_NULL_VOID(pipeline);
8136     pipeline->AddWindowSizeChangeCallback(host->GetId());
8137 }
8138 
8139 void TextFieldPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
8140 {
8141     if (type != WindowSizeChangeReason::ROTATION) {
8142         return;
8143     }
8144     if (SelectOverlayIsOn()) {
8145         selectController_->CalculateHandleOffset();
8146         selectOverlay_->ProcessOverlayOnAreaChanged({ .menuIsShow = false});
8147     }
8148     auto host = GetHost();
8149     CHECK_NULL_VOID(host);
8150     auto context = host->GetContextRefPtr();
8151     CHECK_NULL_VOID(context);
8152     auto taskExecutor = context->GetTaskExecutor();
8153     CHECK_NULL_VOID(taskExecutor);
8154     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
8155     CHECK_NULL_VOID(textFieldManager);
8156     textFieldManager->ResetOptionalClickPosition();
8157     taskExecutor->PostTask(
8158         [weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
8159             auto textField = weak.Upgrade();
8160             CHECK_NULL_VOID(textField);
8161             auto host = textField->GetHost();
8162             CHECK_NULL_VOID(host);
8163             auto nodeId = host->GetId();
8164             textField->parentGlobalOffset_ = textField->GetPaintRectGlobalOffset();
8165             textField->UpdateTextFieldManager(Offset(textField->parentGlobalOffset_.GetX(),
8166                 textField->parentGlobalOffset_.GetY()), textField->frameRect_.Height());
8167             textField->UpdateCaretInfoToController(true);
8168             TAG_LOGI(ACE_TEXT_FIELD, "%{public}d OnWindowSizeChanged change parentGlobalOffset to: %{public}s",
8169                 nodeId, textField->parentGlobalOffset_.ToString().c_str());
8170         },
8171         TaskExecutor::TaskType::UI, "ArkUITextFieldOnWindowSizeChangedRotation");
8172 }
8173 
8174 void TextFieldPattern::PasswordResponseKeyEvent()
8175 {
8176     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
8177     CHECK_NULL_VOID(passwordArea);
8178     passwordArea->OnPasswordIconClicked();
8179 }
8180 
8181 void TextFieldPattern::UnitResponseKeyEvent()
8182 {
8183     auto unitArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
8184     CHECK_NULL_VOID(unitArea);
8185     auto frameNode = unitArea->GetFrameNode();
8186     CHECK_NULL_VOID(frameNode);
8187     if (frameNode->GetTag() == V2::SELECT_ETS_TAG) {
8188         auto selectPattern = frameNode->GetPattern<SelectPattern>();
8189         CHECK_NULL_VOID(selectPattern);
8190         selectPattern->ShowSelectMenu();
8191     }
8192 }
8193 
8194 void TextFieldPattern::ScrollToSafeArea() const
8195 {
8196     auto host = GetHost();
8197     CHECK_NULL_VOID(host);
8198     auto pipeline = host->GetContext();
8199     CHECK_NULL_VOID(pipeline);
8200     if (pipeline->UsingCaretAvoidMode()) {
8201         // using TriggerAvoidOnCaretChange instead in CaretAvoidMode
8202         return;
8203     }
8204     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8205     CHECK_NULL_VOID(textFieldManager);
8206     textFieldManager->ScrollTextFieldToSafeArea();
8207 }
8208 
8209 void TextFieldPattern::TriggerAvoidOnCaretChange()
8210 {
8211     CHECK_NULL_VOID(HasFocus());
8212     auto host = GetHost();
8213     CHECK_NULL_VOID(host);
8214     auto pipeline = host->GetContext();
8215     CHECK_NULL_VOID(pipeline);
8216     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8217     CHECK_NULL_VOID(textFieldManager);
8218     CHECK_NULL_VOID(pipeline->UsingCaretAvoidMode());
8219     auto safeAreaManager = pipeline->GetSafeAreaManager();
8220     if (!safeAreaManager || NearEqual(safeAreaManager->GetKeyboardInset().Length(), 0)) {
8221         return;
8222     }
8223     textFieldManager->TriggerAvoidOnCaretChange();
8224     auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
8225     SetLastCaretPos(caretPos);
8226 }
8227 
8228 void TextFieldPattern::CheckTextAlignByDirection(TextAlign& textAlign, TextDirection direction)
8229 {
8230     if (direction == TextDirection::RTL) {
8231         if (textAlign == TextAlign::START) {
8232             textAlign = TextAlign::END;
8233         } else if (textAlign == TextAlign::END) {
8234             textAlign = TextAlign::START;
8235         }
8236     }
8237 }
8238 
8239 void TextFieldPattern::RequestKeyboardAfterLongPress()
8240 {
8241 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
8242     if (isLongPress_ && HasFocus() && RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::LONG_PRESS)) {
8243         NotifyOnEditChanged(true);
8244     }
8245     isLongPress_ = false;
8246 #endif
8247 }
8248 
8249 void TextFieldPattern::GetCaretMetrics(CaretMetricsF& caretCaretMetric)
8250 {
8251     OffsetF offset = selectController_->GetCaretRect().GetOffset();
8252     float height = selectController_->GetCaretRect().Height();
8253     float width = selectController_->GetCaretRect().Width();
8254     auto host = GetHost();
8255     CHECK_NULL_VOID(host);
8256     auto textPaintOffset = host->GetPaintRectOffset(false, true);
8257     caretCaretMetric.offset = offset + textPaintOffset + OffsetF(width / 2.0f, 0.0f);
8258     caretCaretMetric.height = height;
8259 }
8260 
8261 // correct after OnModifyDone
8262 bool TextFieldPattern::IsUnderlineMode() const
8263 {
8264     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8265     CHECK_NULL_RETURN(layoutProperty, false);
8266     return layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType() && !IsInlineMode();
8267 }
8268 
8269 // correct after OnModifyDone
8270 bool TextFieldPattern::IsInlineMode() const
8271 {
8272     return HasFocus() && IsNormalInlineState();
8273 }
8274 
8275 bool TextFieldPattern::IsShowError()
8276 {
8277     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8278     CHECK_NULL_RETURN(layoutProperty, false);
8279     auto errorText = layoutProperty->GetErrorTextValue("");
8280     return layoutProperty->GetShowErrorTextValue(false) && !errorText.empty() && !IsNormalInlineState();
8281 }
8282 
8283 bool TextFieldPattern::IsShowCount()
8284 {
8285     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8286     CHECK_NULL_RETURN(layoutProperty, false);
8287     return layoutProperty->GetShowCounterValue(false) && !IsNormalInlineState() && !IsInPasswordMode() &&
8288            layoutProperty->HasMaxLength();
8289 }
8290 
8291 void TextFieldPattern::ResetContextAttr()
8292 {
8293     auto host = GetHost();
8294     CHECK_NULL_VOID(host);
8295     auto renderContext = host->GetRenderContext();
8296     CHECK_NULL_VOID(renderContext);
8297     renderContext->ResetBorder();
8298     BorderWidthProperty borderWidth;
8299     borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
8300     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8301     CHECK_NULL_VOID(layoutProperty);
8302     layoutProperty->UpdateBorderWidth(borderWidth);
8303 }
8304 
8305 void TextFieldPattern::SetThemeBorderAttr()
8306 {
8307     auto host = GetHost();
8308     CHECK_NULL_VOID(host);
8309     auto renderContext = host->GetRenderContext();
8310     CHECK_NULL_VOID(renderContext);
8311     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8312     CHECK_NULL_VOID(layoutProperty);
8313     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8314     CHECK_NULL_VOID(paintProperty);
8315     auto theme = GetTheme();
8316     CHECK_NULL_VOID(theme);
8317 
8318     paintProperty->ResetInnerBorderColor();
8319     paintProperty->ResetInnerBorderWidth();
8320     if (!paintProperty->HasBorderColorFlagByUser()) {
8321         BorderColorProperty borderColor;
8322         borderColor.SetColor(Color::BLACK);
8323         renderContext->UpdateBorderColor(borderColor);
8324     } else {
8325         renderContext->UpdateBorderColor(paintProperty->GetBorderColorFlagByUserValue());
8326     }
8327 
8328     if (!paintProperty->HasBorderRadiusFlagByUser()) {
8329         auto radius = theme->GetBorderRadius();
8330         BorderRadiusProperty borderRadius(radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX());
8331         auto ultimatelyRadius = IsUnderlineMode() ?  ZERO_BORDER_RADIUS_PROPERTY : borderRadius;
8332         renderContext->UpdateBorderRadius(ultimatelyRadius);
8333     } else {
8334         renderContext->UpdateBorderRadius(paintProperty->GetBorderRadiusFlagByUserValue());
8335     }
8336 
8337     if (!paintProperty->HasBorderWidthFlagByUser()) {
8338         BorderWidthProperty borderWidth;
8339         borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
8340         renderContext->UpdateBorderWidth(borderWidth);
8341         layoutProperty->UpdateBorderWidth(borderWidth);
8342     } else {
8343         renderContext->UpdateBorderWidth(paintProperty->GetBorderWidthFlagByUserValue());
8344         layoutProperty->UpdateBorderWidth(paintProperty->GetBorderWidthFlagByUserValue());
8345     }
8346 }
8347 
8348 PaddingProperty TextFieldPattern::GetPaddingByUserValue()
8349 {
8350     PaddingProperty padding;
8351     auto theme = GetTheme();
8352     CHECK_NULL_RETURN(theme, padding);
8353     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8354     CHECK_NULL_RETURN(paintProperty, padding);
8355     padding = paintProperty->GetPaddingByUserValue();
8356     auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
8357     if (!padding.top.has_value()) {
8358         padding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
8359     }
8360     if (!padding.bottom.has_value()) {
8361         padding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
8362     }
8363     if (!padding.left.has_value()) {
8364         padding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
8365     }
8366     if (!padding.right.has_value()) {
8367         padding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
8368     }
8369     return padding;
8370 }
8371 
8372 void TextFieldPattern::SetThemeAttr()
8373 {
8374     auto host = GetHost();
8375     CHECK_NULL_VOID(host);
8376     auto renderContext = host->GetRenderContext();
8377     CHECK_NULL_VOID(renderContext);
8378     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8379     CHECK_NULL_VOID(layoutProperty);
8380     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8381     CHECK_NULL_VOID(paintProperty);
8382     auto theme = GetTheme();
8383     CHECK_NULL_VOID(theme);
8384     SetThemeBorderAttr();
8385     if (!paintProperty->HasBackgroundColor()) {
8386         auto backgroundColor = IsUnderlineMode() ? Color::TRANSPARENT : theme->GetBgColor();
8387         renderContext->UpdateBackgroundColor(backgroundColor);
8388     } else {
8389         renderContext->UpdateBackgroundColor(paintProperty->GetBackgroundColorValue());
8390     }
8391 
8392     if (!paintProperty->HasMarginByUser()) {
8393         MarginProperty margin;
8394         margin.SetEdges(CalcLength(0.0_vp));
8395         layoutProperty->UpdateMargin(margin);
8396     } else {
8397         layoutProperty->UpdateMargin(paintProperty->GetMarginByUserValue());
8398     }
8399 
8400     if (!paintProperty->HasPaddingByUser()) {
8401         auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
8402         PaddingProperty padding;
8403         padding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
8404         padding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
8405         padding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
8406         padding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
8407         layoutProperty->UpdatePadding(padding);
8408     } else {
8409         layoutProperty->UpdatePadding(GetPaddingByUserValue());
8410     }
8411 
8412     if (!paintProperty->HasTextColorFlagByUser()) {
8413         layoutProperty->UpdateTextColor(theme->GetTextColor());
8414     } else {
8415         layoutProperty->UpdateTextColor(paintProperty->GetTextColorFlagByUserValue());
8416     }
8417     inlineFocusState_ = false;
8418 }
8419 
8420 const Dimension& TextFieldPattern::GetAvoidSoftKeyboardOffset() const
8421 {
8422     auto textfieldTheme = GetTheme();
8423     if (!textfieldTheme) {
8424         return TextBase::GetAvoidSoftKeyboardOffset();
8425     }
8426     return textfieldTheme->GetAvoidKeyboardOffset();
8427 }
8428 
8429 Offset TextFieldPattern::ConvertGlobalToLocalOffset(const Offset& globalOffset)
8430 {
8431     parentGlobalOffset_ = GetPaintRectGlobalOffset();
8432     auto localOffset = globalOffset - Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY());
8433     if (selectOverlay_->HasRenderTransform()) {
8434         auto localOffsetF = OffsetF(globalOffset.GetX(), globalOffset.GetY());
8435         selectOverlay_->RevertLocalPointWithTransform(localOffsetF);
8436         localOffset.SetX(localOffsetF.GetX());
8437         localOffset.SetY(localOffsetF.GetY());
8438     }
8439     return localOffset;
8440 }
8441 
8442 int32_t TextFieldPattern::SetPreviewText(const std::string &previewValue, const PreviewRange range)
8443 {
8444     PreviewTextInfo info = {
8445         .text = previewValue,
8446         .range = range,
8447         .isIme = true
8448     };
8449     auto host = GetHost();
8450     CHECK_NULL_RETURN(host, PREVIEW_NULL_POINTER);
8451     inputOperations_.emplace(InputOperation::SET_PREVIEW_TEXT);
8452     previewTextOperation_.emplace(info);
8453     CloseSelectOverlay(true);
8454     ScrollToSafeArea();
8455     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
8456     return PREVIEW_NO_ERROR;
8457 }
8458 
8459 void TextFieldPattern::SetPreviewTextOperation(PreviewTextInfo info)
8460 {
8461     auto host = GetHost();
8462     CHECK_NULL_VOID(host);
8463     if (!hasPreviewText_) {
8464         bodyTextInPreivewing_ = GetTextValue();
8465     }
8466     auto rangeStart = info.range.start;
8467     auto rangeEnd = info.range.end;
8468     auto start = GetPreviewTextStart();
8469     auto end = GetPreviewTextEnd();
8470     if (IsSelected()) {
8471         start = selectController_->GetStartIndex();
8472         end = selectController_->GetEndIndex();
8473     } else {
8474         start = (rangeStart == PREVIEW_TEXT_RANGE_DEFAULT) ? start : rangeStart;
8475         end = (rangeEnd == PREVIEW_TEXT_RANGE_DEFAULT) ? end : rangeEnd;
8476     }
8477 
8478     auto oldHasPreviewText = hasPreviewText_;
8479     ChangeValueInfo changeValueInfo;
8480     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
8481     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
8482     changeValueInfo.oldContent = GetBodyTextValue();
8483     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
8484     changeValueInfo.rangeAfter = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
8485     auto originCaretIndex =
8486             TextRange { changeValueInfo.oldPreviewText.offset, changeValueInfo.oldPreviewText.offset };
8487     bool hasInsertValue = false;
8488     auto originLength = static_cast<int32_t>(contentController_->GetWideText().length()) - (end - start);
8489     hasInsertValue = contentController_->ReplaceSelectedValue(start, end, info.text);
8490     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetWideText().length()) - originLength);
8491 
8492     int32_t delta =
8493             static_cast<int32_t>(contentController_->GetWideText().length()) - originLength - (end - start);
8494     int32_t newCaretPosition = std::max(end, GetPreviewTextEnd()) + delta;
8495     newCaretPosition = std::clamp(newCaretPosition, 0,
8496         static_cast<int32_t>(contentController_->GetWideText().length()));
8497     selectController_->UpdateCaretIndex(start + caretMoveLength);
8498 
8499     UpdatePreviewIndex(start, newCaretPosition);
8500     hasPreviewText_ = true;
8501     changeValueInfo.value = GetBodyTextValue();
8502     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
8503     changeValueInfo.previewText.value = GetPreviewTextValue();
8504     bool isWillChange = FireOnWillChange(changeValueInfo);
8505     if (!isWillChange && !info.isIme) {
8506         RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
8507         hasPreviewText_ = oldHasPreviewText;
8508         return;
8509     }
8510     if (HasFocus()) {
8511         cursorVisible_ = true;
8512         StartTwinkling();
8513     } else {
8514         cursorVisible_ = false;
8515         StopTwinkling();
8516     }
8517 }
8518 
8519 void TextFieldPattern::FinishTextPreview()
8520 {
8521     inputOperations_.emplace(InputOperation::SET_PREVIEW_FINISH);
8522     auto host = GetHost();
8523     CHECK_NULL_VOID(host);
8524     ScrollToSafeArea();
8525     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
8526 }
8527 
8528 void TextFieldPattern::FinishTextPreviewOperation()
8529 {
8530     if (!hasPreviewText_) {
8531         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "input state now is not at previewing text");
8532         return;
8533     }
8534     auto host = GetHost();
8535     CHECK_NULL_VOID(host);
8536     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8537     CHECK_NULL_VOID(layoutProperty);
8538 
8539     if (layoutProperty->HasMaxLength()) {
8540         int32_t len = static_cast<int32_t>(contentController_->GetWideText().length());
8541         showCountBorderStyle_ = len >
8542             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
8543         HandleCountStyle();
8544     }
8545 
8546     auto oldValue = contentController_->GetTextValue();
8547     auto originCaretIndex =
8548             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
8549     ChangeValueInfo changeValueInfo;
8550     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
8551     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
8552     changeValueInfo.oldContent = GetBodyTextValue();
8553     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
8554     auto start = GetPreviewTextStart();
8555     auto end = GetPreviewTextEnd();
8556     auto previewValue = GetPreviewTextValue();
8557     hasPreviewText_ = false;
8558 
8559     auto originLength = static_cast<int32_t>(contentController_->GetWideText().length()) - (end - start);
8560     contentController_->ReplaceSelectedValue(start, end, previewValue);
8561     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetWideText().length()) - originLength);
8562     selectController_->UpdateCaretIndex(start + caretMoveLength);
8563     UpdateEditingValueToRecord();
8564     changeValueInfo.rangeAfter =
8565         TextRange { changeValueInfo.oldPreviewText.offset, start + caretMoveLength };
8566     changeValueInfo.value = GetBodyTextValue();
8567     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
8568     changeValueInfo.previewText.value = GetPreviewTextValue();
8569     bool isWillChange = FireOnWillChange(changeValueInfo);
8570     if (!isWillChange) {
8571         RecoverTextValueAndCaret(oldValue, originCaretIndex);
8572         return;
8573     }
8574     if (HasFocus()) {
8575         cursorVisible_ = true;
8576         StartTwinkling();
8577     } else {
8578         cursorVisible_ = false;
8579         StopTwinkling();
8580     }
8581 
8582     bodyTextInPreivewing_ = "";
8583     previewTextStart_ = PREVIEW_TEXT_RANGE_DEFAULT;
8584     previewTextEnd_ = PREVIEW_TEXT_RANGE_DEFAULT;
8585 
8586     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
8587 }
8588 
8589 std::vector<RectF> TextFieldPattern::GetPreviewTextRects() const
8590 {
8591     if (!GetIsPreviewText()) {
8592         return {};
8593     }
8594     std::vector<RectF> boxes;
8595     std::vector<RectF> previewTextRects;
8596     CHECK_NULL_RETURN(paragraph_, boxes);
8597     paragraph_->GetRectsForRange(GetPreviewTextStart(), GetPreviewTextEnd(), boxes);
8598     if (boxes.empty()) {
8599         return {};
8600     }
8601     RectF linerRect(boxes.front().GetOffset(), SizeF(0, boxes.front().GetSize().Height()));
8602     float checkedTop = boxes.front().Top();
8603 
8604     for (const auto& drawRect : boxes) {
8605         if (drawRect.Top() == checkedTop) {
8606             linerRect += SizeF(drawRect.GetSize().Width(), 0);
8607         } else {
8608             previewTextRects.emplace_back(linerRect);
8609             checkedTop = drawRect.Top();
8610             linerRect = drawRect;
8611         }
8612     }
8613     previewTextRects.emplace_back(linerRect);
8614     return previewTextRects;
8615 }
8616 
8617 bool TextFieldPattern::NeedDrawPreviewText()
8618 {
8619     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8620     CHECK_NULL_RETURN(paintProperty, false);
8621 
8622     auto caretInfo = selectController_->GetCaretInfo();
8623     if (!paintProperty->HasPreviewTextStart() || !paintProperty->HasPreviewTextEnd()) {
8624         paintProperty->UpdatePreviewTextStart(caretInfo.index);
8625         paintProperty->UpdatePreviewTextEnd(caretInfo.index);
8626     }
8627 
8628     auto paintStart = paintProperty->GetPreviewTextStart();
8629     auto paintEnd =paintProperty->GetPreviewTextEnd();
8630     if (!GetIsPreviewText()) {
8631         if (!paintStart.has_value() || !paintEnd.has_value()) {
8632             paintProperty->UpdatePreviewTextStart(caretInfo.index);
8633             paintProperty->UpdatePreviewTextEnd(caretInfo.index);
8634             return false;
8635         }
8636 
8637         // end paint
8638         if (paintStart != paintEnd || paintStart.value() != caretInfo.index) {
8639             paintProperty->UpdatePreviewTextStart(caretInfo.index);
8640             paintProperty->UpdatePreviewTextEnd(caretInfo.index);
8641             return true;
8642         }
8643         return false;
8644     }
8645     auto needDraw = paintStart.value() != GetPreviewTextStart() ||
8646                      paintEnd.value() != GetPreviewTextEnd();
8647     paintProperty->UpdatePreviewTextStart(GetPreviewTextStart());
8648     paintProperty->UpdatePreviewTextEnd(GetPreviewTextEnd());
8649     return needDraw;
8650 }
8651 
8652 int32_t TextFieldPattern::CheckPreviewTextValidate(const std::string& previewValue, const PreviewRange range)
8653 {
8654     auto start = range.start;
8655     auto end = range.end;
8656     if (start != end && (start == PREVIEW_TEXT_RANGE_DEFAULT || end == PREVIEW_TEXT_RANGE_DEFAULT)) {
8657         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "range is not [-1,-1] or legal range");
8658         return PREVIEW_BAD_PARAMETERS;
8659     }
8660 
8661     if (start != PREVIEW_TEXT_RANGE_DEFAULT && IsSelected()) {
8662         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "unsupported insert preview text when IsSelected");
8663         return PREVIEW_BAD_PARAMETERS;
8664     }
8665     return PREVIEW_NO_ERROR;
8666 }
8667 
8668 PreviewTextStyle TextFieldPattern::GetPreviewTextStyle() const
8669 {
8670     auto defaultStyle = PreviewTextStyle::NORMAL;
8671     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8672     CHECK_NULL_RETURN(paintProperty, defaultStyle);
8673     if (paintProperty->HasPreviewTextStyle()) {
8674         auto style = paintProperty->GetPreviewTextStyle();
8675         if (style.value() == PREVIEW_STYLE_NORMAL) {
8676             return PreviewTextStyle::NORMAL;
8677         } else if (style.value() == PREVIEW_STYLE_UNDERLINE) {
8678             return PreviewTextStyle::UNDERLINE;
8679         }
8680     }
8681     return defaultStyle;
8682 }
8683 
8684 void TextFieldPattern::ReceivePreviewTextStyle(const std::string& style)
8685 {
8686     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8687     CHECK_NULL_VOID(paintProperty);
8688     if (!style.empty()) {
8689         paintProperty->UpdatePreviewTextStyle(style);
8690     }
8691 }
8692 
8693 void TextFieldPattern::CalculatePreviewingTextMovingLimit(const Offset& touchOffset, double& limitL, double& limitR)
8694 {
8695     float offsetX = IsTextArea() ? contentRect_.GetX() : GetTextRect().GetX();
8696     float offsetY = IsTextArea() ? GetTextRect().GetY() : contentRect_.GetY();
8697     std::vector<RectF> previewTextRects = GetPreviewTextRects();
8698     if (GreatNotEqual(touchOffset.GetY(), previewTextRects.back().Bottom() + offsetY)) {
8699         limitL = previewTextRects.back().Left() + offsetX + MINIMAL_OFFSET;
8700         limitR = previewTextRects.back().Right() + offsetX - MINIMAL_OFFSET;
8701     } else if (LessNotEqual(touchOffset.GetY(), previewTextRects.front().Top() + offsetY)) {
8702         limitL = previewTextRects.front().Left() + offsetX + MINIMAL_OFFSET;
8703         limitR = previewTextRects.front().Right() + offsetX - MINIMAL_OFFSET;
8704     } else {
8705         for (const auto& drawRect : previewTextRects) {
8706             if (GreatOrEqual(touchOffset.GetY(), drawRect.Top() + offsetY)
8707                 && LessOrEqual(touchOffset.GetY(), drawRect.Bottom() + offsetY)) {
8708                 limitL = drawRect.Left() + offsetX + MINIMAL_OFFSET;
8709                 limitR = drawRect.Right() + offsetX - MINIMAL_OFFSET;
8710                 break;
8711             }
8712         }
8713     }
8714 }
8715 
8716 void TextFieldPattern::SetShowKeyBoardOnFocus(bool value)
8717 {
8718     if (showKeyBoardOnFocus_ == value) {
8719         return;
8720     }
8721     showKeyBoardOnFocus_ = value;
8722 
8723     if (!HasFocus()) {
8724         return;
8725     }
8726 
8727     if (value) {
8728         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SHOW_KEYBOARD_ON_FOCUS);
8729     } else {
8730         CloseKeyboard(true, false);
8731     }
8732 }
8733 
8734 void TextFieldPattern::ResetPreviewTextState()
8735 {
8736     if (!GetIsPreviewText()) {
8737         return;
8738     }
8739 #if defined(ENABLE_STANDARD_INPUT)
8740     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
8741         StringUtils::Str8ToStr16(""), 0, 0);
8742     UpdateCaretInfoToController(true);
8743 #endif
8744     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield onDragEnter when has previewText");
8745     FinishTextPreview();
8746 }
8747 
8748 void TextFieldPattern::OnCaretMoveDone(const TouchEventInfo& info)
8749 {
8750     if (isMoveCaretAnywhere_) {
8751         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "isMoveCaretAnywhere_=1, so restore caret");
8752         selectController_->UpdateCaretInfoByOffset(info.GetTouches().front().GetLocalLocation());
8753         StartTwinkling();
8754     }
8755 }
8756 
8757 void TextFieldPattern::OnSelectionMenuOptionsUpdate(
8758     const NG::OnCreateMenuCallback&& onCreateMenuCallback, const NG::OnMenuItemClickCallback&& onMenuItemClick)
8759 {
8760     selectOverlay_->OnSelectionMenuOptionsUpdate(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
8761 }
8762 
8763 bool TextFieldPattern::GetTouchInnerPreviewText(const Offset& offset) const
8764 {
8765     auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset);
8766     return GetPreviewTextStart() <= touchDownIndex && touchDownIndex <= GetPreviewTextEnd() && HasFocus();
8767 }
8768 
8769 bool TextFieldPattern::IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const
8770 {
8771     if (touchEvent.sourceTool != SourceTool::PEN || touchEvent.type != TouchType::DOWN) {
8772         return false;
8773     }
8774     auto host = GetHost();
8775     CHECK_NULL_RETURN(host, false);
8776     auto focusHub = host->GetFocusHub();
8777     CHECK_NULL_RETURN(focusHub, false);
8778     if (!focusHub->IsFocusable() || !host->IsVisible()) {
8779         return false;
8780     }
8781     auto renderContext = host->GetRenderContext();
8782     CHECK_NULL_RETURN(renderContext, false);
8783     auto opacity = renderContext->GetOpacity();
8784     // if opacity is 0.0f, no need to hit frameNode.
8785     if (NearZero(opacity.value_or(1.0f))) {
8786         return false;
8787     }
8788     return !IsInPasswordMode();
8789 }
8790 
8791 RectF TextFieldPattern::ExpandDefaultResponseRegion(RectF& rect)
8792 {
8793     return rect + NG::SizeF(0, OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx() * OHOS::Ace::HOT_AREA_EXPAND_TIME) +
8794            NG::OffsetF(0, -OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx());
8795 }
8796 
8797 bool TextFieldPattern::IsContentRectNonPositive()
8798 {
8799     return NonPositive(contentRect_.Width());
8800 }
8801 
8802 int32_t TextFieldPattern::GetTouchIndex(const OffsetF& offset)
8803 {
8804     return selectOverlay_->GetCaretPositionOnHandleMove(offset, true);
8805 }
8806 
8807 void TextFieldPattern::OnTextGestureSelectionUpdate(int32_t start, int32_t end, const TouchEventInfo& info)
8808 {
8809     auto localOffset = info.GetTouches().front().GetLocalLocation();
8810     if (start != selectController_->GetStartIndex()) {
8811         StartVibratorByIndexChange(start, selectController_->GetStartIndex());
8812     } else if (end != selectController_->GetEndIndex()) {
8813         StartVibratorByIndexChange(end, selectController_->GetEndIndex());
8814     }
8815     if (magnifierController_ && (longPressFingerNum_ == 1)) {
8816         magnifierController_->SetLocalOffset({ localOffset.GetX(), localOffset.GetY() });
8817     }
8818     auto firstIndex = selectController_->GetFirstHandleIndex();
8819     auto secondIndex = selectController_->GetSecondHandleIndex();
8820     bool changed = false;
8821     if (start != firstIndex) {
8822         selectController_->MoveFirstHandleToContentRect(start, false);
8823         changed = true;
8824     }
8825     if (secondIndex != end) {
8826         selectController_->MoveSecondHandleToContentRect(end, false);
8827         changed = true;
8828     }
8829     if (!changed) {
8830         return;
8831     }
8832     auto host = GetHost();
8833     CHECK_NULL_VOID(host);
8834     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8835 }
8836 
8837 void TextFieldPattern::OnTextGenstureSelectionEnd()
8838 {
8839     SetIsSingleHandle(!IsSelected());
8840     if (!IsContentRectNonPositive()) {
8841         ProcessOverlay({ .animation = true });
8842     }
8843 }
8844 
8845 void TextFieldPattern::ReportEvent()
8846 {
8847 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
8848     if (UiSessionManager::GetInstance().GetSearchEventRegistered()) {
8849         auto host = GetHost();
8850         CHECK_NULL_VOID(host);
8851         auto data = JsonUtil::Create();
8852         data->Put("event", "onTextSearch");
8853         data->Put("id", host->GetId());
8854         data->Put("$type", host->GetTag().data());
8855         data->Put("inputType", static_cast<int16_t>(GetKeyboard()));
8856         data->Put("text", GetTextValue().data());
8857         data->Put("position", host->GetGeometryNode()->GetFrameRect().ToString().data());
8858         // report all use textfield component unfocus event,more than just the search box
8859         UiSessionManager::GetInstance().ReportSearchEvent(data->ToString());
8860     }
8861 #endif
8862 }
8863 
8864 bool TextFieldPattern::IsTextEditableForStylus() const
8865 {
8866     auto host = GetHost();
8867     CHECK_NULL_RETURN(host, false);
8868     auto focusHub = host->GetFocusHub();
8869     CHECK_NULL_RETURN(focusHub, false);
8870     if (!focusHub->IsFocusable() || !host->IsVisible()) {
8871         return false;
8872     }
8873     auto renderContext = host->GetRenderContext();
8874     CHECK_NULL_RETURN(renderContext, false);
8875     auto opacity = renderContext->GetOpacity();
8876     // if opacity is 0.0f, no need to hit frameNode.
8877     if (NearZero(opacity.value_or(1.0f))) {
8878         return false;
8879     }
8880     return !IsInPasswordMode();
8881 }
8882 
8883 void TextFieldPattern::OnAttachToMainTree()
8884 {
8885     isDetachFromMainTree_ = false;
8886     auto host = GetHost();
8887     CHECK_NULL_VOID(host);
8888     auto autoFillContainerNode = host->GetFirstAutoFillContainerNode();
8889     CHECK_NULL_VOID(autoFillContainerNode);
8890     firstAutoFillContainerNode_ = WeakClaim(RawPtr(autoFillContainerNode));
8891     AddTextFieldInfo();
8892 }
8893 
8894 void TextFieldPattern::OnDetachFromMainTree()
8895 {
8896     isDetachFromMainTree_ = true;
8897     RemoveTextFieldInfo();
8898 }
8899 
8900 TextFieldInfo TextFieldPattern::GenerateTextFieldInfo()
8901 {
8902     TextFieldInfo textFieldInfo;
8903     auto host = GetHost();
8904     CHECK_NULL_RETURN(host, textFieldInfo);
8905     textFieldInfo.nodeId = host->GetId();
8906     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
8907     CHECK_NULL_RETURN(autoFillContainerNode, textFieldInfo);
8908     textFieldInfo.autoFillContainerNodeId = autoFillContainerNode->GetId();
8909     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8910     CHECK_NULL_RETURN(layoutProperty, textFieldInfo);
8911     textFieldInfo.enableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
8912     textFieldInfo.inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
8913     textFieldInfo.contentType = layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED);
8914     return textFieldInfo;
8915 }
8916 
8917 void TextFieldPattern::AddTextFieldInfo()
8918 {
8919     CHECK_NULL_VOID(IsNeedProcessAutoFill());
8920     auto pipeline = PipelineContext::GetCurrentContextSafely();
8921     CHECK_NULL_VOID(pipeline);
8922     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8923     CHECK_NULL_VOID(textFieldManager);
8924     auto textFieldInfo = GenerateTextFieldInfo();
8925     textFieldManager->AddTextFieldInfo(textFieldInfo);
8926 }
8927 
8928 void TextFieldPattern::RemoveTextFieldInfo()
8929 {
8930     CHECK_NULL_VOID(IsNeedProcessAutoFill());
8931     auto pipeline = PipelineContext::GetCurrentContextSafely();
8932     CHECK_NULL_VOID(pipeline);
8933     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8934     CHECK_NULL_VOID(textFieldManager);
8935     auto host = GetHost();
8936     CHECK_NULL_VOID(host);
8937     auto nodeId = host->GetId();
8938     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
8939     CHECK_NULL_VOID(autoFillContainerNode);
8940     auto autoFillContainerNodeId = autoFillContainerNode->GetId();
8941     textFieldManager->RemoveTextFieldInfo(autoFillContainerNodeId, nodeId);
8942 }
8943 
8944 void TextFieldPattern::UpdateTextFieldInfo()
8945 {
8946     CHECK_NULL_VOID(IsNeedProcessAutoFill());
8947     auto pipeline = PipelineContext::GetCurrentContextSafely();
8948     CHECK_NULL_VOID(pipeline);
8949     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8950     CHECK_NULL_VOID(textFieldManager);
8951     auto textFieldInfo = GenerateTextFieldInfo();
8952     textFieldManager->UpdateTextFieldInfo(textFieldInfo);
8953 }
8954 
8955 bool TextFieldPattern::IsAutoFillUserName(const AceAutoFillType& autoFillType)
8956 {
8957     auto isUserName =
8958         autoFillType == AceAutoFillType::ACE_USER_NAME || autoFillType == AceAutoFillType::ACE_UNSPECIFIED;
8959     return isUserName && HasAutoFillPasswordNode();
8960 }
8961 
8962 bool TextFieldPattern::HasAutoFillPasswordNode()
8963 {
8964     auto pipeline = PipelineContext::GetCurrentContextSafely();
8965     CHECK_NULL_RETURN(pipeline, false);
8966     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8967     CHECK_NULL_RETURN(textFieldManager, false);
8968     auto host = GetHost();
8969     CHECK_NULL_RETURN(host, false);
8970     auto nodeId = host->GetId();
8971     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
8972     CHECK_NULL_RETURN(autoFillContainerNode, false);
8973     auto autoFillContainerNodeId = autoFillContainerNode->GetId();
8974     return textFieldManager->HasAutoFillPasswordNodeInContainer(autoFillContainerNodeId, nodeId);
8975 }
8976 
8977 bool TextFieldPattern::IsTriggerAutoFillPassword()
8978 {
8979     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8980     CHECK_NULL_RETURN(layoutProperty, false);
8981     auto aceContentType =
8982         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
8983     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
8984         if (!IsAutoFillPasswordType(aceContentType)) {
8985             return false;
8986         } else {
8987             if (aceContentType == AceAutoFillType::ACE_PASSWORD ||
8988                 aceContentType == AceAutoFillType::ACE_NEW_PASSWORD) {
8989                 return true;
8990             }
8991             return HasAutoFillPasswordNode();
8992         }
8993     }
8994 
8995     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
8996     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
8997         if (aceInputType == AceAutoFillType::ACE_PASSWORD || aceInputType == AceAutoFillType::ACE_NEW_PASSWORD) {
8998             return true;
8999         }
9000     }
9001     return HasAutoFillPasswordNode();
9002 }
9003 
9004 bool TextFieldPattern::IsNeedProcessAutoFill()
9005 {
9006     return true;
9007 }
9008 
9009 PositionWithAffinity TextFieldPattern::GetGlyphPositionAtCoordinate(int32_t x, int32_t y)
9010 {
9011     PositionWithAffinity finalResult(0, TextAffinity::UPSTREAM);
9012     CHECK_NULL_RETURN(paragraph_, finalResult);
9013     Offset offset(x, y);
9014     return paragraph_->GetGlyphPositionAtCoordinate(ConvertTouchOffsetToTextOffset(offset));
9015 }
9016 
9017 Offset TextFieldPattern::ConvertTouchOffsetToTextOffset(const Offset& touchOffset)
9018 {
9019     return touchOffset - Offset(textRect_.GetX(), textRect_.GetY());
9020 }
9021 
9022 bool TextFieldPattern::InsertOrDeleteSpace(int32_t index)
9023 {
9024     // delete or insert space.
9025     auto wtext = GetWideText();
9026     if (index >= 0 && index < static_cast<int32_t>(wtext.length())) {
9027         auto ret = SetCaretOffset(index);
9028         if (!ret) {
9029             return false;
9030         }
9031         if (wtext[index] == L' ') {
9032             DeleteForward(1);
9033         } else if (index > 0 && wtext[index - 1] == L' ') {
9034             DeleteBackward(1);
9035         } else {
9036             InsertValue(" ", true);
9037         }
9038         return true;
9039     }
9040     return false;
9041 }
9042 
9043 void TextFieldPattern::DeleteRange(int32_t start, int32_t end, bool isIME)
9044 {
9045     auto length = static_cast<int32_t>(contentController_->GetWideText().length());
9046     if (start > end) {
9047         std::swap(start, end);
9048     }
9049     start = std::max(0, start);
9050     end = std::min(length, end);
9051     if (start > length || end < 0 || start == end) {
9052         return;
9053     }
9054     GetEmojiSubStringRange(start, end);
9055     auto value = contentController_->GetSelectedValue(start, end);
9056     auto originCaretIndex =
9057         TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
9058     if (isIME) {
9059         auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::FORWARD, start);
9060         CHECK_NULL_VOID(isDelete);
9061     }
9062     ResetObscureTickCountDown();
9063     CheckAndUpdateRecordBeforeOperation();
9064     auto oldContent = contentController_->GetTextValue();
9065     Delete(start, end);
9066     auto isOnWillChange = OnWillChangePreDelete(oldContent, start, end);
9067     if (!isOnWillChange) {
9068         RecoverTextValueAndCaret(oldContent, originCaretIndex);
9069         return;
9070     }
9071     if (isIME) {
9072         AfterIMEDeleteValue(value, TextDeleteDirection::FORWARD);
9073     }
9074     showCountBorderStyle_ = false;
9075     HandleCountStyle();
9076 }
9077 
9078 bool TextFieldPattern::IsShowAIWrite()
9079 {
9080     auto container = Container::Current();
9081     if (container && container->IsScenceBoardWindow()) {
9082         return false;
9083     }
9084 
9085     auto host = GetHost();
9086     CHECK_NULL_RETURN(host, false);
9087     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9088     CHECK_NULL_RETURN(layoutProperty, false);
9089     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) == CopyOptions::None) {
9090         return false;
9091     }
9092     auto textFieldTheme = GetTheme();
9093     CHECK_NULL_RETURN(textFieldTheme, false);
9094     auto bundleName = textFieldTheme->GetAIWriteBundleName();
9095     auto abilityName = textFieldTheme->GetAIWriteAbilityName();
9096     if (bundleName.empty() || abilityName.empty()) {
9097         return false;
9098     }
9099     aiWriteAdapter_->SetBundleName(bundleName);
9100     aiWriteAdapter_->SetAbilityName(abilityName);
9101     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
9102         "BundleName: %{public}s, abilityName: %{public}s", bundleName.c_str(), abilityName.c_str());
9103 
9104     auto isAISupport = false;
9105     if (textFieldTheme->GetAIWriteIsSupport() == "true") {
9106         isAISupport = true;
9107     }
9108     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "isAISupport: %{public}d", isAISupport);
9109     return IsUnspecifiedOrTextType() && isAISupport;
9110 }
9111 
9112 void TextFieldPattern::GetAIWriteInfo(AIWriteInfo& info)
9113 {
9114     // serialize the selected text
9115     info.selectStart = selectController_->GetStartIndex();
9116     info.selectEnd = selectController_->GetEndIndex();
9117     auto selectContent = contentController_->GetSelectedValue(info.selectStart, info.selectEnd);
9118     RefPtr<SpanString> spanString = AceType::MakeRefPtr<SpanString>(selectContent);
9119     spanString->EncodeTlv(info.selectBuffer);
9120     info.selectLength = static_cast<int32_t>(aiWriteAdapter_->GetSelectLengthOnlyText(spanString->GetWideString()));
9121     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "Selected range=[%{public}d--%{public}d], content = %{private}s",
9122         info.selectStart, info.selectEnd, spanString->GetString().c_str());
9123 
9124     // serialize the sentenced-level text
9125     auto textSize = static_cast<int32_t>(contentController_->GetWideText().length());
9126     auto contentAll = contentController_->GetWideText();
9127     auto sentenceStart = 0;
9128     auto sentenceEnd = textSize;
9129     for (int32_t i = info.selectStart; i >= 0; --i) {
9130         if (aiWriteAdapter_->IsSentenceBoundary(contentAll[i])) {
9131             sentenceStart = i + 1;
9132             break;
9133         }
9134     }
9135     for (int32_t i = info.selectEnd; i < textSize; i++) {
9136         if (aiWriteAdapter_->IsSentenceBoundary(contentAll[i])) {
9137             sentenceEnd = i;
9138             break;
9139         }
9140     }
9141     info.start = info.selectStart - sentenceStart;
9142     info.end = info.selectEnd - sentenceStart;
9143     auto sentenceContent = contentController_->GetSelectedValue(sentenceStart, sentenceEnd);
9144     spanString = AceType::MakeRefPtr<SpanString>(sentenceContent);
9145     spanString->EncodeTlv(info.sentenceBuffer);
9146     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "Sentence range=[%{public}d--%{public}d], content = %{private}s",
9147         sentenceStart, sentenceEnd, spanString->GetString().c_str());
9148 
9149     auto host = GetHost();
9150     CHECK_NULL_VOID(host);
9151     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9152     CHECK_NULL_VOID(layoutProperty);
9153     info.maxLength = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
9154     info.firstHandle = selectController_->GetFirstHandleRect().ToString();
9155     info.secondHandle = selectController_->GetSecondHandleRect().ToString();
9156     info.componentType = host->GetTag();
9157 }
9158 
9159 void TextFieldPattern::HandleOnAIWrite()
9160 {
9161     AIWriteInfo info;
9162     GetAIWriteInfo(info);
9163     CloseSelectOverlay();
9164     CloseKeyboard(true);
9165 
9166     auto callback = [weak = WeakClaim(this), info](std::vector<uint8_t>& buffer) {
9167         auto pattern = weak.Upgrade();
9168         CHECK_NULL_VOID(pattern);
9169         pattern->HandleAIWriteResult(info.selectStart, info.selectEnd, buffer);
9170         auto aiWriteAdapter = pattern->aiWriteAdapter_;
9171         CHECK_NULL_VOID(aiWriteAdapter);
9172         aiWriteAdapter->CloseModalUIExtension();
9173     };
9174     auto pipeline = PipelineContext::GetCurrentContext();
9175     CHECK_NULL_VOID(pipeline);
9176     aiWriteAdapter_->SetPipelineContext(pipeline);
9177     aiWriteAdapter_->ShowModalUIExtension(info, callback);
9178 }
9179 
9180 void TextFieldPattern::HandleAIWriteResult(int32_t start, int32_t end, std::vector<uint8_t>& buffer)
9181 {
9182     RefPtr<SpanString> spanString = SpanString::DecodeTlv(buffer);
9183     auto resultText = spanString->GetString();
9184     TAG_LOGD(AceLogTag::ACE_RICH_TEXT, "Backfilling results range=[%{public}d--%{public}d], content = %{private}s",
9185         start, end, spanString->GetString().c_str());
9186     if (spanString->GetSpanItems().empty()) {
9187         return;
9188     }
9189 
9190     auto host = GetHost();
9191     CHECK_NULL_VOID(host);
9192     auto value = contentController_->GetSelectedValue(start, end);
9193     InputCommandInfo inputCommandInfo;
9194     inputCommandInfo.deleteRange = { start, end };
9195     inputCommandInfo.insertOffset = start;
9196     inputCommandInfo.insertValue = resultText;
9197     inputCommandInfo.reason = InputReason::AI_WRITE;
9198     AddInputCommand(inputCommandInfo);
9199 }
9200 
9201 std::optional<TouchLocationInfo> TextFieldPattern::GetAcceptedTouchLocationInfo(const TouchEventInfo& info)
9202 {
9203     auto touchInfos = info.GetChangedTouches();
9204     if (touchInfos.empty()) {
9205         return std::nullopt;
9206     }
9207     if (!moveCaretState_.isMoveCaret) {
9208         return touchInfos.front();
9209     }
9210     for (auto touchInfo : touchInfos) {
9211         if (touchInfo.GetFingerId() == moveCaretState_.touchFingerId) {
9212             return touchInfo;
9213         }
9214     }
9215     return std::nullopt;
9216 }
9217 
9218 void TextFieldPattern::DoTextSelectionTouchCancel()
9219 {
9220     CHECK_NULL_VOID(magnifierController_);
9221     magnifierController_->RemoveMagnifierFrameNode();
9222     selectController_->UpdateCaretIndex(selectController_->GetCaretIndex());
9223 }
9224 
9225 void TextFieldPattern::ScrollPage(bool reverse, bool smooth, AccessibilityScrollType scrollType)
9226 {
9227     auto border = GetBorderWidthProperty();
9228     float maxFrameHeight =
9229         frameRect_.Height() - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
9230     float distance = reverse ? maxFrameHeight : -maxFrameHeight;
9231     OnScrollCallback(distance, SCROLL_FROM_JUMP);
9232 }
9233 
9234 float TextFieldPattern::GetVerticalPaddingAndBorderSum() const
9235 {
9236     auto border = GetBorderWidthProperty();
9237     if (utilPadding_.has_value()) {
9238         return utilPadding_.value().top.value_or(0.0f) + utilPadding_.value().bottom.value_or(0.0f) +
9239                GetBorderTop(border) + GetBorderBottom(border);
9240     }
9241     auto textFieldTheme = GetTheme();
9242     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
9243     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
9244     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9245     CHECK_NULL_RETURN(layoutProperty, themePadding.Top().ConvertToPx() + themePadding.Bottom().ConvertToPx());
9246     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
9247     CHECK_NULL_RETURN(paddingProperty, themePadding.Top().ConvertToPx() + themePadding.Bottom().ConvertToPx());
9248 
9249     auto result = static_cast<float>(
9250         paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension().ConvertToPx() +
9251         paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension().ConvertToPx());
9252     return result + GetBorderTop(border) + GetBorderBottom(border);
9253 }
9254 
9255 float TextFieldPattern::GetHorizontalPaddingAndBorderSum() const
9256 {
9257     auto border = GetBorderWidthProperty();
9258     if (utilPadding_.has_value()) {
9259         return utilPadding_.value().left.value_or(0.0f) + utilPadding_.value().right.value_or(0.0f) +
9260                GetBorderLeft(border) + GetBorderRight(border);
9261     }
9262     auto textFieldTheme = GetTheme();
9263     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
9264     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
9265     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9266     CHECK_NULL_RETURN(layoutProperty, themePadding.Left().ConvertToPx() + themePadding.Right().ConvertToPx());
9267     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
9268     CHECK_NULL_RETURN(paddingProperty, themePadding.Left().ConvertToPx() + themePadding.Right().ConvertToPx());
9269     auto padding = static_cast<float>(
9270         paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension().ConvertToPx() +
9271         paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension().ConvertToPx());
9272     return padding + GetBorderLeft(border) + GetBorderRight(border);
9273 }
9274 
9275 float TextFieldPattern::GetPaddingTop() const
9276 {
9277     if (utilPadding_.has_value()) {
9278         return utilPadding_.value().top.value_or(0.0f);
9279     }
9280     auto textFieldTheme = GetTheme();
9281     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
9282     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
9283     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9284     CHECK_NULL_RETURN(layoutProperty, themePadding.Top().ConvertToPx());
9285     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
9286     CHECK_NULL_RETURN(paddingProperty, themePadding.Top().ConvertToPx());
9287     return static_cast<float>(
9288         paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension().ConvertToPx());
9289 }
9290 
9291 float TextFieldPattern::GetPaddingBottom() const
9292 {
9293     if (utilPadding_.has_value()) {
9294         return utilPadding_.value().bottom.value_or(0.0f);
9295     }
9296     auto textFieldTheme = GetTheme();
9297     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
9298     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
9299     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9300     CHECK_NULL_RETURN(layoutProperty, themePadding.Bottom().ConvertToPx());
9301     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
9302     CHECK_NULL_RETURN(paddingProperty, themePadding.Bottom().ConvertToPx());
9303     return static_cast<float>(
9304         paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension().ConvertToPx());
9305 }
9306 
9307 float TextFieldPattern::GetPaddingLeft() const
9308 {
9309     if (utilPadding_.has_value()) {
9310         return utilPadding_.value().left.value_or(0.0f);
9311     }
9312     auto textFieldTheme = GetTheme();
9313     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
9314     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
9315     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9316     CHECK_NULL_RETURN(layoutProperty, themePadding.Left().ConvertToPx());
9317     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
9318     CHECK_NULL_RETURN(paddingProperty, themePadding.Left().ConvertToPx());
9319     return static_cast<float>(
9320         paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension().ConvertToPx());
9321 }
9322 
9323 float TextFieldPattern::GetPaddingRight() const
9324 {
9325     if (utilPadding_.has_value()) {
9326         return utilPadding_.value().right.value_or(0.0f);
9327     }
9328     auto textFieldTheme = GetTheme();
9329     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
9330     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
9331     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9332     CHECK_NULL_RETURN(layoutProperty, themePadding.Right().ConvertToPx());
9333     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
9334     CHECK_NULL_RETURN(paddingProperty, themePadding.Right().ConvertToPx());
9335     return static_cast<float>(
9336         paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension().ConvertToPx());
9337 }
9338 
9339 BorderWidthProperty TextFieldPattern::GetBorderWidthProperty() const
9340 {
9341     BorderWidthProperty currentBorderWidth;
9342     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9343     CHECK_NULL_RETURN(layoutProperty, currentBorderWidth);
9344     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9345     CHECK_NULL_RETURN(paintProperty, currentBorderWidth);
9346     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
9347         currentBorderWidth = *(layoutProperty->GetBorderWidthProperty());
9348     } else {
9349         currentBorderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
9350     }
9351     return currentBorderWidth;
9352 }
9353 
9354 float TextFieldPattern::GetBorderLeft(BorderWidthProperty border) const
9355 {
9356     auto leftBorderWidth = border.leftDimen.value_or(Dimension(0.0f));
9357     auto percentReferenceWidth = GetPercentReferenceWidth();
9358     if (leftBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
9359         return leftBorderWidth.Value() * percentReferenceWidth;
9360     }
9361     return leftBorderWidth.ConvertToPx();
9362 }
9363 
9364 float TextFieldPattern::GetBorderTop(BorderWidthProperty border) const
9365 {
9366     auto topBorderWidth = border.topDimen.value_or(Dimension(0.0f));
9367     auto percentReferenceWidth = GetPercentReferenceWidth();
9368     if (topBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
9369         return topBorderWidth.Value() * percentReferenceWidth;
9370     }
9371     return topBorderWidth.ConvertToPx();
9372 }
9373 
9374 float TextFieldPattern::GetBorderBottom(BorderWidthProperty border) const
9375 {
9376     auto bottomBorderWidth = border.bottomDimen.value_or(Dimension(0.0f));
9377     auto percentReferenceWidth = GetPercentReferenceWidth();
9378     if (bottomBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
9379         return bottomBorderWidth.Value() * percentReferenceWidth;
9380     }
9381     return bottomBorderWidth.ConvertToPx();
9382 }
9383 
9384 float TextFieldPattern::GetBorderRight(BorderWidthProperty border) const
9385 {
9386     auto rightBorderWidth = border.rightDimen.value_or(Dimension(0.0f));
9387     auto percentReferenceWidth = GetPercentReferenceWidth();
9388     if (rightBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
9389         return rightBorderWidth.Value() * percentReferenceWidth;
9390     }
9391     return rightBorderWidth.ConvertToPx();
9392 }
9393 
9394 bool TextFieldPattern::FireOnWillChange(const ChangeValueInfo& changeValueInfo)
9395 {
9396     auto host = GetHost();
9397     CHECK_NULL_RETURN(host, true);
9398     auto eventHub = host->GetEventHub<TextFieldEventHub>();
9399     CHECK_NULL_RETURN(eventHub, true);
9400     callbackRangeBefore_ = changeValueInfo.rangeBefore;
9401     callbackRangeAfter_ = changeValueInfo.rangeAfter;
9402     callbackOldContent_ = changeValueInfo.oldContent;
9403     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
9404     return eventHub->FireOnWillChangeEvent(changeValueInfo);
9405 }
9406 
9407 bool TextFieldPattern::OnWillChangePreInsert(const std::string& insertValue, const std::string& oldContent,
9408     uint32_t start, uint32_t end)
9409 {
9410     auto host = GetHost();
9411     CHECK_NULL_RETURN(host, true);
9412     auto eventHub = host->GetEventHub<TextFieldEventHub>();
9413     CHECK_NULL_RETURN(eventHub, true);
9414     ChangeValueInfo changeValueInfo;
9415     PreviewText previewText {.offset = -1, .value = ""};
9416     if (hasPreviewText_) {
9417         previewText.offset = GetPreviewTextStart();
9418         previewText.value = GetPreviewTextValue();
9419     }
9420     changeValueInfo.oldPreviewText = previewText;
9421     changeValueInfo.previewText = previewText;
9422 
9423     auto insertLength = StringUtils::ToWstring(insertValue).length();
9424     changeValueInfo.rangeBefore = TextRange { start, end };
9425     changeValueInfo.rangeAfter = TextRange { start, start + insertLength };
9426 
9427     changeValueInfo.oldContent = oldContent;
9428     changeValueInfo.value = contentController_->GetTextValue();
9429     callbackRangeBefore_ = changeValueInfo.rangeBefore;
9430     callbackRangeAfter_ = changeValueInfo.rangeAfter;
9431     callbackOldContent_ = changeValueInfo.oldContent;
9432     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
9433     return eventHub->FireOnWillChangeEvent(changeValueInfo);
9434 }
9435 
9436 bool TextFieldPattern::OnWillChangePreDelete(const std::string& oldContent, uint32_t start, uint32_t end)
9437 {
9438     auto host = GetHost();
9439     CHECK_NULL_RETURN(host, true);
9440     auto eventHub = host->GetEventHub<TextFieldEventHub>();
9441     CHECK_NULL_RETURN(eventHub, true);
9442     ChangeValueInfo changeValueInfo;
9443     PreviewText previewText {.offset = -1, .value = ""};
9444     if (hasPreviewText_) {
9445         previewText.offset = GetPreviewTextStart();
9446         previewText.value = GetPreviewTextValue();
9447     }
9448     changeValueInfo.oldPreviewText = previewText;
9449     changeValueInfo.previewText = previewText;
9450 
9451     changeValueInfo.rangeBefore = TextRange { start, end };
9452     changeValueInfo.rangeAfter = TextRange { start, start };
9453 
9454     changeValueInfo.oldContent = oldContent;
9455     changeValueInfo.value = contentController_->GetTextValue();
9456     callbackRangeBefore_ = changeValueInfo.rangeBefore;
9457     callbackRangeAfter_ = changeValueInfo.rangeAfter;
9458     callbackOldContent_ = changeValueInfo.oldContent;
9459     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
9460     return eventHub->FireOnWillChangeEvent(changeValueInfo);
9461 }
9462 
9463 bool TextFieldPattern::OnWillChangePreSetValue(const std::string& newValue)
9464 {
9465     auto host = GetHost();
9466     CHECK_NULL_RETURN(host, true);
9467     auto eventHub = host->GetEventHub<TextFieldEventHub>();
9468     CHECK_NULL_RETURN(eventHub, true);
9469     ChangeValueInfo changeValueInfo;
9470     changeValueInfo.oldContent = contentController_->GetTextValue();
9471     changeValueInfo.value = newValue;
9472     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9473     changeValueInfo.previewText.value = GetPreviewTextValue();
9474     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9475     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
9476     changeValueInfo.rangeBefore = TextRange { 0, contentController_->GetWideText().length() };
9477     changeValueInfo.rangeAfter = TextRange { 0, StringUtils::ToWstring(newValue).length() };
9478     callbackRangeBefore_ = changeValueInfo.rangeBefore;
9479     callbackRangeAfter_ = changeValueInfo.rangeAfter;
9480     callbackOldContent_ = changeValueInfo.oldContent;
9481     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
9482     return eventHub->FireOnWillChangeEvent(changeValueInfo);
9483 }
9484 
9485 void TextFieldPattern::RecoverTextValueAndCaret(const std::string& oldValue, TextRange caretIndex)
9486 {
9487     contentController_->SetTextValueOnly(oldValue);
9488     selectController_->UpdateHandleIndex(caretIndex.start, caretIndex.end);
9489     if (IsSelected()) {
9490         ProcessOverlay({ .menuIsShow = false });
9491     }
9492 }
9493 
9494 void TextFieldPattern::AddInsertCommand(const std::string& insertValue, InputReason reason)
9495 {
9496     auto host = GetHost();
9497     CHECK_NULL_VOID(host);
9498     if (!HasFocus()) {
9499         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d on blur, can't insert value", host->GetId());
9500         return;
9501     }
9502     if (!isEdit_ || (reason == InputReason::IME && IsDragging())) {
9503         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
9504             "textfield %{public}d NOT allow input, isEdit_ = %{public}d, IsDragging = %{public}d", host->GetId(),
9505             isEdit_, IsDragging());
9506         return;
9507     }
9508     if (focusIndex_ != FocuseIndex::TEXT && insertValue == " ") {
9509         HandleSpaceEvent();
9510         return;
9511     }
9512     focusIndex_ = FocuseIndex::TEXT;
9513     if (FinishTextPreviewByPreview(insertValue)) {
9514         return;
9515     }
9516     inputOperations_.emplace(InputOperation::INSERT);
9517     InsertCommandInfo info;
9518     info.insertValue = insertValue;
9519     info.reason = reason;
9520     insertCommands_.emplace(info);
9521     CloseSelectOverlay(true);
9522     ScrollToSafeArea();
9523     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9524 }
9525 
9526 void TextFieldPattern::AddInputCommand(const InputCommandInfo& inputCommandInfo)
9527 {
9528     auto host = GetHost();
9529     CHECK_NULL_VOID(host);
9530     inputOperations_.emplace(InputOperation::INPUT);
9531     inputCommands_.emplace(inputCommandInfo);
9532     CloseSelectOverlay(true);
9533     ScrollToSafeArea();
9534     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9535 }
9536 
9537 void TextFieldPattern::ExecuteInputCommand(const InputCommandInfo& info)
9538 {
9539     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9540     CHECK_NULL_VOID(layoutProperty);
9541     auto start = info.deleteRange.start;
9542     auto end = info.deleteRange.end;
9543     auto insertValue = info.insertValue;
9544     auto caretIndex = info.insertOffset;
9545 
9546     auto originCaretIndex =
9547             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
9548     if ((info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) && !insertValue.empty()) {
9549         auto isInsert = BeforeIMEInsertValue(insertValue, caretIndex - (end - start));
9550         CHECK_NULL_VOID(isInsert);
9551     }
9552 
9553     ChangeValueInfo changeValueInfo;
9554     changeValueInfo.oldContent = contentController_->GetTextValue();
9555     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9556     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
9557     changeValueInfo.rangeBefore = TextRange { start, end };
9558 
9559     auto isDelete = true;
9560     if (start != end) {
9561         auto deleteValue = contentController_->GetSelectedValue(start, end);
9562         if (info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) {
9563             isDelete = BeforeIMEDeleteValue(deleteValue, TextDeleteDirection::BACKWARD, end);
9564         }
9565         contentController_->erase(start, end - start);
9566         selectController_->UpdateCaretIndex(start);
9567         if ((info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) && isDelete) {
9568             AfterIMEDeleteValue(deleteValue, TextDeleteDirection::BACKWARD);
9569         }
9570     }
9571 
9572     int32_t insertLength = 0;
9573     if (!insertValue.empty()) {
9574         if (info.insertOffset >= end && isDelete) {
9575             caretIndex = caretIndex - (end - start);
9576         }
9577         auto originLength = contentController_->GetWideText().length();
9578         auto hasInsertValue = contentController_->InsertValue(caretIndex, info.insertValue);
9579         insertLength = abs(static_cast<int32_t>(contentController_->GetWideText().length() - originLength));
9580         caretIndex += insertLength;
9581 
9582         if (layoutProperty->HasMaxLength()) {
9583             CalcCounterAfterFilterInsertValue(originLength, insertValue,
9584                 static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
9585         }
9586         selectController_->UpdateCaretIndex(caretIndex);
9587         UpdateObscure(insertValue, hasInsertValue);
9588         if (info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) {
9589             AfterIMEInsertValue(contentController_->GetInsertValue());
9590         }
9591     }
9592 
9593     changeValueInfo.value = contentController_->GetTextValue();
9594     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9595     changeValueInfo.previewText.value = GetPreviewTextValue();
9596     changeValueInfo.rangeAfter = TextRange { caretIndex - insertLength, caretIndex };
9597 
9598     bool isWillChange = FireOnWillChange(changeValueInfo);
9599     if (!isWillChange) {
9600         RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
9601         return;
9602     }
9603     UpdateEditingValueToRecord();
9604     TwinklingByFocus();
9605 }
9606 
9607 void TextFieldPattern::ClearTextContent()
9608 {
9609     if (GetIsPreviewText()) {
9610         PreviewTextInfo info = {
9611             .text = "",
9612             .range = {-1, -1}
9613         };
9614         SetPreviewTextOperation(info);
9615     }
9616     if (contentController_->IsEmpty()) {
9617         return;
9618     }
9619     InputCommandInfo inputCommandInfo;
9620     inputCommandInfo.deleteRange = { 0, contentController_->GetTextValue().length() };
9621     inputCommandInfo.insertOffset = 0;
9622     inputCommandInfo.insertValue = "";
9623     inputCommandInfo.reason = InputReason::CANCEL_BUTTON;
9624     AddInputCommand(inputCommandInfo);
9625 }
9626 
9627 // return: whether the offset is valid, return false if invalid
9628 bool TextFieldPattern::GetOriginCaretPosition(OffsetF& offset) const
9629 {
9630     if (!originCaretPosition_.NonNegative()) {
9631         return false;
9632     }
9633     offset = originCaretPosition_;
9634     return false;
9635 }
9636 
9637 void TextFieldPattern::ResetOriginCaretPosition()
9638 {
9639     originCaretPosition_ = DEFAULT_NEGATIVE_CARET_OFFSET;
9640 }
9641 
9642 // Record current caret position if originCaretPosition is valid
9643 // return: whether the current offset is recorded and valid
9644 bool TextFieldPattern::RecordOriginCaretPosition()
9645 {
9646     CHECK_NULL_RETURN(selectController_, false);
9647     if (originCaretPosition_.NonNegative()) {
9648         return false;
9649     }
9650     originCaretPosition_ = selectController_->GetCaretRect().GetOffset();
9651     return originCaretPosition_.NonNegative();
9652 }
9653 
9654 SelectionInfo TextFieldPattern::GetSelection()
9655 {
9656     SelectionInfo selection;
9657     selection.SetSelectionStart(selectController_->GetStartIndex());
9658     selection.SetSelectionEnd(selectController_->GetEndIndex());
9659     return selection;
9660 }
9661 } // namespace OHOS::Ace::NG
9662