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/layout/layout_wrapper.h" 20 #include "core/components_ng/pattern/grid/grid_item_layout_property.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 #include "core/components_ng/pattern/grid/grid_layout_property.h" 24 #include "core/components_ng/pattern/scrollable/scrollable_properties.h" 25 26 namespace OHOS::Ace::NG { 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 38 static void PrintGridMatrix( 39 const std::map<int32_t, std::map<int32_t, int32_t>>& gridMatrix, const std::map<int32_t, float>& positions); 40 static void PrintLineHeightMap(const std::map<int32_t, float>& lineHeightMap); SetCanOverScroll(bool canOverScroll)41 void SetCanOverScroll(bool canOverScroll) 42 { 43 canOverScroll_ = canOverScroll; 44 } 45 SetScrollSource(int32_t scrollSource)46 void SetScrollSource(int32_t scrollSource) 47 { 48 scrollSource_ = scrollSource; 49 } 50 51 /** 52 * @brief Set enableSkipping_ parameter. When skip is enabled, the algorithm would skip measuring intermediate items 53 * when the offset change is large (larger than the whole viewport). 54 * 55 * @param skip 56 */ SetLineSkipping(bool skip)57 void SetLineSkipping(bool skip) 58 { 59 enableSkipping_ = skip; 60 } 61 GetScrollGridLayoutInfo()62 GridLayoutInfo GetScrollGridLayoutInfo() 63 { 64 return scrollGridLayoutInfo_; 65 } 66 67 template<class T> DeleteItemsOutOfScope(std::map<int32_t,T> & map,int32_t startLineIndex,int32_t endLineIndex)68 void DeleteItemsOutOfScope(std::map<int32_t, T>& map, int32_t startLineIndex, int32_t endLineIndex) 69 { 70 auto iter = map.begin(); 71 while (iter != map.end()) { 72 if (iter->first < startLineIndex || iter->first > endLineIndex) { 73 iter = map.erase(iter); 74 } else { 75 ++iter; 76 } 77 } 78 } 79 80 protected: 81 void SkipForwardLines(float mainSize, LayoutWrapper* layoutWrapper); 82 void SkipBackwardLines(float mainSize, LayoutWrapper* layoutWrapper); 83 84 private: 85 void FillGridViewportAndMeasureChildren(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 86 void ReloadToStartIndex(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 87 float MeasureRecordedItems(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 88 bool UseCurrentLines(float mainSize, float crossSize, LayoutWrapper* layoutWrapper, float& mainLength); 89 virtual void SkipLargeOffset(float mainSize, LayoutWrapper* layoutWrapper); 90 91 // fill start of viewport 92 bool FillBlankAtStart(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 93 float FillNewLineForward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper); 94 void AddForwardLines(int32_t currentIndex, float crossSize, float mainSize, LayoutWrapper* layoutWrapper); 95 void UpdateMatrixForAddedItems(); 96 97 // fill end of viewport 98 void FillBlankAtEnd(float mainSize, float crossSize, LayoutWrapper* layoutWrapper, float& mainLength); 99 float FillNewLineBackward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper, bool reverse); 100 101 // Measure grid item which not exist in grid matrix already, need to place it and save to grid matrix. 102 int32_t MeasureNewChild(const SizeF& frameSize, int32_t itemIndex, LayoutWrapper* layoutWrapper, 103 const RefPtr<LayoutWrapper>& childLayoutWrapper, bool reverse); 104 // Measure grid item which exist in grid matrix already, needn't to place it again. 105 int32_t MeasureChildPlaced(const SizeF& frameSize, int32_t itemIndex, int32_t crossStart, 106 LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& childLayoutWrapper); 107 void MeasureChild(LayoutWrapper* layoutWrapper, const SizeF& frameSize, 108 const RefPtr<LayoutWrapper>& childLayoutWrapper, int32_t crossStart, int32_t crossSpan); 109 110 // Compote position of grid item in cross axis. 111 float ComputeItemCrossPosition(LayoutWrapper* layoutWrapper, int32_t crossStart) const; 112 virtual void LargeItemLineHeight(const RefPtr<LayoutWrapper>& itemWrapper, bool& hasNormalItem); 113 // Find next valid cell when current is not valid. 114 bool GetNextGrid(int32_t& curMain, int32_t& curCross, bool reverse) const; 115 // Find a valid cell to place grid item and save to grid matrix. 116 bool CheckGridPlaced(int32_t index, int32_t main, int32_t cross, int32_t mainSpan, int32_t crossSpan); 117 LayoutConstraintF CreateChildConstraint(float mainSize, float crossSize, 118 const RefPtr<GridLayoutProperty>& gridLayoutProperty, int32_t crossStart, int32_t crossSpan) const; 119 void ModifyCurrentOffsetWhenReachEnd(float mainSize, LayoutWrapper* layoutWrapper); 120 void InitialItemsCrossSize( 121 const RefPtr<GridLayoutProperty>& layoutProperty, const SizeF& frameSize, int32_t childrenCount); 122 bool IsIndexInMatrix(int32_t index, int32_t& startLine); 123 void UpdateGridLayoutInfo(LayoutWrapper* layoutWrapper, float mainSize); 124 virtual void GetTargetIndexInfoWithBenchMark( 125 LayoutWrapper* layoutWrapper, bool isTargetBackward, int32_t targetIndex); 126 127 void UpdateOffsetOnVirtualKeyboardHeightChange(LayoutWrapper* layoutWrapper, float mainSize); 128 void AdaptToChildMainSize(LayoutWrapper* layoutWrapper, RefPtr<GridLayoutProperty>& gridLayoutProperty, 129 float mainSize, const SizeF& idealSize); 130 void UpdateOffsetOnHeightChangeDuringAnimation(LayoutWrapper* layoutWrapper, float mainSize); 131 132 int32_t GetStartingItem(LayoutWrapper* layoutWrapper, int32_t currentIndex); 133 134 OffsetF CalculateLargeItemOffset( 135 OffsetF currOffset, int32_t itemIndex, int32_t currLineIndex, int32_t currentCrossIndex); 136 bool NeedAdjust(const RefPtr<GridItemLayoutProperty>& itemLayoutWrapper); 137 virtual void AdjustRowColSpan( 138 const RefPtr<LayoutWrapper>& itemLayoutWrapper, LayoutWrapper* layoutWrapper, int32_t itemIndex); 139 void LargeItemNextLineHeight(int32_t currentLineIndex, LayoutWrapper* layoutWrapper); 140 void LargeItemForwardLineHeight(int32_t currentLineIndex, LayoutWrapper* LayoutWrapper); 141 int32_t CalculateLineIndexForLargeItem(std::map<int32_t, std::map<int32_t, int32_t>>::iterator gridMatrixIter, 142 int32_t currentIndex, int32_t lineIndex, LayoutWrapper* layoutWrapper); 143 void CalculateLineHeightForLargeItem(int32_t lineIndex, int32_t currentLineIndex, 144 std::map<int32_t, std::map<int32_t, int32_t>>::iterator gridMatrixIter, LayoutWrapper* layoutWrapper); 145 void ScrollToIndexStart(LayoutWrapper* layoutWrapper, int32_t targetIndex); 146 void ScrollToIndexAuto(LayoutWrapper* layoutWrapper, float mainSize, int32_t targetIndex); 147 bool IsScrollToEndLine() const; 148 bool IsEndLineInScreenWithGap(int32_t targetLine, float totalViewHeight, float mainSize) const; 149 void UpdateCurrentOffsetForJumpTo(float mainSize); 150 void SkipRegularLines(bool forward); 151 void SupplyAllData2ZeroIndex(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 152 153 void FillCacheLineAtEnd(float mainSize, float crossSize, LayoutWrapper* layoutWrapper); 154 float FillNewCacheLineBackward(float crossSize, float mainSize, LayoutWrapper* layoutWrapper); 155 int32_t MeasureCachedChild(const SizeF& frameSize, int32_t itemIndex, LayoutWrapper* layoutWrapper, 156 const RefPtr<LayoutWrapper>& childLayoutWrapper); 157 158 void LayoutCachedItem(LayoutWrapper* layoutWrapper, int32_t cacheCount); 159 void LayoutBackwardCachedLine(LayoutWrapper* layoutWrapper, int32_t cacheCount); 160 void LayoutForwardCachedLine(LayoutWrapper* layoutWrapper, int32_t cacheCount); 161 void CreateCachedChildConstraint(LayoutWrapper* layoutWrapper, float mainSize, float crossSize); 162 163 static void PostIdleTask(RefPtr<FrameNode> frameNode, const GridPredictLayoutParam& param); 164 static bool PredictBuildItem(RefPtr<LayoutWrapper> wrapper, const LayoutConstraintF& constraint); 165 static void SyncGeometry(RefPtr<LayoutWrapper>& wrapper); 166 void CompeleteItemCrossPosition(LayoutWrapper* layoutWrapper, std::map<int32_t, int32_t> items); 167 /** 168 * @brief Updates the main line during ReloadToStartIndex based on the new crossCount_. 169 * 170 * @param startIdx index of the first GridItem in viewport 171 */ 172 virtual void UpdateMainLineOnReload(int32_t startIdx); 173 174 protected: 175 uint32_t crossCount_ = 0; 176 uint32_t mainCount_ = 0; 177 int32_t currentItemRowSpan_ = 0; 178 int32_t currentItemColSpan_ = 0; 179 int32_t currentItemRowStart_ = -1; 180 int32_t currentItemColStart_ = -1; 181 int32_t currentItemRowEnd_ = -1; 182 int32_t currentItemColEnd_ = -1; 183 float cellAveLength_ = -1.0f; 184 185 private: 186 int32_t currentMainLineIndex_ = 0; // it equals to row index in vertical grid 187 int32_t moveToEndLineIndex_ = -1; // place index in the last line when scroll to index after matrix 188 std::map<int32_t, float> itemsCrossSize_; // grid item's size in cross axis. 189 Axis axis_ = Axis::VERTICAL; 190 191 float mainGap_ = 0; 192 float crossGap_ = 0; 193 float crossPaddingOffset_ = 0; 194 int32_t lastCross_ = 0; 195 bool isChildrenUpdated_ = false; 196 bool canOverScroll_ = false; 197 bool enableSkipping_ = true; // enables skipping lines on a large offset change. 198 GridLayoutInfo scrollGridLayoutInfo_; 199 200 // Map structure: [index, crossPosition], store cross position of each item. 201 std::map<int32_t, float> itemsCrossPosition_; 202 int32_t scrollSource_ = SCROLL_FROM_NONE; 203 OffsetF childFrameOffset_; 204 std::list<int32_t> predictBuildList_; 205 LayoutConstraintF cachedChildConstraint_; 206 207 ACE_DISALLOW_COPY_AND_MOVE(GridScrollLayoutAlgorithm); 208 }; 209 210 } // namespace OHOS::Ace::NG 211 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_SCROLL_GRID_SCROLL_LAYOUT_ALGORITHM_H 212