Index: ps/trunk/binaries/data/mods/public/gui/lobby/LobbyPage/PlayerList.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/lobby/LobbyPage/PlayerList.js (revision 25928) +++ ps/trunk/binaries/data/mods/public/gui/lobby/LobbyPage/PlayerList.js (revision 25929) @@ -1,225 +1,226 @@ /** * This class is concerned with displaying players who are online and * triggering handlers when selecting or doubleclicking on a player. */ class PlayerList { constructor(xmppMessages, buddyButton, gameList) { this.gameList = gameList; this.selectedPlayer = undefined; this.statusOrder = Object.keys(this.PlayerStatuses); // Avoid repeated array construction for performance this.buddyStatusList = []; this.playerList = []; this.presenceList = []; this.nickList = []; this.ratingList = []; this.playersFilter = Engine.GetGUIObjectByName("playersFilter"); this.playersFilter.onPress = this.selectPlayer.bind(this); this.playersFilter.onTab = this.autocomplete.bind(this); + this.playersFilter.tooltip = colorizeAutocompleteHotkey(); this.selectionChangeHandlers = new Set(); this.mouseLeftDoubleClickItemHandlers = new Set(); this.playersBox = Engine.GetGUIObjectByName("playersBox"); this.playersBox.onSelectionChange = this.onPlayerListSelection.bind(this); this.playersBox.onSelectionColumnChange = this.rebuildPlayerList.bind(this); this.playersBox.onMouseLeftClickItem = this.onMouseLeftClickItem.bind(this); this.playersBox.onMouseLeftDoubleClickItem = this.onMouseLeftDoubleClickItem.bind(this); buddyButton.registerBuddyChangeHandler(this.onBuddyChange.bind(this)); xmppMessages.registerPlayerListUpdateHandler(this.rebuildPlayerList.bind(this)); this.registerSelectionChangeHandler(buddyButton.onPlayerSelectionChange.bind(buddyButton)); this.registerMouseLeftDoubleClickItemHandler(buddyButton.onPress.bind(buddyButton)); this.rebuildPlayerList(); } selectPlayer() { let index = this.playersBox.list.indexOf(this.playersFilter.caption); if (index != -1) this.playersBox.selected = index; } autocomplete() { autoCompleteText( this.playersFilter, Engine.GetPlayerList().map(player => player.name)); } registerSelectionChangeHandler(handler) { this.selectionChangeHandlers.add(handler); } registerMouseLeftDoubleClickItemHandler(handler) { this.mouseLeftDoubleClickItemHandlers.add(handler); } onBuddyChange() { this.rebuildPlayerList(); } onMouseLeftDoubleClickItem() { for (let handler of this.mouseLeftDoubleClickItemHandlers) handler(); } onMouseLeftClickItem() { // In case of clicking on the same player again this.gameList.selectGameFromPlayername(this.selectedPlayer); } onPlayerListSelection() { if (this.playersBox.selected == this.playersBox.list.indexOf(this.selectedPlayer)) return; this.selectedPlayer = this.playersBox.list[this.playersBox.selected]; this.gameList.selectGameFromPlayername(this.selectedPlayer); for (let handler of this.selectionChangeHandlers) handler(this.selectedPlayer); } parsePlayer(sortKey, player) { player.isBuddy = g_Buddies.indexOf(player.name) != -1; switch (sortKey) { case 'buddy': player.sortValue = (player.isBuddy ? 1 : 2) + this.statusOrder.indexOf(player.presence) + player.name.toLowerCase(); break; case 'rating': player.sortValue = +player.rating; break; case 'status': player.sortValue = this.statusOrder.indexOf(player.presence) + player.name.toLowerCase(); break; case 'name': default: player.sortValue = player.name.toLowerCase(); break; } } /** * Do a full update of the player listing, including ratings from cached C++ information. * Important: This should only be performed once if * there have been multiple messages received changing this list. */ rebuildPlayerList() { Engine.ProfileStart("rebuildPlaersList"); Engine.ProfileStart("getPlayerList"); let playerList = Engine.GetPlayerList(); Engine.ProfileStop(); Engine.ProfileStart("parsePlayers"); playerList.forEach(this.parsePlayer.bind(this, this.playersBox.selected_column)); Engine.ProfileStop(); Engine.ProfileStart("sortPlayers"); playerList.sort(this.sortPlayers.bind(this, this.playersBox.selected_column_order)); Engine.ProfileStop(); Engine.ProfileStart("prepareList"); let length = playerList.length; this.buddyStatusList.length = length; this.playerList.length = length; this.presenceList.length = length; this.nickList.length = length; this.ratingList.length = length; playerList.forEach((player, i) => { // TODO: COList.cpp columns should support horizontal center align let rating = player.rating ? (" " + player.rating).substr(-5) : " -"; let presence = this.PlayerStatuses[player.presence] ? player.presence : "unknown"; if (presence == "unknown") warn("Unknown presence:" + player.presence); let statusTags = this.PlayerStatuses[presence].tags; this.buddyStatusList[i] = player.isBuddy ? setStringTags(g_BuddySymbol, statusTags) : ""; this.playerList[i] = PlayerColor.ColorPlayerName(player.name, "", player.role); this.presenceList[i] = setStringTags(this.PlayerStatuses[presence].status, statusTags); this.ratingList[i] = setStringTags(rating, statusTags); this.nickList[i] = escapeText(player.name); }); Engine.ProfileStop(); Engine.ProfileStart("copyToGUI"); this.playersBox.list_buddy = this.buddyStatusList; this.playersBox.list_name = this.playerList; this.playersBox.list_status = this.presenceList; this.playersBox.list_rating = this.ratingList; this.playersBox.list = this.nickList; Engine.ProfileStop(); Engine.ProfileStart("selectionChange"); this.playersBox.selected = this.playersBox.list.indexOf(this.selectedPlayer); Engine.ProfileStop(); Engine.ProfileStop(); } sortPlayers(sortOrder, player1, player2) { if (player1.sortValue < player2.sortValue) return -sortOrder; if (player1.sortValue > player2.sortValue) return +sortOrder; return 0; } } /** * The playerlist will be assembled using these values. */ PlayerList.prototype.PlayerStatuses = { "available": { "status": translate("Online"), "tags": { "color": "0 219 0" } }, "away": { "status": translate("Away"), "tags": { "color": "255 127 0" } }, "playing": { "status": translate("Busy"), "tags": { "color": "200 0 0" } }, "offline": { "status": translate("Offline"), "tags": { "color": "0 0 0" } }, "unknown": { "status": translateWithContext("lobby presence", "Unknown"), "tags": { "color": "178 178 178" } } };