mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2026-01-12 02:29:24 +01:00
185 lines
4.8 KiB
C++
185 lines
4.8 KiB
C++
#include "common.h"
|
|
#include "CoverFlowRecyclerViewBase.h"
|
|
|
|
void CoverFlowRecyclerViewBase::InitVram(const VramContext& vramContext)
|
|
{
|
|
for (u32 i = 0; i < _viewPool.size(); i++)
|
|
{
|
|
_viewPool[i].view->InitVram(vramContext);
|
|
}
|
|
}
|
|
|
|
void CoverFlowRecyclerViewBase::SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex)
|
|
{
|
|
if (_adapter)
|
|
{
|
|
_selectedItem = nullptr;
|
|
for (u32 i = 0; i < _viewPool.size(); i++)
|
|
{
|
|
_adapter->DestroyView(_viewPool[i].view);
|
|
}
|
|
}
|
|
_adapter = adapter;
|
|
// _adapter->GetViewSize(_itemWidth, _itemHeight);
|
|
_itemCount = _adapter->GetItemCount();
|
|
|
|
for (u32 i = 0; i < _viewPool.size(); i++)
|
|
{
|
|
_viewPool[i].view = _adapter->CreateView();
|
|
_viewPool[i].view->SetParent(this);
|
|
_viewPool[i].itemIdx = -1;
|
|
}
|
|
_viewPoolFreeCount = _viewPool.size();
|
|
|
|
if (initialSelectedIndex < 0 || (u32)initialSelectedIndex >= _itemCount)
|
|
{
|
|
initialSelectedIndex = 0;
|
|
}
|
|
if (_itemCount > 0)
|
|
{
|
|
SetSelectedItem(initialSelectedIndex, true);
|
|
}
|
|
}
|
|
|
|
View* CoverFlowRecyclerViewBase::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
|
|
{
|
|
if (!_selectedItem || currentFocus != _selectedItem->view)
|
|
{
|
|
// incoming focus
|
|
if (direction == FocusMoveDirection::Down)
|
|
{
|
|
return _selectedItem ? _selectedItem->view : this;
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
if (direction == FocusMoveDirection::Left)
|
|
{
|
|
int idx = _selectedItem->itemIdx;
|
|
if (idx - 1 >= 0)
|
|
{
|
|
idx -= 1;
|
|
}
|
|
|
|
SetSelectedItem(idx, false);
|
|
}
|
|
else if (direction == FocusMoveDirection::Right)
|
|
{
|
|
int idx = _selectedItem->itemIdx + 1;
|
|
idx = std::min(idx, (int)_itemCount - 1);
|
|
|
|
SetSelectedItem(idx, false);
|
|
}
|
|
else if (direction == FocusMoveDirection::Up || direction == FocusMoveDirection::Down)
|
|
{
|
|
return View::MoveFocus(currentFocus, direction, this);
|
|
}
|
|
|
|
return _selectedItem ? _selectedItem->view : this;
|
|
}
|
|
|
|
CoverFlowRecyclerViewBase::ViewPoolEntry* CoverFlowRecyclerViewBase::GetViewPoolEntryByItemIndex(int itemIdx)
|
|
{
|
|
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
|
|
{
|
|
if (_viewPool[i].itemIdx == (int)itemIdx)
|
|
return &_viewPool[i];
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CoverFlowRecyclerViewBase::ViewPoolEntry* CoverFlowRecyclerViewBase::BindViewPoolEntry(int itemIdx)
|
|
{
|
|
if (_viewPoolFreeCount == 0)
|
|
{
|
|
LOG_FATAL("No free view pool entries left\n");
|
|
while (true);
|
|
return nullptr;
|
|
}
|
|
|
|
int viewPoolIndex = _viewPoolFreeCount - 1;
|
|
auto& entry = _viewPool[viewPoolIndex];
|
|
_viewPoolFreeCount--;
|
|
entry.itemIdx = itemIdx;
|
|
_adapter->BindView(entry.view, itemIdx);
|
|
UpdateItemPosition(viewPoolIndex, true);
|
|
return &entry;
|
|
}
|
|
|
|
void CoverFlowRecyclerViewBase::BindRange(int start, int end)
|
|
{
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
if (_selectedItem && _selectedItem->itemIdx == i)
|
|
continue;
|
|
if (_curRangeLength != 0 && _curRangeStart <= i && i < _curRangeStart + _curRangeLength)
|
|
continue;
|
|
BindViewPoolEntry(i);
|
|
}
|
|
}
|
|
|
|
void CoverFlowRecyclerViewBase::ReleaseViewPoolEntry(int itemIdx)
|
|
{
|
|
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
|
|
{
|
|
if (_viewPool[i].itemIdx == (int)itemIdx)
|
|
{
|
|
_adapter->ReleaseView(_viewPool[i].view, _viewPool[i].itemIdx);
|
|
_viewPool[i].itemIdx = -1;
|
|
SwapViewPoolEntry(i, _viewPoolFreeCount);
|
|
if (_selectedItem == &_viewPool[_viewPoolFreeCount])
|
|
_selectedItem = &_viewPool[i];
|
|
_viewPoolFreeCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CoverFlowRecyclerViewBase::ReleaseRange(int start, int end)
|
|
{
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
if (_selectedItem && _selectedItem->itemIdx == i)
|
|
continue;
|
|
ReleaseViewPoolEntry(i);
|
|
}
|
|
}
|
|
|
|
void CoverFlowRecyclerViewBase::SetSelectedItem(int itemIdx, bool initial)
|
|
{
|
|
if (_selectedItem)
|
|
{
|
|
if (_selectedItem->itemIdx == itemIdx)
|
|
return;
|
|
|
|
if (_selectedItem->itemIdx < _curRangeStart ||
|
|
_selectedItem->itemIdx >= _curRangeStart + _curRangeLength)
|
|
{
|
|
ReleaseViewPoolEntry(_selectedItem->itemIdx);
|
|
}
|
|
_selectedItem = nullptr;
|
|
}
|
|
|
|
if (itemIdx < 0 || itemIdx >= (int)_itemCount)
|
|
return;
|
|
|
|
if (itemIdx >= _curRangeStart &&
|
|
itemIdx < _curRangeStart + _curRangeLength)
|
|
{
|
|
_selectedItem = GetViewPoolEntryByItemIndex(itemIdx);
|
|
}
|
|
else
|
|
{
|
|
_selectedItem = BindViewPoolEntry(itemIdx);
|
|
}
|
|
|
|
for (u32 i = _viewPoolFreeCount; i < _viewPool.size(); i++)
|
|
{
|
|
UpdateItemPosition(i, initial);
|
|
}
|
|
}
|