298 lines
5.2 KiB
C++
298 lines
5.2 KiB
C++
#include "ui/dl_ui_list_box.h"
|
|
|
|
#ifndef DL_DISABLE_RENDER
|
|
#include "ui/dl_ui_manager.h"
|
|
|
|
namespace dl::UI
|
|
{
|
|
|
|
dl::UI::ListBox* ListBox::Create(Panel* item, size_t num)
|
|
{
|
|
ListBox* ret = new ListBox;
|
|
ret->_item = item;
|
|
ret->_num = num;
|
|
ret->_init();
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ListBox::_init()
|
|
{
|
|
_locItem = createLocatorY((float)_item->GetSize()[1]);
|
|
|
|
_panel = g_ui->CreatePanel();
|
|
_panel->SetAutoRun(false);
|
|
_panel->SetAutoCoor(false);
|
|
_panel->SetOrderMode(Panel::FORCE);
|
|
_coorItem->SetParent(_panel->GetCoor());
|
|
_item->SetAutoRun(false);// 不可见
|
|
_item->SetAutoCoor(false);
|
|
_item->GetCoor()->SetParent(_coorItem);
|
|
_item->SetOrderMode(Panel::FORCE);
|
|
_item->SetPickupMode(Panel::E_ELEMENT);
|
|
|
|
for (size_t i = 0; i < _num; ++i)
|
|
{
|
|
Panel* ret = _item->Clone();
|
|
_allItem.push_back(ret);
|
|
}
|
|
_refresh_item_pos();
|
|
|
|
_refresh_size();
|
|
|
|
_cptElemData._hv = Align::LT;
|
|
_cptElemData._size = toPosition(_panel->GetSize());
|
|
|
|
SetOrder(Z_DEFAULT_UI);
|
|
}
|
|
|
|
void ListBox::_limit_select(std::size_t i_select)
|
|
{
|
|
if (_selectLimit == 0)
|
|
{// 不可选中
|
|
if (!_vecSelect.empty())
|
|
{
|
|
_vecSelect.clear();
|
|
_bSelectChange = true;
|
|
}
|
|
}
|
|
else if (_selectLimit == 1)
|
|
{// 单选
|
|
if (_vecSelect.size() != 1)
|
|
{
|
|
_vecSelect.resize(1);
|
|
*_vecSelect.begin() = i_select;
|
|
_bSelectChange = true;
|
|
}
|
|
else
|
|
{
|
|
if (_vecSelect.front() != i_select)
|
|
{
|
|
*_vecSelect.begin() = i_select;
|
|
_bSelectChange = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{// 复选
|
|
bool is_select = Any::Equal(_vecSelect, i_select);
|
|
if (!is_select)
|
|
{
|
|
_bSelectChange = true;
|
|
assert(_vecSelect.size() <= _selectLimit);
|
|
if (_vecSelect.size() + 1 <= _selectLimit)
|
|
{
|
|
_vecSelect.push_back(i_select);
|
|
}
|
|
else
|
|
{
|
|
_vecSelect.pop_front();
|
|
_vecSelect.push_back(i_select);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
dl::UI::ListBox* ListBox::Clone()
|
|
{
|
|
ListBox* ret = new ListBox;
|
|
ret->_item = _item->Clone();
|
|
ret->_item->GetCoor()->SetParent(ret->_coorItem);
|
|
ret->_panel = _panel->Clone();
|
|
ret->_coorItem->SetParent(ret->_panel->GetCoor());
|
|
ret->_locItem = _locItem;
|
|
ret->_locItem.Reset();
|
|
ret->_selectLimit = _selectLimit;
|
|
ret->_scroll = _scroll;
|
|
ret->_scrollK = _scrollK;
|
|
ret->_num = _num;
|
|
ret->_bSelectChange = _bSelectChange;
|
|
|
|
for (Panel* p : _allItem)
|
|
{
|
|
Panel* p1 = p->Clone();
|
|
p1->GetCoor()->SetParent(ret->_coorItem);
|
|
p1->GetCoor()->SetPosition(ret->_locItem.Get(ret->_allItem.size()));
|
|
ret->_allItem.push_back(p1);
|
|
}
|
|
ret->_vecSelect = _vecSelect;
|
|
return ret;
|
|
}
|
|
|
|
void ListBox::SetElementDataAnchor(const Position& anchor)
|
|
{
|
|
_cptElemData._anchor = anchor;
|
|
}
|
|
|
|
void ListBox::SetElementDataPos(const Position& pos)
|
|
{
|
|
_cptElemData._pos = pos;
|
|
}
|
|
|
|
void ListBox::_limit_scroll()
|
|
{
|
|
if (_scroll < 0)
|
|
_scroll = 0;
|
|
if (_vecItemData.size() <= _num)
|
|
_scroll = 0;
|
|
else
|
|
{
|
|
Float max = (_vecItemData.size() - _num) * _locItem.GetDy();
|
|
if (_scroll > max)
|
|
_scroll = max;
|
|
}
|
|
}
|
|
|
|
void ListBox::_refresh_item()
|
|
{
|
|
auto& vec = _vecItemData;
|
|
size_t cur = _calc_scroll();
|
|
if (vec.size() <= _num)
|
|
{// 能完全绘制
|
|
assert(cur == 0);
|
|
auto iter = vec.begin();
|
|
size_t i = 0;
|
|
while (iter != vec.end())
|
|
{
|
|
_cbItem(_allItem[i], *iter);
|
|
++i;
|
|
++iter;
|
|
}
|
|
for (size_t i = vec.size(); i < _num; ++i)
|
|
{
|
|
if(_bBlankShow)
|
|
_cbItem(_allItem[i], Value{});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cur + _num > vec.size())
|
|
{
|
|
assert(0);
|
|
cur = vec.size() - _num;
|
|
}
|
|
auto iter = vec.begin();
|
|
std::advance(iter, cur);
|
|
size_t i = 0;
|
|
while (i < _num)
|
|
{
|
|
_cbItem(_allItem[i], *iter);
|
|
++i;
|
|
++iter;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ListBox::_refresh_select()
|
|
{
|
|
size_t cur = _calc_scroll();
|
|
for (size_t i = 0; i < _allItem.size(); ++i)
|
|
{
|
|
Panel* panel = _allItem[i];
|
|
if (_vecSelect.empty())
|
|
panel->SetSelectAll(false);
|
|
else
|
|
{
|
|
for (auto& j : _vecSelect)
|
|
{
|
|
panel->SetSelectAll(i + cur == j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ListBox::Update()
|
|
{
|
|
_bSelectChange = false;
|
|
|
|
// 滚轮处理
|
|
Position wheel = g_input->GetScrollDelta();
|
|
if (wheel[1] && IsPickup())
|
|
{
|
|
_scroll += wheel[1] * _locItem.GetDy() * _scrollK;
|
|
_limit_scroll();
|
|
_refresh_scroll();
|
|
// 响应滚轮后置空
|
|
g_input->ClearScrollDelta();
|
|
|
|
// 重建内容
|
|
_refresh_item();
|
|
_refresh_select();
|
|
}
|
|
|
|
std::size_t i_select = -1;
|
|
size_t cur = _calc_scroll();
|
|
|
|
size_t num_update = _bBlankShow ? _num : std::min(_vecItemData.size(), _num);
|
|
for (std::size_t i = 0; i < num_update; ++i)
|
|
{
|
|
Panel* panel = _allItem[i];
|
|
panel->Update();
|
|
if (g_input->KeyUp(MouseCode::LEFT))
|
|
{// 选中
|
|
if (panel->IsPickup())
|
|
i_select = cur + i;
|
|
}
|
|
}
|
|
// 合法性处理
|
|
if (i_select == -1)
|
|
;
|
|
else
|
|
{
|
|
if(i_select < _vecItemData.size())
|
|
_limit_select(i_select);
|
|
_refresh_select();
|
|
}
|
|
}
|
|
|
|
bool ListBox::IsPickup()
|
|
{
|
|
if (_panel->IsPickup())
|
|
return true;
|
|
for (std::size_t i = 0; i < _num; ++i)
|
|
{
|
|
Panel* panel = _allItem[i];
|
|
if (panel->IsPickup())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ListBox::_cb_default(Panel* item, Value v)
|
|
{
|
|
if (v)
|
|
{
|
|
std::string str = v.ToString();
|
|
item->ExSetString(str);
|
|
}
|
|
else
|
|
{
|
|
item->ExSetString({});
|
|
}
|
|
}
|
|
|
|
ListBox::~ListBox()
|
|
{
|
|
for (auto& iter : _allItem)
|
|
{
|
|
g_ui->DeletePanel(iter, true);
|
|
}
|
|
g_ui->DeletePanel(_item, true);
|
|
g_ui->DeletePanel(_panel, true);
|
|
delete _coorItem;
|
|
}
|
|
|
|
void ListBox::_reset_state()
|
|
{
|
|
_scroll = 0;
|
|
for (auto& iter : _allItem)
|
|
{
|
|
iter->SetSelectAll(false);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|