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