mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-03-06 14:27:43 +00:00
Merge remote-tracking branch 'horstbaerbel/master'
Conflicts: src/components/GuiGameList.cpp
This commit is contained in:
commit
d616b4a202
|
@ -9,9 +9,9 @@ class FileData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~FileData() { };
|
virtual ~FileData() { };
|
||||||
virtual bool isFolder() = 0;
|
virtual bool isFolder() const = 0;
|
||||||
virtual std::string getName() = 0;
|
virtual const std::string & getName() const = 0;
|
||||||
virtual std::string getPath() = 0;
|
virtual const std::string & getPath() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,19 +1,29 @@
|
||||||
#include "FolderData.h"
|
#include "FolderData.h"
|
||||||
#include "SystemData.h"
|
#include "SystemData.h"
|
||||||
|
#include "GameData.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
bool FolderData::isFolder() { return true; }
|
|
||||||
std::string FolderData::getName() { return mName; }
|
std::map<FolderData::ComparisonFunction*, std::string> FolderData::sortStateNameMap;
|
||||||
std::string FolderData::getPath() { return mPath; }
|
|
||||||
|
bool FolderData::isFolder() const { return true; }
|
||||||
|
const std::string & FolderData::getName() const { return mName; }
|
||||||
|
const std::string & FolderData::getPath() const { return mPath; }
|
||||||
unsigned int FolderData::getFileCount() { return mFileVector.size(); }
|
unsigned int FolderData::getFileCount() { return mFileVector.size(); }
|
||||||
FileData* FolderData::getFile(unsigned int i) { return mFileVector.at(i); }
|
|
||||||
|
|
||||||
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()
|
||||||
|
@ -31,8 +41,24 @@ 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 filesort(FileData* file1, FileData* file2)
|
bool FolderData::compareFileName(const FileData* file1, const FileData* file2)
|
||||||
{
|
{
|
||||||
std::string name1 = file1->getName();
|
std::string name1 = file1->getName();
|
||||||
std::string name2 = file2->getName();
|
std::string name2 = file2->getName();
|
||||||
|
@ -43,29 +69,118 @@ bool filesort(FileData* file1, FileData* file2)
|
||||||
{
|
{
|
||||||
if(toupper(name1[i]) != toupper(name2[i]))
|
if(toupper(name1[i]) != toupper(name2[i]))
|
||||||
{
|
{
|
||||||
if(toupper(name1[i]) < toupper(name2[i]))
|
return toupper(name1[i]) < toupper(name2[i]);
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name1.length() < name2.length())
|
return name1.length() < name2.length();
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//sort this folder and any subfolders
|
bool FolderData::compareRating(const FileData* file1, const FileData* file2)
|
||||||
void FolderData::sort()
|
|
||||||
{
|
{
|
||||||
std::sort(mFileVector.begin(), mFileVector.end(), filesort);
|
//we need game data. try to cast
|
||||||
|
const GameData * game1 = dynamic_cast<const GameData*>(file1);
|
||||||
for(unsigned int i = 0; i < mFileVector.size(); i++)
|
const GameData * game2 = dynamic_cast<const GameData*>(file2);
|
||||||
{
|
if (game1 != nullptr && game2 != nullptr) {
|
||||||
if(mFileVector.at(i)->isFolder())
|
return game1->getRating() < game2->getRating();
|
||||||
((FolderData*)mFileVector.at(i))->sort();
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FolderData::compareUserRating(const FileData* file1, const FileData* file2)
|
||||||
|
{
|
||||||
|
//we need game data. try to cast
|
||||||
|
const GameData * game1 = dynamic_cast<const GameData*>(file1);
|
||||||
|
const GameData * game2 = dynamic_cast<const GameData*>(file2);
|
||||||
|
if (game1 != nullptr && game2 != nullptr) {
|
||||||
|
return game1->getUserRating() < game2->getUserRating();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FolderData::compareTimesPlayed(const FileData* file1, const FileData* file2)
|
||||||
|
{
|
||||||
|
//we need game data. try to cast
|
||||||
|
const GameData * game1 = dynamic_cast<const GameData*>(file1);
|
||||||
|
const GameData * game2 = dynamic_cast<const GameData*>(file2);
|
||||||
|
if (game1 != nullptr && game2 != nullptr) {
|
||||||
|
return game1->getTimesPlayed() < game2->getTimesPlayed();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FolderData::compareLastPlayed(const FileData* file1, const FileData* file2)
|
||||||
|
{
|
||||||
|
//we need game data. try to cast
|
||||||
|
const GameData * game1 = dynamic_cast<const GameData*>(file1);
|
||||||
|
const GameData * game2 = dynamic_cast<const GameData*>(file2);
|
||||||
|
if (game1 != nullptr && game2 != nullptr) {
|
||||||
|
return game1->getLastPlayed() < game2->getLastPlayed();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FolderData::getSortStateName(ComparisonFunction & comparisonFunction, bool ascending)
|
||||||
|
{
|
||||||
|
std::string temp = sortStateNameMap[comparisonFunction];
|
||||||
|
if (ascending) {
|
||||||
|
temp.append(" (ascending)");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp.append(" (descending)");
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileData* FolderData::getFile(unsigned int i) const
|
||||||
|
{
|
||||||
|
return mFileVector.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FileData*> FolderData::getFiles(bool onlyFiles) const
|
||||||
|
{
|
||||||
|
std::vector<FileData*> temp;
|
||||||
|
//now check if a child is a folder and get those children in turn
|
||||||
|
std::vector<FileData*>::const_iterator fdit = mFileVector.cbegin();
|
||||||
|
while(fdit != mFileVector.cend()) {
|
||||||
|
//dynamically try to cast to FolderData type
|
||||||
|
FolderData * folder = dynamic_cast<FolderData*>(*fdit);
|
||||||
|
if (folder != nullptr) {
|
||||||
|
//add this only when user wanted it
|
||||||
|
if (!onlyFiles) {
|
||||||
|
temp.push_back(*fdit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp.push_back(*fdit);
|
||||||
|
}
|
||||||
|
++fdit;
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FileData*> FolderData::getFilesRecursive(bool onlyFiles) const
|
||||||
|
{
|
||||||
|
std::vector<FileData*> temp;
|
||||||
|
//now check if a child is a folder and get those children in turn
|
||||||
|
std::vector<FileData*>::const_iterator fdit = mFileVector.cbegin();
|
||||||
|
while(fdit != mFileVector.cend()) {
|
||||||
|
//dynamically try to cast to FolderData type
|
||||||
|
FolderData * folder = dynamic_cast<FolderData*>(*fdit);
|
||||||
|
if (folder != nullptr) {
|
||||||
|
//add this onyl when user wanted it
|
||||||
|
if (!onlyFiles) {
|
||||||
|
temp.push_back(*fdit);
|
||||||
|
}
|
||||||
|
//worked. Is actual folder data. recurse
|
||||||
|
std::vector<FileData*> children = folder->getFilesRecursive(onlyFiles);
|
||||||
|
//insert children into return vector
|
||||||
|
temp.insert(temp.end(), children.cbegin(), children.cend());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp.push_back(*fdit);
|
||||||
|
}
|
||||||
|
++fdit;
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
|
@ -1,28 +1,54 @@
|
||||||
#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;
|
||||||
|
std::string description;
|
||||||
|
|
||||||
|
SortState(ComparisonFunction & sortFunction, bool sortAscending, const std::string & sortDescription) : comparisonFunction(sortFunction), ascending(sortAscending), description(sortDescription) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
bool isFolder();
|
bool isFolder() const;
|
||||||
std::string getName();
|
const std::string & getName() const;
|
||||||
std::string getPath();
|
const std::string & getPath() const;
|
||||||
|
|
||||||
unsigned int getFileCount();
|
unsigned int getFileCount();
|
||||||
FileData* getFile(unsigned int i);
|
FileData* getFile(unsigned int i) const;
|
||||||
|
std::vector<FileData*> getFiles(bool onlyFiles = false) const;
|
||||||
|
std::vector<FileData*> getFilesRecursive(bool onlyFiles = false) const;
|
||||||
|
|
||||||
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 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:
|
private:
|
||||||
SystemData* mSystem;
|
SystemData* mSystem;
|
||||||
std::string mPath;
|
std::string mPath;
|
||||||
|
|
123
src/GameData.cpp
123
src/GameData.cpp
|
@ -2,23 +2,110 @@
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
bool GameData::isFolder() { return false; }
|
|
||||||
std::string GameData::getName() { return mName; }
|
const std::string GameData::xmlTagGameList = "gameList";
|
||||||
std::string GameData::getPath() { return mPath; }
|
const std::string GameData::xmlTagGame = "game";
|
||||||
std::string GameData::getDescription() { return mDescription; }
|
const std::string GameData::xmlTagName = "name";
|
||||||
std::string GameData::getImagePath() { return mImagePath; }
|
const std::string GameData::xmlTagPath = "path";
|
||||||
|
const std::string GameData::xmlTagDescription = "desc";
|
||||||
|
const std::string GameData::xmlTagImagePath = "image";
|
||||||
|
const std::string GameData::xmlTagRating = "rating";
|
||||||
|
const std::string GameData::xmlTagUserRating = "userrating";
|
||||||
|
const std::string GameData::xmlTagTimesPlayed = "timesplayed";
|
||||||
|
const std::string GameData::xmlTagLastPlayed = "lastplayed";
|
||||||
|
|
||||||
|
|
||||||
GameData::GameData(SystemData* system, std::string path, std::string name)
|
GameData::GameData(SystemData* system, std::string path, std::string name)
|
||||||
|
: mSystem(system), mPath(path), mName(name), mRating(0.0f), mUserRating(0.0f), mTimesPlayed(0), mLastPlayed(0)
|
||||||
{
|
{
|
||||||
mSystem = system;
|
|
||||||
mPath = path;
|
|
||||||
mName = name;
|
|
||||||
|
|
||||||
mDescription = "";
|
|
||||||
mImagePath = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GameData::getBashPath()
|
bool GameData::isFolder() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & GameData::getName() const
|
||||||
|
{
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setName(const std::string & name)
|
||||||
|
{
|
||||||
|
mName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & GameData::getPath() const
|
||||||
|
{
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setPath(const std::string & path)
|
||||||
|
{
|
||||||
|
mPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & GameData::getDescription() const
|
||||||
|
{
|
||||||
|
return mDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setDescription(const std::string & description)
|
||||||
|
{
|
||||||
|
mDescription = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & GameData::getImagePath() const
|
||||||
|
{
|
||||||
|
return mImagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setImagePath(const std::string & imagePath)
|
||||||
|
{
|
||||||
|
mImagePath = imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GameData::getRating() const
|
||||||
|
{
|
||||||
|
return mRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setRating(float rating)
|
||||||
|
{
|
||||||
|
mRating = rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GameData::getUserRating() const
|
||||||
|
{
|
||||||
|
return mUserRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setUserRating(float rating)
|
||||||
|
{
|
||||||
|
mUserRating = rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GameData::getTimesPlayed() const
|
||||||
|
{
|
||||||
|
return mTimesPlayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setTimesPlayed(size_t timesPlayed)
|
||||||
|
{
|
||||||
|
mTimesPlayed = timesPlayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::time_t GameData::getLastPlayed() const
|
||||||
|
{
|
||||||
|
return mLastPlayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameData::setLastPlayed(std::time_t lastPlayed)
|
||||||
|
{
|
||||||
|
mLastPlayed = lastPlayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GameData::getBashPath() const
|
||||||
{
|
{
|
||||||
//a quick and dirty way to insert a backslash before most characters that would mess up a bash path
|
//a quick and dirty way to insert a backslash before most characters that would mess up a bash path
|
||||||
std::string path = mPath;
|
std::string path = mPath;
|
||||||
|
@ -44,18 +131,8 @@ std::string GameData::getBashPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns the boost::filesystem stem of our path - e.g. for "/foo/bar.rom" returns "bar"
|
//returns the boost::filesystem stem of our path - e.g. for "/foo/bar.rom" returns "bar"
|
||||||
std::string GameData::getBaseName()
|
std::string GameData::getBaseName() const
|
||||||
{
|
{
|
||||||
boost::filesystem::path path(mPath);
|
boost::filesystem::path path(mPath);
|
||||||
return path.stem().string();
|
return path.stem().string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameData::set(std::string name, std::string description, std::string imagePath)
|
|
||||||
{
|
|
||||||
if(!name.empty())
|
|
||||||
mName = name;
|
|
||||||
if(!description.empty())
|
|
||||||
mDescription = description;
|
|
||||||
if(!imagePath.empty() && boost::filesystem::exists(imagePath))
|
|
||||||
mImagePath = imagePath;
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#define _GAMEDATA_H_
|
#define _GAMEDATA_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
#include "FileData.h"
|
#include "FileData.h"
|
||||||
#include "SystemData.h"
|
#include "SystemData.h"
|
||||||
|
|
||||||
|
@ -9,19 +11,49 @@
|
||||||
class GameData : public FileData
|
class GameData : public FileData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
//static tag names for reading/writing XML documents. This might fail in PUGIXML_WCHAR_MODE
|
||||||
|
//TODO: The class should have member to read fromXML() and write toXML() probably...
|
||||||
|
static const std::string xmlTagGameList;
|
||||||
|
static const std::string xmlTagGame;
|
||||||
|
static const std::string xmlTagName;
|
||||||
|
static const std::string xmlTagPath;
|
||||||
|
static const std::string xmlTagDescription;
|
||||||
|
static const std::string xmlTagImagePath;
|
||||||
|
static const std::string xmlTagRating;
|
||||||
|
static const std::string xmlTagUserRating;
|
||||||
|
static const std::string xmlTagTimesPlayed;
|
||||||
|
static const std::string xmlTagLastPlayed;
|
||||||
|
|
||||||
GameData(SystemData* system, std::string path, std::string name);
|
GameData(SystemData* system, std::string path, std::string name);
|
||||||
|
|
||||||
void set(std::string name = "", std::string description = "", std::string imagePath = "");
|
const std::string & getName() const;
|
||||||
|
void setName(const std::string & name);
|
||||||
|
|
||||||
std::string getName();
|
const std::string & getPath() const;
|
||||||
std::string getPath();
|
void setPath(const std::string & path);
|
||||||
std::string getBashPath();
|
|
||||||
std::string getBaseName();
|
|
||||||
|
|
||||||
std::string getDescription();
|
const std::string & getDescription() const;
|
||||||
std::string getImagePath();
|
void setDescription(const std::string & description);
|
||||||
|
|
||||||
bool isFolder();
|
const std::string & getImagePath() const;
|
||||||
|
void setImagePath(const std::string & imagePath);
|
||||||
|
|
||||||
|
float getRating() const;
|
||||||
|
void setRating(float rating);
|
||||||
|
|
||||||
|
float getUserRating() const;
|
||||||
|
void setUserRating(float rating);
|
||||||
|
|
||||||
|
size_t getTimesPlayed() const;
|
||||||
|
void setTimesPlayed(size_t timesPlayed);
|
||||||
|
|
||||||
|
std::time_t getLastPlayed() const;
|
||||||
|
void setLastPlayed(std::time_t lastPlayed);
|
||||||
|
|
||||||
|
std::string getBashPath() const;
|
||||||
|
std::string getBaseName() const;
|
||||||
|
|
||||||
|
bool isFolder() const;
|
||||||
private:
|
private:
|
||||||
SystemData* mSystem;
|
SystemData* mSystem;
|
||||||
std::string mPath;
|
std::string mPath;
|
||||||
|
@ -30,6 +62,10 @@ private:
|
||||||
//extra data
|
//extra data
|
||||||
std::string mDescription;
|
std::string mDescription;
|
||||||
std::string mImagePath;
|
std::string mImagePath;
|
||||||
|
float mRating;
|
||||||
|
float mUserRating;
|
||||||
|
size_t mTimesPlayed;
|
||||||
|
std::time_t mLastPlayed;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -102,6 +102,19 @@ Vector2u GuiComponent::getSize()
|
||||||
return mSize;
|
return mSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiComponent::setSize(Vector2u size)
|
||||||
|
{
|
||||||
|
mSize = size;
|
||||||
|
onSizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiComponent::setSize(unsigned int w, unsigned int h)
|
||||||
|
{
|
||||||
|
mSize.x = w;
|
||||||
|
mSize.y = h;
|
||||||
|
onSizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
//Children stuff.
|
//Children stuff.
|
||||||
void GuiComponent::addChild(GuiComponent* cmp)
|
void GuiComponent::addChild(GuiComponent* cmp)
|
||||||
{
|
{
|
||||||
|
@ -166,4 +179,4 @@ unsigned char GuiComponent::getOpacity()
|
||||||
void GuiComponent::setOpacity(unsigned char opacity)
|
void GuiComponent::setOpacity(unsigned char opacity)
|
||||||
{
|
{
|
||||||
mOpacity = opacity;
|
mOpacity = opacity;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,9 @@ public:
|
||||||
virtual void onOffsetChanged() {};
|
virtual void onOffsetChanged() {};
|
||||||
|
|
||||||
Vector2u getSize();
|
Vector2u getSize();
|
||||||
|
void setSize(Vector2u size);
|
||||||
|
void setSize(unsigned int w, unsigned int h);
|
||||||
|
virtual void onSizeChanged() {};
|
||||||
|
|
||||||
void setParent(GuiComponent* parent);
|
void setParent(GuiComponent* parent);
|
||||||
GuiComponent* getParent();
|
GuiComponent* getParent();
|
||||||
|
|
|
@ -423,6 +423,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()
|
||||||
|
|
|
@ -33,6 +33,8 @@ void Settings::setDefaults()
|
||||||
mBoolMap["WINDOWED"] = false;
|
mBoolMap["WINDOWED"] = false;
|
||||||
|
|
||||||
mIntMap["DIMTIME"] = 30*1000;
|
mIntMap["DIMTIME"] = 30*1000;
|
||||||
|
|
||||||
|
mIntMap["GameListSortIndex"] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename V>
|
template <typename K, typename V>
|
||||||
|
|
|
@ -50,6 +50,10 @@ SystemData::SystemData(std::string name, std::string descName, std::string start
|
||||||
|
|
||||||
SystemData::~SystemData()
|
SystemData::~SystemData()
|
||||||
{
|
{
|
||||||
|
//save changed game data back to xml
|
||||||
|
if(!Settings::getInstance()->getBool("IGNOREGAMELIST")) {
|
||||||
|
updateGamelist(this);
|
||||||
|
}
|
||||||
delete mRootFolder;
|
delete mRootFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +94,10 @@ void SystemData::launchGame(Window* window, GameData* game)
|
||||||
window->init();
|
window->init();
|
||||||
VolumeControl::getInstance()->init();
|
VolumeControl::getInstance()->init();
|
||||||
AudioManager::getInstance()->init();
|
AudioManager::getInstance()->init();
|
||||||
|
|
||||||
|
//update number of times the game has been launched and the time
|
||||||
|
game->setTimesPlayed(game->getTimesPlayed() + 1);
|
||||||
|
game->setLastPlayed(std::time(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemData::populateFolder(FolderData* folder)
|
void SystemData::populateFolder(FolderData* folder)
|
||||||
|
|
|
@ -117,19 +117,19 @@ void parseGamelist(SystemData* system)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pugi::xml_node root = doc.child("gameList");
|
pugi::xml_node root = doc.child(GameData::xmlTagGameList.c_str());
|
||||||
if(!root)
|
if(!root)
|
||||||
{
|
{
|
||||||
LOG(LogError) << "Could not find <gameList> node in gamelist \"" << xmlpath << "\"!";
|
LOG(LogError) << "Could not find <" << GameData::xmlTagGameList << "> node in gamelist \"" << xmlpath << "\"!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(pugi::xml_node gameNode = root.child("game"); gameNode; gameNode = gameNode.next_sibling("game"))
|
for(pugi::xml_node gameNode = root.child(GameData::xmlTagGame.c_str()); gameNode; gameNode = gameNode.next_sibling(GameData::xmlTagGame.c_str()))
|
||||||
{
|
{
|
||||||
pugi::xml_node pathNode = gameNode.child("path");
|
pugi::xml_node pathNode = gameNode.child(GameData::xmlTagPath.c_str());
|
||||||
if(!pathNode)
|
if(!pathNode)
|
||||||
{
|
{
|
||||||
LOG(LogError) << "<game> node contains no <path> child!";
|
LOG(LogError) << "<" << GameData::xmlTagGame << "> node contains no <" << GameData::xmlTagPath << "> child!";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,13 +152,17 @@ void parseGamelist(SystemData* system)
|
||||||
//actually gather the information in the XML doc, then pass it to the game's set method
|
//actually gather the information in the XML doc, then pass it to the game's set method
|
||||||
std::string newName, newDesc, newImage;
|
std::string newName, newDesc, newImage;
|
||||||
|
|
||||||
if(gameNode.child("name"))
|
if(gameNode.child(GameData::xmlTagName.c_str()))
|
||||||
newName = gameNode.child("name").text().get();
|
|
||||||
if(gameNode.child("desc"))
|
|
||||||
newDesc = gameNode.child("desc").text().get();
|
|
||||||
if(gameNode.child("image"))
|
|
||||||
{
|
{
|
||||||
newImage = gameNode.child("image").text().get();
|
game->setName(gameNode.child(GameData::xmlTagName.c_str()).text().get());
|
||||||
|
}
|
||||||
|
if(gameNode.child(GameData::xmlTagDescription.c_str()))
|
||||||
|
{
|
||||||
|
game->setDescription(gameNode.child(GameData::xmlTagDescription.c_str()).text().get());
|
||||||
|
}
|
||||||
|
if(gameNode.child(GameData::xmlTagImagePath.c_str()))
|
||||||
|
{
|
||||||
|
newImage = gameNode.child(GameData::xmlTagImagePath.c_str()).text().get();
|
||||||
|
|
||||||
//expand "."
|
//expand "."
|
||||||
if(newImage[0] == '.')
|
if(newImage[0] == '.')
|
||||||
|
@ -168,15 +172,148 @@ void parseGamelist(SystemData* system)
|
||||||
newImage.insert(0, pathname.parent_path().string() );
|
newImage.insert(0, pathname.parent_path().string() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//if the image doesn't exist, forget it
|
//if the image exist, set it
|
||||||
if(!boost::filesystem::exists(newImage))
|
if(boost::filesystem::exists(newImage))
|
||||||
newImage = "";
|
{
|
||||||
|
game->setImagePath(newImage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
game->set(newName, newDesc, newImage);
|
//get rating and the times played from the XML doc
|
||||||
|
if(gameNode.child(GameData::xmlTagRating.c_str()))
|
||||||
}else{
|
{
|
||||||
|
float rating;
|
||||||
|
std::istringstream(gameNode.child(GameData::xmlTagRating.c_str()).text().get()) >> rating;
|
||||||
|
game->setRating(rating);
|
||||||
|
}
|
||||||
|
if(gameNode.child(GameData::xmlTagUserRating.c_str()))
|
||||||
|
{
|
||||||
|
float userRating;
|
||||||
|
std::istringstream(gameNode.child(GameData::xmlTagUserRating.c_str()).text().get()) >> userRating;
|
||||||
|
game->setUserRating(userRating);
|
||||||
|
}
|
||||||
|
if(gameNode.child(GameData::xmlTagTimesPlayed.c_str()))
|
||||||
|
{
|
||||||
|
size_t timesPlayed;
|
||||||
|
std::istringstream(gameNode.child(GameData::xmlTagTimesPlayed.c_str()).text().get()) >> timesPlayed;
|
||||||
|
game->setTimesPlayed(timesPlayed);
|
||||||
|
}
|
||||||
|
if(gameNode.child(GameData::xmlTagLastPlayed.c_str()))
|
||||||
|
{
|
||||||
|
std::time_t lastPlayed;
|
||||||
|
std::istringstream(gameNode.child(GameData::xmlTagLastPlayed.c_str()).text().get()) >> lastPlayed;
|
||||||
|
game->setLastPlayed(lastPlayed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
LOG(LogWarning) << "Game at \"" << path << "\" does not exist!";
|
LOG(LogWarning) << "Game at \"" << path << "\" does not exist!";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addGameDataNode(pugi::xml_node & parent, const GameData * game)
|
||||||
|
{
|
||||||
|
//create game and add to parent node
|
||||||
|
pugi::xml_node newGame = parent.append_child(GameData::xmlTagGame.c_str());
|
||||||
|
//add values
|
||||||
|
if (!game->getPath().empty()) {
|
||||||
|
pugi::xml_node pathNode = newGame.append_child(GameData::xmlTagPath.c_str());
|
||||||
|
pathNode.text().set(game->getPath().c_str());
|
||||||
|
}
|
||||||
|
if (!game->getName().empty()) {
|
||||||
|
pugi::xml_node nameNode = newGame.append_child(GameData::xmlTagName.c_str());
|
||||||
|
nameNode.text().set(game->getName().c_str());
|
||||||
|
}
|
||||||
|
if (!game->getDescription().empty()) {
|
||||||
|
pugi::xml_node descriptionNode = newGame.append_child(GameData::xmlTagDescription.c_str());
|
||||||
|
descriptionNode.text().set(game->getDescription().c_str());
|
||||||
|
}
|
||||||
|
if (!game->getImagePath().empty()) {
|
||||||
|
pugi::xml_node imagePathNode = newGame.append_child(GameData::xmlTagImagePath.c_str());
|
||||||
|
imagePathNode.text().set(game->getImagePath().c_str());
|
||||||
|
}
|
||||||
|
//all other values are added regardless of their value
|
||||||
|
pugi::xml_node ratingNode = newGame.append_child(GameData::xmlTagRating.c_str());
|
||||||
|
ratingNode.text().set(std::to_string((long double)game->getRating()).c_str());
|
||||||
|
|
||||||
|
pugi::xml_node userRatingNode = newGame.append_child(GameData::xmlTagUserRating.c_str());
|
||||||
|
userRatingNode.text().set(std::to_string((long double)game->getUserRating()).c_str());
|
||||||
|
|
||||||
|
pugi::xml_node timesPlayedNode = newGame.append_child(GameData::xmlTagTimesPlayed.c_str());
|
||||||
|
timesPlayedNode.text().set(std::to_string((unsigned long long)game->getTimesPlayed()).c_str());
|
||||||
|
|
||||||
|
pugi::xml_node lastPlayedNode = newGame.append_child(GameData::xmlTagLastPlayed.c_str());
|
||||||
|
lastPlayedNode.text().set(std::to_string((unsigned long long)game->getLastPlayed()).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateGamelist(SystemData* system)
|
||||||
|
{
|
||||||
|
//We do this by reading the XML again, adding changes and then writing it back,
|
||||||
|
//because there might be information missing in our systemdata which would then miss in the new XML.
|
||||||
|
//We have the complete information for every game though, so we can simply remove a game
|
||||||
|
//we already have in the system from the XML, and then add it back from its GameData information...
|
||||||
|
|
||||||
|
std::string xmlpath = system->getGamelistPath();
|
||||||
|
if(xmlpath.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(LogInfo) << "Parsing XML file \"" << xmlpath << "\" before writing...";
|
||||||
|
|
||||||
|
pugi::xml_document doc;
|
||||||
|
pugi::xml_parse_result result = doc.load_file(xmlpath.c_str());
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
LOG(LogError) << "Error parsing XML file \"" << xmlpath << "\"!\n " << result.description();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pugi::xml_node root = doc.child(GameData::xmlTagGameList.c_str());
|
||||||
|
if(!root) {
|
||||||
|
LOG(LogError) << "Could not find <" << GameData::xmlTagGameList << "> node in gamelist \"" << xmlpath << "\"!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//now we have all the information from the XML. now iterate through all our games and add information from there
|
||||||
|
FolderData * rootFolder = system->getRootFolder();
|
||||||
|
if (rootFolder != nullptr) {
|
||||||
|
//get only files, no folders
|
||||||
|
std::vector<FileData*> files = rootFolder->getFilesRecursive(true);
|
||||||
|
//iterate through all files, checking if they're already in the XML
|
||||||
|
std::vector<FileData*>::const_iterator fit = files.cbegin();
|
||||||
|
while(fit != files.cend()) {
|
||||||
|
//try to cast to gamedata
|
||||||
|
const GameData * game = dynamic_cast<const GameData*>(*fit);
|
||||||
|
if (game != nullptr) {
|
||||||
|
//worked. check if this games' path can be found somewhere in the XML
|
||||||
|
for(pugi::xml_node gameNode = root.child(GameData::xmlTagGame.c_str()); gameNode; gameNode = gameNode.next_sibling(GameData::xmlTagGame.c_str())) {
|
||||||
|
//get path from game node
|
||||||
|
pugi::xml_node pathNode = gameNode.child(GameData::xmlTagPath.c_str());
|
||||||
|
if(!pathNode)
|
||||||
|
{
|
||||||
|
LOG(LogError) << "<" << GameData::xmlTagGame << "> node contains no <" << GameData::xmlTagPath << "> child!";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//check path
|
||||||
|
if (pathNode.text().get() == game->getPath()) {
|
||||||
|
//found the game. remove it. it will be added again later with updated values
|
||||||
|
root.remove_child(gameNode);
|
||||||
|
//break node search loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//either the game content was removed, because it needs to be updated,
|
||||||
|
//or didn't exist in the first place, so just add it
|
||||||
|
addGameDataNode(root, game);
|
||||||
|
}
|
||||||
|
++fit;
|
||||||
|
}
|
||||||
|
//now write the file
|
||||||
|
if (!doc.save_file(xmlpath.c_str())) {
|
||||||
|
LOG(LogError) << "Error saving XML file \"" << xmlpath << "\"!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG(LogError) << "Found no root folder for system \"" << system->getName() << "\"!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,4 +7,7 @@ class SystemData;
|
||||||
//Loads gamelist.xml data into a SystemData.
|
//Loads gamelist.xml data into a SystemData.
|
||||||
void parseGamelist(SystemData* system);
|
void parseGamelist(SystemData* system);
|
||||||
|
|
||||||
|
//Writes changes to SystemData back to a previously loaded gamelist.xml.
|
||||||
|
void updateGamelist(SystemData* system);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,17 +7,15 @@ const std::string GuiFastSelect::LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
const int GuiFastSelect::SCROLLSPEED = 100;
|
const int GuiFastSelect::SCROLLSPEED = 100;
|
||||||
const int GuiFastSelect::SCROLLDELAY = 507;
|
const int GuiFastSelect::SCROLLDELAY = 507;
|
||||||
|
|
||||||
GuiFastSelect::GuiFastSelect(Window* window, GuiGameList* parent, TextListComponent<FileData*>* list, char startLetter, GuiBoxData data,
|
GuiFastSelect::GuiFastSelect(Window* window, GuiGameList* parent, TextListComponent<FileData*>* list, char startLetter, ThemeComponent * theme)
|
||||||
int textcolor, std::shared_ptr<Sound> & scrollsound, Font* font) : GuiComponent(window)
|
: GuiComponent(window), mParent(parent), mList(list), mTheme(theme)
|
||||||
{
|
{
|
||||||
mLetterID = LETTERS.find(toupper(startLetter));
|
mLetterID = LETTERS.find(toupper(startLetter));
|
||||||
if(mLetterID == std::string::npos)
|
if(mLetterID == std::string::npos)
|
||||||
mLetterID = 0;
|
mLetterID = 0;
|
||||||
|
|
||||||
mParent = parent;
|
mScrollSound = mTheme->getSound("menuScroll");
|
||||||
mList = list;
|
mTextColor = mTheme->getColor("fastSelect");
|
||||||
mScrollSound = scrollsound;
|
|
||||||
mFont = font;
|
|
||||||
|
|
||||||
mScrolling = false;
|
mScrolling = false;
|
||||||
mScrollTimer = 0;
|
mScrollTimer = 0;
|
||||||
|
@ -25,9 +23,7 @@ GuiFastSelect::GuiFastSelect(Window* window, GuiGameList* parent, TextListCompon
|
||||||
|
|
||||||
unsigned int sw = Renderer::getScreenWidth(), sh = Renderer::getScreenHeight();
|
unsigned int sw = Renderer::getScreenWidth(), sh = Renderer::getScreenHeight();
|
||||||
mBox = new GuiBox(window, (int)(sw * 0.2f), (int)(sh * 0.2f), (int)(sw * 0.6f), (int)(sh * 0.6f));
|
mBox = new GuiBox(window, (int)(sw * 0.2f), (int)(sh * 0.2f), (int)(sw * 0.6f), (int)(sh * 0.6f));
|
||||||
mBox->setData(data);
|
mBox->setData(mTheme->getBoxData());
|
||||||
|
|
||||||
mTextColor = textcolor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiFastSelect::~GuiFastSelect()
|
GuiFastSelect::~GuiFastSelect()
|
||||||
|
@ -41,11 +37,14 @@ void GuiFastSelect::render()
|
||||||
unsigned int sw = Renderer::getScreenWidth(), sh = Renderer::getScreenHeight();
|
unsigned int sw = Renderer::getScreenWidth(), sh = Renderer::getScreenHeight();
|
||||||
|
|
||||||
if(!mBox->hasBackground())
|
if(!mBox->hasBackground())
|
||||||
Renderer::drawRect((int)(sw * 0.2f), (int)(sh * 0.2f), (int)(sw * 0.6f), (int)(sh * 0.6f), 0x000FF0FF);
|
Renderer::drawRect((int)(sw * 0.3f), (int)(sh * 0.3f), (int)(sw * 0.4f), (int)(sh * 0.4f), 0x000FF0AA);
|
||||||
|
|
||||||
mBox->render();
|
mBox->render();
|
||||||
|
|
||||||
Renderer::drawCenteredText(LETTERS.substr(mLetterID, 1), 0, (int)(sh * 0.5f - (mFont->getHeight() * 0.5f)), mTextColor, mFont);
|
Renderer::drawCenteredText(LETTERS.substr(mLetterID, 1), 0, (int)(sh * 0.5f - (mTheme->getFastSelectFont()->getHeight() * 0.5f)), mTextColor, mTheme->getFastSelectFont());
|
||||||
|
Renderer::drawCenteredText("Sort order:", 0, (int)(sh * 0.6f - (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor, mTheme->getDescriptionFont());
|
||||||
|
std::string sortString = "<- " + mParent->getSortState().description + " ->";
|
||||||
|
Renderer::drawCenteredText(sortString, 0, (int)(sh * 0.6f + (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor, mTheme->getDescriptionFont());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiFastSelect::input(InputConfig* config, Input input)
|
bool GuiFastSelect::input(InputConfig* config, Input input)
|
||||||
|
@ -64,6 +63,19 @@ bool GuiFastSelect::input(InputConfig* config, Input input)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(config->isMappedTo("left", input) && input.value != 0)
|
||||||
|
{
|
||||||
|
mParent->setPreviousSortIndex();
|
||||||
|
mScrollSound->play();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(config->isMappedTo("right", input) && input.value != 0)
|
||||||
|
{
|
||||||
|
mParent->setNextSortIndex();
|
||||||
|
mScrollSound->play();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if((config->isMappedTo("up", input) || config->isMappedTo("down", input)) && input.value == 0)
|
if((config->isMappedTo("up", input) || config->isMappedTo("down", input)) && input.value == 0)
|
||||||
{
|
{
|
||||||
mScrolling = false;
|
mScrolling = false;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "../SystemData.h"
|
#include "../SystemData.h"
|
||||||
#include "../FolderData.h"
|
#include "../FolderData.h"
|
||||||
#include "../Sound.h"
|
#include "../Sound.h"
|
||||||
|
#include "ThemeComponent.h"
|
||||||
#include "TextListComponent.h"
|
#include "TextListComponent.h"
|
||||||
#include "GuiBox.h"
|
#include "GuiBox.h"
|
||||||
|
|
||||||
|
@ -13,8 +14,7 @@ class GuiGameList;
|
||||||
class GuiFastSelect : public GuiComponent
|
class GuiFastSelect : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GuiFastSelect(Window* window, GuiGameList* parent, TextListComponent<FileData*>* list, char startLetter, GuiBoxData data,
|
GuiFastSelect(Window* window, GuiGameList* parent, TextListComponent<FileData*>* list, char startLetter, ThemeComponent * theme);
|
||||||
int textcolor, std::shared_ptr<Sound> & scrollsound, Font* font);
|
|
||||||
~GuiFastSelect();
|
~GuiFastSelect();
|
||||||
|
|
||||||
bool input(InputConfig* config, Input input);
|
bool input(InputConfig* config, Input input);
|
||||||
|
@ -41,7 +41,7 @@ private:
|
||||||
bool mScrolling;
|
bool mScrolling;
|
||||||
|
|
||||||
std::shared_ptr<Sound> mScrollSound;
|
std::shared_ptr<Sound> mScrollSound;
|
||||||
Font* mFont;
|
ThemeComponent * mTheme;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
#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")));
|
||||||
|
@ -26,8 +30,23 @@ GuiGameList::GuiGameList(Window* window) : GuiComponent(window),
|
||||||
mScreenshot(window),
|
mScreenshot(window),
|
||||||
mDescription(window),
|
mDescription(window),
|
||||||
mDescContainer(window),
|
mDescContainer(window),
|
||||||
mTransitionImage(window, 0, 0, "", Renderer::getScreenWidth(), Renderer::getScreenHeight(), true)
|
mTransitionImage(window, 0, 0, "", Renderer::getScreenWidth(), Renderer::getScreenHeight(), true),
|
||||||
|
sortStateIndex(Settings::getInstance()->getInt("GameListSortIndex"))
|
||||||
{
|
{
|
||||||
|
//first object initializes the vector
|
||||||
|
if (sortStates.empty()) {
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareFileName, true, "file name, ascending"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareFileName, false, "file name, descending"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareRating, true, "database rating, ascending"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareRating, false, "database rating, descending"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareUserRating, true, "your rating, ascending"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareUserRating, false, "your rating, descending"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareTimesPlayed, true, "played least often"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareTimesPlayed, false, "played most often"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareLastPlayed, true, "played least recently"));
|
||||||
|
sortStates.push_back(FolderData::SortState(FolderData::compareLastPlayed, false, "played most recently"));
|
||||||
|
}
|
||||||
|
|
||||||
mImageAnimation.addChild(&mScreenshot);
|
mImageAnimation.addChild(&mScreenshot);
|
||||||
mDescContainer.addChild(&mDescription);
|
mDescContainer.addChild(&mDescription);
|
||||||
|
|
||||||
|
@ -175,6 +194,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)
|
||||||
{
|
{
|
||||||
|
@ -185,7 +214,7 @@ bool GuiGameList::input(InputConfig* config, Input input)
|
||||||
//open the fast select menu
|
//open the fast select menu
|
||||||
if(config->isMappedTo("select", input) && input.value != 0)
|
if(config->isMappedTo("select", input) && input.value != 0)
|
||||||
{
|
{
|
||||||
mWindow->pushGui(new GuiFastSelect(mWindow, this, &mList, mList.getSelectedObject()->getName()[0], mTheme->getBoxData(), mTheme->getColor("fastSelect"), mTheme->getSound("menuScroll"), mTheme->getFastSelectFont()));
|
mWindow->pushGui(new GuiFastSelect(mWindow, this, &mList, mList.getSelectedObject()->getName()[0], mTheme));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +233,52 @@ bool GuiGameList::input(InputConfig* config, Input input)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FolderData::SortState & GuiGameList::getSortState() const
|
||||||
|
{
|
||||||
|
return sortStates.at(sortStateIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
//save new index to settings
|
||||||
|
Settings::getInstance()->setInt("GameListSortIndex", sortStateIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
{
|
{
|
||||||
mList.clear();
|
mList.clear();
|
||||||
|
|
|
@ -18,6 +18,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);
|
GuiGameList(Window* window);
|
||||||
virtual ~GuiGameList();
|
virtual ~GuiGameList();
|
||||||
|
@ -33,6 +36,12 @@ public:
|
||||||
|
|
||||||
void updateDetailData();
|
void updateDetailData();
|
||||||
|
|
||||||
|
const FolderData::SortState & getSortState() const;
|
||||||
|
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);
|
||||||
|
|
||||||
bool isDetailed() const;
|
bool isDetailed() const;
|
||||||
|
|
Loading…
Reference in a new issue