1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/swiper_indicator/dot_indicator/dot_indicator_paint_method.h"
17
18 #include "core/components/common/layout/constants.h"
19 #include "core/components/common/properties/color.h"
20 namespace OHOS::Ace::NG {
21 namespace {
22 // for indicator
23 constexpr float BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY = 0.4f;
24 constexpr float LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY = 0.2f;
25 constexpr float LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY = 1.0f;
26 constexpr float CENTER_BEZIER_CURVE_MASS = 0.0f;
27 constexpr float CENTER_BEZIER_CURVE_STIFFNESS = 1.0f;
28 constexpr float CENTER_BEZIER_CURVE_DAMPING = 1.0f;
29 constexpr uint32_t ITEM_HALF_WIDTH = 0;
30 constexpr uint32_t ITEM_HALF_HEIGHT = 1;
31 constexpr uint32_t SELECTED_ITEM_HALF_WIDTH = 2;
32 constexpr uint32_t SELECTED_ITEM_HALF_HEIGHT = 3;
33 constexpr float TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE = 1.225f;
34 constexpr float TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE = 0.0125f;
35 constexpr float LONG_POINT_TAIL_RATIO = 0.5f;
36 constexpr float FIFTY_PERCENT = 0.5f;
37 constexpr float HALF_SELECTED_WIDTH = 2.0f;
38 constexpr float HALF_FLOAT = 0.5f;
39 constexpr int TWOFOLD = 2;
40 constexpr float HALF = 0.5f;
41 } // namespace
42
UpdateContentModifier(PaintWrapper * paintWrapper)43 void DotIndicatorPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
44 {
45 CHECK_NULL_VOID(dotIndicatorModifier_);
46 CHECK_NULL_VOID(paintWrapper);
47
48 auto pipelineContext = PipelineBase::GetCurrentContext();
49 CHECK_NULL_VOID(pipelineContext);
50 auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
51 CHECK_NULL_VOID(swiperTheme);
52
53 const auto& geometryNode = paintWrapper->GetGeometryNode();
54 CHECK_NULL_VOID(geometryNode);
55
56 auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
57 CHECK_NULL_VOID(paintProperty);
58 IsCustomSizeValue_ = paintProperty->GetIsCustomSizeValue(false);
59 dotIndicatorModifier_->SetAxis(axis_);
60 auto [currentIndex, currentIndexActual] = CalCurrentIndex();
61 dotIndicatorModifier_->SetCurrentIndex(currentIndex);
62 dotIndicatorModifier_->SetCurrentIndexActual(currentIndexActual);
63 dotIndicatorModifier_->SetUnselectedColor(paintProperty->GetColorValue(swiperTheme->GetColor()));
64 dotIndicatorModifier_->SetSelectedColor(paintProperty->GetSelectedColorValue(swiperTheme->GetSelectedColor()));
65 dotIndicatorModifier_->SetIndicatorMask(paintProperty->GetIndicatorMaskValue(false));
66 dotIndicatorModifier_->SetIsIndicatorCustomSize(IsCustomSizeValue_);
67 dotIndicatorModifier_->SetOffset(geometryNode->GetContentOffset());
68 dotIndicatorModifier_->SetIndicatorDotItemSpace(
69 paintProperty->GetSpaceValue(swiperTheme->GetIndicatorDotItemSpace()));
70
71 SizeF contentSize = geometryNode->GetFrameSize();
72 centerY_ = (axis_ == Axis::HORIZONTAL ? contentSize.Height() : contentSize.Width()) * 0.5;
73 dotIndicatorModifier_->SetCenterY(centerY_);
74 if (touchBottomType_ != TouchBottomType::NONE) {
75 if (!dotIndicatorModifier_->GetIsPressed()) {
76 PaintPressIndicator(paintWrapper);
77 dotIndicatorModifier_->SetIsPressed(true);
78 }
79 UpdateBackground(paintWrapper);
80 } else if (isPressed_) {
81 PaintPressIndicator(paintWrapper);
82 dotIndicatorModifier_->SetIsPressed(true);
83 } else if (isHover_) {
84 PaintHoverIndicator(paintWrapper);
85 dotIndicatorModifier_->SetIsHover(true);
86 } else {
87 PaintNormalIndicator(paintWrapper);
88 dotIndicatorModifier_->SetIsHover(false);
89 dotIndicatorModifier_->SetIsPressed(false);
90 }
91 }
92
CalCurrentIndex()93 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::CalCurrentIndex()
94 {
95 totalItemCount_ = !isAutoLinear_ ? totalItemCount_ : itemCount_;
96 if (isHorizontalAndRightToLeft_) {
97 if (isSwipeByGroup_) {
98 currentIndex_ = totalItemCount_ - 1 - currentIndex_;
99 } else {
100 currentIndex_ = itemCount_ - 1 - currentIndex_;
101 }
102 }
103 auto currentIndex = currentIndex_;
104 auto currentIndexActual = currentIndexActual_;
105 if (!isAutoLinear_ && isSwipeByGroup_ && displayCount_ != 0) {
106 currentIndex = currentIndex_ / displayCount_;
107 currentIndexActual = currentIndexActual_ / displayCount_;
108 }
109 return { currentIndex, currentIndexActual };
110 }
111
NeedBottomAnimation() const112 bool DotIndicatorPaintMethod::NeedBottomAnimation() const
113 {
114 auto currentIndexActual = currentIndexActual_;
115 auto firstIndex = firstIndex_;
116 if (!isAutoLinear_ && isSwipeByGroup_ && displayCount_ != 0) {
117 firstIndex /= displayCount_;
118 currentIndexActual /= displayCount_;
119 }
120 firstIndex = isHorizontalAndRightToLeft_ ? itemCount_ - 1 - firstIndex : firstIndex;
121 if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT) {
122 if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
123 if (NearZero(touchBottomPageRate_)) {
124 return true;
125 }
126
127 if (currentIndexActual != firstIndex && std::abs(touchBottomPageRate_) < FIFTY_PERCENT) {
128 return false;
129 }
130
131 return true;
132 }
133
134 if (currentIndexActual == firstIndex && firstIndex == itemCount_ - 1 &&
135 std::abs(touchBottomPageRate_) > FIFTY_PERCENT) {
136 return true;
137 }
138 }
139
140 if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
141 if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
142 if (currentIndexActual == 0 && targetIndex_ && targetIndex_.value() == 0 &&
143 std::abs(touchBottomPageRate_) < FIFTY_PERCENT && !NearZero(touchBottomPageRate_)) {
144 return true;
145 }
146
147 return false;
148 }
149
150 if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
151 if (currentIndexActual == firstIndex && std::abs(touchBottomPageRate_) > FIFTY_PERCENT) {
152 return false;
153 }
154 // NearZero(touchBottomPageRate_) is Actual judgment, others are Preconditions.
155 if (currentIndexActual == itemCount_ - 1 && firstIndex == 0 && NearZero(touchBottomPageRate_)) {
156 return false;
157 }
158
159 return true;
160 }
161
162 if (currentIndexActual == 0 && firstIndex == itemCount_ - 1 &&
163 std::abs(touchBottomPageRate_) < FIFTY_PERCENT) {
164 return true;
165 }
166 }
167
168 return false;
169 }
170
GetLongPointAnimationStateSecondCenter(const PaintWrapper * paintWrapper,std::vector<std::pair<float,float>> & pointCenterX)171 void DotIndicatorPaintMethod::GetLongPointAnimationStateSecondCenter(
172 const PaintWrapper* paintWrapper, std::vector<std::pair<float, float>>& pointCenterX)
173 {
174 if (NeedBottomAnimation()) {
175 pointAnimationStage_ = PointAnimationStage::STATE_EXPAND_TO_LONG_POINT;
176 auto [longPointCenterX, _] = CalculateLongPointCenterX(paintWrapper);
177 pointAnimationStage_ = PointAnimationStage::STATE_SHRINKT_TO_BLACK_POINT;
178 pointCenterX.push_back(longPointCenterX);
179 }
180 }
181
UpdateNormalIndicator(LinearVector<float> & itemHalfSizes,const PaintWrapper * paintWrapper)182 void DotIndicatorPaintMethod::UpdateNormalIndicator(
183 LinearVector<float>& itemHalfSizes, const PaintWrapper* paintWrapper)
184 {
185 CHECK_NULL_VOID(dotIndicatorModifier_);
186 if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
187 gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
188 std::vector<std::pair<float, float>> pointCenterX({ longPointCenterX_ });
189 GetLongPointAnimationStateSecondCenter(paintWrapper, pointCenterX);
190 dotIndicatorModifier_->PlayIndicatorAnimation(
191 vectorBlackPointCenterX_, pointCenterX, gestureState_, touchBottomTypeLoop_);
192 } else {
193 dotIndicatorModifier_->UpdateNormalPaintProperty(
194 normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
195 }
196 }
197
PaintNormalIndicator(const PaintWrapper * paintWrapper)198 void DotIndicatorPaintMethod::PaintNormalIndicator(const PaintWrapper* paintWrapper)
199 {
200 CHECK_NULL_VOID(dotIndicatorModifier_);
201 auto [longPointCenterX, itemHalfSizes] = CalculateLongPointCenterX(paintWrapper);
202 longPointCenterX_ = longPointCenterX;
203
204 if (dotIndicatorModifier_->GetIsHover()) {
205 dotIndicatorModifier_->UpdateHoverToNormalPaintProperty(
206 normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
207 } else if (dotIndicatorModifier_->GetIsPressed()) {
208 dotIndicatorModifier_->UpdatePressToNormalPaintProperty(
209 normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
210 } else {
211 UpdateNormalIndicator(itemHalfSizes, paintWrapper);
212 }
213 }
214
PaintHoverIndicator(const PaintWrapper * paintWrapper)215 void DotIndicatorPaintMethod::PaintHoverIndicator(const PaintWrapper* paintWrapper)
216 {
217 CHECK_NULL_VOID(dotIndicatorModifier_);
218 CHECK_NULL_VOID(paintWrapper);
219 auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
220 CHECK_NULL_VOID(paintProperty);
221 auto indicatorTheme = GetSwiperIndicatorTheme();
222 CHECK_NULL_VOID(indicatorTheme);
223 // diameter calculation
224 auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
225 auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
226 auto selectedItemWidth =
227 static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
228 auto selectedItemHeight =
229 static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
230 // use radius calculation
231 LinearVector<float> itemHalfSizes;
232 float indicatorScale = indicatorTheme->GetIndicatorScale();
233 itemHalfSizes.emplace_back(itemWidth * HALF * indicatorScale);
234 itemHalfSizes.emplace_back(itemHeight * HALF * indicatorScale);
235 itemHalfSizes.emplace_back(selectedItemWidth * HALF * indicatorScale);
236 itemHalfSizes.emplace_back(selectedItemHeight * HALF * indicatorScale);
237 Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
238 Dimension indicatorDotItemSpace =
239 paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
240
241 longPointCenterX_ =
242 CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
243 static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
244 if (dotIndicatorModifier_->GetIsPressed()) {
245 dotIndicatorModifier_->SetIsPressed(false);
246 dotIndicatorModifier_->UpdateHoverAndPressConversionPaintProperty();
247 } else if (dotIndicatorModifier_->GetIsHover()) {
248 if (!mouseClickIndex_.has_value()) {
249 dotIndicatorModifier_->UpdateHoverPaintProperty(itemHalfSizes,
250 vectorBlackPointCenterX_, longPointCenterX_);
251 }
252 } else {
253 dotIndicatorModifier_->UpdateNormalToHoverPaintProperty(
254 itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
255 }
256
257 CalculateHoverIndex(itemHalfSizes);
258 if (dotIndicatorModifier_->GetNormalToHoverIndex() != hoverIndex_) {
259 dotIndicatorModifier_->SetHoverToNormalIndex(dotIndicatorModifier_->GetNormalToHoverIndex());
260 dotIndicatorModifier_->UpdateHoverToNormalPointDilateRatio();
261 dotIndicatorModifier_->SetNormalToHoverIndex(hoverIndex_);
262 dotIndicatorModifier_->UpdateNormalToHoverPointDilateRatio();
263 }
264
265 PaintHoverIndicator(itemHalfSizes, paddingSide, indicatorDotItemSpace);
266 }
267
CalculateMouseClickIndexOnRTL()268 int32_t DotIndicatorPaintMethod::CalculateMouseClickIndexOnRTL()
269 {
270 int32_t mouseClickIndex = 0;
271 if (!mouseClickIndex_) {
272 return mouseClickIndex;
273 }
274
275 if (isSwipeByGroup_) {
276 mouseClickIndex = totalItemCount_ - 1 - mouseClickIndex_.value();
277 } else {
278 mouseClickIndex = itemCount_ - 1 - mouseClickIndex_.value();
279 }
280
281 return mouseClickIndex;
282 }
283
PaintHoverIndicator(LinearVector<float> & itemHalfSizes,const Dimension paddingSide,const Dimension & indicatorDotItemSpace)284 void DotIndicatorPaintMethod::PaintHoverIndicator(LinearVector<float>& itemHalfSizes, const Dimension paddingSide,
285 const Dimension& indicatorDotItemSpace)
286 {
287 CHECK_NULL_VOID(dotIndicatorModifier_);
288 if (mouseClickIndex_) {
289 if (currentIndex_ == totalItemCount_ - displayCount_ && !isLoop_ && mouseClickIndex_ > currentIndex_ &&
290 mouseClickIndex_ < totalItemCount_) {
291 longPointCenterX_ = CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
292 static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
293 } else {
294 auto mouseClickIndex = isHorizontalAndRightToLeft_ ?
295 CalculateMouseClickIndexOnRTL() : mouseClickIndex_.value();
296 longPointCenterX_ = CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
297 static_cast<float>(indicatorDotItemSpace.ConvertToPx()), mouseClickIndex);
298 }
299 dotIndicatorModifier_->UpdateAllPointCenterXAnimation(
300 gestureState_, vectorBlackPointCenterX_, longPointCenterX_);
301 mouseClickIndex_ = std::nullopt;
302 }
303 if (dotIndicatorModifier_->GetLongPointIsHover() != longPointIsHover_) {
304 dotIndicatorModifier_->SetLongPointIsHover(longPointIsHover_);
305 dotIndicatorModifier_->UpdateLongPointDilateRatio();
306 }
307 }
308
PaintPressIndicator(const PaintWrapper * paintWrapper)309 void DotIndicatorPaintMethod::PaintPressIndicator(const PaintWrapper* paintWrapper)
310 {
311 CHECK_NULL_VOID(dotIndicatorModifier_);
312 CHECK_NULL_VOID(paintWrapper);
313 auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
314 CHECK_NULL_VOID(paintProperty);
315 auto indicatorTheme = GetSwiperIndicatorTheme();
316 CHECK_NULL_VOID(indicatorTheme);
317 // diameter calculation
318 auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
319 auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
320 auto selectedItemWidth =
321 static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
322 auto selectedItemHeight =
323 static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
324 // use radius calculation
325 float indicatorScale = indicatorTheme->GetIndicatorScale();
326 auto itemHalfWidth = itemWidth * HALF * indicatorScale;
327 auto itemHalfHeight = itemHeight * HALF * indicatorScale;
328 auto selectedItemHalfWidth = selectedItemWidth * HALF * indicatorScale;
329 auto selectedItemHalfHeight = selectedItemHeight * HALF * indicatorScale;
330 LinearVector<float> itemHalfSizes;
331 itemHalfSizes.emplace_back(itemHalfWidth);
332 itemHalfSizes.emplace_back(itemHalfHeight);
333 itemHalfSizes.emplace_back(selectedItemHalfWidth);
334 itemHalfSizes.emplace_back(selectedItemHalfHeight);
335 Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
336 Dimension indicatorDotItemSpace =
337 paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
338 longPointCenterX_ =
339 CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
340 static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
341 if (dotIndicatorModifier_->GetIsPressed()) {
342 dotIndicatorModifier_->UpdatePressPaintProperty(itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
343 } else if (dotIndicatorModifier_->GetIsHover()) {
344 dotIndicatorModifier_->SetIsPressed(true);
345 dotIndicatorModifier_->UpdateHoverAndPressConversionPaintProperty();
346 } else {
347 dotIndicatorModifier_->UpdateNormalToPressPaintProperty(
348 itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
349 }
350 }
351
CalculateNormalMargin(const LinearVector<float> & itemHalfSizes,const SizeF & frameSize,const int32_t displayCount,const Dimension & indicatorDotItemSpace,bool ignoreSize)352 void DotIndicatorPaintMethod::CalculateNormalMargin(const LinearVector<float>& itemHalfSizes,
353 const SizeF& frameSize, const int32_t displayCount, const Dimension& indicatorDotItemSpace, bool ignoreSize)
354 {
355 // diameter calculation
356 auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * 2;
357 auto itemHeight = itemHalfSizes[ITEM_HALF_HEIGHT] * 2;
358 auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * 2;
359 auto selectedItemHeight = itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT] * 2;
360 auto allPointDiameterSum = itemWidth * static_cast<float>(displayCount + 1);
361 if (IsCustomSizeValue_) {
362 allPointDiameterSum = itemWidth * static_cast<float>(displayCount - 1) + selectedItemWidth;
363 }
364 auto allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (displayCount - 1);
365 auto indicatorTheme = GetSwiperIndicatorTheme();
366 CHECK_NULL_VOID(indicatorTheme);
367 Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
368 auto indicatorPaddingSide = static_cast<float>(paddingSide.ConvertToPx());
369 auto contentWidth = indicatorPaddingSide + allPointDiameterSum + allPointSpaceSum + indicatorPaddingSide;
370 auto indicatorHeightPadding = indicatorTheme->GetIndicatorBgHeight().ConvertToPx();
371
372 auto contentHeight = indicatorHeightPadding + itemHeight + indicatorHeightPadding;
373 if (selectedItemHeight > itemHeight) {
374 contentHeight = indicatorHeightPadding + selectedItemHeight + indicatorHeightPadding;
375 }
376
377 float marginX = ((axis_ == Axis::HORIZONTAL ? frameSize.Width() : frameSize.Height()) - contentWidth) * 0.5;
378 float marginY = ((axis_ == Axis::HORIZONTAL ? frameSize.Height() : frameSize.Width()) - contentHeight) * 0.5;
379 normalMargin_.SetX(marginX);
380 normalMargin_.SetY(marginY);
381 }
382
CalculatePointCenterX(const LinearVector<float> & itemHalfSizes,float margin,float padding,float space,int32_t index)383 std::pair<float, float> DotIndicatorPaintMethod::CalculatePointCenterX(
384 const LinearVector<float>& itemHalfSizes, float margin, float padding, float space, int32_t index)
385 {
386 if (itemCount_ == 0) {
387 return { 0, 0 };
388 }
389 float startCenterX = margin + padding;
390 float endCenterX = margin + padding;
391
392 if (!isAutoLinear_) {
393 if (isSwipeByGroup_ && displayCount_ != 0) {
394 index /= displayCount_;
395 }
396 if (isPressed_ && isSwipeByGroup_) {
397 touchBottomTypeLoop_ = TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE;
398 }
399 }
400
401 if (Positive(turnPageRate_)) {
402 auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
403 auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
404 float allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ + 1);
405 if (IsCustomSizeValue_) {
406 allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ - 1) + selectedItemWidth;
407 }
408 auto allPointSpaceSum = static_cast<float>(space * (itemCount_ - 1));
409
410 float rectWidth = padding + allPointDiameterSum + allPointSpaceSum + padding;
411 startCenterX = rectWidth - startCenterX;
412 endCenterX = rectWidth - endCenterX;
413 return BackwardCalculation(itemHalfSizes, startCenterX, endCenterX, space, index);
414 }
415 return ForwardCalculation(itemHalfSizes, startCenterX, endCenterX, space, index);
416 }
417
CalculateLongPointCenterX(const PaintWrapper * paintWrapper)418 std::tuple<std::pair<float, float>, LinearVector<float>> DotIndicatorPaintMethod::CalculateLongPointCenterX(
419 const PaintWrapper* paintWrapper)
420 {
421 std::tuple<std::pair<float, float>, LinearVector<float>> tmp;
422 CHECK_NULL_RETURN(paintWrapper, tmp);
423 const auto& geometryNode = paintWrapper->GetGeometryNode();
424 CHECK_NULL_RETURN(geometryNode, tmp);
425 auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
426 CHECK_NULL_RETURN(paintProperty, tmp);
427 auto indicatorTheme = GetSwiperIndicatorTheme();
428 CHECK_NULL_RETURN(indicatorTheme, tmp);
429 SizeF frameSize = geometryNode->GetFrameSize();
430 // diameter calculation
431 auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
432 auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
433 auto selectedItemWidth =
434 static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
435 auto selectedItemHeight =
436 static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
437 // use radius calculation
438 LinearVector<float> itemHalfSizes;
439 itemHalfSizes.emplace_back(itemWidth * 0.5);
440 itemHalfSizes.emplace_back(itemHeight * 0.5);
441 itemHalfSizes.emplace_back(selectedItemWidth * 0.5);
442 itemHalfSizes.emplace_back(selectedItemHeight * 0.5);
443
444 Dimension indicatorDotItemSpace =
445 paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
446 bool ignoreSize = paintProperty->GetIgnoreSizeValue(false);
447 CalculateNormalMargin(itemHalfSizes, frameSize, itemCount_, indicatorDotItemSpace, ignoreSize);
448 Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
449 auto longPointCenterX = CalculatePointCenterX(itemHalfSizes, normalMargin_.GetX(),
450 static_cast<float>(paddingSide.ConvertToPx()),
451 static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
452 return { longPointCenterX, itemHalfSizes };
453 }
454
GetMoveRate()455 std::tuple<float, float, float> DotIndicatorPaintMethod::GetMoveRate()
456 {
457 auto actualTurnPageRate = !isAutoLinear_ && isSwipeByGroup_ ? groupTurnPageRate_ : turnPageRate_;
458 float blackPointCenterMoveRate = CubicCurve(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS,
459 CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(actualTurnPageRate));
460 float longPointLeftCenterMoveRate = 0.0f;
461 float longPointRightCenterMoveRate = 0.0f;
462 if (isPressed_ && touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
463 longPointLeftCenterMoveRate = CubicCurve(turnPageRate_ > 0 ? LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY :
464 LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS,
465 CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(turnPageRate_));
466 longPointRightCenterMoveRate = CubicCurve(turnPageRate_ > 0 ? LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY :
467 LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS,
468 CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(turnPageRate_));
469 } else if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
470 gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
471 blackPointCenterMoveRate = 1;
472 longPointLeftCenterMoveRate = 1;
473 longPointRightCenterMoveRate = 1;
474 } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
475 auto rateAbs = 1.0f - std::abs(actualTurnPageRate);
476 // x0:0.33, y0:0, x1:0.67, y1:1
477 longPointLeftCenterMoveRate = longPointRightCenterMoveRate = CubicCurve(0.33, 0, 0.67, 1).MoveInternal(rateAbs);
478 } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
479 auto rateAbs = std::abs(actualTurnPageRate);
480 // x0:0.33, y0:0, x1:0.67, y1:1
481 longPointLeftCenterMoveRate = longPointRightCenterMoveRate = CubicCurve(0.33, 0, 0.67, 1).MoveInternal(rateAbs);
482 } else if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT) {
483 longPointLeftCenterMoveRate =std::abs(actualTurnPageRate);
484 longPointRightCenterMoveRate = std::abs(actualTurnPageRate) +
485 ((1 - longPointLeftCenterMoveRate) * LONG_POINT_TAIL_RATIO);
486 } else if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT) {
487 longPointRightCenterMoveRate = std::abs(actualTurnPageRate);
488 longPointLeftCenterMoveRate = std::abs(actualTurnPageRate) * LONG_POINT_TAIL_RATIO;
489 }
490 return { blackPointCenterMoveRate, longPointLeftCenterMoveRate, longPointRightCenterMoveRate };
491 }
492
CalculatePointCenterX(const StarAndEndPointCenter & starAndEndPointCenter,const LinearVector<float> & startVectorBlackPointCenterX,const LinearVector<float> & endVectorBlackPointCenterX)493 std::pair<float, float> DotIndicatorPaintMethod::CalculatePointCenterX(
494 const StarAndEndPointCenter& starAndEndPointCenter, const LinearVector<float>& startVectorBlackPointCenterX,
495 const LinearVector<float>& endVectorBlackPointCenterX)
496 {
497 const auto [blackPointCenterMoveRate, longPointLeftCenterMoveRate, longPointRightCenterMoveRate] = GetMoveRate();
498
499 vectorBlackPointCenterX_.resize(itemCount_);
500 for (int32_t i = 0; i < itemCount_; ++i) {
501 vectorBlackPointCenterX_[i] = startVectorBlackPointCenterX[i] +
502 (endVectorBlackPointCenterX[i] - startVectorBlackPointCenterX[i]) * blackPointCenterMoveRate;
503 }
504
505 std::pair<float, float> longPointCenterX;
506 longPointCenterX.first = starAndEndPointCenter.startLongPointLeftCenterX +
507 (starAndEndPointCenter.endLongPointLeftCenterX - starAndEndPointCenter.startLongPointLeftCenterX) *
508 longPointLeftCenterMoveRate;
509 longPointCenterX.second = starAndEndPointCenter.startLongPointRightCenterX +
510 (starAndEndPointCenter.endLongPointRightCenterX - starAndEndPointCenter.startLongPointRightCenterX) *
511 longPointRightCenterMoveRate;
512 if (isHorizontalAndRightToLeft_) {
513 longPointCenterX.first = starAndEndPointCenter.startLongPointLeftCenterX +
514 (starAndEndPointCenter.endLongPointLeftCenterX - starAndEndPointCenter.startLongPointLeftCenterX) *
515 longPointLeftCenterMoveRate;
516 longPointCenterX.second = starAndEndPointCenter.startLongPointRightCenterX +
517 (starAndEndPointCenter.endLongPointRightCenterX - starAndEndPointCenter.startLongPointRightCenterX) *
518 longPointRightCenterMoveRate;
519 }
520 return longPointCenterX;
521 }
522
CalculateHoverIndex(const LinearVector<float> & itemHalfSizes)523 void DotIndicatorPaintMethod::CalculateHoverIndex(const LinearVector<float>& itemHalfSizes)
524 {
525 CHECK_NULL_VOID(dotIndicatorModifier_);
526 if (!isHover_) {
527 hoverIndex_ = std::nullopt;
528 longPointIsHover_ = false;
529 return;
530 }
531 for (size_t i = 0; i < vectorBlackPointCenterX_.size(); ++i) {
532 OffsetF center = { vectorBlackPointCenterX_[i], centerY_ };
533 if (isHoverPoint(hoverPoint_, center, center, itemHalfSizes)) {
534 hoverIndex_ = i;
535 break;
536 }
537 }
538 auto longPointCenterX = dotIndicatorModifier_->GetLongPointCenterX();
539
540 OffsetF leftCenter = { longPointCenterX.first, centerY_ };
541 OffsetF rightCenter = { longPointCenterX.second, centerY_ };
542 longPointIsHover_ = isHoverPoint(hoverPoint_, leftCenter, rightCenter, itemHalfSizes);
543 }
544
isHoverPoint(const PointF & hoverPoint,const OffsetF & leftCenter,const OffsetF & rightCenter,const LinearVector<float> & itemHalfSizes)545 bool DotIndicatorPaintMethod::isHoverPoint(
546 const PointF& hoverPoint, const OffsetF& leftCenter,
547 const OffsetF& rightCenter, const LinearVector<float>& itemHalfSizes)
548 {
549 float tempLeftCenterX = axis_ == Axis::HORIZONTAL ? leftCenter.GetX() : leftCenter.GetY();
550 float tempLeftCenterY = axis_ == Axis::HORIZONTAL ? leftCenter.GetY() : leftCenter.GetX();
551 float tempRightCenterX = axis_ == Axis::HORIZONTAL ? rightCenter.GetX() : rightCenter.GetY();
552 float tempRightCenterY = axis_ == Axis::HORIZONTAL ? rightCenter.GetY() : rightCenter.GetX();
553 float itemHalfWidth = itemHalfSizes[ITEM_HALF_WIDTH];
554 float itemHalfHeight = itemHalfSizes[ITEM_HALF_HEIGHT];
555 if (hoverIndex_ == currentIndex_) {
556 itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
557 itemHalfHeight = itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT];
558 }
559 return hoverPoint.GetX() >= (tempLeftCenterX - itemHalfWidth) && (hoverPoint.GetX() <=
560 (tempRightCenterX + itemHalfWidth)) && (hoverPoint.GetY() >= (tempLeftCenterY - itemHalfHeight)) &&
561 (hoverPoint.GetY() <= (tempRightCenterY + itemHalfHeight));
562 }
563
UpdateBackground(const PaintWrapper * paintWrapper)564 void DotIndicatorPaintMethod::UpdateBackground(const PaintWrapper* paintWrapper)
565 {
566 CHECK_NULL_VOID(dotIndicatorModifier_);
567 CHECK_NULL_VOID(paintWrapper);
568 auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
569 CHECK_NULL_VOID(paintProperty);
570 auto indicatorTheme = GetSwiperIndicatorTheme();
571 CHECK_NULL_VOID(indicatorTheme);
572
573 // diameter calculation
574 auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
575 auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
576 auto selectedItemWidth =
577 static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
578 auto selectedItemHeight =
579 static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
580 // use radius calculation
581 LinearVector<float> itemHalfSizes;
582 float indicatorScale = indicatorTheme->GetIndicatorScale();
583 itemHalfSizes.emplace_back(itemWidth * HALF * indicatorScale);
584 itemHalfSizes.emplace_back(itemHeight * HALF * indicatorScale);
585 itemHalfSizes.emplace_back(selectedItemWidth * HALF * indicatorScale);
586 itemHalfSizes.emplace_back(selectedItemHeight * HALF * indicatorScale);
587 if (touchBottomType_ != TouchBottomType::NONE) {
588 Dimension indicatorDotItemSpace = paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
589 float allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ + 1);
590 if (IsCustomSizeValue_) {
591 allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ - 1) + selectedItemWidth;
592 }
593 float allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (itemCount_ - 1);
594 Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
595 float padding = static_cast<float>(paddingSide.ConvertToPx());
596 float rectWidth = padding + allPointDiameterSum + allPointSpaceSum + padding;
597 float newRectWidth =
598 rectWidth * (TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE - TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE * itemCount_);
599 auto changeValue = (newRectWidth - rectWidth) * touchBottomRate_;
600
601 float space = static_cast<float>(indicatorDotItemSpace.ConvertToPx());
602 if (itemCount_ > 1) {
603 space = (rectWidth + changeValue - padding * 2 - allPointDiameterSum) / (itemCount_ - 1);
604 }
605 longPointCenterX_ = CalculatePointCenterX(itemHalfSizes, 0, padding, space, currentIndex_);
606 if (touchBottomType_ == TouchBottomType::START) {
607 for (size_t index = 0; index < vectorBlackPointCenterX_.size(); index++) {
608 vectorBlackPointCenterX_[index] = vectorBlackPointCenterX_[index] - changeValue;
609 }
610 longPointCenterX_.first = longPointCenterX_.first - changeValue;
611 longPointCenterX_.second = longPointCenterX_.second - changeValue;
612 }
613 }
614 dotIndicatorModifier_->UpdateTouchBottomAnimation(
615 touchBottomType_, vectorBlackPointCenterX_, longPointCenterX_, touchBottomRate_);
616 }
617
GetIndexOnRTL(int32_t index)618 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetIndexOnRTL(int32_t index)
619 {
620 auto actualTurnPageRate = turnPageRate_;
621 if (!isAutoLinear_ && isSwipeByGroup_ && !NearZero(groupTurnPageRate_)) {
622 actualTurnPageRate = groupTurnPageRate_;
623 }
624
625 int32_t startCurrentIndex = index;
626 auto isInvalid = NearEqual(actualTurnPageRate, 0.0f) || LessOrEqualCustomPrecision(actualTurnPageRate, -1.0f) ||
627 GreatOrEqualCustomPrecision(actualTurnPageRate, 1.0f);
628 if (!isInvalid) {
629 startCurrentIndex = LessNotEqualCustomPrecision(actualTurnPageRate, 0.0f) ? index - 1 : index + 1;
630 }
631
632 if (startCurrentIndex <= -1) {
633 if (isLoop_) {
634 startCurrentIndex = itemCount_ - 1;
635 } else {
636 startCurrentIndex = 0;
637 if (index <= -1) {
638 index = 0;
639 }
640 }
641 }
642
643 return { startCurrentIndex, index };
644 }
645
GetIndex(int32_t index)646 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetIndex(int32_t index)
647 {
648 if (mouseClickIndex_ || gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
649 gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
650 turnPageRate_ = 0;
651 groupTurnPageRate_ = 0;
652 }
653
654 if (isHorizontalAndRightToLeft_ && !isPressed_) {
655 return GetIndexOnRTL(index);
656 }
657
658 auto actualTurnPageRate = turnPageRate_;
659 if (!isAutoLinear_ && isSwipeByGroup_ && groupTurnPageRate_ != 0) {
660 actualTurnPageRate = groupTurnPageRate_;
661 }
662
663 // item may be invalid in auto linear scene
664 if (nextValidIndex_ >= 0) {
665 int32_t startCurrentIndex = index;
666 int32_t endCurrentIndex = NearEqual(turnPageRate_, 0.0f) || LessOrEqualCustomPrecision(turnPageRate_, -1.0f) ||
667 GreatOrEqualCustomPrecision(turnPageRate_, 1.0f)
668 ? index
669 : nextValidIndex_;
670 // reach edge scene
671 if (startCurrentIndex > endCurrentIndex) {
672 startCurrentIndex = currentIndexActual_;
673 endCurrentIndex = currentIndexActual_;
674 }
675 return { startCurrentIndex, endCurrentIndex };
676 }
677
678 int32_t startCurrentIndex = index;
679 int32_t endCurrentIndex = NearEqual(actualTurnPageRate, 0.0f) ||
680 LessOrEqualCustomPrecision(actualTurnPageRate, -1.0f) || GreatOrEqualCustomPrecision(actualTurnPageRate, 1.0f)
681 ? endCurrentIndex = index
682 : (LessNotEqualCustomPrecision(actualTurnPageRate, 0.0f) ? index + 1 : index - 1);
683 if (endCurrentIndex == -1) {
684 endCurrentIndex = itemCount_ - 1;
685 } else if (endCurrentIndex >= itemCount_) {
686 if (isLoop_) {
687 endCurrentIndex = 0;
688 } else {
689 if (startCurrentIndex >= itemCount_) {
690 startCurrentIndex = itemCount_ - 1;
691 }
692 endCurrentIndex = itemCount_ - 1;
693 }
694 }
695
696 return { startCurrentIndex, endCurrentIndex };
697 }
698
GetStartAndEndIndex(int32_t index)699 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetStartAndEndIndex(int32_t index)
700 {
701 auto [startCurrentIndex, endCurrentIndex] = GetIndex(index);
702
703 if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
704 gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
705 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
706 endCurrentIndex = startCurrentIndex;
707 return { startCurrentIndex, endCurrentIndex };
708 } else if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
709 gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
710 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
711 endCurrentIndex = startCurrentIndex = 0;
712 return { startCurrentIndex, endCurrentIndex };
713 }
714
715 auto actualTurnPageRate = !isAutoLinear_ && isSwipeByGroup_ ? groupTurnPageRate_ : turnPageRate_;
716 if (touchBottomTypeLoop_ != TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE && Negative(actualTurnPageRate)) {
717 if (std::abs(actualTurnPageRate) >= FIFTY_PERCENT) {
718 return { endCurrentIndex, endCurrentIndex };
719 }
720
721 return { startCurrentIndex, startCurrentIndex };
722 }
723
724 return { startCurrentIndex, endCurrentIndex };
725 }
726
AdjustPointCenterXForTouchBottomNew(StarAndEndPointCenter & pointCenter,LinearVector<float> & endVectorBlackPointCenterX,int32_t endCurrentIndex,float selectedItemWidth)727 bool DotIndicatorPaintMethod::AdjustPointCenterXForTouchBottomNew(StarAndEndPointCenter& pointCenter,
728 LinearVector<float>& endVectorBlackPointCenterX, int32_t endCurrentIndex, float selectedItemWidth)
729 {
730 auto pageRate = std::abs(touchBottomPageRate_);
731 bool releaseLeftBottom = (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
732 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT);
733 bool releaseRightBottom = (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
734 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT);
735 if ((releaseLeftBottom && (!NearZero(touchBottomPageRate_) && pageRate <= FIFTY_PERCENT)) ||
736 (releaseRightBottom && (pageRate >= FIFTY_PERCENT || NearZero(pageRate)))) {
737 return true;
738 }
739
740 bool dragLeftBottom = (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT &&
741 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT);
742 bool dragRightBottom = (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT &&
743 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT);
744 if (dragLeftBottom && (!NearZero(touchBottomPageRate_) && pageRate <= FIFTY_PERCENT)) {
745 pointCenter.startLongPointLeftCenterX = pointCenter.startLongPointRightCenterX =
746 endVectorBlackPointCenterX[endCurrentIndex];
747 pointCenter.endLongPointLeftCenterX =
748 endVectorBlackPointCenterX[endCurrentIndex] - selectedItemWidth / HALF_SELECTED_WIDTH;
749 pointCenter.endLongPointRightCenterX =
750 endVectorBlackPointCenterX[endCurrentIndex] + selectedItemWidth / HALF_SELECTED_WIDTH;
751 return true;
752 }
753
754 if (dragRightBottom && pageRate >= FIFTY_PERCENT) {
755 pointCenter.startLongPointLeftCenterX = pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[0];
756 pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0] - selectedItemWidth / HALF_SELECTED_WIDTH;
757 pointCenter.endLongPointRightCenterX = endVectorBlackPointCenterX[0] + selectedItemWidth / HALF_SELECTED_WIDTH;
758 return true;
759 }
760
761 return false;
762 }
763
AdjustPointCenterXForTouchBottom(StarAndEndPointCenter & pointCenter,LinearVector<float> & endVectorBlackPointCenterX,int32_t startCurrentIndex,int32_t endCurrentIndex,float selectedItemWidth,int32_t index)764 void DotIndicatorPaintMethod::AdjustPointCenterXForTouchBottom(StarAndEndPointCenter& pointCenter,
765 LinearVector<float>& endVectorBlackPointCenterX, int32_t startCurrentIndex, int32_t endCurrentIndex,
766 float selectedItemWidth, int32_t index)
767 {
768 if (!isAutoLinear_ && isSwipeByGroup_ && !isLoop_) {
769 return;
770 }
771
772 if (AdjustPointCenterXForTouchBottomNew(
773 pointCenter, endVectorBlackPointCenterX, endCurrentIndex, selectedItemWidth)) {
774 return;
775 }
776
777 auto [startIndex, endIndex] = GetIndex(index);
778 if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT &&
779 pointAnimationStage_ != PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
780 (!(endIndex == startIndex && startIndex != 0) ||
781 (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT ||
782 gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT))) {
783 pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0];
784 } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT &&
785 pointAnimationStage_ != PointAnimationStage::STATE_EXPAND_TO_LONG_POINT) {
786 pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX =
787 endVectorBlackPointCenterX[startCurrentIndex];
788 }
789
790 if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
791 gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
792 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
793 pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[endCurrentIndex];
794 pointCenter.endLongPointLeftCenterX =
795 endVectorBlackPointCenterX[endCurrentIndex] - (selectedItemWidth / HALF_SELECTED_WIDTH);
796 } else if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
797 gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
798 touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
799 pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[0];
800 pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0] - (selectedItemWidth / HALF_SELECTED_WIDTH);
801 }
802 }
803
ForwardCalculation(const LinearVector<float> & itemHalfSizes,float startCenterX,float endCenterX,float space,int32_t index)804 std::pair<float, float> DotIndicatorPaintMethod::ForwardCalculation(
805 const LinearVector<float>& itemHalfSizes, float startCenterX, float endCenterX, float space, int32_t index)
806 {
807 auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
808 auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
809 auto itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
810 if (IsCustomSizeValue_) {
811 selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
812 itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * HALF_FLOAT;
813 }
814 StarAndEndPointCenter pointCenter;
815 // Calculate the data required for the current pages
816 LinearVector<float> startVectorBlackPointCenterX(itemCount_);
817 // Calculate the data required for subsequent pages
818 LinearVector<float> endVectorBlackPointCenterX(itemCount_);
819
820 auto [startCurrentIndex, endCurrentIndex] = GetStartAndEndIndex(index);
821 startCurrentIndex = std::clamp(startCurrentIndex, 0, itemCount_ - 1);
822 endCurrentIndex = std::clamp(endCurrentIndex, 0, itemCount_ - 1);
823 for (int32_t i = 0; i < itemCount_; ++i) {
824 if (i != startCurrentIndex) {
825 startVectorBlackPointCenterX[i] = startCenterX + itemHalfSizes[ITEM_HALF_WIDTH];
826 startCenterX += itemWidth;
827 } else {
828 startVectorBlackPointCenterX[i] = startCenterX + selectedItemWidth;
829 pointCenter.startLongPointLeftCenterX = startCenterX + itemHalfWidth;
830 pointCenter.startLongPointRightCenterX = pointCenter.startLongPointLeftCenterX + selectedItemWidth;
831 startCenterX += selectedItemWidth * TWOFOLD;
832 }
833 if (i != endCurrentIndex) {
834 endVectorBlackPointCenterX[i] = endCenterX + itemHalfSizes[ITEM_HALF_WIDTH];
835 endCenterX += itemWidth;
836 } else {
837 endVectorBlackPointCenterX[i] = endCenterX + selectedItemWidth;
838 pointCenter.endLongPointLeftCenterX = endCenterX + itemHalfWidth;
839 pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX + selectedItemWidth;
840 endCenterX += selectedItemWidth * TWOFOLD;
841 }
842 startCenterX += space;
843 endCenterX += space;
844 }
845 AdjustPointCenterXForTouchBottom(
846 pointCenter, endVectorBlackPointCenterX, startCurrentIndex, endCurrentIndex, selectedItemWidth, index);
847 return CalculatePointCenterX(pointCenter, startVectorBlackPointCenterX, endVectorBlackPointCenterX);
848 }
849
BackwardCalculation(const LinearVector<float> & itemHalfSizes,float startCenterX,float endCenterX,float space,int32_t index)850 std::pair<float, float> DotIndicatorPaintMethod::BackwardCalculation(
851 const LinearVector<float>& itemHalfSizes, float startCenterX, float endCenterX, float space, int32_t index)
852 {
853 int32_t startCurrentIndex = index;
854 auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
855 auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
856 auto itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
857 if (IsCustomSizeValue_) {
858 selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
859 itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * HALF_FLOAT;
860 }
861 StarAndEndPointCenter pointCenter;
862 // Calculate the data required for the current pages
863 LinearVector<float> startVectorBlackPointCenterX(itemCount_);
864 // Calculate the data required for subsequent pages
865 LinearVector<float> endVectorBlackPointCenterX(itemCount_);
866 int32_t endCurrentIndex = NearEqual(turnPageRate_, 0.0f) || turnPageRate_ <= -1.0f || turnPageRate_ >= 1.0f
867 ? endCurrentIndex = index : (turnPageRate_ < 0.0f ? index + 1 : index - 1);
868 if (endCurrentIndex == -1) {
869 endCurrentIndex = itemCount_ - 1;
870 } else if (endCurrentIndex == itemCount_) {
871 endCurrentIndex = 0;
872 }
873 for (int32_t i = itemCount_ - 1; i >= 0; --i) {
874 if (i != startCurrentIndex) {
875 startVectorBlackPointCenterX[i] = startCenterX - itemHalfSizes[ITEM_HALF_WIDTH];
876 startCenterX -= itemWidth;
877 } else {
878 startVectorBlackPointCenterX[i] = startCenterX - itemHalfWidth;
879 pointCenter.startLongPointRightCenterX = startCenterX - itemHalfWidth;
880 pointCenter.startLongPointLeftCenterX = pointCenter.startLongPointRightCenterX - selectedItemWidth;
881 startCenterX -= selectedItemWidth * TWOFOLD;
882 }
883 if (i != endCurrentIndex) {
884 endVectorBlackPointCenterX[i] = endCenterX - itemHalfSizes[ITEM_HALF_WIDTH];
885 endCenterX -= itemWidth;
886 } else {
887 endVectorBlackPointCenterX[i] = endCenterX - itemHalfWidth;
888 pointCenter.endLongPointRightCenterX = endCenterX - itemHalfWidth;
889 pointCenter.endLongPointLeftCenterX = pointCenter.endLongPointRightCenterX - selectedItemWidth;
890 endCenterX -= selectedItemWidth * TWOFOLD;
891 }
892 startCenterX -= space;
893 endCenterX -= space;
894 }
895 return CalculatePointCenterX(pointCenter, startVectorBlackPointCenterX, endVectorBlackPointCenterX);
896 }
897 } // namespace OHOS::Ace::NG
898