gui2/mp_connect: Overhaul dialog adding a more powerful server list
There has been functionality to manage custom servers in the player's
preferences file since as far back as commit
5fb0b2a911
in June 2007, but there's never
been a user interface for it.
This commit removes the current server list dialog attached to the MP
Connect dialog and replaces it with the same functionality embedded into
the latter, as well as the ability to edit the server list in the
player's preferences file. There's some code movement in a few other
places since the previous function in the preferences namespace doesn't
suit the new code (it always returned a combined list of game and
player-defined servers).
There's some disabled code referencing a situation where the listbox
with the list of servers allows the code (and the player) to clear the
selection. It's disabled because there are some UX issues with it noted
in the code comments associated to it.
Fixes #4564.
This commit is contained in:
parent
78df5c305e
commit
f136bb9ef3
9 changed files with 473 additions and 409 deletions
|
@ -15,6 +15,17 @@
|
|||
horizontal_placement = "center"
|
||||
|
||||
maximum_width = 800
|
||||
maximum_height = 600
|
||||
|
||||
[linked_group]
|
||||
id = "name"
|
||||
fixed_width = true
|
||||
[/linked_group]
|
||||
|
||||
[linked_group]
|
||||
id = "address"
|
||||
fixed_width = true
|
||||
[/linked_group]
|
||||
|
||||
[tooltip]
|
||||
id = "tooltip"
|
||||
|
@ -57,7 +68,7 @@
|
|||
[label]
|
||||
definition = "default"
|
||||
|
||||
label = _ "You will now connect to the multiplayer server."
|
||||
label = _ "Choose or enter the address of a multiplayer server."
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
@ -87,7 +98,7 @@
|
|||
[label]
|
||||
definition = "default"
|
||||
|
||||
label = _ "Server:"
|
||||
label = _ "Address:"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
@ -121,15 +132,115 @@
|
|||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
grow_factor = 1
|
||||
horizontal_alignment = "right"
|
||||
horizontal_grow = true
|
||||
|
||||
[button]
|
||||
id = "list"
|
||||
[listbox]
|
||||
id = "server_list"
|
||||
definition = "default"
|
||||
# NOTE: Do not use. See mp_connect.cpp.
|
||||
#has_minimum = false
|
||||
|
||||
label = _ "View List"
|
||||
[/button]
|
||||
[header]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "name"
|
||||
definition = "gold_small"
|
||||
linked_group = "name"
|
||||
|
||||
label = _ "Name"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "address"
|
||||
definition = "gold_small"
|
||||
linked_group = "address"
|
||||
|
||||
label = _ "Address"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/header]
|
||||
|
||||
[list_definition]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
vertical_grow = true
|
||||
horizontal_grow = true
|
||||
|
||||
[toggle_panel]
|
||||
definition = "default"
|
||||
|
||||
return_value_id = "ok"
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "name"
|
||||
definition = "default"
|
||||
linked_group = "name"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "address"
|
||||
definition = "default"
|
||||
linked_group = "address"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/toggle_panel]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/list_definition]
|
||||
|
||||
[/listbox]
|
||||
|
||||
[/column]
|
||||
|
||||
|
@ -140,7 +251,7 @@
|
|||
|
||||
[column]
|
||||
|
||||
horizontal_alignment = "right"
|
||||
horizontal_grow = true
|
||||
|
||||
[grid]
|
||||
|
||||
|
@ -148,6 +259,35 @@
|
|||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
|
||||
[button]
|
||||
id = "server_add"
|
||||
definition = "add"
|
||||
label = _ "Add"
|
||||
[/button]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
|
||||
[button]
|
||||
id = "server_delete"
|
||||
definition = "delete"
|
||||
label = _ "Delete"
|
||||
[/button]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "right"
|
||||
|
@ -162,6 +302,7 @@
|
|||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "right"
|
||||
|
|
|
@ -1,248 +0,0 @@
|
|||
#textdomain wesnoth-lib
|
||||
###
|
||||
### Definition of the window to select a predefined mp server.
|
||||
###
|
||||
|
||||
[window]
|
||||
id = "mp_server_list"
|
||||
description = "MP Server list selection dialog."
|
||||
|
||||
[resolution]
|
||||
definition = "default"
|
||||
|
||||
automatic_placement = true
|
||||
vertical_placement = "center"
|
||||
horizontal_placement = "center"
|
||||
|
||||
[linked_group]
|
||||
id = "name"
|
||||
fixed_width = true
|
||||
[/linked_group]
|
||||
|
||||
[linked_group]
|
||||
id = "address"
|
||||
fixed_width = true
|
||||
[/linked_group]
|
||||
|
||||
[tooltip]
|
||||
id = "tooltip"
|
||||
[/tooltip]
|
||||
|
||||
[helptip]
|
||||
id = "tooltip"
|
||||
[/helptip]
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
[label]
|
||||
definition = "title"
|
||||
|
||||
label = _ "Connect to Server"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
|
||||
[label]
|
||||
definition = "default"
|
||||
|
||||
label = _ "You will now connect to the multiplayer server."
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 1
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
|
||||
horizontal_grow = true
|
||||
vertical_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[listbox]
|
||||
id = "server_list"
|
||||
definition = "default"
|
||||
[header]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "name"
|
||||
definition = "default"
|
||||
linked_group = "name"
|
||||
|
||||
label = _ "Name"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "address"
|
||||
definition = "default"
|
||||
linked_group = "address"
|
||||
|
||||
label = _ "Address"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/header]
|
||||
|
||||
[list_definition]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
vertical_grow = true
|
||||
horizontal_grow = true
|
||||
|
||||
[toggle_panel]
|
||||
definition = "default"
|
||||
|
||||
return_value_id = "ok"
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "name"
|
||||
definition = "default"
|
||||
linked_group = "name"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "address"
|
||||
definition = "default"
|
||||
linked_group = "address"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/toggle_panel]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/list_definition]
|
||||
|
||||
[/listbox]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
horizontal_alignment = "right"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "right"
|
||||
|
||||
[button]
|
||||
id = "ok"
|
||||
definition = "default"
|
||||
|
||||
label = _ "Select"
|
||||
[/button]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "right"
|
||||
|
||||
[button]
|
||||
id = "cancel"
|
||||
definition = "default"
|
||||
|
||||
label = _ "Cancel"
|
||||
[/button]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/resolution]
|
||||
|
||||
[/window]
|
|
@ -819,7 +819,7 @@ bool game_launcher::play_multiplayer(mp_selection res)
|
|||
// The prompt saves its input to preferences.
|
||||
multiplayer_server_ = preferences::network_host();
|
||||
|
||||
if(multiplayer_server_ != preferences::server_list().front().address) {
|
||||
if(multiplayer_server_ != preferences::builtin_servers_list().front().address) {
|
||||
preferences::set_network_host(multiplayer_server_);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,114 +16,48 @@
|
|||
|
||||
#include "gui/dialogs/multiplayer/mp_connect.hpp"
|
||||
|
||||
#include "gettext.hpp"
|
||||
#include "preferences/game.hpp"
|
||||
#include "gui/auxiliary/field.hpp"
|
||||
#include "gui/dialogs/edit_text.hpp"
|
||||
#include "gui/dialogs/modal_dialog.hpp"
|
||||
#include "gui/widgets/button.hpp"
|
||||
#include "gui/widgets/listbox.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
#include "utils/functional.hpp"
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
static lg::log_domain log_mpconnect{"gui/dialogs/mp_connect"};
|
||||
#define ERR_DLG LOG_STREAM(err, log_mpconnect)
|
||||
#define WRN_DLG LOG_STREAM(warn, log_mpconnect)
|
||||
#define LOG_DLG LOG_STREAM(info, log_mpconnect)
|
||||
#define DBG_DLG LOG_STREAM(debug, log_mpconnect)
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
namespace dialogs
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/*WIKI
|
||||
* @page = GUIWindowDefinitionWML
|
||||
* @order = 2_mp_server_list
|
||||
*
|
||||
* == Multiplayer server list ==
|
||||
*
|
||||
* This shows the dialog with a list of predefined multiplayer servers.
|
||||
*
|
||||
* @begin{table}{dialog_widgets}
|
||||
*
|
||||
* server_list & & listbox & m &
|
||||
* Listbox with the predefined servers to connect to. $
|
||||
*
|
||||
* -name & & styled_widget & o &
|
||||
* Widget which shows the name of the server. $
|
||||
*
|
||||
* -address & & styled_widget & m &
|
||||
* The address/host_name of the server. $
|
||||
*
|
||||
* @end{table}
|
||||
*/
|
||||
|
||||
class mp_server_list : public modal_dialog
|
||||
// NOTE: See mp_connect::select_first_match() below
|
||||
#if 0
|
||||
void clear_listbox_selection(listbox& listbox)
|
||||
{
|
||||
public:
|
||||
mp_server_list() : host_name_()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& host_name() const
|
||||
{
|
||||
return host_name_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string host_name_;
|
||||
|
||||
/** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */
|
||||
virtual const std::string& window_id() const override;
|
||||
|
||||
/** Inherited from modal_dialog. */
|
||||
virtual void pre_show(window& window) override;
|
||||
|
||||
/** Inherited from modal_dialog. */
|
||||
virtual void post_show(window& window) override;
|
||||
};
|
||||
|
||||
REGISTER_DIALOG(mp_server_list)
|
||||
|
||||
void mp_server_list::pre_show(window& window)
|
||||
{
|
||||
set_restore(true);
|
||||
|
||||
listbox& list = find_widget<listbox>(&window, "server_list", false);
|
||||
|
||||
window.keyboard_capture(&list);
|
||||
|
||||
const std::vector<game_config::server_info>& pref_servers
|
||||
= preferences::server_list();
|
||||
|
||||
for(const auto & server : pref_servers)
|
||||
{
|
||||
|
||||
std::map<std::string, string_map> data;
|
||||
string_map item;
|
||||
|
||||
item["label"] = server.name;
|
||||
data.emplace("name", item);
|
||||
|
||||
item["label"] = server.address;
|
||||
data.emplace("address", item);
|
||||
|
||||
list.add_row(data);
|
||||
const auto selection = listbox.get_selected_row();
|
||||
if(selection >= 0) {
|
||||
listbox.select_row(selection, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void mp_server_list::post_show(window& window)
|
||||
{
|
||||
if(get_retval() == retval::OK) {
|
||||
|
||||
const listbox& list
|
||||
= find_widget<const listbox>(&window, "server_list", false);
|
||||
|
||||
const grid* row = list.get_row_grid(list.get_selected_row());
|
||||
assert(row);
|
||||
|
||||
host_name_ = find_widget<const styled_widget>(row, "address", false).get_label();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
namespace dialogs
|
||||
{
|
||||
|
||||
/*WIKI
|
||||
* @page = GUIWindowDefinitionWML
|
||||
|
@ -146,44 +80,216 @@ void mp_server_list::post_show(window& window)
|
|||
|
||||
REGISTER_DIALOG(mp_connect)
|
||||
|
||||
static void
|
||||
show_server_list(window& window, field_text* host_name)
|
||||
{
|
||||
assert(host_name);
|
||||
|
||||
mp_server_list dlg;
|
||||
dlg.show();
|
||||
|
||||
if(dlg.get_retval() == retval::OK) {
|
||||
host_name->set_widget_value(window, dlg.host_name());
|
||||
}
|
||||
}
|
||||
|
||||
mp_connect::mp_connect()
|
||||
: host_name_(register_text("host_name",
|
||||
true,
|
||||
preferences::network_host,
|
||||
preferences::set_network_host,
|
||||
true))
|
||||
, builtin_servers_(preferences::builtin_servers_list())
|
||||
, user_servers_(preferences::user_servers_list())
|
||||
{
|
||||
set_restore(true);
|
||||
}
|
||||
|
||||
void mp_connect::pre_show(window& win)
|
||||
std::array<mp_connect::server_list*, 2> mp_connect::server_lists()
|
||||
{
|
||||
assert(host_name_);
|
||||
|
||||
// Set view list callback button.
|
||||
if(button* btn = find_widget<button>(&win, "list", false, false)) {
|
||||
|
||||
connect_signal_mouse_left_click(*btn,
|
||||
std::bind(show_server_list, std::ref(win), host_name_));
|
||||
}
|
||||
return {{ &builtin_servers_, &user_servers_ }};
|
||||
}
|
||||
|
||||
modal_dialog* mp_connect::mp_server_list_for_unit_test()
|
||||
void mp_connect::pre_show(window& win)
|
||||
{
|
||||
return new mp_server_list();
|
||||
text_box& hostname_box = find_widget<text_box>(&win, "host_name", false);
|
||||
listbox& server_list = find_widget<listbox>(&win, "server_list", false);
|
||||
button& button_add = find_widget<button>(&win, "server_add", false);
|
||||
button& button_del = find_widget<button>(&win, "server_delete", false);
|
||||
|
||||
for(const auto* servers : server_lists()) {
|
||||
for(const auto& server : *servers) {
|
||||
insert_into_server_listbox(server_list, server);
|
||||
}
|
||||
}
|
||||
|
||||
select_first_match();
|
||||
|
||||
connect_signal_notify_modified(hostname_box, std::bind(&mp_connect::on_address_change, this));
|
||||
connect_signal_notify_modified(server_list, std::bind(&mp_connect::on_server_select, this));
|
||||
connect_signal_mouse_left_click(button_add, std::bind(&mp_connect::on_server_add, this));
|
||||
connect_signal_mouse_left_click(button_del, std::bind(&mp_connect::on_server_delete, this));
|
||||
}
|
||||
|
||||
void mp_connect::insert_into_server_listbox(listbox& listbox, const server_info& srv, int pos)
|
||||
{
|
||||
const std::map<std::string, string_map>& entry{
|
||||
{ "name", string_map{{"label", srv.name}} },
|
||||
{ "address", string_map{{"label", srv.address}} },
|
||||
};
|
||||
|
||||
listbox.add_row(entry, pos);
|
||||
}
|
||||
|
||||
void mp_connect::select_first_match()
|
||||
{
|
||||
window* window = get_window();
|
||||
|
||||
text_box& hostname_box = find_widget<text_box>(window, "host_name", false);
|
||||
listbox& server_list = find_widget<listbox>(window, "server_list", false);
|
||||
button& button_add = find_widget<button>(window, "server_add", false);
|
||||
button& button_del = find_widget<button>(window, "server_delete", false);
|
||||
|
||||
const auto& address = boost::trim_copy(hostname_box.get_value());
|
||||
|
||||
std::size_t row = 0;
|
||||
|
||||
for(const auto* servers : server_lists()) {
|
||||
for(const auto& server : *servers) {
|
||||
if(server.address == address) {
|
||||
server_list.select_row(row);
|
||||
// Can't Add what's already there or Delete built-in servers
|
||||
button_add.set_active(false);
|
||||
button_del.set_active(servers == &user_servers_);
|
||||
return;
|
||||
}
|
||||
|
||||
++row;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Do not use this in production. It requires the listbox to be
|
||||
// defined with has_minimum=false in WML, and makes some UI interactions
|
||||
// awkward. In particular it means we would need to keep track of where
|
||||
// the selection was last at every time we clear the selection so that
|
||||
// the Add button can add under it instead of appending to the very end
|
||||
// of the list (currently it just bails out if there's no selection).
|
||||
#if 0
|
||||
// The user wrote a brand new hostname in so there's no matches, clear the
|
||||
// selection accordingly
|
||||
clear_listbox_selection(server_list);
|
||||
button_del.set_active(false);
|
||||
#endif
|
||||
button_add.set_active(!address.empty());
|
||||
}
|
||||
|
||||
void mp_connect::on_address_change()
|
||||
{
|
||||
// Select the first matching list entry or clear the current selection
|
||||
select_first_match();
|
||||
}
|
||||
|
||||
void mp_connect::on_server_add()
|
||||
{
|
||||
window* window = get_window();
|
||||
|
||||
text_box& hostname_box = find_widget<text_box>(window, "host_name", false);
|
||||
listbox& server_list = find_widget<listbox>(window, "server_list", false);
|
||||
|
||||
const auto& address = boost::trim_copy(hostname_box.get_value());
|
||||
const auto& selection = current_selection();
|
||||
|
||||
if(address.empty() || !selection.valid()) {
|
||||
// We're not supposed to be here
|
||||
return;
|
||||
}
|
||||
|
||||
// We insert under the selection. If a built-in server is selected or the
|
||||
// user-defined list is empty, we insert at the start of the user-defined
|
||||
// list instead.
|
||||
|
||||
const std::size_t mem_pos = selection.user_defined() && !user_servers_.empty()
|
||||
? 1 + selection.relative_index() : 0;
|
||||
const unsigned int ui_pos = 1 + selection.row();
|
||||
|
||||
std::string name;
|
||||
|
||||
if(!gui2::dialogs::edit_text::execute(_("Add Server"), _("Name:"), name, true) || name.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
server_info info;
|
||||
info.name = name;
|
||||
info.address = address;
|
||||
|
||||
user_servers_.insert(user_servers_.begin() + mem_pos, info);
|
||||
preferences::set_user_servers_list(user_servers_);
|
||||
|
||||
insert_into_server_listbox(server_list, info, ui_pos);
|
||||
select_first_match();
|
||||
}
|
||||
|
||||
void mp_connect::on_server_delete()
|
||||
{
|
||||
window* window = get_window();
|
||||
|
||||
listbox& server_list = find_widget<listbox>(window, "server_list", false);
|
||||
|
||||
auto selection = current_selection();
|
||||
|
||||
if(!selection.valid() || !selection.user_defined()) {
|
||||
// We're not supposed to be here
|
||||
return;
|
||||
}
|
||||
|
||||
user_servers_.erase(user_servers_.begin() + selection.relative_index());
|
||||
preferences::set_user_servers_list(user_servers_);
|
||||
|
||||
server_list.remove_row(selection.row());
|
||||
on_server_select();
|
||||
}
|
||||
|
||||
void mp_connect::on_server_select()
|
||||
{
|
||||
window* window = get_window();
|
||||
|
||||
text_box& hostname_box = find_widget<text_box>(window, "host_name", false);
|
||||
button& button_add = find_widget<button>(window, "server_add", false);
|
||||
button& button_del = find_widget<button>(window, "server_delete", false);
|
||||
|
||||
auto selection = current_selection();
|
||||
|
||||
if(!selection.valid()) {
|
||||
// The user cleared the selection. We can't delete what isn't selected
|
||||
// and the Add button's status was already set to a value that makes
|
||||
// sense by another signal handler, so just disable Delete.
|
||||
button_del.set_active(false);
|
||||
return;
|
||||
}
|
||||
|
||||
hostname_box.set_value(selection.get().address);
|
||||
|
||||
// Can't Add what's already there
|
||||
button_add.set_active(false);
|
||||
// Can only Delete user-defined servers
|
||||
button_del.set_active(selection.user_defined());
|
||||
}
|
||||
|
||||
mp_connect::selection mp_connect::current_selection()
|
||||
{
|
||||
listbox& server_list = find_widget<listbox>(get_window(), "server_list", false);
|
||||
return { this, server_list.get_selected_row() };
|
||||
}
|
||||
|
||||
mp_connect::server_info& mp_connect::selection::get()
|
||||
{
|
||||
must_be_valid();
|
||||
return parent_list().at(relative_index());
|
||||
}
|
||||
|
||||
unsigned mp_connect::selection::row() const
|
||||
{
|
||||
must_be_valid();
|
||||
return unsigned(row_);
|
||||
}
|
||||
|
||||
std::size_t mp_connect::selection::relative_index() const
|
||||
{
|
||||
must_be_valid();
|
||||
return user_defined() ? row() - owner_->builtin_servers_.size() : row();
|
||||
}
|
||||
|
||||
mp_connect::server_list& mp_connect::selection::parent_list() const
|
||||
{
|
||||
must_be_valid();
|
||||
return user_defined() ? owner_->user_servers_ : owner_->builtin_servers_;
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
|
|
|
@ -16,8 +16,16 @@
|
|||
|
||||
#include "gui/dialogs/modal_dialog.hpp"
|
||||
|
||||
namespace game_config
|
||||
{
|
||||
struct server_info;
|
||||
}
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
||||
class listbox;
|
||||
|
||||
namespace dialogs
|
||||
{
|
||||
|
||||
|
@ -39,15 +47,72 @@ private:
|
|||
/** Inherited from modal_dialog. */
|
||||
virtual void pre_show(window& window) override;
|
||||
|
||||
/** The host name of the selected servef. */
|
||||
// Signal handlers
|
||||
|
||||
void on_address_change();
|
||||
void on_server_add();
|
||||
void on_server_delete();
|
||||
void on_server_select();
|
||||
|
||||
// Auxiliary functions
|
||||
|
||||
using server_info = game_config::server_info;
|
||||
using server_list = std::vector<server_info>;
|
||||
|
||||
void insert_into_server_listbox(listbox& listbox, const server_info& srv, int pos = -1);
|
||||
|
||||
void select_first_match();
|
||||
|
||||
class selection
|
||||
{
|
||||
public:
|
||||
selection(mp_connect* owner, int row = -1)
|
||||
: owner_(owner)
|
||||
, row_(row)
|
||||
{
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return owner_ && row_ >= 0;
|
||||
}
|
||||
|
||||
bool user_defined() const
|
||||
{
|
||||
// An invalid selection is the same as one from the read-only list of
|
||||
// built-in servers for interaction purposes since it can't be written to.
|
||||
return valid() && std::size_t(row_) >= owner_->builtin_servers_.size();
|
||||
}
|
||||
|
||||
unsigned row() const;
|
||||
|
||||
std::size_t relative_index() const;
|
||||
|
||||
server_list& parent_list() const;
|
||||
|
||||
server_info& get();
|
||||
|
||||
private:
|
||||
mp_connect* owner_;
|
||||
int row_;
|
||||
|
||||
void must_be_valid() const
|
||||
{
|
||||
if(!valid()) {
|
||||
throw std::out_of_range{"Invalid MP server selection"};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
selection current_selection();
|
||||
|
||||
std::array<server_list*, 2> server_lists();
|
||||
|
||||
/** The host name of the selected server. */
|
||||
field_text* host_name_;
|
||||
|
||||
/**
|
||||
* The unit test needs to be able to test the mp_connect dialog.
|
||||
*
|
||||
* @returns A newly allocated mp_server_list.
|
||||
*/
|
||||
static modal_dialog* mp_server_list_for_unit_test();
|
||||
server_list builtin_servers_;
|
||||
server_list user_servers_;
|
||||
};
|
||||
|
||||
} // namespace dialogs
|
||||
|
|
|
@ -516,7 +516,7 @@ void title_screen::button_callback_multiplayer(window& window)
|
|||
|
||||
switch(res) {
|
||||
case 0:
|
||||
game_.select_mp_server(preferences::server_list().front().address);
|
||||
game_.select_mp_server(preferences::builtin_servers_list().front().address);
|
||||
window.set_retval(MP_CONNECT);
|
||||
break;
|
||||
case 1:
|
||||
|
|
|
@ -380,28 +380,43 @@ void _set_lobby_joins(int show)
|
|||
}
|
||||
}
|
||||
|
||||
const std::vector<game_config::server_info>& server_list()
|
||||
const std::vector<game_config::server_info>& builtin_servers_list()
|
||||
{
|
||||
static std::vector<game_config::server_info> pref_servers;
|
||||
if(pref_servers.empty()) {
|
||||
std::vector<game_config::server_info> &game_servers = game_config::server_list;
|
||||
VALIDATE(!game_servers.empty(), _("No server has been defined."));
|
||||
pref_servers.insert(pref_servers.begin(), game_servers.begin(), game_servers.end());
|
||||
for(const config &server : get_prefs()->child_range("server")) {
|
||||
game_config::server_info sinf;
|
||||
sinf.name = server["name"].str();
|
||||
sinf.address = server["address"].str();
|
||||
pref_servers.push_back(sinf);
|
||||
}
|
||||
}
|
||||
static std::vector<game_config::server_info> pref_servers = game_config::server_list;
|
||||
return pref_servers;
|
||||
}
|
||||
|
||||
std::vector<game_config::server_info> user_servers_list()
|
||||
{
|
||||
std::vector<game_config::server_info> pref_servers;
|
||||
|
||||
for(const config &server : get_prefs()->child_range("server")) {
|
||||
game_config::server_info sinf;
|
||||
sinf.name = server["name"].str();
|
||||
sinf.address = server["address"].str();
|
||||
pref_servers.push_back(sinf);
|
||||
}
|
||||
|
||||
return pref_servers;
|
||||
}
|
||||
|
||||
void set_user_servers_list(const std::vector<game_config::server_info>& value)
|
||||
{
|
||||
config& prefs = *get_prefs();
|
||||
prefs.clear_children("server");
|
||||
|
||||
for(const auto& svinfo : value) {
|
||||
config& sv_cfg = prefs.add_child("server");
|
||||
sv_cfg["name"] = svinfo.name;
|
||||
sv_cfg["address"] = svinfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
std::string network_host()
|
||||
{
|
||||
const std::string res = preferences::get("host");
|
||||
if(res.empty()) {
|
||||
return server_list().front().address;
|
||||
return builtin_servers_list().front().address;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,9 @@ class acquaintance;
|
|||
bool is_campaign_completed(const std::string& campaign_id);
|
||||
bool is_campaign_completed(const std::string& campaign_id, const std::string &difficulty_level);
|
||||
|
||||
const std::vector<game_config::server_info>& server_list();
|
||||
const std::vector<game_config::server_info>& builtin_servers_list();
|
||||
std::vector<game_config::server_info> user_servers_list();
|
||||
void set_user_servers_list(const std::vector<game_config::server_info>& value);
|
||||
|
||||
std::string network_host();
|
||||
void set_network_host(const std::string& host);
|
||||
|
|
|
@ -156,13 +156,6 @@ window* unit_test_window(const modeless_dialog& dialog)
|
|||
return dialog.window_.get();
|
||||
}
|
||||
|
||||
class mp_server_list;
|
||||
|
||||
modal_dialog* unit_test_mp_server_list()
|
||||
{
|
||||
return mp_connect::mp_server_list_for_unit_test();
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
} // namespace gui2
|
||||
|
||||
|
@ -471,7 +464,6 @@ BOOST_AUTO_TEST_CASE(test_gui2)
|
|||
test<mp_join_game_password_prompt>();
|
||||
test<mp_login>();
|
||||
test<mp_method_selection>();
|
||||
test<mp_server_list>();
|
||||
//test<mp_staging>();
|
||||
//test<outro>();
|
||||
test<simple_item_selector>();
|
||||
|
@ -1063,15 +1055,6 @@ struct dialog_tester<folder_create>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct dialog_tester<mp_server_list>
|
||||
{
|
||||
static modal_dialog* create()
|
||||
{
|
||||
return unit_test_mp_server_list();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct dialog_tester<transient_message>
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue