mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 06:05:38 +00:00
When marking or unmarking a game as favorite, the cursor position is now retained.
This commit is contained in:
parent
fd92f7f86d
commit
83bae1e963
|
@ -1,4 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// EmulationStation Desktop Edition
|
||||
// BasicGameListView.cpp
|
||||
//
|
||||
// Interface that defines a GameListView of the type 'Basic'.
|
||||
|
@ -46,10 +48,15 @@ void BasicGameListView::onFileChanged(FileData* file, FileChangeType change)
|
|||
|
||||
void BasicGameListView::populateList(const std::vector<FileData*>& files)
|
||||
{
|
||||
firstGameEntry = nullptr;
|
||||
|
||||
mList.clear();
|
||||
mHeaderText.setText(mRoot->getSystem()->getFullName());
|
||||
if (files.size() > 0) {
|
||||
for (auto it = files.cbegin(); it != files.cend(); it++) {
|
||||
if (!firstGameEntry && (*it)->getType() == GAME)
|
||||
firstGameEntry = (*it);
|
||||
|
||||
if ((*it)->getFavorite() &&
|
||||
mRoot->getSystem()->getName() != "favorites") {
|
||||
mList.add(FAVORITE_GAME_CHAR + " " + (*it)->getName(),
|
||||
|
@ -100,6 +107,16 @@ void BasicGameListView::setCursor(FileData* cursor)
|
|||
}
|
||||
}
|
||||
|
||||
FileData* BasicGameListView::getNextEntry()
|
||||
{
|
||||
return mList.getNext();
|
||||
}
|
||||
|
||||
FileData* BasicGameListView::getPreviousEntry()
|
||||
{
|
||||
return mList.getPrevious();
|
||||
}
|
||||
|
||||
FileData* BasicGameListView::getFirstEntry()
|
||||
{
|
||||
return mList.getFirst();
|
||||
|
@ -110,6 +127,11 @@ FileData* BasicGameListView::getLastEntry()
|
|||
return mList.getLast();
|
||||
}
|
||||
|
||||
FileData* BasicGameListView::getFirstGameEntry()
|
||||
{
|
||||
return firstGameEntry;
|
||||
}
|
||||
|
||||
void BasicGameListView::addPlaceholder()
|
||||
{
|
||||
// Empty list - add a placeholder.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// EmulationStation Desktop Edition
|
||||
// BasicGameListView.h
|
||||
//
|
||||
// Interface that defines a GameListView of the type 'basic'.
|
||||
|
@ -22,8 +24,11 @@ public:
|
|||
|
||||
virtual FileData* getCursor() override;
|
||||
virtual void setCursor(FileData* file) override;
|
||||
virtual FileData* getNextEntry() override;
|
||||
virtual FileData* getPreviousEntry() override;
|
||||
virtual FileData* getFirstEntry() override;
|
||||
virtual FileData* getLastEntry() override;
|
||||
virtual FileData* getFirstGameEntry() override;
|
||||
|
||||
virtual const char* getName() const override { return "basic"; }
|
||||
|
||||
|
@ -42,6 +47,8 @@ protected:
|
|||
virtual void addPlaceholder();
|
||||
|
||||
TextListComponent<FileData*> mList;
|
||||
// Points to the first game in the list, i.e. the first entry which is of the type 'GAME'.
|
||||
FileData* firstGameEntry;
|
||||
|
||||
const std::string FAVORITE_GAME_CHAR = "\uF005";
|
||||
const std::string FAVORITE_FOLDER_CHAR = "\uF07C";
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// EmulationStation Desktop Edition
|
||||
// GridGameListView.cpp
|
||||
//
|
||||
// Interface that defines a GameListView of the type 'grid'.
|
||||
|
@ -11,8 +13,8 @@
|
|||
#include "views/ViewController.h"
|
||||
#include "CollectionSystemManager.h"
|
||||
#include "Settings.h"
|
||||
#include "SystemData.h"
|
||||
#include "Sound.h"
|
||||
#include "SystemData.h"
|
||||
#if defined(_RPI_)
|
||||
#include "components/VideoPlayerComponent.h"
|
||||
#endif
|
||||
|
@ -159,6 +161,16 @@ void GridGameListView::setCursor(FileData* file)
|
|||
}
|
||||
}
|
||||
|
||||
FileData* GridGameListView::getNextEntry()
|
||||
{
|
||||
return mGrid.getNext();;
|
||||
}
|
||||
|
||||
FileData* GridGameListView::getPreviousEntry()
|
||||
{
|
||||
return mGrid.getPrevious();
|
||||
}
|
||||
|
||||
FileData* GridGameListView::getFirstEntry()
|
||||
{
|
||||
return mGrid.getFirst();;
|
||||
|
@ -169,6 +181,11 @@ FileData* GridGameListView::getLastEntry()
|
|||
return mGrid.getLast();
|
||||
}
|
||||
|
||||
FileData* GridGameListView::getFirstGameEntry()
|
||||
{
|
||||
return firstGameEntry;
|
||||
}
|
||||
|
||||
std::string GridGameListView::getQuickSystemSelectRightButton()
|
||||
{
|
||||
return "rightshoulder";
|
||||
|
@ -222,11 +239,16 @@ const std::string GridGameListView::getImagePath(FileData* file)
|
|||
|
||||
void GridGameListView::populateList(const std::vector<FileData*>& files)
|
||||
{
|
||||
firstGameEntry = nullptr;
|
||||
|
||||
mGrid.clear();
|
||||
mHeaderText.setText(mRoot->getSystem()->getFullName());
|
||||
if (files.size() > 0) {
|
||||
for (auto it = files.cbegin(); it != files.cend(); it++)
|
||||
for (auto it = files.cbegin(); it != files.cend(); it++) {
|
||||
if (!firstGameEntry && (*it)->getType() == GAME)
|
||||
firstGameEntry = (*it);
|
||||
mGrid.add((*it)->getName(), getImagePath(*it), *it);
|
||||
}
|
||||
}
|
||||
else {
|
||||
addPlaceholder();
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// EmulationStation Desktop Edition
|
||||
// GridGameListView.h
|
||||
//
|
||||
// Interface that defines a GameListView of the type 'grid'.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef ES_APP_VIEWS_GAME_LIST_GRID_GAME_LIST_VIEW_H
|
||||
#define ES_APP_VIEWS_GAME_LIST_GRID_GAME_LIST_VIEW_H
|
||||
|
||||
#include "components/DateTimeComponent.h"
|
||||
#include "components/ImageGridComponent.h"
|
||||
#include "components/RatingComponent.h"
|
||||
#include "components/ScrollableContainer.h"
|
||||
#include "components/ImageGridComponent.h"
|
||||
#include "components/VideoComponent.h"
|
||||
#include "views/gamelist/ISimpleGameListView.h"
|
||||
|
||||
|
@ -27,8 +28,11 @@ public:
|
|||
|
||||
virtual FileData* getCursor() override;
|
||||
virtual void setCursor(FileData*) override;
|
||||
virtual FileData* getNextEntry() override;
|
||||
virtual FileData* getPreviousEntry() override;
|
||||
virtual FileData* getFirstEntry() override;
|
||||
virtual FileData* getLastEntry() override;
|
||||
virtual FileData* getFirstGameEntry() override;
|
||||
|
||||
virtual bool input(InputConfig* config, Input input) override;
|
||||
|
||||
|
@ -47,6 +51,8 @@ protected:
|
|||
virtual void addPlaceholder();
|
||||
|
||||
ImageGridComponent<FileData*> mGrid;
|
||||
// Points to the first game in the list, i.e. the first entry which is of the type 'GAME'.
|
||||
FileData* firstGameEntry;
|
||||
|
||||
private:
|
||||
void updateInfoPanel();
|
||||
|
|
|
@ -44,8 +44,11 @@ public:
|
|||
|
||||
virtual FileData* getCursor() = 0;
|
||||
virtual void setCursor(FileData*) = 0;
|
||||
virtual FileData* getNextEntry() = 0;
|
||||
virtual FileData* getPreviousEntry() = 0;
|
||||
virtual FileData* getFirstEntry() = 0;
|
||||
virtual FileData* getLastEntry() = 0;
|
||||
virtual FileData* getFirstGameEntry() = 0;
|
||||
|
||||
virtual bool input(InputConfig* config, Input input) override;
|
||||
virtual void remove(FileData* game, bool deleteFile) = 0;
|
||||
|
|
|
@ -182,36 +182,118 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
|
|||
if (mRoot->getSystem()->isGameSystem()) {
|
||||
if (getCursor()->getType() == GAME || getCursor()->getType() == FOLDER)
|
||||
NavigationSounds::getInstance()->playThemeNavigationSound(FAVORITESOUND);
|
||||
// When marking or unmarking a game as favorite, don't jump to the new position
|
||||
// it gets after the gamelist sorting. Instead retain the cursor position in the
|
||||
// list using the logic below.
|
||||
FileData* entryToUpdate = getCursor();
|
||||
bool favoritesSorting;
|
||||
bool removedLastFavorite = false;
|
||||
bool foldersOnTop = Settings::getInstance()->getBool("FoldersOnTop");
|
||||
|
||||
if (CollectionSystemManager::get()->getIsCustomCollection(mRoot->getSystem()))
|
||||
favoritesSorting = Settings::getInstance()->getBool("FavFirstCustom");
|
||||
else
|
||||
favoritesSorting = Settings::getInstance()->getBool("FavoritesFirst");
|
||||
|
||||
if (favoritesSorting && static_cast<std::string>(getName()) != "recent") {
|
||||
FileData* entryToSelect;
|
||||
// Add favorite flag.
|
||||
if (!getCursor()->getFavorite()) {
|
||||
// If it's a folder and folders are sorted on top, select the current entry.
|
||||
if (foldersOnTop && getCursor()->getType() == FOLDER)
|
||||
entryToSelect = getCursor();
|
||||
// If it's the first entry to be marked as favorite, select the next entry.
|
||||
else if (getCursor() == getFirstEntry())
|
||||
entryToSelect = getNextEntry();
|
||||
// If we are on the favorite marking boundary, select the next entry.
|
||||
else if (getCursor()->getFavorite() != getPreviousEntry()->getFavorite())
|
||||
entryToSelect = getNextEntry();
|
||||
// For all other scenarios try to select the next entry, and if it doesn't
|
||||
// exist, select the previous entry.
|
||||
else
|
||||
entryToSelect = getCursor() != getNextEntry() ?
|
||||
getNextEntry() : getPreviousEntry();
|
||||
}
|
||||
// Remove favorite flag.
|
||||
else {
|
||||
// If it's a folder and folders are sorted on top, select the current entry.
|
||||
if (foldersOnTop && getCursor()->getType() == FOLDER)
|
||||
entryToSelect = getCursor();
|
||||
// If it's the last entry, select the previous entry.
|
||||
else if (getCursor() == getLastEntry())
|
||||
entryToSelect = getPreviousEntry();
|
||||
// If we are on the favorite marking boundary, select the previous entry,
|
||||
// unless folders are sorted on top and the previous entry is a folder.
|
||||
else if (foldersOnTop &&
|
||||
getCursor()->getFavorite() != getNextEntry()->getFavorite())
|
||||
entryToSelect = getPreviousEntry()->getType() == FOLDER ?
|
||||
getCursor() : getPreviousEntry();
|
||||
// If we are on the favorite marking boundary, select the previous entry.
|
||||
else if (getCursor()->getFavorite() != getNextEntry()->getFavorite())
|
||||
entryToSelect = getPreviousEntry();
|
||||
// For all other scenarios try to select the next entry, and if it doesn't
|
||||
// exist, select the previous entry.
|
||||
else
|
||||
entryToSelect = getCursor() != getNextEntry() ?
|
||||
getNextEntry() : getPreviousEntry();
|
||||
|
||||
// If we removed the last favorite marking, set the flag to jump to the
|
||||
// first list entry after the sorting has been performed.
|
||||
if (foldersOnTop && getCursor() == getFirstGameEntry() &&
|
||||
!getNextEntry()->getFavorite())
|
||||
removedLastFavorite = true;
|
||||
else if (getCursor() == getFirstEntry() && !getNextEntry()->getFavorite())
|
||||
removedLastFavorite = true;
|
||||
}
|
||||
|
||||
setCursor(entryToSelect);
|
||||
}
|
||||
|
||||
// Marking folders as favorites is only cosmetic as they're not sorted
|
||||
// differently and they're not part of any collections. So it makes more
|
||||
// sense to do it here than to add the function to CollectionSystemManager.
|
||||
if (getCursor()->getType() == FOLDER) {
|
||||
if (entryToUpdate->getType() == FOLDER) {
|
||||
GuiInfoPopup* s;
|
||||
MetaDataList* md = &getCursor()->getSourceFileData()->metadata;
|
||||
MetaDataList* md = &entryToUpdate->getSourceFileData()->metadata;
|
||||
if (md->get("favorite") == "false") {
|
||||
md->set("favorite", "true");
|
||||
s = new GuiInfoPopup(mWindow, "Marked folder '" +
|
||||
Utils::String::removeParenthesis(getCursor()->getName()) +
|
||||
Utils::String::removeParenthesis(entryToUpdate->getName()) +
|
||||
"' as favorite", 4000);
|
||||
}
|
||||
else {
|
||||
md->set("favorite", "false");
|
||||
s = new GuiInfoPopup(mWindow, "Removed favorite marking for folder '" +
|
||||
Utils::String::removeParenthesis(getCursor()->getName()) +
|
||||
Utils::String::removeParenthesis(entryToUpdate->getName()) +
|
||||
"'", 4000);
|
||||
}
|
||||
|
||||
mWindow->setInfoPopup(s);
|
||||
getCursor()->getSourceFileData()->getSystem()->onMetaDataSavePoint();
|
||||
entryToUpdate->getSourceFileData()->getSystem()->onMetaDataSavePoint();
|
||||
|
||||
if (!Settings::getInstance()->getBool("FoldersOnTop"))
|
||||
mRoot->sort(mRoot->getSortTypeFromString(mRoot->getSortTypeString()),
|
||||
Settings::getInstance()->getBool("FavoritesFirst"));
|
||||
|
||||
ViewController::get()->onFileChanged(getCursor(), FILE_METADATA_CHANGED);
|
||||
|
||||
// Always jump to the first entry in the gamelist if the last favorite
|
||||
// was unmarked. We couldn't do this earlier as we didn't have the list
|
||||
// sorted yet.
|
||||
if (removedLastFavorite) {
|
||||
ViewController::get()->getGameListView(mRoot->getSystem())->setCursor(
|
||||
ViewController::get()->getGameListView(mRoot->getSystem())->
|
||||
getFirstEntry());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (CollectionSystemManager::get()->toggleGameInCollection(getCursor())) {
|
||||
else if (CollectionSystemManager::get()->toggleGameInCollection(entryToUpdate)) {
|
||||
// Jump to the first entry in the gamelist if the last favorite was unmarked.
|
||||
if (foldersOnTop && removedLastFavorite)
|
||||
setCursor(getFirstGameEntry());
|
||||
else if (removedLastFavorite)
|
||||
setCursor(getFirstEntry());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,6 +144,24 @@ public:
|
|||
return mEntries.at(mCursor).object;
|
||||
}
|
||||
|
||||
inline const UserData& getNext() const
|
||||
{
|
||||
// If there is a next entry, then return it, otherwise return the current entry.
|
||||
if (mCursor + 1 < mEntries.size())
|
||||
return mEntries.at(mCursor+1).object;
|
||||
else
|
||||
return mEntries.at(mCursor).object;
|
||||
}
|
||||
|
||||
inline const UserData& getPrevious() const
|
||||
{
|
||||
// If there is a previous entry, then return it, otherwise return the current entry.
|
||||
if (mCursor != 0)
|
||||
return mEntries.at(mCursor-1).object;
|
||||
else
|
||||
return mEntries.at(mCursor).object;
|
||||
}
|
||||
|
||||
inline const UserData& getFirst() const
|
||||
{
|
||||
assert(size() > 0);
|
||||
|
|
Loading…
Reference in a new issue