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