1 /*
2  * Copyright (c) 2024 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/dot_indicator/overlength_dot_indicator_modifier.h"
17 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_utils.h"
18 #include "base/utils/utils.h"
19 #include "core/components/swiper/swiper_indicator_theme.h"
20 #include "core/components_ng/render/animation_utils.h"
21 #include "core/components_ng/render/drawing.h"
22 
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr Dimension INDICATOR_PADDING_DEFAULT = 12.0_vp;
26 constexpr Dimension INDICATOR_ITEM_SPACE = 8.0_vp;
27 constexpr float BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY = 0.2f;
28 constexpr float CENTER_BEZIER_CURVE_MASS = 0.0f;
29 constexpr float CENTER_BEZIER_CURVE_STIFFNESS = 0.2f;
30 constexpr float CENTER_BEZIER_CURVE_DAMPING = 1.0f;
31 constexpr float SMALLEST_POINT_RATIO = 1.0f / 3.0f;
32 constexpr float SECOND_SMALLEST_POINT_RATIO = 2.0f / 3.0f;
33 constexpr float NORMAL_FADING_RATIO = 1.0f;
34 constexpr double FULL_ALPHA = 255.0;
35 constexpr int32_t BLACK_POINT_DURATION = 400;
36 constexpr int32_t LEFT_FIRST_POINT_INDEX = 0;
37 constexpr int32_t SECOND_POINT_INDEX = 1;
38 constexpr int32_t THIRD_POINT_INDEX = 2;
39 constexpr uint32_t ITEM_HALF_WIDTH = 0;
40 constexpr uint32_t SELECTED_ITEM_HALF_WIDTH = 2;
41 constexpr float HALF_FLOAT = 0.5f;
42 } // namespace
43 
onDraw(DrawingContext & context)44 void OverlengthDotIndicatorModifier::onDraw(DrawingContext& context)
45 {
46     if (maxDisplayCount_ <= 0) {
47         return;
48     }
49 
50     ContentProperty contentProperty;
51     contentProperty.backgroundColor = backgroundColor_->Get().ToColor();
52     contentProperty.unselectedIndicatorWidth = unselectedIndicatorWidth_->Get();
53     contentProperty.unselectedIndicatorHeight = unselectedIndicatorHeight_->Get();
54     contentProperty.vectorBlackPointCenterX = vectorBlackPointCenterX_->Get();
55     contentProperty.longPointLeftCenterX = longPointLeftCenterX_->Get();
56     contentProperty.longPointRightCenterX = longPointRightCenterX_->Get();
57     contentProperty.normalToHoverPointDilateRatio = normalToHoverPointDilateRatio_->Get();
58     contentProperty.hoverToNormalPointDilateRatio = hoverToNormalPointDilateRatio_->Get();
59     contentProperty.longPointDilateRatio = longPointDilateRatio_->Get();
60     contentProperty.indicatorPadding = indicatorPadding_->Get();
61     contentProperty.indicatorMargin = indicatorMargin_->Get();
62     contentProperty.itemHalfSizes = itemHalfSizes_->Get();
63     contentProperty.firstPointOpacity = firstPointOpacity_->Get();
64     contentProperty.newPointOpacity = newPointOpacity_->Get();
65 
66     PaintBackground(context, contentProperty);
67     PaintContent(context, contentProperty);
68 }
69 
GetTouchBottomCenterX(ContentProperty & contentProperty)70 std::pair<float, float> OverlengthDotIndicatorModifier::GetTouchBottomCenterX(ContentProperty& contentProperty)
71 {
72     float leftCenterX = contentProperty.longPointLeftCenterX;
73     float rightCenterX = contentProperty.longPointRightCenterX;
74 
75     if (isCustomSize_ || contentProperty.vectorBlackPointCenterX.empty() ||
76         static_cast<int32_t>(contentProperty.vectorBlackPointCenterX.size()) < maxDisplayCount_) {
77         return { leftCenterX, rightCenterX };
78     }
79 
80     auto currentIndex = isHorizontalAndRTL_ ? realItemCount_ - 1 - currentIndex_ : currentIndex_;
81     bool isLeftTouchBottom = (currentIndex == realItemCount_ - 1);
82     bool isRightTouchBottom = (currentIndex == 0);
83     float radius = (rightCenterX - leftCenterX) * HALF_FLOAT;
84     if ((animationState_ == TouchBottomAnimationStage::STAGE_SHRINKT_TO_BLACK_POINT && isLeftTouchBottom) ||
85         (animationState_ == TouchBottomAnimationStage::STAGE_EXPAND_TO_LONG_POINT && isRightTouchBottom)) {
86         leftCenterX = contentProperty.vectorBlackPointCenterX[0] - radius;
87         rightCenterX = contentProperty.vectorBlackPointCenterX[0] + radius;
88     } else if ((animationState_ == TouchBottomAnimationStage::STAGE_EXPAND_TO_LONG_POINT && isLeftTouchBottom) ||
89                (animationState_ == TouchBottomAnimationStage::STAGE_SHRINKT_TO_BLACK_POINT && isRightTouchBottom)) {
90         leftCenterX = contentProperty.vectorBlackPointCenterX[maxDisplayCount_ - 1] - radius;
91         rightCenterX = contentProperty.vectorBlackPointCenterX[maxDisplayCount_ - 1] + radius;
92     }
93 
94     return { leftCenterX, rightCenterX };
95 }
96 
PaintContent(DrawingContext & context,ContentProperty & contentProperty)97 void OverlengthDotIndicatorModifier::PaintContent(DrawingContext& context, ContentProperty& contentProperty)
98 {
99     PaintBlackPoint(context, contentProperty);
100     RSCanvas& canvas = context.canvas;
101     auto [leftCenterX, rightCenterX] = GetTouchBottomCenterX(contentProperty);
102 
103     OffsetF leftCenter = { leftCenterX, centerY_ };
104     OffsetF rightCenter = { rightCenterX, centerY_ };
105     OffsetF centerDistance = rightCenter - leftCenter;
106     OffsetF centerDilateDistance = centerDistance * contentProperty.longPointDilateRatio;
107     leftCenter -= (centerDilateDistance - centerDistance) * HALF_FLOAT;
108     rightCenter += (centerDilateDistance - centerDistance) * HALF_FLOAT;
109     PaintSelectedIndicator(
110         canvas, leftCenter, rightCenter, contentProperty.itemHalfSizes * contentProperty.longPointDilateRatio);
111 }
112 
PaintBlackPoint(DrawingContext & context,ContentProperty & contentProperty)113 void OverlengthDotIndicatorModifier::PaintBlackPoint(DrawingContext& context, ContentProperty& contentProperty)
114 {
115     RSCanvas& canvas = context.canvas;
116     auto totalCount = contentProperty.vectorBlackPointCenterX.size();
117     for (size_t i = 0; i < totalCount; ++i) {
118         OffsetF center = { contentProperty.vectorBlackPointCenterX[i], centerY_ };
119         float width = contentProperty.unselectedIndicatorWidth[i];
120         float height = contentProperty.unselectedIndicatorHeight[i];
121 
122         auto paintColor = unselectedColor_->Get();
123         bool isFirstPoint = (i == 0 && moveDirection_ == OverlongIndicatorMove::MOVE_BACKWARD) ||
124                             (i == totalCount - 2 && moveDirection_ == OverlongIndicatorMove::MOVE_FORWARD);
125         if (isFirstPoint) {
126             // first point color
127             paintColor = paintColor.BlendOpacity(contentProperty.firstPointOpacity / FULL_ALPHA);
128         } else if (i == totalCount - 1 && moveDirection_ != OverlongIndicatorMove::NONE) {
129             // new point color
130             paintColor = paintColor.BlendOpacity(contentProperty.newPointOpacity / FULL_ALPHA);
131         }
132 
133         PaintUnselectedIndicator(canvas, center, width, height, LinearColor(paintColor));
134     }
135 }
136 
PaintUnselectedIndicator(RSCanvas & canvas,const OffsetF & center,float width,float height,const LinearColor & indicatorColor)137 void OverlengthDotIndicatorModifier::PaintUnselectedIndicator(
138     RSCanvas& canvas, const OffsetF& center, float width, float height, const LinearColor& indicatorColor)
139 {
140     RSBrush brush;
141     brush.SetAntiAlias(true);
142     brush.SetColor(ToRSColor(indicatorColor));
143     canvas.AttachBrush(brush);
144     if (!NearEqual(width, height) || !isCustomSize_) {
145         float rectLeft =
146             (axis_ == Axis::HORIZONTAL ? center.GetX() - width * HALF_FLOAT : center.GetY() - height * HALF_FLOAT);
147         float rectTop =
148             (axis_ == Axis::HORIZONTAL ? center.GetY() - height * HALF_FLOAT : center.GetX() - width * HALF_FLOAT);
149         float rectRight =
150             (axis_ == Axis::HORIZONTAL ? center.GetX() + width * HALF_FLOAT : center.GetY() + height * HALF_FLOAT);
151         float rectBottom =
152             (axis_ == Axis::HORIZONTAL ? center.GetY() + height * HALF_FLOAT : center.GetX() + width * HALF_FLOAT);
153 
154         if (height > width || !isCustomSize_) {
155             canvas.DrawRoundRect({ { rectLeft, rectTop, rectRight, rectBottom }, width, width });
156         } else if (height < width) {
157             canvas.DrawRoundRect({ { rectLeft, rectTop, rectRight, rectBottom }, height, height });
158         } else {
159             float customPointX = axis_ == Axis::HORIZONTAL ? center.GetX() : center.GetY();
160             float customPointY = axis_ == Axis::HORIZONTAL ? center.GetY() : center.GetX();
161             canvas.DrawCircle({ customPointX, customPointY }, height * HALF_FLOAT);
162         }
163     } else {
164         float pointX = axis_ == Axis::HORIZONTAL ? center.GetX() : center.GetY();
165         float pointY = axis_ == Axis::HORIZONTAL ? center.GetY() : center.GetX();
166         canvas.DrawCircle({ pointX, pointY }, width * HALF_FLOAT);
167     }
168     canvas.DetachBrush();
169 }
170 
UpdateShrinkPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const std::pair<float,float> & longPointCenterX)171 void OverlengthDotIndicatorModifier::UpdateShrinkPaintProperty(const OffsetF& margin,
172     const LinearVector<float>& normalItemHalfSizes, const std::pair<float, float>& longPointCenterX)
173 {
174     indicatorMargin_->Set(margin);
175     indicatorPadding_->Set(static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx()));
176 
177     if (longPointLeftAnimEnd_ && longPointRightAnimEnd_) {
178         longPointLeftCenterX_->Set(longPointCenterX.first);
179         longPointRightCenterX_->Set(longPointCenterX.second);
180     }
181 
182     vectorBlackPointCenterX_->Set(animationEndCenterX_);
183     unselectedIndicatorWidth_->Set(animationEndIndicatorWidth_);
184     unselectedIndicatorHeight_->Set(animationEndIndicatorHeight_);
185     itemHalfSizes_->Set(normalItemHalfSizes);
186     normalToHoverPointDilateRatio_->Set(NORMAL_FADING_RATIO);
187     hoverToNormalPointDilateRatio_->Set(NORMAL_FADING_RATIO);
188     longPointDilateRatio_->Set(NORMAL_FADING_RATIO);
189     backgroundWidthDilateRatio_->Set(NORMAL_FADING_RATIO);
190     backgroundHeightDilateRatio_->Set(NORMAL_FADING_RATIO);
191 
192     if (blackPointsAnimEnd_) {
193         currentSelectedIndex_ = targetSelectedIndex_;
194         currentOverlongType_ = targetOverlongType_;
195     }
196 }
197 
UpdateNormalPaintProperty(const OffsetF & margin,const LinearVector<float> & normalItemHalfSizes,const std::pair<float,float> & longPointCenterX)198 void OverlengthDotIndicatorModifier::UpdateNormalPaintProperty(const OffsetF& margin,
199     const LinearVector<float>& normalItemHalfSizes, const std::pair<float, float>& longPointCenterX)
200 {
201     normalMargin_ = margin;
202     CalcAnimationEndCenterX(normalItemHalfSizes);
203     auto swiperTheme = GetSwiperIndicatorTheme();
204     CHECK_NULL_VOID(swiperTheme);
205     auto backgroundColor =
206         indicatorMask_ ? swiperTheme->GetPressedColor() : swiperTheme->GetHoverColor().ChangeOpacity(0);
207     UpdateShrinkPaintProperty(margin, normalItemHalfSizes, overlongSelectedEndCenterX_);
208     UpdateBackgroundColor(backgroundColor);
209 }
210 
CalcLongPointEndCenterXWithBlack(int32_t index,const LinearVector<float> & itemHalfSizes)211 std::pair<float, float> OverlengthDotIndicatorModifier::CalcLongPointEndCenterXWithBlack(
212     int32_t index, const LinearVector<float>& itemHalfSizes)
213 {
214     if (isHorizontalAndRTL_) {
215         index = maxDisplayCount_ - 1 - index;
216     }
217 
218     if (static_cast<size_t>(index) >= animationEndCenterX_.size()) {
219         return std::make_pair(0.0f, 0.0f);
220     }
221 
222     auto selectedIndicatorRadius = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
223     if (!isCustomSizeValue_) {
224         selectedIndicatorRadius *= 2.0f;
225     }
226 
227     auto longPointLeftEndCenterX = animationEndCenterX_[index] - selectedIndicatorRadius * HALF_FLOAT;
228     auto longPointRightEndCenterX = animationEndCenterX_[index] + selectedIndicatorRadius * HALF_FLOAT;
229     return std::make_pair(longPointLeftEndCenterX, longPointRightEndCenterX);
230 }
231 
GetBlackPointsAnimationDuration() const232 int32_t OverlengthDotIndicatorModifier::GetBlackPointsAnimationDuration() const
233 {
234     if (InstanceOf<InterpolatingSpring>(headCurve_)) {
235         return BLACK_POINT_DURATION;
236     }
237 
238     return animationDuration_;
239 }
240 
PlayBlackPointsAnimation(const LinearVector<float> & itemHalfSizes)241 void OverlengthDotIndicatorModifier::PlayBlackPointsAnimation(const LinearVector<float>& itemHalfSizes)
242 {
243     AnimationOption blackPointOption;
244     auto pointMoveCurve = AceType::MakeRefPtr<CubicCurve>(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY,
245         CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING);
246     blackPointOption.SetCurve(pointMoveCurve);
247     blackPointOption.SetDuration(GetBlackPointsAnimationDuration());
248 
249     vectorBlackPointCenterX_->Set(animationStartCenterX_);
250     unselectedIndicatorWidth_->Set(animationStartIndicatorWidth_);
251     unselectedIndicatorHeight_->Set(animationStartIndicatorHeight_);
252     firstPointOpacity_->Set(UINT8_MAX);
253     newPointOpacity_->Set(0);
254     isSelectedColorAnimEnd_ = false;
255     isTouchBottomLoop_ = true;
256     auto longPointEndCenterX = CalcLongPointEndCenterXWithBlack(targetSelectedIndex_, itemHalfSizes);
257     blackPointsAnimEnd_ = false;
258     AnimationUtils::StartAnimation(blackPointOption, [&]() {
259         vectorBlackPointCenterX_->Set(animationEndCenterX_);
260         unselectedIndicatorWidth_->Set(animationEndIndicatorWidth_);
261         unselectedIndicatorHeight_->Set(animationEndIndicatorHeight_);
262 
263         if (moveDirection_ != OverlongIndicatorMove::NONE) {
264             firstPointOpacity_->Set(0);
265             newPointOpacity_->Set(UINT8_MAX);
266             longPointLeftCenterX_->Set(longPointEndCenterX.first);
267             longPointRightCenterX_->Set(longPointEndCenterX.second);
268         }
269     }, [weak = WeakClaim(this)]() {
270         auto modifier = weak.Upgrade();
271         CHECK_NULL_VOID(modifier);
272         if (!modifier->blackPointsAnimEnd_) {
273             modifier->currentSelectedIndex_ = modifier->targetSelectedIndex_;
274             modifier->currentOverlongType_ = modifier->targetOverlongType_;
275             modifier->blackPointsAnimEnd_ = true;
276         }
277     });
278 }
279 
RevertOverlongType(OverlongType overlongType) const280 OverlongType OverlengthDotIndicatorModifier::RevertOverlongType(OverlongType overlongType) const
281 {
282     if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
283         return OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
284     } else if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
285         return OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
286     }
287 
288     return overlongType;
289 }
290 
CalcIndicatorSize(const LinearVector<float> & itemHalfSizes,OverlongType overlongType,bool isWidth)291 LinearVector<float> OverlengthDotIndicatorModifier::CalcIndicatorSize(
292     const LinearVector<float>& itemHalfSizes, OverlongType overlongType, bool isWidth)
293 {
294     if (isHorizontalAndRTL_) {
295         overlongType = RevertOverlongType(overlongType);
296     }
297 
298     auto unselectedIndicatorRadius = isWidth ? itemHalfSizes[0] : itemHalfSizes[1];
299     LinearVector<float> indicatorSize(maxDisplayCount_ + 1);
300 
301     auto secondSmallestRadius = unselectedIndicatorRadius * SECOND_SMALLEST_POINT_RATIO;
302     auto smallestRadius = unselectedIndicatorRadius * SMALLEST_POINT_RATIO;
303 
304     for (int32_t i = 0; i < maxDisplayCount_; i++) {
305         if (i == LEFT_FIRST_POINT_INDEX) {
306             if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
307                 indicatorSize[i] = unselectedIndicatorRadius * 2;
308             } else {
309                 indicatorSize[i] = smallestRadius * 2;
310             }
311             continue;
312         }
313 
314         if (i == SECOND_POINT_INDEX) {
315             if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
316                 indicatorSize[i] = unselectedIndicatorRadius * 2;
317             } else {
318                 indicatorSize[i] = secondSmallestRadius * 2;
319             }
320             continue;
321         }
322 
323         if (i >= THIRD_POINT_INDEX && i <= maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
324             indicatorSize[i] = unselectedIndicatorRadius * 2;
325             continue;
326         }
327 
328         if (i == maxDisplayCount_ - 1 - SECOND_POINT_INDEX) {
329             if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
330                 indicatorSize[i] = unselectedIndicatorRadius * 2;
331             } else {
332                 indicatorSize[i] = secondSmallestRadius * 2;
333             }
334             continue;
335         }
336 
337         if (i == maxDisplayCount_ - 1) {
338             if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
339                 indicatorSize[i] = unselectedIndicatorRadius * 2;
340             } else {
341                 indicatorSize[i] = smallestRadius * 2;
342             }
343             continue;
344         }
345     }
346 
347     return indicatorSize;
348 }
349 
UpdateSelectedCenterXOnDrag(const LinearVector<float> & itemHalfSizes)350 void OverlengthDotIndicatorModifier::UpdateSelectedCenterXOnDrag(const LinearVector<float>& itemHalfSizes)
351 {
352     if (gestureState_ != GestureState::GESTURE_STATE_FOLLOW_LEFT &&
353         gestureState_ != GestureState::GESTURE_STATE_FOLLOW_RIGHT) {
354         return;
355     }
356 
357     auto leftMoveRate = longPointLeftCenterMoveRate_;
358     auto rightMoveRate = longPointRightCenterMoveRate_;
359     if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT &&
360         touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
361         leftMoveRate = 1.0f - longPointLeftCenterMoveRate_;
362         rightMoveRate = 1.0f - longPointRightCenterMoveRate_;
363     }
364 
365     auto targetIndex = isHorizontalAndRTL_ ? currentSelectedIndex_ - 1 : currentSelectedIndex_ + 1;
366     if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT) {
367         targetIndex = isHorizontalAndRTL_ ? currentSelectedIndex_ + 1 : currentSelectedIndex_ - 1;
368     }
369 
370     auto longPointEndCenterX = CalcLongPointEndCenterXWithBlack(targetIndex, itemHalfSizes);
371     if (touchBottomTypeLoop_ != TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
372         auto dragTargetCenterX = (overlongSelectedEndCenterX_.second + overlongSelectedEndCenterX_.first) * HALF_FLOAT;
373         overlongSelectedEndCenterX_.first = overlongSelectedStartCenterX_.first +
374                                             (dragTargetCenterX - overlongSelectedStartCenterX_.first) * leftMoveRate;
375 
376         overlongSelectedEndCenterX_.second = overlongSelectedStartCenterX_.second +
377                                              (dragTargetCenterX - overlongSelectedStartCenterX_.second) * rightMoveRate;
378     } else {
379         auto leftDistance = overlongSelectedEndCenterX_.first - overlongSelectedStartCenterX_.first;
380         auto rightDistance = overlongSelectedEndCenterX_.second - overlongSelectedStartCenterX_.second;
381         if (currentSelectedIndex_ == targetSelectedIndex_ && isSwiperTouchDown_) {
382             leftDistance = longPointEndCenterX.first - overlongSelectedStartCenterX_.first;
383             rightDistance = longPointEndCenterX.second - overlongSelectedStartCenterX_.second;
384         }
385 
386         overlongSelectedEndCenterX_.first = overlongSelectedStartCenterX_.first + leftDistance * leftMoveRate;
387         overlongSelectedEndCenterX_.second = overlongSelectedStartCenterX_.second + rightDistance * rightMoveRate;
388     }
389 }
390 
GetMoveRateOnAllMove() const391 float OverlengthDotIndicatorModifier::GetMoveRateOnAllMove() const
392 {
393     float blackPointCenterMoveRate = CubicCurve(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS,
394         CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING)
395                                          .MoveInternal(std::abs(turnPageRate_));
396     if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
397         gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
398         blackPointCenterMoveRate = 1.0f;
399     }
400 
401     return blackPointCenterMoveRate;
402 }
403 
UpdateUnselectedCenterXOnDrag()404 void OverlengthDotIndicatorModifier::UpdateUnselectedCenterXOnDrag()
405 {
406     if (gestureState_ != GestureState::GESTURE_STATE_FOLLOW_LEFT &&
407         gestureState_ != GestureState::GESTURE_STATE_FOLLOW_RIGHT) {
408         return;
409     }
410 
411     auto moveRate = blackPointCenterMoveRate_;
412     if (currentOverlongType_ != targetOverlongType_ || currentSelectedIndex_ == targetSelectedIndex_) {
413         moveRate = GetMoveRateOnAllMove();
414     }
415 
416     if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT &&
417         touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
418         moveRate = 1.0f - moveRate;
419     }
420 
421     for (size_t i = 0; i < animationEndIndicatorWidth_.size(); i++) {
422         animationEndIndicatorWidth_[i] = animationStartIndicatorWidth_[i] +
423                                          (animationEndIndicatorWidth_[i] - animationStartIndicatorWidth_[i]) * moveRate;
424     }
425 
426     for (size_t i = 0; i < animationEndIndicatorHeight_.size(); i++) {
427         animationEndIndicatorHeight_[i] =
428             animationStartIndicatorHeight_[i] +
429             (animationEndIndicatorHeight_[i] - animationStartIndicatorHeight_[i]) * moveRate;
430     }
431 
432     for (size_t i = 0; i < animationEndCenterX_.size(); i++) {
433         animationEndCenterX_[i] =
434             animationStartCenterX_[i] + (animationEndCenterX_[i] - animationStartCenterX_[i]) * moveRate;
435     }
436 }
437 
CalcTargetIndexOnDrag() const438 int32_t OverlengthDotIndicatorModifier::CalcTargetIndexOnDrag() const
439 {
440     if (NearEqual(turnPageRate_, 0.0f)) {
441         return animationEndIndex_;
442     }
443 
444     auto startIndex = isHorizontalAndRTL_ ? realItemCount_ - 1 - animationStartIndex_ : animationStartIndex_;
445     auto endIndex = isHorizontalAndRTL_ ? realItemCount_ - 1 - animationEndIndex_ : animationEndIndex_;
446     if (startIndex == endIndex) {
447         if (startIndex == realItemCount_ - 1) {
448             return animationStartIndex_;
449         }
450         return isHorizontalAndRTL_ ? animationStartIndex_ - 1 : animationStartIndex_ + 1;
451     }
452 
453     if (startIndex == 0 && endIndex == realItemCount_ - 1) {
454         return animationStartIndex_;
455     }
456 
457     return animationEndIndex_;
458 }
459 
CalcTargetStatusOnLongPointMove(const LinearVector<float> & itemHalfSizes)460 void OverlengthDotIndicatorModifier::CalcTargetStatusOnLongPointMove(const LinearVector<float>& itemHalfSizes)
461 {
462     auto endCenterX = CalcIndicatorCenterX(itemHalfSizes, targetSelectedIndex_, targetOverlongType_);
463     animationEndCenterX_ = endCenterX.first;
464     overlongSelectedEndCenterX_ = endCenterX.second;
465     animationStartIndicatorWidth_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, true);
466     animationStartIndicatorHeight_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, false);
467 
468     animationEndIndicatorWidth_ = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, true);
469     animationEndIndicatorHeight_ = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, false);
470 
471     if (touchBottomTypeLoop_ != TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
472         animationStartCenterX_.resize(maxDisplayCount_);
473         animationEndCenterX_.resize(maxDisplayCount_);
474         animationStartIndicatorWidth_.resize(maxDisplayCount_);
475         animationStartIndicatorHeight_.resize(maxDisplayCount_);
476         animationEndIndicatorWidth_.resize(maxDisplayCount_);
477         animationEndIndicatorHeight_.resize(maxDisplayCount_);
478     }
479 
480     if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
481                                   gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
482         UpdateUnselectedCenterXOnDrag();
483         UpdateSelectedCenterXOnDrag(itemHalfSizes);
484         targetSelectedIndex_ = currentSelectedIndex_;
485         targetOverlongType_ = currentOverlongType_;
486     }
487 }
488 
CalcTargetStatusOnAllPointMoveForward(const LinearVector<float> & itemHalfSizes)489 void OverlengthDotIndicatorModifier::CalcTargetStatusOnAllPointMoveForward(const LinearVector<float>& itemHalfSizes)
490 {
491     auto targetCenterX = CalcIndicatorCenterX(itemHalfSizes, targetSelectedIndex_, targetOverlongType_);
492     overlongSelectedEndCenterX_ = targetCenterX.second;
493     auto targetIndicatorWidth = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, true);
494     auto targetIndicatorHeight = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, false);
495 
496     float itemSpacePx = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx());
497     // calc new point current position
498     animationStartCenterX_[maxDisplayCount_] =
499         animationStartCenterX_[0] - animationStartIndicatorWidth_[0] - itemSpacePx;
500     animationStartIndicatorWidth_[maxDisplayCount_] = animationStartIndicatorWidth_[0];
501     animationStartIndicatorHeight_[maxDisplayCount_] = animationStartIndicatorHeight_[0];
502 
503     // calc new point target position
504     animationEndCenterX_[maxDisplayCount_] = targetCenterX.first[0];
505     animationEndIndicatorWidth_[maxDisplayCount_] = targetIndicatorWidth[0];
506     animationEndIndicatorHeight_[maxDisplayCount_] = targetIndicatorHeight[0];
507 
508     for (int32_t i = 0; i < maxDisplayCount_ - 1; i++) {
509         animationEndCenterX_[i] = targetCenterX.first[i + 1];
510         animationEndIndicatorWidth_[i] = targetIndicatorWidth[i + 1];
511         animationEndIndicatorHeight_[i] = targetIndicatorHeight[i + 1];
512     }
513 
514     animationEndCenterX_[maxDisplayCount_ - 1] =
515         targetCenterX.first[maxDisplayCount_ - 1] + targetIndicatorWidth[maxDisplayCount_ - 1] + itemSpacePx;
516     animationEndIndicatorWidth_[maxDisplayCount_ - 1] = targetIndicatorWidth[maxDisplayCount_ - 1];
517     animationEndIndicatorHeight_[maxDisplayCount_ - 1] = targetIndicatorHeight[maxDisplayCount_ - 1];
518 
519     UpdateUnselectedCenterXOnDrag();
520     UpdateSelectedCenterXOnDrag(itemHalfSizes);
521 
522     if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
523                                   gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
524         targetSelectedIndex_ = currentSelectedIndex_;
525         targetOverlongType_ = currentOverlongType_;
526 
527         auto opacityMoveRate = GetMoveRateOnAllMove();
528         auto firstPointOpacity = static_cast<uint8_t>(UINT8_MAX * opacityMoveRate);
529         auto newPointOpacity = static_cast<uint8_t>(UINT8_MAX * (1.0f - opacityMoveRate));
530         firstPointOpacity_->Set(firstPointOpacity);
531         newPointOpacity_->Set(newPointOpacity);
532     }
533 }
534 
CalcTargetStatusOnAllPointMoveBackward(const LinearVector<float> & itemHalfSizes)535 void OverlengthDotIndicatorModifier::CalcTargetStatusOnAllPointMoveBackward(const LinearVector<float>& itemHalfSizes)
536 {
537     auto targetCenterX = CalcIndicatorCenterX(itemHalfSizes, targetSelectedIndex_, targetOverlongType_);
538     overlongSelectedEndCenterX_ = targetCenterX.second;
539     auto targetIndicatorWidth = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, true);
540     auto targetIndicatorHeight = CalcIndicatorSize(itemHalfSizes, targetOverlongType_, false);
541 
542     float itemSpacePx = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx());
543     // calc new point current position
544     animationStartCenterX_[maxDisplayCount_] = animationStartCenterX_[maxDisplayCount_ - 1] +
545                                                animationStartIndicatorWidth_[maxDisplayCount_ - 1] + itemSpacePx;
546     animationStartIndicatorWidth_[maxDisplayCount_] = animationStartIndicatorWidth_[maxDisplayCount_ - 1];
547     animationStartIndicatorHeight_[maxDisplayCount_] = animationStartIndicatorHeight_[maxDisplayCount_ - 1];
548 
549     // calc first point target position
550     auto distance = std::abs(targetCenterX.first[1] - targetCenterX.first[0]);
551     animationEndCenterX_[0] = targetCenterX.first[0] - distance;
552     animationEndIndicatorWidth_[0] = targetIndicatorWidth[0];
553     animationEndIndicatorHeight_[0] = targetIndicatorHeight[0];
554 
555     for (int32_t i = 1; i <= maxDisplayCount_; i++) {
556         animationEndCenterX_[i] = targetCenterX.first[i - 1];
557         animationEndIndicatorWidth_[i] = targetIndicatorWidth[i - 1];
558         animationEndIndicatorHeight_[i] = targetIndicatorHeight[i - 1];
559     }
560 
561     UpdateUnselectedCenterXOnDrag();
562     UpdateSelectedCenterXOnDrag(itemHalfSizes);
563 
564     if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
565                                   gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
566         targetSelectedIndex_ = currentSelectedIndex_;
567         targetOverlongType_ = currentOverlongType_;
568 
569         auto opacityMoveRate = GetMoveRateOnAllMove();
570         auto firstPointOpacity = static_cast<uint8_t>(UINT8_MAX * (1.0f - opacityMoveRate));
571         auto newPointOpacity = static_cast<uint8_t>(UINT8_MAX * opacityMoveRate);
572         firstPointOpacity_->Set(firstPointOpacity);
573         newPointOpacity_->Set(newPointOpacity);
574     }
575 }
576 
CalcAnimationEndCenterX(const LinearVector<float> & itemHalfSizes)577 void OverlengthDotIndicatorModifier::CalcAnimationEndCenterX(const LinearVector<float>& itemHalfSizes)
578 {
579     if (isSwiperTouchDown_ && (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT ||
580                                   gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT)) {
581         animationEndIndex_ = CalcTargetIndexOnDrag();
582     }
583 
584     CalcTargetOverlongStatus(animationStartIndex_, animationEndIndex_);
585 
586     auto startCenterX = CalcIndicatorCenterX(itemHalfSizes, currentSelectedIndex_, currentOverlongType_);
587     animationStartCenterX_ = startCenterX.first;
588     overlongSelectedStartCenterX_ = startCenterX.second;
589 
590     // long point move or no move
591     if (currentSelectedIndex_ != targetSelectedIndex_ || animationStartIndex_ == animationEndIndex_) {
592         moveDirection_ = OverlongIndicatorMove::NONE;
593         CalcTargetStatusOnLongPointMove(itemHalfSizes);
594         return;
595     }
596 
597     animationStartIndicatorWidth_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, true);
598     animationStartIndicatorHeight_ = CalcIndicatorSize(itemHalfSizes, currentOverlongType_, false);
599     animationEndCenterX_.resize(maxDisplayCount_ + 1);
600     animationEndIndicatorWidth_.resize(maxDisplayCount_ + 1);
601     animationEndIndicatorHeight_.resize(maxDisplayCount_ + 1);
602 
603     auto isBackward =
604         isHorizontalAndRTL_ ? animationStartIndex_ > animationEndIndex_ : animationStartIndex_ < animationEndIndex_;
605     if (isBackward) {
606         moveDirection_ = OverlongIndicatorMove::MOVE_BACKWARD;
607         CalcTargetStatusOnAllPointMoveBackward(itemHalfSizes);
608         return;
609     }
610 
611     moveDirection_ = OverlongIndicatorMove::MOVE_FORWARD;
612     CalcTargetStatusOnAllPointMoveForward(itemHalfSizes);
613 }
614 
PlayIndicatorAnimation(const OffsetF & margin,const LinearVector<float> & itemHalfSizes,GestureState gestureState,TouchBottomTypeLoop touchBottomTypeLoop)615 void OverlengthDotIndicatorModifier::PlayIndicatorAnimation(const OffsetF& margin,
616     const LinearVector<float>& itemHalfSizes, GestureState gestureState, TouchBottomTypeLoop touchBottomTypeLoop)
617 {
618     StopAnimation(false);
619     currentSelectedIndex_ = targetSelectedIndex_;
620     currentOverlongType_ = targetOverlongType_;
621     isTouchBottomLoop_ = false;
622     animationState_ = TouchBottomAnimationStage::STAGE_NONE;
623     normalMargin_ = margin;
624     CalcAnimationEndCenterX(itemHalfSizes);
625     PlayBlackPointsAnimation(itemHalfSizes);
626 
627     std::vector<std::pair<float, float>> pointCenterX;
628     if ((currentSelectedIndex_ == 0 && targetSelectedIndex_ == maxDisplayCount_ - 1) ||
629         (currentSelectedIndex_ == maxDisplayCount_ - 1 && targetSelectedIndex_ == 0)) {
630         auto currentSelectedIndex =
631             isHorizontalAndRTL_ ? maxDisplayCount_ - 1 - currentSelectedIndex_ : currentSelectedIndex_;
632         overlongSelectedStartCenterX_.first = animationEndCenterX_[currentSelectedIndex];
633         overlongSelectedStartCenterX_.second = animationEndCenterX_[currentSelectedIndex];
634         pointCenterX.emplace_back(overlongSelectedStartCenterX_);
635         pointCenterX.emplace_back(overlongSelectedEndCenterX_);
636     } else {
637         pointCenterX.emplace_back(overlongSelectedEndCenterX_);
638     }
639 
640     PlayLongPointAnimation(pointCenterX, gestureState, touchBottomTypeLoop, animationEndCenterX_, false);
641 }
642 
StopAnimation(bool ifImmediately)643 void OverlengthDotIndicatorModifier::StopAnimation(bool ifImmediately)
644 {
645     if (ifImmediately) {
646         AnimationOption option;
647         option.SetDuration(0);
648         option.SetCurve(Curves::LINEAR);
649         AnimationUtils::StartAnimation(option, [weak = WeakClaim(this)]() {
650             auto modifier = weak.Upgrade();
651             CHECK_NULL_VOID(modifier);
652             modifier->longPointLeftCenterX_->Set(modifier->longPointLeftCenterX_->Get());
653             modifier->longPointRightCenterX_->Set(modifier->longPointRightCenterX_->Get());
654         });
655     }
656 
657     blackPointsAnimEnd_ = true;
658     AnimationOption option;
659     option.SetDuration(0);
660     option.SetCurve(Curves::LINEAR);
661     AnimationUtils::StartAnimation(option, [weak = WeakClaim(this)]() {
662         auto modifier = weak.Upgrade();
663         CHECK_NULL_VOID(modifier);
664         modifier->vectorBlackPointCenterX_->Set(modifier->vectorBlackPointCenterX_->Get());
665         modifier->firstPointOpacity_->Set(modifier->firstPointOpacity_->Get());
666         modifier->newPointOpacity_->Set(modifier->newPointOpacity_->Get());
667         modifier->unselectedIndicatorWidth_->Set(modifier->unselectedIndicatorWidth_->Get());
668         modifier->unselectedIndicatorHeight_->Set(modifier->unselectedIndicatorHeight_->Get());
669     });
670 
671     longPointLeftAnimEnd_ = true;
672     longPointRightAnimEnd_ = true;
673     ifNeedFinishCallback_ = false;
674 }
675 
InitOverlongSelectedIndex(int32_t pageIndex)676 void OverlengthDotIndicatorModifier::InitOverlongSelectedIndex(int32_t pageIndex)
677 {
678     if (pageIndex < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
679         targetSelectedIndex_ = pageIndex;
680         return;
681     }
682 
683     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX) {
684         targetSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
685         return;
686     }
687 
688     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - THIRD_POINT_INDEX) {
689         targetSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
690         return;
691     }
692 
693     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - SECOND_POINT_INDEX) {
694         targetSelectedIndex_ = maxDisplayCount_ - 1 - SECOND_POINT_INDEX;
695         return;
696     }
697 
698     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1) {
699         targetSelectedIndex_ = maxDisplayCount_ - 1;
700         return;
701     }
702 }
703 
InitOverlongStatus(int32_t pageIndex)704 void OverlengthDotIndicatorModifier::InitOverlongStatus(int32_t pageIndex)
705 {
706     if (pageIndex < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
707         currentSelectedIndex_ = pageIndex;
708         currentOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
709 
710         targetSelectedIndex_ = currentSelectedIndex_;
711         targetOverlongType_ = currentOverlongType_;
712         return;
713     }
714 
715     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX) {
716         currentSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
717         currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
718 
719         targetSelectedIndex_ = currentSelectedIndex_;
720         targetOverlongType_ = currentOverlongType_;
721         return;
722     }
723 
724     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - THIRD_POINT_INDEX) {
725         currentSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
726         currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
727 
728         targetSelectedIndex_ = currentSelectedIndex_;
729         targetOverlongType_ = currentOverlongType_;
730         return;
731     }
732 
733     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1 - SECOND_POINT_INDEX) {
734         currentSelectedIndex_ = maxDisplayCount_ - 1 - SECOND_POINT_INDEX;
735         currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
736 
737         targetSelectedIndex_ = currentSelectedIndex_;
738         targetOverlongType_ = currentOverlongType_;
739         return;
740     }
741 
742     if (pageIndex >= maxDisplayCount_ - 1 - THIRD_POINT_INDEX && pageIndex == realItemCount_ - 1) {
743         currentSelectedIndex_ = maxDisplayCount_ - 1;
744         currentOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
745 
746         targetSelectedIndex_ = currentSelectedIndex_;
747         targetOverlongType_ = currentOverlongType_;
748         return;
749     }
750 }
751 
CalcTargetSelectedIndex(int32_t currentPageIndex,int32_t targetPageIndex)752 void OverlengthDotIndicatorModifier::CalcTargetSelectedIndex(int32_t currentPageIndex, int32_t targetPageIndex)
753 {
754     if (currentPageIndex == targetPageIndex || keepStatus_) {
755         return;
756     }
757 
758     if (currentPageIndex < targetPageIndex) {
759         CalcTargetSelectedIndexOnForward(currentPageIndex, targetPageIndex);
760         return;
761     }
762 
763     CalcTargetSelectedIndexOnBackward(currentPageIndex, targetPageIndex);
764 }
765 
CalcTargetOverlongStatus(int32_t currentPageIndex,int32_t targetPageIndex)766 void OverlengthDotIndicatorModifier::CalcTargetOverlongStatus(int32_t currentPageIndex, int32_t targetPageIndex)
767 {
768     if (currentPageIndex == targetPageIndex || currentOverlongType_ == OverlongType::NONE || keepStatus_) {
769         AdjustTargetStatus(targetPageIndex);
770         return;
771     }
772 
773     if (currentPageIndex == realItemCount_ - 1 && targetPageIndex == 0) {
774         targetSelectedIndex_ = 0;
775         targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
776         return;
777     }
778 
779     if (currentPageIndex == 0 && targetPageIndex == realItemCount_ - 1) {
780         targetSelectedIndex_ = maxDisplayCount_ - 1;
781         targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
782         return;
783     }
784 
785     CalcTargetSelectedIndex(currentPageIndex, targetPageIndex);
786 
787     if (currentPageIndex < targetPageIndex) {
788         if (currentOverlongType_ == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
789             if (targetSelectedIndex_ < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
790                 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
791             } else if (targetSelectedIndex_ == maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
792                 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
793             }
794         } else if (currentOverlongType_ == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
795             targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
796         } else {
797             if (targetSelectedIndex_ < maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
798                 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
799             } else if (targetSelectedIndex_ == maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
800                 if (targetPageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX) {
801                     targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
802                 } else {
803                     targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
804                 }
805             } else {
806                 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
807             }
808         }
809 
810         return;
811     }
812 
813     if (currentOverlongType_ == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
814         targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
815     } else if (currentOverlongType_ == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
816         if (targetSelectedIndex_ > THIRD_POINT_INDEX) {
817             targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
818         } else if (targetSelectedIndex_ == THIRD_POINT_INDEX) {
819             if (targetPageIndex > THIRD_POINT_INDEX) {
820                 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
821             } else {
822                 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
823             }
824         } else {
825             targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
826         }
827     } else {
828         if (targetSelectedIndex_ > THIRD_POINT_INDEX) {
829             targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
830         } else if (targetSelectedIndex_ == THIRD_POINT_INDEX) {
831             if (targetPageIndex > THIRD_POINT_INDEX) {
832                 targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_FADEOUT;
833             } else {
834                 targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
835             }
836         } else {
837             targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
838         }
839     }
840 }
841 
CalcIndicatorCenterX(const LinearVector<float> & itemHalfSizes,int32_t selectedIndex,OverlongType overlongType)842 std::pair<LinearVector<float>, std::pair<float, float>> OverlengthDotIndicatorModifier::CalcIndicatorCenterX(
843     const LinearVector<float>& itemHalfSizes, int32_t selectedIndex, OverlongType overlongType)
844 {
845     if (isHorizontalAndRTL_) {
846         selectedIndex = maxDisplayCount_ - 1 - selectedIndex;
847         overlongType = RevertOverlongType(overlongType);
848     }
849 
850     auto unselectedIndicatorRadius = itemHalfSizes[ITEM_HALF_WIDTH];
851     auto selectedIndicatorRadius = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
852     if (!isCustomSizeValue_) {
853         selectedIndicatorRadius *= 2.0f;
854     }
855 
856     LinearVector<float> indicatorCenterX(maxDisplayCount_ + 1);
857     std::pair<float, float> longPointCenterX;
858     float itemSpacePx = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx());
859     auto leftFirstRadius = unselectedIndicatorRadius * SMALLEST_POINT_RATIO;
860     auto leftSecondRadius = unselectedIndicatorRadius * SECOND_SMALLEST_POINT_RATIO;
861     auto rightFirstRadius = unselectedIndicatorRadius * SMALLEST_POINT_RATIO;
862     auto rightSecondRadius = unselectedIndicatorRadius * SECOND_SMALLEST_POINT_RATIO;
863 
864     auto startIndicatorCenterX = normalMargin_.GetX() + static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx());
865     for (int32_t i = 0; i < maxDisplayCount_; i++) {
866         if (i == LEFT_FIRST_POINT_INDEX) {
867             if (i == selectedIndex) {
868                 startIndicatorCenterX += selectedIndicatorRadius;
869                 indicatorCenterX[i] = startIndicatorCenterX;
870                 startIndicatorCenterX += selectedIndicatorRadius;
871 
872                 longPointCenterX.first =
873                     indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
874                 longPointCenterX.second =
875                     indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
876             } else if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
877                 startIndicatorCenterX += unselectedIndicatorRadius;
878                 indicatorCenterX[i] = startIndicatorCenterX;
879                 startIndicatorCenterX += unselectedIndicatorRadius;
880             } else {
881                 startIndicatorCenterX += leftFirstRadius;
882                 indicatorCenterX[i] = startIndicatorCenterX;
883                 startIndicatorCenterX += leftFirstRadius;
884             }
885             continue;
886         }
887 
888         if (i == SECOND_POINT_INDEX) {
889             if (i == selectedIndex) {
890                 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
891                 indicatorCenterX[i] = startIndicatorCenterX;
892                 startIndicatorCenterX += selectedIndicatorRadius;
893 
894                 longPointCenterX.first =
895                     indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
896                 longPointCenterX.second =
897                     indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
898             } else if (overlongType == OverlongType::LEFT_NORMAL_RIGHT_FADEOUT) {
899                 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
900                 indicatorCenterX[i] = startIndicatorCenterX;
901                 startIndicatorCenterX += unselectedIndicatorRadius;
902             } else {
903                 startIndicatorCenterX += itemSpacePx + leftSecondRadius;
904                 indicatorCenterX[i] = startIndicatorCenterX;
905                 startIndicatorCenterX += leftSecondRadius;
906             }
907             continue;
908         }
909 
910         if (i >= THIRD_POINT_INDEX && i <= maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
911             if (i == selectedIndex) {
912                 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
913                 indicatorCenterX[i] = startIndicatorCenterX;
914                 startIndicatorCenterX += selectedIndicatorRadius;
915 
916                 longPointCenterX.first =
917                     indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
918                 longPointCenterX.second =
919                     indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
920             } else {
921                 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
922                 indicatorCenterX[i] = startIndicatorCenterX;
923                 startIndicatorCenterX += unselectedIndicatorRadius;
924             }
925             continue;
926         }
927 
928         if (i == maxDisplayCount_ - 1 - SECOND_POINT_INDEX) {
929             if (i == selectedIndex) {
930                 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
931                 indicatorCenterX[i] = startIndicatorCenterX;
932                 startIndicatorCenterX += selectedIndicatorRadius;
933 
934                 longPointCenterX.first =
935                     indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
936                 longPointCenterX.second =
937                     indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
938             } else if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
939                 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
940                 indicatorCenterX[i] = startIndicatorCenterX;
941                 startIndicatorCenterX += unselectedIndicatorRadius;
942             } else {
943                 startIndicatorCenterX += itemSpacePx + rightSecondRadius;
944                 indicatorCenterX[i] = startIndicatorCenterX;
945                 startIndicatorCenterX += rightSecondRadius;
946             }
947             continue;
948         }
949 
950         if (i == maxDisplayCount_ - 1) {
951             if (i == selectedIndex) {
952                 startIndicatorCenterX += itemSpacePx + selectedIndicatorRadius;
953                 indicatorCenterX[i] = startIndicatorCenterX;
954                 startIndicatorCenterX += selectedIndicatorRadius;
955 
956                 longPointCenterX.first =
957                     indicatorCenterX[i] - (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
958                 longPointCenterX.second =
959                     indicatorCenterX[i] + (isCustomSizeValue_ ? 0.0f : selectedIndicatorRadius * 0.5f);
960             } else if (overlongType == OverlongType::LEFT_FADEOUT_RIGHT_NORMAL) {
961                 startIndicatorCenterX += itemSpacePx + unselectedIndicatorRadius;
962                 indicatorCenterX[i] = startIndicatorCenterX;
963                 startIndicatorCenterX += unselectedIndicatorRadius;
964             } else {
965                 startIndicatorCenterX += itemSpacePx + rightFirstRadius;
966                 indicatorCenterX[i] = startIndicatorCenterX;
967                 startIndicatorCenterX += rightFirstRadius;
968             }
969             continue;
970         }
971     }
972 
973     return std::make_pair(indicatorCenterX, longPointCenterX);
974 }
975 
AdjustTargetStatus(int32_t targetPageIndex)976 void OverlengthDotIndicatorModifier::AdjustTargetStatus(int32_t targetPageIndex)
977 {
978     targetSelectedIndex_ = SwiperIndicatorUtils::GetLoopIndex(targetSelectedIndex_, maxDisplayCount_);
979     if (targetPageIndex == 0 || targetPageIndex == SECOND_POINT_INDEX || targetPageIndex == THIRD_POINT_INDEX) {
980         targetSelectedIndex_ = targetPageIndex;
981         targetOverlongType_ = OverlongType::LEFT_NORMAL_RIGHT_FADEOUT;
982         return;
983     }
984 
985     if (targetPageIndex == realItemCount_ - 1) {
986         targetSelectedIndex_ = maxDisplayCount_ - 1;
987         targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
988         return;
989     }
990 
991     if (targetPageIndex == realItemCount_ - 1 - SECOND_POINT_INDEX) {
992         targetSelectedIndex_ = maxDisplayCount_ - 1 - SECOND_POINT_INDEX;
993         targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
994         return;
995     }
996 
997     if (targetPageIndex == realItemCount_ - 1 - THIRD_POINT_INDEX) {
998         targetSelectedIndex_ = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
999         targetOverlongType_ = OverlongType::LEFT_FADEOUT_RIGHT_NORMAL;
1000         return;
1001     }
1002 
1003     if (targetPageIndex > THIRD_POINT_INDEX && targetSelectedIndex_ < THIRD_POINT_INDEX) {
1004         InitOverlongSelectedIndex(targetPageIndex);
1005         return;
1006     }
1007 
1008     if (targetPageIndex < realItemCount_ - 1 - THIRD_POINT_INDEX &&
1009         targetSelectedIndex_ > maxDisplayCount_ - 1 - THIRD_POINT_INDEX) {
1010         InitOverlongSelectedIndex(targetPageIndex);
1011         return;
1012     }
1013 }
1014 
CalcTargetSelectedIndexOnForward(int32_t currentPageIndex,int32_t targetPageIndex)1015 void OverlengthDotIndicatorModifier::CalcTargetSelectedIndexOnForward(int32_t currentPageIndex, int32_t targetPageIndex)
1016 {
1017     auto step = std::abs(targetPageIndex - currentPageIndex);
1018     auto rightThirdIndicatorIndex = maxDisplayCount_ - 1 - THIRD_POINT_INDEX;
1019     auto rightSecondPageIndex = realItemCount_ - 1 - SECOND_POINT_INDEX;
1020     if (currentSelectedIndex_ == rightThirdIndicatorIndex) {
1021         if (targetPageIndex < rightSecondPageIndex) {
1022             step = 0;
1023         } else {
1024             step = targetPageIndex - currentPageIndex;
1025         }
1026     } else if (currentSelectedIndex_ < rightThirdIndicatorIndex) {
1027         if (targetPageIndex < rightSecondPageIndex) {
1028             step = std::min(targetPageIndex - currentPageIndex, rightThirdIndicatorIndex - currentSelectedIndex_);
1029         } else if (targetPageIndex == rightSecondPageIndex) {
1030             step = rightThirdIndicatorIndex - currentSelectedIndex_ + 1;
1031         } else {
1032             step = rightThirdIndicatorIndex - currentSelectedIndex_ + THIRD_POINT_INDEX;
1033         }
1034     } else {
1035         step = targetPageIndex - currentPageIndex;
1036     }
1037 
1038     targetSelectedIndex_ = currentSelectedIndex_ + step;
1039     AdjustTargetStatus(targetPageIndex);
1040 }
1041 
CalcTargetSelectedIndexOnBackward(int32_t currentPageIndex,int32_t targetPageIndex)1042 void OverlengthDotIndicatorModifier::CalcTargetSelectedIndexOnBackward(
1043     int32_t currentPageIndex, int32_t targetPageIndex)
1044 {
1045     auto step = std::abs(targetPageIndex - currentPageIndex);
1046     if (currentSelectedIndex_ > THIRD_POINT_INDEX) {
1047         if (targetPageIndex > SECOND_POINT_INDEX) {
1048             step = std::min(currentPageIndex - targetPageIndex, currentSelectedIndex_ - THIRD_POINT_INDEX);
1049         } else if (targetPageIndex == SECOND_POINT_INDEX) {
1050             step = currentSelectedIndex_ - SECOND_POINT_INDEX;
1051         } else {
1052             step = currentSelectedIndex_ - LEFT_FIRST_POINT_INDEX;
1053         }
1054     } else if (currentSelectedIndex_ == THIRD_POINT_INDEX) {
1055         if (targetPageIndex > SECOND_POINT_INDEX) {
1056             step = 0;
1057         } else if (targetPageIndex == SECOND_POINT_INDEX) {
1058             step = SECOND_POINT_INDEX;
1059         } else {
1060             step = THIRD_POINT_INDEX;
1061         }
1062     } else {
1063         step = currentPageIndex - targetPageIndex;
1064     }
1065 
1066     targetSelectedIndex_ = currentSelectedIndex_ - step;
1067     AdjustTargetStatus(targetPageIndex);
1068 }
1069 
1070 } // namespace OHOS::Ace::NG
1071