Files
2022-01-04 09:40:38 +08:00

210 lines
4.9 KiB
C++

#pragma once
typedef std::function<void(int nStartIndex, int nEndIndex)> DataChangedNotify;
typedef std::function<void()> CountChangedNotify;
class UILIB_API VirtualTileInterface: public nbase::SupportWeakCallback
{
public:
VirtualTileInterface();
/**
* @brief 创建一个子项
* @return 返回创建后的子项指针
*/
virtual ui::Control* CreateElement() = 0;
/**
* @brief 填充指定子项
* @param[in] control 子项控件指针
* @param[in] index 索引
* @return 返回创建后的子项指针
*/
virtual void FillElement(ui::Control *control, int index) = 0;
/**
* @brief 获取子项总数
* @return 返回子项总数
*/
virtual int GetElementtCount() = 0;
void RegNotifys(const DataChangedNotify& dcNotify, const CountChangedNotify& ccNotify);
protected:
void EmitDataChanged(int nStartIndex, int nEndIndex);
void EmitCountChanged();
private:
DataChangedNotify m_DataChangedNotify;
CountChangedNotify m_CountChangedNotify;
};
class UILIB_API VirtualTileLayout : public ui::TileLayout
{
public:
VirtualTileLayout();
virtual ui::CSize ArrangeChild(const std::vector<ui::Control*>& items, ui::UiRect rc) override;
virtual ui::CSize AjustSizeByChild(const std::vector<ui::Control*>& items, ui::CSize szAvailable) override;
virtual bool SetAttribute(const std::wstring& strName, const std::wstring& strValue) override;
virtual int GetElementsHeight(int nCount);
virtual void LazyArrangeChild();
virtual int AjustMaxItem();
private:
bool m_bAutoCalcColumn;
};
class UILIB_API VirtualTileBox : public ui::ListBox
{
friend class VirtualTileLayout;
public:
VirtualTileBox(ui::Layout* pLayout = new VirtualTileLayout);
/**
* @brief 设置数据代理对象
* @param[in] pProvider 开发者需要重写 VirtualListInterface 的接口来作为数据代理对象
* @return 无
*/
virtual void SetDataProvider(VirtualTileInterface *pProvider);
virtual VirtualTileInterface* GetDataProvider();
/**
* @brief 刷新列表
* @return 无
*/
virtual void Refresh();
/**
* @brief 删除所有子项
* @return 无
*/
virtual void RemoveAll() override;
/**
* @brief 设置是否强制重新布局
* @param[in] bForce 设置为 true 为强制,否则为不强制
* @return 无
*/
void SetForceArrange(bool bForce);
/**
* @brief 获取当前所有可见控件的索引
* @param[out] collection 索引列表
* @return 无
*/
void GetDisplayCollection(std::vector<int>& collection);
/**
* @brief 让控件在可见范围内
* @param[in] iIndex 控件索引
* @param[in] bToTop 是否在最上方
* @return 无
*/
void EnsureVisible(int iIndex, bool bToTop = false);
protected:
/// 重写父类接口,提供个性化功能
virtual void SetScrollPos(ui::CSize szPos) override;
virtual void HandleMessage(ui::EventArgs& event) override;
virtual void SetPos(ui::UiRect rc) override;
/**
* @brief 重新布局子项
* @param[in] bForce 是否强制重新布局
* @return 无
*/
void ReArrangeChild(bool bForce);
/**
* @brief 键盘按下通知
* @param[in] ch 按键
* @return 无
*/
virtual void OnKeyDown(TCHAR ch) {}
/**
* @brief 键盘弹起通知
* @param[in] ch 按键
* @return 无
*/
virtual void OnKeyUp(TCHAR ch) {}
private:
enum ScrollDirection
{
kScrollUp = -1,
kScrollDown = 1
};
/**
* @brief 创建一个子项
* @return 返回创建后的子项指针
*/
Control* CreateElement();
/**
* @brief 填充指定子项
* @param[in] control 子项控件指针
* @param[in] index 索引
* @return 返回创建后的子项指针
*/
void FillElement(Control *pControl, int iIndex);
/**
* @brief 获取元素总数
* @return 返回元素总指数
*/
int GetElementCount();
/**
* @brief 得到n个元素对应的高度和,
* @param[in] nCount 要得到多少元素的高度,-1表示全部元素
* @return 返回指定数量元素的高度和
*/
int CalcElementsHeight(int nCount);
/**
* @brief 得到可见范围内第一个元素的前一个元素索引
* @param[out] bottom 返回上一个元素的 bottom 值
* @return 返回上一个元素的索引
*/
int GetTopElementIndex(int &bottom);
/**
* @brief 判断某个元素是否在可见范围内
* @param[in] iIndex 元素索引
* @return 返回 true 表示可见,否则为不可见
*/
bool IsElementDisplay(int iIndex);
/**
* @brief 判断是否要重新布局
* @param[out] direction 向上滚动还是向下滚动
* @return true 为需要重新布局,否则为 false
*/
bool NeedReArrange(ScrollDirection &direction);
VirtualTileLayout* GetTileLayout();
int GetRealElementHeight();
int GetColumns();
void LazyArrangeChild();
void OnModelDataChanged(int nStartIndex, int nEndIndex);
void OnModelCountChanged();
int ElementIndexToItemIndex(int nElementIndex);
int ItemIndexToElementIndex(int nItemIndex);
private:
VirtualTileInterface *m_pDataProvider;
int m_nMaxItemCount; // 列表真实控件数量上限
int m_nOldYScrollPos;
bool m_bArrangedOnce;
bool m_bForceArrange; // 强制布局标记
};