• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/log/dump_log.h"
19 #include "base/utils/utils.h"
20 #include "core/components_ng/base/frame_node.h"
21 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
22 #include "core/components_ng/pattern/swiper/swiper_utils.h"
23 #include "core/event/ace_events.h"
24 #include "core/event/mouse_event.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 constexpr float INDICATOR_ZOOM_IN_SCALE = 1.33f;
30 constexpr Dimension INDICATOR_ITEM_SPACE = 8.0_vp;
31 constexpr Dimension INDICATOR_PADDING_DEFAULT = 12.0_vp;
32 constexpr Dimension INDICATOR_PADDING_HOVER = 12.0_vp;
33 constexpr uint32_t INDICATOR_HAS_CHILD = 2;
34 constexpr Dimension INDICATOR_DRAG_MIN_DISTANCE = 4.0_vp;
35 constexpr Dimension INDICATOR_DRAG_MAX_DISTANCE = 18.0_vp;
36 constexpr Dimension INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE = 80.0_vp;
37 constexpr int32_t LONG_PRESS_DELAY = 300;
38 } // namespace
39 
OnAttachToFrameNode()40 void SwiperIndicatorPattern::OnAttachToFrameNode()
41 {
42     auto host = GetHost();
43     CHECK_NULL_VOID(host);
44     host->GetRenderContext()->SetClipToBounds(true);
45 }
46 
OnModifyDone()47 void SwiperIndicatorPattern::OnModifyDone()
48 {
49     Pattern::OnModifyDone();
50     auto host = GetHost();
51     CHECK_NULL_VOID(host);
52 
53     auto swiperNode = GetSwiperNode();
54     CHECK_NULL_VOID(swiperNode);
55     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
56     CHECK_NULL_VOID(swiperPattern);
57     swiperIndicatorType_ = swiperPattern->GetIndicatorType();
58     if (swiperIndicatorType_ == SwiperIndicatorType::DIGIT) {
59         RefPtr<FrameNode> firstTextNode;
60         RefPtr<FrameNode> lastTextNode;
61         auto layoutProperty = host->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
62         CHECK_NULL_VOID(layoutProperty);
63         if (host->GetChildren().size() == INDICATOR_HAS_CHILD) {
64             firstTextNode = DynamicCast<FrameNode>(host->GetFirstChild());
65             lastTextNode = DynamicCast<FrameNode>(host->GetLastChild());
66         } else {
67             host->Clean();
68             firstTextNode = FrameNode::CreateFrameNode(
69                 V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
70             lastTextNode = FrameNode::CreateFrameNode(
71                 V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
72         }
73         UpdateTextContent(layoutProperty, firstTextNode, lastTextNode);
74         host->AddChild(firstTextNode);
75         host->AddChild(lastTextNode);
76     } else {
77         host->Clean();
78     }
79 
80     if (dotIndicatorModifier_) {
81         dotIndicatorModifier_->StopAnimation();
82     }
83 
84     auto swiperEventHub = swiperPattern->GetEventHub<SwiperEventHub>();
85     CHECK_NULL_VOID(swiperEventHub);
86 
87     swiperEventHub->SetIndicatorOnChange(
88         [weak = AceType::WeakClaim(RawPtr(host)), context = AceType::WeakClaim(this)]() {
89             auto indicator = weak.Upgrade();
90             CHECK_NULL_VOID(indicator);
91             auto textContext = context.Upgrade();
92             CHECK_NULL_VOID(textContext);
93             if (textContext->swiperIndicatorType_ == SwiperIndicatorType::DIGIT) {
94                 RefPtr<FrameNode> firstTextNode;
95                 RefPtr<FrameNode> lastTextNode;
96                 auto layoutProperty = indicator->GetLayoutProperty<SwiperIndicatorLayoutProperty>();
97                 firstTextNode = DynamicCast<FrameNode>(indicator->GetFirstChild());
98                 lastTextNode = DynamicCast<FrameNode>(indicator->GetLastChild());
99                 textContext->UpdateTextContent(layoutProperty, firstTextNode, lastTextNode);
100             }
101             indicator->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
102         });
103     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
104     CHECK_NULL_VOID(swiperLayoutProperty);
105     if (swiperLayoutProperty->GetIndicatorTypeValue(SwiperIndicatorType::DOT) == SwiperIndicatorType::DOT) {
106         auto gestureHub = host->GetOrCreateGestureEventHub();
107         CHECK_NULL_VOID(gestureHub);
108         InitClickEvent(gestureHub);
109         InitHoverMouseEvent();
110         InitTouchEvent(gestureHub);
111         InitLongPressEvent(gestureHub);
112     }
113 }
114 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)115 bool SwiperIndicatorPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
116 {
117     CHECK_NULL_RETURN(config.frameSizeChange, false);
118     return true;
119 }
120 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)121 void SwiperIndicatorPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
122 {
123     CHECK_NULL_VOID(!clickEvent_);
124     auto clickTask = [weak = WeakClaim(this)](const GestureEvent& info) {
125         auto pattern = weak.Upgrade();
126         CHECK_NULL_VOID(pattern);
127         pattern->HandleClick(info);
128     };
129     clickEvent_ = MakeRefPtr<ClickEvent>(std::move(clickTask));
130     gestureHub->AddClickEvent(clickEvent_);
131 }
132 
HandleClick(const GestureEvent & info)133 void SwiperIndicatorPattern::HandleClick(const GestureEvent& info)
134 {
135     if (info.GetSourceDevice() == SourceType::MOUSE) {
136         isClicked_ = true;
137         HandleMouseClick(info);
138     } else {
139         HandleTouchClick(info);
140     }
141 }
142 
HandleMouseClick(const GestureEvent &)143 void SwiperIndicatorPattern::HandleMouseClick(const GestureEvent& /* info */)
144 {
145     if (isRepeatClicked_) {
146         return;
147     }
148     GetMouseClickIndex();
149     CHECK_NULL_VOID(mouseClickIndex_);
150     auto swiperNode = GetSwiperNode();
151     CHECK_NULL_VOID(swiperNode);
152     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
153     CHECK_NULL_VOID(swiperPattern);
154 
155     if (swiperPattern->IsSwipeByGroup()) {
156         auto clickPageIndex = SwiperUtils::ComputePageIndex(mouseClickIndex_.value(), swiperPattern->GetDisplayCount());
157         if (clickPageIndex == swiperPattern->GetCurrentIndex()) {
158             mouseClickIndex_ = std::nullopt;
159             return;
160         }
161 
162         mouseClickIndex_ = clickPageIndex;
163     }
164 
165     swiperPattern->SwipeTo(mouseClickIndex_.value());
166     auto host = GetHost();
167     CHECK_NULL_VOID(host);
168     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
169 }
170 
HandleTouchClick(const GestureEvent & info)171 void SwiperIndicatorPattern::HandleTouchClick(const GestureEvent& info)
172 {
173     auto host = GetHost();
174     CHECK_NULL_VOID(host);
175     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
176     CHECK_NULL_VOID(paintProperty);
177     auto pipeline = PipelineBase::GetCurrentContext();
178     CHECK_NULL_VOID(pipeline);
179     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
180     CHECK_NULL_VOID(theme);
181     auto itemWidth = paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx();
182     auto selectedItemWidth = paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx();
183     if (Negative(itemWidth) || Negative(selectedItemWidth)) {
184         itemWidth = theme->GetSize().ConvertToPx();
185         selectedItemWidth = theme->GetSize().ConvertToPx();
186     }
187     auto swiperNode = GetSwiperNode();
188     CHECK_NULL_VOID(swiperNode);
189     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
190     CHECK_NULL_VOID(swiperPattern);
191 
192     auto currentIndex = swiperPattern->GetCurrentIndex();
193     auto margin = HandleTouchClickMargin();
194     auto lengthBeforeCurrentIndex = margin + INDICATOR_PADDING_DEFAULT.ConvertToPx() +
195                                     (INDICATOR_ITEM_SPACE.ConvertToPx() + itemWidth) * currentIndex;
196     auto lengthWithCurrentIndex = lengthBeforeCurrentIndex + selectedItemWidth;
197     auto axis = swiperPattern->GetDirection();
198     auto mainClickOffset = axis == Axis::HORIZONTAL ? info.GetLocalLocation().GetX() : info.GetLocalLocation().GetY();
199     if (mainClickOffset < lengthBeforeCurrentIndex) {
200         swiperPattern->ShowPrevious();
201     } else if (mainClickOffset > lengthWithCurrentIndex) {
202         swiperPattern->ShowNext();
203     }
204 }
205 
InitHoverMouseEvent()206 void SwiperIndicatorPattern::InitHoverMouseEvent()
207 {
208     auto host = GetHost();
209     CHECK_NULL_VOID(host);
210     auto eventHub = host->GetEventHub<EventHub>();
211     CHECK_NULL_VOID(eventHub);
212     auto inputHub = eventHub->GetOrCreateInputEventHub();
213     CHECK_NULL_VOID(inputHub);
214 
215     auto hoverTask = [weak = WeakClaim(this)](bool isHover, HoverInfo& info) {
216         auto pattern = weak.Upgrade();
217         if (pattern && info.GetSourceDevice() != SourceType::TOUCH) {
218             pattern->HandleHoverEvent(isHover);
219         }
220     };
221 
222     if (!hoverEvent_) {
223         hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
224         inputHub->AddOnHoverEvent(hoverEvent_);
225     }
226 
227     auto mouseEvent = [weak = WeakClaim(this)](MouseInfo& info) {
228         auto pattern = weak.Upgrade();
229         if (pattern) {
230             pattern->HandleMouseEvent(info);
231         }
232     };
233     if (mouseEvent_) {
234         inputHub->RemoveOnMouseEvent(mouseEvent_);
235     }
236     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseEvent));
237     inputHub->AddOnMouseEvent(mouseEvent_);
238 }
239 
HandleMouseEvent(const MouseInfo & info)240 void SwiperIndicatorPattern::HandleMouseEvent(const MouseInfo& info)
241 {
242     if (info.GetSourceDevice() == SourceType::TOUCH) {
243         return;
244     }
245     auto mouseOffsetX = static_cast<float>(info.GetLocalLocation().GetX());
246     auto mouseOffsetY = static_cast<float>(info.GetLocalLocation().GetY());
247     auto mouseAction = info.GetAction();
248     if ((mouseAction == MouseAction::PRESS || mouseAction == MouseAction::RELEASE) &&
249         isClicked_ && NearEqual(hoverPoint_, PointF(mouseOffsetX, mouseOffsetY))) {
250         isRepeatClicked_ = true;
251         return;
252     }
253     isClicked_ = false;
254     isRepeatClicked_ = false;
255     auto host = GetHost();
256     CHECK_NULL_VOID(host);
257     hoverPoint_.SetX(mouseOffsetX);
258     hoverPoint_.SetY(mouseOffsetY);
259 
260     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
261 }
262 
HandleHoverEvent(bool isHover)263 void SwiperIndicatorPattern::HandleHoverEvent(bool isHover)
264 {
265     if (isHover_ == isHover) {
266         return;
267     }
268 
269     isHover_ = isHover;
270     auto host = GetHost();
271     CHECK_NULL_VOID(host);
272     auto swiperNode = GetSwiperNode();
273     CHECK_NULL_VOID(swiperNode);
274     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
275     CHECK_NULL_VOID(swiperPattern);
276     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
277     CHECK_NULL_VOID(swiperLayoutProperty);
278     if (swiperLayoutProperty->GetHoverShowValue(false) && !swiperPattern->GetIsAtHotRegion()) {
279         swiperPattern->ArrowHover(isHover_);
280     }
281     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
282 }
283 
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)284 void SwiperIndicatorPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
285 {
286     if (touchEvent_) {
287         return;
288     }
289 
290     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
291         auto pattern = weak.Upgrade();
292         if (pattern) {
293             pattern->HandleTouchEvent(info);
294         }
295     };
296 
297     if (touchEvent_) {
298         gestureHub->RemoveTouchEvent(touchEvent_);
299     }
300     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
301     gestureHub->AddTouchEvent(touchEvent_);
302 
303     auto swiperNode = GetSwiperNode();
304     CHECK_NULL_VOID(swiperNode);
305     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
306     CHECK_NULL_VOID(swiperPattern);
307     auto stopAnimationCb = [weak = WeakClaim(this)]() {
308         auto pattern = weak.Upgrade();
309         if (pattern) {
310             if (pattern->dotIndicatorModifier_) {
311                 pattern->dotIndicatorModifier_->StopAnimation();
312             }
313         }
314     };
315     swiperPattern->SetStopIndicatorAnimationCb(stopAnimationCb);
316 }
317 
HandleTouchEvent(const TouchEventInfo & info)318 void SwiperIndicatorPattern::HandleTouchEvent(const TouchEventInfo& info)
319 {
320     auto touchType = info.GetTouches().front().GetTouchType();
321     if (touchType == TouchType::UP) {
322         HandleTouchUp();
323         HandleDragEnd(0);
324         isPressed_ = false;
325     } else if (touchType == TouchType::CANCEL) {
326         HandleTouchUp();
327         HandleDragEnd(0);
328         isPressed_ = false;
329     }
330     if (isPressed_) {
331         HandleLongDragUpdate(info.GetTouches().front());
332     }
333 }
334 
HandleTouchDown()335 void SwiperIndicatorPattern::HandleTouchDown()
336 {
337     isPressed_ = true;
338     auto host = GetHost();
339     CHECK_NULL_VOID(host);
340     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
341 }
342 
HandleTouchUp()343 void SwiperIndicatorPattern::HandleTouchUp()
344 {
345     isPressed_ = false;
346     auto host = GetHost();
347     CHECK_NULL_VOID(host);
348     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
349 }
350 
GetMouseClickIndex()351 void SwiperIndicatorPattern::GetMouseClickIndex()
352 {
353     auto pipelineContext = PipelineBase::GetCurrentContext();
354     CHECK_NULL_VOID(pipelineContext);
355     auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
356     CHECK_NULL_VOID(swiperTheme);
357     auto host = GetHost();
358     CHECK_NULL_VOID(host);
359     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
360     CHECK_NULL_VOID(paintProperty);
361     auto swiperNode = GetSwiperNode();
362     CHECK_NULL_VOID(swiperNode);
363     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
364     CHECK_NULL_VOID(swiperPattern);
365     float itemWidthValue = static_cast<float>(paintProperty->GetItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
366     float itemHeightValue = static_cast<float>(paintProperty->GetItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
367     float selectedItemWidthValue =
368         static_cast<float>(paintProperty->GetSelectedItemWidthValue(swiperTheme->GetSize()).ConvertToPx() * 2);
369     if (paintProperty->GetIsCustomSizeValue(false)) {
370         selectedItemWidthValue *= 0.5f;
371     }
372     // diameter calculation
373     float itemWidth = itemWidthValue * INDICATOR_ZOOM_IN_SCALE;
374     float itemHeight = itemHeightValue * INDICATOR_ZOOM_IN_SCALE;
375     float selectedItemWidth = selectedItemWidthValue * INDICATOR_ZOOM_IN_SCALE;
376     float padding = static_cast<float>(INDICATOR_PADDING_HOVER.ConvertToPx());
377     float space = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx());
378     int32_t currentIndex = swiperPattern->GetCurrentShownIndex();
379     int32_t itemCount = swiperPattern->TotalCount();
380     int32_t loopCount = itemCount == 0 ? 0 : std::abs(currentIndex / itemCount);
381     auto frameSize = host->GetGeometryNode()->GetFrameSize();
382     auto axis = swiperPattern->GetDirection();
383     float centerX = padding;
384     float centerY = ((axis == Axis::HORIZONTAL ? frameSize.Height() : frameSize.Width()) - itemHeight) * 0.5f;
385     PointF hoverPoint = axis == Axis::HORIZONTAL ? hoverPoint_ : PointF(hoverPoint_.GetY(), hoverPoint_.GetX());
386     int start = currentIndex >= 0 ? loopCount * itemCount : -(loopCount + 1) * itemCount;
387     int end = currentIndex >= 0 ? (loopCount + 1) * itemCount : -loopCount * itemCount;
388     for (int32_t i = start; i < end; ++i) {
389         if (i != currentIndex) {
390             if (hoverPoint.GetX() >= centerX && hoverPoint.GetX() <= centerX + itemWidth &&
391                 hoverPoint.GetY() >= centerY && hoverPoint.GetY() <= centerY + itemHeight) {
392                 mouseClickIndex_ = i;
393                 break;
394             }
395             centerX += itemWidth + space;
396         } else {
397             centerX += selectedItemWidth + space;
398         }
399     }
400 }
401 
UpdateTextContent(const RefPtr<SwiperIndicatorLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & firstTextNode,const RefPtr<FrameNode> & lastTextNode)402 void SwiperIndicatorPattern::UpdateTextContent(const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
403     const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode)
404 {
405     CHECK_NULL_VOID(layoutProperty);
406     CHECK_NULL_VOID(firstTextNode);
407     CHECK_NULL_VOID(lastTextNode);
408     auto pipeline = PipelineBase::GetCurrentContext();
409     CHECK_NULL_VOID(pipeline);
410     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
411     firstTextNode->SetInternal();
412     lastTextNode->SetInternal();
413     auto firstTextLayoutProperty = firstTextNode->GetLayoutProperty<TextLayoutProperty>();
414     CHECK_NULL_VOID(firstTextLayoutProperty);
415     auto selectedFontColor =
416         layoutProperty->GetSelectedFontColorValue(theme->GetDigitalIndicatorTextStyle().GetTextColor());
417     auto selectedFontSize =
418         layoutProperty->GetSelectedFontSizeValue(theme->GetDigitalIndicatorTextStyle().GetFontSize());
419     if (!selectedFontSize.IsValid()) {
420         selectedFontSize = theme->GetDigitalIndicatorTextStyle().GetFontSize();
421     }
422     auto selectedFontWeight =
423         layoutProperty->GetSelectedFontWeightValue(theme->GetDigitalIndicatorTextStyle().GetFontWeight());
424     firstTextLayoutProperty->UpdateTextColor(selectedFontColor);
425     firstTextLayoutProperty->UpdateFontSize(selectedFontSize);
426     firstTextLayoutProperty->UpdateFontWeight(selectedFontWeight);
427     UpdateTextContentSub(layoutProperty, firstTextNode, lastTextNode);
428 }
429 
UpdateTextContentSub(const RefPtr<SwiperIndicatorLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & firstTextNode,const RefPtr<FrameNode> & lastTextNode)430 void SwiperIndicatorPattern::UpdateTextContentSub(const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
431     const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode)
432 {
433     CHECK_NULL_VOID(layoutProperty);
434     CHECK_NULL_VOID(firstTextNode);
435     CHECK_NULL_VOID(lastTextNode);
436     auto swiperNode = GetSwiperNode();
437     CHECK_NULL_VOID(swiperNode);
438     auto pipeline = PipelineBase::GetCurrentContext();
439     CHECK_NULL_VOID(pipeline);
440     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
441     auto firstTextLayoutProperty = firstTextNode->GetLayoutProperty<TextLayoutProperty>();
442     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
443     CHECK_NULL_VOID(swiperPattern);
444     auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
445     CHECK_NULL_VOID(swiperLayoutProperty);
446     auto currentIndex = swiperPattern->GetCurrentFirstIndex() + 1;
447     if (currentIndex > swiperPattern->TotalCount()) {
448         currentIndex = 1;
449     } else if (swiperLayoutProperty->HasIndex()) {
450         currentIndex = swiperLayoutProperty->GetIndexValue() + 1;
451         if (currentIndex > swiperPattern->TotalCount()) {
452             currentIndex = 1;
453         }
454     }
455     firstTextLayoutProperty->UpdateContent(std::to_string(currentIndex));
456     auto lastTextLayoutProperty = lastTextNode->GetLayoutProperty<TextLayoutProperty>();
457     CHECK_NULL_VOID(lastTextLayoutProperty);
458     auto fontColor = layoutProperty->GetFontColorValue(theme->GetDigitalIndicatorTextStyle().GetTextColor());
459     auto fontSize = layoutProperty->GetFontSizeValue(theme->GetDigitalIndicatorTextStyle().GetFontSize());
460     if (!fontSize.IsValid()) {
461         fontSize = theme->GetDigitalIndicatorTextStyle().GetFontSize();
462     }
463     auto fontWeight = layoutProperty->GetFontWeightValue(theme->GetDigitalIndicatorTextStyle().GetFontWeight());
464     lastTextLayoutProperty->UpdateTextColor(fontColor);
465     lastTextLayoutProperty->UpdateFontSize(fontSize);
466     lastTextLayoutProperty->UpdateFontWeight(fontWeight);
467     lastTextLayoutProperty->UpdateContent("/" + std::to_string(swiperPattern->TotalCount()));
468     firstTextNode->MarkModifyDone();
469     firstTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
470     lastTextNode->MarkModifyDone();
471     lastTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
472 }
473 
HandleDragStart(const GestureEvent & info)474 void SwiperIndicatorPattern::HandleDragStart(const GestureEvent& info)
475 {
476     dragStartPoint_ =
477         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
478 }
479 
HandleDragEnd(double dragVelocity)480 void SwiperIndicatorPattern::HandleDragEnd(double dragVelocity)
481 {
482     auto swiperNode = GetSwiperNode();
483     CHECK_NULL_VOID(swiperNode);
484     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
485     CHECK_NULL_VOID(swiperPattern);
486     swiperPattern->SetTurnPageRate(0.0f);
487     auto swiperPaintProperty = swiperPattern->GetPaintProperty<SwiperPaintProperty>();
488     CHECK_NULL_VOID(swiperPaintProperty);
489     auto autoPlay = swiperPaintProperty->GetAutoPlay().value_or(false);
490     if (autoPlay) {
491         swiperPattern->SetIndicatorLongPress(false);
492         swiperPattern->StartAutoPlay();
493     }
494     auto host = GetHost();
495     CHECK_NULL_VOID(host);
496     touchBottomType_ = TouchBottomType::NONE;
497     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
498 }
499 
CheckIsTouchBottom(const GestureEvent & info)500 bool SwiperIndicatorPattern::CheckIsTouchBottom(const GestureEvent& info)
501 {
502     auto swiperNode = GetSwiperNode();
503     CHECK_NULL_RETURN(swiperNode, false);
504     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
505     CHECK_NULL_RETURN(swiperPattern, false);
506     auto currentIndex = swiperPattern->GetCurrentIndex();
507     auto childrenSize = swiperPattern->TotalCount();
508 
509     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
510     CHECK_NULL_RETURN(swiperLayoutProperty, false);
511     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
512     auto isLoop = swiperLayoutProperty->GetLoop().value_or(true);
513     auto dragPoint =
514         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
515     auto offset = dragPoint - dragStartPoint_;
516     auto touchOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
517     auto touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx())
518                                ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx()
519                                : 1;
520 
521     swiperPattern->SetTurnPageRate(0);
522     swiperPattern->SetTouchBottomRate(std::abs(touchBottomRate));
523     TouchBottomType touchBottomType = TouchBottomType::NONE;
524 
525     if ((currentIndex <= 0) && !isLoop) {
526         if (Negative(info.GetMainDelta()) || NonPositive(touchOffset)) {
527             touchBottomType = TouchBottomType::START;
528         }
529     }
530 
531     if ((currentIndex >= childrenSize - displayCount) && !isLoop) {
532         if (Positive(info.GetMainDelta()) || NonNegative(touchOffset)) {
533             touchBottomType = TouchBottomType::END;
534         }
535     }
536 
537     touchBottomType_ = touchBottomType;
538     auto host = GetHost();
539     CHECK_NULL_RETURN(host, false);
540     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
541 
542     return touchBottomType == TouchBottomType::NONE ? false : true;
543 }
544 
CheckIsTouchBottom(const TouchLocationInfo & info)545 bool SwiperIndicatorPattern::CheckIsTouchBottom(const TouchLocationInfo& info)
546 {
547     auto swiperNode = GetSwiperNode();
548     CHECK_NULL_RETURN(swiperNode, false);
549     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
550     CHECK_NULL_RETURN(swiperPattern, false);
551     auto currentIndex = swiperPattern->GetCurrentIndex();
552     auto childrenSize = swiperPattern->TotalCount();
553 
554     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
555     CHECK_NULL_RETURN(swiperLayoutProperty, false);
556     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
557 
558     auto dragPoint =
559         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
560     auto offset = dragPoint - dragStartPoint_;
561     auto touchOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
562     auto touchBottomRate = LessOrEqual(std::abs(touchOffset), INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx())
563                                ? touchOffset / INDICATOR_TOUCH_BOTTOM_MAX_DISTANCE.ConvertToPx()
564                                : 1;
565 
566     swiperPattern->SetTurnPageRate(0);
567     swiperPattern->SetTouchBottomRate(std::abs(touchBottomRate));
568     TouchBottomType touchBottomType = TouchBottomType::NONE;
569 
570     if (currentIndex <= 0) {
571         if (NonPositive(touchOffset)) {
572             touchBottomType = TouchBottomType::START;
573         }
574     }
575 
576     if (currentIndex >= childrenSize - displayCount) {
577         if (Positive(touchOffset)) {
578             touchBottomType = TouchBottomType::END;
579         }
580     }
581     touchBottomType_ = touchBottomType;
582     auto host = GetHost();
583     CHECK_NULL_RETURN(host, false);
584     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
585 
586     return touchBottomType == TouchBottomType::NONE ? false : true;
587 }
588 
InitLongPressEvent(const RefPtr<GestureEventHub> & gestureHub)589 void SwiperIndicatorPattern::InitLongPressEvent(const RefPtr<GestureEventHub>& gestureHub)
590 {
591     CHECK_NULL_VOID(!longPressEvent_);
592     auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
593         auto pattern = weak.Upgrade();
594         CHECK_NULL_VOID(pattern);
595         pattern->HandleLongPress(info);
596     };
597     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
598 
599     gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
600 }
601 
HandleLongPress(GestureEvent & info)602 void SwiperIndicatorPattern::HandleLongPress(GestureEvent& info)
603 {
604     HandleTouchDown();
605     HandleDragStart(info);
606 
607     auto swiperNode = GetSwiperNode();
608     CHECK_NULL_VOID(swiperNode);
609     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
610     CHECK_NULL_VOID(swiperPattern);
611     auto swiperPaintProperty = swiperPattern->GetPaintProperty<SwiperPaintProperty>();
612     CHECK_NULL_VOID(swiperPaintProperty);
613     auto autoPlay = swiperPaintProperty->GetAutoPlay().value_or(false);
614     if (autoPlay) {
615         swiperPattern->SetIndicatorLongPress(true);
616         swiperPattern->StopTranslateAnimation();
617         swiperPattern->StopSpringAnimation();
618         swiperPattern->StopAutoPlay();
619     }
620 }
621 
HandleLongDragUpdate(const TouchLocationInfo & info)622 void SwiperIndicatorPattern::HandleLongDragUpdate(const TouchLocationInfo& info)
623 {
624     auto swiperNode = GetSwiperNode();
625     CHECK_NULL_VOID(swiperNode);
626     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
627     CHECK_NULL_VOID(swiperPattern);
628     if (swiperPattern->IsIndicatorAnimatorRunning()) {
629         return;
630     }
631     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
632     CHECK_NULL_VOID(swiperLayoutProperty);
633     auto displayCount = swiperLayoutProperty->GetDisplayCount().value_or(1);
634     if (swiperPattern->TotalCount() == displayCount) {
635         return;
636     }
637     if (CheckIsTouchBottom(info)) {
638         return;
639     }
640     auto dragPoint =
641         PointF(static_cast<float>(info.GetLocalLocation().GetX()), static_cast<float>(info.GetLocalLocation().GetY()));
642     auto offset = dragPoint - dragStartPoint_;
643     auto turnPageRateOffset = swiperPattern->GetDirection() == Axis::HORIZONTAL ? offset.GetX() : offset.GetY();
644     if (LessNotEqual(std::abs(turnPageRateOffset), INDICATOR_DRAG_MIN_DISTANCE.ConvertToPx())) {
645         return;
646     }
647 
648     auto turnPageRate = -(turnPageRateOffset / INDICATOR_DRAG_MAX_DISTANCE.ConvertToPx());
649     swiperPattern->SetTurnPageRate(turnPageRate);
650     if (std::abs(turnPageRate) >= 1) {
651         if (Positive(turnPageRateOffset)) {
652             swiperPattern->SwipeToWithoutAnimation(swiperPattern->GetCurrentIndex() + 1);
653         }
654         if (NonPositive(turnPageRateOffset)) {
655             swiperPattern->SwipeToWithoutAnimation(swiperPattern->GetCurrentIndex() - 1);
656         }
657 
658         dragStartPoint_ = dragPoint;
659     }
660 }
661 
HandleTouchClickMargin()662 float SwiperIndicatorPattern::HandleTouchClickMargin()
663 {
664     auto host = GetHost();
665     CHECK_NULL_RETURN(host, 0.0f);
666     auto paintProperty = host->GetPaintProperty<DotIndicatorPaintProperty>();
667     CHECK_NULL_RETURN(paintProperty, 0.0f);
668     auto pipeline = PipelineBase::GetCurrentContext();
669     CHECK_NULL_RETURN(pipeline, 0.0f);
670     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
671     CHECK_NULL_RETURN(theme, 0.0f);
672     auto itemWidth = paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx();
673     auto selectedItemWidth = paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx();
674     if (Negative(itemWidth) || Negative(selectedItemWidth)) {
675         itemWidth = theme->GetSize().ConvertToPx();
676         selectedItemWidth = theme->GetSize().ConvertToPx();
677     }
678     auto swiperNode = GetSwiperNode();
679     CHECK_NULL_RETURN(swiperNode, 0.0f);
680     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
681     int32_t itemCount = swiperPattern->TotalCount();
682     auto allPointDiameterSum = itemWidth * static_cast<float>(itemCount - 1) + selectedItemWidth;
683     auto allPointSpaceSum = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx() * (itemCount - 1));
684     auto indicatorPadding = static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx());
685     auto contentWidth = indicatorPadding + allPointDiameterSum + allPointSpaceSum + indicatorPadding;
686     auto geometryNode = host->GetGeometryNode();
687     CHECK_NULL_RETURN(geometryNode, 0.0f);
688     auto frameSize = geometryNode->GetFrameSize();
689     auto axis = swiperPattern->GetDirection();
690     return ((axis == Axis::HORIZONTAL ? frameSize.Width() : frameSize.Height()) - contentWidth) * 0.5f;
691 }
692 
DumpAdvanceInfo()693 void SwiperIndicatorPattern::DumpAdvanceInfo()
694 {
695     isHover_ ? DumpLog::GetInstance().AddDesc("isHover:true") : DumpLog::GetInstance().AddDesc("isHover:false");
696     isPressed_ ? DumpLog::GetInstance().AddDesc("isPressed:true") : DumpLog::GetInstance().AddDesc("isPressed:false");
697     isClicked_ ? DumpLog::GetInstance().AddDesc("isClicked:true") : DumpLog::GetInstance().AddDesc("isClicked:false");
698     isRepeatClicked_ ? DumpLog::GetInstance().AddDesc("isRepeatClicked:true")
699                      : DumpLog::GetInstance().AddDesc("isRepeatClicked:false");
700     switch (swiperIndicatorType_) {
701         case SwiperIndicatorType::DOT: {
702             DumpLog::GetInstance().AddDesc("SwiperIndicatorType:DOT");
703             break;
704         }
705         case SwiperIndicatorType::DIGIT: {
706             DumpLog::GetInstance().AddDesc("SwiperIndicatorType:DIGIT");
707             break;
708         }
709         default: {
710             break;
711         }
712     }
713 }
714 } // namespace OHOS::Ace::NG
715