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