• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_LAYOUT_ALGORITHM_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_LAYOUT_ALGORITHM_H
18 
19 #include <cstdint>
20 #include <optional>
21 
22 #include "base/geometry/axis.h"
23 #include "base/geometry/ng/offset_t.h"
24 #include "base/memory/referenced.h"
25 #include "core/components_ng/layout/layout_algorithm.h"
26 #include "core/components_ng/layout/layout_wrapper.h"
27 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
28 
29 namespace OHOS::Ace::NG {
30 
31 struct SwiperItemInfo {
32     float startPos = 0.0f;
33     float endPos = 0.0f;
34     RefPtr<FrameNode> node = nullptr;
35     OffsetF finalOffset = OffsetF();
36     CancelableCallback<void()> task = CancelableCallback<void()>();
37     bool isFinishAnimation = false;
38 };
39 
40 class ACE_EXPORT SwiperLayoutAlgorithm : public LayoutAlgorithm {
41     DECLARE_ACE_TYPE(SwiperLayoutAlgorithm, LayoutAlgorithm);
42 
43 public:
44     using PositionMap = std::map<int32_t, SwiperItemInfo>;
45 
46     SwiperLayoutAlgorithm() = default;
~SwiperLayoutAlgorithm()47     ~SwiperLayoutAlgorithm() override
48     {
49         std::lock_guard<std::mutex> lock(swiperMutex_);
50     }
51 
OnReset()52     void OnReset() override {}
53     void Measure(LayoutWrapper* layoutWrapper) override;
54     void Layout(LayoutWrapper* layoutWrapper) override;
55 
SetItemsPosition(const PositionMap & itemPosition)56     void SetItemsPosition(const PositionMap& itemPosition)
57     {
58         itemPosition_ = itemPosition;
59     }
60 
GetItemPosition()61     PositionMap&& GetItemPosition()
62     {
63         return std::move(itemPosition_);
64     }
65 
SetJumpIndex(int32_t index)66     void SetJumpIndex(int32_t index)
67     {
68         jumpIndex_ = index;
69     }
70 
SetCurrentDelta(float offset)71     void SetCurrentDelta(float offset)
72     {
73         currentDelta_ = offset;
74         currentOffset_ = offset;
75     }
76 
SetOverScrollFeature()77     void SetOverScrollFeature()
78     {
79         overScrollFeature_ = true;
80     }
81 
SetCanOverScroll(bool canOverScroll)82     void SetCanOverScroll(bool canOverScroll)
83     {
84         canOverScroll_ = canOverScroll;
85     }
86 
SetTotalItemCount(int32_t totalItemCount)87     void SetTotalItemCount(int32_t totalItemCount)
88     {
89         totalItemCount_ = totalItemCount;
90     }
91 
GetContentMainSize()92     float GetContentMainSize() const
93     {
94         return contentMainSize_;
95     }
96 
SetContentMainSize(float contentMainSize)97     void SetContentMainSize(float contentMainSize)
98     {
99         contentMainSize_ = contentMainSize;
100         oldContentMainSize_ = contentMainSize;
101     }
102 
GetContentCrossSize()103     float GetContentCrossSize() const
104     {
105         return contentCrossSize_;
106     }
107 
SetCurrentOffset(float offset)108     void SetCurrentOffset(float offset)
109     {
110         currentOffset_ = offset;
111     }
112 
GetCurrentOffset()113     float GetCurrentOffset() const
114     {
115         return currentOffset_;
116     }
117 
SetTargetIndex(std::optional<int32_t> targetIndex)118     void SetTargetIndex(std::optional<int32_t> targetIndex)
119     {
120         targetIndex_ = targetIndex;
121     }
122 
SetIsLoop(bool isLoop)123     void SetIsLoop(bool isLoop)
124     {
125         isLoop_ = isLoop;
126     }
127 
GetStartIndex()128     int32_t GetStartIndex() const
129     {
130         return itemPosition_.empty() ? 0 : itemPosition_.begin()->first;
131     }
132 
GetEndIndex()133     int32_t GetEndIndex() const
134     {
135         return itemPosition_.empty() ? 0 : itemPosition_.rbegin()->first;
136     }
137 
GetStartPosition()138     float GetStartPosition() const
139     {
140         if (itemPosition_.empty()) {
141             return 0.0f;
142         }
143         if (GetStartIndex() == 0 && !isLoop_) {
144             return itemPosition_.begin()->second.startPos;
145         }
146         return itemPosition_.begin()->second.startPos - spaceWidth_;
147     }
148 
GetEndPosition()149     float GetEndPosition() const
150     {
151         if (itemPosition_.empty()) {
152             return 0.0f;
153         }
154         if (GetEndIndex() == totalItemCount_ - 1 && !isLoop_) {
155             return itemPosition_.rbegin()->second.endPos;
156         }
157         return itemPosition_.rbegin()->second.endPos + spaceWidth_;
158     }
159 
SetMainSizeIsMeasured(bool mainSizeIsMeasured)160     void SetMainSizeIsMeasured(bool mainSizeIsMeasured)
161     {
162         mainSizeIsMeasured_ = mainSizeIsMeasured;
163     }
164 
GetMainSizeIsMeasured()165     bool GetMainSizeIsMeasured() const
166     {
167         return mainSizeIsMeasured_;
168     }
169 
SetCurrentIndex(int32_t currentIndex)170     void SetCurrentIndex(int32_t currentIndex)
171     {
172         currentIndex_ = currentIndex;
173     }
174 
GetCurrentIndex()175     int32_t GetCurrentIndex() const
176     {
177         return currentIndex_;
178     }
179 
IsCrossMatchChild()180     bool IsCrossMatchChild() const
181     {
182         return crossMatchChild_;
183     }
184 
SetUseCustomAnimation(bool useCustomAnimation)185     void SetUseCustomAnimation(bool useCustomAnimation)
186     {
187         useCustomAnimation_ = useCustomAnimation;
188     }
189 
SetCustomAnimationToIndex(std::optional<int32_t> customAnimationToIndex)190     void SetCustomAnimationToIndex(std::optional<int32_t> customAnimationToIndex)
191     {
192         customAnimationToIndex_ = customAnimationToIndex;
193     }
194 
SetRemoveFromRSTreeIndex(std::optional<int32_t> removeFromRSTreeIndex)195     void SetRemoveFromRSTreeIndex(std::optional<int32_t> removeFromRSTreeIndex)
196     {
197         removeFromRSTreeIndex_ = removeFromRSTreeIndex;
198     }
199 
SetIndexsInAnimation(const std::set<int32_t> & indexsInAnimation)200     void SetIndexsInAnimation(const std::set<int32_t>& indexsInAnimation)
201     {
202         indexsInAnimation_ = indexsInAnimation;
203     }
204 
SetNeedUnmountIndexs(const std::set<int32_t> & needUnmountIndexs)205     void SetNeedUnmountIndexs(const std::set<int32_t>& needUnmountIndexs)
206     {
207         needUnmountIndexs_ = needUnmountIndexs;
208     }
209 
GetNeedUnmountIndexs()210     std::set<int32_t> GetNeedUnmountIndexs() const
211     {
212         return needUnmountIndexs_;
213     }
214 
SetSwipeByGroup(bool swipeByGroup)215     void SetSwipeByGroup(bool swipeByGroup)
216     {
217         swipeByGroup_ = swipeByGroup;
218     }
219 
SetRealTotalCount(int32_t realTotalCount)220     void SetRealTotalCount(int32_t realTotalCount)
221     {
222         realTotalCount_ = realTotalCount;
223     }
224 
SetPlaceItemWidth(std::optional<float> placeItemWidth)225     void SetPlaceItemWidth(std::optional<float> placeItemWidth)
226     {
227         placeItemWidth_ = placeItemWidth;
228     }
229 
SetHasCachedCapture(bool hasCachedCapture)230     void SetHasCachedCapture(bool hasCachedCapture)
231     {
232         hasCachedCapture_ = hasCachedCapture;
233     }
234 
SetIsCaptureReverse(bool isCaptureReverse)235     void SetIsCaptureReverse(bool isCaptureReverse)
236     {
237         isCaptureReverse_ = isCaptureReverse;
238     }
239 
GetIsCaptureReverse()240     bool GetIsCaptureReverse() const
241     {
242         return isCaptureReverse_;
243     }
244 
GetIsNeedUpdateCapture()245     bool GetIsNeedUpdateCapture() const
246     {
247         return isNeedUpdateCapture_;
248     }
249 
SetItemsPositionInAnimation(const PositionMap & itemPositionInAnimation)250     void SetItemsPositionInAnimation(const PositionMap& itemPositionInAnimation)
251     {
252         itemPositionInAnimation_ = itemPositionInAnimation;
253     }
254 
GetItemsPositionInAnimation()255     PositionMap&& GetItemsPositionInAnimation()
256     {
257         return std::move(itemPositionInAnimation_);
258     }
259 
SetIsMeasureOneMoreItem(bool isMeasureOneMoreItem)260     void SetIsMeasureOneMoreItem(bool isMeasureOneMoreItem)
261     {
262         isMeasureOneMoreItem_ = isMeasureOneMoreItem;
263     }
264 
SetIsFrameAnimation(bool isFrameAnimation)265     void SetIsFrameAnimation(bool isFrameAnimation)
266     {
267         isFrameAnimation_ = isFrameAnimation;
268     }
269 
GetTargetStartPos()270     float GetTargetStartPos() const
271     {
272         return targetStartPos_;
273     }
274 
SetCachedCount(int32_t cachedCount)275     void SetCachedCount(int32_t cachedCount)
276     {
277         cachedCount_ = cachedCount > realTotalCount_ ? realTotalCount_ : cachedCount;
278     }
279 
GetCachedItems()280     const std::set<int32_t>& GetCachedItems() const
281     {
282         return cachedItems_;
283     }
284 
GetLayoutConstraint()285     const LayoutConstraintF& GetLayoutConstraint() const
286     {
287         return childLayoutConstraint_;
288     }
289 
GetIgnoreBlankOffset()290     float GetIgnoreBlankOffset() const
291     {
292         return ignoreBlankOffset_;
293     }
294 
SetIgnoreBlankOffset(float ignoreBlankOffset)295     void SetIgnoreBlankOffset(float ignoreBlankOffset)
296     {
297         ignoreBlankOffset_ = ignoreBlankOffset;
298     }
299 
SetDuringInteraction(bool duringInteraction)300     void SetDuringInteraction(bool duringInteraction)
301     {
302         duringInteraction_ = duringInteraction;
303     }
304 
GetJumpIndex()305     std::optional<int32_t> GetJumpIndex() const
306     {
307         return jumpIndex_;
308     }
309 
SetCachedShow(bool cachedShow)310     void SetCachedShow(bool cachedShow)
311     {
312         cachedShow_ = cachedShow;
313     }
314 
315 private:
316     void LayoutForward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t startIndex,
317         float startPos, bool cachedLayout = false);
318     void LayoutBackward(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint, int32_t endIndex,
319         float endPos, bool cachedLayout = false);
320     bool LayoutForwardItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint,
321         int32_t& currentIndex, float startPos, float& endPos);
322     bool LayoutBackwardItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint,
323         int32_t& currentIndex, float endPos, float& startPos);
324     float GetChildMaxSize(LayoutWrapper* layoutWrapper, bool isMainAxis) const;
325     int32_t GetLoopIndex(int32_t originalIndex) const;
326 
327     void LayoutSwiperIndicator(
328         LayoutWrapper* layoutWrapper, const RefPtr<SwiperLayoutProperty>& swiperLayoutProperty,
329         const PaddingPropertyF& padding);
330     void MeasureSwiper(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint);
331     void MeasureTabsCustomAnimation(LayoutWrapper* layoutWrapper);
332     void MeasureSwiperCustomAnimation(LayoutWrapper* layoutWrapper, const LayoutConstraintF& layoutConstraint);
333     void LayoutCustomAnimation(LayoutWrapper* layoutWrapper) const;
334     void LayoutItem(LayoutWrapper* layoutWrapper, OffsetF offset, std::pair<int32_t, SwiperItemInfo> pos);
335     void SetInactive(
336         LayoutWrapper* layoutWrapper, float startMainPos, float endMainPos, std::optional<int32_t> targetIndex);
337 
338     void PlaceDigitChild(const RefPtr<LayoutWrapper>& indicatorWrapper, const RefPtr<LayoutProperty>& layoutProperty);
339     RefPtr<LayoutWrapper> GetNodeLayoutWrapperByTag(LayoutWrapper* layoutWrapper, const std::string& tagName) const;
340     void MeasureArrow(const RefPtr<LayoutWrapper>& arrowWrapper, const RefPtr<LayoutProperty>& layoutProperty) const;
341     void ArrowLayout(
342         LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& arrowWrapper, const PaddingPropertyF padding) const;
343     void ResetOffscreenItemPosition(LayoutWrapper* layoutWrapper, int32_t index, bool isForward) const;
344     int32_t GetDisplayCount(LayoutWrapper* layoutWrapper) const;
345     void SetInactiveOnForward(LayoutWrapper* layoutWrapper);
346     void SetInactiveOnBackward(LayoutWrapper* layoutWrapper);
347     void AdjustStartInfoOnSwipeByGroup(
348         int32_t startIndex, const PositionMap& itemPosition, int32_t& startIndexInVisibleWindow, float& startPos);
349     bool HasCustomIndicatorOffset(const RefPtr<LayoutWrapper>& indicatorWrapper);
350     const OffsetF CalculateCustomOffset(
351         const RefPtr<LayoutWrapper>& indicatorWrapper, const OffsetF& currentOffset);
352     void CaptureMeasure(LayoutWrapper* layoutWrapper, LayoutConstraintF& childLayoutConstraint);
353     void CaptureLayout(LayoutWrapper* layoutWrapper);
354     bool IsNormalItem(const RefPtr<LayoutWrapper>& wrapper) const;
355     void UpdateLayoutInfoBeforeMeasureSwiper(
356         const RefPtr<SwiperLayoutProperty>& property, const LayoutConstraintF& layoutConstraint);
357     void IndicatorAndArrowMeasure(LayoutWrapper* layoutWrapper, const OptionalSizeF& parentIdealSize);
358     float GetChildMainAxisSize(
359         const RefPtr<LayoutWrapper>& childWrapper, const RefPtr<SwiperLayoutProperty>& swiperProperty);
360 
361     void CheckCachedItem(int32_t startIndex, int32_t endIndex, LayoutWrapper* layoutWrapper);
362     void MeasureSwiperOnJump(LayoutWrapper* layoutWrapper, const LayoutConstraintF& constraint, int32_t jumpIndex);
363     bool NeedMeasureForward(int32_t currentIndex, float currentEndPos, float forwardEndPos, bool cachedLayout) const;
364     bool NeedMeasureBackward(
365         int32_t currentIndex, float currentStartPos, float backwardStartPos, bool isStretch, bool cachedLayout) const;
366     void CalcCachedItemIndex(LayoutWrapper* layoutWrapper);
367     int32_t GetCurrentFirstIndexInWindow(LayoutWrapper* layoutWrapper) const;
368     int32_t GetCurrentLastIndexInWindow(LayoutWrapper* layoutWrapper) const;
369     void LayoutCachedItem(LayoutWrapper* layoutWrapper, const LayoutConstraintF& constraint);
370     int32_t GetUserSetCachedCount(LayoutWrapper* layoutWrapper) const;
371     void AdjustItemPositionOnCachedShow();
372     void AdjustOffsetOnForward(float currentEndPos);
373     void AdjustOffsetOnBackward(float currentStartPos);
374     float GetHeightForDigit(LayoutWrapper* layoutWrapper, float height) const;
375 
376     bool isLoop_ = true;
377     float prevMargin_ = 0.0f;
378     float nextMargin_ = 0.0f;
379 
380     PositionMap itemPosition_;
381     PositionMap prevItemPosition_;
382     PositionMap itemPositionInAnimation_;
383     float currentOffset_ = 0.0f;
384     float currentDelta_ = 0.0f;
385     float startMainPos_ = 0.0f;
386     float endMainPos_ = 0.0f;
387 
388     float paddingBeforeContent_ = 0.0f;
389     float paddingAfterContent_ = 0.0f;
390     float contentMainSize_ = 0.0f;
391     float oldContentMainSize_ = 0.0f;
392     float contentCrossSize_ = 0.0f;
393     int32_t totalItemCount_ = 0;
394     bool mainSizeIsDefined_ = false;
395 
396     float spaceWidth_ = 0.0f;
397     bool overScrollFeature_ = false;
398     bool canOverScroll_ = false;
399 
400     bool mainSizeIsMeasured_ = false;
401     bool crossMatchChild_ = false;
402     bool measured_ = false; // to distinguish first and second measure in flex layout
403     bool duringInteraction_ = false; // user interacting, include touching and translating animation.
404 
405     std::optional<int32_t> jumpIndex_;
406     std::optional<int32_t> targetIndex_;
407     std::optional<int32_t> currentJumpIndex_;
408     std::optional<int32_t> currentTargetIndex_;
409     std::optional<int32_t> customAnimationToIndex_;
410     std::optional<int32_t> removeFromRSTreeIndex_;
411     std::optional<SizeF> leftCaptureSize_ = std::nullopt;
412     std::optional<SizeF> rightCaptureSize_ = std::nullopt;
413     int32_t currentIndex_ = 0;
414     bool targetIsSameWithStartFlag_ = false;
415     bool useCustomAnimation_ = false;
416     std::set<int32_t> indexsInAnimation_;
417     std::set<int32_t> needUnmountIndexs_;
418     bool swipeByGroup_ = false;
419     int32_t realTotalCount_ = 0;
420     std::optional<float> placeItemWidth_;
421     bool useCustomIndicatorOffset = false;
422     bool hasCachedCapture_ = false;
423     bool isCaptureReverse_ = false;
424     bool isNeedUpdateCapture_ = false;
425     bool isMeasureOneMoreItem_ = false;
426     bool isFrameAnimation_ = false;
427     float ignoreBlankOffset_ = 0.0f;
428     float currentIgnoreBlankOffset_ = 0.0f;
429     bool prevMarginIgnoreBlank_ = false;
430     std::set<int32_t> measuredItems_;
431     std::set<int32_t> activeItems_;
432     std::set<int32_t> cachedItems_;
433     // only be used in AutoLinear mode
434     float targetStartPos_ = 0.0f;
435     int32_t cachedCount_ = 0;
436     bool cachedShow_ = false;
437     int32_t cachedStartIndex_ = 0;
438     int32_t cachedEndIndex_ = 0;
439     LayoutConstraintF childLayoutConstraint_;
440     Axis axis_ = Axis::HORIZONTAL;
441 
442     std::mutex swiperMutex_;
443 };
444 
445 } // namespace OHOS::Ace::NG
446 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_LAYOUT_ALGORITHM_H
447