mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2026-06-02 17:16:57 +02:00
Add touch input support, add fast scrolling support for coverflow display mode, fix use after free bug in banner list mode
This commit is contained in:
@@ -2,10 +2,10 @@
|
||||
#include "InputKey.h"
|
||||
|
||||
/// @brief Interface for a source of key input.
|
||||
class IInputSource
|
||||
class IKeyInputSource
|
||||
{
|
||||
public:
|
||||
virtual ~IInputSource() { }
|
||||
virtual ~IKeyInputSource() { }
|
||||
|
||||
virtual InputKey Sample() const = 0;
|
||||
};
|
||||
14
arm9/source/gui/input/ITouchInputSource.h
Normal file
14
arm9/source/gui/input/ITouchInputSource.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "core/math/Point.h"
|
||||
|
||||
/// @brief Interface for a source of touch input.
|
||||
class ITouchInputSource
|
||||
{
|
||||
public:
|
||||
virtual ~ITouchInputSource() { }
|
||||
|
||||
/// @brief Samples the touch input.
|
||||
/// @param touchPosition When the pen is down, the current touch position.
|
||||
/// @return \c true when the pen is down, or \c false otherwise.
|
||||
virtual bool Sample(Point& touchPosition) const = 0;
|
||||
};
|
||||
@@ -15,7 +15,9 @@ enum class InputKey : u16
|
||||
L = 1 << 9,
|
||||
X = 1 << 10,
|
||||
Y = 1 << 11,
|
||||
Debug = 1 << 13
|
||||
Debug = 1 << 13,
|
||||
Touch = 1 << 14,
|
||||
Lid = 1 << 15
|
||||
};
|
||||
|
||||
inline InputKey operator&(InputKey lhs, InputKey rhs)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "core/math/Point.h"
|
||||
#include "InputKey.h"
|
||||
|
||||
class InputProvider
|
||||
@@ -14,6 +14,23 @@ public:
|
||||
/// @return \c true if any of the keys in the \p mask is being held, or \c false otherwise.
|
||||
bool Current(InputKey mask) const { return static_cast<bool>(_currentKeys & mask); }
|
||||
|
||||
/// @brief Returns the current touch point if the screen is being touched.
|
||||
/// @param touchPoint The current touch point if the screen is being touched.
|
||||
/// @return \c true if the screen is being touched, or \c false otherwise.
|
||||
bool GetCurrentTouchPoint(Point& touchPoint)
|
||||
{
|
||||
if (Current(InputKey::Touch))
|
||||
{
|
||||
touchPoint = _currentTouchPoint;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
touchPoint = Point(0, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Returns a bitmask of the keys that went from unpressed to pressed in the latest update.
|
||||
/// @return A bitmask of the keys that went from unpressed to pressed in the latest update.
|
||||
InputKey GetTriggeredKeys() const
|
||||
@@ -46,13 +63,16 @@ public:
|
||||
_currentKeys = InputKey::None;
|
||||
_triggeredKeys = InputKey::None;
|
||||
_releasedKeys = InputKey::None;
|
||||
_currentTouchPoint = Point(0, 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
InputKey _currentKeys;
|
||||
InputKey _triggeredKeys;
|
||||
InputKey _releasedKeys;
|
||||
Point _currentTouchPoint;
|
||||
|
||||
InputProvider()
|
||||
: _currentKeys(InputKey::None), _triggeredKeys(InputKey::None), _releasedKeys(InputKey::None) { }
|
||||
: _currentKeys(InputKey::None), _triggeredKeys(InputKey::None), _releasedKeys(InputKey::None)
|
||||
, _currentTouchPoint(0, 0) { }
|
||||
};
|
||||
|
||||
@@ -27,7 +27,9 @@ void InputRepeater::Update()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_state = State::Idle;
|
||||
}
|
||||
}
|
||||
else if (_state == State::NextRepeat)
|
||||
{
|
||||
@@ -40,13 +42,24 @@ void InputRepeater::Update()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_state = State::Idle;
|
||||
}
|
||||
}
|
||||
|
||||
InputKey lastRepKeys = _currentKeys & _repeatMask;
|
||||
_currentKeys = curKeys | repKeys;
|
||||
_triggeredKeys = _inputProvider->GetTriggeredKeys() | repKeys;
|
||||
_releasedKeys = _inputProvider->GetReleasedKeys() | (lastRepKeys & (lastRepKeys ^ repKeys));
|
||||
Point touchPoint;
|
||||
if (_inputProvider->GetCurrentTouchPoint(touchPoint))
|
||||
{
|
||||
_currentTouchPoint = touchPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentTouchPoint = Point(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void InputRepeater::Reset()
|
||||
|
||||
@@ -7,7 +7,7 @@ class InputRepeater : public InputProvider
|
||||
public:
|
||||
InputRepeater(InputProvider* inputProvider, InputKey repeatMask, u16 firstRepeatDelay, u16 nextRepeatDelay)
|
||||
: _inputProvider(inputProvider), _state(State::Idle)
|
||||
, _frameCounter(0), _repeatMask(repeatMask)
|
||||
, _frameCounter(0), _repeatMask(repeatMask & ~InputKey::Touch)
|
||||
, _firstRepeatDelayFrames(firstRepeatDelay)
|
||||
, _nextRepeatDelayFrames(nextRepeatDelay) { }
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include <nds/input.h>
|
||||
#include "IInputSource.h"
|
||||
#include "IKeyInputSource.h"
|
||||
#include "sharedMemory.h"
|
||||
|
||||
/// @brief Input source from the physical DS buttons.
|
||||
class PadInputSource : public IInputSource
|
||||
class PadInputSource : public IKeyInputSource
|
||||
{
|
||||
public:
|
||||
InputKey Sample() const override
|
||||
{
|
||||
u16 arm9Mask = (~REG_KEYINPUT & 0x3FF);
|
||||
u16 arm7Mask = (~SHARED_KEY_XY & 0xB);
|
||||
u16 arm7Mask = (~SHARED_KEY_XY & 0xCB);
|
||||
arm7Mask = (arm7Mask & 0xB) | ((arm7Mask & 0xC0) >> 2);
|
||||
return static_cast<InputKey>((arm9Mask | (arm7Mask << 10)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7,16 +7,44 @@ void SampledInputProvider::Update()
|
||||
InputKey trig = InputKey::None;
|
||||
InputKey rel = InputKey::None;
|
||||
|
||||
Point touchPoint(0, 0);
|
||||
int touchPointCount = 0;
|
||||
while (_inputBufferReadPtr != _inputBufferWritePtr)
|
||||
{
|
||||
InputKey nextKeys = _inputBuffer[_inputBufferReadPtr];
|
||||
InputKey nextKeys = _keyInputBuffer[_inputBufferReadPtr];
|
||||
trig |= (nextKeys ^ curKeys) & nextKeys;
|
||||
rel |= (nextKeys ^ curKeys) & curKeys;
|
||||
curKeys = nextKeys;
|
||||
if ((nextKeys & InputKey::Touch) != InputKey::None)
|
||||
{
|
||||
touchPoint.x += _touchInputBuffer[_inputBufferReadPtr].x;
|
||||
touchPoint.y += _touchInputBuffer[_inputBufferReadPtr].y;
|
||||
touchPointCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
touchPoint = Point(0, 0);
|
||||
touchPointCount = 0;
|
||||
}
|
||||
_inputBufferReadPtr = (_inputBufferReadPtr + 1) & 3;
|
||||
}
|
||||
|
||||
_triggeredKeys = trig;
|
||||
_releasedKeys = rel;
|
||||
_currentKeys = curKeys;
|
||||
if (touchPointCount == 0)
|
||||
{
|
||||
if ((_triggeredKeys & InputKey::Touch) != InputKey::None ||
|
||||
(_currentKeys & InputKey::Touch) != InputKey::None)
|
||||
{
|
||||
_releasedKeys = _releasedKeys | InputKey::Touch;
|
||||
}
|
||||
_triggeredKeys = _triggeredKeys & ~InputKey::Touch;
|
||||
_currentKeys = _currentKeys & ~InputKey::Touch;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentTouchPoint.x = touchPoint.x / touchPointCount;
|
||||
_currentTouchPoint.y = touchPoint.y / touchPointCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
#pragma once
|
||||
#include "InputProvider.h"
|
||||
#include "IInputSource.h"
|
||||
#include "IKeyInputSource.h"
|
||||
#include "ITouchInputSource.h"
|
||||
|
||||
/// @brief Input provider providing input from an \see IInputSource.
|
||||
/// @brief Input provider providing input from an \see IKeyInputSource.
|
||||
class SampledInputProvider : public InputProvider
|
||||
{
|
||||
public:
|
||||
explicit SampledInputProvider(const IInputSource* inputSource)
|
||||
: _inputSource(inputSource), _inputBufferReadPtr(0), _inputBufferWritePtr(0) { }
|
||||
explicit SampledInputProvider(const IKeyInputSource* keyInputSource, const ITouchInputSource* touchInputSource)
|
||||
: _keyInputSource(keyInputSource), _touchInputSource(touchInputSource)
|
||||
, _inputBufferReadPtr(0), _inputBufferWritePtr(0) { }
|
||||
|
||||
void Update() override;
|
||||
|
||||
/// @brief Samples the input source.
|
||||
void Sample()
|
||||
{
|
||||
_inputBuffer[_inputBufferWritePtr] = _inputSource->Sample();
|
||||
_keyInputBuffer[_inputBufferWritePtr] = _keyInputSource->Sample();
|
||||
_touchInputSource->Sample(_touchInputBuffer[_inputBufferWritePtr]);
|
||||
_inputBufferWritePtr = (_inputBufferWritePtr + 1) & 3;
|
||||
}
|
||||
|
||||
@@ -26,9 +29,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const IInputSource* _inputSource;
|
||||
const IKeyInputSource* _keyInputSource;
|
||||
const ITouchInputSource* _touchInputSource;
|
||||
|
||||
InputKey _inputBuffer[4];
|
||||
InputKey _keyInputBuffer[4];
|
||||
Point _touchInputBuffer[4];
|
||||
u8 _inputBufferReadPtr;
|
||||
u8 _inputBufferWritePtr;
|
||||
};
|
||||
|
||||
24
arm9/source/gui/input/TouchInputSource.h
Normal file
24
arm9/source/gui/input/TouchInputSource.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include <nds/input.h>
|
||||
#include "ITouchInputSource.h"
|
||||
#include "sharedMemory.h"
|
||||
|
||||
/// @brief Input source from the physical DS touch screen.
|
||||
class TouchInputSource : public ITouchInputSource
|
||||
{
|
||||
public:
|
||||
bool Sample(Point& touchPosition) const override
|
||||
{
|
||||
if (SHARED_KEY_XY & (1 << 6))
|
||||
{
|
||||
touchPosition = Point(0, 0);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
touchPosition = Point(SHARED_TOUCH_X, SHARED_TOUCH_Y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -3,15 +3,17 @@
|
||||
|
||||
class Label2DView : public LabelView
|
||||
{
|
||||
public:
|
||||
Label2DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font)
|
||||
: LabelView(width, height, maxStringLength, font, false) { }
|
||||
SHARED_ONLY(Label2DView)
|
||||
|
||||
public:
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
void VBlank() override;
|
||||
|
||||
private:
|
||||
Label2DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font)
|
||||
: LabelView(width, height, maxStringLength, font, false) { }
|
||||
|
||||
void UpdateTileBuffer() override;
|
||||
|
||||
bool _tileBufferUpdated = false;
|
||||
|
||||
@@ -12,6 +12,11 @@ Label3DView::Label3DView(u32 width, u32 height, u32 maxStringLength, const nft2_
|
||||
: LabelView(width, height, maxStringLength, font, true)
|
||||
, _vblankTextureLoader(vblankTextureLoader) { }
|
||||
|
||||
Label3DView::~Label3DView()
|
||||
{
|
||||
_vblankTextureLoader->CancelLoad(_textureLoadRequest);
|
||||
}
|
||||
|
||||
void Label3DView::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
const auto texVramManager = vramContext.GetTexVramManager();
|
||||
|
||||
@@ -4,17 +4,21 @@
|
||||
|
||||
class alignas(32) Label3DView : public LabelView
|
||||
{
|
||||
SHARED_ONLY(Label3DView)
|
||||
|
||||
public:
|
||||
Label3DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font,
|
||||
VBlankTextureLoader* vblankTextureLoader);
|
||||
~Label3DView() override;
|
||||
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
|
||||
private:
|
||||
Label3DView(u32 width, u32 height, u32 maxStringLength, const nft2_header_t* font,
|
||||
VBlankTextureLoader* vblankTextureLoader);
|
||||
|
||||
void UpdateTileBuffer() override;
|
||||
|
||||
u32 _texVramOffset = 0;
|
||||
VBlankTextureLoader* _vblankTextureLoader;
|
||||
VBlankTextureLoadRequest _textureLoadRequest;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "gui/input/InputProvider.h"
|
||||
#include "RecyclerView.h"
|
||||
|
||||
RecyclerView::RecyclerView(Private, int x, int y, int width, int height, Mode mode)
|
||||
RecyclerView::RecyclerView(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)
|
||||
@@ -341,6 +341,117 @@ bool RecyclerView::HandleInput(const InputProvider& inputProvider, FocusManager&
|
||||
return View::HandleInput(inputProvider, focusManager);
|
||||
}
|
||||
|
||||
void RecyclerView::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
|
||||
{
|
||||
if (GetBounds().Contains(touchPoint))
|
||||
{
|
||||
_penDown = true;
|
||||
_penDownPosition = touchPoint;
|
||||
_hasScrollStarted = false;
|
||||
_penDownScrollOffset = _scrollOffsetAnimator.GetValue();
|
||||
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
|
||||
{
|
||||
_viewPool[i].view->HandlePenDown(touchPoint, focusManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecyclerView::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
|
||||
{
|
||||
if (!_penDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_hasScrollStarted)
|
||||
{
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
|
||||
{
|
||||
_viewPool[i].view->HandlePenMove(touchPoint, focusManager);
|
||||
if (focusManager.GetCurrentFocus().GetPointer() == _viewPool[i].view.GetPointer())
|
||||
{
|
||||
SetSelectedItem(_viewPool[i].itemIdx);
|
||||
}
|
||||
}
|
||||
|
||||
int dx = touchPoint.x - _penDownPosition.x;
|
||||
int dy = touchPoint.y - _penDownPosition.y;
|
||||
if (dx * dx + dy * dy > 7 * 7)
|
||||
{
|
||||
bool shouldScrollStart = (_mode == Mode::HorizontalGrid || _mode == Mode::HorizontalList)
|
||||
? (std::abs(touchPoint.x - _penDownPosition.x) > std::abs(touchPoint.y - _penDownPosition.y))
|
||||
: (std::abs(touchPoint.x - _penDownPosition.x) < std::abs(touchPoint.y - _penDownPosition.y));
|
||||
|
||||
if (shouldScrollStart)
|
||||
{
|
||||
_hasScrollStarted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_penDown = false; //wrong direction drag, so cancel it
|
||||
}
|
||||
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
|
||||
{
|
||||
_viewPool[i].view->HandlePenUp(Point(-1, -1), focusManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int newScrollOffset;
|
||||
if (_mode == Mode::HorizontalGrid || _mode == Mode::HorizontalList)
|
||||
{
|
||||
newScrollOffset = _penDownScrollOffset + touchPoint.x - _penDownPosition.x;
|
||||
if (-newScrollOffset < 0)
|
||||
{
|
||||
newScrollOffset = 0;
|
||||
_penDownScrollOffset = 0;
|
||||
_penDownPosition.x = touchPoint.x;
|
||||
}
|
||||
else if (newScrollOffset < GetMaxScrollOffset())
|
||||
{
|
||||
newScrollOffset = GetMaxScrollOffset();
|
||||
_penDownScrollOffset = newScrollOffset;
|
||||
_penDownPosition.x = touchPoint.x;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newScrollOffset = _penDownScrollOffset + touchPoint.y - _penDownPosition.y;
|
||||
if (-newScrollOffset < 0)
|
||||
{
|
||||
newScrollOffset = 0;
|
||||
_penDownScrollOffset = 0;
|
||||
_penDownPosition.y = touchPoint.y;
|
||||
}
|
||||
else if (newScrollOffset < GetMaxScrollOffset())
|
||||
{
|
||||
newScrollOffset = GetMaxScrollOffset();
|
||||
_penDownScrollOffset = newScrollOffset;
|
||||
_penDownPosition.y = touchPoint.y;
|
||||
}
|
||||
}
|
||||
|
||||
SetScrollOffset(newScrollOffset, false);
|
||||
}
|
||||
}
|
||||
|
||||
void RecyclerView::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
|
||||
{
|
||||
for (u32 i = _viewPoolFreeCount; i < _viewPoolTotalCount; i++)
|
||||
{
|
||||
_viewPool[i].view->HandlePenUp(lastTouchPoint, focusManager);
|
||||
if (focusManager.GetCurrentFocus().GetPointer() == _viewPool[i].view.GetPointer())
|
||||
{
|
||||
SetSelectedItem(_viewPool[i].itemIdx);
|
||||
}
|
||||
}
|
||||
|
||||
_penDown = false;
|
||||
}
|
||||
|
||||
Point RecyclerView::GetItemPosition(int itemIdx)
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
#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, public EnableSharedFromThis<RecyclerView>
|
||||
class RecyclerView : public RecyclerViewBase
|
||||
{
|
||||
struct Private { explicit Private() = default; };
|
||||
SHARED_ONLY(RecyclerView)
|
||||
|
||||
public:
|
||||
enum class Mode
|
||||
@@ -24,13 +23,6 @@ public:
|
||||
VerticalGrid
|
||||
};
|
||||
|
||||
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(SharedPtr<const RecyclerAdapter> adapter, int initialSelectedIndex = 0) override;
|
||||
@@ -47,6 +39,9 @@ public:
|
||||
SharedPtr<View> MoveFocus(const SharedPtr<View>& currentFocus, FocusMoveDirection direction, View* source) override;
|
||||
|
||||
bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override;
|
||||
void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) override;
|
||||
void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) override;
|
||||
void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) override;
|
||||
|
||||
void Focus(FocusManager& focusManager) override
|
||||
{
|
||||
@@ -107,6 +102,12 @@ private:
|
||||
int _curRangeStart;
|
||||
int _curRangeLength;
|
||||
Animator<int> _scrollOffsetAnimator;
|
||||
bool _penDown = false;
|
||||
Point _penDownPosition = Point(0, 0);
|
||||
bool _hasScrollStarted = false;
|
||||
int _penDownScrollOffset = 0;
|
||||
|
||||
RecyclerView(int x, int y, int width, int height, Mode mode);
|
||||
|
||||
void UpdatePosition(ViewPoolEntry& viewPoolEntry);
|
||||
ViewPoolEntry* GetViewPoolEntryByItemIndex(int itemIdx);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "core/math/Point.h"
|
||||
#include "core/math/Rectangle.h"
|
||||
#include "core/SharedPtr.h"
|
||||
#include "core/EnableSharedFromThis.h"
|
||||
#include "../FocusManager.h"
|
||||
#include "../FocusMoveDirection.h"
|
||||
|
||||
@@ -11,7 +12,7 @@ class VramContext;
|
||||
class InputProvider;
|
||||
|
||||
/// @brief Base class for views.
|
||||
class View
|
||||
class View : public EnableSharedFromThis<View>
|
||||
{
|
||||
public:
|
||||
/// @brief Link used for views that contain other views.
|
||||
@@ -58,6 +59,21 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Handles a pen down event.
|
||||
/// @param touchPoint The touch point.
|
||||
/// @param focusManager The focus manager.
|
||||
virtual void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) { }
|
||||
|
||||
/// @brief Handles a pen move event.
|
||||
/// @param touchPoint The touch point.
|
||||
/// @param focusManager The focus manager.
|
||||
virtual void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) { }
|
||||
|
||||
/// @brief Handles a pen up event.
|
||||
/// @param lastTouchPoint The last touch point.
|
||||
/// @param focusManager The focus manager.
|
||||
virtual void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) { }
|
||||
|
||||
/// @brief Gets the bounds of the view.
|
||||
/// @return The bounds of the view.
|
||||
virtual Rectangle GetBounds() const = 0;
|
||||
|
||||
58
arm9/source/gui/views/ViewContainer.cpp
Normal file
58
arm9/source/gui/views/ViewContainer.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "common.h"
|
||||
#include "ViewContainer.h"
|
||||
|
||||
void ViewContainer::InitVram(const VramContext& vramContext)
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.InitVram(vramContext);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewContainer::Update()
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.Update();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewContainer::Draw(GraphicsContext& graphicsContext)
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.Draw(graphicsContext);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewContainer::VBlank()
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.VBlank();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewContainer::HandlePenDown(const Point& touchPoint, FocusManager& focusManager)
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.HandlePenDown(touchPoint, focusManager);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewContainer::HandlePenMove(const Point& touchPoint, FocusManager& focusManager)
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.HandlePenMove(touchPoint, focusManager);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewContainer::HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager)
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.HandlePenUp(lastTouchPoint, focusManager);
|
||||
}
|
||||
}
|
||||
@@ -6,37 +6,13 @@
|
||||
class ViewContainer : public View
|
||||
{
|
||||
public:
|
||||
void InitVram(const VramContext& vramContext) override
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.InitVram(vramContext);
|
||||
}
|
||||
}
|
||||
|
||||
void Update() override
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.Update();
|
||||
}
|
||||
}
|
||||
|
||||
void Draw(GraphicsContext& graphicsContext) override
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.Draw(graphicsContext);
|
||||
}
|
||||
}
|
||||
|
||||
void VBlank() override
|
||||
{
|
||||
for (auto& view : _children)
|
||||
{
|
||||
view.VBlank();
|
||||
}
|
||||
}
|
||||
void InitVram(const VramContext& vramContext) override;
|
||||
void Update() override;
|
||||
void Draw(GraphicsContext& graphicsContext) override;
|
||||
void VBlank() override;
|
||||
void HandlePenDown(const Point& touchPoint, FocusManager& focusManager) override;
|
||||
void HandlePenMove(const Point& touchPoint, FocusManager& focusManager) override;
|
||||
void HandlePenUp(const Point& lastTouchPoint, FocusManager& focusManager) override;
|
||||
|
||||
protected:
|
||||
/// @brief Adds a child to the head of the list.
|
||||
@@ -55,6 +31,14 @@ protected:
|
||||
view->SetParent(this);
|
||||
}
|
||||
|
||||
/// @brief Removes a child from the list.
|
||||
/// @param view The child to remove.
|
||||
void RemoveChild(View* view)
|
||||
{
|
||||
_children.Remove(view);
|
||||
view->SetParent(nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedList<View, &View::listLink> _children;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user