/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @addtogroup UI_Components
* @{
*
* @brief Defines UI components such as buttons, texts, images, lists, and progress bars.
*
* @since 1.0
* @version 1.0
*/
/**
* @file ui_list.h
*
* @brief Declares a scrollable list in the vertical or horizontal direction. * This scrollable list can be used with
* the adapter {@link AbstractAdapter} to implement scrolling, inertial scrolling, automatic alignment, and
* invoking of a callback when a child view at the preset position is selected as this list scrolls. It is used
* when there is a large number of child views with a fixed format.
*
* @since 1.0
* @version 1.0
*/
#ifndef GRAPHIC_LITE_UI_LIST_H
#define GRAPHIC_LITE_UI_LIST_H
#include "components/abstract_adapter.h"
#include "components/ui_abstract_scroll.h"
#include "dock/focus_manager.h"
#include "dock/vibrator_manager.h"
#include "gfx_utils/list.h"
namespace OHOS {
/**
* @brief Represents a listener that contains a callback to be invoked when the scroll state changes or when a new child
* view is selected at the preset position as this list scrolls. The scroll state can be {@link
* SCROLL_STATE_STOP} or {@link SCROLL_STATE_MOVE}.
* @since 1.0
* @version 1.0
*/
class ListScrollListener : public HeapBase {
public:
/**
* @brief A constructor used to create a ListScrollListener instance with the default state
* {@link SCROLL_STATE_STOP}.
* @since 1.0
* @version 1.0
*/
ListScrollListener() : state_(SCROLL_STATE_STOP) {}
/**
* @brief A destructor used to delete the ListScrollListener instance.
* @since 1.0
* @version 1.0
*/
virtual ~ListScrollListener() {}
/**
* @brief Called when a scroll starts.
* @param index Indicates the index of the child view being selected at the preset position. This parameter should
* be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
* @param view Indicates the child view being selected at the preset position. This parameter should be set to
* NULL if no child view is selected or no position is preset.
* @since 1.0
* @version 1.0
*/
virtual void OnScrollStart(int16_t index, UIView* view) {}
/**
* @brief Called when a scroll ends.
*
* @param index Indicates the index of the child view being selected at the preset position. This parameter should
* be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
* @param view Indicates the child view being selected at the preset position. This parameter should be set to
* NULL if no child view is selected or no position is preset.
* @since 1.0
* @version 1.0
*
*/
virtual void OnScrollEnd(int16_t index, UIView* view) {}
/**
* @brief Called when move to the top of scroll.
*
* @param index Indicates the index of the child view being selected at the preset position. This parameter should
* be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
* @param view Indicates the child view being selected at the preset position. This parameter should be set to
* NULL if no child view is selected or no position is preset.
* @since 8
* @version 8
*
*/
virtual void OnScrollTop(int16_t index, UIView* view) {}
/**
* @brief Called when move to the bottom of scroll.
*
* @param index Indicates the index of the child view being selected at the preset position. This parameter should
* be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
* @param view Indicates the child view being selected at the preset position. This parameter should be set to
* NULL if no child view is selected or no position is preset.
* @since 8
* @version 8
*
*/
virtual void OnScrollBottom(int16_t index, UIView* view) {}
/**
* @brief Called when a new child view is selected at the preset position as this list scrolls. For details about
* how to set the position, see {@link SetSelectPosition}.
*
* @param index Indicates the index of the child view being selected at the preset position. This parameter should
* be set to {@link NULL_SELECT_INDEX} if no child view is selected or no position is preset.
* @param view Indicates the child view being selected at the preset position. This parameter should be set to
* NULL if no child view is selected or no position is preset.
* @since 1.0
* @version 1.0
*
*/
virtual void OnItemSelected(int16_t index, UIView* view) {}
/**
* @brief Obtains the scroll state of this list.
*
* @return Returns the scroll state, either {@link SCROLL_STATE_STOP} or {@link SCROLL_STATE_MOVE}.
* @since 1.0
* @version 1.0
*/
uint8_t GetScrollState() const
{
return state_;
}
void SetScrollState(uint8_t state)
{
state_ = state;
}
static constexpr uint8_t SCROLL_STATE_STOP = 0;
static constexpr uint8_t SCROLL_STATE_MOVE = 1;
private:
friend class UIList;
uint8_t state_;
};
/**
* @brief Represents a scrollable list which is used with the adapter {@link AbstractAdapter} to implement scrolling,
* inertial scrolling, automatic alignment, and invoking of a callback when a child view is selected at the
* preset position as this list scrolls.
*
* You need to override {@link AbstractAdapter} to implement functions for setting and saving data, obtaining data
* quantity, and creating child views. UIList is used when there is a large number of child views with a fixed
* format. This list automatically reclaims the child views removed out of the current view as it scrolls so that as
* many as child views can be displayed with a lower memory consumption.
*
* @since 1.0
* @version 1.0
*/
class UIList : public UIAbstractScroll {
public:
/**
* @brief A constructor used to create a UIList instance in the vertical direction.
* @since 1.0
* @version 1.0
*/
UIList();
/**
* @brief A constructor used to create a UIList instance in the specified direction.
*
* @param direction Indicates the UIList direction, either {@link HORIZONTAL} or {@link VERTICAL}.
* @since 1.0
* @version 1.0
*/
explicit UIList(uint8_t direction);
/**
* @brief A destructor used to delete the UIList instance.
* @since 1.0
* @version 1.0
*/
virtual ~UIList();
/**
* @brief Obtains the view type.
* @return Returns the view type, as defined in {@link UIViewType}.
* @since 1.0
* @version 1.0
*/
UIViewType GetViewType() const override
{
return UI_LIST;
}
bool OnDragEvent(const DragEvent& event) override;
bool OnDragEndEvent(const DragEvent& event) override;
bool OnPressEvent(const PressEvent& event) override;
#if ENABLE_ROTATE_INPUT
bool OnRotateStartEvent(const RotateEvent& event) override;
bool OnRotateEndEvent(const RotateEvent& event) override;
#endif
/**
* @brief Sets the adapter for this list. The content of this list is initialized when the adapter is set.
*
* @param adapter Indicates the adapter to set. For details, see {@link AbstractAdapter}.
* @since 1.0
* @version 1.0
*/
void SetAdapter(AbstractAdapter* adapter);
/**
* @brief Moves the position of all child views.
*
* @param offsetX Indicates the offset distance by which a child view is moved on the x-axis.
* @param offsetY Indicates the offset distance by which a child view is moved on the y-axis.
* @since 1.0
* @version 1.0
*/
void MoveChildByOffset(int16_t x, int16_t y) override;
/**
* @brief Scrolls to change the index of the first row or column of the current view.
*
* @param index Indicates the new index of the first row or column of the current view.
* @since 1.0
* @version 1.0
*/
void ScrollTo(uint16_t index);
/**
* @brief Scrolls the content in this list.
*
* @param distance Indicates the distance by which the content is scrolled.
* @since 1.0
* @version 1.0
*/
void ScrollBy(int16_t distance);
/**
* @brief Sets the start index for this list.
*
* @param index Indicates the start index to set. The default value is 0.
* @since 1.0
* @version 1.0
*
*/
void SetStartIndex(uint16_t index)
{
startIndex_ = index;
}
/**
* @brief Obtains the start index of this list. The default value is 0.
*
* @return Returns the start index.
* @since 1.0
* @version 1.0
*/
uint16_t GetStartIndex() const
{
return startIndex_;
}
/**
* @brief Sets the loop state for this list, in which a loop scroll is possible since the top and bottom of the list
* are connected together.
*
* @param state Indicates the loop state to set.
* @since 1.0
* @version 1.0
*/
void SetLoopState(bool state)
{
isLoopList_ = state;
}
/**
* @brief Checks whether this list is in a loop state.
*
* @return Returns if the list is in the loop state; returns false if the list is in the common state.
* @since 1.0
* @version 1.0
*/
bool GetLoopState() const
{
return isLoopList_;
}
/**
* @brief Sets the position where a child view is selected as this list scrolls.
*
* When a child view is selected at the specified position, the callback {@link ListScrollListener} is invoked.
* You can implement the zoom-in and color-change effects in the callback.
*
* @param position Indicates the position to set. The default value is 0, indicating that no position is
* set.
* @since 1.0
* @version 1.0
*/
void SetSelectPosition(uint16_t position)
{
selectPosition_ = position;
}
/**
* @brief Obtains the child view being selected at the preset position.
*
* @return Returns the child view if available; returns NULL if no child view is selected or no position is
* set.
* @since 1.0
* @version 1.0
*/
UIView* GetSelectView();
/**
* @brief Sets the listener that contains a callback to be invoked when a child view is selected as this list
* scrolls.
*
* @param scrollListener Indicates the listener to set.
* @since 1.0
* @version 1.0
*/
void SetScrollStateListener(ListScrollListener* scrollListener)
{
scrollListener_ = scrollListener;
}
/**
* @brief Refreshes this list. The number of child views in the current view is fixed and the positions of those
* reserved child views as this list scrolls remain unchanged.
* @since 1.0
* @version 1.0
*/
void RefreshList();
/**
* @brief Sets the automatic alignment state for this list. When a scroll stops, a child view is selected and its
* position is automatically aligned with the preset position.
*
* @param state Indicates the automatic alignment state. true indicates this state is enabled, and
* false indicates the opposite case.
* @since 1.0
* @version 1.0
*/
void EnableAutoAlign(bool state)
{
autoAlign_ = state;
}
/**
* @brief
* 设置自动对齐动画时长,单位为毫秒,默认为100毫秒。该功能依赖EnableAutoAlign()方法,自动对齐设置为true情况下才生效。
*
* @param value 自动对齐动画时长,0表示无动画。
* @since 3.0
* @version 3.0
*/
void SetAutoAlignTime(uint16_t time)
{
alignTime_ = time;
}
/**
* @brief Sets the automatic alignment mode for this list when auto align state is enabled.
*
* @param dragBack mode of alignment.
* true means list item will move back when its position crosses the line of select
* position partly (but not all of it).
* false means list item will move front when its position crosses the line of select
* position (no matter how many it crosses).
*
* @since 3.0
* @version 3.0
*/
void EnableCrossDragBack(bool dragBack)
{
dragBack_ = dragBack;
}
/**
* @brief 获取自动对齐动画时长。
*
* @return 自动对齐动画时长。
* @since 3.0
* @version 3.0
*/
uint16_t GetAutoAlignTime() const
{
return alignTime_;
}
void SetXScrollBarVisible(bool visible);
void SetYScrollBarVisible(bool visible);
void RemoveAll() override;
static constexpr int8_t NULL_SELECT_INDEX = -1;
UIView* onSelectedView_;
protected:
static constexpr int16_t RECALCULATE_DRAG_DISTANCE = 10;
static constexpr int16_t RECALCULATE_DRAG_TIMES = 10;
static constexpr int16_t DEFAULT_ALIGN_TIMES = 100;
void StopAnimator() override;
bool DragXInner(int16_t distance) override;
bool DragYInner(int16_t distance) override;
private:
friend class UIPicker;
friend class Recycle;
class Recycle : public HeapBase {
public:
explicit Recycle(UIList* list) : adapter_(nullptr), listView_(list), hasInitialiszed_(false) {}
virtual ~Recycle();
void InitRecycle();
UIView* GetView(int16_t index);
void SetAdapter(AbstractAdapter* adapter)
{
hasInitialiszed_ = false;
adapter_ = adapter;
}
bool HasInitialiszed()
{
return hasInitialiszed_;
}
void AddScrapView(UIView* view)
{
scrapView_.PushBack(view);
}
uint16_t GetAdapterItemCount()
{
return (adapter_ == nullptr) ? 0 : adapter_->GetCount();
}
void ClearScrapView()
{
scrapView_.Clear();
}
Rect32 GetAdapterItemsReletiveRect();
void MoveAdapterItemsRelativeRect(int16_t x, int16_t y);
void MeasureAdapterRelativeRect();
private:
friend class UIList;
void FillActiveView();
List scrapView_;
AbstractAdapter* adapter_;
UIList* listView_;
Rect32 adapterRelativeRect_;
bool hasInitialiszed_;
};
void PushBack(UIView* view);
void PopItem(UIView* view);
void PushFront(UIView* view);
void SetHead(UIView* view);
bool MoveChildStep(int16_t distance);
bool MoveChildStepVertical(int16_t distance);
bool MoveChildStepHorizontal(int16_t distance);
uint16_t GetIndexInc(uint16_t index);
uint16_t GetIndexDec(uint16_t index);
bool MoveOffset(int16_t x, int16_t y);
void UpdateScrollBar();
bool IsNeedReCalculateDragEnd();
bool ReCalculateDragEnd();
void CalculateReboundDistance(int16_t& dragDistanceX, int16_t& dragDistanceY) override;
void FixDistance(int16_t& distanceX, int16_t& distanceY) override;
void FixHorDistance(int16_t& distanceX);
void FixVerDistance(int16_t& distanceY);
bool isLoopList_;
bool isReCalculateDragEnd_;
bool autoAlign_;
uint16_t alignTime_;
uint16_t startIndex_;
uint16_t topIndex_;
uint16_t bottomIndex_;
uint16_t selectPosition_;
int16_t onSelectedIndex_;
Recycle recycle_;
ListScrollListener* scrollListener_;
};
} // namespace OHOS
#endif // GRAPHIC_LITE_UI_LIST_H