Merge DirButton into GameButton

This commit is contained in:
Henrik Rydgård committed 2026-11-01 10:24:34 +01:00
1 parent 3f5a79bfbc
commit ede471aee6
4 files changed
+162 -159

No files matched your search

+1 -1
View File
@@ -59,7 +59,7 @@ public:
}
bool Valid() const { return !path_.empty(); }
bool IsRoot() const { return path_ == "/"; } // Special value - only path that can end in a slash.
bool IsRoot() const { return path_ == "/"; } // Special value - only path that can end in a slash - except see below.
// On Windows, "//" is the network folder that lists the servers, the other path that ends in a slash.
bool IsNetworkRoot() const {
#if PPSSPP_PLATFORM(WINDOWS)
+33 -85
View File
@@ -54,70 +54,6 @@
// Folders get bigger lines too, though not as big as the games.
static constexpr float LARGE_LIST_FOLDER_H = 50.0f;
class DirButton : public UI::Button {
public:
DirButton(const Path &path, GameBrowserViewMode viewMode, UI::LayoutParams *layoutParams)
: UI::Button(path.ToString(), layoutParams), path_(path), viewMode_(viewMode), absolute_(false) {}
DirButton(const Path &path, const std::string &text, GameBrowserViewMode viewMode, UI::LayoutParams *layoutParams = 0)
: UI::Button(text, layoutParams), path_(path), viewMode_(viewMode), absolute_(true) {}
void Draw(UIContext &dc) override;
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
UI::Button::GetContentDimensions(dc, w, h);
if (viewMode_ == GameBrowserViewMode::LARGE_LIST) {
h = std::max(h, LARGE_LIST_FOLDER_H * g_Config.fGameGridScale + LARGE_LIST_PAD * 2);
}
}
const Path &GetPath() const {
return path_;
}
bool PathAbsolute() const {
return absolute_;
}
void SetPinned(bool pin) {
pinned_ = pin;
}
std::string DescribeText() const override {
return std::string(Button::GetText()); // From Button
}
private:
Path path_;
GameBrowserViewMode viewMode_;
bool absolute_;
bool pinned_ = false;
};
void DirButton::Draw(UIContext &dc) {
using namespace UI;
std::string_view text(GetText());
ImageID image = ImageID(pinned_ ? "I_FOLDER_PINNED" : "I_FOLDER");
if (path_.IsNetworkRoot()) {
image = ImageID("I_NETWORK");
} else if (text == "..") {
image = ImageID("I_UP_DIRECTORY");
text = "";
}
Style style = dc.GetTheme().itemStyle;
if (HasFocus()) style = dc.GetTheme().itemFocusedStyle;
if (down_) style = dc.GetTheme().itemDownStyle;
if (!IsEnabled()) style = dc.GetTheme().itemDisabledStyle;
dc.FillRect(style.background, bounds_);
if (viewMode_ == GameBrowserViewMode::GRID) {
DrawIconWithTextGrid(dc, image, text, bounds_, style);
} else {
DrawIconWithTextList(dc, image, text, bounds_, viewMode_, style);
}
}
GameBrowser::GameBrowser(int token, const Path &path, BrowseFlags browseFlags, bool portrait, int *viewMode, ScreenManager *screenManager, std::string_view lastText, std::string_view lastLink, UI::LayoutParams *layoutParams)
: LinearLayout(ORIENT_VERTICAL, layoutParams), viewMode_(viewMode), browseFlags_(browseFlags), portrait_(portrait), lastText_(lastText), lastLink_(lastLink), screenManager_(screenManager), token_(token) {
using namespace UI;
@@ -138,19 +74,19 @@ GameBrowser::GameBrowser(int token, const Path &path, BrowseFlags browseFlags, b
Refresh();
}
void GameBrowser::FocusGame(const Path &gamePath) {
void GameBrowser::FocusGame(const Path &GetPath) {
// If the button's still there, just focus it. That keeps the search results and scroll position.
if (gameList_) {
for (int i = 0; i < gameList_->GetNumSubviews(); i++) {
GameButton *button = dynamic_cast<GameButton *>(gameList_->GetViewByIndex(i));
if (button && button->GamePath() == gamePath && button->GetVisibility() == UI::V_VISIBLE) {
if (button && button->GetPath() == GetPath && button->GetVisibility() == UI::V_VISIBLE) {
button->SetFocus(UI::FocusFlags::CAUSE_RESTORE);
return;
}
}
}
// Otherwise, Refresh focuses it when it recreates the buttons.
focusPath_ = gamePath;
focusPath_ = GetPath;
refreshPending_ = true;
}
@@ -490,7 +426,7 @@ void GameBrowser::Refresh() {
Add(gameList_);
// Find games in the current directory and create new ones.
std::vector<DirButton *> dirButtons;
std::vector<GameButton *> dirButtons;
std::vector<GameButton *> gameButtons;
listingPending_ = !path_.IsListingReady();
@@ -500,7 +436,7 @@ void GameBrowser::Refresh() {
std::vector<Path> filenames;
if (HasSpecialFiles(filenames)) {
for (size_t i = 0; i < filenames.size(); i++) {
gameButtons.push_back(new GameButton(filenames[i], lastViewMode_, new UI::LinearLayoutParams(gridStyle ? UI::WRAP_CONTENT : UI::FILL_PARENT, UI::WRAP_CONTENT)));
gameButtons.push_back(new GameButton(GameButtonType::Game, filenames[i], lastViewMode_, new UI::LinearLayoutParams(gridStyle ? UI::WRAP_CONTENT : UI::FILL_PARENT, UI::WRAP_CONTENT)));
}
} else if (!listingPending_) {
std::vector<File::FileInfo> fileInfo;
@@ -524,11 +460,13 @@ void GameBrowser::Refresh() {
if (!isGame && !isSaveData) {
if (browseFlags_ & BrowseFlags::NAVIGATE) {
const std::string name = fileInfo[i].fullName.IsNetworkRoot() ? std::string(mm->T("Network")) : fileInfo[i].name;
dirButtons.push_back(new DirButton(fileInfo[i].fullName, name, lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)));
dirButtons.push_back(new GameButton(GameButtonType::Dir, fileInfo[i].fullName, lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)));
if (fileInfo[i].fullName.IsNetworkRoot()) {
dirButtons.back()->SetAsAbsolute();
}
}
} else {
gameButtons.push_back(new GameButton(fileInfo[i].fullName, lastViewMode_, new UI::LinearLayoutParams(gridStyle ? UI::WRAP_CONTENT : UI::FILL_PARENT, UI::WRAP_CONTENT)));
gameButtons.push_back(new GameButton(GameButtonType::Game, fileInfo[i].fullName, lastViewMode_, new UI::LinearLayoutParams(gridStyle ? UI::WRAP_CONTENT : UI::FILL_PARENT, UI::WRAP_CONTENT)));
}
}
@@ -541,8 +479,7 @@ void GameBrowser::Refresh() {
if (!fileInfo.empty()) {
for (size_t i = 0; i < fileInfo.size(); i++) {
if (!fileInfo[i].isDirectory) {
GameButton *b = new GameButton(fileInfo[i].fullName, lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT));
b->SetHoldEnabled(false);
GameButton *b = new GameButton(GameButtonType::Other, fileInfo[i].fullName, lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT));
gameButtons.push_back(b);
}
}
@@ -550,19 +487,20 @@ void GameBrowser::Refresh() {
}
}
DirButton *upButton = nullptr;
GameButton *upButton = nullptr;
if (browseFlags_ & BrowseFlags::NAVIGATE) {
if (path_.CanNavigateUp()) {
upButton = gameList_->Add(new DirButton(Path(".."), lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)));
upButton = gameList_->Add(new GameButton(GameButtonType::Dir, Path(".."), lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)));
upButton->OnClick.Handle(this, &GameBrowser::NavigateClick);
}
// Add any pinned paths before other directories.
auto pinnedPaths = GetPinnedPaths();
for (const auto &pinnedPath : pinnedPaths) {
DirButton *pinnedDir = gameList_->Add(new DirButton(pinnedPath, pinnedPath.GetFilename(), lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)));
GameButton *pinnedDir = gameList_->Add(new GameButton(GameButtonType::Dir, pinnedPath, lastViewMode_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)));
pinnedDir->OnClick.Handle(this, &GameBrowser::NavigateClick);
pinnedDir->SetPinned(true);
pinnedDir->SetAsAbsolute();
}
}
@@ -583,7 +521,7 @@ void GameBrowser::Refresh() {
b->OnHoldClick.Handle(this, &GameBrowser::GameButtonHoldClick);
b->OnHighlight.Handle(this, &GameBrowser::GameButtonHighlight);
if (!focusPath_.empty() && b->GamePath() == focusPath_ && b->SetFocus(FocusFlags::CAUSE_RESTORE)) {
if (!focusPath_.empty() && b->GetPath() == focusPath_ && b->SetFocus(FocusFlags::CAUSE_RESTORE)) {
UI::ScrollFocusedViewIntoView();
}
}
@@ -601,6 +539,7 @@ void GameBrowser::Refresh() {
}
// Show a button to toggle pinning at the very end.
// TODO: That's not very friendly.
if ((browseFlags_ & BrowseFlags::PIN) && !path_.GetPath().empty()) {
std::string caption = ""; // IsCurrentPathPinned() ? "-" : "+";
if (!gridStyle) {
@@ -668,16 +607,22 @@ std::vector<Path> GameBrowser::GetPinnedPaths() const {
}
void GameBrowser::GameButtonClick(UI::EventParams &e) {
GameButton *button = static_cast<GameButton *>(e.v);
GameButton *button = dynamic_cast<GameButton *>(e.v);
if (!button) {
return;
}
UI::EventParams e2{};
e2.s = button->GamePath().ToString();
e2.s = button->GetPath().ToString();
OnChoice.Trigger(e2);
}
void GameBrowser::GameButtonHoldClick(UI::EventParams &e) {
GameButton *button = static_cast<GameButton *>(e.v);
GameButton *button = dynamic_cast<GameButton *>(e.v);
if (!button) {
return;
}
UI::EventParams e2{};
e2.s = button->GamePath().ToString();
e2.s = button->GetPath().ToString();
OnHoldChoice.Trigger(e2);
}
@@ -686,15 +631,18 @@ void GameBrowser::GameButtonHighlight(UI::EventParams &e) {
}
void GameBrowser::NavigateClick(UI::EventParams &e) {
DirButton *button = static_cast<DirButton *>(e.v);
GameButton *button = dynamic_cast<GameButton *>(e.v);
if (!button) {
return;
}
Path text = button->GetPath();
if (button->PathAbsolute()) {
if (button->NavigateAsAbsolute()) {
path_.SetPath(text);
} else if (text.ToString() == "..") {
NavigateUp();
return;
} else {
path_.Navigate(text.ToString());
path_.Navigate(text.GetFilename());
}
focusFirstItem_ = true;
PathChanged();
+97 -49
View File
@@ -96,6 +96,7 @@ static ImageID ChooseGameIcon(const std::shared_ptr<GameInfo> &ginfo) {
case IdentifiedFileType::ARCHIVE_7Z: return ImageID("I_ARCHIVE_7Z"); break;
case IdentifiedFileType::ARCHIVE_RAR: return ImageID("I_ARCHIVE_RAR"); break;
case IdentifiedFileType::PSP_PKG: return ImageID("I_FOLDER_UPLOAD"); break;
case IdentifiedFileType::NORMAL_DIRECTORY: return ImageID("I_FOLDER"); break;
case IdentifiedFileType::PSP_ISO:
case IdentifiedFileType::PSP_ISO_NP:
@@ -176,18 +177,88 @@ void DrawIconWithTextList(UIContext &dc, ImageID image, std::string_view text, c
}
}
void GameButton::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
switch (viewMode_) {
case GameBrowserViewMode::GRID:
w = 144 * g_Config.fGameGridScale;
h = 80 * g_Config.fGameGridScale;
break;
case GameBrowserViewMode::LARGE_LIST:
w = 500;
if (type_ == GameButtonType::Dir) {
h = UI::ITEM_HEIGHT;
} else {
h = LARGE_LIST_ICON_H * g_Config.fGameGridScale + LARGE_LIST_PAD * 2;
}
break;
default: // List
w = 500;
h = 56;
break;
}
}
void GameButton::Draw(UIContext &dc) {
// Like the XMB, only the selected game plays its video. Only keyboard/gamepad focus selects, since with
// touch or the mouse, getting a video to play without launching the game was too fiddly.
const bool wantVideo = viewMode_ == GameBrowserViewMode::LARGE_LIST && HasFocus() && pmf_player_available();
GameInfoFlags infoFlags = GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON;
if (wantVideo) {
infoFlags |= GameInfoFlags::ICON1_PMF;
}
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, infoFlags);
UpdateVideo(ginfo, wantVideo);
std::shared_ptr<GameInfo> ginfo;
std::string text;
std::string id_version;
Draw::Texture *texture = nullptr;
ImageID imageIcon;
int regionIndex = -1;
IdentifiedFileType fileType = IdentifiedFileType::UNKNOWN;
if (type_ == GameButtonType::Dir) {
text = gamePath_.GetFilename();
imageIcon = ImageID(IsPinned() ? "I_FOLDER_PINNED" : "I_FOLDER");
if (gamePath_.IsNetworkRoot()) {
imageIcon = ImageID("I_NETWORK");
auto mm = GetI18NCategory(I18NCat::MAINMENU);
text = mm->T("Network");
} else if (text == "..") {
imageIcon = ImageID("I_UP_DIRECTORY");
text = "";
}
fileType = IdentifiedFileType::NORMAL_DIRECTORY;
} else {
GameInfoFlags infoFlags = GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON;
if (wantVideo) {
infoFlags |= GameInfoFlags::ICON1_PMF;
}
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, infoFlags);
UpdateVideo(ginfo, wantVideo);
imageIcon = ChooseGameIcon(ginfo);
if (ginfo->Ready(GameInfoFlags::ICON)) {
if (ginfo->icon.texture) {
texture = ginfo->icon.texture;
// The type icon is only for when there's no picture, and would be drawn on top of it.
imageIcon = ImageID::invalid();
} else {
// No icon, but drawBackground is set. Let's show a plain icon depending on type.
imageIcon = ChooseGameIcon(ginfo);
}
} else if (gamePath_.Type() == PathType::HTTP) {
// Make sure that pending HTTP icons show something, instead of just blank.
// Maybe we should show something for other file types too.
imageIcon = ImageID("I_LINK_OUT_QUESTION");
}
text = ginfo->GetTitle();
id_version = ginfo->GetTitle();
regionIndex = (int)ginfo->region;
fileType = ginfo->fileType;
}
if (video_) {
Draw::Texture *frame = video_->Update(dc.GetDrawContext(), videoStart_.ElapsedSeconds());
if (frame) {
texture = frame;
}
}
u32 color = 0, shadowColor = 0;
using namespace UI;
@@ -196,33 +267,6 @@ void GameButton::Draw(UIContext &dc) {
style = dc.GetTheme().itemDownStyle;
}
// Some types we just draw a default icon for.
ImageID imageIcon = ChooseGameIcon(ginfo);
if (ginfo->Ready(GameInfoFlags::ICON)) {
if (ginfo->icon.texture) {
texture = ginfo->icon.texture;
// The type icon is only for when there's no picture, and would be drawn on top of it.
imageIcon = ImageID::invalid();
} else {
// No icon, but drawBackground is set. Let's show a plain icon depending on type.
imageIcon = ChooseGameIcon(ginfo);
}
} else if (gamePath_.Type() == PathType::HTTP) {
// Make sure that pending HTTP icons show something, instead of just blank.
// Maybe we should show something for other file types too.
imageIcon = ImageID("I_LINK_OUT_QUESTION");
}
Bounds iconBounds = bounds_;
iconBounds.w = viewMode_ == GameBrowserViewMode::GRID ? bounds_.w : 144;
if (viewMode_ == GameBrowserViewMode::LARGE_LIST) {
iconBounds.x += LARGE_LIST_LEFT_PAD;
iconBounds.y += LARGE_LIST_PAD;
iconBounds.w = LARGE_LIST_ICON_W * g_Config.fGameGridScale;
iconBounds.h = LARGE_LIST_ICON_H * g_Config.fGameGridScale;
}
const float textX = ListTextX(viewMode_);
const bool rowFocused = HasFocus() && !infoSelected_;
if (viewMode_ != GameBrowserViewMode::GRID || !texture) {
if (rowFocused)
@@ -236,14 +280,18 @@ void GameButton::Draw(UIContext &dc) {
dc.Draw()->Flush();
}
if (texture && video_) {
Draw::Texture *frame = video_->Update(dc.GetDrawContext(), videoStart_.ElapsedSeconds());
if (frame) {
texture = frame;
}
// Some types we just draw a default icon for.
Bounds iconBounds = bounds_;
iconBounds.w = viewMode_ == GameBrowserViewMode::GRID ? bounds_.w : 144;
if (viewMode_ == GameBrowserViewMode::LARGE_LIST) {
iconBounds.x += LARGE_LIST_LEFT_PAD;
iconBounds.y += LARGE_LIST_PAD;
iconBounds.w = LARGE_LIST_ICON_W * g_Config.fGameGridScale;
iconBounds.h = LARGE_LIST_ICON_H * g_Config.fGameGridScale;
}
const float textX = ListTextX(viewMode_);
if (texture) {
if (texture && ginfo) {
color = whiteAlpha(ease((time_now_d() - ginfo->icon.timeLoaded) * 2));
shadowColor = blackAlpha(ease((time_now_d() - ginfo->icon.timeLoaded) * 2));
float tw = texture->Width();
@@ -295,9 +343,9 @@ void GameButton::Draw(UIContext &dc) {
dc.Draw()->Flush();
}
if (viewMode_ == GameBrowserViewMode::GRID && g_Config.bShowIDOnGameIcon && ginfo->fileType != IdentifiedFileType::PSP_ELF && !ginfo->id_version.empty()) {
if (viewMode_ == GameBrowserViewMode::GRID && g_Config.bShowIDOnGameIcon && fileType != IdentifiedFileType::PSP_ELF && !id_version.empty()) {
std::string_view idStr = ginfo->id_version;
if (ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
if (fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
auto ga = GetI18NCategory(I18NCat::GAME);
idStr = ga->T("SaveData");
}
@@ -315,17 +363,18 @@ void GameButton::Draw(UIContext &dc) {
if (!IsEnabled()) style = dc.GetTheme().itemDisabledStyle;
if (viewMode_ == GameBrowserViewMode::GRID) {
DrawIconWithTextGrid(dc, imageIcon, ginfo->GetTitle(), bounds_, style);
DrawIconWithTextGrid(dc, imageIcon, text, bounds_, style);
} else {
DrawIconWithTextList(dc, imageIcon, ginfo->GetTitle(), bounds_, viewMode_, style, g_Config.bShowIDOnGameIcon ? std::string_view(ginfo->id_version) : std::string_view());
DrawIconWithTextList(dc, imageIcon, text, bounds_, viewMode_, style, g_Config.bShowIDOnGameIcon ? std::string_view(id_version) : std::string_view());
}
} else {
/*
char discNumInfo[8];
if (ginfo->disc_total > 1)
snprintf(discNumInfo, sizeof(discNumInfo), "-DISC%d", ginfo->disc_number);
else
discNumInfo[0] = '\0';
*/
dc.Draw()->Flush();
dc.RebindTexture();
dc.SetFontStyle(dc.GetTheme().uiFont);
@@ -333,7 +382,7 @@ void GameButton::Draw(UIContext &dc) {
float tw, th;
dc.Draw()->Flush();
dc.PushScissor(bounds_);
const std::string currentTitle = ginfo->GetTitle();
const std::string currentTitle = text;
if (!currentTitle.empty()) {
title_ = ReplaceAll(currentTitle, "\n", " ");
}
@@ -343,10 +392,10 @@ void GameButton::Draw(UIContext &dc) {
int availableWidth = bounds_.w - textX - ListTextRightMargin(viewMode_);
if (g_Config.bShowIDOnGameIcon) {
float vw, vh;
dc.MeasureText(dc.GetFontStyle(), 0.7f, 0.7f, ginfo->id_version, &vw, &vh, 0);
dc.MeasureText(dc.GetFontStyle(), 0.7f, 0.7f, id_version, &vw, &vh, 0);
availableWidth -= vw + 20;
dc.SetFontScale(0.7f, 0.7f);
dc.DrawText(ginfo->id_version, bounds_.x + availableWidth + textX + 10, bounds_.centerY(), style.fgColor, ALIGN_VCENTER);
dc.DrawText(id_version, bounds_.x + availableWidth + textX + 10, bounds_.centerY(), style.fgColor, ALIGN_VCENTER);
dc.SetFontScale(1.0f, 1.0f);
}
float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f;
@@ -376,7 +425,7 @@ void GameButton::Draw(UIContext &dc) {
}
}
if (ginfo->hasConfig && !ginfo->id.empty()) {
if (ginfo && ginfo->hasConfig && !ginfo->id.empty()) {
const AtlasImage *gearImage = dc.Draw()->GetAtlas()->getImage(ImageID("I_GEAR_SMALL"));
if (gearImage) {
if (viewMode_ == GameBrowserViewMode::GRID) {
@@ -389,7 +438,6 @@ void GameButton::Draw(UIContext &dc) {
}
}
const int regionIndex = (int)ginfo->region;
if (g_Config.bShowRegionOnGameIcon && regionIndex >= 0 && regionIndex < (int)GameRegion::COUNT) {
const ImageID regionIcons[(int)GameRegion::COUNT] = {
ImageID("I_FLAG_JP"),
+31 -24
View File
@@ -40,10 +40,16 @@ static constexpr float LARGE_LIST_PAD = 6.0f;
static constexpr float LARGE_LIST_LEFT_PAD = 11.0f;
static constexpr float LARGE_LIST_INFO_SIZE = 64.0f;
enum class GameButtonType {
Game,
Other,
Dir,
};
class GameButton : public UI::Clickable {
public:
GameButton(const Path &gamePath, GameBrowserViewMode viewMode, UI::LayoutParams *layoutParams = nullptr)
: UI::Clickable(layoutParams), viewMode_(viewMode), gamePath_(gamePath) {}
GameButton(GameButtonType type, const Path &gamePath, GameBrowserViewMode viewMode, UI::LayoutParams *layoutParams = nullptr)
: UI::Clickable(layoutParams), type_(type), viewMode_(viewMode), gamePath_(gamePath) {}
void Draw(UIContext &dc) override;
std::string DescribeText() const override;
@@ -57,26 +63,10 @@ public:
}
return filename;
}
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
switch (viewMode_) {
case GameBrowserViewMode::GRID:
w = 144 * g_Config.fGameGridScale;
h = 80 * g_Config.fGameGridScale;
break;
case GameBrowserViewMode::LARGE_LIST:
w = 500;
h = LARGE_LIST_ICON_H * g_Config.fGameGridScale + LARGE_LIST_PAD * 2;
break;
default: // List
w = 500;
h = 50;
break;
}
}
const Path &GamePath() const { return gamePath_; }
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;
void SetHoldEnabled(bool hold) {
holdEnabled_ = hold;
bool IsHoldEnabled() const {
return type_ == GameButtonType::Game;
}
bool Touch(const TouchInput &input) override {
hovering_ = bounds_.Contains(input.x, input.y);
@@ -133,7 +123,7 @@ public:
}
// Holding the accept button works like a long press, so a gamepad can do it too.
if (holdEnabled_ && HasFocus() && UI::IsAcceptKey(key) && !(key.flags & KeyInputFlags::IS_REPEAT)) {
if (IsHoldEnabled() && HasFocus() && UI::IsAcceptKey(key) && !(key.flags & KeyInputFlags::IS_REPEAT)) {
if (key.flags & KeyInputFlags::DOWN) {
holdStart_ = time_now_d();
}
@@ -147,7 +137,7 @@ public:
void Update() override {
// Hold button for 1.5 seconds to launch the game options
if (holdEnabled_ && holdStart_ != 0.0 && holdStart_ < time_now_d() - 1.5) {
if (IsHoldEnabled() && holdStart_ != 0.0 && holdStart_ < time_now_d() - 1.5) {
TriggerOnHoldClick();
}
}
@@ -189,6 +179,17 @@ public:
}
}
// Previously in DirButton
// This only determines if the little pin icon is shown.
void SetPinned(bool pin) { pinned_ = pin; }
bool IsPinned() const { return pinned_; }
void SetAsAbsolute() { absolute_ = true; }
bool NavigateAsAbsolute() const { return absolute_; }
const Path &GetPath() const { return gamePath_; }
UI::Event OnHoldClick;
UI::Event OnHighlight;
@@ -213,7 +214,7 @@ private:
// The large list has room for an info button on each line, doing the same as a long press.
bool HasInfoButton() const {
return viewMode_ == GameBrowserViewMode::LARGE_LIST && holdEnabled_;
return viewMode_ == GameBrowserViewMode::LARGE_LIST && type_ == GameButtonType::Game;
}
Bounds InfoButtonBounds() const {
return Bounds(bounds_.x2() - LARGE_LIST_INFO_SIZE - LARGE_LIST_PAD, bounds_.centerY() - LARGE_LIST_INFO_SIZE * 0.5f, LARGE_LIST_INFO_SIZE, LARGE_LIST_INFO_SIZE);
@@ -255,6 +256,12 @@ private:
bool infoButtonDown_ = false;
// The info button has the keyboard focus, rather than the game. Changed from CanMoveFocus, hence mutable.
mutable bool infoSelected_ = false;
// Previously in DirButton
bool pinned_ = false;
bool absolute_ = false;
GameButtonType type_;
};
// Also used for the folder buttons.