The Battle for Wesnoth  1.19.7+dev
lobby_player_list_helper.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2024
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 "serialization/markup.hpp"
20 #include "gettext.hpp"
21 #include "gui/widgets/label.hpp"
24 #include "gui/widgets/window.hpp"
25 
26 static lg::log_domain log_lobby("lobby");
27 #define ERR_LB LOG_STREAM(err, log_lobby)
28 
29 namespace gui2
30 {
31 lobby_player_list_helper::sub_list::sub_list(tree_view* parent_tree, const std::string& lbl, const bool unfolded)
32 {
33  widget_data tree_group_item;
34  tree_group_item["tree_view_node_label"]["label"] = lbl;
35 
36  root = &parent_tree->add_node("player_group", tree_group_item);
37 
38  if(unfolded) {
39  root->unfold();
40  }
41 
42  label_player_count = root->find_widget<label>("player_count", false, true);
43  assert(label_player_count);
44 }
45 
47 {
48  label_player_count->set_label(std::to_string(root->count_children()));
49 }
50 
51 namespace
52 {
53 struct update_pod
54 {
55  /** The raw data used to mass-construct player tree nodes. */
56  std::vector<widget_data> node_data;
57 
58  /** The associated user data for each node, index-to-index. */
59  std::vector<const mp::user_info*> user_data;
60 };
61 } // namespace
62 
63 void lobby_player_list_helper::update(const std::vector<mp::user_info>& user_info, int focused_game)
64 {
65  const unsigned scrollbar_position = tree->get_vertical_scrollbar_item_position();
66  std::array<update_pod, std::tuple_size<decltype(player_lists)>::value> inputs{};
67 
68  for(const auto& user : user_info) {
69  std::string name = user.name;
70 
71  std::stringstream icon_ss;
72  icon_ss << "lobby/status";
73 
74  switch(user.get_state(focused_game)) {
76  icon_ss << "-lobby";
77  break;
79  name = markup::span_color(color_t(0, 255, 255), name);
80  icon_ss << (user.observing ? "-obs" : "-playing");
81  break;
84  icon_ss << (user.observing ? "-obs" : "-playing");
85  break;
86  }
87 
88  switch(user.get_relation()) {
90  icon_ss << "-s";
91  break;
93  icon_ss << "-n";
94  break;
96  icon_ss << "-f";
97  break;
99  icon_ss << "-i";
100  break;
101  }
102 
103  icon_ss << ".png";
104 
105  widget_item tree_group_field;
106  widget_data tree_group_item;
107 
108  /*** Add tree item ***/
109  tree_group_field["label"] = icon_ss.str();
110  tree_group_item["icon"] = tree_group_field;
111 
112  tree_group_field["label"] = name;
113  tree_group_field["use_markup"] = "true";
114  tree_group_item["name"] = tree_group_field;
115 
116  // Indices here must match the order of the lists in the player_lists array (see `init`)
117  switch(user.get_state(focused_game)) {
119  inputs[0].node_data.push_back(std::move(tree_group_item));
120  inputs[0].user_data.push_back(&user);
121 
122  break;
124  inputs[1].node_data.push_back(std::move(tree_group_item));
125  inputs[1].user_data.push_back(&user);
126 
127  break;
129  inputs[2].node_data.push_back(std::move(tree_group_item));
130  inputs[2].user_data.push_back(&user);
131 
132  break;
133  }
134  }
135 
136  info_map.clear();
137 
138  for(std::size_t i = 0; i < player_lists.size(); ++i) {
139  assert(inputs[i].node_data.size() == inputs[i].user_data.size());
140 
141  // Add the player nodes
142  const auto new_nodes = player_lists[i].root->replace_children("player", inputs[i].node_data);
143 
144  for(std::size_t k = 0; k < new_nodes.size(); ++k) {
145  auto* node = new_nodes[k].get();
146  auto* info = inputs[i].user_data[k];
147 
148  // Note the user_info associated with this node
149  info_map.try_emplace(node, info);
150 
152  node->find_widget<toggle_panel>("tree_view_node_label"),
153  std::bind(user_callback, info)
154  );
155  }
156 
157  player_lists[i].update_player_count_label();
158  }
159 
160  // Don't attempt to restore the scroll position if the window hasn't been laid out yet
161  if(tree->get_origin() != point{-1, -1}) {
162  tree->set_vertical_scrollbar_item_position(scrollbar_position);
163  }
164 }
165 
167 {
168  tree = w.find_widget<tree_view>("player_tree", false, true);
169 
170  player_lists = {
171  sub_list{tree, _("Selected Game"), true},
172  sub_list{tree, _("Lobby"), true},
173  sub_list{tree, _("Other Games"), false}
174  };
175 }
176 
178 {
179  return info_map.at(tree->selected_item());
180 }
181 
182 } // namespace gui2
std::map< const tree_view_node *, const mp::user_info * > info_map
Node-to-info mappings for easy access.
const mp::user_info * get_selected_info() const
std::array< sub_list, 3 > player_lists
Main subsections of the player tree.
void update(const std::vector< mp::user_info > &user_info, int focused_game)
Updates the tree contents based on the given user data.
std::function< void(const mp::user_info *)> user_callback
The double click callback bound to each player's tree node.
unsigned get_vertical_scrollbar_item_position() const
Returns current position of the vertical scrollbar.
void set_vertical_scrollbar_item_position(const unsigned position)
Move the vertical scrollbar to a position.
void unfold(const bool recursive=false)
tree_view_node & add_node(const std::string &id, const widget_data &data, const int index=-1)
Definition: tree_view.cpp:56
tree_view_node * selected_item()
Definition: tree_view.hpp:98
point get_origin() const
Returns the screen origin of the widget.
Definition: widget.cpp:311
T * find_widget(const std::string_view id, const bool must_be_active, const bool must_exist)
Gets a widget with the wanted id.
Definition: widget.hpp:753
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:61
std::size_t i
Definition: function.cpp:1029
int w
static std::string _(const char *str)
Definition: gettext.hpp:93
This file contains the window object, this object is a top level container which has the event manage...
static lg::log_domain log_lobby("lobby")
std::vector< widget_data > node_data
The raw data used to mass-construct player tree nodes.
std::vector< const mp::user_info * > user_data
The associated user data for each node, index-to-index.
const color_t GRAY_COLOR
void connect_signal_mouse_left_double_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button double click.
Definition: dispatcher.cpp:198
Generic file dialog.
std::map< std::string, widget_item > widget_data
Definition: widget.hpp:36
std::map< std::string, t_string > widget_item
Definition: widget.hpp:33
logger & info()
Definition: log.cpp:319
std::string span_color(const color_t &color, Args &&... data)
Definition: markup.hpp:68
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
This class represents the information a client has about another player.
Definition: lobby_data.hpp:30
Holds a 2D point.
Definition: point.hpp:25