diff --git a/src/states_screens/online/online_profile_achievements.cpp b/src/states_screens/online/online_profile_achievements.cpp index 665f8fcd1..e275a5148 100644 --- a/src/states_screens/online/online_profile_achievements.cpp +++ b/src/states_screens/online/online_profile_achievements.cpp @@ -48,6 +48,9 @@ BaseOnlineProfileAchievements::BaseOnlineProfileAchievements(const std::string & : OnlineProfileBase(name) { m_selected_achievement_index = -1; + m_sort_column = 0; + m_sort_desc = false; + m_sort_default = true; } // BaseOnlineProfileAchievements // ----------------------------------------------------------------------------- @@ -58,6 +61,7 @@ void BaseOnlineProfileAchievements::loadedFromFile() OnlineProfileBase::loadedFromFile(); m_achievements_list_widget = getWidget("achievements_list"); assert(m_achievements_list_widget != NULL); + m_achievements_list_widget->setColumnListener(this); } // loadedFromFile @@ -98,30 +102,7 @@ void BaseOnlineProfileAchievements::init() // m_visiting_profile is NULL if the user is not logged in. if(!m_visiting_profile || m_visiting_profile->isCurrentUser()) { - // No need to wait for results, since they are local anyway - m_waiting_for_achievements = false; - m_achievements_list_widget->clear(); - std::map & all_achievements = - PlayerManager::getCurrentPlayer()->getAchievementsStatus() - ->getAllAchievements(); - std::map::const_iterator it; - for (it = all_achievements.begin(); it != all_achievements.end(); ++it) - { - std::vector row; - Achievement *a = it->second; - if(a->getInfo()->isSecret() && !a->isAchieved()) - continue; - ListWidget::ListCell title(translations->fribidize(a->getInfo()->getName()), -1, 2); - ListWidget::ListCell goals(a->getGoalProgressAsString(), -1, 1); - ListWidget::ListCell progress(a->getProgressAsString(), -1, 1); - row.push_back(title); - row.push_back(goals); - row.push_back(progress); - const std::string id = StringUtils::toString(a->getInfo()->getID()); - m_achievements_list_widget->addItem(id, row); - if (a->isAchieved()) - m_achievements_list_widget->emphasisItem(id); - } + displayResults(); } else { @@ -177,6 +158,119 @@ void BaseOnlineProfileAchievements::eventCallback(Widget* widget, } } // eventCallback +// ---------------------------------------------------------------------------- +void BaseOnlineProfileAchievements::onColumnClicked(int column_id, bool sort_desc, bool sort_default) +{ + m_sort_column = column_id; + m_sort_desc = sort_desc; + m_sort_default = sort_default; + + if (!m_waiting_for_achievements) + { + displayResults(); + } +} // onColumnClicked + +// ---------------------------------------------------------------------------- +/** Displays the achievements from a given profile. + */ +void BaseOnlineProfileAchievements::displayResults() +{ + m_achievements_list_widget->clear(); + m_waiting_for_achievements = false; + + if (!m_visiting_profile || m_visiting_profile->isCurrentUser()) + { + // No need to wait for results, since they are local anyway + std::map & all_achievements = + PlayerManager::getCurrentPlayer()->getAchievementsStatus() + ->getAllAchievements(); + + // We need to get a vector instead because we need to sort + std::vector all_achievements_list; + + std::map::const_iterator it; + for (it = all_achievements.begin(); it != all_achievements.end(); ++it) + { + all_achievements_list.push_back(it->second); + } + + auto compAchievement = [=](Achievement *a, Achievement *b) { + if (m_sort_column == 0) + { + // Sort by name + return a->getInfo()->getName().lower_ignore_case(b->getInfo()->getName()); + } + else if (m_sort_column == 1) + { + // Sort by goals + return a->getInfo()->goalString().lower_ignore_case(b->getInfo()->goalString()); + } + else if (m_sort_column == 2) + { + // Sort by progress + return a->getProgressAsString().lower_ignore_case(b->getProgressAsString()); + } + }; + + if (m_sort_desc && !m_sort_default) + { + std::sort(all_achievements_list.rbegin(), all_achievements_list.rend(), compAchievement); + } + else if (!m_sort_default) + { + std::sort(all_achievements_list.begin(), all_achievements_list.end(), compAchievement); + } + + std::vector::iterator vit; + for (vit = all_achievements_list.begin(); vit != all_achievements_list.end(); ++vit) + { + std::vector row; + Achievement *a = *vit; + if (a->getInfo()->isSecret() && !a->isAchieved()) + continue; + ListWidget::ListCell title(translations->fribidize(a->getInfo()->getName()), -1, 2); + ListWidget::ListCell goals(a->getGoalProgressAsString(), -1, 1); + ListWidget::ListCell progress(a->getProgressAsString(), -1, 1); + row.push_back(title); + row.push_back(goals); + row.push_back(progress); + const std::string id = StringUtils::toString(a->getInfo()->getID()); + m_achievements_list_widget->addItem(id, row); + if (a->isAchieved()) + m_achievements_list_widget->emphasisItem(id); + } + } + else + { + OnlineProfile::IDList a = m_visiting_profile->getAchievements(); + + auto compAchievementInfo = [](int a, int b) { + AchievementInfo *a1 = AchievementsManager::get()->getAchievementInfo(a); + AchievementInfo *a2 = AchievementsManager::get()->getAchievementInfo(b); + return a1->getName().lower_ignore_case(a2->getName()); + }; + + // Because only the name column is visible when viewing other player's achievements, col does not matter + if (m_sort_desc && !m_sort_default) + { + std::sort(a.rbegin(), a.rend(), compAchievementInfo); + } + else if (!m_sort_default) + { + std::sort(a.begin(), a.end(), compAchievementInfo); + } + + for (unsigned int i = 0; i < a.size(); i++) + { + AchievementInfo *info = + AchievementsManager::get()->getAchievementInfo(a[i]); + m_achievements_list_widget->addItem(StringUtils::toString(info->getID()), + info->getName()); + } + } +} // displayResults + // ---------------------------------------------------------------------------- /** Called every frame. It will check if results from an achievement request * have been received, and if so, display them. @@ -194,15 +288,5 @@ void BaseOnlineProfileAchievements::onUpdate(float delta) } // Now reesults are available, display them. - m_achievements_list_widget->clear(); - const OnlineProfile::IDList &a = m_visiting_profile->getAchievements(); - for (unsigned int i = 0; i < a.size(); i++) - { - AchievementInfo *info = - AchievementsManager::get()->getAchievementInfo(a[i]); - m_achievements_list_widget->addItem(StringUtils::toString(info->getID()), - info->getName() ); - } - m_waiting_for_achievements = false; - + displayResults(); } // onUpdate diff --git a/src/states_screens/online/online_profile_achievements.hpp b/src/states_screens/online/online_profile_achievements.hpp index ddd4bf22f..99fd892b3 100644 --- a/src/states_screens/online/online_profile_achievements.hpp +++ b/src/states_screens/online/online_profile_achievements.hpp @@ -35,7 +35,8 @@ namespace GUIEngine { class Widget; } * \brief Online profiel overview screen * \ingroup states_screens */ -class BaseOnlineProfileAchievements : public OnlineProfileBase +class BaseOnlineProfileAchievements : public OnlineProfileBase, + public GUIEngine::IListWidgetHeaderListener { private: @@ -44,6 +45,15 @@ private: int m_selected_achievement_index; bool m_waiting_for_achievements; + /** Which column to use for sorting. */ + int m_sort_column; + + bool m_sort_desc; + + bool m_sort_default; + + void displayResults(); + protected: BaseOnlineProfileAchievements(const std::string &filename); @@ -62,6 +72,7 @@ public: virtual void onUpdate(float delta) OVERRIDE; virtual void beforeAddingWidget() OVERRIDE; + virtual void onColumnClicked(int column_id, bool sort_desc, bool sort_default) OVERRIDE; // ------------------------------------------------------------------------ virtual void refreshAchievementsList()