Split from wml_message.

This commit is contained in:
Fabian Müller 2011-03-04 00:52:26 +00:00
parent 74ff2a2a51
commit 30ce0c8f5f
2 changed files with 651 additions and 0 deletions

View file

@ -0,0 +1,408 @@
/* $Id$ */
/*
Copyright (C) 2008 - 2011 by Mark de Wever <koraq@xs4all.nl>
Part of 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/wml_message.hpp"
#include "foreach.hpp"
#include "gui/dialogs/helper.hpp"
#include "gui/auxiliary/old_markup.hpp"
#include "gui/widgets/button.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/settings.hpp"
#include "gui/widgets/text_box.hpp"
#include "gui/widgets/window.hpp"
//TODO let's see if we need all of those
#include "resources.hpp"
#include "game_display.hpp"
#include "map.hpp"
#include "help.hpp"
#include "gettext.hpp" //could be done in menu_events
#include <boost/bind.hpp>
namespace gui2 {
//should be active in every dialog that involves units.
void twml_message_::profile_pressed() {
assert(chosen_unit_);
const unit_type& t = *chosen_unit_->type();
help::show_unit_help(*resources::screen, t.id(), t.hide_help());
}
//TODO this is very specific, might need to go into another class
void twml_message_::help_pressed() {
help::show_help(*resources::screen,"recruit_and_recall");
}
void twml_message_::update_unit_list(twindow& window) {
tlistbox& unit_listbox = find_widget<tlistbox> (&window, "recruit_list", false);
//TODO this hack does not respect the sorting of the list.
chosen_unit_ = &unit_list_[unit_listbox.get_selected_row()];
const map_location& loc = chosen_unit_->get_location();
if (resources::game_map->on_board(loc)) {
resources::screen->highlight_hex(loc);
//TODO is false better?
resources::screen->scroll_to_tile(loc,
game_display::SCROLL, true);
} else {
chosen_unit_->draw_report();
}
window.canvas(1).set_variable("portrait_image", variant(
chosen_unit_->big_profile()));
window.set_dirty();
}
void twml_message_::set_input(const std::string& caption,
std::string* text, const unsigned maximum_length)
{
assert(text);
has_input_ = true;
input_caption_ = caption;
input_text_ = text;
input_maximum_lenght_ = maximum_length;
}
void twml_message_::set_option_list(
const std::vector<std::string>& option_list, int* chosen_option)
{
assert(!option_list.empty());
assert(chosen_option);
option_list_ = option_list;
chosen_option_ = chosen_option;
}
void twml_message_::set_unit_list(
const std::vector<unit>& unit_list, std::string* unit_id)
{
assert(unit_id);
assert(!unit_list.empty());
unit_id_ = unit_id;
unit_list_ = unit_list;
chosen_unit_ = &unit_list_[0];
}
void twml_message_::set_type_list(
std::vector<const unit_type*> type_list, std::string* type_id, int side_num, int gold)
{
assert(!type_list.empty());
assert(type_id);
gold_ = gold;
unit_id_ = type_id;
std::vector<const unit_type*>::const_iterator it;
it = type_list.begin();
for (it = type_list.begin(); it != type_list.end(); it++)
{
unit new_unit(*it, side_num, false);
unit_list_.push_back(new_unit);
}
chosen_unit_ = &unit_list_[0];
}
/**
* @todo This function enables the wml markup for all items, but the interface
* is a bit hacky. Especially the fiddling in the internals of the listbox is
* ugly. There needs to be a clean interface to set whether a widget has a
* markup and what kind of markup. These fixes will be post 1.6.
*/
void twml_message_::pre_show(CVideo& /*video*/, twindow& window)
{
window.canvas(1).set_variable("portrait_image", variant(portrait_));
window.canvas(1).set_variable("portrait_mirror", variant(mirror_));
// Set the markup
tlabel& title = find_widget<tlabel>(&window, "title", false);
title.set_label(title_);
title.set_use_markup(true);
title.set_can_wrap(true);
tcontrol& message = find_widget<tcontrol>(&window, "message", false);
message.set_label(message_);
message.set_use_markup(true);
// The message label might not always be a scroll_label but the capturing
// shouldn't hurt.
window.keyboard_capture(&message);
// Find the input box related fields.
tlabel& caption = find_widget<tlabel>(&window, "input_caption", false);
ttext_box& input = find_widget<ttext_box>(&window, "input", true);
if(has_input_) {
caption.set_label(input_caption_);
caption.set_use_markup(true);
input.set_value(*input_text_);
input.set_maximum_length(input_maximum_lenght_);
window.keyboard_capture(&input);
window.set_click_dismiss(false);
window.set_escape_disabled(true);
} else {
caption.set_visible(twidget::INVISIBLE);
input.set_visible(twidget::INVISIBLE);
}
// Find the unit list related fields:
// tlistbox& units = find_widget<tlistbox>(&window, "unit_list", true);
tlistbox& units = find_widget<tlistbox>(&window, "recruit_list", true);
#ifndef GUI2_EXPERIMENTAL_LISTBOX
units.set_callback_value_change(dialog_callback<twml_message_,
&twml_message_::update_unit_list> );
#endif
if(!unit_list_.empty()) {
window.canvas(1).set_variable("portrait_image", variant(
chosen_unit_->big_profile()));
window.set_dirty();
chosen_unit_->draw_report();
//TODO make it optional
connect_signal_mouse_left_click(
find_widget<tbutton>(&window, "help", true)
, boost::bind(
&twml_message_::help_pressed
, this
));
connect_signal_mouse_left_click(
find_widget<tbutton>(&window, "profile", true)
, boost::bind(
&twml_message_::profile_pressed
, this
));
std::map<std::string, string_map> data;
for(size_t i = 0; i < unit_list_.size(); ++i) {
unit& unit = unit_list_[i];
bool affordable = unit.cost() <= gold_ ;
std::string unit_mod = affordable ? unit.image_mods() : "~GS()" ;
std::string icon = (unit.absolute_image() + unit_mod);
std::string type = unit.type_name();
std::string name = unit.name();
//TODO handle traits in another way
//std::string traits = unit.trait_descriptions();
std::ostringstream level;
std::ostringstream xp;
xp << unit.experience() << "/" << unit.max_experience();
// Show units of level (0=gray, 1 normal, 2 bold, 2+ bold&wbright)
const int level_number = unit.level();
//TODO enable the switch construct after replacing the font::NORMAL_TEXT etc.
// switch(level_number)
// {
// case 0: level << "<150,150,150>";
// break;
// case 1: level << font::NORMAL_TEXT;
// break;
// case 2: level << font::BOLD_TEXT;
// break;
// default: level << font::BOLD_TEXT << "<255,255,255>";
// }
level << level_number;
std::string gold_color;
gold_color = affordable ? "green" : "red" ;
std::ostringstream cost;
cost << "<span color=\"" << gold_color << "\">" << unit.cost() << " " << "Gold" << "</span>" ;
// Add the data.
data["cost"]["label"] = cost.str();
data["cost"]["use_markup"] = "true";
data["gold"]["label"] = "items/gold-coins-small.png";
data["usage"]["label"] = unit.usage();
data["icon"]["label"] = icon;
data["icon"]["use_markup"] = "true";
data["name"]["label"] = name;
data["type"]["label"] = type;
data["label"]["use_markup"] = "true";
data["level"]["label"] = level.str();
data["xp"]["label"] = xp.str();
//TODO traits handling changed through the versions
//data["traits"]["label"] = unit.traits_description();
units.add_row(data);
}
} else {
tbutton* profile_button = find_widget<tbutton> (&window, "profile", false,
false);
profile_button->set_visible(twidget::INVISIBLE);
units.set_visible(twidget::INVISIBLE);
tbutton* help_button = find_widget<tbutton> (&window, "help", false,
false);
help_button->set_visible(twidget::INVISIBLE);
tbutton* cancel_button = find_widget<tbutton> (&window, "cancel", false,
false);
cancel_button->set_visible(twidget::INVISIBLE);
}
// Find the option list related fields.
tlistbox& options = find_widget<tlistbox>(&window, "input_list", true);
if(!option_list_.empty()) {
std::map<std::string, string_map> data;
for(size_t i = 0; i < option_list_.size(); ++i) {
/**
* @todo This syntax looks like a bad hack, it would be nice to write
* a new syntax which doesn't use those hacks (also avoids the problem
* with special meanings for certain characters.
*/
tlegacy_menu_item item(option_list_[i]);
if(item.is_default()) {
// Number of items hasn't been increased yet so i is ok.
*chosen_option_ = i;
}
// Add the data.
data["icon"]["label"] = item.icon();
data["label"]["label"] = item.label();
data["label"]["use_markup"] = "true";
data["description"]["label"] = item.description();
data["description"]["use_markup"] = "true";
options.add_row(data);
}
// Avoid negetive and 0 since item 0 is already selected.
if(*chosen_option_ > 0
&& static_cast<size_t>(*chosen_option_)
< option_list_.size()) {
options.select_row(*chosen_option_);
}
if(!has_input_) {
window.keyboard_capture(&options);
window.set_click_dismiss(false);
window.set_escape_disabled(true);
} else {
window.add_to_keyboard_chain(&options);
// click_dismiss has been disabled due to the input.
}
} else {
options.set_visible(twidget::INVISIBLE);
}
window.set_click_dismiss(!has_input_ && option_list_.empty() && unit_list_.empty());
}
void twml_message_::post_show(twindow& window)
{
if(has_input_) {
*input_text_ =
find_widget<ttext_box>(&window, "input", true).get_value();
}
if(!option_list_.empty()) {
*chosen_option_ =
find_widget<tlistbox>(&window, "input_list", true).get_selected_row();
}
if(!unit_list_.empty()) {
*unit_id_ = chosen_unit_->type_id();
}
}
REGISTER_DIALOG(wml_message_left)
REGISTER_DIALOG(wml_message_right)
int show_recruit_message(const bool left_side
, CVideo& video
, std::vector<const unit_type*> type_list
, std::string* type_id
, int side_num
, int gold)
{
const std::string title = _("Recruit");
const std::string message = _("Select unit:");
const std::string portrait = "";
const bool mirror = false;
std::auto_ptr<twml_message_> dlg;
if(left_side) {
dlg.reset(new twml_message_left(title, message, portrait, mirror));
} else {
dlg.reset(new twml_message_right(title, message, portrait, mirror));
}
assert(dlg.get());
dlg->set_type_list(type_list, type_id, side_num, gold);
dlg->show(video);
return dlg->get_retval();
}
int show_wml_message(const bool left_side
, CVideo& video
, const std::string& title
, const std::string& message
, const std::string& portrait
, const bool mirror
, const bool has_input
, const std::string& input_caption
, std::string* input_text
, const unsigned maximum_length
, const bool has_unit
, std::string* unit_id
, const std::vector<unit>& unit_list
, const std::vector<std::string>& option_list
, int* chosen_option)
{
std::auto_ptr<twml_message_> dlg;
if(left_side) {
dlg.reset(new twml_message_left(title, message, portrait, mirror));
} else {
dlg.reset(new twml_message_right(title, message, portrait, mirror));
}
assert(dlg.get());
if(has_input) {
dlg->set_input(input_caption, input_text, maximum_length);
}
if(has_unit) {
dlg->set_unit_list(unit_list, unit_id);
}
if(!option_list.empty()) {
dlg->set_option_list(option_list, chosen_option);
}
dlg->show(video);
return dlg->get_retval();
}
} // namespace gui2

View file

@ -0,0 +1,243 @@
/* $Id$ */
/*
Copyright (C) 2008 - 2011 by Mark de Wever <koraq@xs4all.nl>
Part of 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_WML_MESSAGE_HPP_INCLUDED
#define GUI_DIALOGS_WML_MESSAGE_HPP_INCLUDED
#include "gui/dialogs/dialog.hpp"
//TODO get rid of this here
#include "unit.hpp"
namespace gui2 {
/**
* Base class for the wml generated messages.
*
* We have a separate sub class for left and right images.
*/
class twml_message_
: public tdialog
{
public:
twml_message_(const std::string& title, const std::string& message,
const std::string& portrait, const bool mirror)
: title_(title)
, image_("")
, message_(message)
, portrait_(portrait)
, mirror_(mirror)
, has_input_(false)
, input_caption_("")
, input_text_(NULL)
, input_maximum_lenght_(0)
, option_list_()
, chosen_option_(NULL)
{
}
/**
* Sets the input text variables.
*
* @param caption The caption for the label.
* @param text The initial text, after showing the final
* text.
* @param maximum_length The maximum length of the text.
*/
void set_input(const std::string& caption,
std::string* text, const unsigned maximum_length);
/**
* Sets the option list.
*
* @param option_list Vector of options to choice from.
* @param chosen_option Number of the option that was chosen.
*/
void set_option_list(
const std::vector<std::string>& option_list, int* chosen_option);
/**
* Sets the unit list.
*
* @param unit_list TODO
* @param chosen_unit TODO
*/
void set_unit_list(
const std::vector<unit>& unit_list, std::string* chosen_unit);
/**
* Sets the type list
*
* @param type_list TODO
* @param type_id TODO
* @param side_num TODO
* @param gold TODO
*/
void set_type_list(
std::vector<const unit_type*> type_list, std::string* type_id, int side_num, int gold);
private:
/** Handler for changed unit selection. */
void update_unit_list(twindow& window);
/** Handler for the profile button event. */
void profile_pressed();
/** Handler for the help button event */
void help_pressed();
/** The title for the dialog. */
std::string title_;
/**
* The image which is shown in the dialog.
*
* This image can be an icon or portrait or any other image.
*/
std::string image_;
/** The message to show to the user. */
std::string message_;
/** Filename of the portrait. */
std::string portrait_;
/** Mirror the portrait? */
bool mirror_;
/** Do we need to show an input box? */
bool has_input_;
/** The caption to show for the input text. */
std::string input_caption_;
/** The text input. */
std::string* input_text_;
/** The maximum length of the input text. */
unsigned input_maximum_lenght_;
/** The unit id. */
std::string* unit_id_;
/** The list of units the player can choose. */
std::vector<unit> unit_list_;
/** The list of unit_types the player can choose. */
//std::vector<const unit_type*> type_list_;
/** The list of options the player can choose. */
std::vector<std::string> option_list_;
/** The chosen option. */
int *chosen_option_;
/** The chosen unit. */
unit *chosen_unit_;
/** Gold */
int gold_;
/** Inherited from tdialog. */
void pre_show(CVideo& video, twindow& window);
/** Inherited from tdialog. */
void post_show(twindow& window);
};
/** Shows a dialog with the portrait on the left side. */
class twml_message_left : public twml_message_
{
public:
twml_message_left(const std::string& title, const std::string& message,
const std::string& portrait, const bool mirror)
: twml_message_(title, message, portrait, mirror)
{
}
private:
/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
virtual const std::string& window_id() const;
};
/** Shows a dialog with the portrait on the right side. */
class twml_message_right : public twml_message_
{
public:
twml_message_right(const std::string& title, const std::string& message,
const std::string& portrait, const bool mirror)
: twml_message_(title, message, portrait, mirror)
{
}
private:
/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
virtual const std::string& window_id() const;
};
/**
* Helper function to show a portrait.
*
* @param left_side If true the portrait is shown on the left,
* on the right side otherwise.
* @param video The display variable.
* @param title The title of the dialog.
* @param message The message to show.
* @param portrait Filename of the portrait.
* @param mirror Does the portrait need to be mirrored?
*
* @param has_input Do we need to show the input box.
* @param input_caption The caption for the optional input text
* box. If this value != "" there is an input
* and the input text parameter is mandatory.
* @param input_text Pointer to the initial text value will be
* set to the result.
* @param maximum_length The maximum length of the text.
*
* @param option_list A list of options to select in the dialog.
* @param chosen_option Pointer to the initially chosen option.
* Will be set to the chosen_option when the
* dialog closes.
*/
int show_recruit_message(const bool left_side
, CVideo& video
, std::vector<const unit_type*> type_list
, std::string* type_id
, int side_num
, int gold);
int show_wml_message(const bool left_side
, CVideo& video
, const std::string& title
, const std::string& message
, const std::string& portrait
, const bool mirror
, const bool has_input
, const std::string& input_caption
, std::string* input_text
, const unsigned maximum_length
, const bool has_unit
, std::string* unit_id
, const std::vector<unit>& unit_list
, const std::vector<std::string>& option_list
, int* chosen_option);
} // namespace gui2
#endif