1 /*
2  * Copyright (c) 2023-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_GRID_GRID_IRREGULAR_LAYOUT_ALGORITHM_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_IRREGULAR_LAYOUT_ALGORITHM_H
18 
19 #include "base/utils/noncopyable.h"
20 #include "core/components_ng/layout/layout_wrapper.h"
21 #include "core/components_ng/pattern/grid/grid_layout_base_algorithm.h"
22 #include "core/components_ng/pattern/grid/grid_layout_info.h"
23 
24 /**
25  * @brief GridIrregularLayout class supports irregular grid items that take multiple rows and multiple columns.
26  *
27  * INVARIANT: gridMatrix_ is always filled from the first row up to endIndex_ at the beginning of each layout.
28  * INVARIANT: startMainLineIndex_ always corresponds to where Item [startIndex_] is placed.
29  * But endMainLineIndex_ corresponds to the last line in viewport.
30  */
31 namespace OHOS::Ace::NG {
32 class GridIrregularLayoutAlgorithm : public GridLayoutBaseAlgorithm {
33     DECLARE_ACE_TYPE(GridIrregularLayoutAlgorithm, GridLayoutBaseAlgorithm);
34 
35 public:
36     explicit GridIrregularLayoutAlgorithm(GridLayoutInfo info, bool overScroll = false)
37         : GridLayoutBaseAlgorithm(std::move(info)), info_(gridLayoutInfo_), overScroll_(overScroll) {};
38 
39     ~GridIrregularLayoutAlgorithm() override = default;
40 
41     void Measure(LayoutWrapper* layoutWrapper) override;
42 
43     void Layout(LayoutWrapper* layoutWrapper) override;
44 
SetEnableSkip(bool value)45     void SetEnableSkip(bool value)
46     {
47         enableSkip_ = value;
48     }
49 
50 private:
51     /**
52      * @brief Measures the size of Grid based on the given GridLayoutProperty.
53      * @param props The GridLayoutProperty object containing the layout properties.
54      * @return The main-axis length of Grid contentRect.
55      */
56     float MeasureSelf(const RefPtr<GridLayoutProperty>& props);
57 
58     /**
59      * @brief Initializes member variables based on the given GridLayoutProperty.
60      * @param props The GridLayoutProperty object containing the layout properties.
61      */
62     void Init(const RefPtr<GridLayoutProperty>& props);
63 
64     void MeasureOnOffset(float mainSize);
65     void MeasureForward(float mainSize);
66     void MeasureBackward(float mainSize);
67 
68     /**
69      * @brief Check if offset is larger than the entire viewport. If so, skip measuring intermediate items and jump
70      * directly to the estimated destination.
71      *
72      * @param mainSize main-axis length of the viewport.
73      * @return true if a skip is performed.
74      */
75     bool TrySkipping(float mainSize);
76 
77     /**
78      * @brief Measure all items until targetIndex_ is reached. For performing scrollTo with animation.
79      *
80      */
81     void MeasureToTarget();
82 
83     /**
84      * @brief Check if layout states (matrix, height map) need to be reset during Init.
85      */
86     void CheckForReset();
87 
88     /**
89      * @brief Performs the layout of the children based on the main offset.
90      * @param mainOffset The main offset of the layout.
91      * @param cacheLine number of lines of cache items to layout
92      */
93     void LayoutChildren(float mainOffset, int32_t cacheLine);
94 
95     /**
96      * @brief Update variables in GridLayoutInfo at the end of Layout.
97      */
98     void UpdateLayoutInfo();
99 
100     /**
101      * @brief Calculates the cross positions based on the padding.
102      * @param padding The padding property of the layout.
103      * @return A vector containing the cross positions.
104      */
105     std::vector<float> CalculateCrossPositions(const PaddingPropertyF& padding);
106 
107     // ========================================== MeasureOnJump functions =====================================
108 
109     void MeasureOnJump(float mainSize);
110     void Jump(float mainSize);
111 
112     /**
113      * @brief Find the line the jumpIdx item resides in. If not in matrix, fill the matrix up to [jumpIdx].
114      *
115      * @param jumpIdx The GridItem index to jump to.
116      * @return The line index of the item in GridMatrix.
117      */
118     int32_t FindJumpLineIdx(int32_t jumpIdx);
119 
120     /**
121      * @brief Prepares GridLayoutInfo::lineHeightMap_ using GridIrregularFiller.
122      *
123      * If the algorithm identifies that mainSize can't be filled with the current scrollAlign_ and jumpLineIdx, these
124      * params will be adjusted. For instance, jumping to the last line with ScrollAlign::START isn't possible.
125      *
126      * @param mainSize The main-axis length of the grid.
127      * @param jumpLineIdx The line index to jump to, can be adjusted during the function call.
128      */
129     void PrepareLineHeight(float mainSize, int32_t& jumpLineIdx);
130     // ========================================== MeasureOnJump ends ===========================================
131 
132     /**
133      * @brief Skip forward by currentOffset_ and fill the matrix along the way.
134      *
135      * @return item index to jump to after skipping.
136      */
137     int32_t SkipLinesForward();
138 
139     /**
140      * @brief Skip backward by currentOffset_. Can assume that the matrix is already filled up to startIdx_
141      *
142      * @return item index to jump to after skipping.
143      */
144     int32_t SkipLinesBackward() const;
145 
146     bool IsIrregularLine(int32_t lineIndex) const override;
147 
148     /**
149      * @brief post delayed task to preload GridItems in cache range.
150      */
151     void PreloadItems(int32_t cacheCnt);
152     /**
153      * @brief immediately create & measure GridItems in cache range.
154      */
155     void SyncPreloadItems(int32_t cacheCnt);
156 
157     void AdaptToChildMainSize(RefPtr<GridLayoutProperty>& gridLayoutProperty, float mainSize, SizeF idealSize);
158 
159     GridLayoutInfo& info_;
160 
161     LayoutWrapper* wrapper_ = nullptr;
162 
163     std::vector<float> crossLens_; /**< The column widths of the GridItems. */
164     float crossGap_ = 0.0f;        /**< The cross-axis gap between GridItems. */
165     float mainGap_ = 0.0f;         /**< The main-axis gap between GridItems. */
166 
167     float postJumpOffset_ = 0.0f; /**< The offset to be applied after performing a jump. */
168 
169     bool enableSkip_ = true;
170     bool overScroll_ = false;
171 
172     SizeF frameSize_;
173 
174     ACE_DISALLOW_COPY_AND_MOVE(GridIrregularLayoutAlgorithm);
175 };
176 
177 } // namespace OHOS::Ace::NG
178 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_IRREGULAR_LAYOUT_ALGORITHM_H
179