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