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