1 /* 2 * Copyright (c) 2021-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_V2_GRID_RENDER_GRID_SCROLL_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_GRID_RENDER_GRID_SCROLL_H 18 19 #include <list> 20 #include <map> 21 #include <set> 22 #include <unordered_map> 23 #include <utility> 24 25 #include "core/components/common/layout/constants.h" 26 #include "core/components/common/properties/scroll_bar.h" 27 #include "core/components/grid_layout/grid_layout_component.h" 28 #include "core/components/grid_layout/render_grid_layout.h" 29 #include "core/components/refresh/render_refresh_target.h" 30 #include "core/components/scroll/scroll_bar_theme.h" 31 #include "core/components/scroll/scrollable.h" 32 #include "core/components_v2/grid/grid_event.h" 33 #include "core/pipeline/base/render_node.h" 34 35 namespace OHOS::Ace::V2 { 36 37 class RenderGridScroll : public RenderGridLayout, public RenderRefreshTarget { 38 DECLARE_ACE_TYPE(RenderGridScroll, RenderGridLayout, RenderRefreshTarget); 39 40 public: 41 using BuildChildByIndex = std::function<bool(int32_t)>; 42 using GetChildSpanByIndex = std::function<bool(int32_t, bool, int32_t&, int32_t&, int32_t&, int32_t&)>; 43 using DeleteChildByIndex = std::function<void(int32_t)>; 44 using GetItemTotalCountFunc = std::function<int32_t(void)>; 45 using OnScrolledFunc = std::function<void(std::shared_ptr<GridEventInfo>&)>; 46 47 RenderGridScroll() = default; 48 ~RenderGridScroll() override; 49 50 static RefPtr<RenderNode> Create(); 51 52 void Update(const RefPtr<Component>& component) override; 53 void PerformLayout() override; 54 void OnPredictLayout(int64_t deadline) override; 55 GetChildren()56 const std::list<RefPtr<RenderNode>>& GetChildren() const override 57 { 58 return childrenInRect_; 59 } 60 SetBuildChildByIndex(BuildChildByIndex func)61 void SetBuildChildByIndex(BuildChildByIndex func) 62 { 63 buildChildByIndex_ = std::move(func); 64 } 65 SetDeleteChildByIndex(DeleteChildByIndex func)66 void SetDeleteChildByIndex(DeleteChildByIndex func) 67 { 68 deleteChildByIndex_ = std::move(func); 69 } 70 SetGetChildSpanByIndex(GetChildSpanByIndex func)71 void SetGetChildSpanByIndex(GetChildSpanByIndex func) 72 { 73 getChildSpanByIndex_ = std::move(func); 74 } 75 SetGetItemTotalCount(GetItemTotalCountFunc func)76 void SetGetItemTotalCount(GetItemTotalCountFunc func) 77 { 78 getItemTotalCount_ = std::move(func); 79 } 80 GetItemTotalCount()81 int32_t GetItemTotalCount() 82 { 83 if (getItemTotalCount_) { 84 return getItemTotalCount_(); 85 } 86 return 0; 87 } 88 89 void AddChildByIndex(int32_t index, const RefPtr<RenderNode>& renderNode); RemoveChildByIndex(int32_t index)90 void RemoveChildByIndex(int32_t index) 91 { 92 auto item = items_.find(index); 93 if (item != items_.end()) { 94 RemoveChild(item->second); 95 items_.erase(item); 96 } 97 } 98 void ClearLayout(bool needReservedPlace = false); 99 void ClearItems(); 100 void OnDataSourceUpdated(int32_t index); 101 SetTotalCount(int32_t totalCount)102 void SetTotalCount(int32_t totalCount) 103 { 104 if (totalCount_ == totalCount) { 105 return; 106 } 107 if (totalCount_ < totalCount) { 108 reachTail_ = false; 109 } 110 totalCount_ = totalCount; 111 totalCountFlag_ = true; 112 } 113 114 double GetEstimatedHeight(); 115 // Used in GridPositionController 116 void ScrollToIndex(int32_t index); 117 bool AnimateTo(const Dimension& position, float duration, const RefPtr<Curve>& curve); 118 void BuildItemsBackwardByRange(int32_t startItemIdx, int32_t endItemIdx); 119 void BuildItemsForwardByRange(int32_t startItemIdx, int32_t endItemIdx); 120 double CalculateScrollLength(int32_t index); 121 Offset CurrentOffset(); 122 void ScrollToEdge(ScrollEdgeType edgeType, bool smooth); 123 void ScrollPage(bool reverse, bool smooth); GetAxis()124 Axis GetAxis() const 125 { 126 return useScrollable_ == SCROLLABLE::VERTICAL ? Axis::VERTICAL : Axis::HORIZONTAL; 127 } 128 129 void OnPaintFinish() override; 130 131 bool IsChildrenTouchEnable() override; 132 GetCachedSize()133 size_t GetCachedSize() const 134 { 135 return endShowItemIndex_ - startShowItemIndex_; 136 } 137 GetLastOffset()138 Offset GetLastOffset() const 139 { 140 return useScrollable_ == SCROLLABLE::VERTICAL ? Offset(0, lastOffset_) : Offset(lastOffset_, 0); 141 } 142 143 void HandleAxisEvent(const AxisEvent& event) override; 144 145 bool IsAxisScrollable(AxisDirection direction) override; 146 147 // distribute 148 std::string ProvideRestoreInfo() override; 149 150 protected: 151 int32_t GetItemMainIndex(const RefPtr<RenderNode>& child, bool isMain) const; 152 void SetMainSize(Size& dst, const Size& src); 153 void SizeChangeOffset(double newWindowHeight); 154 double GetSize(const Size& src, bool isMain = true) const; 155 void GetNextGrid(int32_t& curMain, int32_t& curCross) const override; 156 void GetPreviousGrid(int32_t& curMain, int32_t& curCross); 157 LayoutParam MakeInnerLayoutParam( 158 int32_t row, int32_t col, int32_t rowSpan, int32_t colSpan, bool itemIsPercentUnit = false) const override; 159 bool CheckGridPlaced(int32_t index, int32_t row, int32_t col, int32_t& rowSpan, int32_t& colSpan) override; 160 161 // Sets child position, the mainAxis does not contain the offset. 162 void SetChildPosition( 163 const RefPtr<RenderNode>& child, int32_t row, int32_t col, int32_t rowSpan, int32_t colSpan) override; 164 165 void CreateScrollable(); 166 void LayoutChild(const RefPtr<RenderNode>& child, int32_t row, int32_t col, int32_t rowSpan, int32_t colSpan, 167 bool needPosition = true); 168 void OnTouchTestHit( 169 const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) override; 170 bool UpdateScrollPosition(double offset, int32_t source); 171 void CheckJumpToIndex(double offset); 172 void RecordLocation(); 173 174 void InitialGridProp() override; 175 void CalculateViewPort(); 176 double BuildLazyGridLayout(int32_t index, double sizeNeed); 177 bool GetGridSize(); 178 void BuildGrid(std::vector<double>& rows, std::vector<double>& cols); 179 double CalculateBlankOfEnd(); 180 double SupplyItems(int32_t mainIndex, int32_t itemIndex = -1, bool needPosition = true); 181 bool Rank(int32_t mainIndex, int32_t itemIndex = -1); 182 bool GetItemPropsByIndex( 183 int32_t index, int32_t& itemMain, int32_t& itemCross, int32_t& itemMainSpan, int32_t& itemCrossSpan); 184 185 void DealCache(int32_t start, int32_t end); 186 void DeleteItems(int32_t index, bool isTail); 187 188 int32_t GetItemMainIndex(int32_t index); 189 190 bool NeedUpdate(const RefPtr<Component>& component); 191 192 void CalculateWholeSize(double drawLength); 193 194 void InitScrollBar(); 195 void InitScrollBarProxy(); 196 197 void DoJump(double position, int32_t source); 198 199 int32_t GetStartingItem(int32_t first); 200 void LoadForward(); 201 GetCurrentOffset()202 double GetCurrentOffset() const 203 { 204 return estimatePos_ + startMainPos_ + currentOffset_ + firstItemOffset_; 205 } 206 207 void SetScrollBarCallback(); 208 209 int32_t GetIndexByPosition(double position) const; 210 211 void OnScrolled(int32_t scrolled) const; 212 213 // distribute 214 void ApplyRestoreInfo(); 215 216 enum class SCROLLABLE : uint32_t { 217 NO_SCROLL = 0, 218 VERTICAL, 219 HORIZONTAL, 220 }; 221 222 SCROLLABLE useScrollable_ = SCROLLABLE::NO_SCROLL; 223 224 std::map<int32_t, Size> metaData_; 225 std::unordered_map<int32_t, RefPtr<RenderNode>> items_; 226 std::set<int32_t> showItem_; 227 std::set<int32_t> inCache_; 228 std::set<int32_t> inRankCache_; 229 std::list<RefPtr<RenderNode>> childrenInRect_; 230 231 RefPtr<Scrollable> scrollable_; 232 bool reachHead_ = false; 233 bool reachTail_ = false; 234 std::optional<bool> firstLineToBottom_; 235 bool needCalculateViewPort_ = false; 236 double startMainPos_ = 0.0; 237 double currentOffset_ = 0.0; 238 std::optional<double> textFieldOffset_; 239 double animateDelta_ = 0.0; 240 double lastOffset_ = 0.0; 241 double firstItemOffset_ = 0.0; 242 int32_t startIndex_ = 0; 243 int32_t endIndex_ = -1; 244 245 int32_t startShowItemIndex_ = 0; 246 int32_t endShowItemIndex_ = -1; 247 248 int32_t startRankItemIndex_ = 0; 249 int32_t currentItemIndex_ = 0; 250 251 double* mainSize_ = &rowSize_; 252 double* crossSize_ = &colSize_; 253 int32_t* mainCount_ = &rowCount_; 254 int32_t* crossCount_ = &colCount_; 255 int32_t totalCount_ = 0; 256 double* crossGap_ = &colGap_; 257 double* mainGap_ = &rowGap_; 258 259 // used for scrollbar 260 int32_t scrollBarOpacity_ = 0; 261 double estimateHeight_ = 0.0; 262 double estimatePos_ = 0.0; 263 double estimateAverageHeight_ = 0.0; 264 bool totalCountFlag_ = false; 265 bool animatorJumpFlag_ = false; 266 Color scrollBarColor_; 267 268 RefPtr<ScrollBarProxy> scrollBarProxy_; 269 RefPtr<ScrollBar> scrollBar_; 270 RefPtr<Animator> animator_; 271 RefPtr<GridLayoutComponent> component_; 272 BuildChildByIndex buildChildByIndex_; 273 DeleteChildByIndex deleteChildByIndex_; 274 GetChildSpanByIndex getChildSpanByIndex_; 275 GetItemTotalCountFunc getItemTotalCount_; 276 OnScrolledFunc scrolledEventFun_; 277 278 int32_t lastFirstIndex_ = -1; 279 int32_t loadingIndex_ = -1; 280 int32_t cacheCount_ = 1; 281 }; 282 283 } // namespace OHOS::Ace::V2 284 285 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_GRID_RENDER_GRID_SCROLL_H