1 /*
2  * Copyright (c) 2024 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_WATERFLOW_WATER_FLOW_SW_LAYOUT_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_SW_LAYOUT_H
18 
19 #include "core/components/scroll/scroll_controller_base.h"
20 #include "core/components_ng/layout/layout_wrapper.h"
21 #include "core/components_ng/pattern/waterflow/layout/sliding_window/water_flow_layout_info_sw.h"
22 #include "core/components_ng/pattern/waterflow/layout/top_down/water_flow_segmented_layout.h"
23 
24 namespace OHOS::Ace::NG {
25 
26 class ACE_EXPORT WaterFlowLayoutSW : public WaterFlowSegmentLayoutBase {
27     DECLARE_ACE_TYPE(WaterFlowLayoutSW, WaterFlowSegmentLayoutBase);
28 
29 public:
WaterFlowLayoutSW(const RefPtr<WaterFlowLayoutInfoSW> & info)30     explicit WaterFlowLayoutSW(const RefPtr<WaterFlowLayoutInfoSW>& info) : info_(info) {}
31     void Measure(LayoutWrapper* wrapper) override;
32     void Layout(LayoutWrapper* wrapper) override;
33 
SetCanOverScroll(bool value)34     void SetCanOverScroll(bool value) override
35     {
36         overScroll_ = value;
37     }
38 
39     void StartCacheLayout() override;
40     bool PreloadItem(LayoutWrapper* host, int32_t itemIdx, int64_t deadline) override;
41     void EndCacheLayout() override;
42 
43 private:
44     void Init(const SizeF& frameSize);
45     /* init WaterFlow without Sections */
46     void SingleInit(const SizeF& frameSize);
47     void CheckReset();
48 
49     void MeasureOnOffset(float delta);
50 
51     void ApplyDelta(float delta);
52 
53     void MeasureBeforeAnimation(int32_t targetIdx);
54 
55     void MeasureToTarget(int32_t targetIdx);
56 
57     /**
58      * @brief When the item is within or close to viewport, layout is preserved and we merely apply an offset.
59      * When jumping to an item further away, the current layout would be reset for better layout performance.
60      *
61      * @param jumpIdx
62      * @param align ScrollAlign
63      * @param mainSize of the viewport
64      */
65     void MeasureOnJump(int32_t jumpIdx, ScrollAlign align);
66 
67     /**
68      * @brief Helper to perform jumping to an item.
69      *
70      * @param noSkip true if we can directly apply offset to reach the target.
71      */
72     void Jump(int32_t jumpIdx, ScrollAlign align, bool noSkip);
73 
74     /**
75      * @brief convert Auto align to other Align types.
76      *
77      * @param inView true if item is between startIndex and endIndex.
78      * @return converted ScrollAlign type.
79      */
80     ScrollAlign ParseAutoAlign(int32_t jumpIdx, bool inView);
81 
82     /**
83      * @brief fills the viewport backward until [viewportBound] is reached / idx < minChildIdx.
84      *
85      * @param viewportBound boundary to fill towards.
86      * @param idx first item index to fill with.
87      * @param minChildIdx smallest item index to fill before stopping.
88      */
89     void FillFront(float viewportBound, int32_t idx, int32_t minChildIdx);
90     /**
91      * @brief fills backward with one section.
92      *
93      * @return true if fillFront should end. False implies section is completely filled or idx < minChildIdx.
94      */
95     bool FillFrontSection(float viewportBound, int32_t& idx, int32_t minChildIdx);
96     /**
97      * @brief fills the viewport backward with cached idx -> lane mapping.
98      */
99     void RecoverFront(float viewportBound, int32_t& idx, int32_t minChildIdx);
100     /**
101      * @brief Append Item in the front of a lane.
102      * @return endPos of next item in the filled lane.
103      */
104     float FillFrontHelper(float itemLen, int32_t idx, size_t laneIdx);
105     /**
106      * @brief Clear items above the viewport.
107      * Iterate by index to keep item range continuous.
108      */
109     void ClearFront();
110 
111     /**
112      * @brief fills the viewport forward until [viewportBound] is reached / idx > maxChildIdx.
113      *
114      * @param viewportBound boundary to fill towards.
115      * @param idx first item index to fill with.
116      * @param maxChildIdx greatest item index to fill before stopping.
117      */
118     void FillBack(float viewportBound, int32_t idx, int32_t maxChildIdx);
119     /**
120      * @brief fills forward with one section.
121      *
122      * @return true if fillBack should end. False implies section is completely filled or idx > maxChildIdx.
123      */
124     bool FillBackSection(float viewportBound, int32_t& idx, int32_t maxChildIdx);
125     /**
126      * @brief fills the viewport forward with cached idx -> lane mapping.
127      */
128     void RecoverBack(float viewportBound, int32_t& idx, int32_t maxChildIdx);
129     /**
130      * @brief Append Item to a lane.
131      * @return startPos of next item in the filled lane.
132      */
133     float FillBackHelper(float itemLen, int32_t idx, size_t laneIdx);
134     /**
135      * @brief Clear items below the viewport.
136      *
137      * @param bound of the viewport
138      */
139     void ClearBack(float bound);
140 
141     void AdjustOverScroll();
142 
143     /**
144      * @brief If need to match children size, adjust self size after measuring children.
145      */
146     void PostMeasureSelf(float selfCrossLen);
147 
148     float MeasureChild(const RefPtr<WaterFlowLayoutProperty>& props, int32_t idx, size_t lane) const;
149 
150     /**
151      * @brief Fill cache items back to lanes_ to prepare for Layout phase.
152      * (These items were removed during ClearFront / ClearBack)
153      */
154     void RecoverCacheItems(int32_t cacheCount);
155     /**
156      * @param itemIdx to recover.
157      * @param front true if recovering an item before startIndex_.
158      * @return true if item is successfully recovered.
159      */
160     bool RecoverCachedHelper(int32_t itemIdx, bool front);
161 
162     /**
163      * @brief Measure all items in view to check if any item's height changed.
164      */
165     bool ItemHeightChanged() const;
166 
167     /**
168      * @brief Data validity check
169      */
170     bool CheckData() const;
171 
172     /**
173      * @brief Layout a single section of items
174      *
175      * @param idx section index.
176      * @param paddingOffset WaterFlow padding, need to add to the child offset.
177      * @param selfCrossLen cross length of WaterFlow.
178      * @param reverse true if reverse layout
179      * @param rtl true if layout right to left
180      */
181     void LayoutSection(size_t idx, const OffsetF& paddingOffset, float selfCrossLen, bool reverse, bool rtl);
182     void LayoutFooter(const OffsetF& paddingOffset, bool reverse);
183 
184     void SyncPreloadItem(LayoutWrapper* host, int32_t itemIdx) override;
185     /**
186      * @brief shared implementation to preload a cache item.
187      * @return true if the item is successfully preloaded.
188      */
189     bool PreloadItemImpl(int32_t itemIdx);
190 
191     // convert FlowItem's index to children node index.
192     inline int32_t nodeIdx(int32_t idx) const;
193 
194     RefPtr<WaterFlowLayoutInfoSW> info_;
195     RefPtr<WaterFlowSections> sections_;
196 
197     int32_t itemCnt_ = 0; // total number of FlowItems (excluding footer)
198     float mainLen_ = 0.0f;
199     std::optional<int64_t> cacheDeadline_; // cache layout deadline
200 
201     bool overScroll_ = true;
202 };
203 } // namespace OHOS::Ace::NG
204 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_SW_LAYOUT_H
205