mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-12-01 18:45:39 +00:00
Support sorting of game list via input
You can now map the functions "sortordernext" and "sortorderprevious" to inputs (in es_input.cfg) and toggle the game list sort order with them. The order is: "file name, ascending" (default), "file name, descending", "rating ascending", "rating descending", "user rating ascending", "user rating descending", "time played ascending", "times played descending", "last played time ascending", "last played time descending".
This commit is contained in:
parent
c61a470694
commit
a60fe463d4
|
@ -4,6 +4,9 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
std::map<FolderData::ComparisonFunction*, std::string> FolderData::sortStateNameMap;
|
||||||
|
|
||||||
bool FolderData::isFolder() const { return true; }
|
bool FolderData::isFolder() const { return true; }
|
||||||
const std::string & FolderData::getName() const { return mName; }
|
const std::string & FolderData::getName() const { return mName; }
|
||||||
const std::string & FolderData::getPath() const { return mPath; }
|
const std::string & FolderData::getPath() const { return mPath; }
|
||||||
|
@ -11,10 +14,16 @@ unsigned int FolderData::getFileCount() { return mFileVector.size(); }
|
||||||
|
|
||||||
|
|
||||||
FolderData::FolderData(SystemData* system, std::string path, std::string name)
|
FolderData::FolderData(SystemData* system, std::string path, std::string name)
|
||||||
|
: mSystem(system), mPath(path), mName(name)
|
||||||
{
|
{
|
||||||
mSystem = system;
|
//first created folder data initializes the list
|
||||||
mPath = path;
|
if (sortStateNameMap.empty()) {
|
||||||
mName = name;
|
sortStateNameMap[compareFileName] = "file name";
|
||||||
|
sortStateNameMap[compareRating] = "rating";
|
||||||
|
sortStateNameMap[compareUserRating] = "user rating";
|
||||||
|
sortStateNameMap[compareTimesPlayed] = "times played";
|
||||||
|
sortStateNameMap[compareLastPlayed] = "last time played";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderData::~FolderData()
|
FolderData::~FolderData()
|
||||||
|
@ -32,6 +41,22 @@ void FolderData::pushFileData(FileData* file)
|
||||||
mFileVector.push_back(file);
|
mFileVector.push_back(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//sort this folder and any subfolders
|
||||||
|
void FolderData::sort(ComparisonFunction & comparisonFunction, bool ascending)
|
||||||
|
{
|
||||||
|
std::sort(mFileVector.begin(), mFileVector.end(), comparisonFunction);
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < mFileVector.size(); i++)
|
||||||
|
{
|
||||||
|
if(mFileVector.at(i)->isFolder())
|
||||||
|
((FolderData*)mFileVector.at(i))->sort(comparisonFunction, ascending);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ascending) {
|
||||||
|
std::reverse(mFileVector.begin(), mFileVector.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//returns if file1 should come before file2
|
//returns if file1 should come before file2
|
||||||
bool FolderData::compareFileName(const FileData* file1, const FileData* file2)
|
bool FolderData::compareFileName(const FileData* file1, const FileData* file2)
|
||||||
{
|
{
|
||||||
|
@ -95,16 +120,16 @@ bool FolderData::compareLastPlayed(const FileData* file1, const FileData* file2)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sort this folder and any subfolders
|
std::string FolderData::getSortStateName(ComparisonFunction & comparisonFunction, bool ascending)
|
||||||
void FolderData::sort()
|
|
||||||
{
|
{
|
||||||
std::sort(mFileVector.begin(), mFileVector.end(), compareFileName);
|
std::string temp = sortStateNameMap[comparisonFunction];
|
||||||
|
if (ascending) {
|
||||||
for(unsigned int i = 0; i < mFileVector.size(); i++)
|
temp.append(" (ascending)");
|
||||||
{
|
|
||||||
if(mFileVector.at(i)->isFolder())
|
|
||||||
((FolderData*)mFileVector.at(i))->sort();
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
temp.append(" (descending)");
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileData* FolderData::getFile(unsigned int i) const
|
FileData* FolderData::getFile(unsigned int i) const
|
||||||
|
|
|
@ -1,14 +1,30 @@
|
||||||
#ifndef _FOLDER_H_
|
#ifndef _FOLDER_H_
|
||||||
#define _FOLDER_H_
|
#define _FOLDER_H_
|
||||||
|
|
||||||
#include "FileData.h"
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "FileData.h"
|
||||||
|
|
||||||
|
|
||||||
class SystemData;
|
class SystemData;
|
||||||
|
|
||||||
//This class lets us hold a vector of FileDatas within under a common name.
|
//This class lets us hold a vector of FileDatas within under a common name.
|
||||||
class FolderData : public FileData
|
class FolderData : public FileData
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
typedef bool ComparisonFunction(const FileData* a, const FileData* b);
|
||||||
|
struct SortState
|
||||||
|
{
|
||||||
|
ComparisonFunction & comparisonFunction;
|
||||||
|
bool ascending;
|
||||||
|
|
||||||
|
SortState(ComparisonFunction & sortFunction, bool sortAscending) : comparisonFunction(sortFunction), ascending(sortAscending) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::map<ComparisonFunction*, std::string> sortStateNameMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FolderData(SystemData* system, std::string path, std::string name);
|
FolderData(SystemData* system, std::string path, std::string name);
|
||||||
~FolderData();
|
~FolderData();
|
||||||
|
@ -24,13 +40,14 @@ public:
|
||||||
|
|
||||||
void pushFileData(FileData* file);
|
void pushFileData(FileData* file);
|
||||||
|
|
||||||
void sort();
|
void sort(ComparisonFunction & comparisonFunction = compareFileName, bool ascending = true);
|
||||||
|
|
||||||
static bool compareFileName(const FileData* file1, const FileData* file2);
|
static bool compareFileName(const FileData* file1, const FileData* file2);
|
||||||
static bool compareRating(const FileData* file1, const FileData* file2);
|
static bool compareRating(const FileData* file1, const FileData* file2);
|
||||||
static bool compareUserRating(const FileData* file1, const FileData* file2);
|
static bool compareUserRating(const FileData* file1, const FileData* file2);
|
||||||
static bool compareTimesPlayed(const FileData* file1, const FileData* file2);
|
static bool compareTimesPlayed(const FileData* file1, const FileData* file2);
|
||||||
static bool compareLastPlayed(const FileData* file1, const FileData* file2);
|
static bool compareLastPlayed(const FileData* file1, const FileData* file2);
|
||||||
|
static std::string getSortStateName(ComparisonFunction & comparisonFunction = compareFileName, bool ascending = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SystemData* mSystem;
|
SystemData* mSystem;
|
||||||
std::string mPath;
|
std::string mPath;
|
||||||
|
|
|
@ -404,6 +404,9 @@ void InputManager::loadDefaultConfig()
|
||||||
|
|
||||||
cfg->mapInput("mastervolup", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_PLUS, 1, true));
|
cfg->mapInput("mastervolup", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_PLUS, 1, true));
|
||||||
cfg->mapInput("mastervoldown", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_MINUS, 1, true));
|
cfg->mapInput("mastervoldown", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_MINUS, 1, true));
|
||||||
|
|
||||||
|
cfg->mapInput("sortordernext", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_F7, 1, true));
|
||||||
|
cfg->mapInput("sortorderprevious", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_F8, 1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::writeConfig()
|
void InputManager::writeConfig()
|
||||||
|
|
|
@ -7,15 +7,31 @@
|
||||||
#include "../Log.h"
|
#include "../Log.h"
|
||||||
#include "../Settings.h"
|
#include "../Settings.h"
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<FolderData::SortState> GuiGameList::sortStates;
|
||||||
|
|
||||||
|
|
||||||
Vector2i GuiGameList::getImagePos()
|
Vector2i GuiGameList::getImagePos()
|
||||||
{
|
{
|
||||||
return Vector2i((int)(Renderer::getScreenWidth() * mTheme->getFloat("gameImageOffsetX")), (int)(Renderer::getScreenHeight() * mTheme->getFloat("gameImageOffsetY")));
|
return Vector2i((int)(Renderer::getScreenWidth() * mTheme->getFloat("gameImageOffsetX")), (int)(Renderer::getScreenHeight() * mTheme->getFloat("gameImageOffsetY")));
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window),
|
GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window),
|
||||||
mDescription(window), mTransitionImage(window, 0, 0, "", Renderer::getScreenWidth(), Renderer::getScreenHeight(), true)
|
mDescription(window), mTransitionImage(window, 0, 0, "", Renderer::getScreenWidth(), Renderer::getScreenHeight(), true), mDetailed(useDetail), sortStateIndex(0)
|
||||||
{
|
{
|
||||||
mDetailed = useDetail;
|
//first object initializes the vector
|
||||||
|
if (sortStates.empty()) {
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareFileName, true));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareFileName, false));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareRating, true));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareRating, false));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareUserRating, true));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareUserRating, false));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareTimesPlayed, true));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareTimesPlayed, false));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareLastPlayed, true));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareLastPlayed, false));
|
||||||
|
}
|
||||||
|
|
||||||
mTheme = new ThemeComponent(mWindow, mDetailed);
|
mTheme = new ThemeComponent(mWindow, mDetailed);
|
||||||
|
|
||||||
|
@ -190,6 +206,16 @@ bool GuiGameList::input(InputConfig* config, Input input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//change sort order
|
||||||
|
if(config->isMappedTo("sortordernext", input) && input.value != 0) {
|
||||||
|
setNextSortIndex();
|
||||||
|
//std::cout << "Sort order is " << FolderData::getSortStateName(sortStates.at(sortStateIndex).comparisonFunction, sortStates.at(sortStateIndex).ascending) << std::endl;
|
||||||
|
}
|
||||||
|
else if(config->isMappedTo("sortorderprevious", input) && input.value != 0) {
|
||||||
|
setPreviousSortIndex();
|
||||||
|
//std::cout << "Sort order is " << FolderData::getSortStateName(sortStates.at(sortStateIndex).comparisonFunction, sortStates.at(sortStateIndex).ascending) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//open the "start menu"
|
//open the "start menu"
|
||||||
if(config->isMappedTo("menu", input) && input.value != 0)
|
if(config->isMappedTo("menu", input) && input.value != 0)
|
||||||
{
|
{
|
||||||
|
@ -219,6 +245,45 @@ bool GuiGameList::input(InputConfig* config, Input input)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiGameList::setSortIndex(size_t index)
|
||||||
|
{
|
||||||
|
//make the index valid
|
||||||
|
if (index >= sortStates.size()) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
if (index != sortStateIndex) {
|
||||||
|
//get sort state from vector and sort list
|
||||||
|
sortStateIndex = index;
|
||||||
|
sort(sortStates.at(sortStateIndex).comparisonFunction, sortStates.at(sortStateIndex).ascending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiGameList::setNextSortIndex()
|
||||||
|
{
|
||||||
|
//make the index wrap around
|
||||||
|
if ((sortStateIndex - 1) >= sortStates.size()) {
|
||||||
|
setSortIndex(0);
|
||||||
|
}
|
||||||
|
setSortIndex(sortStateIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiGameList::setPreviousSortIndex()
|
||||||
|
{
|
||||||
|
//make the index wrap around
|
||||||
|
if (((int)sortStateIndex - 1) < 0) {
|
||||||
|
setSortIndex(sortStates.size() - 1);
|
||||||
|
}
|
||||||
|
setSortIndex(sortStateIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiGameList::sort(FolderData::ComparisonFunction & comparisonFunction, bool ascending)
|
||||||
|
{
|
||||||
|
//resort list and update it
|
||||||
|
mFolder->sort(comparisonFunction, ascending);
|
||||||
|
updateList();
|
||||||
|
updateDetailData();
|
||||||
|
}
|
||||||
|
|
||||||
void GuiGameList::updateList()
|
void GuiGameList::updateList()
|
||||||
{
|
{
|
||||||
if(mDetailed)
|
if(mDetailed)
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
//It has a TextListComponent child that handles the game list, a ThemeComponent that handles the theming system, and an ImageComponent for game images.
|
//It has a TextListComponent child that handles the game list, a ThemeComponent that handles the theming system, and an ImageComponent for game images.
|
||||||
class GuiGameList : public GuiComponent
|
class GuiGameList : public GuiComponent
|
||||||
{
|
{
|
||||||
|
static std::vector<FolderData::SortState> sortStates;
|
||||||
|
size_t sortStateIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GuiGameList(Window* window, bool useDetail = false);
|
GuiGameList(Window* window, bool useDetail = false);
|
||||||
virtual ~GuiGameList();
|
virtual ~GuiGameList();
|
||||||
|
@ -32,6 +35,11 @@ public:
|
||||||
|
|
||||||
void updateDetailData();
|
void updateDetailData();
|
||||||
|
|
||||||
|
void setSortIndex(size_t index);
|
||||||
|
void setNextSortIndex();
|
||||||
|
void setPreviousSortIndex();
|
||||||
|
void sort(FolderData::ComparisonFunction & comparisonFunction = FolderData::compareFileName, bool ascending = true);
|
||||||
|
|
||||||
static GuiGameList* create(Window* window);
|
static GuiGameList* create(Window* window);
|
||||||
|
|
||||||
static const float sInfoWidth;
|
static const float sInfoWidth;
|
||||||
|
|
Loading…
Reference in a new issue