From ede471aee6d421a781dc0d30050cd76adfed69f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 1 Nov 2026 10:24:34 +0100 Subject: [PATCH] Merge DirButton into GameButton --- Common/File/Path.h | 2 +- UI/GameBrowser.cpp | 118 ++++++++++-------------------------- UI/GameButton.cpp | 146 ++++++++++++++++++++++++++++++--------------- UI/GameButton.h | 55 +++++++++-------- 4 files changed, 162 insertions(+), 159 deletions(-) diff --git a/Common/File/Path.h b/Common/File/Path.h index ab77b82a3a..534a93e2a0 100644 --- a/Common/File/Path.h +++ b/Common/File/Path.h @@ -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) diff --git a/UI/GameBrowser.cpp b/UI/GameBrowser.cpp index 5ee36c6846..99dd05f35e 100644 --- a/UI/GameBrowser.cpp +++ b/UI/GameBrowser.cpp @@ -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(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 dirButtons; + std::vector dirButtons; std::vector gameButtons; listingPending_ = !path_.IsListingReady(); @@ -500,7 +436,7 @@ void GameBrowser::Refresh() { std::vector 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 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 GameBrowser::GetPinnedPaths() const { } void GameBrowser::GameButtonClick(UI::EventParams &e) { - GameButton *button = static_cast(e.v); + GameButton *button = dynamic_cast(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(e.v); + GameButton *button = dynamic_cast(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(e.v); + GameButton *button = dynamic_cast(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(); diff --git a/UI/GameButton.cpp b/UI/GameButton.cpp index e93773c06c..60eab60f57 100644 --- a/UI/GameButton.cpp +++ b/UI/GameButton.cpp @@ -96,6 +96,7 @@ static ImageID ChooseGameIcon(const std::shared_ptr &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 ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, infoFlags); - UpdateVideo(ginfo, wantVideo); + std::shared_ptr 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"), diff --git a/UI/GameButton.h b/UI/GameButton.h index 5d222b1db8..3a691f91aa 100644 --- a/UI/GameButton.h +++ b/UI/GameButton.h @@ -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.