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 <iostream>
std::map<FolderData::ComparisonFunction*, std::string> FolderData::sortStateNameMap;
bool FolderData::isFolder() const { return true; }
const std::string & FolderData::getName() const { return mName; }
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)
: mSystem(system), mPath(path), mName(name)
{
mSystem = system;
mPath = path;
mName = name;
//first created folder data initializes the list
if (sortStateNameMap.empty()) {
sortStateNameMap[compareFileName] = "file name";
sortStateNameMap[compareRating] = "rating";
sortStateNameMap[compareUserRating] = "user rating";
sortStateNameMap[compareTimesPlayed] = "times played";
sortStateNameMap[compareLastPlayed] = "last time played";
}
}
FolderData::~FolderData()
@ -32,6 +41,22 @@ void FolderData::pushFileData(FileData* 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
bool FolderData::compareFileName(const FileData* file1, const FileData* file2)
{
@ -95,16 +120,16 @@ bool FolderData::compareLastPlayed(const FileData* file1, const FileData* file2)
return false;
}
//sort this folder and any subfolders
void FolderData::sort()
std::string FolderData::getSortStateName(ComparisonFunction & comparisonFunction, bool ascending)
{
std::sort(mFileVector.begin(), mFileVector.end(), compareFileName);
for(unsigned int i = 0; i < mFileVector.size(); i++)
{
if(mFileVector.at(i)->isFolder())
((FolderData*)mFileVector.at(i))->sort();
std::string temp = sortStateNameMap[comparisonFunction];
if (ascending) {
temp.append(" (ascending)");
}
else {
temp.append(" (descending)");
}
return temp;
}
FileData* FolderData::getFile(unsigned int i) const

View file

@ -1,14 +1,30 @@
#ifndef _FOLDER_H_
#define _FOLDER_H_
#include "FileData.h"
#include <map>
#include <vector>
#include "FileData.h"
class SystemData;
//This class lets us hold a vector of FileDatas within under a common name.
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:
FolderData(SystemData* system, std::string path, std::string name);
~FolderData();
@ -24,13 +40,14 @@ public:
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 compareRating(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 compareLastPlayed(const FileData* file1, const FileData* file2);
static std::string getSortStateName(ComparisonFunction & comparisonFunction = compareFileName, bool ascending = true);
private:
SystemData* mSystem;
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("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()

View file

@ -7,15 +7,31 @@
#include "../Log.h"
#include "../Settings.h"
std::vector<FolderData::SortState> GuiGameList::sortStates;
Vector2i GuiGameList::getImagePos()
{
return Vector2i((int)(Renderer::getScreenWidth() * mTheme->getFloat("gameImageOffsetX")), (int)(Renderer::getScreenHeight() * mTheme->getFloat("gameImageOffsetY")));
}
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);
@ -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"
if(config->isMappedTo("menu", input) && input.value != 0)
{
@ -219,6 +245,45 @@ bool GuiGameList::input(InputConfig* config, Input input)
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()
{
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.
class GuiGameList : public GuiComponent
{
static std::vector<FolderData::SortState> sortStates;
size_t sortStateIndex;
public:
GuiGameList(Window* window, bool useDetail = false);
virtual ~GuiGameList();
@ -32,6 +35,11 @@ public:
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 const float sInfoWidth;