mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2026-06-02 09:06:54 +02:00
Add new shared pointer and make use of it
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
#include "input/InputProvider.h"
|
||||
#include "FocusManager.h"
|
||||
|
||||
void FocusManager::Focus(View* newFocus)
|
||||
void FocusManager::Focus(const SharedPtr<View>& newFocus)
|
||||
{
|
||||
if (!newFocus)
|
||||
{
|
||||
@@ -11,48 +11,71 @@ void FocusManager::Focus(View* newFocus)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentFocus)
|
||||
_currentFocus->SetFocused(false);
|
||||
if (auto currentFocus = _currentFocus.Lock())
|
||||
{
|
||||
currentFocus->SetFocused(false);
|
||||
}
|
||||
newFocus->SetFocused(true);
|
||||
_currentFocus = newFocus;
|
||||
}
|
||||
|
||||
void FocusManager::Unfocus()
|
||||
{
|
||||
if (_currentFocus)
|
||||
_currentFocus->SetFocused(false);
|
||||
_currentFocus = nullptr;
|
||||
if (auto currentFocus = _currentFocus.Lock())
|
||||
{
|
||||
currentFocus->SetFocused(false);
|
||||
}
|
||||
_currentFocus.Reset();
|
||||
}
|
||||
|
||||
void FocusManager::Update(const InputProvider& inputProvider)
|
||||
{
|
||||
if (!_currentFocus || !_currentFocus->GetParent())
|
||||
auto currentFocus = _currentFocus.Lock();
|
||||
if (!currentFocus || !currentFocus->GetParent())
|
||||
return; // todo
|
||||
|
||||
View* newFocus = nullptr;
|
||||
SharedPtr<View> newFocus;
|
||||
if (inputProvider.Triggered(InputKey::DpadUp))
|
||||
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Up, _currentFocus);
|
||||
{
|
||||
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Up, currentFocus.GetPointer());
|
||||
}
|
||||
else if (inputProvider.Triggered(InputKey::DpadDown))
|
||||
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Down, _currentFocus);
|
||||
{
|
||||
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Down, currentFocus.GetPointer());
|
||||
}
|
||||
else if (inputProvider.Triggered(InputKey::DpadLeft))
|
||||
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Left, _currentFocus);
|
||||
{
|
||||
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Left, currentFocus.GetPointer());
|
||||
}
|
||||
else if (inputProvider.Triggered(InputKey::DpadRight))
|
||||
newFocus = _currentFocus->GetParent()->MoveFocus(_currentFocus, FocusMoveDirection::Right, _currentFocus);
|
||||
{
|
||||
newFocus = currentFocus->GetParent()->MoveFocus(currentFocus, FocusMoveDirection::Right, currentFocus.GetPointer());
|
||||
}
|
||||
else
|
||||
_currentFocus->HandleInput(inputProvider, *this);
|
||||
{
|
||||
currentFocus->HandleInput(inputProvider, *this);
|
||||
}
|
||||
|
||||
if (newFocus)
|
||||
{
|
||||
Focus(newFocus);
|
||||
}
|
||||
}
|
||||
|
||||
bool FocusManager::IsFocusInside(const View* view) const
|
||||
{
|
||||
auto focusView = _currentFocus;
|
||||
while (focusView)
|
||||
if (auto currentFocus = _currentFocus.Lock())
|
||||
{
|
||||
if (view == focusView)
|
||||
return true;
|
||||
focusView = focusView->GetParent();
|
||||
auto focusView = currentFocus.GetPointer();
|
||||
while (focusView)
|
||||
{
|
||||
if (view == focusView)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
focusView = focusView->GetParent();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include <core/SharedPtr.h>
|
||||
#include <core/WeakPtr.h>
|
||||
|
||||
class View;
|
||||
class InputProvider;
|
||||
@@ -9,7 +11,7 @@ class FocusManager
|
||||
public:
|
||||
/// @brief Focuses the given view.
|
||||
/// @param newFocus The view to focus.
|
||||
void Focus(View* newFocus);
|
||||
void Focus(const SharedPtr<View>& newFocus);
|
||||
|
||||
/// @brief Clears the current focus.
|
||||
void Unfocus();
|
||||
@@ -20,7 +22,7 @@ public:
|
||||
|
||||
/// @brief Gets the currently focused view.
|
||||
/// @return A pointer to the view that is currently focused, or null if none.
|
||||
constexpr View* GetCurrentFocus() const { return _currentFocus; }
|
||||
constexpr SharedPtr<View> GetCurrentFocus() const { return _currentFocus.Lock(); }
|
||||
|
||||
/// @brief Checks whether the current focus lies inside the given view.
|
||||
/// @param view The view to check for.
|
||||
@@ -28,5 +30,5 @@ public:
|
||||
bool IsFocusInside(const View* view) const;
|
||||
|
||||
private:
|
||||
View* _currentFocus = nullptr;
|
||||
WeakPtr<View> _currentFocus;
|
||||
};
|
||||
|
||||
@@ -20,19 +20,15 @@ public:
|
||||
|
||||
/// @brief Creates and returns a view for this adapter.
|
||||
/// @return The created view.
|
||||
virtual View* CreateView() const = 0;
|
||||
|
||||
/// @brief Destroys a \p view for this adapter that was previously created with CreateView.
|
||||
/// @param view The view to destroy.
|
||||
virtual void DestroyView(View* view) const = 0;
|
||||
virtual SharedPtr<View> CreateView() const = 0;
|
||||
|
||||
/// @brief Binds the given \p view to the item at the given \p index.
|
||||
/// @param view The view to bind.
|
||||
/// @param index The item index to bind to.
|
||||
virtual void BindView(View* view, int index) const = 0;
|
||||
virtual void BindView(SharedPtr<View> view, int index) const = 0;
|
||||
|
||||
/// @brief Releases a \p view that was previously bound with BindView, such that it can be reused.
|
||||
/// @param view The view to release.
|
||||
/// @param index The item index that was bound to the view.
|
||||
virtual void ReleaseView(View* view, int index) const = 0;
|
||||
virtual void ReleaseView(SharedPtr<View> view, int index) const = 0;
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "gui/input/InputProvider.h"
|
||||
#include "RecyclerView.h"
|
||||
|
||||
RecyclerView::RecyclerView(int x, int y, int width, int height, Mode mode)
|
||||
RecyclerView::RecyclerView(Private, int x, int y, int width, int height, Mode mode)
|
||||
: _width(width), _height(height), _mode(mode), _rows(0), _columns(0)
|
||||
, _viewPoolFreeCount(0), _viewPoolTotalCount(0)
|
||||
, _xOffset(0), _yOffset(0), _xPadding(0), _yPadding(0)
|
||||
@@ -20,21 +20,21 @@ RecyclerView::~RecyclerView()
|
||||
{
|
||||
if (_adapter)
|
||||
{
|
||||
for (u32 i = 0; i < _viewPoolTotalCount; i++)
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
|
||||
{
|
||||
_adapter->DestroyView(_viewPool[i].view);
|
||||
_adapter->ReleaseView(_viewPool[i].view, _viewPool[i].itemIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecyclerView::SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex)
|
||||
void RecyclerView::SetAdapter(SharedPtr<const RecyclerAdapter> adapter, int initialSelectedIndex)
|
||||
{
|
||||
if (_adapter)
|
||||
{
|
||||
_selectedItem = nullptr;
|
||||
for (u32 i = 0; i < _viewPoolTotalCount; i++)
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
|
||||
{
|
||||
_adapter->DestroyView(_viewPool[i].view);
|
||||
_adapter->ReleaseView(_viewPool[i].view, _viewPool[i].itemIdx);
|
||||
}
|
||||
_viewPool.reset();
|
||||
_viewPoolFreeCount = 0;
|
||||
@@ -44,7 +44,7 @@ void RecyclerView::SetAdapter(const RecyclerAdapter* adapter, int initialSelecte
|
||||
_curRangeStart = 0;
|
||||
_curRangeLength = 0;
|
||||
}
|
||||
_adapter = adapter;
|
||||
_adapter = std::move(adapter);
|
||||
_adapter->GetViewSize(_itemWidth, _itemHeight);
|
||||
_itemCount = _adapter->GetItemCount();
|
||||
if (_mode == Mode::HorizontalList || _mode == Mode::HorizontalGrid)
|
||||
@@ -178,7 +178,7 @@ void RecyclerView::VBlank()
|
||||
}
|
||||
}
|
||||
|
||||
View* RecyclerView::MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
|
||||
SharedPtr<View> RecyclerView::MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
|
||||
{
|
||||
if (_itemCount == 0)
|
||||
{
|
||||
@@ -195,9 +195,9 @@ View* RecyclerView::MoveFocus(View* currentFocus, FocusMoveDirection direction,
|
||||
}
|
||||
}
|
||||
|
||||
View* RecyclerView::MoveFocusHorizontal(View* currentFocus, FocusMoveDirection direction, View* source)
|
||||
SharedPtr<View> RecyclerView::MoveFocusHorizontal(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
|
||||
{
|
||||
if (!_selectedItem || currentFocus != _selectedItem->view)
|
||||
if (!_selectedItem || currentFocus.GetPointer() != _selectedItem->view.GetPointer())
|
||||
{
|
||||
// incoming focus
|
||||
if (direction != FocusMoveDirection::Down)
|
||||
@@ -207,7 +207,7 @@ View* RecyclerView::MoveFocusHorizontal(View* currentFocus, FocusMoveDirection d
|
||||
|
||||
int idx = (-_xOffset + currentFocus->GetPosition().x - _xPadding + ((_xSpacing + _itemWidth) >> 1)) / (_xSpacing + _itemWidth) * _rows;
|
||||
SetSelectedItem(std::clamp(idx, 0, ((int)_itemCount - 1) / _rows * _rows));
|
||||
return _selectedItem != nullptr ? _selectedItem->view : this;
|
||||
return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
|
||||
}
|
||||
|
||||
int row = _selectedItem->itemIdx % _rows;
|
||||
@@ -248,12 +248,12 @@ View* RecyclerView::MoveFocusHorizontal(View* currentFocus, FocusMoveDirection d
|
||||
SetSelectedItem(std::clamp(idx, 0, (int)_itemCount - 1));
|
||||
}
|
||||
|
||||
return _selectedItem != nullptr ? _selectedItem->view : this;
|
||||
return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
|
||||
}
|
||||
|
||||
View* RecyclerView::MoveFocusVertical(View* currentFocus, FocusMoveDirection direction, View* source)
|
||||
SharedPtr<View> RecyclerView::MoveFocusVertical(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
|
||||
{
|
||||
if (!_selectedItem || currentFocus != _selectedItem->view)
|
||||
if (!_selectedItem || currentFocus.GetPointer() != _selectedItem->view.GetPointer())
|
||||
{
|
||||
// incoming focus
|
||||
if (direction != FocusMoveDirection::Right)
|
||||
@@ -263,7 +263,7 @@ View* RecyclerView::MoveFocusVertical(View* currentFocus, FocusMoveDirection dir
|
||||
|
||||
int idx = (-_yOffset + currentFocus->GetPosition().y - _yPadding + ((_ySpacing + _itemHeight) >> 1)) / (_ySpacing + _itemHeight) * _columns;
|
||||
SetSelectedItem(std::clamp(idx, 0, ((int)_itemCount - 1) / _columns * _columns));
|
||||
return _selectedItem != nullptr ? _selectedItem->view : this;
|
||||
return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
|
||||
}
|
||||
|
||||
int column = _selectedItem->itemIdx % _columns;
|
||||
@@ -304,7 +304,7 @@ View* RecyclerView::MoveFocusVertical(View* currentFocus, FocusMoveDirection dir
|
||||
SetSelectedItem(std::clamp(idx, 0, (int)_itemCount - 1));
|
||||
}
|
||||
|
||||
return _selectedItem != nullptr ? _selectedItem->view : this;
|
||||
return _selectedItem != nullptr ? _selectedItem->view : SharedFromThis();
|
||||
}
|
||||
|
||||
bool RecyclerView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/EnableSharedFromThis.h"
|
||||
#include "View.h"
|
||||
#include "RecyclerAdapter.h"
|
||||
#include "gui/FocusManager.h"
|
||||
#include "animation/Animator.h"
|
||||
#include "RecyclerViewBase.h"
|
||||
|
||||
class RecyclerView : public RecyclerViewBase
|
||||
class RecyclerView : public RecyclerViewBase, public EnableSharedFromThis<RecyclerView>
|
||||
{
|
||||
struct Private { explicit Private() = default; };
|
||||
|
||||
public:
|
||||
enum class Mode
|
||||
{
|
||||
@@ -21,10 +24,16 @@ public:
|
||||
VerticalGrid
|
||||
};
|
||||
|
||||
RecyclerView(int x, int y, int width, int height, Mode mode);
|
||||
RecyclerView(Private, int x, int y, int width, int height, Mode mode);
|
||||
|
||||
static SharedPtr<RecyclerView> CreateShared(int x, int y, int width, int height, Mode mode)
|
||||
{
|
||||
return SharedPtr<RecyclerView>::MakeShared(Private(), x, y, width, height, mode);
|
||||
}
|
||||
|
||||
~RecyclerView();
|
||||
|
||||
void SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex = 0) override;
|
||||
void SetAdapter(SharedPtr<const RecyclerAdapter> adapter, int initialSelectedIndex = 0) override;
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
void Update() override;
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
@@ -35,16 +44,20 @@ public:
|
||||
return Rectangle(_position, _width, _height);
|
||||
}
|
||||
|
||||
View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source) override;
|
||||
SharedPtr<View> MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source) override;
|
||||
|
||||
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
|
||||
|
||||
void Focus(FocusManager& focusManager) override
|
||||
{
|
||||
if (_selectedItem)
|
||||
{
|
||||
focusManager.Focus(_selectedItem->view);
|
||||
}
|
||||
else
|
||||
focusManager.Focus(this);
|
||||
{
|
||||
focusManager.Focus(SharedFromThis());
|
||||
}
|
||||
}
|
||||
|
||||
int GetSelectedItem() const override
|
||||
@@ -69,7 +82,7 @@ public:
|
||||
private:
|
||||
struct ViewPoolEntry
|
||||
{
|
||||
View* view;
|
||||
SharedPtr<View> view;
|
||||
int itemIdx;
|
||||
};
|
||||
|
||||
@@ -107,6 +120,6 @@ private:
|
||||
void EnsureVisible(int itemIdx, bool animate);
|
||||
Point GetItemPosition(int itemIdx);
|
||||
|
||||
View* MoveFocusHorizontal(View* currentFocus, FocusMoveDirection direction, View* source);
|
||||
View* MoveFocusVertical(View* currentFocus, FocusMoveDirection direction, View* source);
|
||||
SharedPtr<View> MoveFocusHorizontal(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source);
|
||||
SharedPtr<View> MoveFocusVertical(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source);
|
||||
};
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
#include "View.h"
|
||||
#include "RecyclerAdapter.h"
|
||||
#include "gui/FocusManager.h"
|
||||
#include "core/SharedPtr.h"
|
||||
|
||||
/// @brief Abstract base class for a recycler view that displays a possibly large collection of items
|
||||
/// provided by an adapter in an efficient way.
|
||||
class RecyclerViewBase : public View
|
||||
{
|
||||
public:
|
||||
virtual void SetAdapter(const RecyclerAdapter* adapter, int initialSelectedIndex = 0) = 0;
|
||||
virtual void SetAdapter(SharedPtr<const RecyclerAdapter> adapter, int initialSelectedIndex = 0) = 0;
|
||||
virtual void Focus(FocusManager& focusManager) = 0;
|
||||
virtual int GetSelectedItem() const = 0;
|
||||
|
||||
protected:
|
||||
const RecyclerAdapter* _adapter = nullptr;
|
||||
SharedPtr<const RecyclerAdapter> _adapter;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "core/LinkedListLink.h"
|
||||
#include "core/math/Point.h"
|
||||
#include "core/math/Rectangle.h"
|
||||
#include "core/SharedPtr.h"
|
||||
#include "../FocusManager.h"
|
||||
#include "../FocusMoveDirection.h"
|
||||
|
||||
@@ -37,7 +38,7 @@ public:
|
||||
/// @param direction The direction to move the focus in.
|
||||
/// @param source The view that requested this view to move focus.
|
||||
/// @return The newly focused view, or null if the focus didn't change.
|
||||
virtual View* MoveFocus(View* currentFocus, FocusMoveDirection direction, View* source)
|
||||
virtual SharedPtr<View> MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source)
|
||||
{
|
||||
if (_parent && _parent != source)
|
||||
return _parent->MoveFocus(currentFocus, direction, this);
|
||||
|
||||
Reference in New Issue
Block a user