1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "components/ui_swipe_view.h"
17a3e0fd82Sopenharmony_ci#include "dock/focus_manager.h"
18a3e0fd82Sopenharmony_ci#include "dock/vibrator_manager.h"
19a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h"
20a3e0fd82Sopenharmony_ci
21a3e0fd82Sopenharmony_cinamespace OHOS {
22a3e0fd82Sopenharmony_ciUISwipeView::UISwipeView(uint8_t direction)
23a3e0fd82Sopenharmony_ci    : swipeListener_(nullptr), curIndex_(0), blankSize_(DEFAULT_BLANK_SIZE), curView_(nullptr), loop_(false)
24a3e0fd82Sopenharmony_ci{
25a3e0fd82Sopenharmony_ci#if defined(ENABLE_ROTATE_INPUT) && ENABLE_ROTATE_INPUT
26a3e0fd82Sopenharmony_ci    rotateFactor_ = DEFAULT_SWIPE_VIEW_ROTATE_FACTOR;
27a3e0fd82Sopenharmony_ci#endif
28a3e0fd82Sopenharmony_ci    direction_ = direction;
29a3e0fd82Sopenharmony_ci    tickTime_ = ANIMATOR_TIME;
30a3e0fd82Sopenharmony_ci    swipeAccCoefficient_ = DRAG_ACC_FACTOR;
31a3e0fd82Sopenharmony_ci}
32a3e0fd82Sopenharmony_ci
33a3e0fd82Sopenharmony_ciUISwipeView::~UISwipeView() {}
34a3e0fd82Sopenharmony_ci
35a3e0fd82Sopenharmony_civoid UISwipeView::Add(UIView* view)
36a3e0fd82Sopenharmony_ci{
37a3e0fd82Sopenharmony_ci    if (view == nullptr) {
38a3e0fd82Sopenharmony_ci        return;
39a3e0fd82Sopenharmony_ci    }
40a3e0fd82Sopenharmony_ci    view->SetDragParentInstead(true);
41a3e0fd82Sopenharmony_ci    UIViewGroup::Add(view);
42a3e0fd82Sopenharmony_ci    SortChild();
43a3e0fd82Sopenharmony_ci    Invalidate();
44a3e0fd82Sopenharmony_ci}
45a3e0fd82Sopenharmony_ci
46a3e0fd82Sopenharmony_civoid UISwipeView::Insert(UIView* prevView, UIView* insertView)
47a3e0fd82Sopenharmony_ci{
48a3e0fd82Sopenharmony_ci    if (insertView == nullptr) {
49a3e0fd82Sopenharmony_ci        return;
50a3e0fd82Sopenharmony_ci    }
51a3e0fd82Sopenharmony_ci    insertView->SetDragParentInstead(true);
52a3e0fd82Sopenharmony_ci    UIViewGroup::Insert(prevView, insertView);
53a3e0fd82Sopenharmony_ci    SortChild();
54a3e0fd82Sopenharmony_ci    Invalidate();
55a3e0fd82Sopenharmony_ci}
56a3e0fd82Sopenharmony_ci
57a3e0fd82Sopenharmony_civoid UISwipeView::Remove(UIView* view)
58a3e0fd82Sopenharmony_ci{
59a3e0fd82Sopenharmony_ci    if (view == nullptr) {
60a3e0fd82Sopenharmony_ci        return;
61a3e0fd82Sopenharmony_ci    }
62a3e0fd82Sopenharmony_ci    UIViewGroup::Remove(view);
63a3e0fd82Sopenharmony_ci    if (curView_ == view) {
64a3e0fd82Sopenharmony_ci        curView_ = nullptr;
65a3e0fd82Sopenharmony_ci    }
66a3e0fd82Sopenharmony_ci    SortChild();
67a3e0fd82Sopenharmony_ci    Invalidate();
68a3e0fd82Sopenharmony_ci}
69a3e0fd82Sopenharmony_ci
70a3e0fd82Sopenharmony_civoid UISwipeView::MoveHeadOrTailChild()
71a3e0fd82Sopenharmony_ci{
72a3e0fd82Sopenharmony_ci    if (loop_ && (childrenNum_ != 1)) {
73a3e0fd82Sopenharmony_ci        if (direction_ == HORIZONTAL) {
74a3e0fd82Sopenharmony_ci            while (childrenHead_->GetX() >= 0) {
75a3e0fd82Sopenharmony_ci                MoveLastChildToFirst();
76a3e0fd82Sopenharmony_ci            }
77a3e0fd82Sopenharmony_ci            while (childrenTail_->GetX() + childrenTail_->GetWidth() <= GetWidth()) {
78a3e0fd82Sopenharmony_ci                MoveFirstChildToLast();
79a3e0fd82Sopenharmony_ci            }
80a3e0fd82Sopenharmony_ci        } else {
81a3e0fd82Sopenharmony_ci            while (childrenHead_->GetY() >= 0) {
82a3e0fd82Sopenharmony_ci                MoveLastChildToFirst();
83a3e0fd82Sopenharmony_ci            }
84a3e0fd82Sopenharmony_ci            while (childrenTail_->GetY() + childrenTail_->GetHeight() <= GetHeight()) {
85a3e0fd82Sopenharmony_ci                MoveFirstChildToLast();
86a3e0fd82Sopenharmony_ci            }
87a3e0fd82Sopenharmony_ci        }
88a3e0fd82Sopenharmony_ci    }
89a3e0fd82Sopenharmony_ci}
90a3e0fd82Sopenharmony_ci
91a3e0fd82Sopenharmony_civoid UISwipeView::SetCurrentPage(uint16_t index, bool needAnimator)
92a3e0fd82Sopenharmony_ci{
93a3e0fd82Sopenharmony_ci    if (needAnimator) {
94a3e0fd82Sopenharmony_ci        MoveHeadOrTailChild();
95a3e0fd82Sopenharmony_ci    }
96a3e0fd82Sopenharmony_ci    SwitchToPage(index, needAnimator);
97a3e0fd82Sopenharmony_ci    Invalidate();
98a3e0fd82Sopenharmony_ci}
99a3e0fd82Sopenharmony_ci
100a3e0fd82Sopenharmony_cibool UISwipeView::DragXInner(int16_t distance)
101a3e0fd82Sopenharmony_ci{
102a3e0fd82Sopenharmony_ci    if (distance == 0) {
103a3e0fd82Sopenharmony_ci        return true;
104a3e0fd82Sopenharmony_ci    }
105a3e0fd82Sopenharmony_ci    if (!loop_) {
106a3e0fd82Sopenharmony_ci        if ((distance > 0) && (childrenHead_ != nullptr)) {
107a3e0fd82Sopenharmony_ci            if (childrenHead_->GetX() >= blankSize_) {
108a3e0fd82Sopenharmony_ci                distance = 0;
109a3e0fd82Sopenharmony_ci            } else if (childrenHead_ && (childrenHead_->GetX() + distance > blankSize_)) {
110a3e0fd82Sopenharmony_ci                distance = blankSize_ - childrenHead_->GetX();
111a3e0fd82Sopenharmony_ci            }
112a3e0fd82Sopenharmony_ci        } else if (childrenTail_ != nullptr) {
113a3e0fd82Sopenharmony_ci            int16_t width = GetWidth();
114a3e0fd82Sopenharmony_ci            if (childrenTail_->GetRelativeRect().GetRight() < width - blankSize_) {
115a3e0fd82Sopenharmony_ci                distance = 0;
116a3e0fd82Sopenharmony_ci            } else if (width - (childrenTail_->GetX() + childrenTail_->GetWidth() + distance) > blankSize_) {
117a3e0fd82Sopenharmony_ci                distance = width - blankSize_ - childrenTail_->GetX() - childrenTail_->GetWidth();
118a3e0fd82Sopenharmony_ci            }
119a3e0fd82Sopenharmony_ci        }
120a3e0fd82Sopenharmony_ci    }
121a3e0fd82Sopenharmony_ci    CalculateInvalidate();
122a3e0fd82Sopenharmony_ci    MoveChildByOffset(distance, 0);
123a3e0fd82Sopenharmony_ci    CalculateInvalidate();
124a3e0fd82Sopenharmony_ci    return true;
125a3e0fd82Sopenharmony_ci}
126a3e0fd82Sopenharmony_ci
127a3e0fd82Sopenharmony_cibool UISwipeView::DragYInner(int16_t distance)
128a3e0fd82Sopenharmony_ci{
129a3e0fd82Sopenharmony_ci    if (distance == 0) {
130a3e0fd82Sopenharmony_ci        return true;
131a3e0fd82Sopenharmony_ci    }
132a3e0fd82Sopenharmony_ci    if (!loop_) {
133a3e0fd82Sopenharmony_ci        if ((distance > 0) && (childrenHead_ != nullptr)) {
134a3e0fd82Sopenharmony_ci            if (childrenHead_->GetY() >= blankSize_) {
135a3e0fd82Sopenharmony_ci                distance = 0;
136a3e0fd82Sopenharmony_ci            } else if ((childrenHead_ != nullptr) && (childrenHead_->GetY() + distance > blankSize_)) {
137a3e0fd82Sopenharmony_ci                distance = blankSize_ - childrenHead_->GetY();
138a3e0fd82Sopenharmony_ci            }
139a3e0fd82Sopenharmony_ci        } else if (childrenTail_ != nullptr) {
140a3e0fd82Sopenharmony_ci            int16_t height = GetHeight();
141a3e0fd82Sopenharmony_ci            if (childrenTail_->GetRelativeRect().GetBottom() < height - blankSize_) {
142a3e0fd82Sopenharmony_ci                distance = 0;
143a3e0fd82Sopenharmony_ci            } else if (height - (childrenTail_->GetY() + childrenTail_->GetHeight() + distance) > blankSize_) {
144a3e0fd82Sopenharmony_ci                distance = height - blankSize_ - childrenTail_->GetY() - childrenTail_->GetHeight();
145a3e0fd82Sopenharmony_ci            }
146a3e0fd82Sopenharmony_ci        }
147a3e0fd82Sopenharmony_ci    }
148a3e0fd82Sopenharmony_ci    CalculateInvalidate();
149a3e0fd82Sopenharmony_ci    MoveChildByOffset(0, distance);
150a3e0fd82Sopenharmony_ci    CalculateInvalidate();
151a3e0fd82Sopenharmony_ci    return true;
152a3e0fd82Sopenharmony_ci}
153a3e0fd82Sopenharmony_ci
154a3e0fd82Sopenharmony_cibool UISwipeView::OnDragEvent(const DragEvent& event)
155a3e0fd82Sopenharmony_ci{
156a3e0fd82Sopenharmony_ci    UIView* currentView = GetViewByIndex(curIndex_);
157a3e0fd82Sopenharmony_ci    if (currentView == nullptr) {
158a3e0fd82Sopenharmony_ci        return UIView::OnDragEvent(event);
159a3e0fd82Sopenharmony_ci    }
160a3e0fd82Sopenharmony_ci    if (scrollAnimator_.GetState() != Animator::STOP) {
161a3e0fd82Sopenharmony_ci        StopAnimator();
162a3e0fd82Sopenharmony_ci    }
163a3e0fd82Sopenharmony_ci
164a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
165a3e0fd82Sopenharmony_ci        DragXInner(event.GetDeltaX());
166a3e0fd82Sopenharmony_ci        RefreshDelta(event.GetDeltaX());
167a3e0fd82Sopenharmony_ci        RefreshCurrentViewByPosition(&UIView::GetX, &UIView::GetWidthWithMargin);
168a3e0fd82Sopenharmony_ci    } else {
169a3e0fd82Sopenharmony_ci        DragYInner(event.GetDeltaY());
170a3e0fd82Sopenharmony_ci        RefreshDelta(event.GetDeltaY());
171a3e0fd82Sopenharmony_ci        RefreshCurrentViewByPosition(&UIView::GetY, &UIView::GetHeightWithMargin);
172a3e0fd82Sopenharmony_ci    }
173a3e0fd82Sopenharmony_ci    return UIView::OnDragEvent(event);
174a3e0fd82Sopenharmony_ci}
175a3e0fd82Sopenharmony_ci
176a3e0fd82Sopenharmony_cibool UISwipeView::OnDragEndEvent(const DragEvent& event)
177a3e0fd82Sopenharmony_ci{
178a3e0fd82Sopenharmony_ci    int16_t distance = 0;
179a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
180a3e0fd82Sopenharmony_ci        distance = event.GetCurrentPos().x - event.GetPreLastPoint().x;
181a3e0fd82Sopenharmony_ci        RefreshCurrentViewByThrow(distance, event.GetDragDirection(), &UIView::GetX, &UIView::GetWidthWithMargin);
182a3e0fd82Sopenharmony_ci    } else {
183a3e0fd82Sopenharmony_ci        distance = event.GetCurrentPos().y - event.GetPreLastPoint().y;
184a3e0fd82Sopenharmony_ci        RefreshCurrentViewByThrow(distance, event.GetDragDirection(), &UIView::GetY, &UIView::GetHeightWithMargin);
185a3e0fd82Sopenharmony_ci    }
186a3e0fd82Sopenharmony_ci
187a3e0fd82Sopenharmony_ci    if (curView_ == nullptr) {
188a3e0fd82Sopenharmony_ci        return UIView::OnDragEndEvent(event);
189a3e0fd82Sopenharmony_ci    }
190a3e0fd82Sopenharmony_ci
191a3e0fd82Sopenharmony_ci    SwitchToPage(curIndex_);
192a3e0fd82Sopenharmony_ci
193a3e0fd82Sopenharmony_ci    Invalidate();
194a3e0fd82Sopenharmony_ci    return UIView::OnDragEndEvent(event);
195a3e0fd82Sopenharmony_ci}
196a3e0fd82Sopenharmony_ci
197a3e0fd82Sopenharmony_ci#if defined(ENABLE_ROTATE_INPUT) && ENABLE_ROTATE_INPUT
198a3e0fd82Sopenharmony_ci
199a3e0fd82Sopenharmony_cibool UISwipeView::OnRotateEvent(const RotateEvent& event)
200a3e0fd82Sopenharmony_ci{
201a3e0fd82Sopenharmony_ci    int16_t rotateLen = static_cast<int16_t>(event.GetRotate() * rotateFactor_);
202a3e0fd82Sopenharmony_ci    RefreshRotate(rotateLen);
203a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
204a3e0fd82Sopenharmony_ci        DragXInner(rotateLen);
205a3e0fd82Sopenharmony_ci        RefreshCurrentViewByPosition(&UIView::GetX, &UIView::GetWidthWithMargin);
206a3e0fd82Sopenharmony_ci    } else {
207a3e0fd82Sopenharmony_ci        DragYInner(rotateLen);
208a3e0fd82Sopenharmony_ci        RefreshCurrentViewByPosition(&UIView::GetY, &UIView::GetHeightWithMargin);
209a3e0fd82Sopenharmony_ci    }
210a3e0fd82Sopenharmony_ci
211a3e0fd82Sopenharmony_ci    return UIView::OnRotateEvent(event);
212a3e0fd82Sopenharmony_ci}
213a3e0fd82Sopenharmony_ci
214a3e0fd82Sopenharmony_cibool UISwipeView::OnRotateEndEvent(const RotateEvent& event)
215a3e0fd82Sopenharmony_ci{
216a3e0fd82Sopenharmony_ci    uint8_t dir;
217a3e0fd82Sopenharmony_ci    int16_t lastRotateLen = GetMaxRotate();
218a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
219a3e0fd82Sopenharmony_ci        dir = (lastRotateLen >= 0) ? DragEvent::DIRECTION_LEFT_TO_RIGHT : DragEvent::DIRECTION_RIGHT_TO_LEFT;
220a3e0fd82Sopenharmony_ci    } else {
221a3e0fd82Sopenharmony_ci        dir = (lastRotateLen >= 0) ? DragEvent::DIRECTION_TOP_TO_BOTTOM : DragEvent::DIRECTION_BOTTOM_TO_TOP;
222a3e0fd82Sopenharmony_ci    }
223a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
224a3e0fd82Sopenharmony_ci        RefreshCurrentViewByThrow(lastRotateLen, dir, &UIView::GetX, &UIView::GetWidthWithMargin);
225a3e0fd82Sopenharmony_ci    } else {
226a3e0fd82Sopenharmony_ci        RefreshCurrentViewByThrow(lastRotateLen, dir, &UIView::GetY, &UIView::GetHeightWithMargin);
227a3e0fd82Sopenharmony_ci    }
228a3e0fd82Sopenharmony_ci    if (curView_ == nullptr) {
229a3e0fd82Sopenharmony_ci        return UIView::OnRotateEndEvent(event);
230a3e0fd82Sopenharmony_ci    }
231a3e0fd82Sopenharmony_ci    SwitchToPage(curIndex_);
232a3e0fd82Sopenharmony_ci    isRotating_ = false;
233a3e0fd82Sopenharmony_ci    return UIView::OnRotateEndEvent(event);
234a3e0fd82Sopenharmony_ci}
235a3e0fd82Sopenharmony_ci#endif
236a3e0fd82Sopenharmony_ci
237a3e0fd82Sopenharmony_ciUIView* UISwipeView::GetViewByIndex(uint16_t index) const
238a3e0fd82Sopenharmony_ci{
239a3e0fd82Sopenharmony_ci    UIView* child = childrenHead_;
240a3e0fd82Sopenharmony_ci    while (child != nullptr) {
241a3e0fd82Sopenharmony_ci        if (child->GetViewIndex() == index) {
242a3e0fd82Sopenharmony_ci            return child;
243a3e0fd82Sopenharmony_ci        }
244a3e0fd82Sopenharmony_ci        child = child->GetNextSibling();
245a3e0fd82Sopenharmony_ci    }
246a3e0fd82Sopenharmony_ci    return nullptr;
247a3e0fd82Sopenharmony_ci}
248a3e0fd82Sopenharmony_ci
249a3e0fd82Sopenharmony_civoid UISwipeView::SetAnimatorTime(uint16_t time)
250a3e0fd82Sopenharmony_ci{
251a3e0fd82Sopenharmony_ci    tickTime_ = time / DEFAULT_TASK_PERIOD;
252a3e0fd82Sopenharmony_ci    if (tickTime_ == 0) {
253a3e0fd82Sopenharmony_ci        tickTime_ = 1;
254a3e0fd82Sopenharmony_ci    }
255a3e0fd82Sopenharmony_ci    animatorCallback_.SetDragTimes(tickTime_);
256a3e0fd82Sopenharmony_ci}
257a3e0fd82Sopenharmony_ci
258a3e0fd82Sopenharmony_civoid UISwipeView::SwitchToPage(int16_t dst, bool needAnimator)
259a3e0fd82Sopenharmony_ci{
260a3e0fd82Sopenharmony_ci    if (IsNeedLoop()) {
261a3e0fd82Sopenharmony_ci        dst = (dst + childrenNum_) % childrenNum_;
262a3e0fd82Sopenharmony_ci    } else if (dst < 0) {
263a3e0fd82Sopenharmony_ci        dst = 0;
264a3e0fd82Sopenharmony_ci    } else if (dst >= childrenNum_) {
265a3e0fd82Sopenharmony_ci        dst = childrenNum_ - 1;
266a3e0fd82Sopenharmony_ci    }
267a3e0fd82Sopenharmony_ci
268a3e0fd82Sopenharmony_ci    UIView* dstView = GetViewByIndex(dst);
269a3e0fd82Sopenharmony_ci    if (dstView == nullptr) {
270a3e0fd82Sopenharmony_ci        return;
271a3e0fd82Sopenharmony_ci    }
272a3e0fd82Sopenharmony_ci    curIndex_ = dst;
273a3e0fd82Sopenharmony_ci    curView_ = dstView;
274a3e0fd82Sopenharmony_ci    int16_t xOffset = 0;
275a3e0fd82Sopenharmony_ci    int16_t yOffset = 0;
276a3e0fd82Sopenharmony_ci
277a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
278a3e0fd82Sopenharmony_ci        if (alignMode_ == ALIGN_LEFT) {
279a3e0fd82Sopenharmony_ci            xOffset = -dstView->GetX();
280a3e0fd82Sopenharmony_ci        } else if (alignMode_ == ALIGN_RIGHT) {
281a3e0fd82Sopenharmony_ci            xOffset = GetWidth() - (dstView->GetX() + dstView->GetWidthWithMargin());
282a3e0fd82Sopenharmony_ci        } else {
283a3e0fd82Sopenharmony_ci            xOffset = (GetWidth() >> 1) - (dstView->GetX() + (dstView->GetWidthWithMargin() >> 1));
284a3e0fd82Sopenharmony_ci        }
285a3e0fd82Sopenharmony_ci    } else {
286a3e0fd82Sopenharmony_ci        yOffset = (GetHeight() >> 1) - (dstView->GetY() + (dstView->GetHeightWithMargin() >> 1));
287a3e0fd82Sopenharmony_ci    }
288a3e0fd82Sopenharmony_ci
289a3e0fd82Sopenharmony_ci    if ((xOffset != 0) || (yOffset != 0)) {
290a3e0fd82Sopenharmony_ci        if (scrollAnimator_.GetState() != Animator::STOP) {
291a3e0fd82Sopenharmony_ci            scrollAnimator_.Stop();
292a3e0fd82Sopenharmony_ci        }
293a3e0fd82Sopenharmony_ci        if (needAnimator) {
294a3e0fd82Sopenharmony_ci            animatorCallback_.SetDragTimes(tickTime_);
295a3e0fd82Sopenharmony_ci            animatorCallback_.SetDragStartValue(0, 0);
296a3e0fd82Sopenharmony_ci            animatorCallback_.SetDragEndValue(xOffset, yOffset);
297a3e0fd82Sopenharmony_ci            scrollAnimator_.Start();
298a3e0fd82Sopenharmony_ci        } else {
299a3e0fd82Sopenharmony_ci            MoveChildByOffset(xOffset, yOffset);
300a3e0fd82Sopenharmony_ci        }
301a3e0fd82Sopenharmony_ci    }
302a3e0fd82Sopenharmony_ci}
303a3e0fd82Sopenharmony_ci
304a3e0fd82Sopenharmony_civoid UISwipeView::StopAnimator()
305a3e0fd82Sopenharmony_ci{
306a3e0fd82Sopenharmony_ci    UIAbstractScroll::StopAnimator();
307a3e0fd82Sopenharmony_ci    if (swipeListener_ != nullptr) {
308a3e0fd82Sopenharmony_ci        swipeListener_->OnSwipe(*this);
309a3e0fd82Sopenharmony_ci    }
310a3e0fd82Sopenharmony_ci}
311a3e0fd82Sopenharmony_ci
312a3e0fd82Sopenharmony_civoid UISwipeView::SortChild()
313a3e0fd82Sopenharmony_ci{
314a3e0fd82Sopenharmony_ci    if (childrenHead_ == nullptr) {
315a3e0fd82Sopenharmony_ci        return;
316a3e0fd82Sopenharmony_ci    }
317a3e0fd82Sopenharmony_ci    int16_t index = 0;
318a3e0fd82Sopenharmony_ci    UIView* pre = childrenHead_;
319a3e0fd82Sopenharmony_ci    UIView* next = childrenHead_->GetNextSibling();
320a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
321a3e0fd82Sopenharmony_ci        pre->SetX(0);
322a3e0fd82Sopenharmony_ci    } else {
323a3e0fd82Sopenharmony_ci        pre->SetY(0);
324a3e0fd82Sopenharmony_ci    }
325a3e0fd82Sopenharmony_ci    pre->SetViewIndex(index);
326a3e0fd82Sopenharmony_ci    index++;
327a3e0fd82Sopenharmony_ci
328a3e0fd82Sopenharmony_ci    while (next != nullptr) {
329a3e0fd82Sopenharmony_ci        if (direction_ == HORIZONTAL) {
330a3e0fd82Sopenharmony_ci            next->SetX(pre->GetRelativeRect().GetRight() + pre->GetStyle(STYLE_MARGIN_RIGHT) + 1);
331a3e0fd82Sopenharmony_ci        } else {
332a3e0fd82Sopenharmony_ci            next->SetY(pre->GetRelativeRect().GetBottom() + pre->GetStyle(STYLE_MARGIN_BOTTOM) + 1);
333a3e0fd82Sopenharmony_ci        }
334a3e0fd82Sopenharmony_ci        pre = next;
335a3e0fd82Sopenharmony_ci        next->SetViewIndex(index);
336a3e0fd82Sopenharmony_ci        next = next->GetNextSibling();
337a3e0fd82Sopenharmony_ci        index++;
338a3e0fd82Sopenharmony_ci    }
339a3e0fd82Sopenharmony_ci    bool tmpLoop = loop_;
340a3e0fd82Sopenharmony_ci    loop_ = false;
341a3e0fd82Sopenharmony_ci    SwitchToPage(curIndex_, false);
342a3e0fd82Sopenharmony_ci    loop_ = tmpLoop;
343a3e0fd82Sopenharmony_ci}
344a3e0fd82Sopenharmony_ci
345a3e0fd82Sopenharmony_civoid UISwipeView::RefreshCurrentViewByPosition(int16_t (UIView::*pfnGetXOrY)() const,
346a3e0fd82Sopenharmony_ci                                               int16_t (UIView::*pfnGetWidthOrHeight)())
347a3e0fd82Sopenharmony_ci{
348a3e0fd82Sopenharmony_ci    if (childrenHead_ == nullptr) {
349a3e0fd82Sopenharmony_ci        curIndex_ = 0;
350a3e0fd82Sopenharmony_ci        curView_ = nullptr;
351a3e0fd82Sopenharmony_ci        return;
352a3e0fd82Sopenharmony_ci    }
353a3e0fd82Sopenharmony_ci
354a3e0fd82Sopenharmony_ci#if defined(ENABLE_VIBRATOR) && ENABLE_VIBRATOR
355a3e0fd82Sopenharmony_ci    uint16_t lastIndex = curIndex_;
356a3e0fd82Sopenharmony_ci#endif
357a3e0fd82Sopenharmony_ci    curIndex_ = 0;
358a3e0fd82Sopenharmony_ci    curView_ = nullptr;
359a3e0fd82Sopenharmony_ci
360a3e0fd82Sopenharmony_ci    /*
361a3e0fd82Sopenharmony_ci     * It needs to be modified that swipemid should be calculated by the width and height of the current
362a3e0fd82Sopenharmony_ci     * sub view itself, not the width and height of the parent, especially for ALIGN_LEFT and ALIGN_RIGHT.
363a3e0fd82Sopenharmony_ci     */
364a3e0fd82Sopenharmony_ci    uint16_t swipeMid;
365a3e0fd82Sopenharmony_ci    if (alignMode_ == ALIGN_LEFT) {
366a3e0fd82Sopenharmony_ci        swipeMid = 0;
367a3e0fd82Sopenharmony_ci    } else if (alignMode_ == ALIGN_RIGHT) {
368a3e0fd82Sopenharmony_ci        swipeMid = (this->*pfnGetWidthOrHeight)();
369a3e0fd82Sopenharmony_ci    } else {
370a3e0fd82Sopenharmony_ci        swipeMid = (this->*pfnGetWidthOrHeight)() >> 1;
371a3e0fd82Sopenharmony_ci    }
372a3e0fd82Sopenharmony_ci    UIView* view = childrenHead_;
373a3e0fd82Sopenharmony_ci
374a3e0fd82Sopenharmony_ci    if ((childrenHead_->*pfnGetXOrY)() > swipeMid) {
375a3e0fd82Sopenharmony_ci        curIndex_ = childrenHead_->GetViewIndex();
376a3e0fd82Sopenharmony_ci        curView_ = childrenHead_;
377a3e0fd82Sopenharmony_ci    } else if ((childrenTail_->*pfnGetXOrY)() + (childrenHead_->*pfnGetWidthOrHeight)() < swipeMid) {
378a3e0fd82Sopenharmony_ci        curIndex_ = childrenTail_->GetViewIndex();
379a3e0fd82Sopenharmony_ci        curView_ = childrenTail_;
380a3e0fd82Sopenharmony_ci    } else {
381a3e0fd82Sopenharmony_ci        while (view != nullptr) {
382a3e0fd82Sopenharmony_ci            if ((swipeMid >= (view->*pfnGetXOrY)()) &&
383a3e0fd82Sopenharmony_ci                (swipeMid <= (view->*pfnGetXOrY)() + (view->*pfnGetWidthOrHeight)())) {
384a3e0fd82Sopenharmony_ci                curIndex_ = view->GetViewIndex();
385a3e0fd82Sopenharmony_ci                curView_ = view;
386a3e0fd82Sopenharmony_ci                break;
387a3e0fd82Sopenharmony_ci            }
388a3e0fd82Sopenharmony_ci            view = view->GetNextSibling();
389a3e0fd82Sopenharmony_ci        }
390a3e0fd82Sopenharmony_ci    }
391a3e0fd82Sopenharmony_ci#if defined(ENABLE_VIBRATOR) && ENABLE_VIBRATOR
392a3e0fd82Sopenharmony_ci    if (lastIndex != curIndex_) {
393a3e0fd82Sopenharmony_ci        Vibrator();
394a3e0fd82Sopenharmony_ci    }
395a3e0fd82Sopenharmony_ci#endif
396a3e0fd82Sopenharmony_ci}
397a3e0fd82Sopenharmony_ci
398a3e0fd82Sopenharmony_civoid UISwipeView::RefreshCurrentViewByThrow(int16_t distance,
399a3e0fd82Sopenharmony_ci                                            uint8_t dragDirection,
400a3e0fd82Sopenharmony_ci                                            int16_t (UIView::*pfnGetXOrY)() const,
401a3e0fd82Sopenharmony_ci                                            int16_t (UIView::*pfnGetWidthOrHeight)())
402a3e0fd82Sopenharmony_ci{
403a3e0fd82Sopenharmony_ci    if (curView_ == nullptr) {
404a3e0fd82Sopenharmony_ci        return;
405a3e0fd82Sopenharmony_ci    }
406a3e0fd82Sopenharmony_ci#if defined(ENABLE_VIBRATOR) && ENABLE_VIBRATOR
407a3e0fd82Sopenharmony_ci    uint16_t lastIndex = curIndex_;
408a3e0fd82Sopenharmony_ci#endif
409a3e0fd82Sopenharmony_ci
410a3e0fd82Sopenharmony_ci    /*
411a3e0fd82Sopenharmony_ci     * It needs to be modified that swipemid should be calculated by the width and height of the current
412a3e0fd82Sopenharmony_ci     * sub view itself, not the width and height of the parent, especially for ALIGN_LEFT and ALIGN_RIGHT.
413a3e0fd82Sopenharmony_ci     */
414a3e0fd82Sopenharmony_ci    uint16_t swipeMid;
415a3e0fd82Sopenharmony_ci    if (alignMode_ == ALIGN_LEFT) {
416a3e0fd82Sopenharmony_ci        swipeMid = 0;
417a3e0fd82Sopenharmony_ci    } else if (alignMode_ == ALIGN_RIGHT) {
418a3e0fd82Sopenharmony_ci        swipeMid = (this->*pfnGetWidthOrHeight)();
419a3e0fd82Sopenharmony_ci    } else {
420a3e0fd82Sopenharmony_ci        swipeMid = (this->*pfnGetWidthOrHeight)() >> 1;
421a3e0fd82Sopenharmony_ci    }
422a3e0fd82Sopenharmony_ci
423a3e0fd82Sopenharmony_ci    int16_t accelerationOffset = GetMaxDelta() * GetSwipeACCLevel() / DRAG_ACC_FACTOR;
424a3e0fd82Sopenharmony_ci    if (distance < 0) {
425a3e0fd82Sopenharmony_ci        /*
426a3e0fd82Sopenharmony_ci         * 7, 10 : Check whether the current view is dragged by more than 1/5,
427a3e0fd82Sopenharmony_ci         * that is, the x or y coordinate plus 7/10 width or height.
428a3e0fd82Sopenharmony_ci         */
429a3e0fd82Sopenharmony_ci        if (((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) < swipeMid) &&
430a3e0fd82Sopenharmony_ci            ((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() * 7 / 10) - accelerationOffset <
431a3e0fd82Sopenharmony_ci             swipeMid)) {
432a3e0fd82Sopenharmony_ci            CurrentIndexInc();
433a3e0fd82Sopenharmony_ci        }
434a3e0fd82Sopenharmony_ci    } else if (distance > 0) {
435a3e0fd82Sopenharmony_ci        /*
436a3e0fd82Sopenharmony_ci         * 3, 10 : Check whether the current view is dragged by more than 1/5,
437a3e0fd82Sopenharmony_ci         * that is, the x or y coordinate plus 3/10 width or height.
438a3e0fd82Sopenharmony_ci         */
439a3e0fd82Sopenharmony_ci        if (((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) > swipeMid) &&
440a3e0fd82Sopenharmony_ci            ((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() * 3 / 10) + accelerationOffset >
441a3e0fd82Sopenharmony_ci             swipeMid)) {
442a3e0fd82Sopenharmony_ci            CurrentIndexDec();
443a3e0fd82Sopenharmony_ci        }
444a3e0fd82Sopenharmony_ci    } else {
445a3e0fd82Sopenharmony_ci        if (alignMode_ == ALIGN_LEFT) {
446a3e0fd82Sopenharmony_ci            if (((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) < swipeMid)) {
447a3e0fd82Sopenharmony_ci                CurrentIndexInc();
448a3e0fd82Sopenharmony_ci            }
449a3e0fd82Sopenharmony_ci        } else if (alignMode_ == ALIGN_RIGHT) {
450a3e0fd82Sopenharmony_ci            if ((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) > swipeMid) {
451a3e0fd82Sopenharmony_ci                CurrentIndexDec();
452a3e0fd82Sopenharmony_ci            }
453a3e0fd82Sopenharmony_ci        } else {
454a3e0fd82Sopenharmony_ci            /*
455a3e0fd82Sopenharmony_ci             * If the absolute value of the offset is greater than the page turning threshold,
456a3e0fd82Sopenharmony_ci             * page turning is considered.
457a3e0fd82Sopenharmony_ci             */
458a3e0fd82Sopenharmony_ci            int16_t offset = (curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) - swipeMid;
459a3e0fd82Sopenharmony_ci            int16_t threshold = (this->*pfnGetWidthOrHeight)() >> 2; // 2: 1/4 width or height
460a3e0fd82Sopenharmony_ci            if (offset > threshold && (dragDirection == DragEvent::DIRECTION_TOP_TO_BOTTOM ||
461a3e0fd82Sopenharmony_ci                                       dragDirection == DragEvent::DIRECTION_LEFT_TO_RIGHT)) {
462a3e0fd82Sopenharmony_ci                CurrentIndexDec();
463a3e0fd82Sopenharmony_ci            } else if ((offset < -threshold) && (dragDirection == DragEvent::DIRECTION_BOTTOM_TO_TOP ||
464a3e0fd82Sopenharmony_ci                                                 dragDirection == DragEvent::DIRECTION_RIGHT_TO_LEFT)) {
465a3e0fd82Sopenharmony_ci                CurrentIndexInc();
466a3e0fd82Sopenharmony_ci            }
467a3e0fd82Sopenharmony_ci        }
468a3e0fd82Sopenharmony_ci    }
469a3e0fd82Sopenharmony_ci    curView_ = GetViewByIndex(curIndex_);
470a3e0fd82Sopenharmony_ci#if defined(ENABLE_VIBRATOR) && ENABLE_VIBRATOR
471a3e0fd82Sopenharmony_ci    if (lastIndex != curIndex_) {
472a3e0fd82Sopenharmony_ci        Vibrator();
473a3e0fd82Sopenharmony_ci    }
474a3e0fd82Sopenharmony_ci#endif
475a3e0fd82Sopenharmony_ci}
476a3e0fd82Sopenharmony_ci
477a3e0fd82Sopenharmony_civoid UISwipeView::MoveChildByOffset(int16_t xOffset, int16_t yOffset)
478a3e0fd82Sopenharmony_ci{
479a3e0fd82Sopenharmony_ci    UIViewGroup::MoveChildByOffset(xOffset, yOffset);
480a3e0fd82Sopenharmony_ci    MoveHeadOrTailChild();
481a3e0fd82Sopenharmony_ci}
482a3e0fd82Sopenharmony_ci
483a3e0fd82Sopenharmony_cibool UISwipeView::IsNeedLoop()
484a3e0fd82Sopenharmony_ci{
485a3e0fd82Sopenharmony_ci    if (!loop_ || (childrenHead_ == nullptr) || (childrenTail_ == nullptr)) {
486a3e0fd82Sopenharmony_ci        return false;
487a3e0fd82Sopenharmony_ci    }
488a3e0fd82Sopenharmony_ci    Rect childRect = GetAllChildRelativeRect();
489a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
490a3e0fd82Sopenharmony_ci        if ((childRect.GetWidth() - childrenHead_->GetWidth() >= GetWidth()) &&
491a3e0fd82Sopenharmony_ci            (childRect.GetWidth() - childrenTail_->GetWidth() >= GetWidth())) {
492a3e0fd82Sopenharmony_ci            return true;
493a3e0fd82Sopenharmony_ci        }
494a3e0fd82Sopenharmony_ci    } else {
495a3e0fd82Sopenharmony_ci        if ((childRect.GetHeight() - childrenHead_->GetHeight() >= GetHeight()) &&
496a3e0fd82Sopenharmony_ci            (childRect.GetHeight() - childrenTail_->GetHeight() >= GetHeight())) {
497a3e0fd82Sopenharmony_ci            return true;
498a3e0fd82Sopenharmony_ci        }
499a3e0fd82Sopenharmony_ci    }
500a3e0fd82Sopenharmony_ci    return false;
501a3e0fd82Sopenharmony_ci}
502a3e0fd82Sopenharmony_ci
503a3e0fd82Sopenharmony_civoid UISwipeView::MoveFirstChildToLast()
504a3e0fd82Sopenharmony_ci{
505a3e0fd82Sopenharmony_ci    if ((childrenTail_ == nullptr) || (childrenHead_ == nullptr)) {
506a3e0fd82Sopenharmony_ci        return;
507a3e0fd82Sopenharmony_ci    }
508a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
509a3e0fd82Sopenharmony_ci        childrenHead_->SetX(childrenTail_->GetX() + childrenTail_->GetWidth());
510a3e0fd82Sopenharmony_ci    } else {
511a3e0fd82Sopenharmony_ci        childrenHead_->SetY(childrenTail_->GetY() + childrenTail_->GetHeight());
512a3e0fd82Sopenharmony_ci    }
513a3e0fd82Sopenharmony_ci    UIView* head = childrenHead_;
514a3e0fd82Sopenharmony_ci    UIViewGroup::Remove(childrenHead_);
515a3e0fd82Sopenharmony_ci    UIViewGroup::Add(head);
516a3e0fd82Sopenharmony_ci}
517a3e0fd82Sopenharmony_ci
518a3e0fd82Sopenharmony_civoid UISwipeView::MoveLastChildToFirst()
519a3e0fd82Sopenharmony_ci{
520a3e0fd82Sopenharmony_ci    if ((childrenTail_ == nullptr) || (childrenHead_ == nullptr)) {
521a3e0fd82Sopenharmony_ci        return;
522a3e0fd82Sopenharmony_ci    }
523a3e0fd82Sopenharmony_ci    if (direction_ == HORIZONTAL) {
524a3e0fd82Sopenharmony_ci        childrenTail_->SetX(childrenHead_->GetX() - childrenTail_->GetWidth());
525a3e0fd82Sopenharmony_ci    } else {
526a3e0fd82Sopenharmony_ci        childrenTail_->SetY(childrenHead_->GetY() - childrenTail_->GetHeight());
527a3e0fd82Sopenharmony_ci    }
528a3e0fd82Sopenharmony_ci    UIView* last = childrenTail_;
529a3e0fd82Sopenharmony_ci    UIViewGroup::Remove(childrenTail_);
530a3e0fd82Sopenharmony_ci    UIViewGroup::Insert(nullptr, last);
531a3e0fd82Sopenharmony_ci}
532a3e0fd82Sopenharmony_ci
533a3e0fd82Sopenharmony_civoid UISwipeView::CalculateInvalidate()
534a3e0fd82Sopenharmony_ci{
535a3e0fd82Sopenharmony_ci    Rect swipeRect(0, 0, GetRelativeRect().GetWidth() - 1, GetRelativeRect().GetHeight() - 1);
536a3e0fd82Sopenharmony_ci    UIView* view = childrenHead_;
537a3e0fd82Sopenharmony_ci    bool isFound = false;
538a3e0fd82Sopenharmony_ci    while (view != nullptr) {
539a3e0fd82Sopenharmony_ci        Rect rect = view->GetRelativeRect();
540a3e0fd82Sopenharmony_ci        if (rect.IsIntersect(swipeRect)) {
541a3e0fd82Sopenharmony_ci            if (view->IsVisible() && (view->GetOpaScale() != OPA_TRANSPARENT)) {
542a3e0fd82Sopenharmony_ci                view->Invalidate();
543a3e0fd82Sopenharmony_ci            }
544a3e0fd82Sopenharmony_ci            isFound = true;
545a3e0fd82Sopenharmony_ci        } else if (isFound) {
546a3e0fd82Sopenharmony_ci            return;
547a3e0fd82Sopenharmony_ci        }
548a3e0fd82Sopenharmony_ci
549a3e0fd82Sopenharmony_ci        view = view->GetNextSibling();
550a3e0fd82Sopenharmony_ci    }
551a3e0fd82Sopenharmony_ci}
552a3e0fd82Sopenharmony_ci
553a3e0fd82Sopenharmony_civoid UISwipeView::CurrentIndexInc()
554a3e0fd82Sopenharmony_ci{
555a3e0fd82Sopenharmony_ci    curIndex_++;
556a3e0fd82Sopenharmony_ci    if (curIndex_ > childrenNum_ - 1) {
557a3e0fd82Sopenharmony_ci        if (IsNeedLoop()) {
558a3e0fd82Sopenharmony_ci            curIndex_ = curIndex_ % childrenNum_;
559a3e0fd82Sopenharmony_ci        } else {
560a3e0fd82Sopenharmony_ci            curIndex_ = childrenNum_ - 1;
561a3e0fd82Sopenharmony_ci        }
562a3e0fd82Sopenharmony_ci    }
563a3e0fd82Sopenharmony_ci}
564a3e0fd82Sopenharmony_ci
565a3e0fd82Sopenharmony_civoid UISwipeView::CurrentIndexDec()
566a3e0fd82Sopenharmony_ci{
567a3e0fd82Sopenharmony_ci    if (curIndex_ == 0) {
568a3e0fd82Sopenharmony_ci        if (IsNeedLoop()) {
569a3e0fd82Sopenharmony_ci            curIndex_ = childrenNum_ - 1;
570a3e0fd82Sopenharmony_ci        }
571a3e0fd82Sopenharmony_ci    } else {
572a3e0fd82Sopenharmony_ci        curIndex_--;
573a3e0fd82Sopenharmony_ci    }
574a3e0fd82Sopenharmony_ci}
575a3e0fd82Sopenharmony_ci
576a3e0fd82Sopenharmony_ci#if defined(ENABLE_VIBRATOR) && ENABLE_VIBRATOR
577a3e0fd82Sopenharmony_civoid UISwipeView::Vibrator()
578a3e0fd82Sopenharmony_ci{
579a3e0fd82Sopenharmony_ci    VibratorFunc vibratorFunc = VibratorManager::GetInstance()->GetVibratorFunc();
580a3e0fd82Sopenharmony_ci    if (vibratorFunc != nullptr && isRotating_) {
581a3e0fd82Sopenharmony_ci        if (!loop_ && (curIndex_ == 0 || curIndex_ == childrenNum_ - 1)) {
582a3e0fd82Sopenharmony_ci            GRAPHIC_LOGI("UISwipeView::Vibrator calls TYPE_THREE vibrator");
583a3e0fd82Sopenharmony_ci            vibratorFunc(VibratorType::VIBRATOR_TYPE_THREE);
584a3e0fd82Sopenharmony_ci        } else {
585a3e0fd82Sopenharmony_ci            GRAPHIC_LOGI("UISwipeView::Vibrator calls TYPE_ONE vibrator");
586a3e0fd82Sopenharmony_ci            vibratorFunc(VibratorType::VIBRATOR_TYPE_ONE);
587a3e0fd82Sopenharmony_ci        }
588a3e0fd82Sopenharmony_ci    }
589a3e0fd82Sopenharmony_ci}
590a3e0fd82Sopenharmony_ci#endif
591a3e0fd82Sopenharmony_ci} // namespace OHOS
592