#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); } }