Files
dl_old/dl/ui/dl_ui_list_box.cpp
2026-06-18 18:46:20 +08:00

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