diff --git a/NEWS.md b/NEWS.md index f2ab0bd11..b31f6d2c3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -56,6 +56,7 @@ Many bugs have been fixed, and numerous features that were only partially implem * Added a gamelist info text field displaying the game count, any applied filters as well as an icon if a folder has been entered * Expanded the gamelist filter functionality to include completed and broken games as well as the ability to filter on game names (via free text entry) * Expanded the metadata for folders and made it possible to mark them as favorites +* Added functionality to remember cursor positions inside folders and grouped custom collections * Added new component GuiComplexTextEditPopup to handle changes to configuration file entries and similar * Speed improvements and optimizations, the application now starts faster and feels more responsive * Replaced the on and off button icons with new graphics diff --git a/es-app/src/views/ViewController.cpp b/es-app/src/views/ViewController.cpp index f20eda3e2..56ca29309 100644 --- a/es-app/src/views/ViewController.cpp +++ b/es-app/src/views/ViewController.cpp @@ -747,6 +747,11 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme) bool isCurrent = (mCurrentView == it->second); SystemData* system = it->first; FileData* cursor = view->getCursor(); + + // Retain the cursor history for the view. + std::vector cursorHistoryTemp; + it->second->copyCursorHistory(cursorHistoryTemp); + mGameListViews.erase(it); if (reloadTheme) @@ -761,6 +766,7 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme) if (isCurrent) mCurrentView = newView; + newView->populateCursorHistory(cursorHistoryTemp); break; } } diff --git a/es-app/src/views/gamelist/IGameListView.h b/es-app/src/views/gamelist/IGameListView.h index 369882556..982f65ebc 100644 --- a/es-app/src/views/gamelist/IGameListView.h +++ b/es-app/src/views/gamelist/IGameListView.h @@ -48,6 +48,9 @@ public: virtual FileData* getFirstGameEntry() = 0; virtual const std::vector& getFirstLetterIndex() = 0; + virtual void copyCursorHistory(std::vector& cursorHistory) = 0; + virtual void populateCursorHistory(std::vector& cursorHistory) = 0; + virtual bool input(InputConfig* config, Input input) override; virtual void remove(FileData* game, bool deleteFile) = 0; virtual void removeMedia(FileData* game) = 0; diff --git a/es-app/src/views/gamelist/ISimpleGameListView.cpp b/es-app/src/views/gamelist/ISimpleGameListView.cpp index c7352bd68..050d247b4 100644 --- a/es-app/src/views/gamelist/ISimpleGameListView.cpp +++ b/es-app/src/views/gamelist/ISimpleGameListView.cpp @@ -18,6 +18,8 @@ #include "Sound.h" #include "SystemData.h" +#include "Log.h" + ISimpleGameListView::ISimpleGameListView( Window* window, FileData* root) @@ -116,8 +118,25 @@ bool ISimpleGameListView::input(InputConfig* config, Input input) NavigationSounds::getInstance()->playThemeNavigationSound(SELECTSOUND); mCursorStack.push(cursor); populateList(cursor->getChildrenListToDisplay(), cursor); - FileData* cursor = getCursor(); - setCursor(cursor); + + FileData* newCursor = nullptr; + std::vector listEntries = cursor->getChildrenListToDisplay(); + // Check if there is an entry in the cursor stack history matching any entry + // in the currect folder. If so, select that entry. + for (auto it = mCursorStackHistory.begin(); + it != mCursorStackHistory.end(); it++) { + if (std::find(listEntries.begin(), listEntries.end(), *it) != + listEntries.end()) { + newCursor = *it; + mCursorStackHistory.erase(it); + break; + } + } + + // If there was no match in the cursor history, simply select the first entry. + if (!newCursor) + newCursor = getCursor(); + setCursor(newCursor); } } @@ -126,6 +145,8 @@ bool ISimpleGameListView::input(InputConfig* config, Input input) else if (config->isMappedTo("b", input)) { ViewController::get()->cancelViewTransitions(); if (mCursorStack.size()) { + // Save the position to the cursor stack history. + mCursorStackHistory.push_back(getCursor()); NavigationSounds::getInstance()->playThemeNavigationSound(BACKSOUND); populateList(mCursorStack.top()->getParent()->getChildrenListToDisplay(), mCursorStack.top()->getParent()); diff --git a/es-app/src/views/gamelist/ISimpleGameListView.h b/es-app/src/views/gamelist/ISimpleGameListView.h index 548f21844..ae3c37e5e 100644 --- a/es-app/src/views/gamelist/ISimpleGameListView.h +++ b/es-app/src/views/gamelist/ISimpleGameListView.h @@ -35,6 +35,13 @@ public: virtual const std::vector& getFirstLetterIndex() override = 0; + // These functions are used to retain the folder cursor history, for instance + // during a view reload. The calling function stores the history temporarily. + void copyCursorHistory(std::vector& cursorHistory) override + { cursorHistory = mCursorStackHistory; }; + void populateCursorHistory(std::vector& cursorHistory) override + { mCursorStackHistory = cursorHistory; }; + protected: virtual std::string getQuickSystemSelectRightButton() = 0; virtual std::string getQuickSystemSelectLeftButton() = 0; @@ -49,6 +56,7 @@ protected: std::vector mThemeExtras; std::stack mCursorStack; + std::vector mCursorStackHistory; std::vector mFirstLetterIndex;