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 "base/log/dump_log.h"
19 #include "base/utils/utils.h"
20 #include "core/components_ng/base/frame_node.h"
21 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
22 #include "core/components_ng/pattern/swiper/swiper_utils.h"
23 #include "core/event/ace_events.h"
24 #include "core/event/mouse_event.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 constexpr Dimension INDICATOR_PADDING_DOT = 12.0_vp;
30 constexpr float INDICATOR_ZOOM_IN_SCALE = 1.33f;
31 constexpr Dimension INDICATOR_ITEM_SPACE = 8.0_vp;
32 constexpr Dimension INDICATOR_PADDING_DEFAULT = 12.0_vp;
33 constexpr uint32_t INDICATOR_HAS_CHILD = 2;
34 constexpr Dimension INDICATOR_DRAG_MIN_DISTANCE = 4.0_vp;
35 constexpr Dimension INDICATOR_DRAG_MAX_DISTANCE = 18.0_vp;
36 constexpr Dimension INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE = 80.0_vp;
37 constexpr int32_t LONG_PRESS_DELAY = 300;
38 constexpr float HALF_FLOAT = 0.5f;
39 constexpr float MAX_FONT_SCALE = 2.0f;
40 } // namespace
41 
OnAttachToFrameNode()42 void SwiperIndicatorPattern::OnAttachToFrameNode()
43 {
44     auto host = GetHost();
45     CHECK_NULL_VOID(host);
46     host->GetRenderContext()->SetClipToBounds(true);
47 }
48 
OnModifyDone()49 void SwiperIndicatorPattern::OnModifyDone()
50 {
51     Pattern::OnModifyDone();
52     auto host = GetHost();
53     CHECK_NULL_VOID(host);
54 
55     auto swiperNode = GetSwiperNode();
56     CHECK_NULL_VOID(swiperNode);
57     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
58     CHECK_NULL_VOID(swiperPattern);
59     swiperIndicatorType_ = swiperPattern->GetIndicatorType();
60     if (swiperIndicatorType_ == SwiperIndicatorType::DIGIT) {
61         RefPtr<FrameNode> firstTextNode;
62         RefPtr<FrameNode> lastTextNode;
63         auto layoutProperty = host->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
64         CHECK_NULL_VOID(layoutProperty);
65         if (host->GetChildren().size() == INDICATOR_HAS_CHILD) {
66             firstTextNode = DynamicCast<FrameNode>(host->GetFirstChild());
67             lastTextNode = DynamicCast<FrameNode>(host->GetLastChild());
68         } else {
69             host->Clean();
70             firstTextNode = FrameNode::CreateFrameNode(
71                 V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
72             lastTextNode = FrameNode::CreateFrameNode(
73                 V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
74         }
75         UpdateTextContent(layoutProperty, firstTextNode, lastTextNode);
76         host->AddChild(firstTextNode);
77         host->AddChild(lastTextNode);
78     } else {
79         host->Clean();
80     }
81 
82     if (dotIndicatorModifier_) {
83         dotIndicatorModifier_->StopAnimation();
84     }
85 
86     auto swiperEventHub = swiperPattern->GetEventHub<SwiperEventHub>();
87     CHECK_NULL_VOID(swiperEventHub);
88 
89     swiperEventHub->SetIndicatorOnChange(
90         [weak = AceType::WeakClaim(RawPtr(host)), context = AceType::WeakClaim(this)]() {
91             auto pipeline = PipelineContext::GetCurrentContextSafely();
92             CHECK_NULL_VOID(pipeline);
93             pipeline->AddAfterLayoutTask([weak, context]() {
94                 auto indicator = weak.Upgrade();
95                 CHECK_NULL_VOID(indicator);
96                 auto textContext = context.Upgrade();
97                 CHECK_NULL_VOID(textContext);
98                 if (textContext->swiperIndicatorType_ == SwiperIndicatorType::DIGIT) {
99                     RefPtr<FrameNode> firstTextNode;
100                     RefPtr<FrameNode> lastTextNode;
101                     auto layoutProperty = indicator->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
102                     firstTextNode = DynamicCast<FrameNode>(indicator->GetFirstChild());
103                     lastTextNode = DynamicCast<FrameNode>(indicator->GetLastChild());
104                     textContext->UpdateTextContent(layoutProperty, firstTextNode, lastTextNode);
105                 }
106                 indicator->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
107             });
108             pipeline->RequestFrame();
109         });
110     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
111     CHECK_NULL_VOID(swiperLayoutProperty);
112     if (swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::DOT) == SwiperIndicatorType::DOT) {
113         auto gestureHub = host->GetOrCreateGestureEventHub();
114         CHECK_NULL_VOID(gestureHub);
115         InitClickEvent(gestureHub);
116         InitHoverMouseEvent();
117         InitTouchEvent(gestureHub);
118         InitLongPressEvent(gestureHub);
119     }
120 }
121 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)122 bool SwiperIndicatorPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
123 {
124     CHECK_NULL_RETURN(config.frameSizeChange, false);
125     return true;
126 }
127 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)128 void SwiperIndicatorPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
129 {
130     CHECK_NULL_VOID(!clickEvent_);
131     auto clickTask = [weak = WeakClaim(this)](const GestureEvent& info) {
132         auto pattern = weak.Upgrade();
133         CHECK_NULL_VOID(pattern);
134         pattern->HandleClick(info);
135     };
136     clickEvent_ = MakeRefPtr<ClickEvent>(std::move(clickTask));
137     gestureHub->AddClickEvent(clickEvent_);
138 }
139 
HandleClick(const GestureEvent & info)140 void SwiperIndicatorPattern::HandleClick(const GestureEvent& info)
141 {
142     if (info.GetSourceDevice() == SourceType::KEYBOARD) {
143         return;
144     }
145 
146     if (info.GetSourceDevice() == SourceType::MOUSE) {
147         isClicked_ = true;
148         HandleMouseClick(info);
149     } else {
150         HandleTouchClick(info);
151     }
152 }
153 
HandleMouseClick(const GestureEvent &)154 void SwiperIndicatorPattern::HandleMouseClick(const GestureEvent& /* info */)
155 {
156     if (isRepeatClicked_) {
157         return;
158     }
159     GetMouseClickIndex();
160     CHECK_NULL_VOID(mouseClickIndex_);
161     auto swiperNode = GetSwiperNode();
162     CHECK_NULL_VOID(swiperNode);
163     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
164     CHECK_NULL_VOID(swiperPattern);
165 
166     if (swiperPattern->IsSwipeByGroup()) {
167         auto clickPageIndex = SwiperUtils::ComputePageIndex(mouseClickIndex_.value(), swiperPattern->GetDisplayCount());
168         if (clickPageIndex == swiperPattern->GetCurrentIndex()) {
169             mouseClickIndex_ = std::nullopt;
170             return;
171         }
172 
173         mouseClickIndex_ = clickPageIndex;
174     }
175 
176     swiperPattern->SwipeTo(mouseClickIndex_.value());
177     auto host = GetHost();
178     CHECK_NULL_VOID(host);
179     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
180 }
181 
HandleTouchClick(const GestureEvent & info)182 void SwiperIndicatorPattern::HandleTouchClick(const GestureEvent& info)
183 {
184     auto host = GetHost();
185     CHECK_NULL_VOID(host);
186     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
187     CHECK_NULL_VOID(paintProperty);
188     auto pipeline = PipelineBase::GetCurrentContext();
189     CHECK_NULL_VOID(pipeline);
190     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
191     CHECK_NULL_VOID(theme);
192     auto itemWidth = paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx();
193     auto selectedItemWidth = paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx();
194     if (Negative(itemWidth) || Negative(selectedItemWidth)) {
195         itemWidth = theme->GetSize().ConvertToPx();
196         selectedItemWidth = theme->GetSize().ConvertToPx();
197     }
198     auto swiperNode = GetSwiperNode();
199     CHECK_NULL_VOID(swiperNode);
200     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
201     CHECK_NULL_VOID(swiperPattern);
202 
203     auto isRtl = swiperPattern->GetNonAutoLayoutDirection() == TextDirection::RTL;
204     auto indicatorCount = swiperPattern->RealTotalCount();
205     auto currentIndex = swiperPattern->GetCurrentIndex();
206     if (isRtl) {
207         currentIndex = indicatorCount - 1 - currentIndex;
208     }
209 
210     auto margin = HandleTouchClickMargin();
211     auto lengthBeforeCurrentIndex = margin + INDICATOR_PADDING_DEFAULT.ConvertToPx() +
212                                     (INDICATOR_ITEM_SPACE.ConvertToPx() + itemWidth) * currentIndex;
213     auto lengthWithCurrentIndex = lengthBeforeCurrentIndex + selectedItemWidth;
214     auto axis = swiperPattern->GetDirection();
215     auto mainClickOffset = axis == Axis::HORIZONTAL ? info.GetLocalLocation().GetX() : info.GetLocalLocation().GetY();
216     if (mainClickOffset < lengthBeforeCurrentIndex) {
217         isRtl ? swiperPattern->ShowNext() : swiperPattern->ShowPrevious();
218     } else if (mainClickOffset > lengthWithCurrentIndex) {
219         isRtl ? swiperPattern->ShowPrevious() : swiperPattern->ShowNext();
220     }
221 }
222 
InitHoverMouseEvent()223 void SwiperIndicatorPattern::InitHoverMouseEvent()
224 {
225     auto host = GetHost();
226     CHECK_NULL_VOID(host);
227     auto eventHub = host->GetEventHub<EventHub>();
228     CHECK_NULL_VOID(eventHub);
229     auto inputHub = eventHub->GetOrCreateInputEventHub();
230     CHECK_NULL_VOID(inputHub);
231 
232     auto hoverTask = [weak = WeakClaim(this)](bool isHover, HoverInfo& info) {
233         auto pattern = weak.Upgrade();
234         if (pattern && info.GetSourceDevice() != SourceType::TOUCH) {
235             pattern->HandleHoverEvent(isHover);
236         }
237     };
238 
239     if (!hoverEvent_) {
240         hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
241         inputHub->AddOnHoverEvent(hoverEvent_);
242     }
243 
244     auto mouseEvent = [weak = WeakClaim(this)](MouseInfo& info) {
245         auto pattern = weak.Upgrade();
246         if (pattern) {
247             pattern->HandleMouseEvent(info);
248         }
249     };
250     if (mouseEvent_) {
251         inputHub->RemoveOnMouseEvent(mouseEvent_);
252     }
253     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseEvent));
254     inputHub->AddOnMouseEvent(mouseEvent_);
255 }
256 
HandleMouseEvent(const MouseInfo & info)257 void SwiperIndicatorPattern::HandleMouseEvent(const MouseInfo& info)
258 {
259     if (info.GetSourceDevice() == SourceType::TOUCH) {
260         return;
261     }
262     auto mouseOffsetX = static_cast<float>(info.GetLocalLocation().GetX());
263     auto mouseOffsetY = static_cast<float>(info.GetLocalLocation().GetY());
264     auto mouseAction = info.GetAction();
265     if ((mouseAction == MouseAction::PRESS || mouseAction == MouseAction::RELEASE) &&
266         isClicked_ && NearEqual(hoverPoint_, PointF(mouseOffsetX, mouseOffsetY))) {
267         isRepeatClicked_ = true;
268         return;
269     }
270     isClicked_ = false;
271     isRepeatClicked_ = false;
272     auto host = GetHost();
273     CHECK_NULL_VOID(host);
274     hoverPoint_.SetX(mouseOffsetX);
275     hoverPoint_.SetY(mouseOffsetY);
276 
277     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
278 }
279 
HandleHoverEvent(bool isHover)280 void SwiperIndicatorPattern::HandleHoverEvent(bool isHover)
281 {
282     if (isHover_ == isHover) {
283         return;
284     }
285 
286     isHover_ = isHover;
287     auto host = GetHost();
288     CHECK_NULL_VOID(host);
289     auto swiperNode = GetSwiperNode();
290     CHECK_NULL_VOID(swiperNode);
291     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
292     CHECK_NULL_VOID(swiperPattern);
293     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
294     CHECK_NULL_VOID(swiperLayoutProperty);
295     if (swiperLayoutProperty->GetHoverShowValue(false) && !swiperPattern->GetIsAtHotRegion()) {
296         swiperPattern->ArrowHover(isHover_);
297     }
298     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
299 }
300 
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)301 void SwiperIndicatorPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
302 {
303     if (touchEvent_) {
304         return;
305     }
306 
307     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
308         auto pattern = weak.Upgrade();
309         if (pattern) {
310             pattern->HandleTouchEvent(info);
311         }
312     };
313 
314     if (touchEvent_) {
315         gestureHub->RemoveTouchEvent(touchEvent_);
316     }
317     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
318     gestureHub->AddTouchEvent(touchEvent_);
319 
320     auto swiperNode = GetSwiperNode();
321     CHECK_NULL_VOID(swiperNode);
322     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
323     CHECK_NULL_VOID(swiperPattern);
324     auto stopAnimationCb = [weak = WeakClaim(this)](bool ifImmediately) {
325         auto pattern = weak.Upgrade();
326         if (pattern) {
327             if (pattern->dotIndicatorModifier_) {
328                 pattern->dotIndicatorModifier_->StopAnimation(ifImmediately);
329             }
330 
331             if (pattern->overlongDotIndicatorModifier_) {
332                 pattern->overlongDotIndicatorModifier_->StopAnimation(ifImmediately);
333             }
334         }
335     };
336     swiperPattern->SetStopIndicatorAnimationCb(stopAnimationCb);
337 }
338 
HandleTouchEvent(const TouchEventInfo & info)339 void SwiperIndicatorPattern::HandleTouchEvent(const TouchEventInfo& info)
340 {
341     auto touchType = info.GetTouches().front().GetTouchType();
342     if (touchType == TouchType::UP) {
343         HandleTouchUp();
344         HandleDragEnd(0);
345         isPressed_ = false;
346     } else if (touchType == TouchType::CANCEL) {
347         HandleTouchUp();
348         HandleDragEnd(0);
349         isPressed_ = false;
350     }
351     if (isPressed_) {
352         HandleLongDragUpdate(info.GetTouches().front());
353     }
354 }
355 
HandleTouchDown()356 void SwiperIndicatorPattern::HandleTouchDown()
357 {
358     isPressed_ = true;
359     auto host = GetHost();
360     CHECK_NULL_VOID(host);
361     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
362 }
363 
HandleTouchUp()364 void SwiperIndicatorPattern::HandleTouchUp()
365 {
366     isPressed_ = false;
367     auto host = GetHost();
368     CHECK_NULL_VOID(host);
369     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
370 }
371 
GetMouseClickIndex()372 void SwiperIndicatorPattern::GetMouseClickIndex()
373 {
374     auto pipelineContext = PipelineBase::GetCurrentContext();
375     CHECK_NULL_VOID(pipelineContext);
376     auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
377     CHECK_NULL_VOID(swiperTheme);
378     auto host = GetHost();
379     CHECK_NULL_VOID(host);
380     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
381     CHECK_NULL_VOID(paintProperty);
382     auto swiperNode = GetSwiperNode();
383     CHECK_NULL_VOID(swiperNode);
384     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
385     CHECK_NULL_VOID(swiperPattern);
386     float itemWidthValue = static_cast<float>(paintProperty->GetItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
387     float itemHeightValue = static_cast<float>(paintProperty->GetItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
388     float selectedItemWidthValue =
389         static_cast<float>(paintProperty->GetSelectedItemWidthValue(swiperTheme->GetSize()).ConvertToPx() * 2);
390     paintProperty->GetIsCustomSizeValue(false) ? selectedItemWidthValue *= 0.5f : selectedItemWidthValue;
391     // diameter calculation
392     float itemWidth = itemWidthValue * INDICATOR_ZOOM_IN_SCALE;
393     float itemHeight = itemHeightValue * INDICATOR_ZOOM_IN_SCALE;
394     float selectedItemWidth = selectedItemWidthValue * INDICATOR_ZOOM_IN_SCALE;
395     float space = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx());
396     int32_t currentIndex = swiperPattern->GetCurrentShownIndex();
397     int32_t itemCount = swiperPattern->RealTotalCount();
398     int32_t loopCount = SwiperIndicatorUtils::CalcLoopCount(currentIndex, itemCount);
399     auto frameSize = host->GetGeometryNode()->GetFrameSize();
400     auto axis = swiperPattern->GetDirection();
401     float centerX = static_cast<float>(INDICATOR_PADDING_DOT.ConvertToPx());
402     float centerY = ((axis == Axis::HORIZONTAL ? frameSize.Height() : frameSize.Width()) - itemHeight) * 0.5f;
403     PointF hoverPoint = axis == Axis::HORIZONTAL ? hoverPoint_ : PointF(hoverPoint_.GetY(), hoverPoint_.GetX());
404     int start = currentIndex >= 0 ? loopCount * itemCount : -(loopCount + 1) * itemCount;
405     int end = currentIndex >= 0 ? (loopCount + 1) * itemCount : -loopCount * itemCount;
406     if (swiperPattern->IsHorizontalAndRightToLeft()) {
407         end = currentIndex >= 0 ? loopCount * itemCount - 1 : -(loopCount + 1) * itemCount - 1;
408         start = currentIndex >= 0 ? (loopCount + 1) * itemCount - 1 : -loopCount * itemCount - 1;
409     }
410     for (int32_t i = start; i != end; start > end ? --i : ++i) {
411         if (i != currentIndex) {
412             if (hoverPoint.GetX() >= centerX && hoverPoint.GetX() <= centerX + itemWidth &&
413                 hoverPoint.GetY() >= centerY && hoverPoint.GetY() <= centerY + itemHeight) {
414                 mouseClickIndex_ = i;
415                 break;
416             }
417             centerX += itemWidth + space;
418         } else {
419             centerX += selectedItemWidth + space;
420         }
421     }
422 }
423 
UpdateTextContent(const RefPtr<SwiperIndicatorLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & firstTextNode,const RefPtr<FrameNode> & lastTextNode)424 void SwiperIndicatorPattern::UpdateTextContent(const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
425     const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode)
426 {
427     CHECK_NULL_VOID(layoutProperty);
428     CHECK_NULL_VOID(firstTextNode);
429     CHECK_NULL_VOID(lastTextNode);
430     auto pipeline = PipelineBase::GetCurrentContext();
431     CHECK_NULL_VOID(pipeline);
432     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
433     firstTextNode->SetInternal();
434     lastTextNode->SetInternal();
435     auto firstTextLayoutProperty = firstTextNode->GetLayoutProperty<TextLayoutProperty>();
436     CHECK_NULL_VOID(firstTextLayoutProperty);
437     auto selectedFontColor =
438         layoutProperty->GetSelectedFontColorValue(theme->GetDigitalIndicatorTextStyle().GetTextColor());
439     auto selectedFontSize =
440         layoutProperty->GetSelectedFontSizeValue(theme->GetDigitalIndicatorTextStyle().GetFontSize());
441     if (!selectedFontSize.IsValid()) {
442         selectedFontSize = theme->GetDigitalIndicatorTextStyle().GetFontSize();
443     }
444     auto selectedFontWeight =
445         layoutProperty->GetSelectedFontWeightValue(theme->GetDigitalIndicatorTextStyle().GetFontWeight());
446     firstTextLayoutProperty->UpdateTextColor(selectedFontColor);
447     firstTextLayoutProperty->UpdateFontSize(selectedFontSize);
448     firstTextLayoutProperty->UpdateFontWeight(selectedFontWeight);
449     firstTextLayoutProperty->UpdateMaxFontScale(MAX_FONT_SCALE);
450     UpdateTextContentSub(layoutProperty, firstTextNode, lastTextNode);
451 }
452 
GetDisplayCurrentIndex() const453 int32_t SwiperIndicatorPattern::GetDisplayCurrentIndex() const
454 {
455     auto swiperNode = GetSwiperNode();
456     CHECK_NULL_RETURN(swiperNode, 0);
457     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
458     CHECK_NULL_RETURN(swiperPattern, 0);
459     CHECK_NULL_RETURN(swiperPattern->RealTotalCount(), 0);
460     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
461     CHECK_NULL_RETURN(swiperLayoutProperty, 0);
462     auto currentIndex = swiperPattern->GetCurrentFirstIndex() + 1;
463     if (currentIndex > swiperPattern->RealTotalCount()) {
464         currentIndex = 1;
465     } else if (swiperLayoutProperty->HasIndex()) {
466         currentIndex = GetCurrentIndex() + 1;
467         if (currentIndex > swiperPattern->RealTotalCount()) {
468             currentIndex = 1;
469         }
470     }
471 
472     return currentIndex;
473 }
474 
GetCurrentIndex() const475 int32_t SwiperIndicatorPattern::GetCurrentIndex() const
476 {
477     auto swiperNode = GetSwiperNode();
478     CHECK_NULL_RETURN(swiperNode, 0);
479     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
480     CHECK_NULL_RETURN(swiperPattern, 0);
481     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
482     CHECK_NULL_RETURN(swiperLayoutProperty, 0);
483     auto currentIndex = swiperLayoutProperty->GetIndex().value_or(0);
484     if (swiperPattern->IsSwipeByGroup()) {
485         currentIndex = SwiperUtils::ComputePageIndex(currentIndex, swiperPattern->GetDisplayCount());
486     }
487 
488     return currentIndex;
489 }
490 
UpdateTextContentSub(const RefPtr<SwiperIndicatorLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & firstTextNode,const RefPtr<FrameNode> & lastTextNode)491 void SwiperIndicatorPattern::UpdateTextContentSub(const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
492     const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode)
493 {
494     CHECK_NULL_VOID(layoutProperty);
495     CHECK_NULL_VOID(firstTextNode);
496     CHECK_NULL_VOID(lastTextNode);
497     auto swiperNode = GetSwiperNode();
498     CHECK_NULL_VOID(swiperNode);
499     auto pipeline = PipelineBase::GetCurrentContext();
500     CHECK_NULL_VOID(pipeline);
501     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
502     CHECK_NULL_VOID(swiperPattern);
503     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
504     CHECK_NULL_VOID(swiperLayoutProperty);
505     auto currentIndex = GetDisplayCurrentIndex();
506     auto lastTextLayoutProperty = lastTextNode->GetLayoutProperty<TextLayoutProperty>();
507     CHECK_NULL_VOID(lastTextLayoutProperty);
508     lastTextLayoutProperty->UpdateLayoutDirection(swiperPattern->GetNonAutoLayoutDirection());
509     bool isRtl = swiperPattern->GetNonAutoLayoutDirection() == TextDirection::RTL;
510     std::string firstContent = isRtl ? std::to_string(swiperPattern->RealTotalCount()) : std::to_string(currentIndex);
511     std::string lastContent = isRtl ? std::to_string(currentIndex) + "\\" :
512         "/" + std::to_string(swiperPattern->RealTotalCount());
513 
514     auto firstTextLayoutProperty = firstTextNode->GetLayoutProperty<TextLayoutProperty>();
515     CHECK_NULL_VOID(firstTextLayoutProperty);
516     firstTextLayoutProperty->UpdateContent(firstContent);
517     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
518     CHECK_NULL_VOID(theme);
519     auto fontColor = layoutProperty->GetFontColorValue(theme->GetDigitalIndicatorTextStyle().GetTextColor());
520     auto fontSize = layoutProperty->GetFontSizeValue(theme->GetDigitalIndicatorTextStyle().GetFontSize());
521     if (!fontSize.IsValid()) {
522         fontSize = theme->GetDigitalIndicatorTextStyle().GetFontSize();
523     }
524     auto fontWeight = layoutProperty->GetFontWeightValue(theme->GetDigitalIndicatorTextStyle().GetFontWeight());
525     lastTextLayoutProperty->UpdateTextColor(fontColor);
526     lastTextLayoutProperty->UpdateFontSize(fontSize);
527     lastTextLayoutProperty->UpdateFontWeight(fontWeight);
528     lastTextLayoutProperty->UpdateContent(lastContent);
529     lastTextLayoutProperty->UpdateMaxFontScale(MAX_FONT_SCALE);
530     firstTextNode->MarkModifyDone();
531     firstTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
532     lastTextNode->MarkModifyDone();
533     lastTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
534 }
535 
HandleDragStart(const GestureEvent & info)536 void SwiperIndicatorPattern::HandleDragStart(const GestureEvent& info)
537 {
538     dragStartPoint_ =
539         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
540 }
541 
HandleDragEnd(double dragVelocity)542 void SwiperIndicatorPattern::HandleDragEnd(double dragVelocity)
543 {
544     auto swiperNode = GetSwiperNode();
545     CHECK_NULL_VOID(swiperNode);
546     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
547     CHECK_NULL_VOID(swiperPattern);
548     swiperPattern->SetTurnPageRate(0.0f);
549     auto swiperPaintProperty = swiperPattern->GetPaintProperty<SwiperPaintProperty>();
550     CHECK_NULL_VOID(swiperPaintProperty);
551     auto autoPlay = swiperPaintProperty->GetAutoPlay().value_or(false);
552     if (autoPlay) {
553         swiperPattern->SetIndicatorLongPress(false);
554         swiperPattern->StartAutoPlay();
555     }
556     auto host = GetHost();
557     CHECK_NULL_VOID(host);
558     touchBottomType_ = TouchBottomType::NONE;
559     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
560 }
561 
SetIndicatorInteractive(bool isInteractive)562 void SwiperIndicatorPattern::SetIndicatorInteractive(bool isInteractive)
563 {
564     auto host = GetHost();
565     CHECK_NULL_VOID(host);
566     auto eventHub = host->GetEventHub<EventHub>();
567     CHECK_NULL_VOID(eventHub);
568     if (isInteractive) {
569         eventHub->SetEnabled(true);
570     } else {
571         eventHub->SetEnabled(false);
572     }
573 }
574 
CheckIsTouchBottom(const GestureEvent & info)575 bool SwiperIndicatorPattern::CheckIsTouchBottom(const GestureEvent& info)
576 {
577     auto swiperNode = GetSwiperNode();
578     CHECK_NULL_RETURN(swiperNode, false);
579     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
580     CHECK_NULL_RETURN(swiperPattern, false);
581     auto currentIndex = swiperPattern->GetCurrentIndex();
582     auto childrenSize = swiperPattern->RealTotalCount();
583 
584     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
585     CHECK_NULL_RETURN(swiperLayoutProperty, false);
586     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
587     auto isLoop = swiperLayoutProperty->GetLoop().value_or(true);
588     auto dragPoint =
589         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
590     auto offset = dragPoint - dragStartPoint_;
591     auto touchOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
592     auto touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx())
593                                ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx()
594                                : 1;
595 
596     swiperPattern->SetTurnPageRate(0);
597     swiperPattern->SetTouchBottomRate(std::abs(touchBottomRate));
598     TouchBottomType touchBottomType = TouchBottomType::NONE;
599 
600     if ((currentIndex <= 0) && !isLoop) {
601         if (Negative(info.GetMainDelta()) || NonPositive(touchOffset)) {
602             touchBottomType = TouchBottomType::START;
603         }
604     }
605 
606     if ((currentIndex >= childrenSize - displayCount) && !isLoop) {
607         if (Positive(info.GetMainDelta()) || NonNegative(touchOffset)) {
608             touchBottomType = TouchBottomType::END;
609         }
610     }
611 
612     touchBottomType_ = touchBottomType;
613     auto host = GetHost();
614     CHECK_NULL_RETURN(host, false);
615     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
616 
617     return touchBottomType == TouchBottomType::NONE ? false : true;
618 }
619 
CheckIsTouchBottom(const TouchLocationInfo & info)620 bool SwiperIndicatorPattern::CheckIsTouchBottom(const TouchLocationInfo& info)
621 {
622     auto swiperNode = GetSwiperNode();
623     CHECK_NULL_RETURN(swiperNode, false);
624     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
625     CHECK_NULL_RETURN(swiperPattern, false);
626     auto host = GetHost();
627     CHECK_NULL_RETURN(host, false);
628     auto currentIndex = swiperPattern->GetCurrentIndex();
629     auto childrenSize = swiperPattern->RealTotalCount();
630 
631     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
632     CHECK_NULL_RETURN(swiperLayoutProperty, false);
633     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
634 
635     auto dragPoint =
636         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
637     auto offset = dragPoint - dragStartPoint_;
638     auto touchOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
639     auto touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx())
640                                ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx()
641                                : 1;
642 
643     swiperPattern->SetTurnPageRate(0);
644     swiperPattern->SetTouchBottomRate(std::abs(touchBottomRate));
645     TouchBottomType touchBottomType = TouchBottomType::NONE;
646 
647     if (currentIndex <= 0) {
648         if (swiperPattern->IsHorizontalAndRightToLeft()) {
649             if (Positive(touchOffset)) {
650                 touchBottomType = TouchBottomType::END;
651             }
652         } else {
653             if (NonPositive(touchOffset)) {
654                 touchBottomType = TouchBottomType::START;
655             }
656         }
657     }
658 
659     if (currentIndex >= childrenSize - displayCount) {
660         if (swiperPattern->IsHorizontalAndRightToLeft()) {
661             if (NonPositive(touchOffset)) {
662                 touchBottomType = TouchBottomType::START;
663             }
664         } else {
665             if (Positive(touchOffset)) {
666                 touchBottomType = TouchBottomType::END;
667             }
668         }
669     }
670     touchBottomType_ = touchBottomType;
671     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
672 
673     return touchBottomType == TouchBottomType::NONE ? false : true;
674 }
675 
InitLongPressEvent(const RefPtr<GestureEventHub> & gestureHub)676 void SwiperIndicatorPattern::InitLongPressEvent(const RefPtr<GestureEventHub>& gestureHub)
677 {
678     CHECK_NULL_VOID(!longPressEvent_);
679     auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
680         auto pattern = weak.Upgrade();
681         CHECK_NULL_VOID(pattern);
682         pattern->HandleLongPress(info);
683     };
684     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
685 
686     gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
687 }
688 
HandleLongPress(GestureEvent & info)689 void SwiperIndicatorPattern::HandleLongPress(GestureEvent& info)
690 {
691     HandleTouchDown();
692     HandleDragStart(info);
693 
694     auto swiperNode = GetSwiperNode();
695     CHECK_NULL_VOID(swiperNode);
696     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
697     CHECK_NULL_VOID(swiperPattern);
698     auto swiperPaintProperty = swiperPattern->GetPaintProperty<SwiperPaintProperty>();
699     CHECK_NULL_VOID(swiperPaintProperty);
700     auto autoPlay = swiperPaintProperty->GetAutoPlay().value_or(false);
701     if (autoPlay) {
702         swiperPattern->SetIndicatorLongPress(true);
703         swiperPattern->StopTranslateAnimation();
704         swiperPattern->StopSpringAnimation();
705         swiperPattern->StopAutoPlay();
706     }
707 }
708 
HandleLongDragUpdate(const TouchLocationInfo & info)709 void SwiperIndicatorPattern::HandleLongDragUpdate(const TouchLocationInfo& info)
710 {
711     auto swiperNode = GetSwiperNode();
712     CHECK_NULL_VOID(swiperNode);
713     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
714     CHECK_NULL_VOID(swiperPattern);
715     if (swiperPattern->IsIndicatorAnimatorRunning()) {
716         return;
717     }
718     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
719     CHECK_NULL_VOID(swiperLayoutProperty);
720     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
721     if (swiperPattern->RealTotalCount() == displayCount) {
722         return;
723     }
724     if (CheckIsTouchBottom(info)) {
725         return;
726     }
727     auto dragPoint =
728         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
729     auto offset = dragPoint - dragStartPoint_;
730     auto turnPageRateOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
731     if (LessNotEqual(std::abs(turnPageRateOffset), INDICATOR_DRAG_MIN_DISTANCE.ConvertToPx())) {
732         return;
733     }
734     if (swiperPattern->IsHorizontalAndRightToLeft()) {
735         turnPageRateOffset = -turnPageRateOffset;
736     }
737     auto turnPageRate = -(turnPageRateOffset / INDICATOR_DRAG_MAX_DISTANCE.ConvertToPx());
738     swiperPattern->SetTurnPageRate(turnPageRate);
739     if (std::abs(turnPageRate) >= 1) {
740         if (Positive(turnPageRateOffset)) {
741             swiperPattern->SwipeToWithoutAnimation(swiperPattern->GetCurrentIndex() + 1);
742         }
743         if (NonPositive(turnPageRateOffset)) {
744             swiperPattern->SwipeToWithoutAnimation(swiperPattern->GetCurrentIndex() - 1);
745         }
746 
747         dragStartPoint_ = dragPoint;
748     }
749 }
750 
HandleTouchClickMargin()751 float SwiperIndicatorPattern::HandleTouchClickMargin()
752 {
753     auto host = GetHost();
754     CHECK_NULL_RETURN(host, 0.0f);
755     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
756     CHECK_NULL_RETURN(paintProperty, 0.0f);
757     auto pipeline = PipelineBase::GetCurrentContext();
758     CHECK_NULL_RETURN(pipeline, 0.0f);
759     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
760     CHECK_NULL_RETURN(theme, 0.0f);
761     auto itemWidth = paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx();
762     auto selectedItemWidth = paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx();
763     if (Negative(itemWidth) || Negative(selectedItemWidth)) {
764         itemWidth = theme->GetSize().ConvertToPx();
765         selectedItemWidth = theme->GetSize().ConvertToPx();
766     }
767     auto swiperNode = GetSwiperNode();
768     CHECK_NULL_RETURN(swiperNode, 0.0f);
769     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
770     int32_t itemCount = swiperPattern->RealTotalCount();
771     auto allPointDiameterSum = itemWidth * static_cast<float>(itemCount - 1) + selectedItemWidth;
772     auto allPointSpaceSum = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx() * (itemCount - 1));
773     auto indicatorPadding = static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx());
774     auto contentWidth = indicatorPadding + allPointDiameterSum + allPointSpaceSum + indicatorPadding;
775     auto geometryNode = host->GetGeometryNode();
776     CHECK_NULL_RETURN(geometryNode, 0.0f);
777     auto frameSize = geometryNode->GetFrameSize();
778     auto axis = swiperPattern->GetDirection();
779     return ((axis == Axis::HORIZONTAL ? frameSize.Width() : frameSize.Height()) - contentWidth) * 0.5f;
780 }
781 
DumpAdvanceInfo()782 void SwiperIndicatorPattern::DumpAdvanceInfo()
783 {
784     isHover_ ? DumpLog::GetInstance().AddDesc("isHover:true") : DumpLog::GetInstance().AddDesc("isHover:false");
785     isPressed_ ? DumpLog::GetInstance().AddDesc("isPressed:true") : DumpLog::GetInstance().AddDesc("isPressed:false");
786     isClicked_ ? DumpLog::GetInstance().AddDesc("isClicked:true") : DumpLog::GetInstance().AddDesc("isClicked:false");
787     isRepeatClicked_ ? DumpLog::GetInstance().AddDesc("isRepeatClicked:true")
788                      : DumpLog::GetInstance().AddDesc("isRepeatClicked:false");
789     switch (swiperIndicatorType_) {
790         case SwiperIndicatorType::DOT: {
791             DumpLog::GetInstance().AddDesc("SwiperIndicatorType:DOT");
792             break;
793         }
794         case SwiperIndicatorType::DIGIT: {
795             DumpLog::GetInstance().AddDesc("SwiperIndicatorType:DIGIT");
796             break;
797         }
798         default: {
799             break;
800         }
801     }
802 }
803 
CreateOverlongDotIndicatorPaintMethod(RefPtr<SwiperPattern> swiperPattern)804 RefPtr<OverlengthDotIndicatorPaintMethod> SwiperIndicatorPattern::CreateOverlongDotIndicatorPaintMethod(
805     RefPtr<SwiperPattern> swiperPattern)
806 {
807     if (dotIndicatorModifier_) {
808         dotIndicatorModifier_->StopAnimation(true);
809         dotIndicatorModifier_->SetIsOverlong(true);
810     }
811 
812     if (!overlongDotIndicatorModifier_) {
813         overlongDotIndicatorModifier_ = AceType::MakeRefPtr<OverlengthDotIndicatorModifier>();
814     }
815 
816     overlongDotIndicatorModifier_->SetAnimationDuration(swiperPattern->GetDuration());
817     overlongDotIndicatorModifier_->SetLongPointHeadCurve(
818         swiperPattern->GetCurveIncludeMotion(), swiperPattern->GetMotionVelocity());
819 
820     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
821     CHECK_NULL_RETURN(swiperLayoutProperty, nullptr);
822     auto overlongPaintMethod = MakeRefPtr<OverlengthDotIndicatorPaintMethod>(overlongDotIndicatorModifier_);
823     auto paintMethodTemp = DynamicCast<DotIndicatorPaintMethod>(overlongPaintMethod);
824     SetDotIndicatorPaintMethodInfo(swiperPattern, paintMethodTemp, swiperLayoutProperty);
825     UpdateOverlongPaintMethod(swiperPattern, overlongPaintMethod);
826 
827     return overlongPaintMethod;
828 }
829 
CreateDotIndicatorPaintMethod(RefPtr<SwiperPattern> swiperPattern)830 RefPtr<DotIndicatorPaintMethod> SwiperIndicatorPattern::CreateDotIndicatorPaintMethod(
831     RefPtr<SwiperPattern> swiperPattern)
832 {
833     if (overlongDotIndicatorModifier_) {
834         overlongDotIndicatorModifier_->StopAnimation(true);
835         overlongDotIndicatorModifier_->SetMaxDisplayCount(0);
836     }
837 
838     if (!dotIndicatorModifier_) {
839         dotIndicatorModifier_ = AceType::MakeRefPtr<DotIndicatorModifier>();
840     }
841 
842     dotIndicatorModifier_->SetIsOverlong(false);
843     dotIndicatorModifier_->SetAnimationDuration(swiperPattern->GetDuration());
844     dotIndicatorModifier_->SetLongPointHeadCurve(
845         swiperPattern->GetCurveIncludeMotion(), swiperPattern->GetMotionVelocity());
846     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
847     CHECK_NULL_RETURN(swiperLayoutProperty, nullptr);
848     auto paintMethod = MakeRefPtr<DotIndicatorPaintMethod>(dotIndicatorModifier_);
849     SetDotIndicatorPaintMethodInfo(swiperPattern, paintMethod, swiperLayoutProperty);
850 
851     dotIndicatorModifier_->SetBoundsRect(CalcBoundsRect());
852 
853     return paintMethod;
854 }
855 
CalcBoundsRect() const856 RectF SwiperIndicatorPattern::CalcBoundsRect() const
857 {
858     auto swiperNode = GetSwiperNode();
859     CHECK_NULL_RETURN(swiperNode, RectF());
860     auto geometryNode = swiperNode->GetGeometryNode();
861     CHECK_NULL_RETURN(geometryNode, RectF());
862     auto host = GetHost();
863     CHECK_NULL_RETURN(host, RectF());
864     auto indicatorGeometryNode = host->GetGeometryNode();
865     CHECK_NULL_RETURN(indicatorGeometryNode, RectF());
866     auto boundsValue = (geometryNode->GetFrameSize().Width() - indicatorGeometryNode->GetFrameSize().Width()) * 0.5f;
867     auto boundsRectOriginX = -boundsValue;
868     auto boundsRectOriginY = 0.0f;
869     auto boundsRectWidth = geometryNode->GetFrameSize().Width();
870     auto boundsRectHeight = indicatorGeometryNode->GetFrameSize().Height();
871     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
872     CHECK_NULL_RETURN(swiperPattern, RectF());
873     if (swiperPattern->GetDirection() == Axis::VERTICAL) {
874         boundsValue = (geometryNode->GetFrameSize().Height() - indicatorGeometryNode->GetFrameSize().Height()) * 0.5f;
875         boundsRectOriginX = 0.0f;
876         boundsRectOriginY = -boundsValue;
877         boundsRectWidth = indicatorGeometryNode->GetFrameSize().Width();
878         boundsRectHeight = geometryNode->GetFrameSize().Height();
879     }
880     RectF boundsRect(boundsRectOriginX, boundsRectOriginY, boundsRectWidth, boundsRectHeight);
881 
882     return boundsRect;
883 }
884 
UpdateOverlongPaintMethod(const RefPtr<SwiperPattern> & swiperPattern,RefPtr<OverlengthDotIndicatorPaintMethod> & overlongPaintMethod)885 void SwiperIndicatorPattern::UpdateOverlongPaintMethod(
886     const RefPtr<SwiperPattern>& swiperPattern, RefPtr<OverlengthDotIndicatorPaintMethod>& overlongPaintMethod)
887 {
888     auto animationStartIndex = swiperPattern->GetLoopIndex(swiperPattern->GetCurrentIndex());
889     auto animationEndIndex = swiperPattern->GetLoopIndex(swiperPattern->GetCurrentFirstIndex());
890 
891     auto paintMethodTemp = DynamicCast<DotIndicatorPaintMethod>(overlongPaintMethod);
892     if (changeIndexWithAnimation_ && !changeIndexWithAnimation_.value()) {
893         animationStartIndex = startIndex_ ? startIndex_.value() : overlongDotIndicatorModifier_->GetAnimationEndIndex();
894         paintMethodTemp->SetGestureState(GestureState::GESTURE_STATE_NONE);
895     }
896 
897     if (jumpIndex_) {
898         paintMethodTemp->SetGestureState(GestureState::GESTURE_STATE_NONE);
899 
900         if (!changeIndexWithAnimation_) {
901             overlongDotIndicatorModifier_->StopAnimation(true);
902             overlongDotIndicatorModifier_->SetCurrentOverlongType(OverlongType::NONE);
903         }
904     }
905 
906     auto isSwiperTouchDown = swiperPattern->IsTouchDownOnOverlong();
907     auto isSwiperAnimationRunning =
908         swiperPattern->IsPropertyAnimationRunning() || swiperPattern->IsTranslateAnimationRunning();
909     auto keepStatus = !isSwiperTouchDown && !isSwiperAnimationRunning && animationStartIndex != animationEndIndex &&
910                       !changeIndexWithAnimation_;
911 
912     if (!changeIndexWithAnimation_ && gestureState_ == GestureState::GESTURE_STATE_NONE) {
913         keepStatus = true;
914     }
915 
916     auto bottomTouchLoop = swiperPattern->GetTouchBottomTypeLoop();
917     auto turnPageRateAbs = std::abs(swiperPattern->GetTurnPageRate());
918     auto totalCount = swiperPattern->RealTotalCount();
919     auto loopDrag = (animationStartIndex == 0 && animationEndIndex == totalCount - 1 && turnPageRateAbs < HALF_FLOAT &&
920                         turnPageRateAbs > 0.0f) ||
921                     (animationStartIndex == animationEndIndex && animationEndIndex == totalCount - 1 &&
922                         turnPageRateAbs > HALF_FLOAT);
923     auto nonLoopDrag = bottomTouchLoop == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE &&
924                        ((gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT && turnPageRateAbs > HALF_FLOAT) ||
925                            (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT && turnPageRateAbs < HALF_FLOAT &&
926                                turnPageRateAbs > 0.0f));
927 
928     if (isSwiperTouchDown && (loopDrag || nonLoopDrag)) {
929         overlongDotIndicatorModifier_->UpdateCurrentStatus();
930     }
931 
932     overlongPaintMethod->SetMaxDisplayCount(swiperPattern->GetMaxDisplayCount());
933     overlongPaintMethod->SetKeepStatus(keepStatus);
934     overlongPaintMethod->SetAnimationStartIndex(animationStartIndex);
935     overlongPaintMethod->SetAnimationEndIndex(animationEndIndex);
936     overlongDotIndicatorModifier_->SetIsSwiperTouchDown(isSwiperTouchDown);
937     overlongDotIndicatorModifier_->SetBoundsRect(CalcBoundsRect());
938     changeIndexWithAnimation_.reset();
939     jumpIndex_.reset();
940     startIndex_.reset();
941 }
942 } // namespace OHOS::Ace::NG
943