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