Ticket #2405: colist_handler_lobby_sortable_game_list.patch

File colist_handler_lobby_sortable_game_list.patch, 6.2 KB (added by Vladislav Belov, 9 years ago)
  • binaries/data/mods/public/gui/lobby/lobby.js

     
    11var g_ChatMessages = [];
    22var g_Name = "unknown";
    33var g_GameList = {};
     4var g_GameListSortBy = "default";
     5var g_GameListOrder = 1; // 1 for ascending sort, and -1 for descending
    46var g_specialKey = Math.random();
    57// This object looks like {"name":[numMessagesSinceReset, lastReset, timeBlocked]} when in use.
    68var g_spamMonitor = {};
     
    7476// Update functions
    7577////////////////////////////////////////////////////////////////////////////////////////////////
    7678
     79function updateOrderSelection()
     80{
     81    var newGameListSortBy = Engine.GetGUIObjectByName("gamesBox").selected_column;
     82
     83    // If selected column equal to previous then just reverse order
     84    if (newGameListSortBy == g_GameListSortBy)
     85        g_GameListOrder = -g_GameListOrder;
     86    else
     87    {
     88        g_GameListSortBy = newGameListSortBy;
     89        g_GameListOrder = 1;
     90    }
     91
     92    updateGameList();
     93    updateGameSelection();
     94}
     95
    7796function resetFilters()
    7897{
    7998    // Reset states of gui objects
     
    365384    // Sort the list of games to that games 'waiting' are displayed at the top, followed by 'init', followed by 'running'.
    366385    var gameStatuses = ['waiting', 'init', 'running'];
    367386    g_GameList.sort(function (a,b) {
    368         if (gameStatuses.indexOf(a.state) < gameStatuses.indexOf(b.state))
    369             return -1;
    370         else if (gameStatuses.indexOf(a.state) > gameStatuses.indexOf(b.state))
    371             return 1;
     387        switch (g_GameListSortBy)
     388        {
     389        case 'name':
     390            if (a.name < b.name)
     391                return -g_GameListOrder;
     392            else if (a.name > b.name)
     393                return g_GameListOrder;
     394            return 0;
     395        case 'mapName':
     396            if (translate(a.niceMapName) < translate(b.niceMapName))
     397                return -g_GameListOrder;
     398            else if (translate(a.niceMapName) > translate(b.niceMapName))
     399                return g_GameListOrder;
     400            return 0;
     401        case 'mapSize':
     402            if (translatedMapSize(a.mapSize) < translatedMapSize(b.mapSize))
     403                return -g_GameListOrder;
     404            else if (translatedMapSize(a.mapSize) > translatedMapSize(b.mapSize))
     405                return g_GameListOrder;
     406            return 0;
     407        case 'mapType':
     408            if (a.mapType < b.mapType)
     409                return -g_GameListOrder;
     410            else if (a.mapType > b.mapType)
     411                return g_GameListOrder;
     412            return 0;
     413        case 'nPlayers':
     414            // Numerical comparison of player count ratio.
     415            if (a.nbp * b.tnbp < b.nbp * a.tnbp) // ratio a = a.nbp / a.tnbp, ratio b = b.nbp / b.tnbp
     416                return -g_GameListOrder;
     417            else if (a.nbp * b.tnbp > b.nbp * a.tnbp)
     418                return g_GameListOrder;
     419            return 0;
     420        default:
     421            if (gameStatuses.indexOf(a.state) < gameStatuses.indexOf(b.state))
     422                return -1;
     423            else if (gameStatuses.indexOf(a.state) > gameStatuses.indexOf(b.state))
     424                return 1;
    372425
    373         // Alphabetical comparison of names as tiebreaker.
    374         if (a.name < b.name)
    375             return -1;
    376         else if (a.name > b.name)
    377             return 1;
    378         return 0;
     426            // Alphabetical comparison of names as tiebreaker.
     427            if (a.name < b.name)
     428                return -1;
     429            else if (a.name > b.name)
     430                return 1;
     431            return 0;
     432        }
    379433    });
    380434
    381435    var list_name = [];
  • binaries/data/mods/public/gui/lobby/lobby.xml

     
    169169
    170170        <!-- Middle panel: Filters, game list, chat box. -->
    171171        <object name="middlePanel" size="20%+5 5% 100%-255 97.2%">
    172             <object name="gamesBox" style="ModernList" type="olist" size="0 25 100% 48%" font="sans-stroke-13">
     172            <object name="gamesBox" style="ModernList" type="olist" sortable="true" size="0 25 100% 48%" font="sans-stroke-13">
    173173                <action on="SelectionChange">updateGameSelection();</action>
     174                <action on="SelectionColumnChange">updateOrderSelection();</action>
    174175                <def id="name" color="0 60 0" width="27%">
    175176                    <translatableAttribute id="heading">Name</translatableAttribute>
    176177                </def>
  • source/gui/COList.cpp

     
    1919#include "i18n/L10n.h"
    2020
    2121#include "ps/CLogger.h"
     22#include "soundmanager/ISoundManager.h"
    2223
    2324COList::COList() : CList(),m_HeadingHeight(30.f)
    2425{
    2526    AddSetting(GUIST_CGUISpriteInstance,    "sprite_heading");
     27    AddSetting(GUIST_bool,                  "sortable");
     28    AddSetting(GUIST_CStr,                  "selected_column");
     29    AddSetting(GUIST_int,                   "selected_def");
     30
     31    // Nothing is selected by default.
     32    GUI<CStr>::SetSetting(this, "selected_column", "");
     33    GUI<int>::SetSetting(this, "selected_def", -1);
    2634}
    2735
    2836void COList::SetupText()
     
    119127void COList::HandleMessage(SGUIMessage &Message)
    120128{
    121129    CList::HandleMessage(Message);
     130
     131    switch (Message.type)
     132    {
     133    // If somebody clicks on the column heading
     134    case GUIM_MOUSE_PRESS_LEFT:
     135    {
     136        bool sortable;
     137        GUI<bool>::GetSetting(this, "sortable", sortable);
     138        if (!sortable)
     139            return;
     140
     141        CPos mouse = GetMousePos();
     142        if (!m_CachedActualSize.PointInside(mouse))
     143            return;
     144       
     145        float xpos = 0;
     146        for (unsigned int def = 0; def < m_ObjectsDefs.size(); ++def)
     147        {
     148            float width = m_ObjectsDefs[def].m_Width;
     149            // Check if it's a decimal value, and if so, assume relative positioning.
     150            if (m_ObjectsDefs[def].m_Width < 1 && m_ObjectsDefs[def].m_Width > 0)
     151                width *= m_TotalAvalibleColumnWidth;
     152            CPos leftTopCorner = m_CachedActualSize.TopLeft() + CPos(xpos, 4);
     153            if (mouse.x >= leftTopCorner.x &&
     154                mouse.x < leftTopCorner.x + width &&
     155                mouse.y < leftTopCorner.y + m_HeadingHeight)
     156            {
     157                GUI<CStr>::SetSetting(this, "selected_column", m_ObjectsDefs[def].m_Id.substr(5));
     158                GUI<int>::SetSetting(this, "selected_def", def);
     159                ScriptEvent("selectioncolumnchange");
     160
     161                CStrW soundPath;
     162                if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_selected", soundPath) == PSRETURN_OK && !soundPath.empty())
     163                    g_SoundManager->PlayAsUI(soundPath.c_str(), false);
     164
     165                return;
     166            }
     167            xpos += width;
     168        }
     169        return;
     170    }
     171    default:
     172        return;
     173    }
    122174}
    123175
    124176bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile)