• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_pattern.h"
17 
18 #include <cmath>
19 
20 #include "base/log/dump_log.h"
21 #include "base/utils/utils.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
24 #include "core/components_ng/pattern/swiper/swiper_utils.h"
25 #include "core/event/ace_events.h"
26 #include "core/event/mouse_event.h"
27 #include "core/pipeline_ng/pipeline_context.h"
28 
29 namespace OHOS::Ace::NG {
30 namespace {
31 constexpr uint32_t INDICATOR_HAS_CHILD = 2;
32 constexpr Dimension INDICATOR_DRAG_MIN_DISTANCE = 4.0_vp;
33 constexpr Dimension INDICATOR_DRAG_MAX_DISTANCE = 18.0_vp;
34 constexpr Dimension INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE = 80.0_vp;
35 constexpr int32_t MULTIPLIER = 2;
36 constexpr int32_t LONG_PRESS_DELAY = 300;
37 constexpr float HALF_FLOAT = 0.5f;
38 constexpr float MAX_FONT_SCALE = 2.0f;
39 constexpr double QUARTER_CIRCLE_ANGLE = 90.0;
40 constexpr double HALF_CIRCLE_ANGLE = 180.0;
41 constexpr double THREE_QUARTER_CIRCLE_ANGLE = 270.0;
42 constexpr double FULL_CIRCLE_ANGLE = 360.0;
43 constexpr Dimension CONTAINER_BORDER_WIDTH = 24.0_vp;
44 constexpr float INDICATOR_TOUCH_BOTTOM_MAX_ANGLE = 120.0;
45 } // namespace
46 
OnAttachToFrameNode()47 void SwiperIndicatorPattern::OnAttachToFrameNode()
48 {
49     auto host = GetHost();
50     CHECK_NULL_VOID(host);
51     auto pipeline = host->GetContext();
52     CHECK_NULL_VOID(pipeline);
53     auto indicatorTheme = pipeline->GetTheme<SwiperIndicatorTheme>();
54     CHECK_NULL_VOID(indicatorTheme);
55     host->GetRenderContext()->SetClipToBounds(indicatorTheme->GetClipEdge());
56 }
57 
OnModifyDone()58 void SwiperIndicatorPattern::OnModifyDone()
59 {
60     Pattern::OnModifyDone();
61     auto host = GetHost();
62     CHECK_NULL_VOID(host);
63 
64     if (GetIndicatorType() == SwiperIndicatorType::DIGIT) {
65         UpdateDigitalIndicator();
66     } else {
67         host->Clean();
68     }
69 
70     if (dotIndicatorModifier_) {
71         dotIndicatorModifier_->StopAnimation();
72     }
73 
74     InitIndicatorEvent();
75 }
76 
InitIndicatorEvent()77 void SwiperIndicatorPattern::InitIndicatorEvent()
78 {
79     auto host = GetHost();
80     CHECK_NULL_VOID(host);
81     RegisterIndicatorChangeEvent();
82 
83     auto gestureHub = host->GetOrCreateGestureEventHub();
84     CHECK_NULL_VOID(gestureHub);
85     if (GetIndicatorType() == SwiperIndicatorType::DOT) {
86         InitClickEvent(gestureHub);
87         InitHoverMouseEvent();
88         InitTouchEvent(gestureHub);
89         InitLongPressEvent(gestureHub);
90         InitFocusEvent();
91     } else {
92         if (clickEvent_) {
93             gestureHub->RemoveClickEvent(clickEvent_);
94             clickEvent_ = nullptr;
95         }
96     }
97 
98     auto swiperPattern = GetSwiperPattern();
99     CHECK_NULL_VOID(swiperPattern);
100     swiperIndicatorType_ = swiperPattern->GetIndicatorType();
101     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
102     CHECK_NULL_VOID(swiperLayoutProperty);
103     if (swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::ARC_DOT) == SwiperIndicatorType::ARC_DOT) {
104         InitTouchEvent(gestureHub);
105         InitLongPressEvent(gestureHub);
106         InitAccessibilityFocusEvent();
107     }
108 }
109 
UpdateDigitalIndicator()110 void SwiperIndicatorPattern::UpdateDigitalIndicator()
111 {
112     auto host = GetHost();
113     CHECK_NULL_VOID(host);
114     RefPtr<FrameNode> firstTextNode;
115     RefPtr<FrameNode> lastTextNode;
116     auto layoutProperty = host->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
117     CHECK_NULL_VOID(layoutProperty);
118     if (host->GetChildren().size() == INDICATOR_HAS_CHILD) {
119         firstTextNode = DynamicCast<FrameNode>(host->GetFirstChild());
120         lastTextNode = DynamicCast<FrameNode>(host->GetLastChild());
121     } else {
122         host->Clean();
123         firstTextNode = FrameNode::CreateFrameNode(
124             V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
125         lastTextNode = FrameNode::CreateFrameNode(
126             V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
127     }
128     UpdateTextContent(layoutProperty, firstTextNode, lastTextNode);
129     host->AddChild(firstTextNode);
130     host->AddChild(lastTextNode);
131 }
132 
RegisterIndicatorChangeEvent()133 void SwiperIndicatorPattern::RegisterIndicatorChangeEvent()
134 {
135     auto host = GetHost();
136     CHECK_NULL_VOID(host);
137 
138     RefPtr<SwiperPattern> swiperPattern = GetSwiperPattern();
139     CHECK_NULL_VOID(swiperPattern);
140 
141     auto swiperEventHub = swiperPattern->GetEventHub<SwiperEventHub>();
142     CHECK_NULL_VOID(swiperEventHub);
143 
144     swiperEventHub->SetIndicatorOnChange(
145         [weak = AceType::WeakClaim(RawPtr(host)), context = AceType::WeakClaim(this)]() {
146             auto indicator = weak.Upgrade();
147             CHECK_NULL_VOID(indicator);
148             auto pipeline = indicator->GetContext();
149             CHECK_NULL_VOID(pipeline);
150             pipeline->AddAfterLayoutTask([weak, context]() {
151                 auto indicator = weak.Upgrade();
152                 CHECK_NULL_VOID(indicator);
153                 auto textContext = context.Upgrade();
154                 CHECK_NULL_VOID(textContext);
155                 if (textContext->GetIndicatorType() == SwiperIndicatorType::DIGIT) {
156                     RefPtr<FrameNode> firstTextNode;
157                     RefPtr<FrameNode> lastTextNode;
158                     auto layoutProperty = indicator->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
159                     firstTextNode = DynamicCast<FrameNode>(indicator->GetFirstChild());
160                     lastTextNode = DynamicCast<FrameNode>(indicator->GetLastChild());
161                     textContext->UpdateTextContent(layoutProperty, firstTextNode, lastTextNode);
162                 }
163                 indicator->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
164             });
165             pipeline->RequestFrame();
166         });
167     swiperEventHub->SetIndicatorIndexChangeEvent(
168         [weak = AceType::WeakClaim(RawPtr(host)), context = AceType::WeakClaim(this)](int32_t index) {
169         auto indicator = weak.Upgrade();
170         CHECK_NULL_VOID(indicator);
171         auto pipeline = indicator->GetContext();
172         CHECK_NULL_VOID(pipeline);
173         auto pattern = context.Upgrade();
174         CHECK_NULL_VOID(pattern);
175         pattern->FireIndicatorIndexChangeEvent(index);
176     });
177 }
178 
UpdateFocusable() const179 void SwiperIndicatorPattern::UpdateFocusable() const
180 {
181     auto swiperNode = GetSwiperNode();
182     CHECK_NULL_VOID(swiperNode);
183     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
184     CHECK_NULL_VOID(swiperPattern);
185     auto focusable = swiperPattern->TotalCount() != 0;
186 
187     auto host = GetHost();
188     CHECK_NULL_VOID(host);
189     auto focusHub = host->GetOrCreateFocusHub();
190     CHECK_NULL_VOID(focusHub);
191     focusHub->SetFocusable(focusable);
192 
193     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
194     CHECK_NULL_VOID(accessibilityProperty);
195     auto level = focusable ? "auto" : "no";
196     accessibilityProperty->SetAccessibilityLevel(level);
197 }
198 
GetInnerFocusPaintRect(RoundRect & paintRect)199 void SwiperIndicatorPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
200 {
201     auto host = GetHost();
202     CHECK_NULL_VOID(host);
203     auto geometryNode = host->GetGeometryNode();
204     CHECK_NULL_VOID(geometryNode);
205     auto swiperNode = GetSwiperNode();
206     CHECK_NULL_VOID(swiperNode);
207     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
208     CHECK_NULL_VOID(swiperPattern);
209     auto pipelineContext = host->GetContext();
210     CHECK_NULL_VOID(pipelineContext);
211     auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
212     CHECK_NULL_VOID(swiperTheme);
213     auto maxDisplayCount = swiperPattern->GetMaxDisplayCount() > 0 ? swiperPattern->GetMaxDisplayCount()
214                                                                    : swiperPattern->TotalCount();
215     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
216     CHECK_NULL_VOID(paintProperty);
217     auto itemWidth = paintProperty->GetItemWidthValue(swiperTheme->GetSize()).ConvertToPx();
218     auto normalHeight = paintProperty->GetItemHeightValue(swiperTheme->GetSize()).ConvertToPx();
219     auto selectedItemWidth = paintProperty->GetSelectedItemWidthValue(swiperTheme->GetSize()).ConvertToPx();
220     auto selectedItemHeight = paintProperty->GetSelectedItemHeightValue(swiperTheme->GetSize()).ConvertToPx();
221     auto itemHeight = normalHeight > selectedItemHeight ? normalHeight : selectedItemHeight;
222     auto isCustomSize = paintProperty->GetIsCustomSizeValue(false);
223     auto allPointDiameterSum = isCustomSize ? itemWidth * static_cast<float>(maxDisplayCount - 1) + selectedItemWidth :
224         itemWidth * static_cast<float>(maxDisplayCount + 1);
225     auto indicatorHeightPadding = swiperTheme->GetIndicatorBgHeight().ConvertToPx();
226     Dimension indicatorDotItemSpace =
227         paintProperty->GetSpaceValue(swiperTheme->GetIndicatorDotItemSpace());
228     auto allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (maxDisplayCount - 1);
229     auto paddingSide = swiperTheme->GetIndicatorPaddingDot().ConvertToPx();
230     auto focusPadding = swiperTheme->GetIndicatorFocusedPadding().ConvertToPx();
231     auto width = allPointDiameterSum + allPointSpaceSum + MULTIPLIER * (paddingSide + focusPadding);
232     auto height = itemHeight + MULTIPLIER * indicatorHeightPadding + MULTIPLIER * focusPadding;
233     auto axis = swiperPattern->GetDirection();
234     if (axis == Axis::VERTICAL) {
235         std::swap(width, height);
236     }
237     auto swiperSize = geometryNode->GetFrameSize();
238     auto widthSize = swiperSize.Width() + MULTIPLIER * focusPadding;
239     auto heightSize = swiperSize.Height() + MULTIPLIER * focusPadding;
240     auto widthDiff = (widthSize - width) / MULTIPLIER;
241     auto heightDiff = (heightSize - height) / MULTIPLIER;
242     paintRect.SetRect({ widthDiff - focusPadding, heightDiff - focusPadding, width, height });
243     auto radius = axis == Axis::HORIZONTAL ? height : width;
244     auto realRadius = static_cast<float>(radius + focusPadding);
245     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, realRadius, realRadius);
246     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, realRadius, realRadius);
247     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, realRadius, realRadius);
248     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, realRadius, realRadius);
249 }
250 
InitFocusEvent()251 void SwiperIndicatorPattern::InitFocusEvent()
252 {
253     if (focusEventInitialized_) {
254         return;
255     }
256     auto host = GetHost();
257     CHECK_NULL_VOID(host);
258     auto focusHub = host->GetOrCreateFocusHub();
259     CHECK_NULL_VOID(focusHub);
260     auto focusTask = [weak = WeakClaim(this)]() {
261         auto pattern = weak.Upgrade();
262         CHECK_NULL_VOID(pattern);
263         pattern->HandleFocusEvent();
264     };
265     focusHub->SetOnFocusInternal(focusTask);
266     auto blurTask = [weak = WeakClaim(this)]() {
267         auto pattern = weak.Upgrade();
268         CHECK_NULL_VOID(pattern);
269         pattern->HandleBlurEvent();
270     };
271     focusHub->SetOnBlurInternal(blurTask);
272     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
273         auto pattern = wp.Upgrade();
274         CHECK_NULL_VOID(pattern);
275         pattern->GetInnerFocusPaintRect(paintRect);
276     };
277     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
278     focusEventInitialized_ = true;
279 }
280 
HandleFocusEvent()281 void SwiperIndicatorPattern::HandleFocusEvent()
282 {
283     CHECK_NULL_VOID(dotIndicatorModifier_);
284     AddIsFocusActiveUpdateEvent();
285     auto pipeline = GetContext();
286     CHECK_NULL_VOID(pipeline);
287     if (pipeline->GetIsFocusActive()) {
288         OnIsFocusActiveUpdate(true);
289     }
290 }
291 
HandleBlurEvent()292 void SwiperIndicatorPattern::HandleBlurEvent()
293 {
294     CHECK_NULL_VOID(dotIndicatorModifier_);
295     RemoveIsFocusActiveUpdateEvent();
296     OnIsFocusActiveUpdate(false);
297 }
298 
AddIsFocusActiveUpdateEvent()299 void SwiperIndicatorPattern::AddIsFocusActiveUpdateEvent()
300 {
301     if (!isFocusActiveUpdateEvent_) {
302         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
303             auto pattern = weak.Upgrade();
304             CHECK_NULL_VOID(pattern);
305             pattern->OnIsFocusActiveUpdate(isFocusAcitve);
306         };
307     }
308     auto pipeline = GetContext();
309     CHECK_NULL_VOID(pipeline);
310     pipeline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
311 }
312 
RemoveIsFocusActiveUpdateEvent()313 void SwiperIndicatorPattern::RemoveIsFocusActiveUpdateEvent()
314 {
315     auto pipeline = GetContext();
316     CHECK_NULL_VOID(pipeline);
317     pipeline->RemoveIsFocusActiveUpdateEvent(GetHost());
318 }
319 
OnIsFocusActiveUpdate(bool isFocusAcitve)320 void SwiperIndicatorPattern::OnIsFocusActiveUpdate(bool isFocusAcitve)
321 {
322     CHECK_NULL_VOID(dotIndicatorModifier_);
323     dotIndicatorModifier_->SetIsFocused(isFocusAcitve);
324 }
325 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)326 bool SwiperIndicatorPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
327 {
328     UpdateFocusable();
329 
330     if (swiperIndicatorType_ == SwiperIndicatorType::ARC_DOT) {
331         return SetArcIndicatorHotRegion(dirty, config);
332     }
333     CHECK_NULL_RETURN(config.frameSizeChange, false);
334     return true;
335 }
336 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)337 void SwiperIndicatorPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
338 {
339     CHECK_NULL_VOID(!clickEvent_);
340     auto clickTask = [weak = WeakClaim(this)](const GestureEvent& info) {
341         auto pattern = weak.Upgrade();
342         CHECK_NULL_VOID(pattern);
343         pattern->HandleClick(info);
344     };
345     clickEvent_ = MakeRefPtr<ClickEvent>(std::move(clickTask));
346     gestureHub->AddClickEvent(clickEvent_);
347 }
348 
HandleClick(const GestureEvent & info)349 void SwiperIndicatorPattern::HandleClick(const GestureEvent& info)
350 {
351     if (info.GetSourceDevice() == SourceType::KEYBOARD) {
352         return;
353     }
354 
355     if (info.GetSourceDevice() == SourceType::MOUSE) {
356         isClicked_ = true;
357         HandleMouseClick(info);
358     } else {
359         HandleTouchClick(info);
360     }
361 }
362 
HandleMouseClick(const GestureEvent &)363 void SwiperIndicatorPattern::HandleMouseClick(const GestureEvent& /* info */)
364 {
365     if (isRepeatClicked_) {
366         return;
367     }
368     GetMouseClickIndex();
369     CHECK_NULL_VOID(mouseClickIndex_);
370     SwipeTo(mouseClickIndex_);
371     auto host = GetHost();
372     CHECK_NULL_VOID(host);
373     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
374 }
375 
HandleTouchClick(const GestureEvent & info)376 void SwiperIndicatorPattern::HandleTouchClick(const GestureEvent& info)
377 {
378     auto host = GetHost();
379     CHECK_NULL_VOID(host);
380     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
381     CHECK_NULL_VOID(paintProperty);
382     auto pipeline = PipelineBase::GetCurrentContext();
383     CHECK_NULL_VOID(pipeline);
384     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
385     CHECK_NULL_VOID(theme);
386     auto itemWidth = paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx();
387     auto selectedItemWidth = paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx();
388     if (Negative(itemWidth) || Negative(selectedItemWidth)) {
389         itemWidth = theme->GetSize().ConvertToPx();
390         selectedItemWidth = theme->GetSize().ConvertToPx();
391     }
392 
393     auto isRtl = IsHorizontalAndRightToLeft();
394     auto currentIndex = GetTouchCurrentIndex();
395     auto margin = HandleTouchClickMargin();
396     Dimension indicatorDotItemSpace =
397         paintProperty->GetSpaceValue(theme->GetIndicatorDotItemSpace());
398     auto lengthBeforeCurrentIndex = margin + theme->GetIndicatorPaddingDot().ConvertToPx() +
399                                     (indicatorDotItemSpace.ConvertToPx() + itemWidth) * currentIndex;
400     auto lengthWithCurrentIndex = lengthBeforeCurrentIndex + selectedItemWidth;
401     auto axis = GetDirection();
402     auto mainClickOffset = axis == Axis::HORIZONTAL ? info.GetLocalLocation().GetX() : info.GetLocalLocation().GetY();
403     if (mainClickOffset < lengthBeforeCurrentIndex) {
404         isRtl ? ShowNext() : ShowPrevious();
405     } else if (mainClickOffset > lengthWithCurrentIndex) {
406         isRtl ? ShowPrevious() : ShowNext();
407     }
408 }
409 
InitHoverMouseEvent()410 void SwiperIndicatorPattern::InitHoverMouseEvent()
411 {
412     auto host = GetHost();
413     CHECK_NULL_VOID(host);
414     auto eventHub = host->GetEventHub<EventHub>();
415     CHECK_NULL_VOID(eventHub);
416     auto inputHub = eventHub->GetOrCreateInputEventHub();
417     CHECK_NULL_VOID(inputHub);
418 
419     auto hoverTask = [weak = WeakClaim(this)](bool isHover, HoverInfo& info) {
420         auto pattern = weak.Upgrade();
421         if (pattern && info.GetSourceDevice() != SourceType::TOUCH) {
422             pattern->HandleHoverEvent(isHover);
423         }
424     };
425 
426     if (!hoverEvent_) {
427         hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
428         inputHub->AddOnHoverEvent(hoverEvent_);
429     }
430 
431     auto mouseEvent = [weak = WeakClaim(this)](MouseInfo& info) {
432         auto pattern = weak.Upgrade();
433         if (pattern) {
434             pattern->HandleMouseEvent(info);
435         }
436     };
437     if (mouseEvent_) {
438         inputHub->RemoveOnMouseEvent(mouseEvent_);
439     }
440     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseEvent));
441     inputHub->AddOnMouseEvent(mouseEvent_);
442 }
443 
HandleMouseEvent(const MouseInfo & info)444 void SwiperIndicatorPattern::HandleMouseEvent(const MouseInfo& info)
445 {
446     if (info.GetSourceDevice() == SourceType::TOUCH) {
447         return;
448     }
449     auto mouseOffsetX = static_cast<float>(info.GetLocalLocation().GetX());
450     auto mouseOffsetY = static_cast<float>(info.GetLocalLocation().GetY());
451     auto mouseAction = info.GetAction();
452     if ((mouseAction == MouseAction::PRESS || mouseAction == MouseAction::RELEASE) &&
453         isClicked_ && NearEqual(hoverPoint_, PointF(mouseOffsetX, mouseOffsetY))) {
454         isRepeatClicked_ = true;
455         return;
456     }
457     isClicked_ = false;
458     isRepeatClicked_ = false;
459     auto host = GetHost();
460     CHECK_NULL_VOID(host);
461     hoverPoint_.SetX(mouseOffsetX);
462     hoverPoint_.SetY(mouseOffsetY);
463 
464     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
465 }
466 
HandleHoverEvent(bool isHover)467 void SwiperIndicatorPattern::HandleHoverEvent(bool isHover)
468 {
469     if (isHover_ == isHover) {
470         return;
471     }
472 
473     isHover_ = isHover;
474     auto host = GetHost();
475     CHECK_NULL_VOID(host);
476     auto swiperNode = GetSwiperNode();
477     if (swiperNode) {
478         auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
479         CHECK_NULL_VOID(swiperPattern);
480         auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
481         CHECK_NULL_VOID(swiperLayoutProperty);
482         if (swiperLayoutProperty->GetHoverShowValue(false) && !swiperPattern->GetIsAtHotRegion()) {
483             swiperPattern->ArrowHover(isHover_, HOVER_INDICATOR);
484         }
485     }
486     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
487 }
488 
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)489 void SwiperIndicatorPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
490 {
491     if (touchEvent_) {
492         return;
493     }
494 
495     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
496         auto pattern = weak.Upgrade();
497         if (pattern) {
498             pattern->HandleTouchEvent(info);
499         }
500     };
501 
502     if (touchEvent_) {
503         gestureHub->RemoveTouchEvent(touchEvent_);
504     }
505     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
506     gestureHub->AddTouchEvent(touchEvent_);
507 
508     auto swiperNode = GetSwiperNode();
509     CHECK_NULL_VOID(swiperNode);
510     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
511     CHECK_NULL_VOID(swiperPattern);
512     auto stopAnimationCb = [weak = WeakClaim(this)](bool ifImmediately) {
513         auto pattern = weak.Upgrade();
514         if (pattern) {
515             if (pattern->dotIndicatorModifier_) {
516                 pattern->dotIndicatorModifier_->StopAnimation(ifImmediately);
517             }
518 
519             if (pattern->overlongDotIndicatorModifier_) {
520                 pattern->overlongDotIndicatorModifier_->StopAnimation(ifImmediately);
521             }
522         }
523     };
524     swiperPattern->SetStopIndicatorAnimationCb(stopAnimationCb);
525 
526     auto updateOverlongForceStopPageRateCb = [weak = WeakClaim(this)](float forceStopPageRate) {
527         auto pattern = weak.Upgrade();
528         if (pattern && pattern->overlongDotIndicatorModifier_) {
529             pattern->overlongDotIndicatorModifier_->SetForceStopPageRate(forceStopPageRate);
530         }
531     };
532     swiperPattern->SetUpdateOverlongForceStopPageRateCb(updateOverlongForceStopPageRateCb);
533 }
534 
HandleTouchEvent(const TouchEventInfo & info)535 void SwiperIndicatorPattern::HandleTouchEvent(const TouchEventInfo& info)
536 {
537     if (info.GetTouches().empty()) {
538         return;
539     }
540     auto touchType = info.GetTouches().front().GetTouchType();
541     if (touchType == TouchType::UP) {
542         HandleTouchUp();
543         HandleDragEnd(0);
544         isPressed_ = false;
545     } else if (touchType == TouchType::CANCEL) {
546         HandleTouchUp();
547         HandleDragEnd(0);
548         isPressed_ = false;
549     }
550     if (isPressed_) {
551         HandleLongDragUpdate(info.GetTouches().front());
552     }
553 }
554 
HandleTouchDown()555 void SwiperIndicatorPattern::HandleTouchDown()
556 {
557     isPressed_ = true;
558     auto host = GetHost();
559     CHECK_NULL_VOID(host);
560     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
561 }
562 
HandleTouchUp()563 void SwiperIndicatorPattern::HandleTouchUp()
564 {
565     isPressed_ = false;
566     auto host = GetHost();
567     CHECK_NULL_VOID(host);
568     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
569 }
570 
CalMouseClickIndexStartAndEnd(int32_t itemCount,int32_t currentIndex)571 std::pair<int32_t, int32_t> SwiperIndicatorPattern::CalMouseClickIndexStartAndEnd(
572     int32_t itemCount, int32_t currentIndex)
573 {
574     auto swiperPattern = GetSwiperPattern();
575     CHECK_NULL_RETURN(swiperPattern, std::make_pair(0, 0));
576     int32_t loopCount = SwiperIndicatorUtils::CalcLoopCount(currentIndex, itemCount);
577     int32_t start = currentIndex >= 0 ? loopCount * itemCount : -(loopCount + 1) * itemCount;
578     int32_t end = currentIndex >= 0 ? (loopCount + 1) * itemCount : -loopCount * itemCount;
579     if (IsHorizontalAndRightToLeft()) {
580         end = currentIndex >= 0 ? loopCount * itemCount - 1 : -(loopCount + 1) * itemCount - 1;
581         start = currentIndex >= 0 ? (loopCount + 1) * itemCount - 1 : -loopCount * itemCount - 1;
582         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) &&
583             swiperPattern->IsSwipeByGroup()) {
584             start += (1 - swiperPattern->GetDisplayCount());
585         }
586     }
587     return { start, end };
588 }
589 
GetMouseClickIndex()590 void SwiperIndicatorPattern::GetMouseClickIndex()
591 {
592     auto pipelineContext = PipelineBase::GetCurrentContext();
593     CHECK_NULL_VOID(pipelineContext);
594     auto theme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
595     CHECK_NULL_VOID(theme);
596     auto host = GetHost();
597     CHECK_NULL_VOID(host);
598     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
599     CHECK_NULL_VOID(paintProperty);
600     float itemWidthValue = static_cast<float>(paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx());
601     float itemHeightValue = static_cast<float>(paintProperty->GetItemHeightValue(theme->GetSize()).ConvertToPx());
602     float selectedItemWidthValue =
603         static_cast<float>(paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx() * 2);
604     paintProperty->GetIsCustomSizeValue(false) ? selectedItemWidthValue *= 0.5f : selectedItemWidthValue;
605     // diameter calculation
606     double indicatorScale = theme->GetIndicatorScale();
607     float itemWidth = itemWidthValue * indicatorScale;
608     float itemHeight = itemHeightValue * indicatorScale;
609     float selectedItemWidth = selectedItemWidthValue * indicatorScale;
610     Dimension indicatorDotItemSpace =
611         paintProperty->GetSpaceValue(theme->GetIndicatorDotItemSpace());
612     float space = static_cast<float>(indicatorDotItemSpace.ConvertToPx());
613     int32_t currentIndex = GetCurrentShownIndex();
614     auto [itemCount, step] = CalculateStepAndItemCount();
615     auto frameSize = host->GetGeometryNode()->GetFrameSize();
616     auto axis = GetDirection();
617     float centerX = static_cast<float>((theme->GetIndicatorPaddingDot()).ConvertToPx());
618     float centerY = ((axis == Axis::HORIZONTAL ? frameSize.Height() : frameSize.Width()) - itemHeight) * 0.5f;
619     PointF hoverPoint = axis == Axis::HORIZONTAL ? hoverPoint_ : PointF(hoverPoint_.GetY(), hoverPoint_.GetX());
620 
621     auto [start, end] = CalMouseClickIndexStartAndEnd(itemCount, currentIndex);
622     for (int32_t i = start; (start > end ? i > end : i < end); start > end ? i -= step : i += step) {
623         if (hoverPoint.GetX() >= centerX && hoverPoint.GetX() <= centerX + itemWidth &&
624             hoverPoint.GetY() >= centerY && hoverPoint.GetY() <= centerY + itemHeight) {
625             mouseClickIndex_ = i;
626             break;
627         }
628         if (i != currentIndex) {
629             centerX += itemWidth + space;
630         } else {
631             centerX += selectedItemWidth + space;
632         }
633     }
634 }
635 
UpdateTextContent(const RefPtr<SwiperIndicatorLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & firstTextNode,const RefPtr<FrameNode> & lastTextNode)636 void SwiperIndicatorPattern::UpdateTextContent(const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
637     const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode)
638 {
639     CHECK_NULL_VOID(layoutProperty);
640     CHECK_NULL_VOID(firstTextNode);
641     CHECK_NULL_VOID(lastTextNode);
642     auto pipeline = PipelineBase::GetCurrentContext();
643     CHECK_NULL_VOID(pipeline);
644     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
645     firstTextNode->SetInternal();
646     lastTextNode->SetInternal();
647     auto firstTextLayoutProperty = firstTextNode->GetLayoutProperty<TextLayoutProperty>();
648     CHECK_NULL_VOID(firstTextLayoutProperty);
649     auto selectedFontColor =
650         layoutProperty->GetSelectedFontColorValue(theme->GetDigitalIndicatorTextStyle().GetTextColor());
651     auto selectedFontSize =
652         layoutProperty->GetSelectedFontSizeValue(theme->GetDigitalIndicatorTextStyle().GetFontSize());
653     if (!selectedFontSize.IsValid()) {
654         selectedFontSize = theme->GetDigitalIndicatorTextStyle().GetFontSize();
655     }
656     auto selectedFontWeight =
657         layoutProperty->GetSelectedFontWeightValue(theme->GetDigitalIndicatorTextStyle().GetFontWeight());
658     firstTextLayoutProperty->UpdateTextColor(selectedFontColor);
659     firstTextLayoutProperty->UpdateFontSize(selectedFontSize);
660     firstTextLayoutProperty->UpdateFontWeight(selectedFontWeight);
661     firstTextLayoutProperty->UpdateMaxFontScale(MAX_FONT_SCALE);
662     UpdateTextContentSub(layoutProperty, firstTextNode, lastTextNode);
663 }
664 
GetDisplayCurrentIndex() const665 int32_t SwiperIndicatorPattern::GetDisplayCurrentIndex() const
666 {
667     auto swiperNode = GetSwiperNode();
668     CHECK_NULL_RETURN(swiperNode, 0);
669     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
670     CHECK_NULL_RETURN(swiperPattern, 0);
671     CHECK_NULL_RETURN(swiperPattern->RealTotalCount(), 0);
672     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
673     CHECK_NULL_RETURN(swiperLayoutProperty, 0);
674     auto currentIndex = swiperPattern->GetCurrentFirstIndex() + 1;
675     if (currentIndex > swiperPattern->RealTotalCount()) {
676         currentIndex = 1;
677     } else if (swiperLayoutProperty->HasIndex()) {
678         currentIndex = GetInitialIndex() + 1;
679         if (currentIndex > swiperPattern->RealTotalCount()) {
680             currentIndex = 1;
681         }
682     }
683 
684     return currentIndex;
685 }
686 
GetInitialIndex() const687 int32_t SwiperIndicatorPattern::GetInitialIndex() const
688 {
689     auto swiperNode = GetSwiperNode();
690     CHECK_NULL_RETURN(swiperNode, 0);
691     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
692     CHECK_NULL_RETURN(swiperPattern, 0);
693     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
694     CHECK_NULL_RETURN(swiperLayoutProperty, 0);
695     auto currentIndex = swiperLayoutProperty->GetIndex().value_or(0);
696     if (swiperPattern->IsSwipeByGroup()) {
697         currentIndex = SwiperUtils::ComputePageIndex(currentIndex, swiperPattern->GetDisplayCount());
698     }
699 
700     return currentIndex;
701 }
702 
UpdateTextContentSub(const RefPtr<SwiperIndicatorLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & firstTextNode,const RefPtr<FrameNode> & lastTextNode)703 void SwiperIndicatorPattern::UpdateTextContentSub(const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
704     const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode)
705 {
706     CHECK_NULL_VOID(layoutProperty);
707     CHECK_NULL_VOID(firstTextNode);
708     CHECK_NULL_VOID(lastTextNode);
709     auto pipeline = PipelineBase::GetCurrentContext();
710     CHECK_NULL_VOID(pipeline);
711     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
712     CHECK_NULL_VOID(theme);
713     auto firstTextLayoutProperty = firstTextNode->GetLayoutProperty<TextLayoutProperty>();
714     CHECK_NULL_VOID(firstTextLayoutProperty);
715     auto lastTextLayoutProperty = lastTextNode->GetLayoutProperty<TextLayoutProperty>();
716     CHECK_NULL_VOID(lastTextLayoutProperty);
717     lastTextLayoutProperty->UpdateLayoutDirection(GetNonAutoLayoutDirection());
718 
719     std::string firstContent = "";
720     std::string lastContent = "";
721     GetTextContentSub(firstContent, lastContent);
722     firstTextLayoutProperty->UpdateContent(firstContent);
723     auto fontColor = layoutProperty->GetFontColorValue(theme->GetDigitalIndicatorTextStyle().GetTextColor());
724     auto fontSize = layoutProperty->GetFontSizeValue(theme->GetDigitalIndicatorTextStyle().GetFontSize());
725     if (!fontSize.IsValid()) {
726         fontSize = theme->GetDigitalIndicatorTextStyle().GetFontSize();
727     }
728     auto fontWeight = layoutProperty->GetFontWeightValue(theme->GetDigitalIndicatorTextStyle().GetFontWeight());
729     lastTextLayoutProperty->UpdateTextColor(fontColor);
730     lastTextLayoutProperty->UpdateFontSize(fontSize);
731     lastTextLayoutProperty->UpdateFontWeight(fontWeight);
732     lastTextLayoutProperty->UpdateContent(lastContent);
733     lastTextLayoutProperty->UpdateMaxFontScale(MAX_FONT_SCALE);
734     firstTextNode->MarkModifyDone();
735     firstTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
736     lastTextNode->MarkModifyDone();
737     lastTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
738 }
739 
HandleDragStart(const GestureEvent & info)740 void SwiperIndicatorPattern::HandleDragStart(const GestureEvent& info)
741 {
742     dragStartPoint_ =
743         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
744     UpadateStartAngle();
745 }
746 
HandleDragEnd(double dragVelocity)747 void SwiperIndicatorPattern::HandleDragEnd(double dragVelocity)
748 {
749     auto swiperNode = GetSwiperNode();
750     CHECK_NULL_VOID(swiperNode);
751     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
752     CHECK_NULL_VOID(swiperPattern);
753     swiperPattern->SetTurnPageRate(0.0f);
754     swiperPattern->SetGroupTurnPageRate(0.0f);
755     auto swiperPaintProperty = swiperPattern->GetPaintProperty<SwiperPaintProperty>();
756     CHECK_NULL_VOID(swiperPaintProperty);
757     auto autoPlay = swiperPaintProperty->GetAutoPlay().value_or(false);
758     if (autoPlay) {
759         swiperPattern->SetIndicatorLongPress(false);
760         swiperPattern->StartAutoPlay();
761     }
762     if (swiperPattern->GetIndicatorType() == SwiperIndicatorType::ARC_DOT) {
763         isLongPressed_ = false;
764         if (IsHorizontalAndRightToLeft()) {
765             swiperPattern->SetTurnPageRate(-1.0f);
766         }
767     }
768     auto host = GetHost();
769     CHECK_NULL_VOID(host);
770     touchBottomType_ = TouchBottomType::NONE;
771     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
772 }
773 
SetIndicatorInteractive(bool isInteractive)774 void SwiperIndicatorPattern::SetIndicatorInteractive(bool isInteractive)
775 {
776     auto host = GetHost();
777     CHECK_NULL_VOID(host);
778     auto eventHub = host->GetEventHub<EventHub>();
779     CHECK_NULL_VOID(eventHub);
780     if (isInteractive) {
781         eventHub->SetEnabled(true);
782     } else {
783         eventHub->SetEnabled(false);
784     }
785 }
786 
CheckIsTouchBottom(const GestureEvent & info)787 bool SwiperIndicatorPattern::CheckIsTouchBottom(const GestureEvent& info)
788 {
789     auto swiperNode = GetSwiperNode();
790     CHECK_NULL_RETURN(swiperNode, false);
791     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
792     CHECK_NULL_RETURN(swiperPattern, false);
793     auto currentIndex = swiperPattern->GetCurrentIndex();
794     auto childrenSize = swiperPattern->RealTotalCount();
795     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
796     CHECK_NULL_RETURN(swiperLayoutProperty, false);
797     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
798     auto isLoop = swiperLayoutProperty->GetLoop().value_or(true);
799     auto dragPoint =
800         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
801     auto offset = dragPoint - dragStartPoint_;
802     float touchBottomRate = 0.0;
803     float touchOffset = 0.0;
804     if (swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::ARC_DOT) == SwiperIndicatorType::ARC_DOT) {
805         auto center = GetCenterPointF();
806         float startAngle = GetAngleWithPoint(center, dragStartPoint_);
807         float endAngle = GetEndAngle(center, dragPoint, startAngle);
808         touchOffset = startAngle - endAngle;
809         touchOffset = GetDirection() == Axis::HORIZONTAL ? touchOffset : -touchOffset;
810         touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_ANGLE)
811                               ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_ANGLE : 1;
812     } else {
813         touchOffset = GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
814         touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx())
815                               ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx() : 1;
816     }
817     swiperPattern->SetTurnPageRate(0);
818     swiperPattern->SetGroupTurnPageRate(0.0f);
819     swiperPattern->SetTouchBottomRate(std::abs(touchBottomRate));
820     TouchBottomType touchBottomType = TouchBottomType::NONE;
821     if ((currentIndex <= 0) && !isLoop) {
822         if (Negative(info.GetMainDelta()) || NonPositive(touchOffset)) {
823             touchBottomType = TouchBottomType::START;
824         }
825     }
826     if ((currentIndex >= childrenSize - displayCount) && !isLoop) {
827         if (Positive(info.GetMainDelta()) || NonNegative(touchOffset)) {
828             touchBottomType = TouchBottomType::END;
829         }
830     }
831     touchBottomType_ = touchBottomType;
832     auto host = GetHost();
833     CHECK_NULL_RETURN(host, false);
834     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
835     return touchBottomType == TouchBottomType::NONE ? false : true;
836 }
837 
CheckIsTouchBottom(const TouchLocationInfo & info)838 bool SwiperIndicatorPattern::CheckIsTouchBottom(const TouchLocationInfo& info)
839 {
840     auto swiperNode = GetSwiperNode();
841     CHECK_NULL_RETURN(swiperNode, false);
842     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
843     CHECK_NULL_RETURN(swiperPattern, false);
844     auto host = GetHost();
845     CHECK_NULL_RETURN(host, false);
846     auto currentIndex = swiperPattern->GetCurrentIndex();
847     auto childrenSize = swiperPattern->RealTotalCount();
848 
849     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
850     CHECK_NULL_RETURN(swiperLayoutProperty, false);
851     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
852 
853     auto dragPoint =
854         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
855     float touchBottomRate = 0.0;
856     float touchOffset = 0.0;
857     if (swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::ARC_DOT) == SwiperIndicatorType::ARC_DOT) {
858         auto center = GetCenterPointF();
859         float startAngle = GetAngleWithPoint(center, dragStartPoint_);
860         float endAngle = GetEndAngle(center, dragPoint, startAngle);
861         touchOffset = startAngle - endAngle;
862         touchOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? touchOffset : -touchOffset;
863         touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_ANGLE)
864                               ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_ANGLE : 1;
865     } else {
866         auto offset = dragPoint - dragStartPoint_;
867         touchOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
868         touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx())
869                               ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx() : 1;
870     }
871 
872     swiperPattern->SetTurnPageRate(0);
873     swiperPattern->SetGroupTurnPageRate(0.0f);
874     swiperPattern->SetTouchBottomRate(std::abs(touchBottomRate));
875     TouchBottomType touchBottomType = TouchBottomType::NONE;
876 
877     if (currentIndex <= 0) {
878         if (swiperPattern->IsHorizontalAndRightToLeft()) {
879             if (Positive(touchOffset)) {
880                 touchBottomType = TouchBottomType::END;
881             }
882         } else {
883             if (NonPositive(touchOffset)) {
884                 touchBottomType = TouchBottomType::START;
885             }
886         }
887     }
888 
889     if (currentIndex >= childrenSize - displayCount) {
890         if (swiperPattern->IsHorizontalAndRightToLeft()) {
891             if (NonPositive(touchOffset)) {
892                 touchBottomType = TouchBottomType::START;
893             }
894         } else {
895             if (Positive(touchOffset)) {
896                 touchBottomType = TouchBottomType::END;
897             }
898         }
899     }
900     touchBottomType_ = touchBottomType;
901     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
902 
903     return touchBottomType == TouchBottomType::NONE ? false : true;
904 }
905 
InitLongPressEvent(const RefPtr<GestureEventHub> & gestureHub)906 void SwiperIndicatorPattern::InitLongPressEvent(const RefPtr<GestureEventHub>& gestureHub)
907 {
908     CHECK_NULL_VOID(!longPressEvent_);
909     auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
910         auto pattern = weak.Upgrade();
911         CHECK_NULL_VOID(pattern);
912         pattern->HandleLongPress(info);
913     };
914     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
915 
916     gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
917 }
918 
HandleLongPress(GestureEvent & info)919 void SwiperIndicatorPattern::HandleLongPress(GestureEvent& info)
920 {
921     HandleTouchDown();
922     HandleDragStart(info);
923 
924     auto swiperNode = GetSwiperNode();
925     CHECK_NULL_VOID(swiperNode);
926     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
927     CHECK_NULL_VOID(swiperPattern);
928     auto swiperPaintProperty = swiperPattern->GetPaintProperty<SwiperPaintProperty>();
929     CHECK_NULL_VOID(swiperPaintProperty);
930     auto autoPlay = swiperPaintProperty->GetAutoPlay().value_or(false);
931     if (autoPlay) {
932         swiperPattern->SetIndicatorLongPress(true);
933         swiperPattern->StopTranslateAnimation();
934         swiperPattern->StopSpringAnimation();
935         swiperPattern->StopAutoPlay();
936     }
937     if (swiperPattern->GetIndicatorType() == SwiperIndicatorType::ARC_DOT) {
938         isLongPressed_ = true;
939     }
940 }
941 
GetIndicatorDragAngleThreshold(bool isMaxAngle)942 double SwiperIndicatorPattern::GetIndicatorDragAngleThreshold(bool isMaxAngle)
943 {
944     auto host = GetHost();
945     CHECK_NULL_RETURN(host, 0.0f);
946     auto pipelineContext = host->GetContext();
947     CHECK_NULL_RETURN(pipelineContext, 0.0f);
948     auto theme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
949     CHECK_NULL_RETURN(theme, 0.0f);
950     if (isMaxAngle) {
951         return theme->GetIndicatorDragMaxAngle();
952     } else {
953         return theme->GetIndicatorDragMinAngle();
954     }
955 }
956 
HandleLongDragUpdate(const TouchLocationInfo & info)957 void SwiperIndicatorPattern::HandleLongDragUpdate(const TouchLocationInfo& info)
958 {
959     auto swiperNode = GetSwiperNode();
960     CHECK_NULL_VOID(swiperNode);
961     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
962     CHECK_NULL_VOID(swiperPattern);
963     if (swiperPattern->IsIndicatorAnimatorRunning()) {
964         return;
965     }
966     float turnPageRate = 0.0;
967     float turnPageRateOffset = 0.0;
968     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
969     CHECK_NULL_VOID(swiperLayoutProperty);
970     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
971     if (swiperPattern->RealTotalCount() == displayCount) {
972         return;
973     }
974     if (CheckIsTouchBottom(info)) {
975         return;
976     }
977     auto dragPoint =
978         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
979     if (swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::ARC_DOT) == SwiperIndicatorType::ARC_DOT) {
980         auto center = GetCenterPointF();
981         float startAngle = GetAngleWithPoint(center, dragStartPoint_);
982         float endAngle = GetEndAngle(center, dragPoint, startAngle);
983         turnPageRateOffset = startAngle - endAngle;
984         if (LessNotEqual(std::abs(turnPageRateOffset), GetIndicatorDragAngleThreshold(false))) {
985             return;
986         }
987         turnPageRateOffset =
988             GetDirection() == Axis::HORIZONTAL ? turnPageRateOffset : -turnPageRateOffset;
989         turnPageRate = -(turnPageRateOffset / GetIndicatorDragAngleThreshold(true));
990     } else {
991         auto offset = dragPoint - dragStartPoint_;
992         turnPageRateOffset = GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
993         if (LessNotEqual(std::abs(turnPageRateOffset), INDICATOR_DRAG_MIN_DISTANCE.ConvertToPx())) {
994             return;
995         }
996         turnPageRate = -(turnPageRateOffset / INDICATOR_DRAG_MAX_DISTANCE.ConvertToPx());
997         if (swiperPattern->IsHorizontalAndRightToLeft()) {
998             turnPageRateOffset = -turnPageRateOffset;
999         }
1000     }
1001 
1002     swiperPattern->SetTurnPageRate(turnPageRate);
1003     swiperPattern->SetGroupTurnPageRate(turnPageRate);
1004     if (std::abs(turnPageRate) >= 1) {
1005         int32_t step = (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) &&
1006                                 swiperPattern->IsSwipeByGroup()
1007                             ? swiperPattern->GetDisplayCount()
1008                             : 1);
1009 
1010         if (IsHorizontalAndRightToLeft() && swiperIndicatorType_ == SwiperIndicatorType::ARC_DOT) {
1011             step = -step;
1012         }
1013 
1014         if (Positive(turnPageRateOffset)) {
1015             swiperPattern->SwipeToWithoutAnimation(swiperPattern->GetCurrentIndex() + step);
1016         }
1017         if (NonPositive(turnPageRateOffset)) {
1018             swiperPattern->SwipeToWithoutAnimation(swiperPattern->GetCurrentIndex() - step);
1019         }
1020         dragStartPoint_ = dragPoint;
1021         UpadateStartAngle();
1022     }
1023 }
1024 
HandleTouchClickMargin()1025 float SwiperIndicatorPattern::HandleTouchClickMargin()
1026 {
1027     auto host = GetHost();
1028     CHECK_NULL_RETURN(host, 0.0f);
1029     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
1030     CHECK_NULL_RETURN(paintProperty, 0.0f);
1031     auto pipeline = PipelineBase::GetCurrentContext();
1032     CHECK_NULL_RETURN(pipeline, 0.0f);
1033     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
1034     CHECK_NULL_RETURN(theme, 0.0f);
1035     auto itemWidth = paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx();
1036     auto selectedItemWidth = paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx();
1037     if (Negative(itemWidth) || Negative(selectedItemWidth)) {
1038         itemWidth = theme->GetSize().ConvertToPx();
1039         selectedItemWidth = theme->GetSize().ConvertToPx();
1040     }
1041 
1042     int32_t itemCount = DisplayIndicatorTotalCount();
1043     auto allPointDiameterSum = itemWidth * static_cast<float>(itemCount - 1) + selectedItemWidth;
1044     Dimension indicatorDotItemSpace =
1045         paintProperty->GetSpaceValue(theme->GetIndicatorDotItemSpace());
1046     auto allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx() * (itemCount - 1));
1047     auto indicatorPadding = static_cast<float>(theme->GetIndicatorPaddingDot().ConvertToPx());
1048     auto contentWidth = indicatorPadding + allPointDiameterSum + allPointSpaceSum + indicatorPadding;
1049     auto geometryNode = host->GetGeometryNode();
1050     CHECK_NULL_RETURN(geometryNode, 0.0f);
1051     auto frameSize = geometryNode->GetFrameSize();
1052     auto axis = GetDirection();
1053     return ((axis == Axis::HORIZONTAL ? frameSize.Width() : frameSize.Height()) - contentWidth) * 0.5f;
1054 }
1055 
DumpAdvanceInfo()1056 void SwiperIndicatorPattern::DumpAdvanceInfo()
1057 {
1058     isHover_ ? DumpLog::GetInstance().AddDesc("isHover:true") : DumpLog::GetInstance().AddDesc("isHover:false");
1059     isPressed_ ? DumpLog::GetInstance().AddDesc("isPressed:true") : DumpLog::GetInstance().AddDesc("isPressed:false");
1060     isClicked_ ? DumpLog::GetInstance().AddDesc("isClicked:true") : DumpLog::GetInstance().AddDesc("isClicked:false");
1061     isRepeatClicked_ ? DumpLog::GetInstance().AddDesc("isRepeatClicked:true")
1062                      : DumpLog::GetInstance().AddDesc("isRepeatClicked:false");
1063     switch (GetIndicatorType()) {
1064         case SwiperIndicatorType::DOT: {
1065             DumpLog::GetInstance().AddDesc("SwiperIndicatorType:DOT");
1066             break;
1067         }
1068         case SwiperIndicatorType::DIGIT: {
1069             DumpLog::GetInstance().AddDesc("SwiperIndicatorType:DIGIT");
1070             break;
1071         }
1072         case SwiperIndicatorType::ARC_DOT: {
1073             DumpLog::GetInstance().AddDesc("SwiperIndicatorType:ARC_DOT");
1074             break;
1075         }
1076         default: {
1077             break;
1078         }
1079     }
1080 }
1081 
CalculateAngleOffset(float centerX,float centerY,float radius,double angle)1082 OffsetF SwiperIndicatorPattern::CalculateAngleOffset(float centerX, float centerY, float radius, double angle)
1083 {
1084     double radians = 0.0;
1085     OffsetF angleOffset;
1086     if (GreatOrEqual(angle, 0.0) && LessNotEqual(angle, QUARTER_CIRCLE_ANGLE)) {
1087         radians = std::abs(angle) * M_PI / HALF_CIRCLE_ANGLE;
1088         angleOffset.SetX(centerX + cos(radians) * radius);
1089         angleOffset.SetY(centerY + sin(radians) * radius);
1090     } else if (GreatOrEqual(angle, QUARTER_CIRCLE_ANGLE) && LessNotEqual(angle, HALF_CIRCLE_ANGLE)) {
1091         radians = std::abs(HALF_CIRCLE_ANGLE - angle) * M_PI / HALF_CIRCLE_ANGLE;
1092         angleOffset.SetX(centerX - cos(radians) * radius);
1093         angleOffset.SetY(centerY + sin(radians) * radius);
1094     } else if (GreatOrEqual(angle, HALF_CIRCLE_ANGLE) && LessNotEqual(angle, THREE_QUARTER_CIRCLE_ANGLE)) {
1095         radians = std::abs(angle - HALF_CIRCLE_ANGLE) * M_PI / HALF_CIRCLE_ANGLE;
1096         angleOffset.SetX(centerX - cos(radians) * radius);
1097         angleOffset.SetY(centerY - sin(radians) * radius);
1098     } else if (GreatOrEqual(angle, THREE_QUARTER_CIRCLE_ANGLE) && LessNotEqual(angle, FULL_CIRCLE_ANGLE)) {
1099         radians = std::abs(FULL_CIRCLE_ANGLE - angle) * M_PI / HALF_CIRCLE_ANGLE;
1100         angleOffset.SetX(centerX + cos(radians) * radius);
1101         angleOffset.SetY(centerY - sin(radians) * radius);
1102     }
1103     return angleOffset;
1104 }
1105 
CalculateRectLayout(double angle,float radius,OffsetF angleOffset,Dimension & width,Dimension & height)1106 OffsetF SwiperIndicatorPattern::CalculateRectLayout(
1107     double angle, float radius, OffsetF angleOffset, Dimension& width, Dimension& height)
1108 {
1109     OffsetF hotRegionOffset = angleOffset;
1110     Dimension oneAngleLength = Dimension(sin(M_PI / HALF_CIRCLE_ANGLE) * radius, DimensionUnit::PX);
1111     // The number 0.5 represents equal division
1112     if ((GreatOrEqual(angle, QUARTER_CIRCLE_ANGLE * 0.5) &&
1113             LessNotEqual(angle, QUARTER_CIRCLE_ANGLE * 0.5 + QUARTER_CIRCLE_ANGLE)) ||
1114         (GreatOrEqual(angle, QUARTER_CIRCLE_ANGLE * 0.5 + HALF_CIRCLE_ANGLE) &&
1115             LessNotEqual(angle, QUARTER_CIRCLE_ANGLE * 0.5 + THREE_QUARTER_CIRCLE_ANGLE))) {
1116         hotRegionOffset.SetY(angleOffset.GetY() - CONTAINER_BORDER_WIDTH.ConvertToPx() * 0.5);
1117         width = oneAngleLength;
1118         height = CONTAINER_BORDER_WIDTH;
1119     } else {
1120         hotRegionOffset.SetX(angleOffset.GetX() - CONTAINER_BORDER_WIDTH.ConvertToPx() * 0.5);
1121         width = CONTAINER_BORDER_WIDTH;
1122         height = oneAngleLength;
1123     }
1124     return hotRegionOffset;
1125 }
1126 
ResetDotModifier()1127 void SwiperIndicatorPattern::ResetDotModifier()
1128 {
1129     if (!dotIndicatorModifier_) {
1130         return;
1131     }
1132 
1133     auto host = GetHost();
1134     CHECK_NULL_VOID(host);
1135     auto rsRenderContext = host->GetRenderContext();
1136     CHECK_NULL_VOID(rsRenderContext);
1137     rsRenderContext->RemoveContentModifier(dotIndicatorModifier_);
1138     dotIndicatorModifier_ = nullptr;
1139 }
1140 
ResetOverlongModifier()1141 void SwiperIndicatorPattern::ResetOverlongModifier()
1142 {
1143     if (!overlongDotIndicatorModifier_) {
1144         return;
1145     }
1146 
1147     auto host = GetHost();
1148     CHECK_NULL_VOID(host);
1149     auto rsRenderContext = host->GetRenderContext();
1150     CHECK_NULL_VOID(rsRenderContext);
1151     rsRenderContext->RemoveContentModifier(overlongDotIndicatorModifier_);
1152     overlongDotIndicatorModifier_ = nullptr;
1153 }
1154 
CreateOverlongDotIndicatorPaintMethod(RefPtr<SwiperPattern> swiperPattern)1155 RefPtr<OverlengthDotIndicatorPaintMethod> SwiperIndicatorPattern::CreateOverlongDotIndicatorPaintMethod(
1156     RefPtr<SwiperPattern> swiperPattern)
1157 {
1158     ResetDotModifier();
1159 
1160     if (!overlongDotIndicatorModifier_) {
1161         overlongDotIndicatorModifier_ = AceType::MakeRefPtr<OverlengthDotIndicatorModifier>();
1162     }
1163 
1164     overlongDotIndicatorModifier_->SetAnimationDuration(swiperPattern->GetDuration());
1165     overlongDotIndicatorModifier_->SetLongPointHeadCurve(
1166         swiperPattern->GetIndicatorHeadCurve(), swiperPattern->GetMotionVelocity());
1167     overlongDotIndicatorModifier_->SetUserSetSwiperCurve(swiperPattern->GetCurve());
1168     overlongDotIndicatorModifier_->SetIsBindIndicator(swiperPattern->IsBindIndicator());
1169 
1170     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
1171     CHECK_NULL_RETURN(swiperLayoutProperty, nullptr);
1172     auto overlongPaintMethod = MakeRefPtr<OverlengthDotIndicatorPaintMethod>(overlongDotIndicatorModifier_);
1173     auto paintMethodTemp = DynamicCast<DotIndicatorPaintMethod>(overlongPaintMethod);
1174     SetDotIndicatorPaintMethodInfo(swiperPattern, paintMethodTemp, swiperLayoutProperty);
1175     UpdateOverlongPaintMethod(swiperPattern, overlongPaintMethod);
1176 
1177     return overlongPaintMethod;
1178 }
1179 
CreateDotIndicatorPaintMethod(RefPtr<SwiperPattern> swiperPattern)1180 RefPtr<DotIndicatorPaintMethod> SwiperIndicatorPattern::CreateDotIndicatorPaintMethod(
1181     RefPtr<SwiperPattern> swiperPattern)
1182 {
1183     ResetOverlongModifier();
1184 
1185     if (!dotIndicatorModifier_) {
1186         dotIndicatorModifier_ = AceType::MakeRefPtr<DotIndicatorModifier>();
1187     }
1188 
1189     dotIndicatorModifier_->SetAnimationDuration(swiperPattern->GetDuration());
1190     dotIndicatorModifier_->SetLongPointHeadCurve(
1191         swiperPattern->GetIndicatorHeadCurve(), swiperPattern->GetMotionVelocity());
1192     dotIndicatorModifier_->SetUserSetSwiperCurve(swiperPattern->GetCurve());
1193     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
1194     CHECK_NULL_RETURN(swiperLayoutProperty, nullptr);
1195     auto paintMethod = MakeRefPtr<DotIndicatorPaintMethod>(dotIndicatorModifier_);
1196     SetDotIndicatorPaintMethodInfo(swiperPattern, paintMethod, swiperLayoutProperty);
1197 
1198     dotIndicatorModifier_->SetBoundsRect(CalcBoundsRect());
1199 
1200     return paintMethod;
1201 }
1202 
CalcBoundsRect() const1203 RectF SwiperIndicatorPattern::CalcBoundsRect() const
1204 {
1205     auto swiperNode = GetSwiperNode();
1206     CHECK_NULL_RETURN(swiperNode, RectF());
1207     auto geometryNode = swiperNode->GetGeometryNode();
1208     CHECK_NULL_RETURN(geometryNode, RectF());
1209     auto host = GetHost();
1210     CHECK_NULL_RETURN(host, RectF());
1211     auto indicatorGeometryNode = host->GetGeometryNode();
1212     CHECK_NULL_RETURN(indicatorGeometryNode, RectF());
1213     auto boundsValue = (geometryNode->GetFrameSize().Width() - indicatorGeometryNode->GetFrameSize().Width()) * 0.5f;
1214     auto boundsRectOriginX = -boundsValue;
1215     auto boundsRectOriginY = 0.0f;
1216     auto boundsRectWidth = geometryNode->GetFrameSize().Width();
1217     auto boundsRectHeight = indicatorGeometryNode->GetFrameSize().Height();
1218     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
1219     CHECK_NULL_RETURN(swiperPattern, RectF());
1220     if (GetDirection() == Axis::VERTICAL) {
1221         boundsValue = (geometryNode->GetFrameSize().Height() - indicatorGeometryNode->GetFrameSize().Height()) * 0.5f;
1222         boundsRectOriginX = 0.0f;
1223         boundsRectOriginY = -boundsValue;
1224         boundsRectWidth = indicatorGeometryNode->GetFrameSize().Width();
1225         boundsRectHeight = geometryNode->GetFrameSize().Height();
1226     }
1227     RectF boundsRect(boundsRectOriginX, boundsRectOriginY, boundsRectWidth, boundsRectHeight);
1228 
1229     return boundsRect;
1230 }
1231 
CheckDragAndUpdate(const RefPtr<SwiperPattern> & swiperPattern,int32_t animationStartIndex,int32_t animationEndIndex)1232 void SwiperIndicatorPattern::CheckDragAndUpdate(
1233     const RefPtr<SwiperPattern>& swiperPattern, int32_t animationStartIndex, int32_t animationEndIndex)
1234 {
1235     CHECK_NULL_VOID(swiperPattern);
1236 
1237     if (!swiperPattern->IsTouchDownOnOverlong()) {
1238         return;
1239     }
1240 
1241     auto bottomTouchLoop = swiperPattern->GetTouchBottomTypeLoop();
1242     auto turnPageRateAbs = std::abs(swiperPattern->GetTurnPageRate());
1243     auto totalCount = swiperPattern->RealTotalCount();
1244     auto loopDrag = (animationStartIndex == 0 && animationEndIndex == totalCount - 1 && turnPageRateAbs < HALF_FLOAT &&
1245                         turnPageRateAbs > 0.0f) ||
1246                     (animationStartIndex == animationEndIndex && animationEndIndex == totalCount - 1 &&
1247                         turnPageRateAbs > HALF_FLOAT);
1248     auto nonLoopDrag = bottomTouchLoop == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE &&
1249                        ((gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT && turnPageRateAbs > HALF_FLOAT) ||
1250                            (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT && turnPageRateAbs < HALF_FLOAT &&
1251                                turnPageRateAbs > 0.0f));
1252 
1253     if (loopDrag || nonLoopDrag) {
1254         overlongDotIndicatorModifier_->UpdateCurrentStatus();
1255     }
1256 }
1257 
UpdateOverlongPaintMethod(const RefPtr<SwiperPattern> & swiperPattern,RefPtr<OverlengthDotIndicatorPaintMethod> & overlongPaintMethod)1258 void SwiperIndicatorPattern::UpdateOverlongPaintMethod(
1259     const RefPtr<SwiperPattern>& swiperPattern, RefPtr<OverlengthDotIndicatorPaintMethod>& overlongPaintMethod)
1260 {
1261     auto animationStartIndex = swiperPattern->GetLoopIndex(swiperPattern->GetCurrentIndex(true));
1262     auto animationEndIndex = swiperPattern->GetLoopIndex(swiperPattern->GetCurrentFirstIndex());
1263 
1264     auto paintMethodTemp = DynamicCast<DotIndicatorPaintMethod>(overlongPaintMethod);
1265     if (changeIndexWithAnimation_ && !changeIndexWithAnimation_.value()) {
1266         animationStartIndex = startIndex_ ? startIndex_.value() : overlongDotIndicatorModifier_->GetAnimationEndIndex();
1267         paintMethodTemp->SetGestureState(GestureState::GESTURE_STATE_NONE);
1268     }
1269 
1270     if (jumpIndex_) {
1271         paintMethodTemp->SetGestureState(GestureState::GESTURE_STATE_NONE);
1272 
1273         if (!changeIndexWithAnimation_) {
1274             overlongDotIndicatorModifier_->StopAnimation(true);
1275             overlongDotIndicatorModifier_->SetCurrentOverlongType(OverlongType::NONE);
1276         }
1277     }
1278 
1279     auto isSwiperTouchDown = swiperPattern->IsTouchDownOnOverlong();
1280     auto isSwiperAnimationRunning =
1281         swiperPattern->IsPropertyAnimationRunning() || swiperPattern->IsTranslateAnimationRunning();
1282     auto keepStatus = !isSwiperTouchDown && !isSwiperAnimationRunning && animationStartIndex != animationEndIndex &&
1283                       !changeIndexWithAnimation_;
1284 
1285     if (!changeIndexWithAnimation_ && gestureState_ == GestureState::GESTURE_STATE_NONE) {
1286         keepStatus = true;
1287     }
1288 
1289     CheckDragAndUpdate(swiperPattern, animationStartIndex, animationEndIndex);
1290 
1291     if (!swiperPattern->IsLoop() && animationStartIndex == 0 &&
1292         gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT) {
1293         overlongPaintMethod->SetTouchBottomTypeLoop(TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT);
1294     }
1295 
1296     overlongPaintMethod->SetMaxDisplayCount(swiperPattern->GetMaxDisplayCount());
1297     overlongPaintMethod->SetKeepStatus(keepStatus);
1298     overlongPaintMethod->SetAnimationStartIndex(animationStartIndex);
1299     overlongPaintMethod->SetAnimationEndIndex(animationEndIndex);
1300     overlongPaintMethod->SetIsBindIndicator(swiperPattern->IsBindIndicator());
1301     overlongDotIndicatorModifier_->SetIsSwiperTouchDown(isSwiperTouchDown);
1302     overlongDotIndicatorModifier_->SetBoundsRect(CalcBoundsRect());
1303     overlongDotIndicatorModifier_->SetIsAutoPlay(swiperPattern->IsAutoPlay());
1304     changeIndexWithAnimation_.reset();
1305     jumpIndex_.reset();
1306     startIndex_.reset();
1307 }
1308 
ShowPrevious()1309 void SwiperIndicatorPattern::ShowPrevious()
1310 {
1311     auto swiperPattern = GetSwiperPattern();
1312     CHECK_NULL_VOID(swiperPattern);
1313     swiperPattern->ShowPrevious();
1314 }
1315 
ShowNext()1316 void SwiperIndicatorPattern::ShowNext()
1317 {
1318     auto swiperPattern = GetSwiperPattern();
1319     CHECK_NULL_VOID(swiperPattern);
1320     swiperPattern->ShowNext();
1321 }
1322 
ChangeIndex(int32_t index,bool useAnimation)1323 void SwiperIndicatorPattern::ChangeIndex(int32_t index, bool useAnimation)
1324 {
1325     auto swiperPattern = GetSwiperPattern();
1326     CHECK_NULL_VOID(swiperPattern);
1327     swiperPattern->ChangeIndex(index, useAnimation);
1328 }
1329 
GetTouchCurrentIndex() const1330 int32_t SwiperIndicatorPattern::GetTouchCurrentIndex() const
1331 {
1332     return GetCurrentIndex();
1333 }
1334 
GetCurrentIndex() const1335 int32_t SwiperIndicatorPattern::GetCurrentIndex() const
1336 {
1337     auto swiperPattern = GetSwiperPattern();
1338     CHECK_NULL_RETURN(swiperPattern, 0);
1339     auto currentIndex = swiperPattern->GetCurrentIndex();
1340     auto isRtl = swiperPattern->IsHorizontalAndRightToLeft();
1341     auto indicatorCount = swiperPattern->DisplayIndicatorTotalCount();
1342     auto displayCount = swiperPattern->GetDisplayCount();
1343 
1344     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) &&
1345         swiperPattern->IsSwipeByGroup() && displayCount != 0) {
1346         currentIndex /= displayCount;
1347     }
1348 
1349     if (isRtl) {
1350         currentIndex = indicatorCount - 1 - currentIndex;
1351     }
1352     return currentIndex;
1353 }
1354 
GetCurrentShownIndex() const1355 int32_t SwiperIndicatorPattern::GetCurrentShownIndex() const
1356 {
1357     auto swiperPattern = GetSwiperPattern();
1358     CHECK_NULL_RETURN(swiperPattern, 0);
1359     return swiperPattern->GetCurrentShownIndex();
1360 }
1361 
RealTotalCount() const1362 int32_t SwiperIndicatorPattern::RealTotalCount() const
1363 {
1364     auto swiperPattern = GetSwiperPattern();
1365     CHECK_NULL_RETURN(swiperPattern, 0);
1366     return swiperPattern->RealTotalCount();
1367 }
1368 
DisplayIndicatorTotalCount() const1369 int32_t SwiperIndicatorPattern::DisplayIndicatorTotalCount() const
1370 {
1371     auto swiperPattern = GetSwiperPattern();
1372     CHECK_NULL_RETURN(swiperPattern, 0);
1373     return swiperPattern->DisplayIndicatorTotalCount();
1374 }
1375 
GetDirection() const1376 Axis SwiperIndicatorPattern::GetDirection() const
1377 {
1378     auto swiperPattern = GetSwiperPattern();
1379     CHECK_NULL_RETURN(swiperPattern, Axis::HORIZONTAL);
1380     return swiperPattern->GetDirection();
1381 }
1382 
IsHorizontalAndRightToLeft() const1383 bool SwiperIndicatorPattern::IsHorizontalAndRightToLeft() const
1384 {
1385     auto swiperPattern = GetSwiperPattern();
1386     CHECK_NULL_RETURN(swiperPattern, false);
1387     return swiperPattern->IsHorizontalAndRightToLeft();
1388 }
1389 
GetNonAutoLayoutDirection() const1390 TextDirection SwiperIndicatorPattern::GetNonAutoLayoutDirection() const
1391 {
1392     auto swiperPattern = GetSwiperPattern();
1393     CHECK_NULL_RETURN(swiperPattern, TextDirection::LTR);
1394     return swiperPattern->GetNonAutoLayoutDirection();
1395 }
1396 
IsLoop() const1397 bool SwiperIndicatorPattern::IsLoop() const
1398 {
1399     auto swiperPattern = GetSwiperPattern();
1400     CHECK_NULL_RETURN(swiperPattern, true);
1401     return swiperPattern->IsLoop();
1402 }
1403 
GetTextContentSub(std::string & firstContent,std::string & lastContent) const1404 void SwiperIndicatorPattern::GetTextContentSub(std::string& firstContent, std::string& lastContent) const
1405 {
1406     auto swiperPattern = GetSwiperPattern();
1407     CHECK_NULL_VOID(swiperPattern);
1408     auto currentIndex = GetDisplayCurrentIndex();
1409     bool isRtl = swiperPattern->GetNonAutoLayoutDirection() == TextDirection::RTL;
1410     firstContent = isRtl ? std::to_string(swiperPattern->RealTotalCount()) : std::to_string(currentIndex);
1411     lastContent = isRtl ? std::to_string(currentIndex) + "\\" : "/" + std::to_string(swiperPattern->RealTotalCount());
1412 }
1413 
SwipeTo(std::optional<int32_t> mouseClickIndex)1414 void SwiperIndicatorPattern::SwipeTo(std::optional<int32_t> mouseClickIndex)
1415 {
1416     auto swiperNode = GetSwiperNode();
1417     CHECK_NULL_VOID(swiperNode);
1418     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
1419     CHECK_NULL_VOID(swiperPattern);
1420     if (swiperPattern->IsSwipeByGroup()) {
1421         auto clickPageIndex = SwiperUtils::ComputePageIndex(mouseClickIndex.value(), swiperPattern->GetDisplayCount());
1422         mouseClickIndex_ = clickPageIndex;
1423     }
1424     swiperPattern->SwipeTo(mouseClickIndex_.value());
1425 }
1426 
CalculateStepAndItemCountDefault() const1427 std::pair<int32_t, int32_t> SwiperIndicatorPattern::CalculateStepAndItemCountDefault() const
1428 {
1429     int32_t itemCount = RealTotalCount();
1430     int32_t step = 1;
1431     return { itemCount, step };
1432 }
1433 
CalculateStepAndItemCount() const1434 std::pair<int32_t, int32_t> SwiperIndicatorPattern::CalculateStepAndItemCount() const
1435 {
1436     auto swiperPattern = GetSwiperPattern();
1437     CHECK_NULL_RETURN(swiperPattern, CalculateStepAndItemCountDefault());
1438     return swiperPattern->CalculateStepAndItemCount();
1439 }
1440 
GetDotCurrentOffset(OffsetF & offset,float indicatorWidth,float indicatorHeight)1441 bool SwiperIndicatorPattern::GetDotCurrentOffset(OffsetF& offset, float indicatorWidth, float indicatorHeight)
1442 {
1443     auto frameNode = GetHost();
1444     CHECK_NULL_RETURN(frameNode, true);
1445     auto swiperNode = GetSwiperNode();
1446     CHECK_NULL_RETURN(swiperNode, true);
1447     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
1448     CHECK_NULL_RETURN(swiperLayoutProperty, true);
1449     auto indicatorlayoutProperty = frameNode->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
1450     CHECK_NULL_RETURN(indicatorlayoutProperty, true);
1451 
1452     offset = SwiperIndicatorUtils::CalcIndicatrFrameOffSet(
1453         swiperLayoutProperty, indicatorlayoutProperty, indicatorWidth, indicatorHeight);
1454     return true;
1455 }
1456 
GetLoopIndex(int32_t originalIndex) const1457 int32_t SwiperIndicatorPattern::GetLoopIndex(int32_t originalIndex) const
1458 {
1459     auto realTotalCount = RealTotalCount();
1460     if (realTotalCount <= 0) {
1461         return originalIndex;
1462     }
1463     auto loopIndex = originalIndex;
1464     while (loopIndex < 0) {
1465         loopIndex = loopIndex + realTotalCount;
1466     }
1467     if (realTotalCount != 0) {
1468         loopIndex %= realTotalCount;
1469     }
1470     return loopIndex;
1471 }
1472 
IndicatorOnChange()1473 void SwiperIndicatorPattern::IndicatorOnChange()
1474 {
1475     auto host = GetHost();
1476     CHECK_NULL_VOID(host);
1477     auto pipeline = PipelineContext::GetCurrentContextSafely();
1478     CHECK_NULL_VOID(pipeline);
1479     pipeline->AddAfterLayoutTask([weak = AceType::WeakClaim(RawPtr(host)), context = AceType::WeakClaim(this)]() {
1480         auto indicator = weak.Upgrade();
1481         CHECK_NULL_VOID(indicator);
1482         auto textContext = context.Upgrade();
1483         CHECK_NULL_VOID(textContext);
1484         if (textContext->GetIndicatorType() == SwiperIndicatorType::DIGIT) {
1485             RefPtr<FrameNode> firstTextNode;
1486             RefPtr<FrameNode> lastTextNode;
1487             auto layoutProperty = indicator->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
1488             firstTextNode = DynamicCast<FrameNode>(indicator->GetFirstChild());
1489             lastTextNode = DynamicCast<FrameNode>(indicator->GetLastChild());
1490             textContext->UpdateTextContent(layoutProperty, firstTextNode, lastTextNode);
1491         }
1492         indicator->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1493     });
1494     pipeline->RequestFrame();
1495 }
1496 
GetDigitFrameSize(RefPtr<GeometryNode> & geoNode,SizeF & frameSize) const1497 bool SwiperIndicatorPattern::GetDigitFrameSize(RefPtr<GeometryNode>& geoNode, SizeF& frameSize) const
1498 {
1499     CHECK_NULL_RETURN(geoNode, false);
1500     frameSize = geoNode->GetMarginFrameSize();
1501     return true;
1502 }
1503 
DumpAdvanceInfo(std::unique_ptr<JsonValue> & json)1504 void SwiperIndicatorPattern::DumpAdvanceInfo(std::unique_ptr<JsonValue>& json)
1505 {
1506     json->Put("isHover", isHover_);
1507     json->Put("isPressed", isPressed_);
1508     json->Put("isClicked", isClicked_);
1509     json->Put("isRepeatClicked", isRepeatClicked_);
1510     switch (GetIndicatorType()) {
1511         case SwiperIndicatorType::DOT: {
1512             json->Put("SwiperIndicatorType", "DOT");
1513             break;
1514         }
1515         case SwiperIndicatorType::DIGIT: {
1516             json->Put("SwiperIndicatorType", "DIGIT");
1517             break;
1518         }
1519         default: {
1520             break;
1521         }
1522     }
1523 }
1524 } // namespace OHOS::Ace::NG
1525