1 /*
2  * Copyright (c) 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_WATERFLOW_WATER_FLOW_LAYOUT_INFO_BASE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_BASE_H
18 
19 #include "base/memory/ace_type.h"
20 #include "base/utils/noncopyable.h"
21 #include "core/components/scroll/scroll_controller_base.h"
22 #include "core/components_ng/pattern/scrollable/scrollable.h"
23 #include "core/components_ng/pattern/waterflow/water_flow_sections.h"
24 #include "core/components_ng/property/measure_property.h"
25 
26 namespace OHOS::Ace::NG {
27 constexpr int32_t EMPTY_JUMP_INDEX = -2;
28 
29 enum class WaterFlowLayoutMode;
30 
31 class WaterFlowLayoutInfoBase : public AceType {
32     DECLARE_ACE_TYPE(WaterFlowLayoutInfoBase, AceType);
33 
34 public:
35     WaterFlowLayoutInfoBase() = default;
36     ~WaterFlowLayoutInfoBase() override = default;
37 
38     /* Factory method */
39     static RefPtr<WaterFlowLayoutInfoBase> Create(WaterFlowLayoutMode mode);
40 
41     /* PURE GETTERs */
42     virtual WaterFlowLayoutMode Mode() const = 0;
43     virtual float Offset() const = 0;     // total offset of content
44     virtual int32_t FirstIdx() const = 0; // for compatibility
45 
46     virtual void UpdateOffset(float delta) = 0;
47 
48     /**
49      * @brief try calibrating total offset to an accurate value.
50      *
51      * @return amount of adjustment to total offset of content
52      */
53     virtual float CalibrateOffset() = 0;
54 
55     /**
56      * @brief Get which cross-axis lane the item is in.
57      *
58      * @param itemIndex
59      * @return lane index
60      */
61     virtual int32_t GetCrossIndex(int32_t itemIndex) const = 0;
62 
63     // implementation of WaterFlowPattern::GetOverScrollOffset
64     // returns the portion of [delta] that's in overScroll range
65     virtual OverScrollOffset GetOverScrolledDelta(float delta) const = 0;
66 
67     /**
68      * @param mainSize of viewport.
69      * @param delta change in content offset.
70      * @return amount of overScroll (distance to edge) after applying delta.
71      */
72     virtual float CalcOverScroll(float mainSize, float delta) const = 0;
73 
74     /**
75      * @brief Check if WaterFlow just reached content top from the recent layout.
76      * For triggering events.
77      *
78      * @param prevPos previous layout position.
79      * @param firstLayout check this to emit ReachStart on the initial layout.
80      * @return true if current position just reached content top.
81      */
82     virtual bool ReachStart(float prevPos, bool firstLayout) const = 0;
83     /**
84      * @brief Check if WaterFlow just reached content bottom from the recent layout.
85      * For triggering events.
86      *
87      * @param prevPos previous layout position.
88      * @return true if current position just reached content bottom.
89      */
90     virtual bool ReachEnd(float prevPos, bool firstLayout) const = 0;
91 
92     virtual bool OutOfBounds() const = 0;
93 
94     /**
95      * @return total height of all recorded items.
96      */
97     virtual float GetContentHeight() const = 0;
98 
99     /**
100      * @brief Get target item's position in order to perform scrollTo animation.
101      *
102      * @param idx item's index.
103      * @param crossIdx item's cross-axis lane index.
104      * @return absolute position to scroll to.
105      */
106     virtual float CalcTargetPosition(int32_t idx, int32_t crossIdx) const = 0;
107 
108     /**
109      * @return change in position, comparing to [prevPos]
110      */
111     virtual float GetDelta(float prevPos) const = 0;
112 
113     virtual int32_t GetMainCount() const = 0;
114     virtual int32_t GetCrossCount() const = 0;
115 
116     /* ======== provide position info for spring effect animation ========= */
117     virtual float CurrentPos() const = 0;
118     /**
119      * @return final position to bounce back to after over-scrolling from top.
120      */
121     virtual float TopFinalPos() const = 0;
122     /**
123      * @param viewHeight height of the viewport.
124      * @return final position to bounce back to after over-scrolling from bottom.
125      */
126     virtual float BottomFinalPos(float viewHeight) const = 0;
127     /* ========================================== */
128 
129     virtual void Reset() = 0;
130 
131     // for compatibility
UpdateStartIndex()132     virtual void UpdateStartIndex() {};
133 
134     /**
135      * @brief Check if the layout is misaligned.
136      *
137      * If we jump and scroll back to top, the staring items might not be aligned with the top boundary.
138      * @return true if 1. any lane misaligned with top boundary.
139      *                 2. the first item is not in the first lane.
140      */
141     virtual bool IsMisaligned() const = 0;
142 
143     /**
144      * @brief Initialize variables based on incoming section data.
145      *
146      * @param sections section data.
147      * @param start first updated section.
148      */
149     virtual void InitSegments(const std::vector<WaterFlowSections::Section>& sections, int32_t start) = 0;
150 
151     /**
152      * @brief Get the Segment index of a FlowItem
153      *
154      * @param itemIdx
155      * @return segment index, guaranteed within range [0, total sections).
156      */
157     int32_t GetSegment(int32_t itemIdx) const;
158 
159     // convert FlowItem's index to children node index.
NodeIdx(int32_t idx)160     inline int32_t NodeIdx(int32_t idx) const
161     {
162         return idx + footerIndex_ + 1;
163     }
164 
165     /**
166      * @brief obtain true total number of FlowItems by filtering out the footer node.
167      */
ItemCnt(int32_t childrenCount)168     inline int32_t ItemCnt(int32_t childrenCount) const
169     {
170         return childrenCount - footerIndex_ - 1;
171     }
172 
173     /**
174      * @brief Initialize margin of each section, along with segmentStartPos_, which depends on margin_.
175      *
176      * @param sections vector of Sections info.
177      * @param scale for calculating margins in PX.
178      * @param percentWidth for calculating margins in PX.
179      */
180     void InitMargins(
181         const std::vector<WaterFlowSections::Section>& sections, const ScaleProperty& scale, float percentWidth);
182 
183     virtual void NotifyDataChange(int32_t index, int32_t count) = 0;
184     virtual void InitSegmentsForKeepPositionMode(const std::vector<WaterFlowSections::Section>& sections,
185         const std::vector<WaterFlowSections::Section>& prevSections, int32_t start) = 0;
186 
187     void UpdateDefaultCachedCount();
188 
189     bool itemStart_ = false;
190     /**
191      * @brief last item is partially in viewport.
192      * With footer, footer should be considered the last item.
193      */
194     bool itemEnd_ = false;
195     bool offsetEnd_ = false; // last item's bottom is in viewport
196     bool isDataValid_ = true;
197 
198     Axis axis_ = Axis::VERTICAL;
199 
200     int32_t jumpIndex_ = EMPTY_JUMP_INDEX;
201     ScrollAlign align_ = ScrollAlign::START;
202     std::optional<int32_t> targetIndex_;
203     std::optional<float> extraOffset_;
204 
205     int32_t startIndex_ = 0;
206     int32_t endIndex_ = -1;
207     int32_t footerIndex_ = -1;
208 
209     float lastMainSize_ = 0.0f;
210 
211     // store offset for distributed migration
212     float storedOffset_ = 0.0f;
213     float restoreOffset_ = 0.0f;
214 
215     // Stores the tail item index of each segment.
216     std::vector<int32_t> segmentTails_;
217     // K: item index; V: corresponding segment index
218     mutable std::unordered_map<int32_t, int32_t> segmentCache_;
219     // margin of each segment
220     std::vector<PaddingPropertyF> margins_;
221     // default cached count
222     int32_t defCachedCount_ = 1;
223 
224     ACE_DISALLOW_COPY_AND_MOVE(WaterFlowLayoutInfoBase);
225 };
226 
227 } // namespace OHOS::Ace::NG
228 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WATERFLOW_WATER_FLOW_LAYOUT_INFO_BASE_H
229