• 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/text_select_overlay.h"
17 
18 #include <algorithm>
19 #include <optional>
20 
21 #include "base/utils/utils.h"
22 #include "core/components/text_overlay/text_overlay_theme.h"
23 #include "core/components_ng/manager/select_content_overlay/select_content_overlay_manager.h"
24 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
25 #include "core/components_ng/pattern/text/text_pattern.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 constexpr float BOX_EPSILON = 0.5f;
30 }
31 
PreProcessOverlay(const OverlayRequest & request)32 bool TextSelectOverlay::PreProcessOverlay(const OverlayRequest& request)
33 {
34     auto pipeline = PipelineContext::GetCurrentContextSafely();
35     CHECK_NULL_RETURN(pipeline, false);
36     auto textPattern = GetPattern<TextPattern>();
37     CHECK_NULL_RETURN(textPattern, false);
38     SetUsingMouse(textPattern->IsUsingMouse());
39     SetEnableHandleLevel(true);
40     textPattern->CalculateHandleOffsetAndShowOverlay();
41     selectTextUseTopHandle = true;
42     return true;
43 }
44 
GetFirstHandleInfo()45 std::optional<SelectHandleInfo> TextSelectOverlay::GetFirstHandleInfo()
46 {
47     auto textPattern = GetPattern<TextPattern>();
48     CHECK_NULL_RETURN(textPattern, std::nullopt);
49     SelectHandleInfo handleInfo;
50     handleInfo.paintRect = textPattern->GetTextSelector().firstHandle;
51     handleInfo.isShow = CheckAndAdjustHandle(handleInfo.paintRect);
52 
53     auto localPaintRect = textPattern->GetTextSelector().firstHandle;
54     localPaintRect.SetOffset(localPaintRect.GetOffset() - GetPaintOffsetWithoutTransform());
55     handleInfo.localPaintRect = localPaintRect;
56     SetTransformPaintInfo(handleInfo, localPaintRect);
57     return handleInfo;
58 }
59 
GetSecondHandleInfo()60 std::optional<SelectHandleInfo> TextSelectOverlay::GetSecondHandleInfo()
61 {
62     auto textPattern = GetPattern<TextPattern>();
63     CHECK_NULL_RETURN(textPattern, std::nullopt);
64     SelectHandleInfo handleInfo;
65     handleInfo.paintRect = textPattern->GetTextSelector().secondHandle;
66     handleInfo.isShow = CheckAndAdjustHandle(handleInfo.paintRect);
67 
68     auto localPaintRect = textPattern->GetTextSelector().secondHandle;
69     localPaintRect.SetOffset(localPaintRect.GetOffset() - GetPaintOffsetWithoutTransform());
70     handleInfo.localPaintRect = localPaintRect;
71     SetTransformPaintInfo(handleInfo, localPaintRect);
72     return handleInfo;
73 }
74 
GetFirstHandleLocalPaintRect()75 RectF TextSelectOverlay::GetFirstHandleLocalPaintRect()
76 {
77     auto textPattern = GetPattern<TextPattern>();
78     CHECK_NULL_RETURN(textPattern, RectF());
79     auto localPaintRect = textPattern->GetTextSelector().firstHandle;
80     localPaintRect.SetOffset(localPaintRect.GetOffset() - GetPaintOffsetWithoutTransform());
81     return localPaintRect;
82 }
83 
GetSecondHandleLocalPaintRect()84 RectF TextSelectOverlay::GetSecondHandleLocalPaintRect()
85 {
86     auto textPattern = GetPattern<TextPattern>();
87     CHECK_NULL_RETURN(textPattern, RectF());
88     auto localPaintRect = textPattern->GetTextSelector().secondHandle;
89     localPaintRect.SetOffset(localPaintRect.GetOffset() - GetPaintOffsetWithoutTransform());
90     return localPaintRect;
91 }
92 
CheckAndAdjustHandle(RectF & paintRect)93 bool TextSelectOverlay::CheckAndAdjustHandle(RectF& paintRect)
94 {
95     auto textPattern = GetPattern<TextPattern>();
96     CHECK_NULL_RETURN(textPattern, false);
97     auto host = textPattern->GetHost();
98     CHECK_NULL_RETURN(host, false);
99     auto renderContext = host->GetRenderContext();
100     CHECK_NULL_RETURN(renderContext, false);
101     auto clip = false;
102     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
103         clip = true;
104     }
105     if (!renderContext->GetClipEdge().value_or(clip)) {
106         if (handleLevelMode_ == HandleLevelMode::EMBED) {
107             return true;
108         }
109         auto contentRect = textPattern->GetTextContentRect();
110         auto localPaintRect = paintRect;
111         localPaintRect.SetOffset(localPaintRect.GetOffset() - GetPaintOffsetWithoutTransform());
112         localPaintRect.SetOffset(OffsetF(localPaintRect.GetX() + localPaintRect.Width() / 2.0f, localPaintRect.GetY()));
113         auto visibleContentRect = contentRect.CombineRectT(localPaintRect);
114         visibleContentRect.SetOffset(visibleContentRect.GetOffset() + textPattern->GetTextPaintOffset());
115         visibleContentRect = GetVisibleRect(host, visibleContentRect);
116         return CheckAndAdjustHandleWithContent(visibleContentRect, paintRect);
117     }
118     auto contentRect = textPattern->GetTextContentRect();
119     RectF visibleContentRect(contentRect.GetOffset() + textPattern->GetTextPaintOffset(), contentRect.GetSize());
120     if (handleLevelMode_ == HandleLevelMode::OVERLAY) {
121         visibleContentRect = GetVisibleRect(host, visibleContentRect);
122     }
123     return CheckAndAdjustHandleWithContent(visibleContentRect, paintRect);
124 }
125 
CheckAndAdjustHandleWithContent(const RectF & visibleContentRect,RectF & paintRect)126 bool TextSelectOverlay::CheckAndAdjustHandleWithContent(const RectF& visibleContentRect, RectF& paintRect)
127 {
128     auto paintLeft = paintRect.GetX() + paintRect.Width() / 2.0f;
129     PointF bottomPoint = { paintLeft, paintRect.Bottom() - BOX_EPSILON };
130     PointF topPoint = { paintLeft, paintRect.Top() + BOX_EPSILON };
131     bool bottomInRegion = visibleContentRect.IsInRegion(bottomPoint);
132     bool topInRegion = visibleContentRect.IsInRegion(topPoint);
133     if (IsClipHandleWithViewPort()) {
134         return bottomInRegion || topInRegion;
135     }
136     if (!bottomInRegion && topInRegion) {
137         paintRect.SetHeight(visibleContentRect.Bottom() - paintRect.Top());
138     } else if (bottomInRegion && !topInRegion) {
139         paintRect.SetHeight(paintRect.Bottom() - visibleContentRect.Top());
140         paintRect.SetTop(visibleContentRect.Top());
141     }
142     return bottomInRegion || topInRegion;
143 }
144 
CheckHandleVisible(const RectF & paintRect)145 bool TextSelectOverlay::CheckHandleVisible(const RectF& paintRect)
146 {
147     auto textPattern = GetPattern<TextPattern>();
148     CHECK_NULL_RETURN(textPattern, false);
149     auto host = textPattern->GetHost();
150     CHECK_NULL_RETURN(host, false);
151     auto renderContext = host->GetRenderContext();
152     CHECK_NULL_RETURN(renderContext, false);
153     auto clip = false;
154     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
155         clip = true;
156     }
157     if (!renderContext->GetClipEdge().value_or(clip)) {
158         return true;
159     }
160     auto contentRect = textPattern->GetTextContentRect();
161     RectF visibleContentRect(contentRect.GetOffset() + textPattern->GetTextPaintOffset(), contentRect.GetSize());
162     visibleContentRect = GetVisibleRect(host, visibleContentRect);
163     PointF bottomPoint = { paintRect.Left(), paintRect.Bottom() - BOX_EPSILON };
164     PointF topPoint = { paintRect.Left(), paintRect.Top() + BOX_EPSILON };
165     return visibleContentRect.IsInRegion(bottomPoint) && visibleContentRect.IsInRegion(topPoint);
166 }
167 
OnResetTextSelection()168 void TextSelectOverlay::OnResetTextSelection()
169 {
170     auto textPattern = GetPattern<TextPattern>();
171     CHECK_NULL_VOID(textPattern);
172     textPattern->ResetSelection();
173 }
174 
OnHandleMove(const RectF & handleRect,bool isFirst)175 void TextSelectOverlay::OnHandleMove(const RectF& handleRect, bool isFirst)
176 {
177     auto textPattern = GetPattern<TextPattern>();
178     CHECK_NULL_VOID(textPattern);
179     auto host = textPattern->GetHost();
180     CHECK_NULL_VOID(host);
181     auto renderContext = host->GetRenderContext();
182     CHECK_NULL_VOID(renderContext);
183     auto contentRect = textPattern->GetTextContentRect();
184     auto contentOffset = contentRect.GetOffset();
185     auto localHandleOffset = handleRect.GetOffset();
186     if (IsOverlayMode()) {
187         contentOffset = contentOffset + GetPaintOffsetWithoutTransform();
188         localHandleOffset -= GetPaintOffsetWithoutTransform();
189     }
190     localHandleOffset.SetY(localHandleOffset.GetY() + handleRect.Height() / 2.0f);
191     textPattern->GetMagnifierController()->SetLocalOffset(localHandleOffset);
192     auto handleOffset = handleRect.GetOffset();
193     handleOffset.SetY(handleOffset.GetY() + handleRect.Height() / 2.0f);
194     auto clip = false;
195     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
196         clip = true;
197     }
198     if (renderContext->GetClipEdge().value_or(clip)) {
199         handleOffset.SetX(
200             std::clamp(handleOffset.GetX(), contentOffset.GetX(), contentOffset.GetX() + contentRect.Width()));
201         handleOffset.SetY(
202             std::clamp(handleOffset.GetY(), contentOffset.GetY(), contentOffset.GetY() + contentRect.Height()));
203     }
204     auto textPaintOffset = contentOffset - OffsetF(0.0f, std::min(textPattern->GetBaselineOffset(), 0.0f));
205     handleOffset -= textPaintOffset;
206     // the handle position is calculated based on the middle of the handle height.
207     UpdateSelectorOnHandleMove(handleOffset, isFirst);
208     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
209     auto overlayManager = GetManager<SelectContentOverlayManager>();
210     CHECK_NULL_VOID(overlayManager);
211     overlayManager->MarkInfoChange(DIRTY_SELECT_TEXT);
212 }
213 
UpdateSelectorOnHandleMove(const OffsetF & handleOffset,bool isFirstHandle)214 void TextSelectOverlay::UpdateSelectorOnHandleMove(const OffsetF& handleOffset, bool isFirstHandle)
215 {
216     auto textPattern = GetPattern<TextPattern>();
217     CHECK_NULL_VOID(textPattern);
218     auto currentHandleIndex = textPattern->GetHandleIndex(Offset(handleOffset.GetX(), handleOffset.GetY()));
219     if (isFirstHandle) {
220         textPattern->StartVibratorByIndexChange(currentHandleIndex, textPattern->GetTextSelector().baseOffset);
221         textPattern->HandleSelectionChange(currentHandleIndex, textPattern->GetTextSelector().destinationOffset);
222     } else {
223         textPattern->StartVibratorByIndexChange(currentHandleIndex, textPattern->GetTextSelector().destinationOffset);
224         textPattern->HandleSelectionChange(textPattern->GetTextSelector().baseOffset, currentHandleIndex);
225     }
226 }
227 
OnHandleMoveDone(const RectF & rect,bool isFirst)228 void TextSelectOverlay::OnHandleMoveDone(const RectF& rect, bool isFirst)
229 {
230     BaseTextSelectOverlay::OnHandleMoveDone(rect, isFirst);
231     auto textPattern = GetPattern<TextPattern>();
232     CHECK_NULL_VOID(textPattern);
233     if (textPattern->GetMagnifierController()) {
234         textPattern->GetMagnifierController()->RemoveMagnifierFrameNode();
235     }
236     textPattern->SetTextResponseType(TextResponseType::LONG_PRESS);
237     auto textSelector = textPattern->GetTextSelector();
238     textPattern->UpdateSelectionSpanType(textSelector.GetTextStart(), textSelector.GetTextEnd());
239     textPattern->CalculateHandleOffsetAndShowOverlay();
240     auto overlayManager = GetManager<SelectContentOverlayManager>();
241     CHECK_NULL_VOID(overlayManager);
242     overlayManager->ShowOptionMenu();
243     overlayManager->MarkInfoChange((isFirst ? DIRTY_FIRST_HANDLE : DIRTY_SECOND_HANDLE) | DIRTY_SELECT_AREA |
244                                    DIRTY_SELECT_TEXT | DIRTY_COPY_ALL_ITEM);
245     if (textPattern->CheckSelectedTypeChange()) {
246         CloseOverlay(false, CloseReason::CLOSE_REASON_NORMAL);
247         ProcessOverlay({ .animation = true });
248     }
249     overlayManager->SetHandleCircleIsShow(isFirst, true);
250     auto host = textPattern->GetHost();
251     CHECK_NULL_VOID(host);
252     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
253 }
254 
GetSelectedText()255 std::string TextSelectOverlay::GetSelectedText()
256 {
257     auto textPattern = GetPattern<TextPattern>();
258     CHECK_NULL_RETURN(textPattern, "");
259     auto start = textPattern->GetTextSelector().GetTextStart();
260     auto end = textPattern->GetTextSelector().GetTextEnd();
261     return textPattern->GetSelectedText(start, end);
262 }
263 
GetSelectArea()264 RectF TextSelectOverlay::GetSelectArea()
265 {
266     auto pattern = GetPattern<TextPattern>();
267     RectF res;
268     CHECK_NULL_RETURN(pattern, res);
269     auto selectRects = pattern->GetTextBoxes();
270     auto textPaintOffset = GetPaintOffsetWithoutTransform();
271     if (selectRects.empty()) {
272         res.SetOffset(res.GetOffset() + textPaintOffset);
273         GetSelectAreaFromHandle(res);
274         ApplySelectAreaWithKeyboard(res);
275         return res;
276     }
277     auto contentRect = pattern->GetTextContentRect();
278     auto textRect = pattern->GetTextRect();
279     res = MergeSelectedBoxes(selectRects, contentRect, textRect, textPaintOffset);
280     RectF visibleContentRect(contentRect.GetOffset() + textPaintOffset, contentRect.GetSize());
281     visibleContentRect = GetVisibleRect(pattern->GetHost(), visibleContentRect);
282     auto intersectRect = res.IntersectRectT(visibleContentRect);
283     intersectRect.SetWidth(std::max(intersectRect.Width(), 0.0f));
284     intersectRect.SetHeight(std::max(intersectRect.Height(), 0.0f));
285     if (hasTransform_) {
286         intersectRect.SetOffset(intersectRect.GetOffset() - textPaintOffset);
287         GetGlobalRectWithTransform(intersectRect);
288     }
289     ApplySelectAreaWithKeyboard(intersectRect);
290     return intersectRect;
291 }
292 
GetSelectAreaFromHandle(RectF & rect)293 void TextSelectOverlay::GetSelectAreaFromHandle(RectF& rect)
294 {
295     auto firstHandle = GetFirstHandleInfo();
296     if (firstHandle) {
297         auto firstRect = firstHandle->paintRect;
298         if (hasTransform_) {
299             firstRect.SetOffset(firstRect.GetOffset() - GetPaintOffsetWithoutTransform());
300             GetGlobalRectWithTransform(firstRect);
301         }
302         rect = firstRect;
303         return;
304     }
305     auto secondHandle = GetSecondHandleInfo();
306     if (secondHandle) {
307         auto secondRect = secondHandle->paintRect;
308         if (hasTransform_) {
309             secondRect.SetOffset(secondRect.GetOffset() - GetPaintOffsetWithoutTransform());
310             GetGlobalRectWithTransform(secondRect);
311         }
312         rect = secondRect;
313     }
314 }
315 
OnUpdateMenuInfo(SelectMenuInfo & menuInfo,SelectOverlayDirtyFlag dirtyFlag)316 void TextSelectOverlay::OnUpdateMenuInfo(SelectMenuInfo& menuInfo, SelectOverlayDirtyFlag dirtyFlag)
317 {
318     auto textPattern = GetPattern<TextPattern>();
319     CHECK_NULL_VOID(textPattern);
320     menuInfo.showCopyAll = !textPattern->IsSelectAll();
321     menuInfo.showCopy = !textPattern->GetTextSelector().SelectNothing();
322     if (dirtyFlag == DIRTY_COPY_ALL_ITEM) {
323         return;
324     }
325     menuInfo.menuIsShow = IsShowMenu();
326     menuInfo.showCut = false;
327     menuInfo.showPaste = false;
328 }
329 
OnUpdateSelectOverlayInfo(SelectOverlayInfo & overlayInfo,int32_t requestCode)330 void TextSelectOverlay::OnUpdateSelectOverlayInfo(SelectOverlayInfo& overlayInfo, int32_t requestCode)
331 {
332     overlayInfo.clipHandleDrawRect = IsClipHandleWithViewPort();
333     BaseTextSelectOverlay::OnUpdateSelectOverlayInfo(overlayInfo, requestCode);
334     auto textPattern = GetPattern<TextPattern>();
335     CHECK_NULL_VOID(textPattern);
336     textPattern->CopySelectionMenuParams(overlayInfo);
337     OnUpdateOnCreateMenuCallback(overlayInfo);
338     auto scrollableParent = FindScrollableParent();
339     if (scrollableParent) {
340         auto weakParent = WeakClaim(AceType::RawPtr(scrollableParent));
341         overlayInfo.onHandlePanMove = [weak = WeakClaim(this), weakParent](const GestureEvent& event, bool isFirst) {
342             auto overlay = weak.Upgrade();
343             CHECK_NULL_VOID(overlay);
344             overlay->TriggerScrollableParentToScroll(weakParent.Upgrade(), event.GetGlobalLocation(), false);
345         };
346         overlayInfo.onHandlePanEnd = [weak = WeakClaim(this), weakParent](const GestureEvent& event, bool isFirst) {
347             auto overlay = weak.Upgrade();
348             CHECK_NULL_VOID(overlay);
349             overlay->TriggerScrollableParentToScroll(weakParent.Upgrade(), event.GetGlobalLocation(), true);
350         };
351         overlayInfo.getDeltaHandleOffset = [weak = WeakClaim(this)]() {
352             auto overlay = weak.Upgrade();
353             CHECK_NULL_RETURN(overlay, OffsetF());
354             auto hostPaintOffset = overlay->GetHotPaintOffset();
355             auto deltaOffset = overlay->hostPaintOffset_ - hostPaintOffset;
356             overlay->hostPaintOffset_ = hostPaintOffset;
357             return deltaOffset;
358         };
359     }
360 }
361 
OnMenuItemAction(OptionMenuActionId id,OptionMenuType type)362 void TextSelectOverlay::OnMenuItemAction(OptionMenuActionId id, OptionMenuType type)
363 {
364     auto textPattern = GetPattern<TextPattern>();
365     CHECK_NULL_VOID(textPattern);
366     switch (id) {
367         case OptionMenuActionId::COPY:
368             textPattern->HandleOnCopy();
369             break;
370         case OptionMenuActionId::SELECT_ALL:
371             textPattern->HandleOnSelectAll();
372             break;
373         default:
374             TAG_LOGI(AceLogTag::ACE_TEXT, "Unsupported menu option id %{public}d", id);
375             break;
376     }
377 }
378 
OnCloseOverlay(OptionMenuType menuType,CloseReason reason,RefPtr<OverlayInfo> info)379 void TextSelectOverlay::OnCloseOverlay(OptionMenuType menuType, CloseReason reason, RefPtr<OverlayInfo> info)
380 {
381     BaseTextSelectOverlay::OnCloseOverlay(menuType, reason, info);
382     auto textPattern = GetPattern<TextPattern>();
383     CHECK_NULL_VOID(textPattern);
384     if (reason == CloseReason::CLOSE_REASON_HOLD_BY_OTHER || reason == CloseReason::CLOSE_REASON_TOOL_BAR ||
385         reason == CloseReason::CLOSE_REASON_BACK_PRESSED) {
386         textPattern->ResetSelection();
387     }
388     if (textPattern->GetMagnifierController()) {
389         textPattern->GetMagnifierController()->RemoveMagnifierFrameNode();
390     }
391 }
392 
OnHandleGlobalTouchEvent(SourceType sourceType,TouchType touchType,bool touchInside)393 void TextSelectOverlay::OnHandleGlobalTouchEvent(SourceType sourceType, TouchType touchType, bool touchInside)
394 {
395     auto textPattern = GetPattern<TextPattern>();
396     CHECK_NULL_VOID(textPattern);
397     if (IsMouseClickDown(sourceType, touchType) && touchInside) {
398         textPattern->ResetSelection();
399     }
400     BaseTextSelectOverlay::OnHandleGlobalTouchEvent(sourceType, touchType);
401 }
402 
OnAncestorNodeChanged(FrameNodeChangeInfoFlag flag)403 void TextSelectOverlay::OnAncestorNodeChanged(FrameNodeChangeInfoFlag flag)
404 {
405     auto isDragging = GetIsHandleDragging();
406     if (IsAncestorNodeGeometryChange(flag)) {
407         auto textPattern = GetPattern<TextPattern>();
408         CHECK_NULL_VOID(textPattern);
409         textPattern->UpdateParentGlobalOffset();
410         textPattern->CalculateHandleOffsetAndShowOverlay();
411         if (isDragging && isDraggingFirstHandle_) {
412             UpdateViewPort();
413             UpdateSecondHandleOffset();
414             return;
415         }
416         if (isDragging && !isDraggingFirstHandle_) {
417             UpdateViewPort();
418             UpdateFirstHandleOffset();
419             return;
420         }
421         UpdateAllHandlesOffset();
422     }
423     if (!isDragging) {
424         BaseTextSelectOverlay::OnAncestorNodeChanged(flag);
425     }
426 }
427 
OnHandleLevelModeChanged(HandleLevelMode mode)428 void TextSelectOverlay::OnHandleLevelModeChanged(HandleLevelMode mode)
429 {
430     if (handleLevelMode_ != mode && mode == HandleLevelMode::OVERLAY) {
431         auto textPattern = GetPattern<TextPattern>();
432         CHECK_NULL_VOID(textPattern);
433         textPattern->UpdateParentGlobalOffset();
434         textPattern->CalculateHandleOffsetAndShowOverlay();
435         UpdateAllHandlesOffset();
436     }
437     BaseTextSelectOverlay::OnHandleLevelModeChanged(mode);
438 }
439 
OnHandleMoveStart(const GestureEvent & event,bool isFirst)440 void TextSelectOverlay::OnHandleMoveStart(const GestureEvent& event, bool isFirst)
441 {
442     BaseTextSelectOverlay::OnHandleMoveStart(event, isFirst);
443     auto textPattern = GetPattern<TextPattern>();
444     CHECK_NULL_VOID(textPattern);
445     textPattern->ChangeHandleHeight(event, isFirst, IsOverlayMode());
446     auto manager = GetManager<SelectContentOverlayManager>();
447     CHECK_NULL_VOID(manager);
448     manager->MarkInfoChange(isFirst ? DIRTY_FIRST_HANDLE : DIRTY_SECOND_HANDLE);
449     manager->SetHandleCircleIsShow(isFirst, false);
450     isDraggingFirstHandle_ = isFirst;
451     hostPaintOffset_ = GetHotPaintOffset();
452 }
453 
OnOverlayClick(const GestureEvent & event,bool isFirst)454 void TextSelectOverlay::OnOverlayClick(const GestureEvent& event, bool isFirst)
455 {
456     if (!IsSingleHandle()) {
457         ToggleMenu();
458     }
459 }
460 
UpdateClipHandleViewPort(RectF & rect)461 void TextSelectOverlay::UpdateClipHandleViewPort(RectF& rect)
462 {
463     auto host = GetOwner();
464     CHECK_NULL_VOID(host);
465     auto renderContext = host->GetRenderContext();
466     CHECK_NULL_VOID(renderContext);
467     if (renderContext->GetClipEdge().value_or(false)) {
468         return;
469     }
470     auto clipNode = host->GetAncestorNodeOfFrame(true);
471     while (clipNode) {
472         renderContext = clipNode->GetRenderContext();
473         CHECK_NULL_VOID(renderContext);
474         if (renderContext->GetClipEdge().value_or(false)) {
475             break;
476         }
477         clipNode = clipNode->GetAncestorNodeOfFrame(true);
478     }
479     CHECK_NULL_VOID(clipNode);
480     RectF visibleRect;
481     RectF frameRect;
482     clipNode->GetVisibleRect(visibleRect, frameRect);
483     rect.SetHeight(visibleRect.Bottom() - rect.Top());
484 }
485 
TriggerScrollableParentToScroll(const RefPtr<ScrollablePattern> scrollablePattern,const Offset & globalOffset,bool isStopAutoScroll)486 void TextSelectOverlay::TriggerScrollableParentToScroll(
487     const RefPtr<ScrollablePattern> scrollablePattern, const Offset& globalOffset, bool isStopAutoScroll)
488 {
489     CHECK_NULL_VOID(scrollablePattern);
490     auto scrollAxis = scrollablePattern->GetAxis();
491     if (!scrollablePattern->IsScrollable() || (scrollAxis != Axis::VERTICAL && scrollAxis != Axis::HORIZONTAL)) {
492         return;
493     }
494     auto scrollableHost = scrollablePattern->GetHost();
495     CHECK_NULL_VOID(scrollableHost);
496     auto scrollableFrameRect = scrollableHost->GetPaintRectWithTransform();
497     auto host = GetOwner();
498     CHECK_NULL_VOID(host);
499     auto hostRect = host->GetPaintRectWithTransform();
500     auto hostSize = hostRect.Height();
501     auto scrollableParentSize = scrollableFrameRect.Height();
502     if (scrollAxis == Axis::HORIZONTAL) {
503         hostSize = hostRect.Width();
504         scrollableParentSize = scrollableFrameRect.Width();
505     }
506     if (LessOrEqual(hostSize, scrollableParentSize)) {
507         return;
508     }
509     RefPtr<NotifyDragEvent> notifyDragEvent = AceType::MakeRefPtr<NotifyDragEvent>();
510     notifyDragEvent->SetX(globalOffset.GetX());
511     notifyDragEvent->SetY(globalOffset.GetY());
512     scrollablePattern->HandleOnDragStatusCallback(
513         isStopAutoScroll ? DragEventType::DROP : DragEventType::MOVE, notifyDragEvent);
514 }
515 
FindScrollableParent()516 const RefPtr<ScrollablePattern> TextSelectOverlay::FindScrollableParent()
517 {
518     auto host = GetOwner();
519     CHECK_NULL_RETURN(host, nullptr);
520     auto parent = host->GetAncestorNodeOfFrame(true);
521     while (parent) {
522         auto scrollablePattern = parent->GetPattern<ScrollablePattern>();
523         if (scrollablePattern) {
524             return scrollablePattern;
525         }
526         parent = parent->GetAncestorNodeOfFrame(true);
527     }
528     return nullptr;
529 }
530 
GetHotPaintOffset()531 OffsetF TextSelectOverlay::GetHotPaintOffset()
532 {
533     auto host = GetOwner();
534     CHECK_NULL_RETURN(host, hostPaintOffset_);
535     auto renderContext = host->GetRenderContext();
536     CHECK_NULL_RETURN(renderContext, hostPaintOffset_);
537     return renderContext->GetPaintRectWithTransform().GetOffset();
538 }
539 } // namespace OHOS::Ace::NG
540