diff --git a/data/gui/default/widget/unit_preview_pane.cfg b/data/gui/default/widget/unit_preview_pane.cfg new file mode 100644 index 000000000000..dbfee4c2ac19 --- /dev/null +++ b/data/gui/default/widget/unit_preview_pane.cfg @@ -0,0 +1,279 @@ +#textdomain wesnoth-lib + +#define _GUI_UNIT_PREVIEW_PANE_FULL + [grid] + vertical_grow = "true" + horizontal_grow = "true" + + [row] + grow_factor = 0 + [column] + border = "bottom" + border_size = 5 + vertical_grow = "true" + horizontal_grow = "true" + + [label] + id = "type_name" + wrap = "true" + [/label] + + [/column] + + [/row] + + [row] + grow_factor = 0 + + [column] + border = "bottom" + border_size = 5 + horizontal_alignment = "center" + vertical_alignment = "center" + + [image] + id = "type_image" + definition = "default" + [/image] + + [/column] + + [/row] + + [row] + grow_factor = 0 + + [column] + border = "bottom" + border_size = 5 + horizontal_alignment = "center" + + [button] + id = "type_profile" + definition = "default" + + label = _ "Profile" + [/button] + + [/column] + + [/row] + + [row] + grow_factor = 0 + + [column] + horizontal_grow = "true" + + [grid] + + [row] + grow_factor = 1 + + [column] + border = "right,bottom" + border_size = 5 + horizontal_alignment = "left" + + [label] + id = "type_level" + [/label] + + [/column] + + [column] + border = "right,bottom" + border_size = 5 + horizontal_alignment = "left" + + [image] + id = "type_race" + [/image] + + [/column] + + [column] + border = "bottom" + border_size = 5 + horizontal_alignment = "left" + + [image] + id = "type_alignment" + [/image] + + [/column] + + [/row] + + [/grid] + + [/column] + + [/row] + + [row] + grow_factor = 1 + + [column] + vertical_grow = "true" + horizontal_alignment = "left" + + [label] + id = "type_details" + definition = "default_small" + wrap = "true" + [/label] + + [/column] + + [/row] + + [/grid] +#enddef + +#define _GUI_UNIT_PREVIEW_PANE_MINIMAL + [grid] + vertical_grow = "true" + horizontal_grow = "true" + + [row] + grow_factor = 0 + + [column] + border = "bottom" + border_size = 5 + horizontal_alignment = "center" + + [button] + id = "type_profile" + definition = "default" + + label = _ "Profile" + [/button] + + [/column] + + [/row] + + [row] + grow_factor = 0 + + [column] + horizontal_grow = "true" + + [grid] + + [row] + grow_factor = 1 + + [column] + border = "right,bottom" + border_size = 5 + horizontal_alignment = "left" + + [label] + id = "type_level" + [/label] + + [/column] + + [column] + border = "right,bottom" + border_size = 5 + horizontal_alignment = "left" + + [image] + id = "type_race" + [/image] + + [/column] + + [column] + border = "bottom" + border_size = 5 + horizontal_alignment = "left" + + [image] + id = "type_alignment" + [/image] + + [/column] + + [/row] + + [/grid] + + [/column] + + [/row] + + [row] + grow_factor = 1 + + [column] + vertical_grow = "true" + horizontal_alignment = "left" + + [label] + id = "type_details" + definition = "default_small" + wrap = "true" + [/label] + + [/column] + + [/row] + + [/grid] +#enddef + +#define _GUI_RESOLUTION DEFINITION_GRID + [resolution] + + min_width = 0 + min_height = 0 + + default_width = 0 + default_height = 0 + + max_width = 0 + max_height = 0 + + [background] + + [draw] + + [/draw] + + [/background] + + [foreground] + + [draw] + + [/draw] + + [/foreground] + + {DEFINITION_GRID} + + [/resolution] +#enddef + +[unit_preview_pane_definition] + id = "default" + description = "A fully detailed preview area for unit stats." + + {_GUI_RESOLUTION ({_GUI_UNIT_PREVIEW_PANE_FULL})} +[/unit_preview_pane_definition] + +[unit_preview_pane_definition] + id = "minimal" + description = "A unit preview pane without the image or title." + + {_GUI_RESOLUTION ({_GUI_UNIT_PREVIEW_PANE_MINIMAL})} +[/unit_preview_pane_definition] + +#undef _GUI_UNIT_PREVIEW_PANE_FULL +#undef _GUI_UNIT_PREVIEW_PANE_MINIMAL +#undef _GUI_RESOLUTION diff --git a/data/gui/default/window/unit_create.cfg b/data/gui/default/window/unit_create.cfg index 8437a3317ec9..16014c547af1 100644 --- a/data/gui/default/window/unit_create.cfg +++ b/data/gui/default/window/unit_create.cfg @@ -63,133 +63,14 @@ [row] [column] - vertical_alignment = "top" - - [grid] - - [row] - - [column] - border = "all" - border_size = 5 - vertical_grow = "true" - horizontal_grow = "true" - - [label] - id = "type_name" - wrap = "true" - [/label] - - [/column] - - [/row] - - [row] - grow_factor = 1 - - [column] - border = "all" - border_size = 5 - horizontal_alignment = "center" - vertical_alignment = "center" - - [image] - id = "type_image" - definition = "default" - [/image] - - [/column] - - [/row] - - [row] - - [column] - border = "all" - border_size = 5 - horizontal_alignment = "center" - - [button] - id = "type_profile" - definition = "default" - - label = _ "Profile" - [/button] - - [/column] - - [/row] - - [row] - - [column] - horizontal_grow = "true" - - [grid] - - [row] - grow_factor = 1 - - [column] - border = "all" - border_size = 5 - horizontal_alignment = "left" - - [label] - id = "type_level" - [/label] - - [/column] - - [column] - border = "all" - border_size = 5 - horizontal_alignment = "left" - - [image] - id = "type_race" - [/image] - - [/column] - - [column] - border = "all" - border_size = 5 - horizontal_alignment = "left" - - [image] - id = "type_alignment" - [/image] - - [/column] - - [/row] - - [/grid] - - [/column] - - [/row] - - [row] - - [column] - border = "all" - border_size = 5 - vertical_grow = "true" - horizontal_alignment = "left" - - [label] - id = "type_details" - definition = "default_small" - wrap = "true" - [/label] - - [/column] - - [/row] + vertical_grow = "true" + border = "all" + border_size = 5 - [/grid] + [unit_preview_pane] + definition = "default" + id = "unit_details" + [/unit_preview_pane] [/column] diff --git a/data/gui/default/window/unit_recruit.cfg b/data/gui/default/window/unit_recruit.cfg new file mode 100644 index 000000000000..cc4cbbcb3eec --- /dev/null +++ b/data/gui/default/window/unit_recruit.cfg @@ -0,0 +1,234 @@ +#textdomain wesnoth-lib +### +### Definition of the window to recruit units +### + +#define _GUI_RECRUIT_LIST + [listbox] + id = "recruit_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 = 5 + [image] + id = "unit_image" + definition = "default" + linked_group = "image" + [/image] + [/column] + + [column] + grow_factor = 0 + horizontal_grow = "true" + + [grid] + [row] + [column] + border = "all" + border_size = 5 + horizontal_alignment = "left" + [label] + id = "unit_type" + definition = "default" + linked_group = "type" + [/label] + [/column] + [/row] + + [row] + [column] + horizontal_alignment = "left" + [grid] + [row] + grow_factor = 1 + + [column] + border = "left,top,bottom" + border_size = 5 + horizontal_alignment = "left" + [image] + id = "gold_icon" + definition = "default" + + label = "themes/gold.png" + [/image] + [/column] + + [column] + border = "all" + border_size = 5 + horizontal_alignment = "left" + [label] + id = "unit_cost" + definition = "default" + [/label] + [/column] + [/row] + [/grid] + [/column] + [/row] + [/grid] + [/column] + [/row] + [/grid] + [/toggle_panel] + [/column] + [/row] + [/list_definition] + [/listbox] +#enddef + +[window] + id = "unit_recruit" + description = "Unut recruit dialog." + + [resolution] + definition = "default" + automatic_placement = "true" + vertical_placement = "center" + horizontal_placement = "center" + + maximum_height = 600 + + [linked_group] + id = "image" + fixed_width = "true" + [/linked_group] + + [linked_group] + id = "type" + fixed_width = "true" + [/linked_group] + + [tooltip] + id = "tooltip_large" + [/tooltip] + + [helptip] + id = "tooltip_large" + [/helptip] + + [grid] + [row] + grow_factor = 0 + + [column] + grow_factor = 1 + border = "all" + border_size = 5 + horizontal_alignment = "left" + + [label] + definition = "title" + label = _ "Recruit Unit" + [/label] + + [/column] + + [/row] + + [row] + grow_factor = 1 + + [column] + horizontal_grow = "true" + [grid] + + [row] + [column] + horizontal_grow = "true" + vertical_grow = "true" + border = "all" + border_size = 5 + + [unit_preview_pane] + definition = "minimal" + id = "recruit_details" + [/unit_preview_pane] + + [/column] + + [column] + horizontal_alignment = "right" + border = "all" + border_size = 5 + {_GUI_RECRUIT_LIST} + [/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 = "left" + [button] + id = "show_help" + definition = "default" + label = _ "Help" + [/button] + [/column] + + [column] + grow_factor = 0 + border = "all" + border_size = 5 + horizontal_alignment = "right" + [button] + id = "ok" + definition = "default" + label = _ "Recruit" + [/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_RECRUIT_LIST +#undef _GUI_DETAILS_SECTION diff --git a/projectfiles/CodeBlocks/wesnoth.cbp b/projectfiles/CodeBlocks/wesnoth.cbp index 56318d91b3de..34cd04869324 100644 --- a/projectfiles/CodeBlocks/wesnoth.cbp +++ b/projectfiles/CodeBlocks/wesnoth.cbp @@ -533,6 +533,8 @@ + + @@ -595,6 +597,8 @@ + + @@ -733,6 +737,8 @@ + + @@ -819,6 +825,8 @@ + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ebf505a9fe24..63c9351cbfb4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -604,6 +604,7 @@ set(wesnoth-gui_widget_SRC gui/widgets/toggle_panel.cpp gui/widgets/tree_view.cpp gui/widgets/tree_view_node.cpp + gui/widgets/unit_preview_pane.cpp gui/widgets/vertical_scrollbar.cpp gui/widgets/viewport.cpp gui/widgets/widget.cpp @@ -637,6 +638,7 @@ set(wesnoth-gui_widget_SRC gui/auxiliary/window_builder/toggle_button.cpp gui/auxiliary/window_builder/toggle_panel.cpp gui/auxiliary/window_builder/tree_view.cpp + gui/auxiliary/window_builder/unit_preview_pane.cpp gui/auxiliary/window_builder/vertical_scrollbar.cpp gui/auxiliary/window_builder/viewport.cpp ) @@ -685,6 +687,7 @@ set(wesnoth-gui_widget_definition_SRC gui/auxiliary/widget_definition/toggle_button.cpp gui/auxiliary/widget_definition/toggle_panel.cpp gui/auxiliary/widget_definition/tree_view.cpp + gui/auxiliary/widget_definition/unit_preview_pane.cpp gui/auxiliary/widget_definition/vertical_scrollbar.cpp gui/auxiliary/widget_definition/window.cpp ) @@ -947,6 +950,7 @@ set(wesnoth-main_SRC gui/dialogs/transient_message.cpp gui/dialogs/unit_attack.cpp gui/dialogs/unit_create.cpp + gui/dialogs/unit_recruit.cpp gui/dialogs/wml_error.cpp gui/dialogs/wml_message.cpp halo.cpp diff --git a/src/SConscript b/src/SConscript index fa52189200bb..aae4b438b2b9 100644 --- a/src/SConscript +++ b/src/SConscript @@ -367,6 +367,7 @@ wesnoth_sources = Split(""" gui/auxiliary/widget_definition/toggle_button.cpp gui/auxiliary/widget_definition/toggle_panel.cpp gui/auxiliary/widget_definition/tree_view.cpp + gui/auxiliary/widget_definition/unit_preview_pane.cpp gui/auxiliary/widget_definition/vertical_scrollbar.cpp gui/auxiliary/widget_definition/window.cpp gui/auxiliary/window_builder.cpp @@ -398,6 +399,7 @@ wesnoth_sources = Split(""" gui/auxiliary/window_builder/toggle_button.cpp gui/auxiliary/window_builder/toggle_panel.cpp gui/auxiliary/window_builder/tree_view.cpp + gui/auxiliary/window_builder/unit_preview_pane.cpp gui/auxiliary/window_builder/vertical_scrollbar.cpp gui/auxiliary/window_builder/viewport.cpp gui/dialogs/addon/description.cpp @@ -466,6 +468,7 @@ wesnoth_sources = Split(""" gui/dialogs/transient_message.cpp gui/dialogs/unit_attack.cpp gui/dialogs/unit_create.cpp + gui/dialogs/unit_recruit.cpp gui/dialogs/wml_error.cpp gui/dialogs/wml_message.cpp gui/lib/types/point.cpp @@ -504,6 +507,7 @@ wesnoth_sources = Split(""" gui/widgets/toggle_panel.cpp gui/widgets/tree_view.cpp gui/widgets/tree_view_node.cpp + gui/widgets/unit_preview_pane.cpp gui/widgets/vertical_scrollbar.cpp gui/widgets/viewport.cpp gui/widgets/widget.cpp diff --git a/src/gui/auxiliary/widget_definition/unit_preview_pane.cpp b/src/gui/auxiliary/widget_definition/unit_preview_pane.cpp new file mode 100644 index 000000000000..9c40225a1781 --- /dev/null +++ b/src/gui/auxiliary/widget_definition/unit_preview_pane.cpp @@ -0,0 +1,45 @@ +/* + 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/auxiliary/widget_definition/unit_preview_pane.hpp" + +#include "gettext.hpp" +#include "gui/auxiliary/log.hpp" +#include "wml_exception.hpp" + +namespace gui2 +{ + +tunit_preview_pane_definition::tunit_preview_pane_definition(const config& cfg) + : tcontrol_definition(cfg) +{ + DBG_GUI_P << "Parsing unit preview pane " << id << '\n'; + + load_resolutions(cfg); +} + +tunit_preview_pane_definition::tresolution::tresolution(const config& cfg) + : tresolution_definition_(cfg), grid() +{ + state.push_back(tstate_definition(cfg.child("background"))); + state.push_back(tstate_definition(cfg.child("foreground"))); + + const config& child = cfg.child("grid"); + VALIDATE(child, _("No grid defined.")); + + grid = new tbuilder_grid(child); +} + +} diff --git a/src/gui/auxiliary/widget_definition/unit_preview_pane.hpp b/src/gui/auxiliary/widget_definition/unit_preview_pane.hpp new file mode 100644 index 000000000000..62ddd80895f4 --- /dev/null +++ b/src/gui/auxiliary/widget_definition/unit_preview_pane.hpp @@ -0,0 +1,38 @@ +/* + 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. +*/ + +#ifndef GUI_AUXILIARY_WIDGET_DEFINITION_UNIT_PREVIEW_PANE_HPP_INCLUDED +#define GUI_AUXILIARY_WIDGET_DEFINITION_UNIT_PREVIEW_PANE_HPP_INCLUDED + +#include "gui/auxiliary/widget_definition.hpp" +#include "gui/auxiliary/window_builder.hpp" + +namespace gui2 +{ + +struct tunit_preview_pane_definition : public tcontrol_definition +{ + + explicit tunit_preview_pane_definition(const config& cfg); + + struct tresolution : public tresolution_definition_ + { + explicit tresolution(const config& cfg); + + tbuilder_grid_ptr grid; + }; +}; + +} // namespace gui2 + +#endif diff --git a/src/gui/auxiliary/window_builder.cpp b/src/gui/auxiliary/window_builder.cpp index ab75d177d784..28709953f4c7 100644 --- a/src/gui/auxiliary/window_builder.cpp +++ b/src/gui/auxiliary/window_builder.cpp @@ -39,6 +39,7 @@ #include "gui/auxiliary/window_builder/pane.hpp" #include "gui/auxiliary/window_builder/password_box.hpp" #include "gui/auxiliary/window_builder/viewport.hpp" +#include "gui/auxiliary/window_builder/unit_preview_pane.hpp" #endif #include "gui/auxiliary/window_builder/instance.hpp" #include "gui/widgets/settings.hpp" @@ -227,6 +228,7 @@ tbuilder_widget_ptr create_builder_widget(const config& cfg) TRY(combobox); TRY(drawing); TRY(password_box); + TRY(unit_preview_pane); #undef TRY #endif diff --git a/src/gui/auxiliary/window_builder/unit_preview_pane.cpp b/src/gui/auxiliary/window_builder/unit_preview_pane.cpp new file mode 100644 index 000000000000..e967f2ada1e3 --- /dev/null +++ b/src/gui/auxiliary/window_builder/unit_preview_pane.cpp @@ -0,0 +1,58 @@ +/* + 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/auxiliary/window_builder/unit_preview_pane.hpp" + +#include "config.hpp" +#include "gui/auxiliary/log.hpp" +#include "gui/auxiliary/widget_definition/unit_preview_pane.hpp" +#include "gui/auxiliary/window_builder/helper.hpp" +#include "gui/widgets/unit_preview_pane.hpp" + +namespace gui2 +{ + +namespace implementation +{ + +tbuilder_unit_preview_pane::tbuilder_unit_preview_pane(const config& cfg) + : tbuilder_control(cfg) +{ +} + +twidget* tbuilder_unit_preview_pane::build() const +{ + tunit_preview_pane* widget = new tunit_preview_pane(); + + init_control(widget); + + DBG_GUI_G << "Window builder: placed unit preview pane '" << id + << "' with definition '" << definition << "'.\n"; + + boost::intrusive_ptr conf + = boost::dynamic_pointer_cast< + const tunit_preview_pane_definition::tresolution>(widget->config()); + + assert(conf); + + widget->init_grid(conf->grid); + widget->finalize_setup(); + + return widget; +} + +} // namespace implementation + +} // namespace gui2 diff --git a/src/gui/auxiliary/window_builder/unit_preview_pane.hpp b/src/gui/auxiliary/window_builder/unit_preview_pane.hpp new file mode 100644 index 000000000000..b23c77a2fce7 --- /dev/null +++ b/src/gui/auxiliary/window_builder/unit_preview_pane.hpp @@ -0,0 +1,38 @@ +/* + 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. +*/ + +#ifndef GUI_AUXILIARY_WINDOW_BUILDER_UNIT_PREVIEW_PANE_HPP_INCLUDED +#define GUI_AUXILIARY_WINDOW_BUILDER_UNIT_PREVIEW_PANE_HPP_INCLUDED + +#include "gui/auxiliary/window_builder/control.hpp" + +namespace gui2 +{ + +namespace implementation +{ + +struct tbuilder_unit_preview_pane : public tbuilder_control +{ + explicit tbuilder_unit_preview_pane(const config& cfg); + + using tbuilder_control::build; + + twidget* build() const; +}; + +} // namespace implementation + +} // namespace gui2 + +#endif diff --git a/src/gui/dialogs/unit_create.cpp b/src/gui/dialogs/unit_create.cpp index aa9db1df8f67..0ca672f9f747 100644 --- a/src/gui/dialogs/unit_create.cpp +++ b/src/gui/dialogs/unit_create.cpp @@ -31,6 +31,7 @@ #include "gui/widgets/grid.hpp" #include "gui/widgets/text_box.hpp" #include "gui/widgets/toggle_button.hpp" +#include "gui/widgets/unit_preview_pane.hpp" #include "gui/widgets/window.hpp" #include "display.hpp" #include "marked-up_text.hpp" @@ -127,12 +128,6 @@ void tunit_create::pre_show(CVideo& /*video*/, twindow& window) dialog_callback); #endif - connect_signal_mouse_left_click( - find_widget(&window, "type_profile", false), - boost::bind(&tunit_create::profile_button_callback, - this, - boost::ref(window))); - list.clear(); FOREACH(const AUTO & i, unit_types.types()) @@ -221,145 +216,17 @@ void tunit_create::post_show(twindow& window) last_gender = gender_; } -void tunit_create::print_stats(std::stringstream& str, const int row) -{ - const unit_type* u = units_[row]; - - str << "" << _("HP: ") << "" - << "" << u->hitpoints() << " "; - - str << "" << _("XP: ") << "" - << "" << u->experience_needed() << " "; - - str << "" << _("MP: ") << "" - << u->movement() << "\n"; - - str << " \n"; - - // Print trait details - bool has_traits = false; - std::stringstream t_str; - - BOOST_FOREACH(const config& tr, u->possible_traits()) - { - if(tr["availability"] != "musthave") continue; - - const std::string gender_string = - u->genders().front() == unit_race::FEMALE ? "female_name" : "male_name"; - - t_string name = tr[gender_string]; - if(name.empty()) { - name = tr["name"]; - } - - if(!name.empty()) { - t_str << " " << name << "\n"; - } - - has_traits = true; - } - - if(has_traits) { - str << "" << "Traits" << "" << "\n"; - str << t_str.str(); - str << " \n"; - } - - // Print ability details - if(!u->abilities().empty()) { - str << "" << "Abilities" << "" << "\n"; - - BOOST_FOREACH(const std::string& ab, u->abilities()) - { - str << " " << ab << "\n"; - } - - str << " \n"; - } - - // Print attack details - if(!u->attacks().empty()) { - str << "" << "Attacks" << "" << "\n"; - - BOOST_FOREACH(const attack_type& a, u->attacks()) - { - str << "" << a.damage() - << font::weapon_numbers_sep << a.num_attacks() << " " << a.name() << "" << "\n"; - - str << "" << " " << a.range() - << font::weapon_details_sep << a.type() << "" << "\n"; - - const std::string special = a.weapon_specials(); - if (!special.empty()) { - str << "" << " " << special << "" << "\n"; - } - - const std::string accuracy_parry = a.accuracy_parry_description(); - if(!accuracy_parry.empty()) { - str << "" << " " << accuracy_parry << "" << "\n"; - } - - str << " \n"; - } - } -} - void tunit_create::list_item_clicked(twindow& window) { const int selected_row - = find_widget(&window, "unit_type_list", false).get_selected_row(); + = find_widget(&window, "unit_type_list", false).get_selected_row(); if(selected_row == -1) { return; } - const unit_type* u = units_[selected_row]; - - std::stringstream str; - print_stats(str, selected_row); - - std::string tc; - - if(resources::controller) { - tc = "~RC(" + u->flag_rgb() + ">" + - team::get_side_color_index(resources::controller->current_side()) - + ")"; - } - - find_widget(&window, "type_image", false) - .set_label((u->icon().empty() ? u->image() : u->icon()) + tc); - - tlabel& u_name = find_widget(&window, "type_name", false); - - u_name.set_label("" + u->type_name() + ""); - u_name.set_use_markup(true); - - std::stringstream l_str; - l_str << "" << "Lvl " << u->level() << ""; - - tlabel& l_label = find_widget(&window, "type_level", false); - - l_label.set_label(l_str.str()); - l_label.set_use_markup(true); - - timage& r_icon = find_widget(&window, "type_race", false); - - r_icon.set_label("icons/unit-groups/race_" + u->race_id() + "_30.png"); - r_icon.set_tooltip(u->race()->name(u->genders().front())); - - const std::string& alignment_name = u->alignment().to_string(); - - timage& a_icon = find_widget(&window, "type_alignment", false); - - a_icon.set_label("icons/alignments/alignment_" + alignment_name + "_30.png"); - a_icon.set_tooltip(unit_type::alignment_description( - u->alignment(), - u->genders().front())); - - tlabel& details = find_widget(&window, "type_details", false); - - details.set_label(str.str()); - details.set_use_markup(true); + find_widget(&window, "unit_details", false) + .set_displayed_type(units_[selected_row]); } bool tunit_create::filter_text_changed(ttext_* textbox, const std::string& text) @@ -409,16 +276,6 @@ bool tunit_create::filter_text_changed(ttext_* textbox, const std::string& text) return false; } -void tunit_create::profile_button_callback(twindow& window) -{ - const int selected_row - = find_widget(&window, "unit_type_list", false).get_selected_row(); - - help::show_unit_help(window.video(), - units_[selected_row]->id(), - units_[selected_row]->show_variations_in_help(), false); -} - void tunit_create::gender_toggle_callback(twindow&) { gender_ = gender_toggle.get_active_member_value(); diff --git a/src/gui/dialogs/unit_create.hpp b/src/gui/dialogs/unit_create.hpp index fbd6be96d68a..32626a0552eb 100644 --- a/src/gui/dialogs/unit_create.hpp +++ b/src/gui/dialogs/unit_create.hpp @@ -75,12 +75,9 @@ class tunit_create : public tdialog /** Inherited from tdialog. */ void post_show(twindow& window); - void print_stats(std::stringstream& str, const int row); - /** Callbacks */ void list_item_clicked(twindow& window); bool filter_text_changed(ttext_* textbox, const std::string& text); - void profile_button_callback(twindow& window); void gender_toggle_callback(twindow& window); tgroup gender_toggle; diff --git a/src/gui/dialogs/unit_recruit.cpp b/src/gui/dialogs/unit_recruit.cpp new file mode 100644 index 000000000000..1bbea3c8634c --- /dev/null +++ b/src/gui/dialogs/unit_recruit.cpp @@ -0,0 +1,141 @@ +/* + 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/auxiliary/find_widget.tpp" +#include "gui/dialogs/helper.hpp" +#include "gui/dialogs/unit_recruit.hpp" +#include "gui/widgets/button.hpp" +#include "gui/widgets/image.hpp" +#include "gui/widgets/label.hpp" +#ifdef GUI2_EXPERIMENTAL_LISTBOX +#include "gui/widgets/list.hpp" +#else +#include "gui/widgets/listbox.hpp" +#endif +#include "gui/widgets/unit_preview_pane.hpp" +#include "gui/widgets/settings.hpp" +#include "gui/widgets/window.hpp" +#include "gettext.hpp" +#include "help/help.hpp" +#include "marked-up_text.hpp" +#include "play_controller.hpp" +#include "resources.hpp" +#include "team.hpp" +#include "unit_types.hpp" +#include "whiteboard/manager.hpp" + +#include "utils/foreach.tpp" + +#include + +namespace gui2 +{ + +REGISTER_DIALOG(unit_recruit) + +tunit_recruit::tunit_recruit(std::vector& recruit_list, team& team) + : recruit_list_(recruit_list) + , team_(team) + , selected_index_(0) +{ +} + +static std::string can_afford_unit(const std::string& text, const bool can_afford) +{ + return can_afford ? text : "" + text + ""; +} + +void tunit_recruit::pre_show(CVideo& /*video*/, twindow& window) +{ + tlistbox& list = find_widget(&window, "recruit_list", false); + +#ifdef GUI2_EXPERIMENTAL_LISTBOX + connect_signal_notify_modified(*list, + boost::bind(&tunit_recruit::list_item_clicked, + *this, + boost::ref(window))); +#else + list.set_callback_value_change( + dialog_callback); +#endif + + connect_signal_mouse_left_click( + find_widget(&window, "show_help", false), + boost::bind(&tunit_recruit::show_help, this, boost::ref(window))); + + FOREACH(const AUTO& recruit, recruit_list_) + { + std::map row_data; + string_map column; + + std::string image_string = recruit->image() + "~RC(" + recruit->flag_rgb() + ">" + + team::get_side_color_index(team_.side()) + ")"; + + int wb_gold = 0; + if(resources::controller) { + if(const boost::shared_ptr& whiteb = resources::controller->get_whiteboard()) { + wb::future_map future; // So gold takes into account planned spending + wb_gold = whiteb->get_spent_gold_for(team_.side()); + } + } + + const bool can_afford = recruit->cost() < team_.gold() - wb_gold; + + const std::string cost_string = lexical_cast(recruit->cost()); + + column["label"] = image_string; + row_data.insert(std::make_pair("unit_image", column)); + + column["label"] = can_afford_unit(recruit->type_name(), can_afford); + column["use_markup"] = "true"; + row_data.insert(std::make_pair("unit_type", column)); + + column["label"] = can_afford_unit(cost_string, can_afford); + column["use_markup"] = "true"; + row_data.insert(std::make_pair("unit_cost", column)); + + list.add_row(row_data); + } + + list_item_clicked(window); +} + +void tunit_recruit::list_item_clicked(twindow& window) +{ + const int selected_row + = find_widget(&window, "recruit_list", false).get_selected_row(); + + if(selected_row == -1) { + return; + } + + find_widget(&window, "recruit_details", false) + .set_displayed_type(recruit_list_[selected_row]); +} + +void tunit_recruit::show_help(twindow& window) +{ + help::show_help(window.video(), "recruit_and_recall"); +} + +void tunit_recruit::post_show(twindow& window) +{ + if(get_retval() == twindow::OK) { + selected_index_ = find_widget(&window, "recruit_list", false) + .get_selected_row(); + } +} + +} // namespace gui2 diff --git a/src/gui/dialogs/unit_recruit.hpp b/src/gui/dialogs/unit_recruit.hpp new file mode 100644 index 000000000000..1dab0c545ae2 --- /dev/null +++ b/src/gui/dialogs/unit_recruit.hpp @@ -0,0 +1,54 @@ +/* + 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. +*/ + +#ifndef GUI_DIALOGS_UNIT_RECRUIT_HPP_INCLUDED +#define GUI_DIALOGS_UNIT_RECRUIT_HPP_INCLUDED + +#include "gui/dialogs/dialog.hpp" +#include "team.hpp" +#include "unit_types.hpp" + +namespace gui2 { + +class tunit_recruit : public tdialog +{ +public: + tunit_recruit(std::vector& recruit_list, team& team); + + int get_selected_index() const + { + return selected_index_; + } + +private: + /** Inherited from tdialog, implemented by REGISTER_DIALOG. */ + virtual const std::string& window_id() const; + + /** Inherited from tdialog. */ + void pre_show(CVideo& video, twindow& window); + void post_show(twindow& window); + + void list_item_clicked(twindow& window); + + void show_help(twindow& window); + + std::vector& recruit_list_; + + team& team_; + + int selected_index_; +}; + +} // namespace gui2 + +#endif /* ! GUI_DIALOGS_UNIT_RECRUIT_HPP_INCLUDED */ diff --git a/src/gui/widgets/unit_preview_pane.cpp b/src/gui/widgets/unit_preview_pane.cpp new file mode 100644 index 000000000000..0bbdd28eee27 --- /dev/null +++ b/src/gui/widgets/unit_preview_pane.cpp @@ -0,0 +1,232 @@ +/* + Copyright (C) 2016 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/widgets/unit_preview_pane.hpp" + +#include "gui/auxiliary/find_widget.tpp" +#include "gui/auxiliary/widget_definition/unit_preview_pane.hpp" +#include "gui/auxiliary/window_builder/unit_preview_pane.hpp" + +#include "gui/widgets/detail/register.tpp" +#include "gui/widgets/button.hpp" +#include "gui/widgets/image.hpp" +#include "gui/widgets/label.hpp" +#include "gui/widgets/settings.hpp" +#include "gui/widgets/window.hpp" + +#include "formula_string_utils.hpp" +#include "game_config.hpp" +#include "gettext.hpp" +#include "help/help.hpp" +#include "marked-up_text.hpp" +#include "play_controller.hpp" +#include "resources.hpp" +#include "team.hpp" + +#include "utils/foreach.tpp" + +#include + +namespace gui2 +{ + +REGISTER_WIDGET(unit_preview_pane) + +void tunit_preview_pane::finalize_setup() +{ + // Icons + icon_type_ = find_widget(this, "type_image" , false, false); + icon_race_ = find_widget(this, "type_race" , false, false); + icon_alignment_ = find_widget(this, "type_alignment", false, false); + + // Labels + label_name_ = find_widget(this, "type_name" , false, false); + label_level_ = find_widget(this, "type_level" , false, false); + label_details_ = find_widget(this, "type_details", false, false); + + // Profile button + button_profile_ = find_widget(this, "type_profile", false, false); + + if(button_profile_) { + connect_signal_mouse_left_click(*button_profile_, + boost::bind(&tunit_preview_pane::profile_button_callback, this)); + } +} + +void tunit_preview_pane::set_displayed_type(const unit_type* type) +{ + // Sets the current type id for the profile button callback to use + current_type_ = type->id(); + + if(icon_type_) { + std::string tc; + + if(resources::controller) { + tc = "~RC(" + type->flag_rgb() + ">" + + team::get_side_color_index(resources::controller->current_side()) + + ")"; + } + + icon_type_->set_label((type->icon().empty() ? type->image() : type->icon()) + tc); + } + + if(label_name_) { + label_name_->set_label("" + type->type_name() + ""); + label_name_->set_use_markup(true); + } + + if(label_level_) { + utils::string_map symbols; + symbols["lvl"] = lexical_cast(type->level()); + + std::string l_str = vgettext("Lvl $lvl", symbols); + + label_level_->set_label("" + l_str + ""); + label_level_->set_use_markup(true); + } + + if(icon_race_) { + icon_race_->set_label("icons/unit-groups/race_" + type->race_id() + "_30.png"); + icon_race_->set_tooltip(type->race()->name(type->genders().front())); + } + + if(icon_alignment_) { + const std::string& alignment_name = type->alignment().to_string(); + + icon_alignment_->set_label("icons/alignments/alignment_" + alignment_name + "_30.png"); + icon_alignment_->set_tooltip(unit_type::alignment_description( + type->alignment(), + type->genders().front())); + } + + if(label_details_) { + std::stringstream str; + str << "" << _("HP: ") << "" + << "" << type->hitpoints() << " "; + + str << "" << _("XP: ") << "" + << "" << type->experience_needed() << " "; + + str << "" << _("MP: ") << "" + << type->movement() << "\n"; + + str << " \n"; + + // Print trait details + bool has_traits = false; + std::stringstream t_str; + + FOREACH(const AUTO& tr, type->possible_traits()) + { + if(tr["availability"] != "musthave") continue; + + const std::string gender_string = + type->genders().front() == unit_race::FEMALE ? "female_name" : "male_name"; + + t_string name = tr[gender_string]; + if(name.empty()) { + name = tr["name"]; + } + + if(!name.empty()) { + t_str << " " << name << "\n"; + } + + has_traits = true; + } + + if(has_traits) { + str << "" << _("Traits") << "" << "\n"; + str << t_str.str(); + str << " \n"; + } + + // Print ability details + if(!type->abilities().empty()) { + str << "" << _("Abilities") << "" << "\n"; + + FOREACH(const AUTO& ab, type->abilities()) + { + str << " " << ab << "\n"; + } + + str << " \n"; + } + + // Print attack details + if(!type->attacks().empty()) { + str << "" << _("Attacks") << "" << "\n"; + + FOREACH(const AUTO& a, type->attacks()) + { + str << "" << a.damage() + << font::weapon_numbers_sep << a.num_attacks() << " " << a.name() << "" << "\n"; + + str << "" << " " << a.range() + << font::weapon_details_sep << a.type() << "" << "\n"; + + const std::string special = a.weapon_specials(); + if (!special.empty()) { + str << "" << " " << special << "" << "\n"; + } + + const std::string accuracy_parry = a.accuracy_parry_description(); + if(!accuracy_parry.empty()) { + str << "" << " " << accuracy_parry << "" << "\n"; + } + + str << " \n"; + } + } + + label_details_->set_label(str.str()); + label_details_->set_use_markup(true); + } +} + +void tunit_preview_pane::profile_button_callback() +{ + if(get_window()) { + help::show_unit_help((*get_window()).video(), current_type_); + } +} + +void tunit_preview_pane::set_active(const bool /*active*/) +{ + /* DO NOTHING */ +} + +bool tunit_preview_pane::get_active() const +{ + return true; +} + +unsigned tunit_preview_pane::get_state() const +{ + return ENABLED; +} + +const std::string& tunit_preview_pane::get_control_type() const +{ + static const std::string type = "unit_preview_pane"; + return type; +} + +void tunit_preview_pane::set_self_active(const bool /*active*/) +{ + /* DO NOTHING */ +} + +} // namespace gui2 diff --git a/src/gui/widgets/unit_preview_pane.hpp b/src/gui/widgets/unit_preview_pane.hpp new file mode 100644 index 000000000000..5e6a813935c5 --- /dev/null +++ b/src/gui/widgets/unit_preview_pane.hpp @@ -0,0 +1,102 @@ +/* + 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. +*/ + +#ifndef GUI_WIDGETS_UNIT_PREVIEW_PANE_HPP_INCLUDED +#define GUI_WIDGETS_UNIT_PREVIEW_PANE_HPP_INCLUDED + +#include "gui/auxiliary/widget_definition/unit_preview_pane.hpp" +#include "gui/widgets/container.hpp" +#include "unit_types.hpp" + +#include + +namespace gui2 +{ + +class tbutton; +class timage; +class tlabel; + +namespace implementation +{ + struct tbuilder_unit_preview_pane; +} + +class tunit_preview_pane : public tcontainer_ +{ + friend struct implementation::tbuilder_unit_preview_pane; + +public: + tunit_preview_pane() + : tcontainer_(1) + , current_type_("") + , icon_type_() + , icon_race_() + , icon_alignment_() + , label_name_() + , label_level_() + , label_details_() + , button_profile_() + { + } + + /** + * Initializes the interneral sub-widget pointers. + * Should be called when building the window, so the pointers + * are initilized when set_displayed_type() is called. + */ + void finalize_setup(); + + /** Displays the stats of a specified unit type */ + void set_displayed_type(const unit_type* type); + + /** Callback for the profile button */ + void profile_button_callback(); + + /** See @ref tcontrol::set_active. */ + virtual void set_active(const bool active) OVERRIDE; + + /** See @ref tcontrol::get_active. */ + virtual bool get_active() const OVERRIDE; + + /** See @ref tcontrol::get_state. */ + virtual unsigned get_state() const OVERRIDE; + +private: + std::string current_type_; + + timage* icon_type_; + timage* icon_race_; + timage* icon_alignment_; + + tlabel* label_name_; + tlabel* label_level_; + tlabel* label_details_; + + tbutton* button_profile_; + + enum tstate { + ENABLED + }; + + /** See @ref tcontrol::get_control_type. */ + virtual const std::string& get_control_type() const OVERRIDE; + + /** See @ref tcontainer_::set_self_active. */ + virtual void set_self_active(const bool active) OVERRIDE; + +}; + +} // namespace gui2 + +#endif diff --git a/src/menu_events.cpp b/src/menu_events.cpp index e43452b29d59..f9ac16601a5b 100644 --- a/src/menu_events.cpp +++ b/src/menu_events.cpp @@ -52,6 +52,7 @@ #include "gui/dialogs/simple_item_selector.hpp" #include "gui/dialogs/edit_text.hpp" #include "gui/dialogs/unit_create.hpp" +#include "gui/dialogs/unit_recruit.hpp" #include "gui/widgets/settings.hpp" #include "gui/widgets/window.hpp" #include "help/help.hpp" @@ -522,59 +523,33 @@ bool menu_handler::has_friends() const void menu_handler::recruit(int side_num, const map_location &last_hex) { - team ¤t_team = teams()[side_num - 1]; - std::vector sample_units; gui_->draw(); //clear the old menu - std::vector item_keys; - std::vector items; std::set recruits = actions::get_recruits(side_num, last_hex); for(std::set::const_iterator it = recruits.begin(); it != recruits.end(); ++it) { - const unit_type *type = unit_types.find(*it); + const unit_type* type = unit_types.find(*it); if (!type) { ERR_NG << "could not find unit '" << *it << "'" << std::endl; return; } - item_keys.push_back(*it); - - char prefix; - int wb_gold = 0; - - if (const boost::shared_ptr & whiteb = pc_.get_whiteboard()) - { wb::future_map future; // so gold takes into account planned spending - wb_gold = whiteb->get_spent_gold_for(side_num); - //display units that we can't afford to recruit in red - } // end planned unit map scope - - prefix = (type->cost() > current_team.gold() - wb_gold - ? font::BAD_TEXT : font::NULL_MARKUP); - - std::stringstream description; - description << font::IMAGE << type->image(); -#ifndef LOW_MEM - description << "~RC(" << type->flag_rgb() << '>' - << team::get_side_color_index(side_num) << ')'; -#endif - description << COLUMN_SEPARATOR << font::LARGE_TEXT << prefix << type->type_name() << "\n" - << prefix << type->cost() << " " << translation::sngettext("unit^Gold", "Gold", type->cost()); - - items.push_back(description.str()); sample_units.push_back(type); } if(sample_units.empty()) { - gui2::show_transient_message(gui_->video(),"",_("You have no units available to recruit.")); + gui2::show_transient_message(gui_->video(), "", _("You have no units available to recruit.")); return; } - int recruit_res = dialogs::recruit_dialog(*gui_, sample_units, items, side_num, get_title_suffix(side_num)); + gui2::tunit_recruit dlg(sample_units, teams()[side_num - 1]); + + dlg.show(gui_->video()); - if(recruit_res != -1) { - do_recruit(item_keys[recruit_res], side_num, last_hex); + if(dlg.get_retval() == gui2::twindow::OK) { + do_recruit(sample_units[dlg.get_selected_index()]->type_name(), side_num, last_hex); } }