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