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_FILLER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_IRREGULAR_FILLER_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_info.h" 22 #include "core/components_ng/pattern/grid/grid_layout_options.h" 23 24 namespace OHOS::Ace::NG { 25 /** 26 * @brief The GridIrregularFiller class is responsible for filling an irregular grid layout with items. 27 * 28 * It calculates the positions and sizes of the items based on the provided layout information. 29 * The GridItems can have varying row and column lengths. 30 */ 31 class GridIrregularFiller { 32 ACE_DISALLOW_COPY_AND_MOVE(GridIrregularFiller); 33 34 public: 35 /** 36 * @brief Constructs a GridIrregularFiller object. 37 * REQUIRES: All indices prior to GridLayoutInfo::startIndex_ should already be in the GridMatrix. 38 */ 39 GridIrregularFiller(GridLayoutInfo* info, LayoutWrapper* wrapper); 40 ~GridIrregularFiller() = default; 41 42 struct FillParameters { 43 std::vector<float> crossLens; /**< The column widths of items. */ 44 float crossGap = 0.0f; /**< The cross-axis gap between items. */ 45 float mainGap = 0.0f; /**< The main-axis gap between items. */ 46 }; 47 48 struct FillResult { 49 float length = 0.0f; /**< The total length filled on the main axis. */ 50 int32_t endMainLineIndex = -1; /**< The last line filled to reach target length. */ 51 int32_t endIndex = -1; /**< The index of the last item measured. */ 52 }; 53 54 /** 55 * @brief Fills the grid with items in the forward direction. 56 * 57 * @param params The FillParameters object containing the fill parameters. 58 * @param targetLen The target length of the main axis (total row height to fill). 59 * @param startingLine The line index to start filling from. 60 */ 61 FillResult Fill(const FillParameters& params, float targetLen, int32_t startingLine); 62 63 /** 64 * @brief Fills the grid with items in the forward direction until targetIdx is measured. 65 * 66 * @param params The FillParameters object containing the fill parameters. 67 * @param targetIdx The target index to fill up to. 68 * @param startingLine The line index to start filling from. 69 */ 70 void FillToTarget(const FillParameters& params, int32_t targetIdx, int32_t startingLine); 71 72 /** 73 * @brief Fills the gridMatrix in forward direction until the target GridItem is included. Measure isn't performed, 74 * and lineHeightMap_ isn't updated. 75 * 76 * @param targetIdx The target GridItem index to fill. 77 * 78 * @return Line index in which Item [targetIdx] resides. 79 */ 80 int32_t FillMatrixOnly(int32_t targetIdx); 81 82 /** 83 * @brief Fills the gridMatrix in forward direction until lines prior to [targetLine] are all filled. 84 * Measure isn't performed, and lineHeightMap_ isn't updated. 85 * 86 * @param startingLine The starting line index. 87 * @param targetLine The target GridItem index to fill up to. 88 * 89 * @return Last item index filled to reach [targetLine]. 90 */ 91 int32_t FillMatrixByLine(int32_t startingLine, int32_t targetLine); 92 93 /** 94 * @brief Measures the GridItems in the backward direction until the target length is filled. 95 * 96 * REQUIRES: GridMatrix prior to startingLine is already filled. 97 * 98 * @param params The fill parameters for measuring GridItems. 99 * @param targetLen The target length of the main axis (total row height to fill). 100 * @param startingLine The line index to start measuring backward. 101 * @return The total length filled on the main axis. 102 */ 103 float MeasureBackward(const FillParameters& params, float targetLen, int32_t startingLine); 104 105 /** 106 * @brief Measures the GridItems in the backward direction until the target line is measured. 107 * 108 * REQUIRES: GridMatrix prior to startingLine is already filled. 109 * 110 * @param params The fill parameters for measuring GridItems. 111 * @param targetLine The target line index to fill backward to. 112 * @param startingLine The line index to start measuring backward. 113 */ 114 void MeasureBackwardToTarget(const FillParameters& params, int32_t targetLine, int32_t startingLine); 115 116 /** 117 * @brief Check if the line contains non-top-left tiles of irregular items (represented by idx < 0 in the matrix). 118 * These items would be skipped in a a regular forward Fill, so we need to use a backward traversal to measure them. 119 * If the line doesn't contain any irregulars, no measure is performed in this function. 120 * 121 * REQUIRES: GridMatrix prior to [line] is already filled. 122 * 123 * @param params FillParameters 124 * @param line index to prepare and measure. 125 */ 126 void MeasureLineWithIrregulars(const FillParameters& params, int32_t line); 127 128 /** 129 * @brief Measures a GridItem and updates the grid layout information. 130 * 131 * @param params The FillParameters object containing the fill parameters. 132 * @param itemIdx The index of the GridItem. 133 * @param col The column index where the item is being added. 134 * @param row The row index where the item is being added. 135 */ 136 std::pair<float, LayoutConstraintF> MeasureItem( 137 const FillParameters& params, int32_t itemIdx, int32_t col, int32_t row, bool isCache); 138 139 private: 140 /** 141 * @brief Fills one GridItem into the Grid. 142 * 143 * @param idx Item index to fill in the matrix. 144 */ 145 void FillOne(int32_t idx); 146 147 /** 148 * @brief Updates the length of the main axis. Add heights in range [row, rowBound). 149 * Return immediately when [targetLen] is reached. 150 * 151 * @param len A reference to the filled length on the main axis. 152 * @param row A reference to the current row index. 153 * @param rowBound Upper bound of row index to add heights. 154 * @return true if len >= targetLen after adding height of [row]. At this point, row = last 155 */ 156 bool UpdateLength(float& len, float targetLen, int32_t& row, int32_t rowBound, float mainGap) const; 157 158 /** 159 * @brief Initializes the position of the filler in the grid to GridLayoutInfo::startIndex_. 160 * 161 * @param lineIdx The line index of the starting position. 162 * REQUIRES: lineIdx is a valid startMainLineIndex_, 163 * i.e. the top-left corner of an item resides in the first column. 164 * @return startIndex_ - 1 165 */ 166 int32_t InitPos(int32_t lineIdx); 167 168 /** 169 * @brief Initializes the position of the filler to the last item above [lineIdx] in gridMatrix_. 170 * 171 * @param lineIdx The line index to start traversing backwards (inclusive). 172 * @return index of the last item. 173 */ 174 int32_t InitPosToLastItem(int32_t lineIdx); 175 176 /** 177 * @brief Try to find the GridItem with target index in the grid matrix. 178 * 179 * @param target The target index of the GridItem. 180 * @return True if target index is already recorded in the matrix. 181 */ 182 bool FindNextItem(int32_t target); 183 184 /** 185 * @brief Advances the position of the filler in the grid. 186 * 187 * @return True if the position is successfully advanced, false if the end of the grid is reached. 188 */ 189 bool AdvancePos(); 190 191 /** 192 * @brief Checks if an item can fit in the grid based on its width and the available space in the current row or 193 * column. 194 * 195 * @param it An iterator pointing to the current row or column in the grid layout information. 196 * @param itemWidth The width of the item. 197 * @return The cross-axis index where the item can fit. Returns -1 if it can't fit on the current row. 198 */ 199 int32_t FitItem(const decltype(GridLayoutInfo::gridMatrix_)::iterator& it, int32_t itemWidth); 200 201 /** 202 * @brief Implementation of MeasureBackward algorithm on each row. 203 * 204 * @param measured unordered_set to record items that are already measured. 205 * @param params Fill Parameters needed for measure. 206 */ 207 void BackwardImpl(std::unordered_set<int32_t>& measured, const FillParameters& params); 208 209 /** 210 * @brief Finds the top row index of an item in the grid. 211 * 212 * @param row The row index of the item's bottom-left tile. 213 * @param col The column index of the item's bottom-left tile. 214 * @return The top row index of the GridItem. 215 */ 216 int32_t FindItemTopRow(int32_t row, int32_t col) const; 217 218 /** 219 * @brief Update item info to the newly filled GridItem. 220 * 221 * @param idx item index 222 * @param row row index of item's top-left corner 223 * @param col column index of item's top-left corner 224 * @param size size of the item. 225 */ 226 void SetItemInfo(int32_t idx, int32_t row, int32_t col, GridItemSize size); 227 228 int32_t posY_ = 0; /**< The current row index in the grid. */ 229 int32_t posX_ = -1; /**< The current column index in the grid. */ 230 231 GridLayoutInfo* info_; 232 LayoutWrapper* wrapper_; 233 }; 234 235 } // namespace OHOS::Ace::NG 236 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_IRREGULAR_FILLER_H 237