• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_select_overlay.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 
21 #include "base/geometry/ng/rect_t.h"
22 #include "base/memory/ace_type.h"
23 #include "base/utils/utils.h"
24 #include "core/components_ng/manager/select_content_overlay/select_content_overlay_manager.h"
25 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
26 #include "core/components_ng/pattern/text_field/text_field_paint_property.h"
27 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
28 #include "core/event/ace_events.h"
29 #include "core/event/touch_event.h"
30 
31 #ifndef ACE_UNITTEST
32 #ifdef ENABLE_STANDARD_INPUT
33 #include "input_method_controller.h"
34 #endif
35 #endif
36 
37 namespace OHOS::Ace::NG {
38 namespace {
39 // uncertainty range when comparing selectedTextBox to contentRect
40 constexpr float BOX_EPSILON = 0.5f;
41 constexpr uint32_t REQUEST_SELECT_ALL = 1 << 1;
42 } // namespace
43 
PreProcessOverlay(const OverlayRequest & request)44 bool TextFieldSelectOverlay::PreProcessOverlay(const OverlayRequest& request)
45 {
46     auto pattern = GetPattern<TextFieldPattern>();
47     CHECK_NULL_RETURN(pattern, false);
48     auto host = pattern->GetHost();
49     CHECK_NULL_RETURN(host, false);
50     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
51     CHECK_NULL_RETURN(layoutProperty, false);
52     bool isHideRightClickMenu = layoutProperty->GetSelectionMenuHiddenValue(false) && IsUsingMouse();
53     bool isFontSizeZero = layoutProperty->HasFontSize() && NearZero(layoutProperty->GetFontSize()->Value());
54     if (isHideRightClickMenu || isFontSizeZero) {
55         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
56             "The selection menu is not displayed cause Font size is zero or selectionMenuHidden is true");
57         return false;
58     }
59     UpdatePattern(request);
60     CHECK_NULL_RETURN(!pattern->IsTransparent(), false);
61     pattern->ShowSelect();
62     SetEnableHandleLevel(true);
63     CheckEnableContainerModal();
64     return true;
65 }
66 
UpdatePattern(const OverlayRequest & request)67 void TextFieldSelectOverlay::UpdatePattern(const OverlayRequest& request)
68 {
69     auto pattern = GetPattern<TextFieldPattern>();
70     CHECK_NULL_VOID(pattern);
71     bool isRequestSelectAll = (static_cast<uint32_t>(request.requestCode) & REQUEST_SELECT_ALL) == REQUEST_SELECT_ALL;
72     auto selectController = pattern->GetTextSelectController();
73     if ((static_cast<uint32_t>(request.requestCode) & REQUEST_SELECT_ALL) != REQUEST_SELECT_ALL) {
74         selectController->CalculateHandleOffset();
75     }
76     if (pattern->IsSelected() && selectController->IsHandleSamePosition()) {
77         SetIsSingleHandle(true);
78         selectController->UpdateCaretIndex(selectController->GetFirstHandleIndex());
79         selectController->UpdateCaretOffset();
80         selectController->MoveCaretToContentRect(selectController->GetCaretIndex());
81     } else if (!IsSingleHandle() && !isRequestSelectAll) {
82         auto rects = pattern->GetTextBoxes();
83         if (!rects.empty() && NearEqual(rects.size(), 1) && NearZero(rects[0].Width())) {
84             SetIsSingleHandle(true);
85             selectController->UpdateCaretIndex(selectController->GetFirstHandleIndex());
86             selectController->UpdateCaretOffset();
87         }
88     }
89     if (IsSingleHandle()) {
90         pattern->StartTwinkling();
91     }
92 }
93 
OnAfterSelectOverlayShow(bool isCreate)94 void TextFieldSelectOverlay::OnAfterSelectOverlayShow(bool isCreate)
95 {
96     CHECK_NULL_VOID(latestReqeust_);
97     auto manager = GetManager<SelectContentOverlayManager>();
98     CHECK_NULL_VOID(manager);
99     if (latestReqeust_->hideHandle) {
100         manager->HideHandle();
101     }
102     manager->MarkInfoChange(DIRTY_SELECT_TEXT);
103     latestReqeust_.reset();
104 }
105 
OnCloseOverlay(OptionMenuType menuType,CloseReason reason,RefPtr<OverlayInfo> info)106 void TextFieldSelectOverlay::OnCloseOverlay(OptionMenuType menuType, CloseReason reason, RefPtr<OverlayInfo> info)
107 {
108     BaseTextSelectOverlay::OnCloseOverlay(menuType, reason, info);
109     auto pattern = GetPattern<TextFieldPattern>();
110     CHECK_NULL_VOID(pattern);
111     CloseMagnifier();
112     if (CloseReason::CLOSE_REASON_BACK_PRESSED == reason) {
113         OnResetTextSelection();
114         if (info && info->isSingleHandle) {
115             pattern->OnBackPressed();
116         }
117     }
118 }
119 
OnHandleGlobalTouchEvent(SourceType sourceType,TouchType touchType,bool touchInside)120 void TextFieldSelectOverlay::OnHandleGlobalTouchEvent(SourceType sourceType, TouchType touchType, bool touchInside)
121 {
122     BaseTextSelectOverlay::OnHandleGlobalTouchEvent(sourceType, touchType);
123     SetLastSourceType(sourceType);
124 }
125 
HandleOnShowMenu()126 void TextFieldSelectOverlay::HandleOnShowMenu()
127 {
128     auto selectArea = GetSelectArea();
129     if (Negative(selectArea.Width()) || Negative(selectArea.Height())) {
130         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "The selected area is not visible.");
131         return;
132     }
133     if (SelectOverlayIsOn()) {
134         auto manager = GetManager<SelectContentOverlayManager>();
135         manager->ShowOptionMenu();
136         return;
137     }
138     auto pattern = GetPattern<TextFieldPattern>();
139     CHECK_NULL_VOID(pattern);
140     SetUsingMouse(lastSourceType_ == SourceType::MOUSE);
141     if (IsUsingMouse()) {
142         auto controller = pattern->GetTextSelectController();
143         SetMouseMenuOffset(controller->GetCaretRect().GetOffset() + pattern->GetParentGlobalOffset());
144     } else {
145         auto isSingleHandle = pattern->GetTextContentController()->IsEmpty() || !pattern->IsSelected();
146         SetIsSingleHandle(isSingleHandle);
147     }
148     ProcessOverlay({ .animation = true });
149 }
150 
GetFirstHandleInfo()151 std::optional<SelectHandleInfo> TextFieldSelectOverlay::GetFirstHandleInfo()
152 {
153     if (IsSingleHandle()) {
154         return std::nullopt;
155     }
156     auto handleRect = GetFirstHandleLocalPaintRect();
157     return GetHandleInfo(handleRect);
158 }
159 
GetSecondHandleInfo()160 std::optional<SelectHandleInfo> TextFieldSelectOverlay::GetSecondHandleInfo()
161 {
162     auto handleRect = GetSecondHandleLocalPaintRect();
163     return GetHandleInfo(handleRect);
164 }
165 
GetFirstHandleLocalPaintRect()166 RectF TextFieldSelectOverlay::GetFirstHandleLocalPaintRect()
167 {
168     auto pattern = GetPattern<TextFieldPattern>();
169     CHECK_NULL_RETURN(pattern, RectF());
170     auto controller = pattern->GetTextSelectController();
171     CHECK_NULL_RETURN(controller, RectF());
172     return controller->GetFirstHandleRect();
173 }
174 
GetSecondHandleLocalPaintRect()175 RectF TextFieldSelectOverlay::GetSecondHandleLocalPaintRect()
176 {
177     auto pattern = GetPattern<TextFieldPattern>();
178     CHECK_NULL_RETURN(pattern, RectF());
179     auto controller = pattern->GetTextSelectController();
180     CHECK_NULL_RETURN(controller, RectF());
181     if (IsSingleHandle()) {
182         return controller->GetCaretRect();
183     }
184     auto handleRect = controller->GetSecondHandleRect();
185     auto contentHeight = pattern->GetTextContentRect().Height();
186     auto handleHeight = std::min(handleRect.Height(), contentHeight);
187     handleRect.SetHeight(handleHeight);
188     return handleRect;
189 }
190 
GetHandleInfo(const RectF & handlePaintRect)191 std::optional<SelectHandleInfo> TextFieldSelectOverlay::GetHandleInfo(const RectF& handlePaintRect)
192 {
193     auto handleRect = handlePaintRect;
194     SelectHandleInfo handleInfo;
195     handleInfo.localPaintRect = handlePaintRect;
196     handleRect.SetOffset(handleRect.GetOffset() + GetPaintOffsetWithoutTransform());
197     handleInfo.paintRect = handleRect;
198     handleInfo.isShow = CheckHandleVisible(handleRect);
199 
200     SetTransformPaintInfo(handleInfo, handlePaintRect);
201     return handleInfo;
202 }
203 
CheckHandleVisible(const RectF & handlePaintRect)204 bool TextFieldSelectOverlay::CheckHandleVisible(const RectF& handlePaintRect)
205 {
206     auto pattern = GetPattern<TextFieldPattern>();
207     CHECK_NULL_RETURN(pattern, false);
208     // use global offset.
209     auto contentRect = pattern->GetContentRect();
210     auto visibleRect = GetVisibleContentRect();
211     // revert to original offset.
212     auto paintRect = handlePaintRect;
213     paintRect.SetOffset(OffsetF(paintRect.GetX() + paintRect.Width() / 2.0f, paintRect.GetY()));
214     if (!pattern->IsTextArea()) {
215         auto verticalEpsilon = std::max(0.0f, paintRect.Height() - contentRect.Height());
216         return GreatOrEqual(paintRect.Top() + verticalEpsilon, visibleRect.Top()) &&
217                LessOrEqual(paintRect.Bottom() - verticalEpsilon, visibleRect.Bottom()) &&
218                LessOrEqual(paintRect.Left() - paintRect.Width() - BOX_EPSILON, visibleRect.Right()) &&
219                GreatOrEqual(paintRect.Right(), visibleRect.Left());
220     }
221     PointF bottomPoint = { paintRect.Left(), paintRect.Bottom() - BOX_EPSILON };
222     PointF topPoint = { paintRect.Left(), paintRect.Top() + BOX_EPSILON };
223     visibleRect.SetLeft(visibleRect.GetX() - BOX_EPSILON);
224     visibleRect.SetWidth(visibleRect.Width() + 2.0f * BOX_EPSILON);
225     visibleRect.SetTop(visibleRect.GetY() - BOX_EPSILON);
226     visibleRect.SetHeight(visibleRect.Height() + 2.0f * BOX_EPSILON);
227     return visibleRect.IsInRegion(bottomPoint) && visibleRect.IsInRegion(topPoint);
228 }
229 
OnResetTextSelection()230 void TextFieldSelectOverlay::OnResetTextSelection()
231 {
232     auto pattern = GetPattern<TextFieldPattern>();
233     CHECK_NULL_VOID(pattern);
234     pattern->SetCaretPosition(pattern->GetTextSelectController()->GetEndIndex());
235 }
236 
AfterCloseOverlay()237 void TextFieldSelectOverlay::AfterCloseOverlay()
238 {
239     CloseMagnifier();
240 }
241 
CloseMagnifier()242 void TextFieldSelectOverlay::CloseMagnifier()
243 {
244     auto pattern = GetPattern<TextFieldPattern>();
245     CHECK_NULL_VOID(pattern);
246     if (pattern->GetMagnifierController()->GetShowMagnifier()) {
247         pattern->GetMagnifierController()->RemoveMagnifierFrameNode();
248     }
249 }
250 
OnUpdateMenuInfo(SelectMenuInfo & menuInfo,SelectOverlayDirtyFlag dirtyFlag)251 void TextFieldSelectOverlay::OnUpdateMenuInfo(SelectMenuInfo& menuInfo, SelectOverlayDirtyFlag dirtyFlag)
252 {
253     auto pattern = GetPattern<TextFieldPattern>();
254     CHECK_NULL_VOID(pattern);
255     auto host = pattern->GetHost();
256     CHECK_NULL_VOID(host);
257     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
258     CHECK_NULL_VOID(layoutProperty);
259     auto hasText = pattern->IsOperation();
260     if ((dirtyFlag & DIRTY_COPY_ALL_ITEM) == DIRTY_COPY_ALL_ITEM) {
261         menuInfo.showCopyAll = hasText && !pattern->IsSelectAll();
262         return;
263     }
264     bool isHideSelectionMenu = layoutProperty->GetSelectionMenuHiddenValue(false);
265 #if defined(ENABLE_STANDARD_INPUT)
266     auto inputMethod = MiscServices::InputMethodController::GetInstance();
267     auto isSupportCameraInput = inputMethod &&
268                                 inputMethod->IsInputTypeSupported(MiscServices::InputType::CAMERA_INPUT) &&
269                                 !pattern->IsInPasswordMode();
270 #else
271     auto isSupportCameraInput = false;
272 #endif
273     menuInfo.showCameraInput = !pattern->IsSelected() && isSupportCameraInput && !pattern->HasCustomKeyboard();
274     if (IsUsingMouse()) {
275         auto manager = SelectContentOverlayManager::GetOverlayManager();
276         CHECK_NULL_VOID(manager);
277         menuInfo.menuIsShow = !isHideSelectionMenu || manager->IsOpen();
278     } else {
279         menuInfo.menuIsShow = (hasText || IsShowPaste() || menuInfo.showCameraInput) &&
280             !isHideSelectionMenu && IsShowMenu();
281     }
282     menuInfo.menuDisable = isHideSelectionMenu;
283     menuInfo.showPaste = IsShowPaste();
284     menuInfo.menuType = IsUsingMouse() ? OptionMenuType::MOUSE_MENU : OptionMenuType::TOUCH_MENU;
285     menuInfo.showCopy = hasText && pattern->AllowCopy() && pattern->IsSelected();
286     menuInfo.showCut = menuInfo.showCopy;
287     menuInfo.showCopyAll = hasText && !pattern->IsSelectAll();
288     menuInfo.showTranslate = menuInfo.showCopy && pattern->IsShowTranslate() && IsNeedMenuTranslate();
289     menuInfo.showAIWrite = pattern->IsShowAIWrite() && pattern->IsSelected();
290 }
291 
OnUpdateSelectOverlayInfo(SelectOverlayInfo & overlayInfo,int32_t requestCode)292 void TextFieldSelectOverlay::OnUpdateSelectOverlayInfo(SelectOverlayInfo& overlayInfo, int32_t requestCode)
293 {
294     overlayInfo.clipHandleDrawRect = IsClipHandleWithViewPort();
295     BaseTextSelectOverlay::OnUpdateSelectOverlayInfo(overlayInfo, requestCode);
296     auto textFieldPattern = GetPattern<TextFieldPattern>();
297     CHECK_NULL_VOID(textFieldPattern);
298     auto paintProperty = textFieldPattern->GetPaintProperty<TextFieldPaintProperty>();
299     CHECK_NULL_VOID(paintProperty);
300     overlayInfo.handlerColor = paintProperty->GetCursorColor();
301     OnUpdateOnCreateMenuCallback(overlayInfo);
302     auto layoutProperty =
303         DynamicCast<TextFieldLayoutProperty>(textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>());
304     CHECK_NULL_VOID(layoutProperty);
305     if (layoutProperty->HasMaxLines()) {
306         uint32_t maxLine = layoutProperty->GetMaxLinesValue(Infinity<uint32_t>());
307         if (1 == maxLine) {
308             overlayInfo.isSingleLine = true;
309         }
310     }
311 }
312 
GetSelectAreaFromRects(SelectRectsType pos)313 RectF TextFieldSelectOverlay::GetSelectAreaFromRects(SelectRectsType pos)
314 {
315     auto pattern = GetPattern<TextFieldPattern>();
316     CHECK_NULL_RETURN(pattern, {});
317     auto host = pattern->GetHost();
318     CHECK_NULL_RETURN(host, {});
319     auto selectRects = pattern->GetTextBoxes();
320     RectF res(pattern->GetCaretRect());
321     auto textPaintOffset = host->GetTransformRelativeOffset();
322     if (selectRects.empty()) {
323         res.SetOffset(res.GetOffset() + textPaintOffset);
324     } else {
325         auto contentRect = pattern->GetContentRect();
326         auto textRect = pattern->GetTextRect();
327         if (pos == SelectRectsType::LEFT_TOP_POINT) {
328             selectRects.erase(std::next(selectRects.begin()), selectRects.end());
329             selectRects.front().SetSize({0, 0});
330         } else if (pos == SelectRectsType::RIGHT_BOTTOM_POINT) {
331             selectRects.erase(selectRects.begin(), std::prev(selectRects.end()));
332             selectRects.front().SetRect({selectRects.front().Right(), selectRects.front().Bottom()}, {0, 0});
333         }
334         res = MergeSelectedBoxes(selectRects, contentRect, textRect, textPaintOffset);
335     }
336     auto globalContentRect = GetVisibleContentRect();
337     auto intersectRect = res.IntersectRectT(globalContentRect);
338     if (hasTransform_) {
339         intersectRect.SetOffset(intersectRect.GetOffset() - textPaintOffset);
340         GetGlobalRectWithTransform(intersectRect);
341     }
342     ApplySelectAreaWithKeyboard(intersectRect);
343     return intersectRect;
344 }
345 
GetSelectedText()346 std::string TextFieldSelectOverlay::GetSelectedText()
347 {
348     auto pattern = GetPattern<TextFieldPattern>();
349     CHECK_NULL_RETURN(pattern, "");
350     auto start = pattern->GetTextSelectController()->GetStartIndex();
351     auto end = pattern->GetTextSelectController()->GetEndIndex();
352     return pattern->GetTextContentController()->GetSelectedValue(start, end);
353 }
354 
OnMenuItemAction(OptionMenuActionId id,OptionMenuType type)355 void TextFieldSelectOverlay::OnMenuItemAction(OptionMenuActionId id, OptionMenuType type)
356 {
357     auto pattern = GetPattern<TextFieldPattern>();
358     CHECK_NULL_VOID(pattern);
359     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Handle overlay menu, men id %{public}d, menu type %{public}d", id, type);
360     switch (id) {
361         case OptionMenuActionId::COPY:
362             pattern->HandleOnCopy();
363             return;
364         case OptionMenuActionId::CUT:
365             pattern->HandleOnCut();
366             return;
367         case OptionMenuActionId::SELECT_ALL:
368             pattern->HandleOnSelectAll(type == OptionMenuType::MOUSE_MENU, false, true);
369             return;
370         case OptionMenuActionId::PASTE:
371             pattern->HandleOnPaste();
372             return;
373         case OptionMenuActionId::TRANSLATE:
374             HandleOnTranslate();
375             return;
376         case OptionMenuActionId::CAMERA_INPUT:
377             pattern->HandleOnCameraInput();
378             return;
379         case OptionMenuActionId::AI_WRITE:
380             pattern->HandleOnAIWrite();
381             return;
382         default:
383             return;
384     }
385 }
386 
GetTextAreaCaretPosition(const OffsetF & localOffset)387 int32_t TextFieldSelectOverlay::GetTextAreaCaretPosition(const OffsetF& localOffset)
388 {
389     auto pattern = GetPattern<TextFieldPattern>();
390     auto contentRect = pattern->GetContentRect();
391     auto paddingLeft = pattern->GetPaddingLeft();
392     auto textRect = pattern->GetTextRect();
393     auto lineHeight = pattern->PreferredLineHeight();
394     Offset offset;
395     if (LessNotEqual(localOffset.GetY(), contentRect.GetY())) {
396         offset = Offset(localOffset.GetX() - paddingLeft, localOffset.GetY() - textRect.GetY() - lineHeight);
397     } else if (GreatOrEqual(localOffset.GetY(), contentRect.GetY() + contentRect.Height())) {
398         offset = Offset(localOffset.GetX() - paddingLeft, localOffset.GetY() - textRect.GetY() + lineHeight);
399     } else {
400         offset = Offset(localOffset.GetX() - paddingLeft, localOffset.GetY() - textRect.GetY());
401     }
402     return pattern->ConvertTouchOffsetToCaretPosition(offset);
403 }
404 
GetTextInputCaretPosition(const OffsetF & localOffset,bool isFirst)405 int32_t TextFieldSelectOverlay::GetTextInputCaretPosition(const OffsetF& localOffset, bool isFirst)
406 {
407     auto pattern = GetPattern<TextFieldPattern>();
408     auto contentRect = pattern->GetContentRect();
409     auto selectController = pattern->GetTextSelectController();
410     auto wideText = pattern->GetWideText();
411     if (LessNotEqual(localOffset.GetX(), contentRect.GetX())) {
412         auto index = selectController->GetStartIndex();
413         if ((!isFirst && !IsHandleReverse()) || (isFirst && IsHandleReverse())) {
414             index = selectController->GetEndIndex();
415         }
416         auto len = pattern->GetGraphemeClusterLength(wideText, index, true);
417         return std::max(index - len, 0);
418     }
419     if (GreatOrEqual(localOffset.GetX(), contentRect.GetX() + contentRect.Width())) {
420         auto index = selectController->GetEndIndex();
421         if ((isFirst && !IsHandleReverse()) || (!isFirst && IsHandleReverse())) {
422             index = selectController->GetStartIndex();
423         }
424         auto len = pattern->GetGraphemeClusterLength(wideText, index);
425         return std::min(index + len, pattern->GetContentWideTextLength());
426     }
427     Offset offset(localOffset.GetX() - pattern->GetTextRect().GetX(), 0.0f);
428     return pattern->ConvertTouchOffsetToCaretPosition(offset);
429 }
430 
GetCaretPositionOnHandleMove(const OffsetF & localOffset,bool isFirst)431 int32_t TextFieldSelectOverlay::GetCaretPositionOnHandleMove(const OffsetF& localOffset, bool isFirst)
432 {
433     auto pattern = GetPattern<TextFieldPattern>();
434     CHECK_NULL_RETURN(pattern, 0);
435     if (pattern->IsTextArea()) {
436         return GetTextAreaCaretPosition(localOffset);
437     }
438     return GetTextInputCaretPosition(localOffset, isFirst);
439 }
440 
OnHandleMove(const RectF & handleRect,bool isFirst)441 void TextFieldSelectOverlay::OnHandleMove(const RectF& handleRect, bool isFirst)
442 {
443     auto pattern = GetPattern<TextFieldPattern>();
444     CHECK_NULL_VOID(pattern);
445     CHECK_NULL_VOID(pattern->IsOperation());
446     auto localOffset = handleRect.GetOffset();
447     localOffset.SetY(localOffset.GetY() + handleRect.Height() / 2.0f);
448     if (IsOverlayMode()) {
449         localOffset = localOffset - GetPaintOffsetWithoutTransform();
450     }
451     auto selectController = pattern->GetTextSelectController();
452     CHECK_NULL_VOID(selectController);
453     int32_t startIndex = selectController->GetFirstHandleIndex();
454     int32_t endIndex = selectController->GetSecondHandleIndex();
455     if (pattern->GetMagnifierController() && SelectOverlayIsOn()) {
456         auto magnifierLocalOffsetY = localOffset.GetY();
457         auto magnifierLocalOffset = OffsetF(localOffset.GetX(), magnifierLocalOffsetY);
458         if (IsOverlayMode()) {
459             GetLocalPointWithTransform(magnifierLocalOffset);
460         }
461         pattern->GetMagnifierController()->SetLocalOffset(magnifierLocalOffset);
462     }
463     if (IsSingleHandle()) {
464         int32_t preIndex = selectController->GetCaretIndex();
465         selectController->UpdateCaretInfoByOffset(Offset(localOffset.GetX(), localOffset.GetY()));
466         pattern->ShowCaretAndStopTwinkling();
467         pattern->StartVibratorByIndexChange(selectController->GetCaretIndex(), preIndex);
468     } else {
469         auto position = GetCaretPositionOnHandleMove(localOffset, isFirst);
470         if (isFirst) {
471             pattern->StartVibratorByIndexChange(position, startIndex);
472             selectController->MoveFirstHandleToContentRect(position, false);
473             UpdateSecondHandleOffset();
474         } else {
475             pattern->StartVibratorByIndexChange(position, endIndex);
476             selectController->MoveSecondHandleToContentRect(position, false);
477             UpdateFirstHandleOffset();
478         }
479     }
480     pattern->PlayScrollBarAppearAnimation();
481     auto tmpHost = pattern->GetHost();
482     CHECK_NULL_VOID(tmpHost);
483     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
484 }
485 
OnHandleMoveDone(const RectF & rect,bool isFirst)486 void TextFieldSelectOverlay::OnHandleMoveDone(const RectF& rect, bool isFirst)
487 {
488     BaseTextSelectOverlay::OnHandleMoveDone(rect, isFirst);
489     auto pattern = GetPattern<TextFieldPattern>();
490     CHECK_NULL_VOID(pattern);
491     auto host = pattern->GetHost();
492     CHECK_NULL_VOID(host);
493     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
494     CHECK_NULL_VOID(layoutProperty);
495     auto overlayManager = GetManager<SelectContentOverlayManager>();
496     CHECK_NULL_VOID(overlayManager);
497     if (!layoutProperty->GetSelectionMenuHiddenValue(false)) {
498         overlayManager->MarkInfoChange(DIRTY_COPY_ALL_ITEM);
499     }
500     if (pattern->GetMagnifierController()) {
501         pattern->GetMagnifierController()->RemoveMagnifierFrameNode();
502     }
503     auto selectController = pattern->GetTextSelectController();
504     if (!IsSingleHandle()) {
505         if (selectController->GetFirstHandleIndex() == selectController->GetSecondHandleIndex()) {
506             CloseOverlay(true, CloseReason::CLOSE_REASON_NORMAL);
507             pattern->StartTwinkling();
508             selectController->MoveCaretToContentRect(pattern->GetCaretIndex());
509         } else {
510             overlayManager->MarkInfoChange(DIRTY_DOUBLE_HANDLE | DIRTY_SELECT_AREA | DIRTY_SELECT_TEXT);
511         }
512     } else {
513         pattern->StopTwinkling();
514         overlayManager->MarkInfoChange(DIRTY_SECOND_HANDLE);
515     }
516     overlayManager->ShowOptionMenu();
517     overlayManager->SetHandleCircleIsShow(isFirst, true);
518     if (IsSingleHandle()) {
519         overlayManager->SetIsHandleLineShow(true);
520     }
521     pattern->ScheduleDisappearDelayTask();
522     pattern->UpdateCaretInfoToController();
523     auto tmpHost = pattern->GetHost();
524     CHECK_NULL_VOID(tmpHost);
525     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
526 }
527 
ProcessSelectAllOverlay(const OverlayRequest & request)528 void TextFieldSelectOverlay::ProcessSelectAllOverlay(const OverlayRequest& request)
529 {
530     OverlayRequest newRequest = request;
531     newRequest.requestCode = static_cast<uint32_t>(newRequest.requestCode) | REQUEST_SELECT_ALL;
532     ProcessOverlay(newRequest);
533 }
534 
OnAncestorNodeChanged(FrameNodeChangeInfoFlag flag)535 void TextFieldSelectOverlay::OnAncestorNodeChanged(FrameNodeChangeInfoFlag flag)
536 {
537     if (IsAncestorNodeGeometryChange(flag) || IsAncestorNodeTransformChange(flag)) {
538         UpdateAllHandlesOffset();
539     }
540     BaseTextSelectOverlay::OnAncestorNodeChanged(flag);
541 }
542 
OnHandleLevelModeChanged(HandleLevelMode mode)543 void TextFieldSelectOverlay::OnHandleLevelModeChanged(HandleLevelMode mode)
544 {
545     if (handleLevelMode_ != mode && mode == HandleLevelMode::OVERLAY) {
546         auto pattern = GetPattern<TextFieldPattern>();
547         if (pattern) {
548             pattern->UpdateParentGlobalOffset();
549             pattern->GetTextSelectController()->CalculateHandleOffset();
550         }
551     }
552     BaseTextSelectOverlay::OnHandleLevelModeChanged(mode);
553 }
554 
OnOverlayClick(const GestureEvent & event,bool isFirst)555 void TextFieldSelectOverlay::OnOverlayClick(const GestureEvent& event, bool isFirst)
556 {
557     auto pattern = GetPattern<TextFieldPattern>();
558     CHECK_NULL_VOID(pattern);
559     auto recognizer = pattern->GetMultipleClickRecognizer();
560     CHECK_NULL_VOID(recognizer);
561     if (recognizer->IsRunning() && recognizer->IsValidClick(event)) {
562         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield overlayClick multiple click recognizer is running.");
563         auto overlayEvent = event;
564         overlayEvent.SetLocalLocation(recognizer->GetBeginLocalLocation());
565         overlayEvent.SetGlobalLocation(recognizer->GetBeginGlobalLocation());
566         pattern->HandleClickEvent(overlayEvent);
567     } else if (!IsSingleHandle()) {
568         if (pattern->HandleBetweenSelectedPosition(event)) {
569             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield HandleBetweenSelectedPosition");
570             return;
571         }
572         auto selectController = pattern->GetTextSelectController();
573         auto index = isFirst ? selectController->GetFirstHandleIndex() : selectController->GetSecondHandleIndex();
574         pattern->HandleSetSelection(index, index, false);
575         pattern->StartTwinkling();
576     } else {
577         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield overlayClick");
578     }
579 }
580 
OnHandleIsHidden()581 void TextFieldSelectOverlay::OnHandleIsHidden()
582 {
583     auto pattern = GetPattern<TextFieldPattern>();
584     CHECK_NULL_VOID(pattern);
585     pattern->StartTwinkling();
586 }
587 
OnHandleMoveStart(const GestureEvent & event,bool isFirst)588 void TextFieldSelectOverlay::OnHandleMoveStart(const GestureEvent& event, bool isFirst)
589 {
590     BaseTextSelectOverlay::OnHandleMoveStart(event, isFirst);
591     auto manager = GetManager<SelectContentOverlayManager>();
592     CHECK_NULL_VOID(manager);
593     auto pattern = GetPattern<TextFieldPattern>();
594     CHECK_NULL_VOID(pattern);
595     manager->SetHandleCircleIsShow(isFirst, false);
596     if (IsSingleHandle()) {
597         manager->SetIsHandleLineShow(false);
598         if (!pattern->IsOperation()) {
599             pattern->StartTwinkling();
600         }
601     }
602 }
603 
GetHandleColor()604 std::optional<Color> TextFieldSelectOverlay::GetHandleColor()
605 {
606     auto textFieldPattern = GetPattern<TextFieldPattern>();
607     CHECK_NULL_RETURN(textFieldPattern, std::nullopt);
608     auto paintProperty = textFieldPattern->GetPaintProperty<TextFieldPaintProperty>();
609     CHECK_NULL_RETURN(paintProperty, std::nullopt);
610     return paintProperty->GetCursorColor();
611 }
612 
IsStopBackPress() const613 bool TextFieldSelectOverlay::IsStopBackPress() const
614 {
615     auto pattern = GetPattern<TextFieldPattern>();
616     CHECK_NULL_RETURN(pattern, true);
617     return pattern->IsStopBackPress();
618 }
619 
AllowTranslate()620 bool TextFieldSelectOverlay::AllowTranslate()
621 {
622     auto pattern = GetPattern<TextFieldPattern>();
623     CHECK_NULL_RETURN(pattern, false);
624     return pattern->AllowCopy();
625 }
626 } // namespace OHOS::Ace::NG
627