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