Replaced the report and element classes...

...with a WML-friendly data structure, that is, config.
This commit is contained in:
Guillaume Melquiond 2010-12-26 20:01:00 +00:00
parent f7dae4410c
commit ef36d05b20
6 changed files with 123 additions and 142 deletions

View file

@ -2218,7 +2218,7 @@ void display::draw_image_for_report(surface& img, SDL_Rect& rect)
}
}
void display::refresh_report(std::string const &report_name, reports::report report)
void display::refresh_report(std::string const &report_name, const config &_report)
{
const theme::status_item *item = theme_.get_status_item(report_name);
if (!item) {
@ -2229,13 +2229,14 @@ void display::refresh_report(std::string const &report_name, reports::report rep
SDL_Rect &rect = reportRects_[report_name];
const SDL_Rect &new_rect = item->location(screen_area());
surface &surf = reportSurfaces_[report_name];
config &report = reports_[report_name];
// Report and its location is unchanged since last time. Do nothing.
if (surf && rect == new_rect && reports_[report_name] == report) {
if (surf && rect == new_rect && report == _report) {
return;
}
reports_[report_name] = report;
report = _report;
if (surf) {
sdl_blit(surf, NULL, screen_.getSurface(), &rect);
@ -2272,11 +2273,15 @@ void display::refresh_report(std::string const &report_name, reports::report rep
// as the guys around them.
std::string str = item->prefix();
if (!str.empty()) {
report.insert(report.begin(), reports::element(str, "", report.begin()->tooltip));
config &e = report.add_child_at("element", config(), 0);
e["text"] = str;
e["tooltip"] = report.child("element")["tooltip"];
}
str = item->postfix();
if (!str.empty()) {
report.push_back(reports::element(str, "", report.back().tooltip));
config &e = report.add_child("element");
e["text"] = str;
e["tooltip"] = report.child("element", -1)["tooltip"];
}
// Loop through and display each report element.
@ -2286,13 +2291,14 @@ void display::refresh_report(std::string const &report_name, reports::report rep
std::ostringstream ellipsis_tooltip;
SDL_Rect ellipsis_area = rect;
reports::report::iterator e = report.begin();
for(; e != report.end(); ++e)
for (config::const_child_itors elements = report.child_range("element");
elements.first != elements.second; ++elements.first)
{
SDL_Rect area = create_rect(x, y, rect.w + rect.x - x, rect.h + rect.y - y);
if (area.h <= 0) break;
if (!e->text.empty())
std::string t = (*elements.first)["text"];
if (!t.empty())
{
if (used_ellipsis) goto skip_element;
@ -2301,7 +2307,6 @@ void display::refresh_report(std::string const &report_name, reports::report rep
if (item->font_rgb_set()) {
text.set_foreground_color(item->font_rgb());
}
std::string t = e->text;
bool eol = false;
if (t[t.size() - 1] == '\n') {
eol = true;
@ -2315,8 +2320,9 @@ void display::refresh_report(std::string const &report_name, reports::report rep
// check if next element is text with almost no space to show it
const int minimal_text = 12; // width in pixels
if(!eol && rect.w - (x - rect.x + s->w) < minimal_text
&& e+1 != report.end() && !(e+1)->text.empty())
config::const_child_iterator ee = elements.first;
if (!eol && rect.w - (x - rect.x + s->w) < minimal_text &&
++ee != elements.second && !(*ee)["text"].empty())
{
// make this element longer to trigger rendering of ellipsis
// (to indicate that next elements have not enough space)
@ -2346,15 +2352,15 @@ void display::refresh_report(std::string const &report_name, reports::report rep
x += area.w;
}
}
else if (!e->image.get_filename().empty())
else if (!(t = (*elements.first)["image"].str()).empty())
{
if (used_ellipsis) goto skip_element;
// Draw an image element.
surface img(image::get_image(e->image));
surface img(image::get_image(t));
if (!img) {
ERR_DP << "could not find image for report: '" << e->image.get_filename() << "'\n";
ERR_DP << "could not find image for report: '" << t << "'\n";
continue;
}
@ -2386,15 +2392,17 @@ void display::refresh_report(std::string const &report_name, reports::report rep
}
skip_element:
if (!e->tooltip.empty()) {
t = (*elements.first)["tooltip"].str();
if (!t.empty()) {
if (!used_ellipsis) {
tooltips::add_tooltip(area, e->tooltip, e->action);
tooltips::add_tooltip(area, t, (*elements.first)["help"]);
} else {
// Collect all tooltips for the ellipsis.
// TODO: need a better separator
// TODO: assign an action
ellipsis_tooltip << e->tooltip;
if(e+1 != report.end())
ellipsis_tooltip << t;
config::const_child_iterator ee = elements.first;
if (++ee != elements.second)
ellipsis_tooltip << "\n _________\n\n";
}
}

View file

@ -264,7 +264,7 @@ public:
void create_buttons();
void invalidate_theme() { panelsDrawn_ = false; }
void refresh_report(std::string const &report_name, reports::report report);
void refresh_report(std::string const &report_name, const config &);
// Will be overridden in the display subclass
virtual void draw_minimap_units() {};
@ -578,7 +578,7 @@ protected:
// Not set by the initializer:
std::map<std::string, SDL_Rect> reportRects_;
std::map<std::string, surface> reportSurfaces_;
std::map<std::string, reports::report> reports_;
std::map<std::string, config> reports_;
std::vector<gui::button> buttons_;
std::set<map_location> invalidated_;
std::set<map_location> previous_invalidated_;

View file

@ -97,13 +97,19 @@ const SDL_Rect& editor_display::get_clip_rect()
void editor_display::draw_sidebar()
{
config element;
config::attribute_value &text = element["text"];
// Fill in the terrain report
if(get_map().on_board_with_border(mouseoverHex_)) {
refresh_report("terrain", reports::report(get_map().get_terrain_editor_string(mouseoverHex_)));
refresh_report("position", reports::report(str_cast(mouseoverHex_)));
if (get_map().on_board_with_border(mouseoverHex_)) {
text = get_map().get_terrain_editor_string(mouseoverHex_);
refresh_report("terrain", element);
text = str_cast(mouseoverHex_);
refresh_report("position", element);
}
refresh_report("villages", reports::report(str_cast(get_map().villages().size())));
refresh_report("editor_tool_hint", reports::report(toolbar_hint_));
text = int(get_map().villages().size());
refresh_report("villages", element);
text = toolbar_hint_;
refresh_report("editor_tool_hint", element);
}
} //end namespace editor

View file

@ -438,8 +438,7 @@ void game_display::draw_report(const std::string &report_name)
observers_, level_, !viewpoint_
};
reports::report report = reports::generate_report(report_name, data);
refresh_report(report_name, report);
refresh_report(report_name, reports::generate_report(report_name, data));
}
void game_display::draw_sidebar()

View file

@ -33,31 +33,54 @@
#include <cassert>
#include <ctime>
namespace reports {
void report::add_text(const std::string& text,
const std::string& tooltip, const std::string& action) {
this->push_back(element(text,"",tooltip,action));
static void add_text(config &report, const std::string &text,
const std::string &tooltip, const std::string &help = "")
{
config &element = report.add_child("element");
element["text"] = text;
if (!tooltip.empty()) element["tooltip"] = tooltip;
if (!help.empty()) element["help"] = help;
}
void report::add_image(const std::string& image, const std::string& tooltip,
const std::string& action) {
this->push_back(element("",image,tooltip,action));
static void add_image(config &report, const std::string &image,
const std::string &tooltip, const std::string &help = "")
{
config &element = report.add_child("element");
element["image"] = image;
if (!tooltip.empty()) element["tooltip"] = tooltip;
if (!help.empty()) element["help"] = help;
}
static config report()
{
return config();
}
static config text_report(const std::string &text,
const std::string &tooltip = "", const std::string &help = "")
{
config r;
add_text(r, text, tooltip, help);
return r;
}
static config image_report(const std::string &image,
const std::string &tooltip = "", const std::string &help = "")
{
config r;
add_image(r, image, tooltip, help);
return r;
}
using reports::report;
using reports::report_data;
using font::span_color;
static void add_status(report &r,
static void add_status(config &r,
char const *path, char const *desc1, char const *desc2)
{
std::ostringstream s;
s << gettext(desc1) << gettext(desc2);
r.add_image(path, s.str());
add_image(r, path, s.str());
}
static std::string flush(std::ostringstream &s)
@ -69,7 +92,7 @@ static std::string flush(std::ostringstream &s)
struct report_generator
{
typedef report (*fun)(report_data const &);
typedef config (*fun)(report_data const &);
fun generator;
bool for_units;
report_generator(fun g, bool u): generator(g), for_units(u) {}
@ -88,9 +111,9 @@ struct report_generator_helper
};
#define REPORT_GENERATOR(n, u, data) \
static report report_##n(const report_data &); \
static config report_##n(const report_data &); \
static report_generator_helper reg_gen_##n(#n, &report_##n, u); \
static report report_##n(const report_data &data)
static config report_##n(const report_data &data)
static char const *naps = "</span>";
@ -100,11 +123,11 @@ static unit *get_visible_unit(const report_data &data)
(*resources::teams)[data.viewing_side - 1], data.show_everything);
}
static report gray_inactive(const report_data &data, const std::string &str)
static config gray_inactive(const report_data &data, const std::string &str)
{
if (data.current_side == data.active_side)
return report(str);
return report(span_color(font::GRAY_COLOR) + str + naps);
return text_report(str);
return text_report(span_color(font::GRAY_COLOR) + str + naps);
}
REPORT_GENERATOR(unit_name, true, data)
@ -114,7 +137,7 @@ REPORT_GENERATOR(unit_name, true, data)
std::ostringstream str, tooltip;
str << "<b>" << u->name() << "</b>";
tooltip << _("Name: ") << "<b>" << u->name() << "</b>";
return report(str.str(), "", tooltip.str());
return text_report(str.str(), tooltip.str());
}
REPORT_GENERATOR(unit_type, true, data)
@ -125,7 +148,7 @@ REPORT_GENERATOR(unit_type, true, data)
str << span_color(font::unit_type_color) << u->type_name() << naps;
tooltip << _("Type: ") << "<b>" << u->type_name() << "</b>\n"
<< u->unit_description();
return report(str.str(), "", tooltip.str(), "unit_" + u->type_id());
return text_report(str.str(), tooltip.str(), "unit_" + u->type_id());
}
REPORT_GENERATOR(unit_race, true, data)
@ -135,7 +158,7 @@ REPORT_GENERATOR(unit_race, true, data)
std::ostringstream str, tooltip;
str << span_color(font::race_color) << u->race()->name(u->gender()) << naps;
tooltip << _("Race: ") << "<b>" << u->race()->name(u->gender()) << "</b>";
return report(str.str(), "", tooltip.str(), "..race_" + u->race()->id());
return text_report(str.str(), tooltip.str(), "..race_" + u->race()->id());
}
REPORT_GENERATOR(unit_side, true, data)
@ -149,8 +172,7 @@ REPORT_GENERATOR(unit_side, true, data)
std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";
if (flag_icon.empty())
flag_icon = game_config::images::flag_icon;
image::locator flag_icon_img(flag_icon, mods);
return report("", flag_icon_img, u_team.current_player());
return image_report(flag_icon + mods, u_team.current_player());
}
REPORT_GENERATOR(unit_level, true, data)
@ -166,17 +188,17 @@ REPORT_GENERATOR(unit_level, true, data)
else
tooltip << _("Advances to:") << "\n<b>\t"
<< utils::join(adv_to, "\n\t") << "</b>";
return report(str.str(), "", tooltip.str());
return text_report(str.str(), tooltip.str());
}
REPORT_GENERATOR(unit_amla, true, data)
{
unit *u = get_visible_unit(data);
if (!u) return report();
report res;
config res;
typedef std::pair<std::string, std::string> pair_string;
foreach(const pair_string &ps, u->amla_icons()) {
res.add_image(ps.first,ps.second);
add_image(res, ps.first, ps.second);
}
return res;
}
@ -185,7 +207,7 @@ REPORT_GENERATOR(unit_traits, true, data)
{
unit *u = get_visible_unit(data);
if (!u) return report();
report res;
config res;
const std::vector<t_string> &traits = u->trait_names();
const std::vector<t_string> &descriptions = u->trait_descriptions();
unsigned nb = traits.size();
@ -196,7 +218,7 @@ REPORT_GENERATOR(unit_traits, true, data)
if (i != nb - 1 ) str << ", ";
tooltip << _("Trait: ") << "<b>" << traits[i] << "</b>\n"
<< descriptions[i];
res.add_text(str.str(), tooltip.str());
add_text(res, str.str(), tooltip.str());
}
return res;
}
@ -205,7 +227,7 @@ REPORT_GENERATOR(unit_status, true, data)
{
unit *u = get_visible_unit(data);
if (!u) return report();
report res;
config res;
if (resources::game_map->on_board(data.displayed_unit_hex) &&
u->invisible(data.displayed_unit_hex))
{
@ -238,14 +260,14 @@ REPORT_GENERATOR(unit_alignment, true, data)
str << align << " (" << utils::signed_percent(cm) << ")";
tooltip << _("Alignment: ") << "<b>" << align << "</b>\n"
<< string_table[align_id + "_description"];
return report(str.str(), "", tooltip.str(), "time_of_day");
return text_report(str.str(), tooltip.str(), "time_of_day");
}
REPORT_GENERATOR(unit_abilities, true, data)
{
unit *u = get_visible_unit(data);
if (!u) return report();
report res;
config res;
const std::vector<std::string> &abilities = u->ability_tooltips();
for (std::vector<std::string>::const_iterator i = abilities.begin(),
i_end = abilities.end(); i != i_end; ++i)
@ -256,7 +278,7 @@ REPORT_GENERATOR(unit_abilities, true, data)
if (i + 2 != i_end) str << ", ";
++i;
tooltip << _("Ability: ") << *i;
res.add_text(str.str(), tooltip.str(), "ability_" + name);
add_text(res, str.str(), tooltip.str(), "ability_" + name);
}
return res;
}
@ -296,7 +318,7 @@ REPORT_GENERATOR(unit_hp, true, data)
foreach (const std::string &line, resistances_table) {
tooltip << line;
}
return report(str.str(), "", tooltip.str());
return text_report(str.str(), tooltip.str());
}
REPORT_GENERATOR(unit_xp, true, data)
@ -309,17 +331,17 @@ REPORT_GENERATOR(unit_xp, true, data)
std::string exp_mod = data.level["experience_modifier"].str();
tooltip << _("Experience Modifier: ") << (!exp_mod.empty() ? exp_mod : "100") << '%';
return report(str.str(), "", tooltip.str());
return text_report(str.str(), tooltip.str());
}
REPORT_GENERATOR(unit_advancement_options, true, data)
{
unit *u = get_visible_unit(data);
if (!u) return report();
report res;
config res;
typedef std::pair<std::string, std::string> pair_string;
foreach (const pair_string &ps, u->advancement_icons()) {
res.add_image(ps.first,ps.second);
add_image(res, ps.first, ps.second);
}
return res;
}
@ -358,7 +380,7 @@ REPORT_GENERATOR(unit_defense, true, data)
}
tooltip << "<b>" << _("Defense: ") << span_color(color) << def << "%</span></b>";
return report(str.str(), "", tooltip.str());
return text_report(str.str(), tooltip.str());
}
REPORT_GENERATOR(unit_moves, true, data)
@ -376,7 +398,7 @@ REPORT_GENERATOR(unit_moves, true, data)
int grey = 128 + int((255 - 128) * movement_frac);
SDL_Color c = create_color(grey, grey, grey);
str << span_color(c) << u->movement_left() << '/' << u->total_movement() << naps;
return report(str.str());
return text_report(str.str());
}
REPORT_GENERATOR(unit_weapons, true, data)
@ -384,7 +406,7 @@ REPORT_GENERATOR(unit_weapons, true, data)
unit *u = get_visible_unit(data);
if (!u) return report();
std::ostringstream str, tooltip;
report res;
config res;
foreach (const attack_type &at, u->attacks())
{
@ -451,7 +473,7 @@ REPORT_GENERATOR(unit_weapons, true, data)
tooltip << '\t' << _("Swarm: ") << "* "<< hp_ratio << "%\n";
}
res.add_text(flush(str), flush(tooltip));
add_text(res, flush(str), flush(tooltip));
std::string range = gettext(at.range().c_str());
std::string lang_type = gettext(at.type().c_str());
@ -497,7 +519,7 @@ REPORT_GENERATOR(unit_weapons, true, data)
<< "<i>(" << utils::signed_percent(resist.first-100) << ")</i> : "
<< utils::join(resist.second, ", ") << '\n';
}
res.add_text(flush(str), flush(tooltip));
add_text(res, flush(str), flush(tooltip));
const std::string &accuracy_parry = at.accuracy_parry_description();
if (!accuracy_parry.empty())
@ -514,7 +536,7 @@ REPORT_GENERATOR(unit_weapons, true, data)
tooltip << _("Parry:") << "<b>"
<< utils::signed_percent(parry) << "</b>\n";
}
res.add_text(flush(str), flush(tooltip));
add_text(res, flush(str), flush(tooltip));
}
const std::vector<t_string> &specials = at.special_tooltips();
@ -529,7 +551,7 @@ REPORT_GENERATOR(unit_weapons, true, data)
++sp_it;
//FIXME pull out special's name from description
tooltip << _("Weapon special: ") << *sp_it << '\n';
res.add_text(flush(str), flush(tooltip), help_page);
add_text(res, flush(str), flush(tooltip), help_page);
}
}
}
@ -540,14 +562,14 @@ REPORT_GENERATOR(unit_image, true, data)
{
unit *u = get_visible_unit(data);
if (!u) return report();
return report("", image::locator(u->absolute_image(), u->image_mods()), "");
return image_report(u->absolute_image() + u->image_mods());
}
REPORT_GENERATOR(unit_profile, true, data)
{
unit *u = get_visible_unit(data);
if (!u) return report();
return report("", u->small_profile(), "");
return image_report(u->small_profile());
}
REPORT_GENERATOR(time_of_day, false, data)
@ -579,7 +601,7 @@ REPORT_GENERATOR(time_of_day, false, data)
else if (tod.lawful_bonus_modified < 0) tod_image += "~DARKEN()";
if (preferences::flip_time()) tod_image += "~FL(horiz)";
return report("", tod_image, tooltip.str(), "time_of_day");
return image_report(tod_image, tooltip.str(), "time_of_day");
}
REPORT_GENERATOR(turn, false, /*data*/)
@ -588,7 +610,7 @@ REPORT_GENERATOR(turn, false, /*data*/)
str << resources::tod_manager->turn();
int nb = resources::tod_manager->number_of_turns();
if (nb != -1) str << '/' << nb;
return report(str.str());
return text_report(str.str());
}
REPORT_GENERATOR(gold, false, data)
@ -605,7 +627,7 @@ REPORT_GENERATOR(gold, false, data)
else
end = "";
str << fake_gold << end;
return report(str.str());
return text_report(str.str());
}
REPORT_GENERATOR(villages, false, data)
@ -661,7 +683,7 @@ REPORT_GENERATOR(income, false, data)
else
end = "";
str << td.net_income << end;
return report(str.str());
return text_report(str.str());
}
REPORT_GENERATOR(terrain, false, data)
@ -707,7 +729,7 @@ REPORT_GENERATOR(terrain, false, data)
}
str << ')';
}
return report(str.str());
return text_report(str.str());
}
REPORT_GENERATOR(position, false, data)
@ -728,7 +750,7 @@ REPORT_GENERATOR(position, false, data)
(data.displayed_unit_hex != data.mouseover_hex &&
data.displayed_unit_hex != data.selected_hex) ||
viewing_team.shrouded(data.mouseover_hex))
return report(str.str());
return text_report(str.str());
int move_cost = u->movement_cost(terrain);
int defense = 100 - u->defense_modifier(terrain);
@ -739,7 +761,7 @@ REPORT_GENERATOR(position, false, data)
} else {
str << " (-)";
}
return report(str.str());
return text_report(str.str());
}
REPORT_GENERATOR(side_playing, false, data)
@ -751,8 +773,7 @@ REPORT_GENERATOR(side_playing, false, data)
std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";
if (flag_icon.empty())
flag_icon = game_config::images::flag_icon;
image::locator flag_icon_img(flag_icon, mods);
return report("", flag_icon_img, active_team.current_player());
return image_report(flag_icon + mods, active_team.current_player());
}
REPORT_GENERATOR(observers, false, data)
@ -765,7 +786,7 @@ REPORT_GENERATOR(observers, false, data)
foreach (const std::string &obs, data.observers) {
str << obs << '\n';
}
return report("", game_config::images::observer, str.str());
return image_report(game_config::images::observer, str.str());
}
#ifdef DISABLE_EDITOR
@ -788,7 +809,7 @@ REPORT_GENERATOR(selected_terrain, false, /*data*/)
if (editor::selected_terrain.empty())
return report();
else
return report(editor::selected_terrain);
return text_report(editor::selected_terrain);
}
REPORT_GENERATOR(edit_left_button_function, false, /*data*/)
@ -796,7 +817,7 @@ REPORT_GENERATOR(edit_left_button_function, false, /*data*/)
if (editor::left_button_function.empty())
return report();
else
return report(editor::left_button_function);
return text_report(editor::left_button_function);
}
#endif
@ -813,7 +834,7 @@ REPORT_GENERATOR(report_clock, false, /*data*/)
char temp[10];
size_t s = std::strftime(temp, 10, preferences::clock_format().c_str(), lt);
if (!s) return report();
return report(temp);
return text_report(temp);
}
REPORT_GENERATOR(report_countdown, false, data)
@ -838,10 +859,10 @@ REPORT_GENERATOR(report_countdown, false, data)
sec = sec % 60;
if (sec < 10) str << '0';
str << sec << end;
return report(str.str());
return text_report(str.str());
}
report reports::generate_report(const std::string &name, const report_data &data)
config reports::generate_report(const std::string &name, const report_data &data)
{
report_generators::const_iterator i = static_generators.find(name);
if (i == static_generators.end()) return report();

View file

@ -16,64 +16,11 @@
#ifndef REPORTS_HPP_INCLUDED
#define REPORTS_HPP_INCLUDED
#include "image.hpp"
class team;
#include "map_location.hpp"
//this module is responsible for outputting textual reports of
//various game and unit statistics
namespace reports {
struct element {
explicit element(const std::string& text) :
image(),
text(text),
tooltip(),
action()
{}
// Invariant: either text or image should be empty
// It would be okay to create a class for this, but it's a pretty simple
// invariant so I left it like the original report class.
image::locator image;
std::string text;
std::string tooltip;
std::string action;
element(const std::string& text, const std::string& image,
const std::string& tooltip, const std::string& action="") :
image(image), text(text), tooltip(tooltip), action(action) {}
element(const std::string& text, const image::locator& image,
const std::string& tooltip, const std::string& action="") :
image(image), text(text), tooltip(tooltip), action(action) {}
element(const std::string& text, const char* image,
const std::string& tooltip, const std::string& action="") :
image(image), text(text), tooltip(tooltip), action(action) {}
bool operator==(const element& o) const {
return o.text == text && o.image == image && o.tooltip == tooltip && o.action == action;
}
bool operator!=(const element& o) const { return !(o == *this); }
};
struct report : public std::vector<element> {
report() {}
explicit report(const std::string& text) { this->push_back(element(text)); }
report(const std::string& text, const std::string& image, const std::string& tooltip, const std::string& action="") {
this->push_back(element(text, image, tooltip, action));
}
report(const std::string& text, const char* image, const std::string& tooltip, const std::string& action="") {
this->push_back(element(text, image, tooltip, action));
}
report(const std::string& text, const image::locator& image, const std::string& tooltip, const std::string& action="") {
this->push_back(element(text, image, tooltip, action));
}
// Convenience functions
void add_text(const std::string& text,
const std::string& tooltip, const std::string& action="");
void add_image(const std::string& image,
const std::string& tooltip, const std::string& action="");
};
struct report_data
{
@ -88,7 +35,7 @@ struct report_data
bool show_everything;
};
report generate_report(const std::string &name, const report_data &data);
config generate_report(const std::string &name, const report_data &data);
const std::set<std::string> &report_list(bool for_units);
}