1 /*
2  * Copyright (c) 2021-2022 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/text/render_text.h"
17 
18 #include "base/geometry/size.h"
19 #include "base/log/dump_log.h"
20 #include "core/common/ace_engine_ext.h"
21 #include "core/common/clipboard/clipboard_proxy.h"
22 #include "core/common/font_manager.h"
23 #include "core/components/container_modal/container_modal_constants.h"
24 #include "core/components/gesture_listener/gesture_listener_component.h"
25 #include "core/components/text/text_component.h"
26 #include "core/components/text_field/render_text_field.h"
27 #include "core/components/text_overlay/text_overlay_component.h"
28 #include "core/components_v2/inspector/utils.h"
29 #include "core/event/ace_event_helper.h"
30 #include "core/event/ace_events.h"
31 
32 namespace OHOS::Ace {
33 
34 namespace {
35 constexpr Dimension CURSOR_WIDTH = 1.5_vp;
36 constexpr double HANDLE_HOT_ZONE = 10.0;
37 } // namespace
38 
~RenderText()39 RenderText::~RenderText()
40 {
41     auto context = context_.Upgrade();
42     if (context) {
43         context->RemoveFontNode(AceType::WeakClaim(this));
44         auto fontManager = context->GetFontManager();
45         if (fontManager) {
46             fontManager->UnRegisterCallback(AceType::WeakClaim(this));
47             fontManager->RemoveVariationNode(WeakClaim(this));
48         }
49     }
50 
51     auto textOverlayManager = GetTextOverlayManager(context_);
52     if (textOverlayManager) {
53         auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
54         if (textOverlayBase) {
55             auto targetNode = textOverlayManager->GetTargetNode();
56             if (targetNode == this) {
57                 textOverlayManager->PopTextOverlay();
58                 textOverlayBase->ChangeSelection(0, 0);
59                 textOverlayBase->MarkIsOverlayShowed(false);
60                 targetNode->MarkNeedRender();
61             }
62         }
63     }
64 }
65 
Update(const RefPtr<Component> & component)66 void RenderText::Update(const RefPtr<Component>& component)
67 {
68     text_ = AceType::DynamicCast<TextComponent>(component);
69     CheckIfNeedMeasure();
70     auto context = context_.Upgrade();
71     if (!context) {
72         LOGE("the context is nullptr in text update");
73         return;
74     }
75     // Register callback for fonts.
76     auto callback = [weakText = AceType::WeakClaim(this)] {
77         auto text = weakText.Upgrade();
78         if (text) {
79             text->isCallbackCalled_ = true;
80             text->MarkNeedLayout();
81         }
82     };
83 
84     auto fontManager = context->GetFontManager();
85     if (fontManager) {
86         for (const auto& familyName : textStyle_.GetFontFamilies()) {
87             auto isCustomFont = fontManager->RegisterCallback(AceType::WeakClaim(this), familyName, callback);
88             if (isCustomFont) {
89                 isCustomFont_ = true;
90             }
91         }
92         fontManager->AddVariationNode(WeakClaim(this));
93     }
94     if (isFocus_) {
95         textStyle_.SetTextColor(focusColor_);
96     }
97 
98     if (textStyle_.IsAllowScale() || textStyle_.GetFontSize().Unit() == DimensionUnit::FP) {
99         context->AddFontNode(AceType::WeakClaim(this));
100     }
101 
102     if (!clipboard_ && context) {
103         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
104     }
105 
106     copyOption_ = text_->GetCopyOption();
107     textForDisplay_ = text_->GetData();
108     defaultTextDirection_ = TextDirection::LTR;
109     realTextDirection_ = defaultTextDirection_;
110     textAffinity_ = TextAffinity::UPSTREAM;
111     textValue_.text = text_->GetData();
112     cursorWidth_ = NormalizeToPx(CURSOR_WIDTH);
113     alignment_ = text_->GetAlignment();
114 
115     onDragStart_ = text_->GetOnDragStartId();
116     onDragEnter_ = text_->GetOnDragEnterId();
117     onDragMove_ = text_->GetOnDragMoveId();
118     onDragLeave_ = text_->GetOnDragLeaveId();
119     onDrop_ = text_->GetOnDropId();
120     if (onDragStart_) {
121         CreateDragDropRecognizer(context_);
122         CreateSelectRecognizer();
123     }
124 }
125 
OnPaintFinish()126 void RenderText::OnPaintFinish()
127 {
128     UpdateOverlay();
129 #if !defined(PREVIEW)
130     UpdateAccessibilityText();
131 #endif
132 }
133 
UpdateAccessibilityText()134 void RenderText::UpdateAccessibilityText()
135 {
136     const auto& context = context_.Upgrade();
137     if (!context) {
138         return;
139     }
140     auto viewScale = context->GetViewScale();
141     if (NearZero(viewScale)) {
142         return;
143     }
144     auto accessibilityNode = GetAccessibilityNode().Upgrade();
145     if (!accessibilityNode) {
146         return;
147     }
148     if (GetChildren().empty()) {
149         if (text_) {
150             accessibilityNode->SetText(text_->GetData());
151         }
152     } else {
153         std::string accessibilityText;
154         for (const auto& child : GetChildren()) {
155             auto renderTextSpan = AceType::DynamicCast<RenderTextSpan>(child);
156             if (renderTextSpan) {
157                 accessibilityText += renderTextSpan->GetSpanData();
158             }
159         }
160         accessibilityNode->SetText(accessibilityText);
161     }
162     if (!accessibilityNode->GetVisible()) { // Set 0 to item when whole outside of view port.
163         accessibilityNode->SetWidth(0.0);
164         accessibilityNode->SetHeight(0.0);
165         accessibilityNode->SetTop(0.0);
166         accessibilityNode->SetLeft(0.0);
167         return;
168     }
169     if (accessibilityNode->IsValidRect()) {
170         return; // Rect already clamp by viewport, no need to set again.
171     }
172     Size size = GetLayoutSize();
173     Offset globalOffset = GetGlobalOffsetExternal();
174     PositionInfo positionInfo = { (size.Width()) * viewScale, (size.Height()) * viewScale,
175         (globalOffset.GetX()) * viewScale, (globalOffset.GetY()) * viewScale };
176     accessibilityNode->SetPositionInfo(positionInfo);
177     accessibilityNode->SetIsMultiLine(GetTextLines() > 1);
178 }
179 
IsDeclarativePara()180 bool RenderText::IsDeclarativePara()
181 {
182     auto context = context_.Upgrade();
183     if (!context) {
184         return false;
185     }
186 
187     return context->GetIsDeclarative();
188 }
189 
PerformLayout()190 void RenderText::PerformLayout()
191 {
192     // When the constraint is set, minHeight is reset to 0.0,
193     // and the occupied height is controlled by the parent node box
194     if (IsDeclarativePara()) {
195         LayoutParam layoutParam = GetLayoutParam();
196         auto minWidth = layoutParam.GetMinSize().Width();
197         auto minHeight = layoutParam.GetMinSize().Height();
198         if (GreatNotEqual(minHeight, 0.0f)) {
199             layoutParam.SetMinSize(Size(minWidth, 0.0f));
200             SetLayoutParam(layoutParam);
201         }
202     }
203     auto pipelineContext = GetContext().Upgrade();
204     if ((textStyle_.IsAllowScale() || textStyle_.GetFontSize().Unit() == DimensionUnit::FP) && pipelineContext &&
205         !NearEqual(fontScale_, pipelineContext->GetFontScale())) {
206         needMeasure_ = true;
207         fontScale_ = pipelineContext->GetFontScale();
208     }
209     if (pipelineContext) {
210         UpdateIfChanged(dipScale_, pipelineContext->GetDipScale());
211     }
212     Size size = Measure();
213     SetLayoutSize(GetLayoutParam().Constrain(size));
214     for (const auto& spanChild : GetChildren()) {
215         if (spanChild) {
216             const auto& param = GetLayoutParam();
217             spanChild->Layout(param);
218         }
219     }
220     textOverlayPaintRect_ = GetPaintRect();
221 }
222 
TouchTest(const Point & globalPoint,const Point & parentLocalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result)223 bool RenderText::TouchTest(const Point& globalPoint, const Point& parentLocalPoint, const TouchRestrict& touchRestrict,
224     TouchTestResult& result)
225 {
226     if (GetDisableTouchEvent() || disabled_) {
227         return false;
228     }
229 
230     // Since the paintRect is relative to parent, use parent local point to perform touch test.
231     if (!InTouchRectList(parentLocalPoint, GetTouchRectList())) {
232         return false;
233     }
234 
235     // Reset flag firstly.
236     needClickDetector_ = false;
237     needLongPressDetector_ = false;
238     needTouchDetector_ = false;
239     // Calculates the local point location in this node.
240     const auto localPoint = parentLocalPoint - GetPaintRect().GetOffset();
241     Offset localOffset = Offset(localPoint.GetX(), localPoint.GetY());
242     // If span of touch position has click event, need add click detector.
243     if (!GetEventMarker(GetTouchPosition(localOffset), GestureType::CLICK).IsEmpty() ||
244         !GetEventMarker(GetTouchPosition(localOffset), GestureType::REMOTE_MESSAGE).IsEmpty()) {
245         needClickDetector_ = true;
246     }
247     // If span of touch position has long press event, need add long press detector.
248     if (!GetEventMarker(GetTouchPosition(localOffset), GestureType::LONG_PRESS).IsEmpty()) {
249         needLongPressDetector_ = true;
250     }
251     // If span of touch position has touch event, need add touch detector.
252     if (!GetEventMarker(GetTouchPosition(localOffset), GestureType::TOUCH_START).IsEmpty() ||
253         !GetEventMarker(GetTouchPosition(localOffset), GestureType::TOUCH_MOVE).IsEmpty() ||
254         !GetEventMarker(GetTouchPosition(localOffset), GestureType::TOUCH_END).IsEmpty() ||
255         !GetEventMarker(GetTouchPosition(localOffset), GestureType::TOUCH_CANCEL).IsEmpty()) {
256         needTouchDetector_ = true;
257     }
258     if (!needClickDetector_ && !needLongPressDetector_ && !needTouchDetector_ && copyOption_ == CopyOptions::None &&
259         !onDragStart_) {
260         return false;
261     }
262 
263     auto beforeSize = result.size();
264     if (touchable_) {
265         // Calculates the coordinate offset in this node.
266         const auto coordinateOffset = globalPoint - localPoint;
267         globalPoint_ = globalPoint;
268         OnTouchTestHit(coordinateOffset, touchRestrict, result);
269     }
270     auto endSize = result.size();
271     return beforeSize != endSize;
272 }
273 
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)274 void RenderText::OnTouchTestHit(
275     const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
276 {
277     if (copyOption_ != CopyOptions::None) {
278         if (!textOverlayRecognizer_) {
279             textOverlayRecognizer_ = AceType::MakeRefPtr<LongPressRecognizer>(context_);
280             textOverlayRecognizer_->SetOnLongPress([weak = WeakClaim(this)](const LongPressInfo& info) {
281                 auto client = weak.Upgrade();
282                 if (client) {
283                     client->OnLongPress(info);
284                 }
285             });
286         }
287         textOverlayRecognizer_->SetCoordinateOffset(coordinateOffset);
288         textOverlayRecognizer_->SetTouchRestrict(touchRestrict);
289         textOverlayRecognizer_->SetUseCatchMode(false);
290         result.emplace_back(textOverlayRecognizer_);
291     }
292 
293     if (onDragStart_) {
294         if (!hideTextOverlayRecognizer_) {
295             hideTextOverlayRecognizer_ = AceType::MakeRefPtr<ClickRecognizer>();
296             hideTextOverlayRecognizer_->SetOnClick([weak = WeakClaim(this)](const ClickInfo& info) {
297                 auto text = weak.Upgrade();
298                 if (text && info.GetSourceDevice() == SourceType::MOUSE) {
299                     text->HideTextOverlay();
300                 }
301             });
302         }
303         hideTextOverlayRecognizer_->SetCoordinateOffset(coordinateOffset);
304         hideTextOverlayRecognizer_->SetTouchRestrict(touchRestrict);
305         result.emplace_back(hideTextOverlayRecognizer_);
306 
307         if (touchRestrict.sourceType == SourceType::MOUSE) {
308             Offset offset(globalPoint_.GetX(), globalPoint_.GetY());
309             if (IsSelectedText(offset, GetGlobalOffset())) {
310                 result.emplace_back(dragDropGesture_);
311             } else {
312                 result.emplace_back(selectRecognizer_);
313             }
314         } else {
315             auto renderText = AceType::Claim(this);
316             if (renderText) {
317                 SetStartOffset(GetHandleOffset(0));
318                 SetEndOffset(GetHandleOffset(textValue_.GetWideText().length()));
319                 textValue_.UpdateSelection(0, textValue_.GetWideText().length());
320             }
321             result.emplace_back(dragDropGesture_);
322         }
323     }
324 
325     if (GetChildren().empty()) {
326         return;
327     }
328 
329     auto context = context_.Upgrade();
330     if (!context) {
331         return;
332     }
333 
334     if (needTouchDetector_) {
335         if (!rawRecognizer_) {
336             rawRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
337             rawRecognizer_->SetOnTouchDown([weak = WeakClaim(this)](const TouchEventInfo& info) {
338                 auto text = weak.Upgrade();
339                 if (text && !info.GetTouches().empty()) {
340                     text->HandleTouchEvent(GestureType::TOUCH_START,
341                         info.GetTouches().front().GetLocalLocation() - text->GetGlobalOffset());
342                 }
343             });
344 
345             rawRecognizer_->SetOnTouchMove([weak = WeakClaim(this)](const TouchEventInfo& info) {
346                 auto text = weak.Upgrade();
347                 if (text && !info.GetTouches().empty()) {
348                     text->HandleTouchEvent(GestureType::TOUCH_MOVE,
349                         info.GetTouches().front().GetLocalLocation() - text->GetGlobalOffset());
350                 }
351             });
352 
353             rawRecognizer_->SetOnTouchUp([weak = WeakClaim(this)](const TouchEventInfo& info) {
354                 auto text = weak.Upgrade();
355                 if (text && !info.GetTouches().empty()) {
356                     text->HandleTouchEvent(
357                         GestureType::TOUCH_END, info.GetTouches().front().GetLocalLocation() - text->GetGlobalOffset());
358                 }
359             });
360 
361             rawRecognizer_->SetOnTouchCancel([weak = WeakClaim(this)](const TouchEventInfo& info) {
362                 auto text = weak.Upgrade();
363                 if (text && !info.GetTouches().empty()) {
364                     text->HandleTouchEvent(GestureType::TOUCH_CANCEL,
365                         info.GetTouches().front().GetLocalLocation() - text->GetGlobalOffset());
366                 }
367             });
368         }
369         rawRecognizer_->SetTouchRestrict(touchRestrict);
370         rawRecognizer_->SetCoordinateOffset(coordinateOffset);
371         result.emplace_back(rawRecognizer_);
372         needTouchDetector_ = false;
373     }
374 
375     if (needClickDetector_) {
376         if (!clickDetector_) {
377             clickDetector_ = AceType::MakeRefPtr<ClickRecognizer>();
378             clickDetector_->SetOnClick([weak = WeakClaim(this)](const ClickInfo& info) {
379                 auto text = weak.Upgrade();
380                 if (text) {
381                     text->HandleClick(info);
382                 }
383             });
384             clickDetector_->SetRemoteMessage([weak = WeakClaim(this)](const ClickInfo& info) {
385                 auto text = weak.Upgrade();
386                 if (text) {
387                     text->HandleRemoteMessage(info);
388                 }
389             });
390         }
391         clickDetector_->SetCoordinateOffset(coordinateOffset);
392         clickDetector_->SetTouchRestrict(touchRestrict);
393         clickDetector_->SetIsExternalGesture(true);
394         result.emplace_back(clickDetector_);
395         needClickDetector_ = false;
396     }
397 
398     if (needLongPressDetector_) {
399         if (!longPressRecognizer_) {
400             longPressRecognizer_ = AceType::MakeRefPtr<LongPressRecognizer>(context_);
401             longPressRecognizer_->SetOnLongPress([weak = WeakClaim(this)](const LongPressInfo& info) {
402                 auto text = weak.Upgrade();
403                 if (text) {
404                     text->HandleLongPress(info.GetLocalLocation());
405                 }
406             });
407         }
408         longPressRecognizer_->SetCoordinateOffset(coordinateOffset);
409         longPressRecognizer_->SetTouchRestrict(touchRestrict);
410         result.emplace_back(longPressRecognizer_);
411         needLongPressDetector_ = false;
412     }
413 }
414 
HideTextOverlay()415 void RenderText::HideTextOverlay()
416 {
417     auto textOverlayManager = GetTextOverlayManager(context_);
418     if (!textOverlayManager) {
419         return;
420     }
421 
422     auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
423     if (!textOverlayBase) {
424         return;
425     }
426 
427     auto targetNode = textOverlayManager->GetTargetNode();
428     if (targetNode == this) {
429         textOverlayManager->PopTextOverlay();
430         textOverlayBase->ChangeSelection(0, 0);
431         textOverlayBase->MarkIsOverlayShowed(false);
432         targetNode->MarkNeedRender();
433     }
434 }
435 
UpdateTextOverlay()436 void RenderText::UpdateTextOverlay()
437 {
438     auto textOverlayManager = GetTextOverlayManager(context_);
439     if (!textOverlayManager) {
440         return;
441     }
442 
443     auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
444     if (!textOverlayBase) {
445         return;
446     }
447 
448     auto targetNode = textOverlayManager->GetTargetNode();
449     if (targetNode == this) {
450         targetNode->MarkNeedRender();
451     }
452 }
453 
OnLongPress(const LongPressInfo & longPressInfo)454 void RenderText::OnLongPress(const LongPressInfo& longPressInfo)
455 {
456     if (longPressInfo.GetSourceDevice() == SourceType::MOUSE) {
457         return;
458     }
459 
460     auto textOverlayManager = GetTextOverlayManager(context_);
461     if (textOverlayManager) {
462         auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
463         if (textOverlayBase) {
464             auto targetNode = textOverlayManager->GetTargetNode();
465             if (targetNode) {
466                 textOverlayManager->PopTextOverlay();
467                 textOverlayBase->ChangeSelection(0, 0);
468                 textOverlayBase->MarkIsOverlayShowed(false);
469                 targetNode->MarkNeedRender();
470             }
471         }
472         textOverlayManager->SetTextOverlayBase(AceType::WeakClaim(this));
473     }
474 
475     Offset longPressPosition = longPressInfo.GetGlobalLocation();
476     auto context = context_.Upgrade();
477     if (context) {
478         auto isContainerModal = context->GetWindowModal() == WindowModal::CONTAINER_MODAL &&
479                                 context->GetWindowManager()->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
480         if (isContainerModal) {
481             longPressPosition =
482                 longPressPosition + Offset(-(CONTAINER_BORDER_WIDTH.ConvertToPx() + CONTENT_PADDING.ConvertToPx()),
483                                            -CONTAINER_TITLE_HEIGHT.ConvertToPx());
484         }
485     }
486 
487     InitSelection(longPressPosition, GetGlobalOffset());
488     ShowTextOverlay(longPressPosition, false);
489 }
490 
HandleMouseEvent(const MouseEvent & event)491 bool RenderText::HandleMouseEvent(const MouseEvent& event)
492 {
493     if (copyOption_ == CopyOptions::None) {
494         return false;
495     }
496     if (event.button == MouseButton::RIGHT_BUTTON && event.action == MouseAction::PRESS) {
497         Offset rightClickOffset = event.GetOffset();
498 
499         auto textOverlayManager = GetTextOverlayManager(context_);
500         if (textOverlayManager) {
501             auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
502             if (textOverlayBase) {
503                 auto targetNode = textOverlayManager->GetTargetNode();
504                 if (targetNode) {
505                     textOverlayManager->PopTextOverlay();
506                     textOverlayBase->ChangeSelection(0, 0);
507                     textOverlayBase->MarkIsOverlayShowed(false);
508                     targetNode->MarkNeedRender();
509                 }
510             }
511             textOverlayManager->SetTextOverlayBase(AceType::WeakClaim(this));
512         }
513         InitSelection(rightClickOffset, GetGlobalOffset());
514         ShowTextOverlay(rightClickOffset, true);
515         return true;
516     }
517 
518     return false;
519 }
520 
ShowTextOverlay(const Offset & showOffset)521 void RenderText::ShowTextOverlay(const Offset& showOffset)
522 {
523     ShowTextOverlay(showOffset, false);
524 }
525 
ShowTextOverlay(const Offset & showOffset,bool isUsingMouse)526 void RenderText::ShowTextOverlay(const Offset& showOffset, bool isUsingMouse)
527 {
528     auto selStart = textValue_.selection.GetStart();
529     auto selEnd = textValue_.selection.GetEnd();
530 
531     Offset startHandleOffset = GetHandleOffset(selStart);
532     Offset endHandleOffset = GetHandleOffset(selEnd);
533 
534     if (isOverlayShowed_ && updateHandlePosition_) {
535         Rect caretStart;
536         bool visible =
537             GetCaretRect(selStart, caretStart, 0.0) ? IsVisible(caretStart + textOffsetForShowCaret_) : false;
538         OverlayShowOption option { .showMenu = isOverlayShowed_,
539             .showStartHandle = visible,
540             .showEndHandle = visible,
541             .isSingleHandle = false,
542             .updateOverlayType = UpdateOverlayType::LONG_PRESS,
543             .startHandleOffset = startHandleOffset,
544             .endHandleOffset = endHandleOffset };
545         updateHandlePosition_(option);
546 
547         // When the textOverlay is showed, restart the animation
548         if (!animator_) {
549             LOGE("Show textOverlay error, animator is nullptr");
550             return;
551         }
552         if (!animator_->IsStopped()) {
553             animator_->Stop();
554         }
555         animator_->Play();
556         return;
557     }
558 
559     textOverlay_ =
560         AceType::MakeRefPtr<TextOverlayComponent>(GetThemeManager(), context_.Upgrade()->GetAccessibilityManager());
561     textOverlay_->SetWeakText(WeakClaim(this));
562     textOverlay_->SetLineHeight(selectHeight_);
563     Rect paintRect = { Offset::Zero(), GetLayoutParam().GetMaxSize() };
564     textOverlay_->SetClipRect(paintRect + Size(HANDLE_HOT_ZONE, HANDLE_HOT_ZONE) + GetOffsetToPage() -
565                               Offset(HANDLE_HOT_ZONE / 2.0, 0.0));
566     textOverlay_->SetTextDirection(defaultTextDirection_);
567     textOverlay_->SetStartHandleOffset(startHandleOffset);
568     textOverlay_->SetEndHandleOffset(endHandleOffset);
569     textOverlay_->SetContext(context_);
570     textOverlay_->SetIsUsingMouse(isUsingMouse);
571     if (isUsingMouse) {
572         textOverlay_->SetMouseOffset(showOffset);
573     }
574     // Add the Animation
575     InitAnimation(context_);
576     RegisterCallbacksToOverlay();
577     MarkNeedRender();
578 }
579 
RegisterCallbacksToOverlay()580 void RenderText::RegisterCallbacksToOverlay()
581 {
582     if (!textOverlay_) {
583         return;
584     }
585 
586     textOverlay_->SetOnCopy([weak = AceType::WeakClaim(this)] {
587         auto text = weak.Upgrade();
588         if (text) {
589             text->HandleOnCopy();
590         }
591     });
592 
593     textOverlay_->SetOnCopyAll(
594         [weak = AceType::WeakClaim(this)](const std::function<void(const Offset&, const Offset&)>& callback) {
595             auto text = weak.Upgrade();
596             if (text) {
597                 text->HandleOnCopyAll(callback);
598             }
599         });
600 
601     textOverlay_->SetOnStartHandleMove(
602         [weak = AceType::WeakClaim(this)](int32_t end, const Offset& startHandleOffset,
603             const std::function<void(const Offset&)>& startCallback, bool isSingleHandle) {
604             auto text = weak.Upgrade();
605             if (text) {
606                 text->HandleOnStartHandleMove(end, startHandleOffset, startCallback, isSingleHandle);
607             }
608         });
609 
610     textOverlay_->SetOnEndHandleMove([weak = AceType::WeakClaim(this)](int32_t start, const Offset& endHandleOffset,
611                                          const std::function<void(const Offset&)>& endCallback) {
612         auto text = weak.Upgrade();
613         if (text) {
614             text->HandleOnEndHandleMove(start, endHandleOffset, endCallback);
615         }
616     });
617 
618     auto callback = [weak = WeakClaim(this), pipelineContext = context_, textOverlay = textOverlay_](
619                         const std::string& data) {
620         auto context = pipelineContext.Upgrade();
621         if (!context) {
622             return;
623         }
624         auto textOverlayManager = context->GetTextOverlayManager();
625         if (!textOverlayManager) {
626             return;
627         }
628         textOverlayManager->PushTextOverlayToStack(textOverlay, pipelineContext);
629 
630         auto text = weak.Upgrade();
631         if (!text) {
632             return;
633         }
634         text->UpdateOverlay();
635         text->MarkIsOverlayShowed(true);
636     };
637     if (clipboard_) {
638         clipboard_->GetData(callback);
639     }
640 }
641 
UpdateOverlay()642 void RenderText::UpdateOverlay()
643 {
644     // When textfield PerformLayout, update overlay.
645     if (isOverlayShowed_ && updateHandlePosition_) {
646         auto selStart = textValue_.selection.GetStart();
647         auto selEnd = textValue_.selection.GetEnd();
648         Rect caretStart;
649         Rect caretEnd;
650         bool startHandleVisible =
651             GetCaretRect(selStart, caretStart, 0.0) ? IsVisible(caretStart + textOffsetForShowCaret_) : false;
652         bool endHandleVisible =
653             (selStart == selEnd)
654                 ? startHandleVisible
655                 : (GetCaretRect(selEnd, caretEnd, 0.0) ? IsVisible(caretEnd + textOffsetForShowCaret_) : false);
656 
657         OverlayShowOption option { .showMenu = isOverlayShowed_,
658             .showStartHandle = startHandleVisible,
659             .showEndHandle = endHandleVisible,
660             .isSingleHandle = false,
661             .updateOverlayType = UpdateOverlayType::SCROLL,
662             .startHandleOffset = GetPositionForExtend(selStart),
663             .endHandleOffset = GetPositionForExtend(selEnd) };
664         updateHandlePosition_(option);
665         if (onClipRectChanged_) {
666             Rect paintRect = { Offset::Zero(), GetLayoutParam().GetMaxSize() };
667             onClipRectChanged_(paintRect + Size(HANDLE_HOT_ZONE, HANDLE_HOT_ZONE) + GetOffsetToPage() -
668                                Offset(HANDLE_HOT_ZONE / 2.0, 0.0));
669         }
670     }
671 }
672 
GetPositionForExtend(int32_t extend)673 Offset RenderText::GetPositionForExtend(int32_t extend)
674 {
675     if (extend < 0) {
676         extend = 0;
677     }
678     if (static_cast<size_t>(extend) > StringUtils::ToWstring(textValue_.text).length()) {
679         extend = static_cast<int32_t>(StringUtils::ToWstring(textValue_.text).length());
680     }
681     return GetHandleOffset(extend);
682 }
683 
HandleOnCopy()684 void RenderText::HandleOnCopy()
685 {
686     if (!clipboard_) {
687         return;
688     }
689     if (textValue_.GetSelectedText().empty()) {
690         return;
691     }
692     clipboard_->SetData(textValue_.GetSelectedText(), copyOption_);
693 
694     auto textOverlayManager = GetTextOverlayManager(context_);
695     if (textOverlayManager) {
696         textOverlayManager->PopTextOverlay();
697     }
698     isOverlayShowed_ = false;
699     textValue_.UpdateSelection(0, 0);
700     MarkNeedRender();
701 }
702 
HandleOnCopyAll(const std::function<void (const Offset &,const Offset &)> & callback)703 void RenderText::HandleOnCopyAll(const std::function<void(const Offset&, const Offset&)>& callback)
704 {
705     auto textSize = textValue_.GetWideText().length();
706     textValue_.UpdateSelection(0, textSize);
707     if (callback) {
708         callback(GetPositionForExtend(0), GetPositionForExtend(textValue_.GetWideText().length()));
709     }
710     MarkNeedRender();
711 }
712 
HandleOnStartHandleMove(int32_t end,const Offset & startHandleOffset,const std::function<void (const Offset &)> & startCallback,bool isSingleHandle)713 void RenderText::HandleOnStartHandleMove(int32_t end, const Offset& startHandleOffset,
714     const std::function<void(const Offset&)>& startCallback, bool isSingleHandle)
715 {
716     Offset realOffset = startHandleOffset;
717     if (startCallback) {
718         UpdateStartSelection(end, realOffset, GetGlobalOffset());
719         startCallback(GetHandleOffset(textValue_.selection.GetStart()));
720     }
721     MarkNeedRender();
722 }
723 
HandleOnEndHandleMove(int32_t start,const Offset & endHandleOffset,const std::function<void (const Offset &)> & endCallback)724 void RenderText::HandleOnEndHandleMove(
725     int32_t start, const Offset& endHandleOffset, const std::function<void(const Offset&)>& endCallback)
726 {
727     Offset realOffset = endHandleOffset;
728     if (endCallback) {
729         UpdateEndSelection(start, realOffset, GetGlobalOffset());
730         endCallback(GetHandleOffset(textValue_.selection.GetEnd()));
731     }
732     MarkNeedRender();
733 }
734 
FireEvent(const EventMarker & marker)735 void RenderText::FireEvent(const EventMarker& marker)
736 {
737     if (marker.IsEmpty()) {
738         return;
739     }
740 
741     auto func = AceAsyncEvent<void()>::Create(marker, context_);
742     if (func) {
743         func();
744     }
745 }
746 
HandleTouchEvent(GestureType type,const Offset & touchPosition)747 void RenderText::HandleTouchEvent(GestureType type, const Offset& touchPosition)
748 {
749     if (type == GestureType::TOUCH_START) {
750         touchStartPosition_ = GetTouchPosition(touchPosition);
751     }
752 
753     auto eventMarker = GetEventMarker(touchStartPosition_, type);
754     if (!eventMarker.IsEmpty()) {
755         FireEvent(eventMarker);
756         return;
757     }
758 
759     // If span has not touch event, use touch event of text.
760     if (!text_) {
761         return;
762     }
763     auto declaration = text_->GetDeclaration();
764     if (!declaration) {
765         return;
766     }
767     auto& rawEvent = static_cast<CommonRawEvent&>(declaration->GetEvent(EventTag::COMMON_RAW_EVENT));
768     if (!rawEvent.IsValid()) {
769         return;
770     }
771 
772     switch (type) {
773         case GestureType::TOUCH_START:
774             eventMarker = rawEvent.touchStart.eventMarker;
775             break;
776         case GestureType::TOUCH_MOVE:
777             eventMarker = rawEvent.touchMove.eventMarker;
778             break;
779         case GestureType::TOUCH_END:
780             eventMarker = rawEvent.touchEnd.eventMarker;
781             break;
782         case GestureType::TOUCH_CANCEL:
783             eventMarker = rawEvent.touchCancel.eventMarker;
784             break;
785         default:
786             break;
787     }
788     FireEvent(eventMarker);
789 }
790 
HandleClick(const ClickInfo & info)791 void RenderText::HandleClick(const ClickInfo& info)
792 {
793     auto clickPosition = info.GetLocalLocation();
794     auto clickMarker = GetEventMarker(GetTouchPosition(clickPosition), GestureType::CLICK);
795     // If span has not click event, use click event of text.
796     if (text_ && clickMarker.IsEmpty()) {
797         auto declaration = text_->GetDeclaration();
798         if (declaration) {
799             auto& gestureEvent =
800                 static_cast<CommonGestureEvent&>(declaration->GetEvent(EventTag::COMMON_GESTURE_EVENT));
801             if (gestureEvent.IsValid() && !gestureEvent.click.eventMarker.IsEmpty()) {
802                 clickMarker = gestureEvent.click.eventMarker;
803             }
804         }
805     }
806 
807     auto onClick = AceAsyncEvent<void(const ClickInfo&)>::Create(clickMarker, context_);
808     if (onClick) {
809         onClick(info);
810     }
811 }
812 
HandleRemoteMessage(const ClickInfo & info)813 void RenderText::HandleRemoteMessage(const ClickInfo& info)
814 {
815     auto clickPosition = info.GetLocalLocation();
816     auto clickMarker = GetEventMarker(GetTouchPosition(clickPosition), GestureType::REMOTE_MESSAGE);
817     // If span has not click event, use click event of text.
818     if (text_ && clickMarker.IsEmpty()) {
819         auto declaration = text_->GetDeclaration();
820         if (declaration) {
821             auto& gestureEvent =
822                 static_cast<CommonGestureEvent&>(declaration->GetEvent(EventTag::COMMON_REMOTE_MESSAGE_GESTURE_EVENT));
823             if (gestureEvent.IsValid() && !gestureEvent.click.eventMarker.IsEmpty()) {
824                 clickMarker = gestureEvent.click.eventMarker;
825             }
826         }
827     }
828 
829     auto remoteMessage = AceAsyncEvent<void(const ClickInfo&)>::Create(clickMarker, context_);
830     if (remoteMessage) {
831         remoteMessage(info);
832     }
833 }
834 
HandleLongPress(const Offset & longPressPosition)835 void RenderText::HandleLongPress(const Offset& longPressPosition)
836 {
837     auto longPressMarker = GetEventMarker(GetTouchPosition(longPressPosition), GestureType::LONG_PRESS);
838     // If span has not long press event, use long press event of text.
839     if (text_ && longPressMarker.IsEmpty()) {
840         auto declaration = text_->GetDeclaration();
841         if (declaration) {
842             auto& gestureEvent =
843                 static_cast<CommonGestureEvent&>(declaration->GetEvent(EventTag::COMMON_GESTURE_EVENT));
844             if (gestureEvent.IsValid() && !gestureEvent.longPress.eventMarker.IsEmpty()) {
845                 longPressMarker = gestureEvent.longPress.eventMarker;
846             }
847         }
848     }
849 
850     FireEvent(longPressMarker);
851 }
852 
GetEventMarker(int32_t position,GestureType type)853 EventMarker RenderText::GetEventMarker(int32_t position, GestureType type)
854 {
855     if (touchRegions_.empty()) {
856         return EventMarker();
857     }
858     for (const auto& region : touchRegions_) {
859         if (position < region.first) {
860             auto markerIter = region.second.find(type);
861             if (markerIter != region.second.end()) {
862                 return markerIter->second;
863             }
864             return EventMarker();
865         }
866     }
867     return EventMarker();
868 }
869 
OnStatusChanged(OHOS::Ace::RenderStatus renderStatus)870 void RenderText::OnStatusChanged(OHOS::Ace::RenderStatus renderStatus)
871 {
872     auto context = context_.Upgrade();
873     if (context && context->GetIsDeclarative()) {
874         return;
875     }
876 
877     if (renderStatus == RenderStatus::FOCUS) {
878         textStyle_.SetTextColor(focusColor_);
879         isFocus_ = true;
880     } else {
881         textStyle_.SetTextColor(lostFocusColor_);
882         isFocus_ = false;
883     }
884     needMeasure_ = true;
885     Measure();
886     MarkNeedRender();
887 }
888 
CheckIfNeedMeasure()889 void RenderText::CheckIfNeedMeasure()
890 {
891     if (!text_) {
892         return;
893     }
894 
895     if (text_->IsChanged()) {
896         needMeasure_ = true;
897     }
898     UpdateIfChanged(defaultTextDirection_, text_->GetTextDirection());
899     realTextDirection_ = defaultTextDirection_;
900     UpdateIfChanged(textStyle_, text_->GetTextStyle());
901     UpdateIfChanged(focusColor_, text_->GetFocusColor());
902     UpdateIfChanged(lostFocusColor_, textStyle_.GetTextColor());
903     UpdateIfChanged(maxLines_, textStyle_.GetMaxLines());
904     if (needMeasure_) {
905         MarkNeedLayout();
906     }
907 }
908 
GetTextData() const909 std::string RenderText::GetTextData() const
910 {
911     return text_ ? text_->GetData() : "";
912 }
913 
SetTextData(const std::string & textData)914 void RenderText::SetTextData(const std::string& textData)
915 {
916     if (text_) {
917         text_->SetData(textData);
918     }
919 }
920 
ClearRenderObject()921 void RenderText::ClearRenderObject()
922 {
923     RenderNode::ClearRenderObject();
924     text_.Reset();
925     textStyle_ = TextStyle();
926     defaultTextDirection_ = TextDirection::LTR;
927     focusColor_ = Color();
928     lostFocusColor_ = Color();
929     fontScale_ = 1.0;
930     dipScale_ = 1.0;
931     isFocus_ = false;
932     needMeasure_ = true;
933     isCallbackCalled_ = false;
934 }
935 
GetContentSize()936 Size RenderText::GetContentSize()
937 {
938     if (textStyle_.GetAdaptTextSize()) {
939         return Size();
940     }
941     // Make sure text's height is not clipped, width is not guard.
942     auto measuredSize = Measure();
943     if (textStyle_.GetTextOverflow() != TextOverflow::NONE || maxLines_ > 1) {
944         measuredSize.SetWidth(0.0);
945     }
946     return measuredSize;
947 }
948 
GetComponent()949 RefPtr<Component> RenderText::GetComponent()
950 {
951     return text_;
952 }
953 
GetSelectedContent() const954 std::string RenderText::GetSelectedContent() const
955 {
956     return textValue_.GetSelectedText();
957 }
958 
Dump()959 void RenderText::Dump()
960 {
961     DumpLog::GetInstance().AddDesc(std::string("Data: ").append(text_->GetData()));
962     DumpLog::GetInstance().AddDesc(std::string("FontColor: ").append(textStyle_.GetTextColor().ColorToString()));
963     DumpLog::GetInstance().AddDesc(std::string("FontSize: ").append(textStyle_.GetFontSize().ToString()));
964     DumpLog::GetInstance().AddDesc(
965         std::string("FontStyle: ").append(V2::ConvertWrapFontStyleToStirng(textStyle_.GetFontStyle())));
966     DumpLog::GetInstance().AddDesc(
967         std::string("FontWeight: ").append(V2::ConvertWrapFontWeightToStirng(textStyle_.GetFontWeight())));
968     std::string fontFamilies;
969     for (const auto& family : textStyle_.GetFontFamilies()) {
970         fontFamilies += family;
971         fontFamilies += ",";
972     }
973     DumpLog::GetInstance().AddDesc(std::string("FontFamily: ").append(fontFamilies));
974     DumpLog::GetInstance().AddDesc(std::string("CopyOptions: ").append(V2::ConvertWrapCopyOptionToString(copyOption_)));
975 }
976 
GenerateDragItemInfo(const RefPtr<PipelineContext> & context,const GestureEvent & info)977 DragItemInfo RenderText::GenerateDragItemInfo(const RefPtr<PipelineContext>& context, const GestureEvent& info)
978 {
979     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
980     event->SetX(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
981     event->SetY(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
982     selectedItemSize_ = GetLayoutSize();
983     auto extraParams = JsonUtil::Create(true);
984 
985     return onDragStart_(event, extraParams->ToString());
986 }
987 
PanOnActionStart(const GestureEvent & info)988 void RenderText::PanOnActionStart(const GestureEvent& info)
989 {
990     if (!onDragStart_) {
991         return;
992     }
993     auto pipelineContext = context_.Upgrade();
994     if (!pipelineContext) {
995         LOGE("Context is null.");
996         return;
997     }
998 
999     GestureEvent newInfo = info;
1000     Point newPoint = UpdatePoint(pipelineContext, startPoint_);
1001     newInfo.SetGlobalPoint(newPoint);
1002     auto dragItemInfo = GenerateDragItemInfo(pipelineContext, newInfo);
1003 #if !defined(PREVIEW)
1004     if (!dragItemInfo.pixelMap && !dragItemInfo.customComponent) {
1005         auto initRenderNode = AceType::Claim(this);
1006         isDragDropNode_ = true;
1007         pipelineContext->SetInitRenderNode(initRenderNode);
1008 
1009         AddDataToClipboard(pipelineContext, dragItemInfo.extraInfo, textValue_.GetSelectedText(), "");
1010         if (!dragWindow_) {
1011             auto rect = pipelineContext->GetCurrentWindowRect();
1012             dragWindow_ = DragWindow::CreateDragWindow("APP_DRAG_WINDOW",
1013                 static_cast<int32_t>(info.GetGlobalPoint().GetX() + rect.Left()),
1014                 static_cast<int32_t>(info.GetGlobalPoint().GetY() + rect.Top()),
1015                 static_cast<int32_t>(GetPaintRect().Width()),
1016                 static_cast<int32_t>(GetPaintRect().Height()));
1017             dragWindow_->SetOffset(static_cast<int32_t>(rect.Left()), static_cast<int32_t>(rect.Top()));
1018             dragWindow_->DrawText(paragraph_, GetPaintRect().GetOffset(), initRenderNode);
1019         }
1020         if (dragWindow_) {
1021             AceEngineExt::GetInstance().DragStartExt();
1022         }
1023         return;
1024     }
1025 
1026     if (dragItemInfo.pixelMap) {
1027         auto initRenderNode = AceType::Claim(this);
1028         isDragDropNode_ = true;
1029         pipelineContext->SetInitRenderNode(initRenderNode);
1030 
1031         AddDataToClipboard(pipelineContext, dragItemInfo.extraInfo, textValue_.GetSelectedText(), "");
1032         if (!dragWindow_) {
1033             auto rect = pipelineContext->GetCurrentWindowRect();
1034             dragWindow_ = DragWindow::CreateDragWindow("APP_DRAG_WINDOW",
1035                 static_cast<int32_t>(info.GetGlobalPoint().GetX()) + rect.Left(),
1036                 static_cast<int32_t>(info.GetGlobalPoint().GetY()) + rect.Top(), dragItemInfo.pixelMap->GetWidth(),
1037                 dragItemInfo.pixelMap->GetHeight());
1038             dragWindow_->SetOffset(rect.Left(), rect.Top());
1039             dragWindow_->DrawPixelMap(dragItemInfo.pixelMap);
1040         }
1041         if (dragWindow_) {
1042             AceEngineExt::GetInstance().DragStartExt();
1043         }
1044         return;
1045     }
1046 #endif
1047     if (!dragItemInfo.customComponent) {
1048         LOGW("the drag custom component is null");
1049         return;
1050     }
1051 
1052     hasDragItem_ = true;
1053     auto positionedComponent = AceType::MakeRefPtr<PositionedComponent>(dragItemInfo.customComponent);
1054     positionedComponent->SetTop(Dimension(GetGlobalOffset().GetY()));
1055     positionedComponent->SetLeft(Dimension(GetGlobalOffset().GetX()));
1056     SetLocalPoint(startPoint_ - GetGlobalOffset());
1057     auto updatePosition = [renderBox = AceType::Claim(this)](
1058                               const std::function<void(const Dimension&, const Dimension&)>& func) {
1059         if (!renderBox) {
1060             return;
1061         }
1062         renderBox->SetUpdateBuilderFuncId(func);
1063     };
1064     positionedComponent->SetUpdatePositionFuncId(updatePosition);
1065     auto stackElement = pipelineContext->GetLastStack();
1066     stackElement->PushComponent(positionedComponent);
1067 }
1068 
PanOnActionUpdate(const GestureEvent & info)1069 void RenderText::PanOnActionUpdate(const GestureEvent& info)
1070 {
1071 #if !defined(PREVIEW)
1072     if (isDragDropNode_ && dragWindow_) {
1073         int32_t x = static_cast<int32_t>(info.GetGlobalPoint().GetX());
1074         int32_t y = static_cast<int32_t>(info.GetGlobalPoint().GetY());
1075         if (lastDragMoveOffset_ == Offset(x, y)) {
1076             return;
1077         }
1078         lastDragMoveOffset_ = Offset(x, y);
1079         if (dragWindow_) {
1080             dragWindow_->MoveTo(x, y);
1081         }
1082         return;
1083     }
1084 #endif
1085     auto pipelineContext = context_.Upgrade();
1086     if (!pipelineContext) {
1087         LOGE("Context is null.");
1088         return;
1089     }
1090 
1091     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1092     event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1093     event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1094 
1095     Offset offset = info.GetGlobalPoint() - GetLocalPoint();
1096     if (GetUpdateBuilderFuncId()) {
1097         GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY()));
1098     }
1099 
1100     auto extraParams = JsonUtil::Create(true);
1101     auto targetDragDropNode = FindDragDropNode(pipelineContext, info);
1102     auto preDragDropNode = GetPreDragDropNode();
1103     if (preDragDropNode == targetDragDropNode) {
1104         if (targetDragDropNode && targetDragDropNode->GetOnDragMove()) {
1105             (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
1106         }
1107         return;
1108     }
1109     if (preDragDropNode && preDragDropNode->GetOnDragLeave()) {
1110         (preDragDropNode->GetOnDragLeave())(event, extraParams->ToString());
1111     }
1112     if (targetDragDropNode && targetDragDropNode->GetOnDragEnter()) {
1113         (targetDragDropNode->GetOnDragEnter())(event, extraParams->ToString());
1114     }
1115     SetPreDragDropNode(targetDragDropNode);
1116 }
1117 
PanOnActionEnd(const GestureEvent & info)1118 void RenderText::PanOnActionEnd(const GestureEvent& info)
1119 {
1120     auto pipelineContext = context_.Upgrade();
1121     if (!pipelineContext) {
1122         LOGE("Context is null.");
1123         return;
1124     }
1125 #if !defined(PREVIEW)
1126     if (isDragDropNode_) {
1127         isDragDropNode_ = false;
1128 
1129         if (GetOnDrop()) {
1130             RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1131             RefPtr<PasteData> pasteData = AceType::MakeRefPtr<PasteData>();
1132             event->SetPasteData(pasteData);
1133             event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1134             event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1135 
1136             auto extraParams = JsonUtil::Create(true);
1137             (GetOnDrop())(event, extraParams->ToString());
1138             pipelineContext->SetInitRenderNode(nullptr);
1139         }
1140 
1141         auto textfield = FindTargetRenderNode<RenderTextField>(context_.Upgrade(), info);
1142         if (textfield) {
1143             auto value = textfield->GetEditingValue();
1144             value.Append(textValue_.GetSelectedText());
1145             textfield->SetEditingValue(std::move(value));
1146         }
1147         if (info.GetSourceDevice() == SourceType::TOUCH) {
1148             textValue_.UpdateSelection(0, 0);
1149         }
1150         RestoreCilpboardData(pipelineContext);
1151     }
1152 
1153     if (dragWindow_) {
1154         dragWindow_->Destroy();
1155         dragWindow_ = nullptr;
1156         return;
1157     }
1158 #endif
1159     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1160     RefPtr<PasteData> pasteData = AceType::MakeRefPtr<PasteData>();
1161     event->SetPasteData(pasteData);
1162     event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1163     event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1164 
1165     Offset offset = info.GetGlobalPoint() - GetLocalPoint();
1166     if (GetUpdateBuilderFuncId()) {
1167         GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY()));
1168     }
1169     if (hasDragItem_) {
1170         auto stackElement = pipelineContext->GetLastStack();
1171         stackElement->PopComponent();
1172     }
1173     hasDragItem_ = false;
1174 
1175     ACE_DCHECK(GetPreDragDropNode() == FindTargetRenderNode<DragDropEvent>(pipelineContext, info));
1176     auto targetDragDropNode = GetPreDragDropNode();
1177     if (!targetDragDropNode) {
1178         return;
1179     }
1180     if (targetDragDropNode->GetOnDrop()) {
1181         auto extraParams = JsonUtil::Create(true);
1182         (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
1183     }
1184     SetPreDragDropNode(nullptr);
1185 }
1186 
PanOnActionCancel()1187 void RenderText::PanOnActionCancel()
1188 {
1189     auto pipelineContext = context_.Upgrade();
1190     if (!pipelineContext) {
1191         LOGE("Context is null.");
1192         return;
1193     }
1194 
1195 #if !defined(PREVIEW)
1196     if (isDragDropNode_) {
1197         isDragDropNode_ = false;
1198         RestoreCilpboardData(pipelineContext);
1199     }
1200 
1201     if (dragWindow_) {
1202         dragWindow_->Destroy();
1203         dragWindow_ = nullptr;
1204     }
1205 #endif
1206     if (hasDragItem_) {
1207         auto stackElement = pipelineContext->GetLastStack();
1208         stackElement->PopComponent();
1209         hasDragItem_ = false;
1210     }
1211     SetPreDragDropNode(nullptr);
1212 }
1213 
CreateSelectRecognizer()1214 void RenderText::CreateSelectRecognizer()
1215 {
1216     if (selectRecognizer_) {
1217         return;
1218     }
1219 
1220     auto context = context_.Upgrade();
1221     if (!context) {
1222         return;
1223     }
1224 
1225     PanDirection panDirection;
1226     selectRecognizer_ = AceType::MakeRefPtr<OHOS::Ace::PanRecognizer>(context, 1, panDirection, 0);
1227     selectRecognizer_->SetOnActionStart([weak = WeakClaim(this), context = context_](const GestureEvent& info) {
1228         if (info.GetSourceDevice() != SourceType::MOUSE) {
1229             return;
1230         }
1231 
1232         auto text = weak.Upgrade();
1233         if (text) {
1234             text->HideTextOverlay();
1235             auto textOverlayManager = text->GetTextOverlayManager(context);
1236             if (textOverlayManager) {
1237                 textOverlayManager->SetTextOverlayBase(weak);
1238             }
1239             Offset offset(info.GetGlobalPoint().GetX(), info.GetGlobalPoint().GetY());
1240             text->InitSelection(offset, text->GetGlobalOffset());
1241         }
1242     });
1243     selectRecognizer_->SetOnActionUpdate([weak = WeakClaim(this), context = context_](const GestureEvent& info) {
1244         if (info.GetSourceDevice() != SourceType::MOUSE) {
1245             return;
1246         }
1247 
1248         auto text = weak.Upgrade();
1249         if (text) {
1250             Offset offset(info.GetGlobalPoint().GetX(), info.GetGlobalPoint().GetY());
1251             text->UpdateEndSelection(text->GetTextSelect().baseOffset, offset, text->GetGlobalOffset());
1252             text->SetStartOffset(text->GetHandleOffset(text->GetTextSelect().GetStart()));
1253             text->SetEndOffset(text->GetHandleOffset(text->GetTextSelect().GetEnd()));
1254             text->UpdateTextOverlay();
1255         }
1256     });
1257 }
1258 
1259 } // namespace OHOS::Ace
1260