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