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 void FillOneLineForwardWithoutUpdatingStartIndex(float crossSize, float mainSize, LayoutWrapper* layoutWrapper); 99 100 // fill end of viewport 101 void FillBlankAtEnd(float mainSize, float crossSize, LayoutWrapper* layoutWrapper, float& mainLength); 102 float FillNewLineBackward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper, bool reverse); 103 104 // Measure grid item which not exist in grid matrix already, need to place it and save to grid matrix. 105 int32_t MeasureNewChild(const SizeF& frameSize, int32_t itemIndex, LayoutWrapper* layoutWrapper, 106 const RefPtr<LayoutWrapper>& childLayoutWrapper, bool reverse); 107 // Measure grid item which exist in grid matrix already, needn't to place it again. 108 int32_t MeasureChildPlaced(const SizeF& frameSize, int32_t itemIndex, int32_t crossStart, 109 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& childLayoutWrapper); 110 bool CheckNeedMeasure(const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstraint) const; 111 bool CheckNeedMeasureWhenStretch( 112 const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstraint) const; 113 void MeasureChild(LayoutWrapper* layoutWrapper, const SizeF& frameSize, 114 const RefPtr<LayoutWrapper>& childLayoutWrapper, int32_t crossStart, int32_t crossSpan); 115 116 // Compote position of grid item in cross axis. 117 float ComputeItemCrossPosition(int32_t crossStart) const; 118 virtual void LargeItemLineHeight(const RefPtr<LayoutWrapper>& itemWrapper, bool& hasNormalItem); 119 // Find next valid cell when current is not valid. 120 bool GetNextGrid(int32_t& curMain, int32_t& curCross, bool reverse) const; 121 // Find a valid cell to place grid item and save to grid matrix. 122 bool CheckGridPlaced(int32_t index, int32_t main, int32_t cross, int32_t mainSpan, int32_t crossSpan); 123 LayoutConstraintF CreateChildConstraint(float mainSize, float crossSize, 124 const RefPtr<GridLayoutProperty>& gridLayoutProperty, int32_t crossStart, int32_t crossSpan) const; 125 void ModifyCurrentOffsetWhenReachEnd(float mainSize, LayoutWrapper* layoutWrapper); 126 void InitialItemsCrossSize( 127 const RefPtr<GridLayoutProperty>& layoutProperty, const SizeF& frameSize, int32_t childrenCount); 128 bool IsIndexInMatrix(int32_t index, int32_t& startLine); 129 void UpdateGridLayoutInfo(LayoutWrapper* layoutWrapper, float mainSize); 130 virtual void GetTargetIndexInfoWithBenchMark( 131 LayoutWrapper* layoutWrapper, bool isTargetBackward, int32_t targetIndex); 132 133 void UpdateOffsetOnVirtualKeyboardHeightChange(LayoutWrapper* layoutWrapper, float mainSize); 134 void AdaptToChildMainSize(LayoutWrapper* layoutWrapper, RefPtr<GridLayoutProperty>& gridLayoutProperty, 135 float mainSize, SizeF idealSize, bool matchChildren); 136 void UpdateOffsetOnHeightChangeDuringAnimation(LayoutWrapper* layoutWrapper, float mainSize); 137 138 int32_t GetStartingItem(LayoutWrapper* layoutWrapper, int32_t currentIndex); 139 140 OffsetF CalculateLargeItemOffset( 141 OffsetF currOffset, int32_t itemIndex, int32_t currLineIndex, int32_t currentCrossIndex); 142 bool NeedAdjust(const RefPtr<GridItemLayoutProperty>& itemLayoutWrapper); 143 virtual void AdjustRowColSpan( 144 const RefPtr<LayoutWrapper>& itemLayoutWrapper, LayoutWrapper* layoutWrapper, int32_t itemIndex); 145 void LargeItemNextLineHeight(int32_t currentLineIndex, LayoutWrapper* layoutWrapper); 146 void LargeItemForwardLineHeight(int32_t currentLineIndex, LayoutWrapper* LayoutWrapper); 147 int32_t CalculateLineIndexForLargeItem(std::map<int32_t, std::map<int32_t, int32_t>>::iterator gridMatrixIter, 148 int32_t currentIndex, int32_t lineIndex, LayoutWrapper* layoutWrapper); 149 void CalculateLineHeightForLargeItem(int32_t lineIndex, int32_t currentLineIndex, 150 std::map<int32_t, std::map<int32_t, int32_t>>::iterator gridMatrixIter, LayoutWrapper* layoutWrapper); 151 void ScrollToIndexStart(LayoutWrapper* layoutWrapper, int32_t targetIndex); 152 void ScrollToIndexAuto(LayoutWrapper* layoutWrapper, float mainSize, int32_t targetIndex); 153 bool IsScrollToEndLine() const; 154 bool IsEndLineInScreenWithGap(int32_t targetLine, float totalViewHeight, float mainSize) const; 155 void UpdateCurrentOffsetForJumpTo(float mainSize); 156 void SupplyAllData2ZeroIndex(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 157 158 void FillCacheLineAtEnd(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 159 float FillNewCacheLineBackward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper, int32_t currentLine); 160 int32_t MeasureCachedChild(const SizeF& frameSize, int32_t itemIndex, LayoutWrapper* layoutWrapper, 161 const RefPtr<LayoutWrapper>& childLayoutWrapper); 162 163 void LayoutCachedItem(LayoutWrapper* layoutWrapper, int32_t cacheCount); 164 void LayoutBackwardCachedLine(LayoutWrapper* layoutWrapper, int32_t cacheCount); 165 void LayoutForwardCachedLine(LayoutWrapper* layoutWrapper, int32_t cacheCount); 166 void CreateCachedChildConstraint(LayoutWrapper* layoutWrapper, float mainSize, float crossSize); 167 168 static bool PredictBuildItem(const RefPtr<FrameNode>& host, int32_t itemIdx, const GridPredictLayoutParam& param); 169 static void SyncGeometry(RefPtr<LayoutWrapper>& wrapper); 170 void CompleteItemCrossPosition(LayoutWrapper* layoutWrapper, std::map<int32_t, int32_t> items); 171 /** 172 * @brief Updates the main line during ReloadToStartIndex based on the new crossCount_. 173 * 174 * @param startIdx index of the first GridItem in viewport 175 */ 176 virtual void UpdateMainLineOnReload(int32_t startIdx); 177 178 // get [resetFromStart,resetFromUpdate] 179 std::pair<bool, bool> GetResetMode(LayoutWrapper* layoutWrapper, int32_t updateIdx); 180 181 void CheckReset(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 182 183 bool CheckLastLineItemFullyShowed(LayoutWrapper* layoutWrapper); 184 185 void ResetOffsetWhenHeightChanged(); 186 187 bool IsIrregularLine(int32_t lineIndex) const override; 188 189 void MergeRemainingLines(std::map<int32_t, std::map<int32_t, int32_t>> matrix, int32_t forwardLines); 190 191 bool SkipLargeLineHeightLines(float mainSize); 192 193 protected: 194 uint32_t crossCount_ = 0; 195 uint32_t mainCount_ = 0; 196 int32_t currentItemRowSpan_ = 0; 197 int32_t currentItemColSpan_ = 0; 198 int32_t currentItemRowStart_ = -1; 199 int32_t currentItemColStart_ = -1; 200 int32_t currentItemRowEnd_ = -1; 201 int32_t currentItemColEnd_ = -1; 202 float cellAveLength_ = -1.0f; 203 float mainGap_ = 0; 204 205 private: 206 int32_t currentMainLineIndex_ = 0; // it equals to row index in vertical grid 207 int32_t moveToEndLineIndex_ = -1; // place index in the last line when scroll to index after matrix 208 std::map<int32_t, float> itemsCrossSize_; // grid item's size in cross axis. 209 Axis axis_ = Axis::VERTICAL; 210 211 float crossGap_ = 0; 212 float crossPaddingOffset_ = 0; 213 int32_t lastCross_ = 0; 214 bool isChildrenUpdated_ = false; 215 216 bool expandSafeArea_ = false; 217 bool canOverScroll_ = false; 218 bool enableSkipping_ = true; // enables skipping lines on a large offset change. 219 GridLayoutInfo scrollGridLayoutInfo_; 220 221 // Map structure: [index, crossPosition], store cross position of each item. 222 std::map<int32_t, float> itemsCrossPosition_; 223 int32_t scrollSource_ = SCROLL_FROM_NONE; 224 OffsetF childFrameOffset_; 225 std::list<GridPreloadItem> predictBuildList_; 226 LayoutConstraintF cachedChildConstraint_; 227 228 ACE_DISALLOW_COPY_AND_MOVE(GridScrollLayoutAlgorithm); 229 }; 230 231 } // namespace OHOS::Ace::NG 232 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_SCROLL_GRID_SCROLL_LAYOUT_ALGORITHM_H 233