1 /*
2  * Copyright (c) 2020-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 /**
17  * @addtogroup UI_Components
18  * @{
19  *
20  * @brief Defines UI components such as buttons, texts, images, lists, and progress bars.
21  *
22  * @since 1.0
23  * @version 1.0
24  */
25 
26 /**
27  * @file ui_list.h
28  *
29  * @brief Declares a scrollable list in the vertical or horizontal direction. * This scrollable list can be used with
30  *        the adapter {@link AbstractAdapter} to implement scrolling, inertial scrolling, automatic alignment, and
31  *        invoking of a callback when a child view at the preset position is selected as this list scrolls. It is used
32  *        when there is a large number of child views with a fixed format.
33  *
34  * @since 1.0
35  * @version 1.0
36  */
37 
38 #ifndef GRAPHIC_LITE_UI_LIST_H
39 #define GRAPHIC_LITE_UI_LIST_H
40 
41 #include "components/abstract_adapter.h"
42 #include "components/ui_abstract_scroll.h"
43 #include "dock/focus_manager.h"
44 #include "dock/vibrator_manager.h"
45 #include "gfx_utils/list.h"
46 
47 namespace OHOS {
48 /**
49  * @brief Represents a listener that contains a callback to be invoked when the scroll state changes or when a new child
50  *        view is selected at the preset position as this list scrolls. The scroll state can be {@link
51  *        SCROLL_STATE_STOP} or {@link SCROLL_STATE_MOVE}.
52  * @since 1.0
53  * @version 1.0
54  */
55 class ListScrollListener : public HeapBase {
56 public:
57     /**
58      * @brief A constructor used to create a <b>ListScrollListener</b> instance with the default state
59      *        {@link SCROLL_STATE_STOP}.
60      * @since 1.0
61      * @version 1.0
62      */
ListScrollListener()63     ListScrollListener() : state_(SCROLL_STATE_STOP) {}
64 
65     /**
66      * @brief A destructor used to delete the <b>ListScrollListener</b> instance.
67      * @since 1.0
68      * @version 1.0
69      */
~ListScrollListener()70     virtual ~ListScrollListener() {}
71 
72     /**
73      * @brief Called when a scroll starts.
74      * @param index Indicates the index of the child view being selected at the preset position. This parameter should
75      *              be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
76      * @param view Indicates the child view being selected at the preset position. This parameter should be set to
77      *             <b>NULL</b> if no child view is selected or no position is preset.
78      * @since 1.0
79      * @version 1.0
80      */
OnScrollStart(int16_t index,UIView * view)81     virtual void OnScrollStart(int16_t index, UIView* view) {}
82 
83     /**
84      * @brief Called when a scroll ends.
85      *
86      * @param index Indicates the index of the child view being selected at the preset position. This parameter should
87      *              be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
88      * @param view Indicates the child view being selected at the preset position. This parameter should be set to
89      *             <b>NULL</b> if no child view is selected or no position is preset.
90      * @since 1.0
91      * @version 1.0
92      *
93      */
OnScrollEnd(int16_t index,UIView * view)94     virtual void OnScrollEnd(int16_t index, UIView* view) {}
95 
96     /**
97      * @brief Called when move to the top of scroll.
98      *
99      * @param index Indicates the index of the child view being selected at the preset position. This parameter should
100      *              be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
101      * @param view Indicates the child view being selected at the preset position. This parameter should be set to
102      *             <b>NULL</b> if no child view is selected or no position is preset.
103      * @since 8
104      * @version 8
105      *
106      */
OnScrollTop(int16_t index,UIView * view)107     virtual void OnScrollTop(int16_t index, UIView* view) {}
108 
109     /**
110      * @brief Called when move to the bottom of scroll.
111      *
112      * @param index Indicates the index of the child view being selected at the preset position. This parameter should
113      *              be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
114      * @param view Indicates the child view being selected at the preset position. This parameter should be set to
115      *             <b>NULL</b> if no child view is selected or no position is preset.
116      * @since 8
117      * @version 8
118      *
119      */
OnScrollBottom(int16_t index,UIView * view)120     virtual void OnScrollBottom(int16_t index, UIView* view) {}
121 
122     /**
123      * @brief Called when a new child view is selected at the preset position as this list scrolls. For details about
124      * how to set the position, see {@link SetSelectPosition}.
125      *
126      * @param index Indicates the index of the child view being selected at the preset position. This parameter should
127      *              be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
128      * @param view Indicates the child view being selected at the preset position. This parameter should be set to
129      *             <b>NULL</b> if no child view is selected or no position is preset.
130      * @since 1.0
131      * @version 1.0
132      *
133      */
OnItemSelected(int16_t index,UIView * view)134     virtual void OnItemSelected(int16_t index, UIView* view) {}
135 
136     /**
137      * @brief Obtains the scroll state of this list.
138      *
139      * @return Returns the scroll state, either {@link SCROLL_STATE_STOP} or {@link SCROLL_STATE_MOVE}.
140      * @since 1.0
141      * @version 1.0
142      */
GetScrollState()143     uint8_t GetScrollState() const
144     {
145         return state_;
146     }
147 
SetScrollState(uint8_t state)148     void SetScrollState(uint8_t state)
149     {
150         state_ = state;
151     }
152 
153     static constexpr uint8_t SCROLL_STATE_STOP = 0;
154     static constexpr uint8_t SCROLL_STATE_MOVE = 1;
155 
156 private:
157     friend class UIList;
158     uint8_t state_;
159 };
160 
161 /**
162  * @brief Represents a scrollable list which is used with the adapter {@link AbstractAdapter} to implement scrolling,
163  *        inertial scrolling, automatic alignment, and invoking of a callback when a child view is selected at the
164  *        preset position as this list scrolls.
165  *
166  * You need to override {@link AbstractAdapter} to implement functions for setting and saving data, obtaining data
167  * quantity, and creating child views. <b>UIList</b> is used when there is a large number of child views with a fixed
168  * format. This list automatically reclaims the child views removed out of the current view as it scrolls so that as
169  * many as child views can be displayed with a lower memory consumption.
170  *
171  * @since 1.0
172  * @version 1.0
173  */
174 class UIList : public UIAbstractScroll {
175 public:
176     /**
177      * @brief A constructor used to create a <b>UIList</b> instance in the vertical direction.
178      * @since 1.0
179      * @version 1.0
180      */
181     UIList();
182 
183     /**
184      * @brief A constructor used to create a <b>UIList</b> instance in the specified direction.
185      *
186      * @param direction Indicates the <b>UIList</b> direction, either {@link HORIZONTAL} or {@link VERTICAL}.
187      * @since 1.0
188      * @version 1.0
189      */
190     explicit UIList(uint8_t direction);
191 
192     /**
193      * @brief A destructor used to delete the <b>UIList</b> instance.
194      * @since 1.0
195      * @version 1.0
196      */
197     virtual ~UIList();
198 
199     /**
200      * @brief Obtains the view type.
201      * @return Returns the view type, as defined in {@link UIViewType}.
202      * @since 1.0
203      * @version 1.0
204      */
GetViewType()205     UIViewType GetViewType() const override
206     {
207         return UI_LIST;
208     }
209 
210     bool OnDragEvent(const DragEvent& event) override;
211 
212     bool OnDragEndEvent(const DragEvent& event) override;
213 
214     bool OnPressEvent(const PressEvent& event) override;
215 
216 #if ENABLE_ROTATE_INPUT
217     bool OnRotateStartEvent(const RotateEvent& event) override;
218 
219     bool OnRotateEndEvent(const RotateEvent& event) override;
220 #endif
221 
222     /**
223      * @brief Sets the adapter for this list. The content of this list is initialized when the adapter is set.
224      *
225      * @param adapter Indicates the adapter to set. For details, see {@link AbstractAdapter}.
226      * @since 1.0
227      * @version 1.0
228      */
229     void SetAdapter(AbstractAdapter* adapter);
230 
231     /**
232      * @brief Moves the position of all child views.
233      *
234      * @param offsetX Indicates the offset distance by which a child view is moved on the x-axis.
235      * @param offsetY Indicates the offset distance by which a child view is moved on the y-axis.
236      * @since 1.0
237      * @version 1.0
238      */
239     void MoveChildByOffset(int16_t x, int16_t y) override;
240 
241     /**
242      * @brief Scrolls to change the index of the first row or column of the current view.
243      *
244      * @param index Indicates the new index of the first row or column of the current view.
245      * @since 1.0
246      * @version 1.0
247      */
248     void ScrollTo(uint16_t index);
249 
250     /**
251      * @brief Scrolls the content in this list.
252      *
253      * @param distance Indicates the distance by which the content is scrolled.
254      * @since 1.0
255      * @version 1.0
256      */
257     void ScrollBy(int16_t distance);
258 
259     /**
260      * @brief Sets the start index for this list.
261      *
262      * @param index Indicates the start index to set. The default value is <b>0</b>.
263      * @since 1.0
264      * @version 1.0
265      *
266      */
SetStartIndex(uint16_t index)267     void SetStartIndex(uint16_t index)
268     {
269         startIndex_ = index;
270     }
271 
272     /**
273      * @brief Obtains the start index of this list. The default value is <b>0</b>.
274      *
275      * @return Returns the start index.
276      * @since 1.0
277      * @version 1.0
278      */
GetStartIndex()279     uint16_t GetStartIndex() const
280     {
281         return startIndex_;
282     }
283 
284     /**
285      * @brief Sets the loop state for this list, in which a loop scroll is possible since the top and bottom of the list
286      *        are connected together.
287      *
288      * @param state Indicates the loop state to set.
289      * @since 1.0
290      * @version 1.0
291      */
SetLoopState(bool state)292     void SetLoopState(bool state)
293     {
294         isLoopList_ = state;
295     }
296 
297     /**
298      * @brief Checks whether this list is in a loop state.
299      *
300      * @return Returns if the list is in the loop state; returns <b>false</b> if the list is in the common state.
301      * @since 1.0
302      * @version 1.0
303      */
GetLoopState()304     bool GetLoopState() const
305     {
306         return isLoopList_;
307     }
308 
309     /**
310      * @brief Sets the position where a child view is selected as this list scrolls.
311      *
312      * When a child view is selected at the specified position, the callback {@link ListScrollListener} is invoked.
313      * You can implement the zoom-in and color-change effects in the callback.
314      *
315      * @param position Indicates the position to set. The default value is <b>0</b>, indicating that no position is
316      *                 set.
317      * @since 1.0
318      * @version 1.0
319      */
SetSelectPosition(uint16_t position)320     void SetSelectPosition(uint16_t position)
321     {
322         selectPosition_ = position;
323     }
324 
325     /**
326      * @brief Obtains the child view being selected at the preset position.
327      *
328      * @return Returns the child view if available; returns <b>NULL</b> if no child view is selected or no position is
329      *         set.
330      * @since 1.0
331      * @version 1.0
332      */
333     UIView* GetSelectView();
334 
335     /**
336      * @brief Sets the listener that contains a callback to be invoked when a child view is selected as this list
337      *        scrolls.
338      *
339      * @param scrollListener Indicates the listener to set.
340      * @since 1.0
341      * @version 1.0
342      */
SetScrollStateListener(ListScrollListener * scrollListener)343     void SetScrollStateListener(ListScrollListener* scrollListener)
344     {
345         scrollListener_ = scrollListener;
346     }
347 
348     /**
349      * @brief Refreshes this list. The number of child views in the current view is fixed and the positions of those
350      *        reserved child views as this list scrolls remain unchanged.
351      * @since 1.0
352      * @version 1.0
353      */
354     void RefreshList();
355 
356     /**
357      * @brief Sets the automatic alignment state for this list. When a scroll stops, a child view is selected and its
358      *        position is automatically aligned with the preset position.
359      *
360      * @param state Indicates the automatic alignment state. <b>true</b> indicates this state is enabled, and
361      *              <b>false</b> indicates the opposite case.
362      * @since 1.0
363      * @version 1.0
364      */
EnableAutoAlign(bool state)365     void EnableAutoAlign(bool state)
366     {
367         autoAlign_ = state;
368     }
369 
370     /**
371      * @brief
372      * 设置自动对齐动画时长,单位为毫秒,默认为100毫秒。该功能依赖EnableAutoAlign()方法,自动对齐设置为true情况下才生效。
373      *
374      * @param value 自动对齐动画时长,0表示无动画。
375      * @since 3.0
376      * @version 3.0
377      */
SetAutoAlignTime(uint16_t time)378     void SetAutoAlignTime(uint16_t time)
379     {
380         alignTime_ = time;
381     }
382 
383     /**
384      * @brief Sets the automatic alignment mode for this list when auto align state is enabled.
385      *
386      * @param dragBack mode of alignment.
387      *        true means list item will move back when its position crosses the line of select
388      *        position partly (but not all of it).
389      *        false means list item will move front when its position crosses the line of select
390      *        position (no matter how many it crosses).
391      *
392      * @since 3.0
393      * @version 3.0
394      */
EnableCrossDragBack(bool dragBack)395     void EnableCrossDragBack(bool dragBack)
396     {
397         dragBack_ = dragBack;
398     }
399 
400     /**
401      * @brief 获取自动对齐动画时长。
402      *
403      * @return 自动对齐动画时长。
404      * @since 3.0
405      * @version 3.0
406      */
GetAutoAlignTime()407     uint16_t GetAutoAlignTime() const
408     {
409         return alignTime_;
410     }
411 
412     void SetXScrollBarVisible(bool visible);
413 
414     void SetYScrollBarVisible(bool visible);
415 
416     void RemoveAll() override;
417 
418     static constexpr int8_t NULL_SELECT_INDEX = -1;
419 
420     UIView* onSelectedView_;
421 
422 protected:
423     static constexpr int16_t RECALCULATE_DRAG_DISTANCE = 10;
424     static constexpr int16_t RECALCULATE_DRAG_TIMES = 10;
425     static constexpr int16_t DEFAULT_ALIGN_TIMES = 100;
426     void StopAnimator() override;
427     bool DragXInner(int16_t distance) override;
428     bool DragYInner(int16_t distance) override;
429 
430 private:
431     friend class UIPicker;
432     friend class Recycle;
433     class Recycle : public HeapBase {
434     public:
Recycle(UIList * list)435         explicit Recycle(UIList* list) : adapter_(nullptr), listView_(list), hasInitialiszed_(false) {}
436         virtual ~Recycle();
437         void InitRecycle();
438         UIView* GetView(int16_t index);
SetAdapter(AbstractAdapter * adapter)439         void SetAdapter(AbstractAdapter* adapter)
440         {
441             hasInitialiszed_ = false;
442             adapter_ = adapter;
443         }
444 
HasInitialiszed()445         bool HasInitialiszed()
446         {
447             return hasInitialiszed_;
448         }
449 
AddScrapView(UIView * view)450         void AddScrapView(UIView* view)
451         {
452             scrapView_.PushBack(view);
453         }
454 
GetAdapterItemCount()455         uint16_t GetAdapterItemCount()
456         {
457             return (adapter_ == nullptr) ? 0 : adapter_->GetCount();
458         }
459 
ClearScrapView()460         void ClearScrapView()
461         {
462             scrapView_.Clear();
463         }
464 
465         Rect32 GetAdapterItemsReletiveRect();
466         void MoveAdapterItemsRelativeRect(int16_t x, int16_t y);
467         void MeasureAdapterRelativeRect();
468 
469     private:
470         friend class UIList;
471         void FillActiveView();
472 
473         List<UIView*> scrapView_;
474         AbstractAdapter* adapter_;
475         UIList* listView_;
476         Rect32 adapterRelativeRect_;
477         bool hasInitialiszed_;
478     };
479 
480     void PushBack(UIView* view);
481     void PopItem(UIView* view);
482     void PushFront(UIView* view);
483     void SetHead(UIView* view);
484     bool MoveChildStep(int16_t distance);
485     bool MoveChildStepVertical(int16_t distance);
486     bool MoveChildStepHorizontal(int16_t distance);
487     uint16_t GetIndexInc(uint16_t index);
488     uint16_t GetIndexDec(uint16_t index);
489 
490     bool MoveOffset(int16_t x, int16_t y);
491     void UpdateScrollBar();
492     bool IsNeedReCalculateDragEnd();
493     bool ReCalculateDragEnd();
494     void CalculateReboundDistance(int16_t& dragDistanceX, int16_t& dragDistanceY) override;
495     void FixDistance(int16_t& distanceX, int16_t& distanceY) override;
496     void FixHorDistance(int16_t& distanceX);
497     void FixVerDistance(int16_t& distanceY);
498     bool isLoopList_;
499     bool isReCalculateDragEnd_;
500     bool autoAlign_;
501     uint16_t alignTime_;
502     uint16_t startIndex_;
503     uint16_t topIndex_;
504     uint16_t bottomIndex_;
505     uint16_t selectPosition_;
506     int16_t onSelectedIndex_;
507     Recycle recycle_;
508     ListScrollListener* scrollListener_;
509 };
510 } // namespace OHOS
511 #endif // GRAPHIC_LITE_UI_LIST_H
512