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:
Bim Overbohm 2013-06-28 19:44:28 +02:00
parent c61a470694
commit a60fe463d4
5 changed files with 134 additions and 16 deletions

View file

@ -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

View file

@ -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;

View file

@ -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()

View file

@ -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)

View file

@ -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;