Some usability tweaks of the SelectFileScene

- Add title
- Add scroll arrows
- Make it possible to go back to the previous scene
- Increase PokeMe64 version to 0.2
This commit is contained in:
Philippe Symons 2024-09-11 22:00:50 +02:00
parent 28827fc926
commit 9da7dac0b2
9 changed files with 118 additions and 14 deletions

View File

@ -3,14 +3,11 @@
#include "scenes/SceneWithDialogWidget.h"
#include "widget/FileBrowserWidget.h"
#include "widget/ImageWidget.h"
typedef struct SelectFileSceneContext
{
struct {
const char* text;
TextRenderSettings renderSettings;
Rectangle bounds;
} title;
const char* titleText;
struct {
SceneType type;
void* context;
@ -37,6 +34,7 @@ public:
void init() override;
void destroy() override;
bool handleUserInput(joypad_port_t port, const joypad_inputs_t& inputs) override;
void render(RDPQGraphics& gfx, const Rectangle& sceneBounds) override;
void onDialogDone();
@ -52,6 +50,9 @@ private:
DialogData diag_;
SelectFileSceneContext* context_;
sprite_t* dialogWidgetBackgroundSprite_;
sprite_t* uiArrowUpSprite_;
sprite_t* uiArrowDownSprite_;
bool bButtonPressed_;
};
void deleteSelectFileSceneContext(void* context);

View File

@ -6,6 +6,8 @@
#include "widget/IWidget.h"
#include "widget/VerticalList.h"
#include "widget/MenuItemWidget.h"
#include "widget/ImageWidget.h"
#include "widget/IScrollWindowListener.h"
#include <vector>
@ -13,6 +15,8 @@ typedef struct FileBrowserWidgetStyle
{
VerticalListStyle listStyle;
MenuItemStyle itemStyle;
ImageWidgetStyle scrollArrowUpStyle;
ImageWidgetStyle scrollArrowDownStyle;
} FileBrowserWidgetStyle;
typedef struct FileBrowserWidgetStatus
@ -26,7 +30,7 @@ typedef struct FileBrowserWidgetStatus
* select a file
*
*/
class FileBrowserWidget : public IWidget
class FileBrowserWidget : public IWidget, public IScrollWindowListener
{
public:
FileBrowserWidget(AnimationManager& animManager);
@ -122,6 +126,8 @@ public:
* whereas non-matching files WON'T be shown
*/
void setFileExtensionToFilter(const char* fileExtensionFilter);
void onScrollWindowChanged(const ScrollWindowUpdate& update) override;
protected:
private:
void clearList();
@ -133,6 +139,8 @@ private:
// so we need to keep track of them.
std::vector<MenuItemWidget*> itemWidgetList_;
VerticalList listWidget_;
ImageWidget scrollArrowUp_;
ImageWidget scrollArrowDown_;
FileBrowserWidgetStyle style_;
FileBrowserWidgetStatus status_;
Rectangle bounds_;

View File

@ -32,7 +32,7 @@ typedef struct ImageWidgetStyle
SpriteRenderSettings spriteSettings;
/**
* relative bounds of the icon sprite in relation to the MenuItem widget
* relative bounds of the icon sprite in relation to the ImageWidget widget
*/
Rectangle spriteBounds;
} image;

View File

@ -152,6 +152,7 @@ void goToDataCopyScene(void* context, const void* param)
if(operation == DataCopyOperation::RESTORE_SAVE)
{
auto fileSelectContext = new SelectFileSceneContext{
.titleText = "Select Save file",
.nextScene = {
.type = SceneType::COPY_DATA,
.context = dataCopyContext,

View File

@ -31,7 +31,7 @@ github.com/LinusU/pokemon-sprite-compression
github.com/xvillaneau/poke-sprite-python
)delim";
static const char* headerTextString = R"delim(PokeMe64 Version 0.1
static const char* headerTextString = R"delim(PokeMe64 Version 0.2
by risingPhil
SPECIAL THANKS TO:

View File

@ -65,7 +65,7 @@ void InitTransferPakScene::destroy()
void InitTransferPakScene::render(RDPQGraphics& gfx, const Rectangle& sceneBounds)
{
gfx.drawText(Rectangle{0, 10, 320, 16}, "PokeMe64 by risingPhil. Version 0.1", pokeMe64TextSettings_);
gfx.drawText(Rectangle{0, 10, 320, 16}, "PokeMe64 by risingPhil. Version 0.2", pokeMe64TextSettings_);
tpakDetectWidget_.render(gfx, sceneBounds);
SceneWithDialogWidget::render(gfx, sceneBounds);

View File

@ -2,7 +2,8 @@
#include "scenes/SceneManager.h"
#include "scenes/DataCopyScene.h"
static const Rectangle fileBrowserBounds = {20, 20, 280, 200};
static const Rectangle titleBounds = {20, 10, 280, 16};
static const Rectangle fileBrowserBounds = {20, 30, 280, 180};
static void fileConfirmedCallback(void* context, const char* path)
{
@ -26,6 +27,9 @@ SelectFileScene::SelectFileScene(SceneDependencies& deps, void* context)
, diag_({0})
, context_((SelectFileSceneContext*)context)
, dialogWidgetBackgroundSprite_(nullptr)
, uiArrowUpSprite_(nullptr)
, uiArrowDownSprite_(nullptr)
, bButtonPressed_(false)
{
}
@ -45,6 +49,8 @@ void SelectFileScene::init()
}
dialogWidgetBackgroundSprite_ = sprite_load("rom://menu-bg-9slice.sprite");
uiArrowUpSprite_ = sprite_load("rom://ui-arrow-up.sprite");
uiArrowDownSprite_ = sprite_load("rom://ui-arrow-down.sprite");
SceneWithDialogWidget::init();
@ -58,7 +64,8 @@ void SelectFileScene::init()
}
},
.margin = {
.top = 5
.top = 5,
.bottom = 5
}
},
.itemStyle = {
@ -73,6 +80,18 @@ void SelectFileScene::init()
},
.leftMargin = 10,
.topMargin = 1
},
.scrollArrowUpStyle = {
.image = {
.sprite = uiArrowUpSprite_,
.spriteBounds = Rectangle{0, 0, uiArrowUpSprite_->width, uiArrowUpSprite_->height}
}
},
.scrollArrowDownStyle = {
.image = {
.sprite = uiArrowDownSprite_,
.spriteBounds = Rectangle{0, 0, uiArrowDownSprite_->width, uiArrowDownSprite_->height}
}
}
};
@ -93,6 +112,50 @@ void SelectFileScene::destroy()
sprite_free(dialogWidgetBackgroundSprite_);
dialogWidgetBackgroundSprite_ = nullptr;
}
if(uiArrowUpSprite_)
{
sprite_free(uiArrowUpSprite_);
uiArrowUpSprite_ = nullptr;
}
if(uiArrowDownSprite_)
{
sprite_free(uiArrowDownSprite_);
uiArrowDownSprite_ = nullptr;
}
}
bool SelectFileScene::handleUserInput(joypad_port_t port, const joypad_inputs_t& inputs)
{
bool goBackToPreviousSceneOnUnhandledBPress = false;
// keep track of the b button
// if the FileBrowserWidget doesn't handle the release
// then we need to go back to the previous scene
if(!bButtonPressed_ && inputs.btn.b)
{
bButtonPressed_ = true;
}
else if(bButtonPressed_ && !inputs.btn.b)
{
bButtonPressed_ = false;
goBackToPreviousSceneOnUnhandledBPress = true;
}
bool ret = SceneWithDialogWidget::handleUserInput(port, inputs);
if(ret)
{
return ret;
}
if(goBackToPreviousSceneOnUnhandledBPress)
{
deps_.sceneManager.goBackToPreviousScene();
return true;
}
return false;
// not handled by normal means
}
void SelectFileScene::render(RDPQGraphics& gfx, const Rectangle& sceneBounds)
@ -100,10 +163,15 @@ void SelectFileScene::render(RDPQGraphics& gfx, const Rectangle& sceneBounds)
fileBrowser_.render(gfx, sceneBounds);
SceneWithDialogWidget::render(gfx, sceneBounds);
if(context_->title.text && !isZeroSizeRectangle(context_->title.bounds))
if(context_->titleText && !isZeroSizeRectangle(titleBounds))
{
const Rectangle absoluteTextBounds = addOffset(context_->title.bounds, sceneBounds);
gfx.drawText(absoluteTextBounds, context_->title.text, context_->title.renderSettings);
const TextRenderSettings renderSettings = {
.fontId = arialId_,
.fontStyleId = fontStyleWhiteId_,
.halign = ALIGN_CENTER
};
const Rectangle absoluteTextBounds = addOffset(titleBounds, sceneBounds);
gfx.drawText(absoluteTextBounds, context_->titleText, renderSettings);
}
}

View File

@ -17,6 +17,8 @@ FileBrowserWidget::FileBrowserWidget(AnimationManager& animManager)
: duplicatedDirEntNameList_()
, itemWidgetList_()
, listWidget_(animManager)
, scrollArrowUp_()
, scrollArrowDown_()
, style_({0})
, status_({
.itemList = itemWidgetList_,
@ -32,10 +34,12 @@ FileBrowserWidget::FileBrowserWidget(AnimationManager& animManager)
, bButtonPressed_(false)
{
pathBuffer_[0] = '\0';
listWidget_.registerScrollWindowListener(this);
}
FileBrowserWidget::~FileBrowserWidget()
{
listWidget_.unregisterScrollWindowListener(this);
clearList();
}
@ -69,6 +73,9 @@ void FileBrowserWidget::setBounds(const Rectangle& bounds)
{
bounds_ = bounds;
listWidget_.setBounds(Rectangle{0, 0, bounds.width, bounds.height});
scrollArrowUp_.setBounds(Rectangle{bounds.width / 2, -6, style_.scrollArrowUpStyle.image.spriteBounds.width, style_.scrollArrowUpStyle.image.spriteBounds.height});
scrollArrowDown_.setBounds(Rectangle{bounds.width / 2, bounds.height, style_.scrollArrowDownStyle.image.spriteBounds.width, style_.scrollArrowDownStyle.image.spriteBounds.height});
}
Dimensions FileBrowserWidget::getSize() const
@ -78,8 +85,18 @@ Dimensions FileBrowserWidget::getSize() const
void FileBrowserWidget::setStyle(const FileBrowserWidgetStyle& style)
{
const Rectangle bounds = getBounds();
style_ = style;
listWidget_.setStyle(style.listStyle);
scrollArrowUp_.setStyle(style.scrollArrowUpStyle);
scrollArrowUp_.setBounds(Rectangle{bounds.width / 2, -6, style.scrollArrowUpStyle.image.spriteBounds.width, style.scrollArrowUpStyle.image.spriteBounds.height});
// note: even though autogrow is turned on for the vertical list, it doesn't matter for the down arrow.
// because when the list is still growing, no scrolling is needed anyway, so the arrow would be invisible anyway.
scrollArrowDown_.setStyle(style.scrollArrowDownStyle);
scrollArrowDown_.setBounds(Rectangle{bounds.width / 2, bounds.height, style.scrollArrowDownStyle.image.spriteBounds.width, style.scrollArrowDownStyle.image.spriteBounds.height});
}
bool FileBrowserWidget::handleUserInput(const joypad_inputs_t& userInput)
@ -113,6 +130,8 @@ void FileBrowserWidget::render(RDPQGraphics& gfx, const Rectangle& parentBounds)
const Rectangle absoluteBounds = addOffset(bounds_, parentBounds);
listWidget_.render(gfx, absoluteBounds);
scrollArrowUp_.render(gfx, absoluteBounds);
scrollArrowDown_.render(gfx, absoluteBounds);
}
const FileBrowserWidgetStatus& FileBrowserWidget::getStatus() const
@ -183,6 +202,12 @@ void FileBrowserWidget::setFileExtensionToFilter(const char* fileExtensionFilter
loadDirectoryItems();
}
void FileBrowserWidget::onScrollWindowChanged(const ScrollWindowUpdate& update)
{
scrollArrowUp_.setVisible(canScrollTo(update, UINavigationDirection::UP));
scrollArrowDown_.setVisible(canScrollTo(update, UINavigationDirection::DOWN));
}
void FileBrowserWidget::clearList()
{
listWidget_.clearWidgets();

View File

@ -246,6 +246,7 @@ void VerticalList::clearWidgets()
widgetList_.clear();
widgetBoundsList_.clear();
focusedWidgetIndex_ = 0;
windowMinY_ = 0;
notifyScrollWindowListeners();
}