1 /*
2  * Copyright (c) 2023 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_WATERFLOW_WATER_FLOW_LAYOUT_INFO_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_H
18 
19 #include <cstdint>
20 #include <map>
21 #include <optional>
22 #include <sstream>
23 
24 #include "core/components_ng/pattern/waterflow/layout/water_flow_layout_algorithm_base.h"
25 #include "core/components_ng/pattern/waterflow/layout/water_flow_layout_info_base.h"
26 #include "core/components_ng/pattern/waterflow/water_flow_sections.h"
27 
28 namespace OHOS::Ace::NG {
29 struct FlowItemIndex {
30     int32_t crossIndex = 0;
31     int32_t lastItemIndex = 0;
32 };
33 
34 struct FlowItemPosition {
35     int32_t crossIndex = 0;
36     float startMainPos = 0;
37 };
38 
39 class WaterFlowLayoutInfo : public WaterFlowLayoutInfoBase {
40     DECLARE_ACE_TYPE(WaterFlowLayoutInfo, WaterFlowLayoutInfoBase);
41 
42 public:
43     WaterFlowLayoutInfo() = default;
44     ~WaterFlowLayoutInfo() override = default;
45 
Mode()46     WaterFlowLayoutMode Mode() const override
47     {
48         return WaterFlowLayoutMode::TOP_DOWN;
49     }
Offset()50     float Offset() const override
51     {
52         return currentOffset_;
53     }
FirstIdx()54     int32_t FirstIdx() const override
55     {
56         return firstIndex_;
57     }
58     int32_t GetCrossIndex(int32_t itemIndex) const override;
59 
60     void UpdateStartIndex() override;
61     int32_t GetEndIndexByOffset(float offset) const;
62     float GetMaxMainHeight() const;
63     float GetContentHeight() const override;
64     float EstimateContentHeight() const;
65     bool IsAllCrossReachEnd(float mainSize) const;
66 
67     /**
68      * @brief Get the next available cross index to place a new item.
69      *
70      * @param segmentIdx index of the WaterFlow segment.
71      * @return FlowItemIndex
72      */
73     FlowItemIndex GetCrossIndexForNextItem(int32_t segmentIdx) const;
74 
75     float GetMainHeight(int32_t crossIndex, int32_t itemIndex) const;
76     float GetStartMainPos(int32_t crossIndex, int32_t itemIndex) const;
77     void Reset() override;
78     void Reset(int32_t resetFrom);
79     int32_t GetCrossCount() const override;
80     int32_t GetMainCount() const override;
81     void ClearCacheAfterIndex(int32_t currentIndex);
82 
83     bool ReachStart(float prevOffset, bool firstLayout) const override;
84     bool ReachEnd(float prevOffset, bool firstLayout) const override;
85     bool OutOfBounds() const override;
86 
87     OverScrollOffset GetOverScrolledDelta(float delta) const override;
88     float CalcOverScroll(float mainSize, float delta) const override;
89 
90     void UpdateOffset(float delta) override;
91 
CalibrateOffset()92     float CalibrateOffset() override
93     {
94         /* offset always accurate */
95         return 0.0f;
96     }
97 
98     float CalcTargetPosition(int32_t idx, int32_t crossIdx) const override;
99 
GetDelta(float prevPos)100     float GetDelta(float prevPos) const override
101     {
102         return prevPos - currentOffset_;
103     }
104 
CurrentPos()105     float CurrentPos() const override
106     {
107         return currentOffset_;
108     }
TopFinalPos()109     float TopFinalPos() const override
110     {
111         return 0.0f;
112     };
BottomFinalPos(float viewHeight)113     float BottomFinalPos(float viewHeight) const override
114     {
115         float endOffset = viewHeight - GetContentHeight();
116         return Negative(endOffset) ? endOffset : 0.0f;
117     };
118 
119     float JumpToTargetAlign(const std::pair<float, float>& item) const;
120     void JumpTo(const std::pair<float, float>& item);
121 
IsMisaligned()122     bool IsMisaligned() const override
123     {
124         return false;
125     }
126 
127     /**
128      * @brief Init data structures based on new WaterFlow Sections.
129      *
130      * @param sections vector of Sections info.
131      * @param start index of the first modified section, all sections prior to [start] remain the same.
132      */
133     void InitSegments(const std::vector<WaterFlowSections::Section>& sections, int32_t start) override;
134 
135     // set up startPos of next segment after initializing margins_
136     void PrepareSegmentStartPos();
137 
138     void ResetSegmentStartPos();
139 
140     /**
141      * @brief Record a new FlowItem in ItemMap and update related data structures.
142      *
143      * @param idx index of FlowItem.
144      * @param pos position of this FlowItem
145      * @param height FlowItem height.
146      */
147     void RecordItem(int32_t idx, const FlowItemPosition& pos, float height);
148 
149     /**
150      * @brief FInd the first item inside viewport in log_n time using endPosReverseMap_.
151      *
152      * @return index of the starting item.
153      */
154     int32_t FastSolveStartIndex() const;
155 
156     /**
157      * @brief Find the last item inside viewport in log_n time using itemInfos_.
158      *
159      * @param mainSize main-axis length of viewport.
160      * @return index of the item.
161      */
162     int32_t FastSolveEndIndex(float mainSize) const;
163 
164     /**
165      * @brief Calculate and set the start position of next segment after filling the tail item of the current segment.
166      *
167      * @param itemIdx index of the current flow item.
168      */
169     void SetNextSegmentStartPos(int32_t itemIdx);
170 
171     /**
172      * @brief Update member variables after measure.
173      *
174      * @param mainSize waterFlow length on the main axis.
175      * @param overScroll whether overScroll is allowed. Might adjust offset if not.
176      */
177     void Sync(float mainSize, bool overScroll);
178 
179     /**
180      * @brief Obtain index of last item recorded in Original layout.
181      * @note in segmented layout, use itemInfos_ instead.
182      */
183     int32_t GetLastItem() const;
184 
NotifyDataChange(int32_t index,int32_t count)185     void NotifyDataChange(int32_t index, int32_t count) override {};
InitSegmentsForKeepPositionMode(const std::vector<WaterFlowSections::Section> & sections,const std::vector<WaterFlowSections::Section> & prevSections,int32_t start)186     void InitSegmentsForKeepPositionMode(const std::vector<WaterFlowSections::Section>& sections,
187         const std::vector<WaterFlowSections::Section>& prevSections, int32_t start) override
188     {}
189 
190     int32_t childrenCount_ = 0;
191 
192     float currentOffset_ = 0.0f;
193     // 0.0f until itemEnd_ is true
194     float maxHeight_ = 0.0f;
195 
196     // first index for onScrollIndex
197     int32_t firstIndex_ = 0;
198 
199     // Map structure: [crossIndex, [index, {mainOffset, itemMainSize}]],
200     using ItemMap = std::map<int32_t, std::map<int32_t, std::pair<float, float>>>;
201 
202     std::vector<ItemMap> items_ { ItemMap() };
203 
204     struct ItemInfo;
205     // quick access to FlowItem by index
206     std::vector<ItemInfo> itemInfos_;
207 
208     /**
209      * @brief pair = { item bottom position, item index }.
210      * A strictly increasing array of item endPos to speed up startIndex solver.
211      * Only add to this map when a new endPos is greater than the last one in array.
212      */
213     std::vector<std::pair<float, int32_t>> endPosArray_;
214 
215     // Stores the start position of each segment.
216     std::vector<float> segmentStartPos_ = { 0.0f };
217 
218     void PrintWaterFlowItems() const;
219 };
220 
221 struct WaterFlowLayoutInfo::ItemInfo {
222     ItemInfo() = default;
ItemInfoItemInfo223     ItemInfo(int32_t cross, float offset, float size) : crossIdx(cross), mainOffset(offset), mainSize(size) {}
224     bool operator==(const ItemInfo& other) const
225     {
226         return crossIdx == other.crossIdx && mainOffset == other.mainOffset && mainSize == other.mainSize;
227     }
228 
229     int32_t crossIdx = 0;
230     float mainOffset = 0.0f;
231     float mainSize = 0.0f;
232 };
233 
234 } // namespace OHOS::Ace::NG
235 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_H
236