1 /* 2 * Copyright (c) 2022-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_SCROLL_GRID_SCROLL_LAYOUT_ALGORITHM_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_SCROLL_GRID_SCROLL_LAYOUT_ALGORITHM_H 18 19 #include "core/components_ng/pattern/grid/grid_item_layout_property.h" 20 #include "core/components_ng/pattern/grid/grid_layout_base_algorithm.h" 21 #include "core/components_ng/pattern/grid/grid_layout_info.h" 22 #include "core/components_ng/pattern/grid/grid_layout_property.h" 23 #include "core/components_ng/pattern/scrollable/scrollable_properties.h" 24 25 namespace OHOS::Ace::NG { 26 27 class ACE_EXPORT GridScrollLayoutAlgorithm : public GridLayoutBaseAlgorithm { 28 DECLARE_ACE_TYPE(GridScrollLayoutAlgorithm, GridLayoutBaseAlgorithm); 29 30 public: GridScrollLayoutAlgorithm(GridLayoutInfo gridLayoutInfo,uint32_t crossCount,uint32_t mainCount)31 GridScrollLayoutAlgorithm(GridLayoutInfo gridLayoutInfo, uint32_t crossCount, uint32_t mainCount) 32 : GridLayoutBaseAlgorithm(std::move(gridLayoutInfo)), crossCount_(crossCount), mainCount_(mainCount) {}; 33 ~GridScrollLayoutAlgorithm() override = default; 34 35 void Measure(LayoutWrapper* layoutWrapper) override; 36 void Layout(LayoutWrapper* layoutWrapper) override; 37 SetCanOverScroll(bool canOverScroll)38 void SetCanOverScroll(bool canOverScroll) 39 { 40 canOverScroll_ = canOverScroll; 41 } 42 SetScrollSource(int32_t scrollSource)43 void SetScrollSource(int32_t scrollSource) 44 { 45 scrollSource_ = scrollSource; 46 } 47 48 /** 49 * @brief Set enableSkipping_ parameter. When skip is enabled, the algorithm would skip measuring intermediate items 50 * when the offset change is large (larger than the whole viewport). 51 * 52 * @param skip 53 */ SetLineSkipping(bool skip)54 void SetLineSkipping(bool skip) 55 { 56 enableSkipping_ = skip; 57 } 58 GetScrollGridLayoutInfo()59 GridLayoutInfo GetScrollGridLayoutInfo() 60 { 61 return scrollGridLayoutInfo_; 62 } 63 64 template<class T> DeleteItemsOutOfScope(std::map<int32_t,T> & map,int32_t startLineIndex,int32_t endLineIndex)65 void DeleteItemsOutOfScope(std::map<int32_t, T>& map, int32_t startLineIndex, int32_t endLineIndex) 66 { 67 auto iter = map.begin(); 68 while (iter != map.end()) { 69 if (iter->first < startLineIndex || iter->first > endLineIndex) { 70 iter = map.erase(iter); 71 } else { 72 ++iter; 73 } 74 } 75 } 76 77 protected: 78 void SkipForwardLines(float mainSize, LayoutWrapper* layoutWrapper); 79 void SkipBackwardLines(float mainSize, LayoutWrapper* layoutWrapper); 80 void SkipRegularLines(bool forward); 81 virtual void SkipIrregularLines(LayoutWrapper* layoutWrapper, bool forward); 82 83 private: 84 void FillGridViewportAndMeasureChildren(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 85 void ReloadToStartIndex(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 86 void ReloadFromUpdateIdxToStartIndex( 87 float mainSize, float crossSize, int32_t updateLineIndex, LayoutWrapper* layoutWrapper); 88 float MeasureRecordedItems(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 89 bool UseCurrentLines(float mainSize, float crossSize, LayoutWrapper* layoutWrapper, float& mainLength); 90 virtual void SkipLargeOffset(float mainSize, LayoutWrapper* layoutWrapper); 91 92 // fill start of viewport 93 bool FillBlankAtStart(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 94 float FillNewLineForward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper); 95 void AddForwardLines(int32_t currentIndex, float crossSize, float mainSize, LayoutWrapper* layoutWrapper); 96 void UpdateMatrixForAddedItems(); 97 // Fill forward one line, but do not update startMainLineIndex_ and startIndex_ 98 virtual void FillOneLineForwardWithoutUpdatingStartIndex( 99 float crossSize, float mainSize, LayoutWrapper* layoutWrapper); 100 101 // fill end of viewport 102 void FillBlankAtEnd(float mainSize, float crossSize, LayoutWrapper* layoutWrapper, float& mainLength); 103 float FillNewLineBackward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper, bool reverse); 104 105 // Measure grid item which not exist in grid matrix already, need to place it and save to grid matrix. 106 int32_t MeasureNewChild(const SizeF& frameSize, int32_t itemIndex, LayoutWrapper* layoutWrapper, 107 const RefPtr<LayoutWrapper>& childLayoutWrapper, bool reverse); 108 // Measure grid item which exist in grid matrix already, needn't to place it again. 109 int32_t MeasureChildPlaced(const SizeF& frameSize, int32_t itemIndex, int32_t crossStart, 110 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& childLayoutWrapper); 111 bool CheckNeedMeasure(const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstraint) const; 112 bool CheckNeedMeasureWhenStretch( 113 const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstraint) const; 114 void MeasureChild(LayoutWrapper* layoutWrapper, const SizeF& frameSize, 115 const RefPtr<LayoutWrapper>& childLayoutWrapper, int32_t crossStart, int32_t crossSpan); 116 117 // Compote position of grid item in cross axis. 118 float ComputeItemCrossPosition(int32_t crossStart) const; 119 virtual void LargeItemLineHeight(const RefPtr<LayoutWrapper>& itemWrapper, bool& hasNormalItem); 120 // Find next valid cell when current is not valid. 121 bool GetNextGrid(int32_t& curMain, int32_t& curCross, bool reverse) const; 122 // Find a valid cell to place grid item and save to grid matrix. 123 bool CheckGridPlaced(int32_t index, int32_t main, int32_t cross, int32_t mainSpan, int32_t crossSpan); 124 LayoutConstraintF CreateChildConstraint(float mainSize, float crossSize, 125 const RefPtr<GridLayoutProperty>& gridLayoutProperty, int32_t crossStart, int32_t crossSpan) const; 126 void ModifyCurrentOffsetWhenReachEnd(float mainSize, LayoutWrapper* layoutWrapper); 127 void InitialItemsCrossSize( 128 const RefPtr<GridLayoutProperty>& layoutProperty, const SizeF& frameSize, int32_t childrenCount); 129 bool IsIndexInMatrix(int32_t index, int32_t& startLine); 130 void UpdateGridLayoutInfo(LayoutWrapper* layoutWrapper, float mainSize); 131 virtual void GetTargetIndexInfoWithBenchMark( 132 LayoutWrapper* layoutWrapper, bool isTargetBackward, int32_t targetIndex); 133 134 void UpdateOffsetOnVirtualKeyboardHeightChange(LayoutWrapper* layoutWrapper, float mainSize); 135 void AdaptToChildMainSize(LayoutWrapper* layoutWrapper, RefPtr<GridLayoutProperty>& gridLayoutProperty, 136 float mainSize, SizeF idealSize, bool matchChildren); 137 void UpdateOffsetOnHeightChangeDuringAnimation(LayoutWrapper* layoutWrapper, float mainSize); 138 139 int32_t GetStartingItem(LayoutWrapper* layoutWrapper, int32_t currentIndex); 140 141 OffsetF CalculateLargeItemOffset( 142 OffsetF currOffset, int32_t itemIndex, int32_t currLineIndex, int32_t currentCrossIndex); 143 bool NeedAdjust(const RefPtr<GridItemLayoutProperty>& itemLayoutWrapper); 144 virtual void AdjustRowColSpan( 145 const RefPtr<LayoutWrapper>& itemLayoutWrapper, LayoutWrapper* layoutWrapper, int32_t itemIndex); 146 void LargeItemNextLineHeight(int32_t currentLineIndex, LayoutWrapper* layoutWrapper); 147 void LargeItemForwardLineHeight(int32_t currentLineIndex, LayoutWrapper* LayoutWrapper); 148 int32_t CalculateLineIndexForLargeItem(std::map<int32_t, std::map<int32_t, int32_t>>::iterator gridMatrixIter, 149 int32_t currentIndex, int32_t lineIndex, LayoutWrapper* layoutWrapper); 150 void CalculateLineHeightForLargeItem(int32_t lineIndex, int32_t currentLineIndex, 151 std::map<int32_t, std::map<int32_t, int32_t>>::iterator gridMatrixIter, LayoutWrapper* layoutWrapper); 152 void ScrollToIndexStart(LayoutWrapper* layoutWrapper, int32_t targetIndex); 153 void ScrollToIndexAuto(LayoutWrapper* layoutWrapper, float mainSize, int32_t targetIndex); 154 bool IsScrollToEndLine() const; 155 bool IsEndLineInScreenWithGap(int32_t targetLine, float totalViewHeight, float mainSize) const; 156 void UpdateCurrentOffsetForJumpTo(float mainSize); 157 void SupplyAllData2ZeroIndex(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 158 159 void FillCacheLineAtEnd(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 160 float FillNewCacheLineBackward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper, int32_t currentLine); 161 int32_t MeasureCachedChild(const SizeF& frameSize, int32_t itemIndex, LayoutWrapper* layoutWrapper, 162 const RefPtr<LayoutWrapper>& childLayoutWrapper); 163 164 void CreateCachedChildConstraint(LayoutWrapper* layoutWrapper, float mainSize, float crossSize); 165 166 static bool PredictBuildItem(FrameNode& host, int32_t itemIdx, const GridPredictLayoutParam& param); 167 static void SyncGeometry(RefPtr<LayoutWrapper>& wrapper); 168 void CompleteItemCrossPosition(LayoutWrapper* layoutWrapper, const std::map<int32_t, int32_t>& items); 169 /** 170 * @brief Updates the main line during ReloadToStartIndex based on the new crossCount_. 171 * 172 * @param startIdx index of the first GridItem in viewport 173 */ 174 virtual void UpdateMainLineOnReload(int32_t startIdx); 175 176 // get [resetFromStart,resetFromUpdate] 177 std::pair<bool, bool> GetResetMode(LayoutWrapper* layoutWrapper, int32_t updateIdx); 178 179 void CheckReset(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 180 181 bool CheckLastLineItemFullyShowed(LayoutWrapper* layoutWrapper); 182 183 void ResetOffsetWhenHeightChanged(); 184 185 bool IsIrregularLine(int32_t lineIndex) const override; 186 187 void MergeRemainingLines(std::map<int32_t, std::map<int32_t, int32_t>> matrix, int32_t forwardLines); 188 189 bool SkipLargeLineHeightLines(float mainSize); 190 191 /** 192 * @brief immediately create & measure items in cache range. 193 * 194 * @param cacheLineCnt number of lines to preload above and below viewport. 195 */ 196 void SyncPreload(LayoutWrapper* wrapper, int32_t cacheLineCnt, float crossSize, float mainSize); 197 198 protected: 199 uint32_t crossCount_ = 0; 200 uint32_t mainCount_ = 0; 201 int32_t currentItemRowSpan_ = 0; 202 int32_t currentItemColSpan_ = 0; 203 int32_t currentItemRowStart_ = -1; 204 int32_t currentItemColStart_ = -1; 205 int32_t currentItemRowEnd_ = -1; 206 int32_t currentItemColEnd_ = -1; 207 float cellAveLength_ = -1.0f; 208 float mainGap_ = 0; 209 210 private: 211 /** 212 * @brief Measure items on a line previously recorded 213 * 214 * @param line index of line to measure 215 * updates @param mainLength by adding this line's measured height 216 * updates @param endIdx with max item index in this line 217 * @return false if line isn't recorded. 218 */ 219 bool MeasureExistingLine(int32_t line, float& mainLength, int32_t& endIdx); 220 221 LayoutWrapper* wrapper_; 222 SizeF frameSize_; 223 int32_t currentMainLineIndex_ = 0; // it equals to row index in vertical grid 224 int32_t moveToEndLineIndex_ = -1; // place index in the last line when scroll to index after matrix 225 std::map<int32_t, float> itemsCrossSize_; // grid item's size in cross axis. 226 Axis axis_ = Axis::VERTICAL; 227 228 float crossGap_ = 0; 229 float crossPaddingOffset_ = 0; 230 int32_t lastCross_ = 0; 231 bool isChildrenUpdated_ = false; 232 233 bool expandSafeArea_ = false; 234 bool canOverScroll_ = false; 235 bool enableSkipping_ = true; // enables skipping lines on a large offset change. 236 GridLayoutInfo scrollGridLayoutInfo_; 237 238 // Map structure: [index, crossPosition], store cross position of each item. 239 std::map<int32_t, float> itemsCrossPosition_; 240 int32_t scrollSource_ = SCROLL_FROM_NONE; 241 OffsetF childFrameOffset_; 242 std::list<GridPreloadItem> predictBuildList_; 243 LayoutConstraintF cachedChildConstraint_; 244 245 ACE_DISALLOW_COPY_AND_MOVE(GridScrollLayoutAlgorithm); 246 }; 247 248 } // namespace OHOS::Ace::NG 249 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_SCROLL_GRID_SCROLL_LAYOUT_ALGORITHM_H 250