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