The Battle for Wesnoth  1.17.0-dev
lobby_player_list_helper.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2021
3  by Tomasz Sniatowski <kailoran@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
17 
18 #include "font/text_formatting.hpp"
20 #include "gettext.hpp"
23 #include "gui/widgets/label.hpp"
26 #include "gui/widgets/window.hpp"
27 
28 static lg::log_domain log_lobby("lobby");
29 #define ERR_LB LOG_STREAM(err, log_lobby)
30 
31 namespace gui2
32 {
33 lobby_player_list_helper::sub_list::sub_list(tree_view* parent_tree, const std::string& lbl, const bool unfolded)
34 {
35  std::map<std::string, string_map> tree_group_item;
36  tree_group_item["tree_view_node_label"]["label"] = lbl;
37 
38  root = &parent_tree->add_node("player_group", tree_group_item);
39 
40  if(unfolded) {
41  root->unfold();
42  }
43 
44  label_player_count = find_widget<label>(root, "player_count", false, true);
45  assert(label_player_count);
46 }
47 
49 {
50  label_player_count->set_label(std::to_string(root->count_children()));
51 }
52 
53 namespace
54 {
55 struct update_pod
56 {
57  /** The raw data used to mass-construct player tree nodes. */
58  std::vector<std::map<std::string, string_map>> node_data;
59 
60  /** The associated user data for each node, index-to-index. */
61  std::vector<mp::user_info*> user_data;
62 };
63 } // namespace
64 
65 void lobby_player_list_helper::update(std::vector<mp::user_info>& user_info)
66 {
67  const unsigned scrollbar_position = tree->get_vertical_scrollbar_item_position();
68  std::array<update_pod, std::tuple_size<decltype(player_lists)>::value> inputs{};
69 
70  for(auto& user : user_info) {
71  std::string name = user.name;
72 
73  std::stringstream icon_ss;
74  icon_ss << "lobby/status";
75 
76  switch(user.state) {
78  icon_ss << "-lobby";
79  break;
81  name = font::span_color({0, 255, 255}, name);
82  icon_ss << (user.observing ? "-obs" : "-playing");
83  break;
85  name = font::span_color(font::GRAY_COLOR, name);
86  icon_ss << (user.observing ? "-obs" : "-playing");
87  break;
88  default:
89  ERR_LB << "Bad user state in lobby: " << user.name << ": " << static_cast<int>(user.state) << "\n";
90  continue;
91  }
92 
93  switch(user.relation) {
95  icon_ss << "-s";
96  break;
98  icon_ss << "-n";
99  break;
101  icon_ss << "-f";
102  break;
104  icon_ss << "-i";
105  break;
106  default:
107  ERR_LB << "Bad user relation in lobby: " << static_cast<int>(user.relation) << "\n";
108  }
109 
110  icon_ss << ".png";
111 
112  string_map tree_group_field;
113  std::map<std::string, string_map> tree_group_item;
114 
115  /*** Add tree item ***/
116  tree_group_field["label"] = icon_ss.str();
117  tree_group_item["icon"] = tree_group_field;
118 
119  tree_group_field["label"] = name;
120  tree_group_field["use_markup"] = "true";
121  tree_group_item["name"] = tree_group_field;
122 
123  // Indices here must match the order of the lists in the player_lists array (see `init`)
124  switch(user.state) {
126  inputs[0].node_data.push_back(std::move(tree_group_item));
127  inputs[0].user_data.push_back(&user);
128 
129  break;
131  inputs[1].node_data.push_back(std::move(tree_group_item));
132  inputs[1].user_data.push_back(&user);
133 
134  break;
136  inputs[2].node_data.push_back(std::move(tree_group_item));
137  inputs[2].user_data.push_back(&user);
138 
139  break;
140  default:
141  ERR_LB << "Bad user state in lobby: " << user.name << ": " << static_cast<int>(user.state) << "\n";
142  continue;
143  }
144  }
145 
146  for(std::size_t i = 0; i < player_lists.size(); ++i) {
147  assert(inputs[i].node_data.size() == inputs[i].user_data.size());
148 
149  // Add the player nodes
150  const auto new_nodes = player_lists[i].root->replace_children("player", inputs[i].node_data);
151 
152  for(std::size_t k = 0; k < new_nodes.size(); ++k) {
154  find_widget<toggle_panel>(new_nodes[k].get(), "tree_view_node_label", false),
155  std::bind(user_callback, inputs[i].user_data[k])
156  );
157  }
158 
159  player_lists[i].update_player_count_label();
160  }
161 
162  // Don't attempt to restore the scroll position if the window hasn't been laid out yet
163  if(tree->get_origin() != point{-1, -1}) {
164  tree->set_vertical_scrollbar_item_position(scrollbar_position);
165  }
166 }
167 
169 {
170  tree = find_widget<tree_view>(&w, "player_tree", false, true);
171 
172  player_lists = {
173  sub_list{tree, _("Selected Game"), true},
174  sub_list{tree, _("Lobby"), true},
175  sub_list{tree, _("Other Games"), false}
176  };
177 }
178 } // namespace gui2
std::vector< mp::user_info * > user_data
The associated user data for each node, index-to-index.
const color_t GRAY_COLOR
tree_view * tree
The parent tree.
This file contains the window object, this object is a top level container which has the event manage...
static std::string _(const char *str)
Definition: gettext.hpp:93
std::size_t count_children() const
The number of children in this widget.
Generic file dialog.
Definition: field-fwd.hpp:23
std::function< void(mp::user_info *)> user_callback
The double click callback bound to each player&#39;s tree node.
virtual void set_label(const t_string &label)
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
static lg::log_domain log_lobby("lobby")
std::vector< std::map< std::string, string_map > > node_data
The raw data used to mass-construct player tree nodes.
A tree view is a control that holds several items of the same or different types. ...
Definition: tree_view.hpp:60
std::array< sub_list, 3 > player_lists
Main subsections of the player tree.
void connect_signal_mouse_left_double_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button double click.
Definition: dispatcher.cpp:182
std::size_t i
Definition: function.cpp:967
void set_vertical_scrollbar_item_position(const unsigned position)
Move the vertical scrollbar to a position.
std::map< std::string, t_string > string_map
Definition: widget.hpp:26
Holds a 2D point.
Definition: point.hpp:24
void unfold(const bool recursive=false)
int w
void update(std::vector< mp::user_info > &user_info)
Updates the tree contents based on the given user data.
#define ERR_LB
unsigned get_vertical_scrollbar_item_position() const
Returns current position of the vertical scrollbar.
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:65
point get_origin() const
Returns the screen origin of the widget.
Definition: widget.cpp:300
tree_view_node & add_node(const std::string &id, const std::map< std::string, string_map > &data, const int index=-1)
Definition: tree_view.cpp:57