"Patch to reports to handle multiple images & strings per report ...
...each with their own tooltips." (patch by John B. Messerly)
This commit is contained in:
parent
6d02c13ed1
commit
577d087f78
3 changed files with 113 additions and 153 deletions
147
src/display.cpp
147
src/display.cpp
|
@ -674,7 +674,7 @@ void display::draw_report(reports::TYPE report_num)
|
|||
const theme::status_item* const item = theme_.get_status_item(reports::report_name(report_num));
|
||||
if(item != NULL) {
|
||||
|
||||
const reports::report& report = reports::generate_report(report_num,map_,
|
||||
reports::report report = reports::generate_report(report_num,map_,
|
||||
units_, teams_,
|
||||
teams_[viewing_team()],
|
||||
currentTeam_+1,activeTeam_+1,
|
||||
|
@ -705,7 +705,7 @@ void display::draw_report(reports::TYPE report_num)
|
|||
//if the rectangle is present, and we are blitting text, then
|
||||
//we need to backup the surface. (Images generally won't need backing
|
||||
//up unless they are transperant, but that is done later)
|
||||
if(rect.w > 0 && rect.h > 0 && report.text.empty() == false) {
|
||||
if(rect.w > 0 && rect.h > 0) {
|
||||
surf.assign(get_surface_portion(screen_.getSurface(),rect));
|
||||
if(reportSurfaces_[report_num] == NULL) {
|
||||
std::cerr << "Could not backup background for report!\n";
|
||||
|
@ -719,109 +719,60 @@ void display::draw_report(reports::TYPE report_num)
|
|||
|
||||
SDL_Rect area = rect;
|
||||
|
||||
// Code for handling a report with multiple tooltips in different areas of the text
|
||||
// XXX figure out if prefix/postfix makes sense for these reports, and if so how
|
||||
// should we support it?
|
||||
if(report.text.size() > 1) {
|
||||
int x = rect.x, y = rect.y;
|
||||
for(size_t i = 0; i < report.text.size(); ++i) {
|
||||
std::string text = report.text[i];
|
||||
std::string tooltip = (i < report.tooltip.size() ? report.tooltip[i] : "");
|
||||
|
||||
area = font::draw_text(this,rect,item->font_size(),font::NORMAL_COLOUR,text,x,y);
|
||||
if(text != "" && *(text.end()-1) == '\n') {
|
||||
x = area.x;
|
||||
y = area.y + area.h;
|
||||
} else {
|
||||
x = area.x + area.w;
|
||||
y = area.y;
|
||||
}
|
||||
if(tooltip.empty() == false) {
|
||||
tooltips::add_tooltip(area,tooltip);
|
||||
}
|
||||
}
|
||||
// Skip single-tooltip report code and image drawing code
|
||||
return;
|
||||
}
|
||||
|
||||
std::string text = report.text.size() ? report.text[0] : "";
|
||||
std::string tooltip = report.tooltip.size() ? report.tooltip[0] : "";
|
||||
|
||||
if(text.empty() == false) {
|
||||
if(!report.empty()) {
|
||||
// Add prefix, postfix elements. Make sure that they get the same tooltip as the guys
|
||||
// around them.
|
||||
std::string str = item->prefix();
|
||||
|
||||
int nchop;
|
||||
|
||||
//if there are formatting directives on the front of the report,
|
||||
//move them to the front of the string
|
||||
for(nchop = 0; nchop != text.size() && font::is_format_char(text[nchop]); ++nchop) {
|
||||
str.insert(str.begin(),text[nchop]);
|
||||
if(str.empty() == false) {
|
||||
report.insert(report.begin(), reports::element(str,"",report.begin()->tooltip));
|
||||
}
|
||||
str = item->postfix();
|
||||
if(str.empty() == false) {
|
||||
report.push_back(reports::element(str,"",report.end()->tooltip));
|
||||
}
|
||||
|
||||
str += text.substr(nchop) + item->postfix();
|
||||
|
||||
area = font::draw_text(this,rect,item->font_size(),font::NORMAL_COLOUR,str,rect.x,rect.y);
|
||||
}
|
||||
|
||||
if(tooltip.empty() == false) {
|
||||
tooltips::add_tooltip(area,tooltip);
|
||||
}
|
||||
|
||||
if(report.image.empty() == false) {
|
||||
|
||||
//check if it's a table of images or a standalone image
|
||||
if((report.image.find_first_of(",") == -1) &&
|
||||
(report.image.find_first_of(";") == -1)) {
|
||||
scoped_sdl_surface img(image::get_image(report.image,image::UNSCALED));
|
||||
if(img == NULL) {
|
||||
std::cerr << "could not find image for report: '" << report.image << "'\n";
|
||||
return;
|
||||
}
|
||||
draw_image_for_report(img,surf,rect);
|
||||
// Loop through and display each report element
|
||||
size_t tallest = 0;
|
||||
for(reports::report::iterator i = report.begin(); i != report.end(); ++i) {
|
||||
if(i->text.empty() == false) {
|
||||
// Draw a text element
|
||||
area = font::draw_text(this,rect,item->font_size(),font::NORMAL_COLOUR,i->text,x,y);
|
||||
if(area.h > tallest) tallest = area.h;
|
||||
if(i->text[i->text.size() - 1] == '\n') {
|
||||
x = rect.x;
|
||||
y += tallest;
|
||||
tallest = 0;
|
||||
} else {
|
||||
//draw a table of images...
|
||||
|
||||
//first back up the current area for later restoration
|
||||
surf.assign(get_surface_portion(screen_.getSurface(),rect));
|
||||
|
||||
//each image may have a seperate tooltip, so seperate the tooltips
|
||||
tooltips::clear_tooltips(rect);
|
||||
|
||||
int x = rect.x, y = rect.y;
|
||||
const std::vector<std::string> rows = config::split(report.image,';');
|
||||
const std::vector<std::string> tooltip_rows = config::split(tooltip,';');
|
||||
std::vector<std::string>::const_iterator current_tooltip = tooltip_rows.begin();
|
||||
for(std::vector<std::string>::const_iterator row = rows.begin(); row != rows.end(); ++row) {
|
||||
|
||||
size_t tallest_image = 0;
|
||||
|
||||
std::vector<std::string> cols = config::split(*row);
|
||||
for(std::vector<std::string>::const_iterator col = cols.begin(); col != cols.end(); ++col) {
|
||||
SDL_Rect clip_rect = rect;
|
||||
scoped_sdl_surface image(image::get_image(*col,image::UNSCALED));
|
||||
if(image == NULL) {
|
||||
std::cerr << "could not find image for report: '" << *col << "'\n";
|
||||
return;
|
||||
}
|
||||
|
||||
blit_surface(x,y,image,NULL,&clip_rect);
|
||||
if(image->h > tallest_image)
|
||||
tallest_image = image->h;
|
||||
|
||||
SDL_Rect tooltip_rect = {x,y,image->w,image->h};
|
||||
if(current_tooltip != tooltip_rows.end()) {
|
||||
if(*current_tooltip != "") {
|
||||
tooltips::add_tooltip(tooltip_rect,*current_tooltip);
|
||||
}
|
||||
|
||||
++current_tooltip;
|
||||
}
|
||||
|
||||
x += image->w;
|
||||
x += area.w;
|
||||
}
|
||||
} else if(i->image.empty() == false) {
|
||||
//first back up the current area for later restoration
|
||||
//surf.assign(get_surface_portion(screen_.getSurface(),rect));
|
||||
|
||||
x = rect.x;
|
||||
y += tallest_image;
|
||||
// Draw an image element
|
||||
scoped_sdl_surface img(image::get_image(i->image,image::UNSCALED));
|
||||
|
||||
if(img == NULL) {
|
||||
std::cerr << "could not find image for report: '" << i->image << "'\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
area.x = x;
|
||||
area.y = y;
|
||||
area.w = minimum<int>(rect.w + rect.x - x, img->w);
|
||||
area.h = minimum<int>(rect.h + rect.y - y, img->h);
|
||||
draw_image_for_report(img,surf,area);
|
||||
|
||||
if(area.h > tallest) tallest = area.h;
|
||||
x += area.w;
|
||||
|
||||
} else {
|
||||
// No text or image, skip this element
|
||||
continue;
|
||||
}
|
||||
if(i->tooltip.empty() == false) {
|
||||
tooltips::add_tooltip(area,i->tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,13 +33,18 @@ void report::add_text(std::stringstream& text, std::stringstream& tooltip) {
|
|||
}
|
||||
|
||||
void report::add_text(const std::string& text, const std::string& tooltip) {
|
||||
this->text.push_back(text);
|
||||
this->tooltip.push_back(tooltip);
|
||||
this->push_back(element(text,"",tooltip));
|
||||
}
|
||||
|
||||
void report::set_tooltip(const std::string& tooltip) {
|
||||
this->tooltip.clear();
|
||||
this->tooltip.push_back(tooltip);
|
||||
void report::add_image(std::stringstream& image, std::stringstream& tooltip) {
|
||||
add_image(image.str(), tooltip.str());
|
||||
// Clear the streams
|
||||
image.str("");
|
||||
tooltip.str("");
|
||||
}
|
||||
|
||||
void report::add_image(const std::string& image, const std::string& tooltip) {
|
||||
this->push_back(element("",image,tooltip));
|
||||
}
|
||||
|
||||
report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
||||
|
@ -79,55 +84,47 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
switch(type) {
|
||||
case UNIT_DESCRIPTION:
|
||||
return report(u->second.description());
|
||||
case UNIT_TYPE: {
|
||||
report res(u->second.type().language_name());
|
||||
res.set_tooltip(u->second.type().unit_description());
|
||||
return res;
|
||||
}
|
||||
case UNIT_TYPE:
|
||||
return report(u->second.type().language_name(),"",u->second.type().unit_description());
|
||||
case UNIT_LEVEL:
|
||||
str << u->second.type().level();
|
||||
break;
|
||||
case UNIT_TRAITS: {
|
||||
report res(u->second.traits_description());
|
||||
res.set_tooltip(u->second.modification_description("trait"));
|
||||
return res;
|
||||
}
|
||||
case UNIT_TRAITS:
|
||||
return report(u->second.traits_description(),"",u->second.modification_description("trait"));
|
||||
case UNIT_STATUS: {
|
||||
std::stringstream unit_status;
|
||||
std::stringstream tooltip;
|
||||
report res;
|
||||
|
||||
if(map.on_board(loc) && u->second.invisible(map.underlying_terrain(map[loc.x][loc.y]),status.get_time_of_day().lawful_bonus,loc,units,teams)) {
|
||||
unit_status << "misc/invisible.png,";
|
||||
tooltip << string_table["invisible"] << ": " <<
|
||||
string_table["invisible_description"] << ";";
|
||||
unit_status << "misc/invisible.png";
|
||||
tooltip << string_table["invisible"] << ": " << string_table["invisible_description"];
|
||||
res.add_image(unit_status,tooltip);
|
||||
}
|
||||
if(u->second.has_flag("slowed")) {
|
||||
unit_status << "misc/slowed.png,";
|
||||
tooltip << string_table["slowed"] << ": " <<
|
||||
string_table["slowed_description"] << ";";
|
||||
unit_status << "misc/slowed.png";
|
||||
tooltip << string_table["slowed"] << ": " << string_table["slowed_description"];
|
||||
res.add_image(unit_status,tooltip);
|
||||
}
|
||||
if(u->second.has_flag("poisoned")) {
|
||||
unit_status << "misc/poisoned.png,";
|
||||
tooltip << string_table["poisoned"] << ": " <<
|
||||
string_table["poisoned_description"] << ";";
|
||||
unit_status << "misc/poisoned.png";
|
||||
tooltip << string_table["poisoned"] << ": " << string_table["poisoned_description"];
|
||||
res.add_image(unit_status,tooltip);
|
||||
}
|
||||
if(u->second.has_flag("stone")) {
|
||||
unit_status << "misc/stone.png,";
|
||||
tooltip << string_table["stone"] << ": " <<
|
||||
string_table["stone_description"] << ";";
|
||||
unit_status << "misc/stone.png";
|
||||
tooltip << string_table["stone"] << ": " << string_table["stone_description"];
|
||||
res.add_image(unit_status,tooltip);
|
||||
}
|
||||
|
||||
report res("",unit_status.str());
|
||||
res.set_tooltip(tooltip.str());
|
||||
return res;
|
||||
}
|
||||
case UNIT_ALIGNMENT: {
|
||||
const std::string& align = unit_type::alignment_description(u->second.type().alignment());
|
||||
report res(translate_string(align));
|
||||
res.set_tooltip(string_table[align + "_description"]);
|
||||
return res;
|
||||
return report(translate_string(align),"",string_table[align + "_description"]);
|
||||
}
|
||||
case UNIT_ABILITIES: {
|
||||
report res;
|
||||
std::stringstream tooltip;
|
||||
const std::vector<std::string>& abilities = u->second.type().abilities();
|
||||
for(std::vector<std::string>::const_iterator i = abilities.begin(); i != abilities.end(); ++i) {
|
||||
|
@ -135,11 +132,10 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
if(i+1 != abilities.end())
|
||||
str << ",";
|
||||
|
||||
tooltip << string_table[*i + "_description"] << "\n\n";
|
||||
tooltip << string_table[*i + "_description"];
|
||||
res.add_text(str,tooltip);
|
||||
}
|
||||
|
||||
report res(str.str());
|
||||
res.set_tooltip(tooltip.str());
|
||||
return res;
|
||||
}
|
||||
case UNIT_HP:
|
||||
|
@ -181,11 +177,11 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
|
||||
str << (lang_weapon.empty() ? at_it->name():lang_weapon) << " ("
|
||||
<< (lang_type.empty() ? at_it->type():lang_type) << ")\n";
|
||||
res.add_text(str, tooltip);
|
||||
res.add_text(str,tooltip);
|
||||
|
||||
str << (lang_special.empty() ? at_it->special():lang_special) << "\n";
|
||||
tooltip << string_table["weapon_special_" + at_it->special() + "_description"];
|
||||
res.add_text(str, tooltip);
|
||||
res.add_text(str,tooltip);
|
||||
|
||||
str << at_it->damage() << "-" << at_it->num_attacks() << " -- "
|
||||
<< (at_it->range() == attack_type::SHORT_RANGE ?
|
||||
|
@ -199,18 +195,17 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
tooltip << ", " << at_it->hexes() << " " << string_table["hexes"];
|
||||
}
|
||||
str << "\n";
|
||||
res.add_text(str, tooltip);
|
||||
res.add_text(str,tooltip);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
case UNIT_IMAGE:
|
||||
return report("",u->second.type().image());
|
||||
return report("",u->second.type().image(),"");
|
||||
case UNIT_PROFILE:
|
||||
return report("",u->second.type().image_profile());
|
||||
return report("",u->second.type().image_profile(),"");
|
||||
case TIME_OF_DAY: {
|
||||
const time_of_day& tod = timeofday_at(status,units,mouseover);
|
||||
report res("",tod.image);
|
||||
std::stringstream tooltip;
|
||||
|
||||
tooltip << font::LARGE_TEXT << translate_string_default(tod.id,tod.name) << "\n"
|
||||
|
@ -219,8 +214,8 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
<< translate_string("neutral") << " " << string_table["units"] << ": " << "0%\n"
|
||||
<< translate_string("chaotic") << " " << string_table["units"] << ": "
|
||||
<< (tod.lawful_bonus < 0 ? "+" : "") << (tod.lawful_bonus*-1) << "%";
|
||||
res.set_tooltip(tooltip.str());
|
||||
return res;
|
||||
|
||||
return report("",tod.image,tooltip.str());
|
||||
}
|
||||
case TURN:
|
||||
str << status.turn() << "/" << status.number_of_turns() << "\n";
|
||||
|
@ -295,7 +290,7 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
case SIDE_PLAYING: {
|
||||
char buf[50];
|
||||
sprintf(buf,"terrain/flag-team%d.png",playing_side);
|
||||
return report("",buf);
|
||||
return report("",buf,"");
|
||||
}
|
||||
|
||||
case OBSERVERS: {
|
||||
|
@ -307,9 +302,7 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
str << *i << "\n";
|
||||
}
|
||||
|
||||
report res("",game_config::observer_image);
|
||||
res.set_tooltip(str.str());
|
||||
return res;
|
||||
return report("",game_config::observer_image,str.str());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,21 +25,37 @@ namespace reports {
|
|||
|
||||
const std::string& report_name(TYPE type);
|
||||
|
||||
struct report {
|
||||
struct element {
|
||||
// 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.
|
||||
std::string image;
|
||||
std::vector<std::string> text, tooltip;
|
||||
std::string text;
|
||||
|
||||
std::string tooltip;
|
||||
|
||||
element() {}
|
||||
explicit element(const std::string& text) : text(text) {}
|
||||
element(const std::string& text, const std::string& image, const std::string& tooltip) :
|
||||
text(text), image(image), tooltip(tooltip) {}
|
||||
|
||||
bool operator==(const element& o) const {
|
||||
return o.text == text && o.image == image && o.tooltip == tooltip;
|
||||
}
|
||||
bool operator!=(const element& o) const { return !(o == *this); }
|
||||
};
|
||||
struct report : public std::vector<element> {
|
||||
report() {}
|
||||
explicit report(const std::string& text) { this->text.push_back(text); }
|
||||
report(const std::string& text, const std::string& image) : image(image) { this->text.push_back(text); }
|
||||
bool empty() const { return text.empty() && image.empty(); }
|
||||
bool operator==(const report& o) const { return o.text == text && o.image == image && o.tooltip == tooltip; }
|
||||
bool operator!=(const report& o) const { return !(o == *this); }
|
||||
explicit report(const std::string& text) { this->push_back(element(text)); }
|
||||
report(const std::string& text, const std::string& image, const std::string& tooltip) {
|
||||
this->push_back(element(text, image, tooltip));
|
||||
}
|
||||
|
||||
// Convenience functions
|
||||
void add_text(std::stringstream& text, std::stringstream& tooltip);
|
||||
void add_text(const std::string& text, const std::string& tooltip);
|
||||
void set_tooltip(const std::string& tooltip);
|
||||
void add_image(const std::string& image, const std::string& tooltip);
|
||||
void add_image(std::stringstream& image, std::stringstream& tooltip);
|
||||
};
|
||||
|
||||
report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
||||
|
|
Loading…
Add table
Reference in a new issue