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_V2_WATER_FLOW_RENDER_WATER_FLOW_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_WATER_FLOW_RENDER_WATER_FLOW_H
18 
19 #include <map>
20 #include <set>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "core/components/common/layout/constants.h"
25 #include "core/components/common/properties/scroll_bar.h"
26 #include "core/components/positioned/positioned_component.h"
27 #include "core/components/scroll/scroll_bar_theme.h"
28 #include "core/components/scroll/scrollable.h"
29 #include "core/components_v2/water_flow/render_water_flow_item.h"
30 #include "core/components_v2/water_flow/water_flow_component.h"
31 #include "core/components_v2/water_flow/water_flow_item_generator.h"
32 #include "core/pipeline/base/render_node.h"
33 
34 namespace OHOS::Ace::V2 {
35 enum class SCROLLABLE : uint32_t {
36     NO_SCROLL = 0,
37     VERTICAL,
38     HORIZONTAL,
39 };
40 
41 enum class WaterFlowEvents : uint32_t {
42     NONE = 0,
43     REACH_START,
44     REACH_END,
45 };
46 
47 using FlowStyle = struct {
48     double mainPos = 0.0;   // position of main side
49     double crossPos = 0.0;  // position of cross side
50     double mainSize = 0.0;  // size of main side
51     double crossSize = 0.0; // size of corss side
52 };
53 
54 using ItemConstraintSize = struct {
55     double minCrossSize = 0.0; // min cross Size
56     double maxCrossSize = 0.0; // max cross Size
57     double minMainSize = 0.0;  // min main Size
58     double maxMainSize = 0.0;  // max cross Size
59 };
60 
61 class RenderWaterFlow : public RenderNode {
62     DECLARE_ACE_TYPE(RenderWaterFlow, RenderNode);
63 
64 public:
65     using BuildChildByIndex = std::function<bool(size_t)>;
66     using DeleteChildByIndex = std::function<void(size_t)>;
67     using UpdateTotalCount = std::function<size_t()>;
68 
69     RenderWaterFlow() = default;
70     ~RenderWaterFlow() override;
71 
72     static RefPtr<RenderNode> Create();
73 
74     void Update(const RefPtr<Component>& component) override;
75     void PerformLayout() override;
76     void OnPredictLayout(int64_t deadline) override;
77 
SetBuildChildByIndex(BuildChildByIndex func)78     inline void SetBuildChildByIndex(BuildChildByIndex func)
79     {
80         buildChildByIndex_ = std::move(func);
81     }
82 
SetDeleteChildByIndex(DeleteChildByIndex func)83     inline void SetDeleteChildByIndex(DeleteChildByIndex func)
84     {
85         deleteChildByIndex_ = std::move(func);
86     }
87 
SetGetTotalCount(UpdateTotalCount func)88     inline void SetGetTotalCount(UpdateTotalCount func)
89     {
90         getTotalCount_ = std::move(func);
91     }
92 
93     void AddChildByIndex(size_t index, const RefPtr<RenderNode>& renderNode);
RemoveChildByIndex(size_t index)94     inline void RemoveChildByIndex(size_t index)
95     {
96         auto item = items_.find(index);
97         if (item != items_.end()) {
98             RemoveChild(item->second);
99             items_.erase(item);
100         }
101     }
102     void ClearLayout(size_t index, bool clearAll = false);
103     void ClearItems(size_t index = 0);
104     void OnDataSourceUpdated(size_t index);
105 
SetTotalCount(size_t totalCount)106     inline void SetTotalCount(size_t totalCount)
107     {
108         if (totalCount_ != totalCount) {
109             totalCount_ = totalCount;
110         }
111     }
112 
113     double GetEstimatedHeight();
114     void ScrollToIndex(int32_t index);
115 
GetAxis()116     inline Axis GetAxis() const
117     {
118         return useScrollable_ == SCROLLABLE::VERTICAL ? Axis::VERTICAL : Axis::HORIZONTAL;
119     }
120 
121     bool IsChildrenTouchEnable() override;
GetLastOffset()122     inline Offset GetLastOffset() const
123     {
124         return useScrollable_ == SCROLLABLE::VERTICAL ? Offset(0.0, lastOffset_) : Offset(lastOffset_, 0.0);
125     }
126 
127     void HandleAxisEvent(const AxisEvent& event) override;
128     bool IsAxisScrollable(AxisDirection direction) override;
129     WeakPtr<RenderNode> CheckAxisNode() override;
130     void OnChildAdded(const RefPtr<RenderNode>& renderNode) override;
131     bool IsUseOnly() override;
132     void RequestWaterFlowFooter();
RegisterItemGenerator(WeakPtr<WaterFlowItemGenerator> && waterFlowItemGenerator)133     inline void RegisterItemGenerator(WeakPtr<WaterFlowItemGenerator>&& waterFlowItemGenerator)
134     {
135         itemGenerator_ = std::move(waterFlowItemGenerator);
136     }
137 
GetColumnsArgs()138     const std::string& GetColumnsArgs() const
139     {
140         return colsArgs_;
141     }
142 
GetRowsArgs()143     const std::string& GetRowsArgs() const
144     {
145         return rowsArgs_;
146     }
147 
GetColumnsGap()148     const Dimension& GetColumnsGap() const
149     {
150         return userColGap_;
151     }
152 
GetRowsGap()153     const Dimension& GetRowsGap() const
154     {
155         return userRowGap_;
156     }
157 
GetlayoutDirection()158     FlexDirection GetlayoutDirection() const
159     {
160         return direction_;
161     }
162 
GetItemConstraintSize()163     ItemConstraintSize GetItemConstraintSize() const
164     {
165         return itemConstraintSize_;
166     }
167 
168 protected:
169     RefPtr<ScrollBarProxy> scrollBarProxy_;
170     RefPtr<ScrollBar> scrollBar_;
171     int32_t scrollBarOpacity_ = 0;
172     SCROLLABLE useScrollable_ = SCROLLABLE::NO_SCROLL;
173     double lastOffset_ = 0.0;
174 
175 private:
176     void HandleScrollEvent();
177     LayoutParam MakeInnerLayoutParam(size_t itemIndex);
178 
179     // Sets child position, the mainAxis does not contain the offset.
180     void SetChildPosition(const RefPtr<RenderNode>& child, size_t itemIndex);
181     void CreateScrollable();
182     void OnTouchTestHit(
183         const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) override;
184     bool UpdateScrollPosition(double offset, int32_t source);
185     void CallGap();
186     void CallItemConstraintSize();
187     void InitialFlowProp();
188     void GetFlowSize();
189     void SupplyItems(size_t startIndex, double targetPos);
190     void LayoutItems(std::set<size_t>& items);
191     void GetFooterSize(double mainSize, double crossSize);
192     void LayoutFooter();
193     void SetFooterPosition();
194     void UpdateCacheItems();
195     std::set<size_t> GetShowItems();
196     size_t GetLastSupplyedIndex();
197     size_t GetNextSupplyedIndex();
198     double GetLastSupplyedMainSize();
199     Offset GetLastMainBlankPos();
200     size_t GetLastMainBlankCross();
201     Offset GetLastMainPos();
202     void ClearFlowMatrix(size_t index, bool clearAll = false);
203     void ClearItemsByCrossIndex(size_t index, bool clearAll = false);
204     void InitMainSideEndPos();
205     void UpdateMainSideEndPos();
206     double GetCrossEndPos(size_t crossIndex);
207     FlowStyle ConstraintItemSize(FlowStyle item, size_t crossIndex);
208     static RefPtr<RenderWaterFlowItem> GetFlowItemByChild(const RefPtr<RenderNode>& child);
209     double GetMainSize(const RefPtr<RenderNode>& item) const;
210     double GetCrossSize(const RefPtr<RenderNode>& item) const;
211     bool CheckReachHead();
212     bool CheckReachTail();
213     void AdjustViewPort();
214     double GetTailPos();
215     double GetTargetPos();
216     double GetCacheTargetPos() const;
217     void SetTargetPos(double targetPos);
218     void DealCache();
219     void DeleteItems(size_t index);
220     bool GetItemMainCrossIndex(int32_t index, int32_t& mainIndex, int32_t& crossIndex);
221     void InitScrollBar();
222     void InitScrollBarProxy();
223     void DoJump(double position, int32_t source);
224     void SetScrollBarCallback();
225     void AnimateToPos(const double& position, int32_t duration, const RefPtr<Curve>& curve);
226     void OutputMatrix();
227     void RemoveAllChild();
228     bool NeedPredictLayout();
229     static std::string PreParseArgs(const std::string& args);
230 
231     std::unordered_map<size_t, RefPtr<RenderNode>> items_;
232     std::set<size_t> cacheItems_;
233 
234     RefPtr<Scrollable> scrollable_;
235     bool reachHead_ = false;
236     bool reachTail_ = false;
237     int32_t targetIndex_ = -1; // target item index of supply items (for scrollToIndex)
238     double viewportStartPos_ = 0.0;
239     bool lastReachHead_ = false;
240     bool lastReachTail_ = false;
241     double mainSize_ = 0.0;  // size ot main side
242     double crossSize_ = 0.0; // size of cross side
243     double crossGap_ = 0.0;  // gap of cross side
244     double mainGap_ = 0.0;   // gap of main side
245     size_t crossCount_ = 0;  // splits count of cross side
246     size_t totalCount_ = 0;  // ElementProxyHost::TotalCount()
247     size_t totalCountBack_ = 0;
248 
249     // used for scrollbar
250     double scrollBarExtent_ = 0.0;
251     double mainScrollExtent_ = 0.0;
252     double estimateHeight_ = 0.0;
253 
254     RefPtr<Animator> animator_;
255     RefPtr<V2::WaterFlowComponent> component_;
256     WeakPtr<WaterFlowItemGenerator> itemGenerator_;
257     BuildChildByIndex buildChildByIndex_;
258     DeleteChildByIndex deleteChildByIndex_;
259     UpdateTotalCount getTotalCount_;
260 
261     double cacheSize_ = 0.0;
262     bool updateFlag_ = false;
263     FlexDirection direction_ = FlexDirection::COLUMN;
264     ItemConstraintSize itemConstraintSize_ = { 0.0, 0.0, 0.0, 0.0 };
265     double mainMaxConstraintSize_ = 0.0;
266     double dVPStartPosBackup_ = -1;
267     std::string colsArgs_;
268     std::string rowsArgs_;
269 
270     Dimension userColGap_ = 0.0_px;
271     Dimension userRowGap_ = 0.0_px;
272     DisplayMode displayMode_ = DisplayMode::OFF;
273     // Map structure: [Index - FlowStyle]
274     std::map<size_t, FlowStyle> flowMatrix_;
275     // Map structure: [crossIndex,  main side endPos of per splits]
276     std::vector<double> mainSideEndPos_;
277     // Map structure: [crossIndex, cross side size of per splits]
278     std::vector<double> crossSideSize_;
279     // Map structure: [crossIndex, item index]
280     std::vector<std::vector<size_t>> itemsByCrossIndex_;
281 
282     std::map<WaterFlowEvents, bool> waterflowEventFlags_;
283     RefPtr<RenderNode> footer_;
284     Size footerMaxSize_;
285 
286     ACE_DISALLOW_COPY_AND_MOVE(RenderWaterFlow);
287 };
288 } // namespace OHOS::Ace::V2
289 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_WATER_FLOW_RENDER_WATER_FLOW_H
290