Convert Select Faction (FLG) dialog to GUI2

This commit is contained in:
Charles Dang 2016-08-29 05:33:15 +11:00
parent 4180a36d33
commit 2bffd4af56
10 changed files with 698 additions and 174 deletions

View file

@ -0,0 +1,407 @@
#textdomain wesnoth-lib
###
### Definition of the window to select faction, leader, and gender
###
#define _GUI_FACTION_LIST
[listbox]
id = "faction_list"
definition = "default"
[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 = 1
[image]
id = "faction_image"
definition = "default"
linked_group = "image"
[/image]
[/column]
[column]
border = "all"
border_size = 5
horizontal_grow = "true"
[label]
id = "faction_name"
definition = "default"
linked_group = "name"
[/label]
[/column]
[column]
[spacer]
width = 25
[/spacer]
[/column]
[/row]
[/grid]
[/toggle_panel]
[/column]
[/row]
[/list_definition]
[/listbox]
#enddef
#define _GUI_GENDER_TOGGLE _ID _LABEL
[column]
border = "all"
border_size = 5
horizontal_grow = "true"
[toggle_button]
id = {_ID}
definition = "radio"
label = {_LABEL}
[/toggle_button]
[/column]
#enddef
#define _GUI_DETAILS_AREA
[grid]
[row]
grow_factor = 0
[column]
horizontal_alignment = "center"
border = "all"
border_size = 5
{GUI_FORCE_WIDGET_MINIMUM_SIZE 144 144 (
[image]
definition = "default"
id = "leader_image"
[/image]
)}
[/column]
[/row]
[row]
grow_factor = 0
[column]
horizontal_grow = "true"
[grid]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
label = _ "Leader:"
linked_group = "details_label"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_grow = "true"
[menu_button]
id = "leader_menu"
definition = "default"
[/menu_button]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
grow_factor = 0
[column]
horizontal_grow = "true"
[grid]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
label = _ "Gender:"
linked_group = "details_label"
[/label]
[/column]
{_GUI_GENDER_TOGGLE "gender_random" ( _ "Random")}
{_GUI_GENDER_TOGGLE "gender_male" ( _ "Male")}
{_GUI_GENDER_TOGGLE "gender_female" ( _ "Female")}
[/row]
[/grid]
[/column]
[/row]
[row]
grow_factor = 1
[column]
horizontal_grow = "true"
vertical_grow = "true"
[grid]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
vertical_alignment = "top"
[label]
definition = "default"
label = _ "Recruits:"
linked_group = "details_label"
[/label]
[/column]
[column]
grow_factor = 1
border = "all"
border_size = 5
vertical_grow = "true"
horizontal_grow = "true"
[scroll_label]
id = "recruits"
definition = "default"
wrap = "true"
[/scroll_label]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
#enddef
[window]
id = "faction_select"
description = "Faction and leader selection dialog."
[resolution]
definition = "default"
automatic_placement = "true"
vertical_placement = "center"
horizontal_placement = "center"
maximum_height = 700
[linked_group]
id = "image"
fixed_width = "true"
[/linked_group]
[linked_group]
id = "name"
fixed_width = "true"
[/linked_group]
[linked_group]
id = "details_label"
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 = _ "Choose Your Faction"
[/label]
[/column]
[/row]
[row]
grow_factor = 0
[column]
horizontal_grow = "true"
[grid]
[row]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
definition = "default"
label = _ "Starting position:"
[/label]
[/column]
[column]
grow_factor = 1
border = "top,bottom,right"
border_size = 5
horizontal_grow = "true"
[label]
id = "starting_pos"
definition = "default"
[/label]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
grow_factor = 1
[column]
horizontal_grow = "true"
[grid]
[row]
[column]
grow_factor = 0
horizontal_alignment = "left"
vertical_grow = "true"
border = "all"
border_size = 5
{_GUI_FACTION_LIST}
[/column]
[column]
grow_factor = 1
horizontal_grow = "true"
vertical_grow = "true"
{_GUI_DETAILS_AREA}
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
grow_factor = 0
[column]
grow_factor = 0
horizontal_grow = "true"
[grid]
[row]
grow_factor=0
[column]
grow_factor = 1
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "ok"
definition = "default"
label = _ "OK"
[/button]
[/column]
[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "cancel"
definition = "default"
label = _ "Cancel"
[/button]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
[/resolution]
[/window]
#undef _GUI_FACTION_LIST
#undef _GUI_GENDER_TOGGLE
#undef _GUI_DETAILS_AREA

View file

@ -585,6 +585,8 @@
<Unit filename="../../src/gui/dialogs/lua_interpreter.hpp" />
<Unit filename="../../src/gui/dialogs/message.cpp" />
<Unit filename="../../src/gui/dialogs/message.hpp" />
<Unit filename="../../src/gui/dialogs/multiplayer/faction_select.cpp" />
<Unit filename="../../src/gui/dialogs/multiplayer/faction_select.hpp" />
<Unit filename="../../src/gui/dialogs/multiplayer/mp_alerts_options.cpp" />
<Unit filename="../../src/gui/dialogs/multiplayer/mp_alerts_options.hpp" />
<Unit filename="../../src/gui/dialogs/multiplayer/mp_change_control.cpp" />

View file

@ -822,6 +822,7 @@ set(wesnoth-main_SRC
gui/dialogs/logging.cpp
gui/dialogs/lua_interpreter.cpp
gui/dialogs/message.cpp
gui/dialogs/multiplayer/faction_select.cpp
gui/dialogs/multiplayer/mp_alerts_options.cpp
gui/dialogs/multiplayer/mp_change_control.cpp
gui/dialogs/multiplayer/mp_cmd_wrapper.cpp

View file

@ -399,6 +399,7 @@ wesnoth_sources = Split("""
gui/dialogs/logging.cpp
gui/dialogs/lua_interpreter.cpp
gui/dialogs/message.cpp
gui/dialogs/multiplayer/faction_select.cpp
gui/dialogs/multiplayer/mp_alerts_options.cpp
gui/dialogs/multiplayer/mp_change_control.cpp
gui/dialogs/multiplayer/mp_cmd_wrapper.cpp

View file

@ -56,6 +56,11 @@ public:
bool is_random_faction();
void resolve_random(rand_rng::mt_rng & rng, const std::vector<std::string> & avoid); //Second Argument is a list of faction ids we don't want to match, used to implement random faction modes. If it is not possible to resolve then we just proceed anyways rather than give an error.
bool is_saved_game() const
{
return saved_game_;
}
// Picks the first faction with the greater amount of data
// matching the criteria.
int find_suitable_faction() const;
@ -78,6 +83,11 @@ public:
int current_faction_index() const;
int current_leader_index() const
{ return leader_index(current_leader_); }
int current_gender_index() const
{ return gender_index(current_gender_); }
private:
flg_manager(const flg_manager&);
void operator=(const flg_manager&);
@ -99,11 +109,6 @@ private:
/// returns -1 if no gender with that name was found
int gender_index(const std::string& gender) const;
int current_leader_index() const
{ return leader_index(current_leader_); }
int current_gender_index() const
{ return gender_index(current_gender_); }
const std::vector<const config*>& era_factions_;
const config& side_;

View file

@ -18,8 +18,10 @@
#include "gettext.hpp"
#include "game_config_manager.hpp"
#include "game_preferences.hpp"
#include "gui/dialogs/multiplayer/faction_select.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "gui/dialogs/network_transmission.hpp"
#include "gui/widgets/window.hpp"
#include "image.hpp"
#include "log.hpp"
#include "marked-up_text.hpp"
@ -60,140 +62,6 @@ const int leader_pane_border = 10;
namespace mp {
wait::leader_preview_pane::leader_preview_pane(CVideo& v,
ng::flg_manager& flg, const std::string& color) :
gui::preview_pane(v),
flg_(flg),
color_(color),
combo_leader_(v, std::vector<std::string>()),
combo_gender_(v, std::vector<std::string>())
{
flg_.reset_leader_combo(combo_leader_, color_);
flg_.reset_gender_combo(combo_gender_, color_);
set_location(leader_pane_position);
}
void wait::leader_preview_pane::process_event()
{
if (combo_leader_.changed() && combo_leader_.selected() >= 0) {
flg_.set_current_leader(combo_leader_.selected());
flg_.reset_gender_combo(combo_gender_, color_);
set_dirty();
}
if (combo_gender_.changed() && combo_gender_.selected() >= 0) {
flg_.set_current_gender(combo_gender_.selected());
set_dirty();
}
}
void wait::leader_preview_pane::draw_contents()
{
bg_restore();
surface& screen = video().getSurface();
SDL_Rect const &loc = location();
const SDL_Rect area = sdl::create_rect(loc.x + leader_pane_border,
loc.y + leader_pane_border,loc.w - leader_pane_border * 2,
loc.h - leader_pane_border * 2);
const clip_rect_setter clipper(screen, &area);
std::string faction = flg_.current_faction()["faction"];
const std::string recruits = flg_.current_faction()["recruit"];
const std::vector<std::string> recruit_list = utils::split(recruits);
std::ostringstream recruit_string;
if (!faction.empty() && faction[0] == font::IMAGE) {
std::string::size_type p = faction.find_first_of(COLUMN_SEPARATOR);
if (p != std::string::npos && p < faction.size())
faction = faction.substr(p+1);
}
std::string image;
const unit_type *ut = unit_types.find(flg_.current_leader());
if (ut) {
const unit_type &utg = ut->get_gender_unit_type(flg_.current_gender());
image = utg.image() + ng::get_RC_suffix(utg.flag_rgb(), color_);
}
for(std::vector<std::string>::const_iterator itor = recruit_list.begin();
itor != recruit_list.end(); ++itor) {
const unit_type *rt = unit_types.find(*itor);
if (!rt) continue;
if (itor != recruit_list.begin())
recruit_string << ", ";
recruit_string << rt->type_name();
}
SDL_Rect image_rect = {area.x,area.y,0,0};
surface unit_image(image::get_image(image));
if (!unit_image.null()) {
image_rect.w = unit_image->w;
image_rect.h = unit_image->h;
sdl_blit(unit_image, nullptr, screen, &image_rect);
}
font::draw_text(&video(), area, font::SIZE_PLUS, font::NORMAL_COLOR,
faction, area.x + 110, area.y + 60);
const SDL_Rect leader_rect = font::draw_text(&video(), area,
font::SIZE_SMALL, font::NORMAL_COLOR, _("Leader: "), area.x,
area.y + 110);
const SDL_Rect gender_rect = font::draw_text(&video(), area,
font::SIZE_SMALL, font::NORMAL_COLOR, _("Gender: "), area.x,
leader_rect.y + 30 + (leader_rect.h - combo_leader_.height()) / 2);
font::draw_wrapped_text(&video(), area, font::SIZE_SMALL,
font::NORMAL_COLOR, _("Recruits: ") + recruit_string.str(), area.x,
area.y + 132 + 30 + (leader_rect.h - combo_leader_.height()) / 2,
area.w);
combo_leader_.set_location(leader_rect.x + leader_rect.w + 16,
leader_rect.y + (leader_rect.h - combo_leader_.height()) / 2);
combo_gender_.set_location(leader_rect.x + leader_rect.w + 16,
gender_rect.y + (gender_rect.h - combo_gender_.height()) / 2);
}
bool wait::leader_preview_pane::show_above() const
{
return false;
}
bool wait::leader_preview_pane::left_side() const
{
return false;
}
void wait::leader_preview_pane::set_selection(int selection)
{
if (selection >= 0) {
flg_.set_current_faction(selection);
flg_.reset_leader_combo(combo_leader_, color_);
flg_.reset_gender_combo(combo_gender_, color_);
set_dirty();
}
}
sdl_handler_vector wait::leader_preview_pane::handler_members() {
sdl_handler_vector h;
h.push_back(&combo_leader_);
h.push_back(&combo_gender_);
return h;
}
wait::wait(CVideo& v, twesnothd_connection* wesnothd_connection, const config& cfg, saved_game& state,
mp::chat& c, config& gamelist, const bool first_scenario) :
ui(v, wesnothd_connection, _("Game Lobby"), cfg, c, gamelist),
@ -361,16 +229,10 @@ void wait::join_game(bool observe)
}
}
gui2::tfaction_select dlg(flg, color, side_num + 1);
dlg.show(video());
std::vector<gui::preview_pane* > preview_panes;
leader_preview_pane leader_selector(video(), flg, color);
preview_panes.push_back(&leader_selector);
const int faction_choice = gui::show_dialog(video(), nullptr,
_("Choose your faction:"), _("Starting position: ") +
std::to_string(side_num + 1), gui::OK_CANCEL,
&choices, &preview_panes);
if(faction_choice < 0) {
if(dlg.get_retval() != gui2::twindow::OK) {
set_result(QUIT);
return;
}
@ -652,7 +514,7 @@ bool wait::download_level_data()
}
has_scenario_and_controllers = true;
}
}
DBG_MP << "download_level_data() success.\n";

View file

@ -40,30 +40,6 @@ protected:
virtual void process_network_data(const config& data);
private:
class leader_preview_pane : public gui::preview_pane
{
public:
leader_preview_pane(CVideo& v, ng::flg_manager& flg,
const std::string& color);
bool show_above() const;
bool left_side() const;
void set_selection(int index);
sdl_handler_vector handler_members();
private:
virtual void process_event();
virtual void draw_contents();
ng::flg_manager& flg_;
const std::string color_;
gui::combo combo_leader_;
gui::combo combo_gender_;
};
void generate_menu();
bool download_level_data();
config& get_scenario();

View file

@ -0,0 +1,208 @@
/*
Copyright (C) 2016 by the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "gui/dialogs/multiplayer/faction_select.hpp"
#include "gui/auxiliary/find_widget.hpp"
#include "gui/core/log.hpp"
#include "gui/dialogs/helper.hpp"
#ifdef GUI2_EXPERIMENTAL_LISTBOX
#include "gui/widgets/list.hpp"
#else
#include "gui/widgets/listbox.hpp"
#endif
#include "gui/widgets/settings.hpp"
#include "gui/widgets/image.hpp"
#include "gui/widgets/label.hpp"
#include "gui/widgets/menu_button.hpp"
#include "gui/widgets/toggle_button.hpp"
#include "gui/widgets/window.hpp"
#include "config_assign.hpp"
#include "formatter.hpp"
#include "gettext.hpp"
#include "units/types.hpp"
#include "utils/functional.hpp"
namespace gui2
{
REGISTER_DIALOG(faction_select)
tfaction_select::tfaction_select(ng::flg_manager& flg_manager, const std::string& color, const int side)
: flg_manager_(flg_manager)
, tc_color_(color)
, side_(side)
{
}
void tfaction_select::pre_show(twindow& window)
{
window.set_escape_disabled(true);
find_widget<tlabel>(&window, "starting_pos", false).set_label(std::to_string(side_));
//
// Set up gender radio buttons
//
ttoggle_button& gender_rand = find_widget<ttoggle_button>(&window, "gender_random", false);
ttoggle_button& gender_male = find_widget<ttoggle_button>(&window, "gender_male", false);
ttoggle_button& gender_female = find_widget<ttoggle_button>(&window, "gender_female", false);
gender_toggle_.add_member(&gender_rand, "random");
gender_toggle_.add_member(&gender_male, unit_race::s_male);
gender_toggle_.add_member(&gender_female, unit_race::s_female);
gender_toggle_.set_member_states("random");
// TODO: consolidate when adding a all-member callback setter to tgroup
gender_rand.set_callback_state_change(
dialog_callback<tfaction_select, &tfaction_select::on_gender_select>);
gender_male.set_callback_state_change(
dialog_callback<tfaction_select, &tfaction_select::on_gender_select>);
gender_female.set_callback_state_change(
dialog_callback<tfaction_select, &tfaction_select::on_gender_select>);
//
// Set up leader menu button
//
find_widget<tmenu_button>(&window, "leader_menu", false).connect_click_handler(
std::bind(&tfaction_select::on_leader_select, this, std::ref(window)));
//
// Set up faction list
//
tlistbox& list = find_widget<tlistbox>(&window, "faction_list", false);
window.keyboard_capture(&list);
#ifdef GUI2_EXPERIMENTAL_LISTBOX
connect_signal_notify_modified(*list,
std::bind(&tfaction_select::on_faction_select,
*this, std::ref(window)));
#else
list.set_callback_value_change(
dialog_callback<tfaction_select, &tfaction_select::on_faction_select>);
#endif
for(const config *s : flg_manager_.choosable_factions()) {
const config& side = *s;
std::map<std::string, string_map> data;
string_map item;
// TODO: don't hardcode magenta?
item["label"] = (formatter() << side["image"] << "~RC(magenta>" << tc_color_ << ")").str();
data.emplace("faction_image", item);
item["label"] = side["name"];
data.emplace("faction_name", item);
list.add_row(data);
}
on_faction_select(window);
}
void tfaction_select::on_faction_select(twindow& window)
{
const int selected_row = find_widget<tlistbox>(&window, "faction_list", false).get_selected_row();
if(selected_row == -1) {
return;
}
flg_manager_.set_current_faction(selected_row);
std::vector<config> leaders;
for(const std::string& leader : flg_manager_.choosable_leaders()) {
const unit_type* unit = unit_types.find(leader);
if(unit) {
const std::string icon = formatter() << unit->image() << "~RC(" << unit->flag_rgb() << ">" << tc_color_ << ")";
leaders.push_back(config_of("label", unit->type_name())("icon", icon));
} else if(leader == "random") {
leaders.push_back(config_of("label", _("Random"))("icon", "units/random-dice.png"));
} else if(leader == "null") {
leaders.push_back(config_of("label", utils::unicode_em_dash));
} else {
leaders.push_back(config_of("label", "?"));
}
}
// TODO: this breaks ordering within the FLG manager
//std::sort(leaders.begin(), leaders.end(), [](const config& cfg1, const config& cfg2) {
// return cfg1["label"].str() < cfg2["label"].str();
//});
tmenu_button& leader_dropdown = find_widget<tmenu_button>(&window, "leader_menu", false);
leader_dropdown.set_values(leaders, flg_manager_.current_leader_index());
leader_dropdown.set_active(leaders.size() > 1 && !flg_manager_.is_saved_game());
on_leader_select(window);
// Print recruits
const std::vector<std::string> recruit_list = utils::split(flg_manager_.current_faction()["recruit"]);
std::vector<t_string> recruit_names;
for(const auto& recruit : recruit_list) {
if(const unit_type* rt = unit_types.find(recruit)) {
recruit_names.push_back("" + rt->type_name());
}
}
find_widget<tcontrol>(&window, "recruits", false).set_label(utils::join(recruit_names, "\n"));
}
void tfaction_select::on_leader_select(twindow& window)
{
flg_manager_.set_current_leader(find_widget<tmenu_button>(&window, "leader_menu", false).get_value());
auto gender_available = [this](const std::string gender)->bool {
const std::vector<std::string>& genders = flg_manager_.choosable_genders();
return std::find(genders.begin(), genders.end(), gender) != genders.end();
};
// TODO: should we decouple this from the dlg manager and instead just check the unit type directly?
find_widget<ttoggle_button>(&window, "gender_male", false).set_active(gender_available(unit_race::s_male));
find_widget<ttoggle_button>(&window, "gender_female", false).set_active(gender_available(unit_race::s_female));
update_leader_image(window);
}
void tfaction_select::on_gender_select(twindow& window)
{
flg_manager_.set_current_gender(gender_toggle_.get_active_member_value());
update_leader_image(window);
}
void tfaction_select::update_leader_image(twindow& window)
{
std::string leader_image = "units/random-dice.png";
if(const unit_type* ut = unit_types.find(flg_manager_.current_leader())) {
const unit_type& utg = ut->get_gender_unit_type(flg_manager_.current_gender());
leader_image = formatter() << utg.image() << "~RC(" << utg.flag_rgb() << ">" << tc_color_ << ")" << "~SCALE_INTO_SHARP(144,144)";
}
find_widget<timage>(&window, "leader_image", false).set_label(leader_image);
}
}

View file

@ -0,0 +1,59 @@
/*
Copyright (C) 2009 - 2016 by the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef GUI_DIALOGS_FACTION_SELECT_HPP_INCLUDED
#define GUI_DIALOGS_FACTION_SELECT_HPP_INCLUDED
#include "game_initialization/flg_manager.hpp"
#include "gui/dialogs/dialog.hpp"
#include "gui/widgets/group.hpp"
#include <string>
#include <vector>
namespace gui2
{
class tfaction_select : public tdialog
{
public:
tfaction_select(ng::flg_manager& flg_manager, const std::string& color, const int side);
private:
ng::flg_manager& flg_manager_;
const std::string tc_color_;
const int side_;
tgroup<std::string> gender_toggle_;
/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
virtual const std::string& window_id() const;
/** Inherited from tdialog. */
void pre_show(twindow& window);
/** Callbacks */
void on_faction_select(twindow& window);
void on_leader_select(twindow& window);
void on_gender_select(twindow& window);
void update_leader_image(twindow& window);
};
}
#endif /* ! GUI_DIALOGS_FACTION_SELECT_HPP_INCLUDED */

View file

@ -65,6 +65,7 @@
#include "gui/dialogs/logging.hpp"
#include "gui/dialogs/lua_interpreter.hpp"
#include "gui/dialogs/message.hpp"
#include "gui/dialogs/multiplayer/faction_select.cpp"
#include "gui/dialogs/multiplayer/mp_alerts_options.hpp"
#include "gui/dialogs/multiplayer/mp_change_control.hpp"
#include "gui/dialogs/multiplayer/mp_cmd_wrapper.hpp"
@ -388,6 +389,7 @@ BOOST_AUTO_TEST_CASE(test_gui2)
test<gui2::teditor_new_map>();
test<gui2::teditor_resize_map>();
test<gui2::teditor_set_starting_position>();
//test<gui2::tfaction_select>();
test<gui2::tfolder_create>();
test<gui2::tformula_debugger>();
test<gui2::tgame_cache_options>();
@ -483,7 +485,8 @@ BOOST_AUTO_TEST_CASE(test_gui2)
"game_stats",
"unit_advance",
"mp_host_game_prompt",
"mp_create_game"
"mp_create_game",
"faction_select"
};
std::sort(list.begin(), list.end());
std::sort(omitted.begin(), omitted.end());