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