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