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