map_label.cpp

Go to the documentation of this file.
00001 /* $Id: map_label.cpp 23842 2008-02-16 08:47:16Z mordante $ */
00002 /*
00003    Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 #include "global.hpp"
00016 
00017 #include "display.hpp"
00018 #include "font.hpp"
00019 #include "language.hpp"
00020 #include "map_label.hpp"
00021 
00022 #include <cassert>
00023 #include <vector>
00024 
00025 namespace {
00026     const size_t max_label_size = 32;
00027 }
00028 
00029 //our definition of map labels being obscured is if the tile is obscured,
00030 //or the tile below is obscured. This is because in the case where the tile
00031 //itself is visible, but the tile below is obscured, the bottom half of the
00032 //tile will still be shrouded, and the label being drawn looks weird
00033 static bool is_shrouded(const display& disp, const gamemap::location& loc)
00034 {
00035     return disp.shrouded(loc) || disp.shrouded(gamemap::location(loc.x,loc.y+1));
00036 }
00037 
00038 map_labels::map_labels(const display& disp,
00039                        const gamemap& map,
00040                        const team* team) :
00041         disp_(disp),
00042         team_(team),
00043         map_(map)
00044 {
00045 }
00046 
00047 map_labels::map_labels(const display& disp,
00048                const config& cfg,
00049                const gamemap& map,
00050                const team* team,
00051                const variable_set *variables) :
00052         disp_(disp),
00053         team_(team),
00054         map_(map)
00055 {
00056     read(cfg, variables);
00057 }
00058 
00059 map_labels::~map_labels()
00060 {
00061     clear_all();
00062 }
00063 
00064 void map_labels::write(config& res) const
00065 {
00066     for (team_label_map::const_iterator labs = labels_.begin(); labs != labels_.end(); ++labs)
00067     {
00068         for(label_map::const_iterator i = labs->second.begin(); i != labs->second.end(); ++i) {
00069             config item;
00070             i->second->write(item);
00071 
00072 
00073             res.add_child("label",item);
00074         }
00075     }
00076 }
00077 
00078 void map_labels::read(const config& cfg, const variable_set *variables)
00079 {
00080     clear_all();
00081 
00082     const config::child_list& items = cfg.get_children("label");
00083     for(config::child_list::const_iterator i = items.begin(); i != items.end(); ++i) {
00084         const gamemap::location loc(**i, variables);
00085         terrain_label* label = new terrain_label(*this, **i, variables);
00086         add_label(loc, label);
00087     }
00088     recalculate_labels();
00089 }
00090 
00091 
00092 size_t map_labels::get_max_chars()
00093 {
00094     return max_label_size;
00095 }
00096 
00097 const terrain_label* map_labels::get_label(const gamemap::location& loc, const std::string& team_name)
00098 {
00099     team_label_map::const_iterator label_map = labels_.find(team_name);
00100     if (label_map != labels_.end()) {
00101         map_labels::label_map::const_iterator itor = label_map->second.find(loc);;  
00102         if (itor != label_map->second.end())
00103             return itor->second;
00104     }
00105     return NULL;
00106 }
00107 
00108 const terrain_label* map_labels::get_label(const gamemap::location& loc)
00109 {
00110     const terrain_label* res = get_label(loc, team_name());
00111     // no such team label, we try global label, except if it's what we just did
00112     // NOTE: This also avoid infinite recursion
00113     if (res == NULL && team_name() != "") {
00114         return get_label(loc, "");
00115     }
00116     return res;
00117 }
00118 
00119 
00120 const display& map_labels::disp() const
00121 {
00122     return disp_;
00123 }
00124 
00125 const std::string& map_labels::team_name() const
00126 {
00127     if (team_)
00128     {
00129         return team_->team_name();
00130     }
00131     static const std::string empty;
00132     return empty;
00133 }
00134 
00135 void map_labels::set_team(const team* team)
00136 {
00137     if ( team_ != team )
00138     {
00139         team_ = team;
00140     }
00141 }
00142 
00143 
00144 const terrain_label* map_labels::set_label(const gamemap::location& loc,
00145                        const std::string& text,
00146                        const std::string team_name,
00147                        const SDL_Color colour)
00148 {
00149     terrain_label* res = 0;
00150     const team_label_map::const_iterator current_label_map = labels_.find(team_name);
00151     label_map::const_iterator current_label;
00152 
00153     if ( current_label_map != labels_.end()
00154             && (current_label = current_label_map->second.find(loc)) != current_label_map->second.end() )
00155     {
00156         // Found old checking if need to erase it
00157         if(text.empty())
00158         {
00159             const_cast<terrain_label*>(current_label->second)->set_text("");
00160             res = new terrain_label("",team_name,loc,*this,colour);
00161             delete current_label->second;
00162             const_cast<label_map&>(current_label_map->second).erase(loc);
00163 
00164             team_label_map::iterator global_label_map = labels_.find("");
00165             label_map::iterator itor;
00166             bool update = false;
00167             if(global_label_map != labels_.end()) {
00168                 itor = global_label_map->second.find(loc);
00169                 update = itor != global_label_map->second.end();
00170             }
00171             if (update)
00172             {
00173                 const_cast<terrain_label*>(itor->second)->recalculate();
00174             }
00175 
00176         }
00177         else
00178         {
00179             const_cast<terrain_label*>(current_label->second)->update_info(text,
00180                                                                            team_name,
00181                                                                             colour);
00182             res = const_cast<terrain_label*>(current_label->second);
00183         }
00184     }
00185     else if(!text.empty())
00186     {
00187         team_label_map::iterator global_label_map = labels_.find("");
00188         label_map::iterator itor;
00189         bool update = false;
00190         if(global_label_map != labels_.end()) {
00191             itor = global_label_map->second.find(loc);
00192             update = itor != global_label_map->second.end();
00193         }
00194 
00195         terrain_label* label = new terrain_label(text,
00196                 team_name,
00197                 loc,
00198                 *this,
00199                 colour);
00200         add_label(loc,label);
00201 
00202         res = label;
00203 
00204         if (update)
00205         {
00206             const_cast<terrain_label*>(itor->second)->recalculate();
00207         }
00208 
00209     }
00210     return res;
00211 }
00212 
00213 void map_labels::add_label(const gamemap::location& loc,
00214     const terrain_label* new_label)
00215 {
00216     team_label_map::const_iterator labs = labels_.find(new_label->team_name());
00217     if(labs == labels_.end())
00218     {
00219         labels_.insert(std::pair<std::string,label_map>(new_label->team_name(), label_map()));
00220         labs = labels_.find(new_label->team_name());
00221 
00222         assert(labs != labels_.end());
00223     }
00224 
00225     const_cast<label_map&>(labs->second).insert(std::pair<gamemap::location,const terrain_label*>(loc,new_label));
00226 }
00227 
00228 void map_labels::clear(const std::string& team_name)
00229 {
00230     team_label_map::iterator i = labels_.find(team_name);
00231     if (i != labels_.end())
00232     {
00233         clear_map(i->second);
00234     }
00235 
00236     i = labels_.find("");
00237     if (i != labels_.end())
00238     {
00239         clear_map(i->second);
00240     }
00241 }
00242 
00243 void map_labels::clear_map(const label_map& m)
00244 {
00245     for (label_map::const_iterator j = m.begin(); j != m.end(); ++j)
00246     {
00247         delete j->second;
00248     }
00249     const_cast<label_map&>(m).clear();
00250 }
00251 
00252 void map_labels::clear_all()
00253 {
00254     for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00255     {
00256         clear_map(i->second);
00257     }
00258     labels_.clear();
00259 }
00260 
00261 void map_labels::scroll(double xmove, double ymove)
00262 {
00263     for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00264     {
00265         for (label_map::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
00266         {
00267             j->second->scroll(xmove, ymove);
00268         }
00269     }
00270 }
00271 
00272 void map_labels::recalculate_labels()
00273 {
00274     for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00275     {
00276         for (label_map::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
00277         {
00278             const_cast<terrain_label*>(j->second)->recalculate();
00279         }
00280     }
00281 }
00282 
00283 bool map_labels::visible_global_label(const gamemap::location& loc) const
00284 {
00285     const team_label_map::const_iterator glabels = labels_.find(team_name());
00286     return glabels == labels_.end()
00287             || glabels->second.find(loc) == glabels->second.end();
00288 }
00289 
00290 void map_labels::recalculate_shroud()
00291 {
00292     for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00293     {
00294         for (label_map::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
00295         {
00296             const_cast<terrain_label*>(j->second)->calculate_shroud();
00297         }
00298     }
00299 }
00300 
00301 
00302 /// creating new label
00303 terrain_label::terrain_label(const std::string& text,
00304                              const std::string& team_name,
00305                              const gamemap::location& loc,
00306                              const map_labels& parent,
00307                              const SDL_Color colour)  :
00308         handle_(0),
00309         text_(text),
00310         team_name_(team_name),
00311         colour_(colour),
00312         parent_(&parent),
00313         loc_(loc)
00314 {
00315     check_text_length();
00316     draw();
00317 }
00318 
00319 terrain_label::terrain_label(const map_labels& parent)  :
00320         handle_(0),
00321         text_(),
00322         team_name_(),
00323         colour_(),
00324         parent_(&parent),
00325         loc_()
00326 {
00327 }
00328 
00329 
00330 /// Load label from config
00331 terrain_label::terrain_label(const map_labels& parent,
00332                  const config& cfg,
00333                  const variable_set *variables) :
00334         handle_(0),
00335         parent_(&parent)
00336 {
00337     read(cfg, variables);
00338     check_text_length();
00339 }
00340 
00341 
00342 terrain_label::~terrain_label()
00343 {
00344     clear();
00345 }
00346 
00347 void terrain_label::read(const config& cfg, const variable_set *variables)
00348 {
00349     loc_ = gamemap::location(cfg, variables);
00350     SDL_Color colour = font::LABEL_COLOUR;
00351     std::string tmp_colour = cfg["colour"];
00352 
00353     text_      = cfg["text"];
00354     team_name_ = cfg["team_name"];
00355 
00356     if (variables)
00357     {
00358         text_ = utils::interpolate_variables_into_string(
00359                 text_, *variables);
00360         team_name_ = utils::interpolate_variables_into_string(
00361                     team_name_, *variables);
00362         tmp_colour = utils::interpolate_variables_into_string(
00363                   tmp_colour, *variables);
00364     }
00365 
00366     if(!tmp_colour.empty()) {
00367         std::vector<Uint32> temp_rgb;
00368         try {
00369             temp_rgb = string2rgb(tmp_colour);
00370         } catch(bad_lexical_cast&) {
00371             //throw config::error(_("Invalid color range: ") + name);
00372         }
00373         if(!temp_rgb.empty()) {
00374             colour = int_to_color(temp_rgb[0]);
00375         }
00376     }
00377     colour_ = colour;
00378 }
00379 
00380 void terrain_label::write(config& cfg) const
00381 {
00382     loc_.write(cfg);
00383     cfg["text"] = text();
00384     cfg["team_name"] = (this->team_name());
00385     cfg["colour"] = cfg_colour();
00386 
00387 }
00388 
00389 const std::string& terrain_label::text() const
00390 {
00391     return text_;
00392 }
00393 
00394 const std::string& terrain_label::team_name() const
00395 {
00396     return team_name_;
00397 }
00398 
00399 const gamemap::location& terrain_label::location() const
00400 {
00401     return loc_;
00402 }
00403 
00404 const SDL_Colour& terrain_label::colour() const
00405 {
00406     return colour_;
00407 }
00408 
00409 const std::string terrain_label::cfg_colour() const
00410 {
00411     std::stringstream buf;
00412     const unsigned int red = static_cast<unsigned int>(colour_.r);
00413     const unsigned int green = static_cast<unsigned int>(colour_.g);
00414     const unsigned int blue = static_cast<unsigned int>(colour_.b);
00415     const unsigned int alpha = static_cast<unsigned int>(colour_.unused);
00416     buf << red << ","
00417             << green << ","
00418             << blue << ","
00419             << alpha;
00420     return buf.str();
00421 }
00422 
00423 void terrain_label::set_text(const std::string& text)
00424 {
00425     text_ = text;
00426 }
00427 
00428 void terrain_label::update_info(const std::string& text,
00429                                 const std::string& team_name,
00430                                 const SDL_Color colour)
00431 {
00432     colour_ = colour;
00433     text_ = text;
00434     check_text_length();
00435     team_name_ = team_name;
00436     draw();
00437 }
00438 
00439 void terrain_label::scroll(const double xmove,
00440                            const double ymove) const
00441 {
00442     if(handle_)
00443     {
00444         font::move_floating_label(handle_,
00445                                   xmove,
00446                                   ymove);
00447     }
00448 }
00449 
00450 void terrain_label::recalculate()
00451 {
00452     draw();
00453 }
00454 
00455 void terrain_label::calculate_shroud() const
00456 {
00457 
00458     if (handle_)
00459     {
00460         font::show_floating_label(handle_,
00461                                   !is_shrouded(parent_->disp(),
00462                                                loc_));
00463     }
00464 }
00465 
00466 void terrain_label::draw()
00467 {
00468     clear();
00469     if (visible())
00470     {
00471 
00472         const gamemap::location loc_nextx(loc_.x+1,loc_.y);
00473         const gamemap::location loc_nexty(loc_.x,loc_.y+1);
00474         const int xloc = (parent_->disp().get_location_x(loc_) +
00475                 parent_->disp().get_location_x(loc_nextx)*2)/3;
00476         const int yloc = parent_->disp().get_location_y(loc_nexty) - font::SIZE_NORMAL;
00477 
00478         cfg_colour();
00479 
00480         handle_ = font::add_floating_label(text_,
00481                                            font::SIZE_NORMAL,
00482                                            colour_,
00483                                            xloc, yloc,
00484                                            0,0,
00485                                            -1,
00486                                            parent_->disp().map_outside_area());
00487 
00488         calculate_shroud();
00489     }
00490 }
00491 
00492 bool terrain_label::visible() const
00493 {
00494     return  parent_->team_name() == team_name_
00495             || (team_name_.empty() && parent_->visible_global_label(loc_));
00496 }
00497 
00498 void terrain_label::check_text_length()
00499 {
00500     // The actual data is wide_strings so test in wide_string mode
00501     // also cutting a wide_string at an arbritary place gives odd 
00502     // problems. 
00503     utils::truncate_as_wstring(text_, parent_->get_max_chars());
00504 }
00505 
00506 void terrain_label::clear()
00507 {
00508     if (handle_)
00509     {
00510         font::remove_floating_label(handle_);
00511         handle_ = 0;
00512     }
00513 }

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs