• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_LIST_LAYOUT_MANAGER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_LAYOUT_MANAGER_H
18 
19 #include <map>
20 
21 #include "base/geometry/dimension.h"
22 #include "base/geometry/offset.h"
23 #include "base/memory/ace_type.h"
24 #include "base/utils/system_properties.h"
25 #include "core/event/touch_event.h"
26 #include "core/pipeline/base/component.h"
27 #include "core/pipeline/base/render_node.h"
28 
29 namespace OHOS::Ace {
30 
31 const double DEFAULT_SCALE = 1.0;
32 const double TV_ITEM_SCALE = 1.05;
33 const double HALF_ITEM_SIZE = 0.5;
34 const int32_t LIST_PARAM_INVAID = -2;
35 const int32_t LIST_LENGTH_INFINITE = -1;
36 const double INFINITE_POSITION = 0.0;
37 
38 // first bool mean if vertical, second bool mean if reverse
39 // false, false --> RIGHT
40 // false, true --> LEFT
41 // true, false --> DOWN
42 // true, true ---> UP
43 // This map will adapter the Grid FlexDirection with Key Direction.
44 extern const std::map<bool, std::map<FlexDirection, std::map<bool, std::map<bool, KeyDirection>>>> DIRECTION_MAP;
45 
46 class LayoutManager : public virtual AceType {
47     DECLARE_ACE_TYPE(LayoutManager, AceType);
48 
49 public:
50     LayoutManager() = default;
51     ~LayoutManager() override = default;
52 
53     virtual void Update() = 0;
54 
55     virtual void PerformLayout() = 0;
56 
57     virtual void RefreshLayout() = 0;
58 
59     virtual void CalculateCachedRange(int32_t viewBegin, int32_t viewEnd, int32_t cachedCount, int32_t& cachedBegin,
60         int32_t& cachedEnd) = 0;
61 
62     virtual void RequestMoreItemsIfNeeded(int32_t viewBegin, int32_t viewEnd) = 0;
63 
64     virtual int32_t focusMove(KeyDirection key) = 0;
65 
CalculateFocusIndexPosition()66     virtual void CalculateFocusIndexPosition() {}
67 
MoveItemToViewPort(double position)68     virtual void MoveItemToViewPort(double position) {}
69 
MoveItemGroupToViewPort(double position,double size)70     virtual void MoveItemGroupToViewPort(double position, double size) {}
71 
LayoutToItem(int32_t toIndex)72     virtual void LayoutToItem(int32_t toIndex) {}
73 
LayoutToPosition(double position)74     virtual void LayoutToPosition(double position) {}
75 
LayoutMore(double incDistance)76     virtual void LayoutMore(double incDistance) {}
77 
NotifyNeedRefresh()78     virtual void NotifyNeedRefresh() {}
79 
RequestNextFocus(bool vertical,bool reverse)80     int32_t RequestNextFocus(bool vertical, bool reverse)
81     {
82         KeyDirection key = DIRECTION_MAP.at(rightToLeft_).at(direction_).at(vertical).at(reverse);
83         int32_t index = focusMove(key);
84         LOGD("Focus move from %{public}d to %{public}d", focusIndex_, index);
85         if (index < 0) {
86             focusMove_ = focusIndex_;
87             return index;
88         }
89         focusMove_ = index;
90         focusIndex_ = index;
91         return focusMove_;
92     }
93 
ListItemFocused(int32_t focusIndex)94     void ListItemFocused(int32_t focusIndex)
95     {
96         focusIndex_ = focusIndex;
97         focusMove_ = focusIndex;
98     }
99 
MarkNeedRefresh()100     void MarkNeedRefresh()
101     {
102         needRefresh_ = true;
103         NotifyNeedRefresh();
104     }
105 
ResetLayoutRange(double head,double tail,Offset position,Size viewPort)106     void ResetLayoutRange(double head, double tail, Offset position, Size viewPort)
107     {
108         head_ = head;
109         tail_ = tail;
110         position_ = position;
111         viewPort_ = viewPort;
112     }
113 
GetPosition()114     const Offset& GetPosition() const
115     {
116         return position_;
117     }
118 
FlushChainAnimation()119     virtual double FlushChainAnimation()
120     {
121         return 0.0;
122     }
123 
IsRowReverse()124     bool IsRowReverse() const
125     {
126         return (rightToLeft_ && direction_ == FlexDirection::ROW)
127          || (!rightToLeft_ && direction_ == FlexDirection::ROW_REVERSE);
128     }
129 
IsColReverse()130     bool IsColReverse() const
131     {
132         return direction_ == FlexDirection::COLUMN_REVERSE;
133     }
134 
GetItemGrid(int32_t index)135     int32_t GetItemGrid(int32_t index) const
136     {
137         auto iter = itemGrid_.find(index);
138         if (iter == itemGrid_.end()) {
139             return 0;
140         }
141         return iter->second;
142     }
143 
CheckItemPosition(int32_t index)144     bool CheckItemPosition(int32_t index) const
145     {
146         return itemPosition_.find(index) != itemPosition_.end();
147     }
148 
GetItemAnimationValue(int32_t index)149     virtual double GetItemAnimationValue(int32_t index) const
150     {
151         return 0.0;
152     }
153 
GetItemPosition(int32_t index)154     double GetItemPosition(int32_t index) const
155     {
156         auto iter = itemPosition_.find(index);
157         if (iter == itemPosition_.end()) {
158             return 0.0;
159         }
160         return iter->second;
161     }
162 
GetChainInterval()163     double GetChainInterval() const
164     {
165         return enableChain_ ? chainInterval_ : 0.0;
166     }
167 
GetChainItemRange(int32_t index,double & start,double & end)168     void GetChainItemRange(int32_t index, double& start, double& end) const
169     {
170         if (!enableChain_) {
171             return;
172         }
173         start = GetItemPosition(index) - GetChainInterval() * HALF_ITEM_SIZE;
174         double nextStartPosition = GetItemPosition(index + 1);
175         if (!NearZero(nextStartPosition)) {
176             end = nextStartPosition - GetChainInterval() * HALF_ITEM_SIZE;
177         }
178     }
179 
GetIndexByPosition(double position)180     int32_t GetIndexByPosition(double position) const
181     {
182         int32_t index = 0;
183         double curPosition = 0.0;
184         for (const auto& item : itemPosition_) {
185             double correctedPosition =  item.second + GetItemAnimationValue(item.first);
186             if (NearEqual(correctedPosition, position)) {
187                 return item.first;
188             } else {
189                 if (NearEqual(curPosition, correctedPosition)) {
190                     continue;
191                 }
192                 curPosition = correctedPosition;
193                 if (correctedPosition < position) {
194                     index = item.first;
195                 } else {
196                     return index;
197                 }
198             }
199         }
200         return index;
201     }
202 
CalculateRepeatedIndex(int32_t cachedIndex)203     int32_t CalculateRepeatedIndex(int32_t cachedIndex)
204     {
205         int32_t repeatedIndex;
206         if (repeatedLength_ == LIST_LENGTH_INFINITE) {
207             repeatedIndex = ((cachedIndex - indexOffset_) > 0 ? (cachedIndex - indexOffset_) : 0);
208         } else {
209             if (cachedIndex < indexOffset_) {
210                 repeatedIndex = 0;
211             } else {
212                 if (cachedIndex > indexOffset_ + repeatedLength_) {
213                     repeatedIndex = repeatedLength_;
214                 } else {
215                     repeatedIndex = cachedIndex - indexOffset_;
216                 }
217             }
218         }
219         return repeatedIndex;
220     }
221 
GetExpandStatus(int32_t groupIndex)222     bool GetExpandStatus(int32_t groupIndex) const
223     {
224         auto iter = itemGroupsExpand_.find(groupIndex);
225         if (iter != itemGroupsExpand_.end()) {
226             return iter->second;
227         } else {
228             return expandAll_;
229         }
230     }
231 
GetItemGroupFocusIndex(int32_t groupIndex)232     int32_t GetItemGroupFocusIndex(int32_t groupIndex) const
233     {
234         auto iter = itemGroupsFocusIndex_.find(groupIndex);
235         if (iter != itemGroupsFocusIndex_.end()) {
236             return iter->second;
237         }
238         return 0;
239     }
240 
SetExpandAll(bool expandAll)241     void SetExpandAll(bool expandAll)
242     {
243         expandAll_ = expandAll;
244     }
245 
ClearItemGroupsExpand()246     void ClearItemGroupsExpand()
247     {
248         itemGroupsExpand_.clear();
249     }
250 
ClearItemPosition()251     void ClearItemPosition()
252     {
253         itemPosition_.clear();
254     }
255 
AddItemGroupExpand(int32_t index,bool expand)256     void AddItemGroupExpand(int32_t index, bool expand)
257     {
258         itemGroupsExpand_[index] = expand;
259     }
260 
AddItemGroupFocusIndex(int32_t index,int32_t groupFocusIndex)261     void AddItemGroupFocusIndex(int32_t index, int32_t groupFocusIndex)
262     {
263         itemGroupsFocusIndex_[index] = groupFocusIndex;
264     }
265 
GetFriction()266     double GetFriction() const
267     {
268         return friction_;
269     }
270 
SetFriction(double friction)271     void SetFriction(double friction)
272     {
273         friction_ = friction;
274     }
275 
GetSlipFactor()276     double GetSlipFactor() const
277     {
278         return slipFactor_;
279     }
280 
281 protected:
282     double head_ = 0.0;
283     double tail_ = 0.0;
284     double lastHead_ = 0.0;
285     double lastTail_ = 0.0;
286     int32_t focusMove_ = 0; // Record the focus move path.
287     int32_t focusIndex_ = 0; // Record the index of focus item.
288     Offset position_;
289     Size viewPort_;
290     bool needRefresh_ = false;
291     bool firstLayout_ = true;
292     Dimension itemExtent_;
293 
294     bool rightToLeft_ = false;
295     bool isVertical_ = false;
296     FlexDirection direction_ { FlexDirection::COLUMN };
297     FlexAlign crossAxisAlign_ { FlexAlign::STRETCH };
298     int32_t beginIndex_ = LIST_PARAM_INVAID;
299     int32_t endIndex_ = LIST_PARAM_INVAID;
300     int32_t length_ = 0;
301     int32_t repeatedLength_ = 0;
302     int32_t indexOffset_ = 0;
303 
304     std::map<int32_t, int32_t> itemGrid_;
305     std::map<int32_t, double> itemPosition_;
306     std::map<int32_t, bool> itemGroupsExpand_;
307     std::map<int32_t, int32_t> itemGroupsFocusIndex_;
308 
309     RefPtr<Animator> controller_;
310     std::vector<int32_t> needRemoveItems_;
311     std::map<int32_t, RefPtr<RenderNode>> newItems_;
312     bool isAnimating_ = false;
313     double friction_ = 1.0;
314     bool expandAll_ = false;
315     bool enableChain_ = false; // whether enables spring chain effect.
316     double chainInterval_ = 0.0;
317     int32_t itemCountOfPage_ = 0;
318     double slipFactor_ = 0.0;
319 };
320 
321 } // namespace OHOS::Ace
322 
323 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_LIST_LAYOUT_MANAGER_H
324