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_v2/indexer/render_indexer.h"
17
18 #include "base/log/event_report.h"
19 #include "core/components/arc/render_arc.h"
20 #include "core/components/text/render_text.h"
21
22 namespace OHOS::Ace::V2 {
23 namespace {
24 constexpr Dimension FOCUS_PADDING = 2.0_vp;
25 constexpr int32_t PADDING_SIZE = 2;
26 } // namespace
27
Create()28 RefPtr<RenderNode> RenderIndexer::Create()
29 {
30 return AceType::MakeRefPtr<RenderIndexer>();
31 }
32
RenderIndexer()33 RenderIndexer::RenderIndexer()
34 {
35 touchRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
36 touchRecognizer_->SetOnTouchDown([wp = AceType::WeakClaim(this)](const TouchEventInfo& info) {
37 auto sp = wp.Upgrade();
38 if (sp) {
39 sp->HandleTouchDown(info);
40 }
41 });
42 touchRecognizer_->SetOnTouchUp([wp = AceType::WeakClaim(this)](const TouchEventInfo& info) {
43 auto sp = wp.Upgrade();
44 if (sp) {
45 sp->HandleTouchUp(info);
46 }
47 });
48 touchRecognizer_->SetOnTouchMove([wp = AceType::WeakClaim(this)](const TouchEventInfo& info) {
49 auto sp = wp.Upgrade();
50 if (sp) {
51 sp->HandleTouchMove(info);
52 }
53 });
54 }
55
Update(const RefPtr<Component> & component)56 void RenderIndexer::Update(const RefPtr<Component>& component)
57 {
58 RefPtr<IndexerComponent> indexerComponent = AceType::DynamicCast<IndexerComponent>(component);
59 if (!indexerComponent) {
60 LOGE("[indexer] Update Get component failed");
61 EventReport::SendRenderException(RenderExcepType::RENDER_COMPONENT_ERR);
62 return;
63 }
64 nonItemCount_ = indexerComponent->GetNonItemCount();
65 bubbleEnabled_ = indexerComponent->IsBubbleEnabled();
66 popupListEnabled_ = indexerComponent->IsPopupListEnabled();
67 bubbleText_ = indexerComponent->GetBubbleTextComponent();
68 focusedItem_ = indexerComponent->GetSelectedIndex();
69 alignStyle_ = indexerComponent->GetAlignStyle();
70 color_ = indexerComponent->GetBubbleBackgroundColor();
71 valueArray_ = indexerComponent->GetLabel();
72
73 // update item information
74 auto context = GetContext().Upgrade();
75 if (context) {
76 itemSize_ = context->NormalizeToPx(indexerComponent->GetItemSize());
77 }
78 itemSizeRender_ = itemSize_;
79 itemCount_ = indexerComponent->GetItemCount();
80 LOGI("[indexer] Init data, itemSizeRender_:%{public}lf, itemCount_:%{public}d", itemSizeRender_, itemCount_);
81
82 if (IsValidBubbleBox() && !bubbleBox_->GetChildren().empty()) {
83 auto text = AceType::DynamicCast<RenderText>(bubbleBox_->GetChildren().front());
84 auto item = GetSpecificItem(focusedItem_);
85 if (bubbleText_ && text && item) {
86 bubbleText_->SetData(item->GetSectionText());
87 text->Update(bubbleText_);
88 text->PerformLayout();
89 }
90 }
91 MarkNeedLayout();
92 selectedEventFun_ = AceSyncEvent<void(const std::shared_ptr<IndexerEventInfo>&)>::
93 Create(indexerComponent->GetSelectedEvent(), context_);
94 requestPopupDataEventFun_ = indexerComponent->GetRequestPopupDataFunc();
95 }
96
PerformLayout()97 void RenderIndexer::PerformLayout()
98 {
99 UpdateItems();
100 if (itemCount_ <= 0) {
101 SetLayoutSize(Size());
102 return;
103 }
104
105 // calculate self and children size,
106 if (NearZero(itemSize_)) {
107 LOGE("[indexer] Invalid Item size:%{public}lf", itemSize_);
108 return;
109 }
110
111 // calculate the size of the items
112 const LayoutParam& layoutSetByParent = GetLayoutParam();
113 Size sizeMax = layoutSetByParent.GetMaxSize();
114 if (LessOrEqual(paddingY_ * DOUBLE + itemCount_ * itemSize_, sizeMax.Height())) {
115 itemSizeRender_ = itemSize_;
116 } else {
117 itemSizeRender_ = (sizeMax.Height() - paddingY_ * DOUBLE) / itemCount_;
118 }
119
120 InitFocusedItem();
121 LayoutParam childrenLayout;
122 childrenLayout.SetMinSize(Size(0.0, 0.0));
123 for (const auto& item : GetChildren()) {
124 item->Layout(childrenLayout);
125 }
126
127 // then set the position of children
128 Offset position;
129 int32_t count = 0;
130 for (const auto& item : GetChildren()) {
131 if (!AceType::InstanceOf<RenderIndexerItem>(item)) {
132 continue;
133 }
134 position.SetX(paddingX_);
135 position.SetY(paddingY_ + count * itemSizeRender_);
136 item->SetPosition(position);
137 count++;
138 }
139
140 double indexerWidth = paddingX_ + itemSizeRender_ + paddingX_;
141 double indexerHeight = paddingY_ + count * itemSizeRender_ + paddingY_;
142 SetLayoutSize(Size(indexerWidth, indexerHeight));
143 // layout bubble and popup list.
144 LayoutPopup();
145 }
146
UpdateItems()147 void RenderIndexer::UpdateItems()
148 {
149 if (nonItemCount_ + static_cast<int32_t>(items_.size()) == static_cast<int32_t>(GetChildren().size())) {
150 LOGI("[indexer] no need update Items");
151 return;
152 }
153 items_.clear();
154 for (auto item : GetChildren()) {
155 if (AceType::InstanceOf<RenderIndexerItem>(item)) {
156 items_.push_back(item);
157 }
158 }
159 LOGI("[indexer] items nums : %{public}d", static_cast<int32_t>(items_.size()));
160 }
161
InitFocusedItem()162 void RenderIndexer::InitFocusedItem()
163 {
164 for (auto item : items_) {
165 RefPtr<RenderIndexerItem> indexerItem = AceType::DynamicCast<RenderIndexerItem>(item);
166 if (indexerItem) {
167 indexerItem->SetClicked(false);
168 }
169 }
170
171 if (focusedItem_ >= 0) {
172 auto item = GetSpecificItem(focusedItem_);
173 if (item) {
174 item->SetClicked(true);
175 }
176 }
177 }
178
LayoutPopup()179 void RenderIndexer::LayoutPopup()
180 {
181 if (IsValidBubbleBox()) {
182 Offset bubblePosition;
183 if (alignStyle_ == AlignStyle::RIGHT) {
184 bubblePosition.SetX(NormalizeToPx(-BUBBLE_POSITION_X) - bubbleDisplay_->GetLayoutSize().Width());
185 bubblePosition.SetY(NormalizeToPx(BUBBLE_POSITION_Y));
186 } else {
187 bubblePosition.SetX(NormalizeToPx(BUBBLE_POSITION_X) + GetLayoutSize().Width());
188 bubblePosition.SetY(NormalizeToPx(BUBBLE_POSITION_Y));
189 }
190
191 bubbleDisplay_->SetPosition(bubblePosition);
192 #ifdef ENABLE_ROSEN_BACKEND
193 bubbleDisplay_->SetPaintOutOfParent(true);
194 #endif
195 }
196
197 if (IsValidPopupList()) {
198 Offset popupPosition;
199 popupPosition.SetX(bubbleDisplay_->GetPosition().GetX());
200 popupPosition.SetY(bubbleDisplay_->GetPosition().GetY() + bubbleDisplay_->GetLayoutSize().Height());
201 popupListDisplay_->SetPosition(popupPosition);
202 #ifdef ENABLE_ROSEN_BACKEND
203 popupListDisplay_->SetPaintOutOfParent(true);
204 #endif
205 }
206 }
207
HandleTouchDown(const TouchEventInfo & info)208 void RenderIndexer::HandleTouchDown(const TouchEventInfo& info)
209 {
210 if (touchBubbleDisplay || touchPopupListDisplay) {
211 LOGI("touch down bubble or popup list.");
212 if (IsValidBubbleBox()) {
213 bubbleDisplay_->UpdateOpacity(DEFAULT_OPACITY);
214 }
215
216 if (IsValidPopupList()) {
217 popupListDisplay_->UpdateOpacity(DEFAULT_OPACITY);
218 }
219
220 if (bubbleController_) {
221 bubbleController_->Pause();
222 }
223 return;
224 }
225
226 if (info.GetTouches().empty()) {
227 return;
228 }
229
230 touchPostion_ = info.GetTouches().front().GetLocalLocation();
231 LOGI("[indexer] item is HandleTouchDown x:%{public}lf, y:%{public}lf", touchPostion_.GetX(), touchPostion_.GetY());
232 HandleTouched(touchPostion_);
233 clicked_ = true;
234
235 MarkNeedLayout();
236 }
237
HandleTouchUp(const TouchEventInfo & info)238 void RenderIndexer::HandleTouchUp(const TouchEventInfo& info)
239 {
240 if ((touchBubbleDisplay || touchPopupListDisplay) && bubbleController_) {
241 LOGI("touch up bubble or popup list.");
242 bubbleController_->UpdatePlayedTime(0);
243 bubbleController_->Resume();
244 return;
245 }
246
247 if (info.GetTouches().empty()) {
248 return;
249 }
250
251 touchPostion_ = info.GetTouches().front().GetLocalLocation();
252 LOGI("[indexer] item is HandleTouchUp x:%{public}lf, y:%{public}lf", touchPostion_.GetX(), touchPostion_.GetY());
253 HandleTouched(touchPostion_);
254 if (clicked_) {
255 clicked_ = false;
256 MarkNeedLayout();
257 }
258 }
259
HandleTouchMove(const TouchEventInfo & info)260 void RenderIndexer::HandleTouchMove(const TouchEventInfo& info)
261 {
262 if (touchBubbleDisplay || touchPopupListDisplay) {
263 return;
264 }
265
266 if (info.GetTouches().empty()) {
267 return;
268 }
269
270 touchPostion_ = info.GetTouches().front().GetLocalLocation();
271 LOGI("[indexer] item is HandleTouchMove x:%{public}lf, y:%{public}lf", touchPostion_.GetX(), touchPostion_.GetY());
272 HandleTouched(touchPostion_);
273 if (clicked_) {
274 clicked_ = true;
275 MarkNeedLayout();
276 }
277 }
278
TouchTest(const Point & globalPoint,const Point & parentLocalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result)279 bool RenderIndexer::TouchTest(const Point& globalPoint, const Point& parentLocalPoint,
280 const TouchRestrict& touchRestrict, TouchTestResult& result)
281 {
282 if (GetDisableTouchEvent() || disabled_) {
283 return false;
284 }
285 auto focusedNode = GetSpecificItem(focusedItem_);
286 if (focusedNode) {
287 focusedNode->SetFocused(false);
288 }
289
290 // reset touch flag
291 touchBubbleDisplay = false;
292 touchPopupListDisplay = false;
293 Rect bubbleRect;
294 Rect popupListRect;
295
296 auto isBubbleRect = GetBubbleRect(bubbleRect);
297 if (!isBubbleRect) {
298 LOGW("bubble rect wrong.");
299 }
300
301 auto isPopupListRect = GetPopupListRect(popupListRect);
302 if (!isPopupListRect) {
303 LOGW("popup list rect wrong.");
304 }
305
306 // Since the paintRect is relative to parent, use parent local point to perform touch test.
307 if (GetPaintRect().IsInRegion(parentLocalPoint)) {
308 LOGI("touch in indexer");
309
310 // Calculates the local point location and coordinate offset in this node.
311 const auto localPoint = parentLocalPoint - GetPaintRect().GetOffset();
312 const auto coordinateOffset = globalPoint - localPoint;
313 globalPoint_ = globalPoint;
314 OnTouchTestHit(coordinateOffset, touchRestrict, result);
315 return true;
316 } else if (isBubbleRect && bubbleRect.IsInRegion(globalPoint)) {
317 LOGI("touch in bubble display");
318 touchBubbleDisplay = true;
319
320 // Calculates the local point location and coordinate offset in bubble.
321 const auto localPoint = parentLocalPoint - GetPaintRect().GetOffset();
322 const auto coordinateOffset = globalPoint - localPoint;
323 globalPoint_ = globalPoint;
324 OnTouchTestHit(coordinateOffset, touchRestrict, result);
325 return RenderNode::TouchTest(globalPoint, parentLocalPoint, touchRestrict, result);
326 } else if (isPopupListRect && popupListRect.IsInRegion(globalPoint)) {
327 LOGI("touch in popupList display");
328 touchPopupListDisplay = true;
329
330 // Calculates the local point location and coordinate offset in bubble.
331 const auto localPoint = parentLocalPoint - GetPaintRect().GetOffset();
332 const auto coordinateOffset = globalPoint - localPoint;
333 globalPoint_ = globalPoint;
334 OnTouchTestHit(coordinateOffset, touchRestrict, result);
335 return RenderNode::TouchTest(globalPoint, parentLocalPoint, touchRestrict, result);
336 } else {
337 LOGI("touch in other display");
338 if (IsValidBubbleBox() && bubbleController_ && bubbleController_->IsRunning()) {
339 bubbleController_->Finish();
340 }
341 }
342 return false;
343 }
344
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)345 void RenderIndexer::OnTouchTestHit(
346 const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
347 {
348 if (touchRecognizer_) {
349 touchRecognizer_->SetCoordinateOffset(coordinateOffset);
350 result.emplace_back(touchRecognizer_);
351 }
352 }
353
HandleTouched(const Offset & touchPosition)354 void RenderIndexer::HandleTouched(const Offset& touchPosition)
355 {
356 int32_t index = GetTouchedItemIndex(touchPosition);
357 if (index > -1) {
358 MoveSectionWithIndexer(index);
359 }
360 }
361
GetTouchedItemIndex(const Offset & touchPosition)362 int32_t RenderIndexer::GetTouchedItemIndex(const Offset& touchPosition)
363 {
364 double position = touchPosition.GetY();
365 if (position < paddingY_) {
366 return -1;
367 }
368
369 if (NearZero(itemSizeRender_)) {
370 LOGE("[indexer] Invalid Item size:%{public}lf", itemSizeRender_);
371 return -1;
372 }
373
374 int32_t index = static_cast<int32_t>((position - paddingY_) / itemSizeRender_);
375 LOGI("[indexer] GetTouchedItemIndex section index:%{public}d", index);
376 return GetItemIndex(index);
377 }
378
UpdateBubbleText()379 void RenderIndexer::UpdateBubbleText()
380 {
381 if (IsValidBubbleBox() && !bubbleBox_->GetChildren().empty()) {
382 // update bubble border
383 RefPtr<Decoration> decoration = bubbleBox_->GetBackDecoration();
384 Border border = decoration->GetBorder();
385 Radius radius;
386 if (popupListEnabled_) {
387 radius = Radius(Dimension(ZERO_RADIUS, DimensionUnit::VP));
388 } else {
389 radius = Radius(Dimension(BUBBLE_BOX_RADIUS, DimensionUnit::VP));
390 }
391 border.SetBottomLeftRadius(radius);
392 border.SetBottomRightRadius(radius);
393 decoration->SetBorder(border);
394
395 auto text = AceType::DynamicCast<RenderText>(bubbleBox_->GetChildren().front());
396 auto item = GetSpecificItem(focusedItem_);
397 if (bubbleText_ && text && item) {
398 bubbleText_->SetData(item->GetSectionText());
399 text->Update(bubbleText_);
400 text->PerformLayout();
401 BeginBubbleAnimation();
402 }
403 }
404 }
405
BuildBubbleAnimation()406 void RenderIndexer::BuildBubbleAnimation()
407 {
408 if (!IsValidBubbleBox()) {
409 LOGI("bubble box is invalid");
410 return;
411 }
412 if (!bubbleController_) {
413 bubbleController_ = CREATE_ANIMATOR(GetContext());
414 }
415 bubbleController_->ClearInterpolators();
416 bubbleController_->ClearAllListeners();
417 auto weak = AceType::WeakClaim(this);
418 bubbleController_->AddStopListener([weak]() {
419 auto indexer = weak.Upgrade();
420 if (!indexer) {
421 return;
422 }
423
424 if (indexer->IsValidBubbleBox()) {
425 indexer->bubbleDisplay_->UpdateOpacity(ZERO_OPACITY);
426 }
427
428 if (indexer->IsValidPopupList()) {
429 indexer->popupListDisplay_->UpdateOpacity(ZERO_OPACITY);
430 }
431 });
432
433 // build and start animation
434 auto animation = AceType::MakeRefPtr<KeyframeAnimation<uint8_t>>();
435 auto startFrame = AceType::MakeRefPtr<Keyframe<uint8_t>>(KEYFRAME_BEGIN, DEFAULT_OPACITY);
436 auto midFrame = AceType::MakeRefPtr<Keyframe<uint8_t>>(KEYFRAME_HALF, DEFAULT_OPACITY);
437 auto endFrame = AceType::MakeRefPtr<Keyframe<uint8_t>>(KEYFRAME_END, ZERO_OPACITY);
438 midFrame->SetCurve(Curves::DECELE);
439 endFrame->SetCurve(Curves::DECELE);
440 animation->AddKeyframe(startFrame);
441 animation->AddKeyframe(midFrame);
442 animation->AddKeyframe(endFrame);
443 animation->AddListener([weak](uint8_t value) {
444 auto indexer = weak.Upgrade();
445 if (!indexer) {
446 LOGW("indexer error %s", AceType::TypeName(indexer));
447 return;
448 }
449
450 if (indexer->IsValidBubbleBox()) {
451 indexer->bubbleDisplay_->UpdateOpacity(value);
452 }
453
454 // add popup list animation
455 if (indexer->IsValidPopupList()) {
456 indexer->popupListDisplay_->UpdateOpacity(value);
457 }
458 });
459
460 bubbleController_->AddInterpolator(animation);
461 bubbleController_->SetDuration(INDEXER_BUBBLE_ANIMATION_DURATION);
462 }
463
BeginBubbleAnimation()464 void RenderIndexer::BeginBubbleAnimation()
465 {
466 if (!IsValidBubbleBox()) {
467 LOGI("bubble box is invalid");
468 return;
469 }
470 if (!bubbleController_) {
471 BuildBubbleAnimation();
472 }
473 if (bubbleController_->IsRunning()) {
474 bubbleController_->Finish();
475 }
476 bubbleController_->Play();
477 }
478
IsValidBubbleBox()479 bool RenderIndexer::IsValidBubbleBox()
480 {
481 if (!bubbleEnabled_ || GetChildren().empty()) {
482 return false;
483 }
484 if (!bubbleDisplay_) {
485 bubbleDisplay_ = AceType::DynamicCast<RenderDisplay>(GetChildren().front());
486 if (!bubbleDisplay_ || bubbleDisplay_->GetChildren().empty()) {
487 return false;
488 }
489 bubbleBox_ = AceType::DynamicCast<RenderBox>(bubbleDisplay_->GetChildren().front());
490 if (!bubbleBox_) {
491 return false;
492 }
493 }
494 return true;
495 }
496
IsValidPopupList()497 bool RenderIndexer::IsValidPopupList()
498 {
499 if (!bubbleEnabled_ || !popupListEnabled_ || GetChildren().empty()) {
500 return false;
501 }
502 if (!popupListDisplay_) {
503 popupListDisplay_ = AceType::DynamicCast<RenderDisplay>(GetChildren().back());
504 if (!popupListDisplay_ || popupListDisplay_->GetChildren().empty()) {
505 return false;
506 }
507 popupList_ = AceType::DynamicCast<RenderPopupList>(popupListDisplay_->GetChildren().front());
508 if (!popupList_) {
509 return false;
510 }
511 }
512 return true;
513 }
514
GetItemIndex(int32_t index)515 int32_t RenderIndexer::GetItemIndex(int32_t index)
516 {
517 if (items_.empty()) {
518 return -1;
519 }
520 int32_t itemIndexInList = -1;
521 RefPtr<RenderNode> itemNode;
522 auto iter = items_.begin();
523 std::advance(iter, index);
524 if (iter == items_.end()) {
525 itemNode = items_.back();
526 } else {
527 itemNode = *iter;
528 }
529 RefPtr<RenderIndexerItem> indexerItem = AceType::DynamicCast<RenderIndexerItem>(itemNode);
530 if (indexerItem) {
531 itemIndexInList = indexerItem->GetSectionIndex();
532 }
533 LOGI("[indexer] GetItemIndex index:%{public}d indexInList:%{public}d", index, itemIndexInList);
534 return itemIndexInList;
535 }
536
HandleFocusAnimation(const Size & size,const Offset & offset)537 void RenderIndexer::HandleFocusAnimation(const Size& size, const Offset& offset)
538 {
539 auto context = context_.Upgrade();
540 if (!context) {
541 LOGE("Pipeline context upgrade fail!");
542 return;
543 }
544 if (!context->GetRenderFocusAnimation()) {
545 LOGE("focusAnimation is null!");
546 return;
547 }
548
549 double focusPadding = NormalizeToPx(FOCUS_PADDING);
550 context->ShowFocusAnimation(RRect::MakeRRect(Rect(Offset(), size - Size(focusPadding, focusPadding) * PADDING_SIZE),
551 focusPadding, focusPadding),
552 Color::BLUE, offset + Offset(focusPadding, focusPadding));
553 }
554
MoveSectionWithIndexer(int32_t curSection)555 void RenderIndexer::MoveSectionWithIndexer(int32_t curSection)
556 {
557 if (focusedItem_ == curSection) {
558 LOGI("Current focused item already is:%{public}d", curSection);
559
560 // click the same letter multiple times.
561 if (bubbleController_ && !bubbleController_->IsRunning()) {
562 bubbleController_->Play();
563 }
564 return;
565 }
566
567 RefPtr<RenderIndexerItem> curItem = GetSpecificItem(curSection);
568 if (!curItem || !NeedProcess(curItem)) {
569 LOGW("[indexer] invalid indexer item");
570 return;
571 }
572
573 // change to correct index
574 BeginFocusAnimation(focusedItem_, curSection);
575 curItem->SetClicked(true); // Make cur clicked item focus.
576 UpdateCurrentSectionItem(curSection);
577
578 // Make pre focused item blur.
579 RefPtr<RenderIndexerItem> preItem = GetSpecificItem(focusedItem_);
580 if (preItem) {
581 preItem->SetClicked(false);
582 }
583 focusedItem_ = curSection;
584 MoveList(curItem->GetSectionIndex());
585 UpdateBubbleText();
586 }
587
MoveList(int32_t index)588 void RenderIndexer::MoveList(int32_t index)
589 {
590 if (index < 0) {
591 LOGE("[indexer] invalid item indexer");
592 return;
593 }
594
595 // trigger onSelected Method
596 OnSelected(index);
597
598 // trigger onRequestPopupData Method
599 OnRequestPopupData(index);
600 }
601
GetSpecificItem(int32_t index) const602 RefPtr<RenderIndexerItem> RenderIndexer::GetSpecificItem(int32_t index) const
603 {
604 auto iter = items_.begin();
605 std::advance(iter, index);
606 if (iter != items_.end()) {
607 return AceType::DynamicCast<RenderIndexerItem>(*iter);
608 }
609 return nullptr;
610 }
611
OnSelected(int32_t selected) const612 void RenderIndexer::OnSelected(int32_t selected) const
613 {
614 if (selectedEventFun_) {
615 auto event = std::make_shared<IndexerEventInfo>(selected);
616 if (event) {
617 selectedEventFun_(event);
618 }
619 }
620 }
621
OnRequestPopupData(int32_t selected)622 void RenderIndexer::OnRequestPopupData(int32_t selected)
623 {
624 if (requestPopupDataEventFun_) {
625 auto event = std::make_shared<IndexerEventInfo>(selected);
626 if (event) {
627 auto popupData = requestPopupDataEventFun_(event);
628 if (popupList_) {
629 popupList_->OnRequestPopupDataSelected(popupData);
630 }
631
632 // switch bubble style
633 if (popupData.size() == 0) {
634 popupListEnabled_ = false;
635 } else {
636 popupListEnabled_ = true;
637 }
638 }
639 }
640 }
641
GetBubbleRect(Rect & rect)642 bool RenderIndexer::GetBubbleRect(Rect& rect)
643 {
644 if (!IsValidBubbleBox()) {
645 return false;
646 }
647
648 Offset bubbleOffset = bubbleDisplay_->GetGlobalOffset();
649 Size bubbleSize = bubbleDisplay_->GetLayoutSize();
650
651 rect.SetOffset(bubbleOffset);
652 rect.SetSize(bubbleSize);
653 return true;
654 }
655
GetPopupListRect(Rect & rect)656 bool RenderIndexer::GetPopupListRect(Rect& rect)
657 {
658 if (!IsValidPopupList()) {
659 return false;
660 }
661 Offset popupListOffset = popupListDisplay_->GetGlobalOffset();
662 Size popupListSize = popupListDisplay_->GetLayoutSize();
663
664 rect.SetOffset(popupListOffset);
665 rect.SetSize(popupListSize);
666 return true;
667 }
668 } // namespace OHOS::Ace::V2
669