The Battle for Wesnoth  1.17.12+dev
label.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2022
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include "map/label.hpp"
17 #include "color.hpp"
18 #include "display.hpp"
19 #include "floating_label.hpp"
20 #include "formula/string_utils.hpp"
21 #include "game_board.hpp"
22 #include "game_data.hpp"
23 #include "resources.hpp"
24 #include "tooltips.hpp"
25 
26 /**
27  * Our definition of map labels being obscured is if the tile is obscured,
28  * or the tile below is obscured. This is because in the case where the tile
29  * itself is visible, but the tile below is obscured, the bottom half of the
30  * tile will still be shrouded, and the label being drawn looks weird.
31  */
32 inline bool is_shrouded(const display* disp, const map_location& loc)
33 {
34  return disp->shrouded(loc) || disp->shrouded(loc.get_direction(map_location::SOUTH));
35 }
36 
37 /**
38  * Rather simple test for a hex being fogged.
39  * This only exists because is_shrouded() does. (The code looks nicer if
40  * the test for being fogged looks similar to the test for being shrouded.)
41  */
42 inline bool is_fogged(const display* disp, const map_location& loc)
43 {
44  return disp->fogged(loc);
45 }
46 
48  : team_(team)
49  , labels_()
50  , enabled_(true)
51  , categories_dirty(true)
52 {
53 }
54 
56  : team_(other.team_)
57  , labels_()
58  , enabled_(true)
59 {
60  config cfg;
61  other.write(cfg);
62  read(cfg);
63 }
64 
66 {
67  clear_all();
68 }
69 
71 {
72  if(this != &other) {
73  this->~map_labels();
74  new(this) map_labels(other);
75  }
76 
77  return *this;
78 }
79 
80 void map_labels::write(config& res) const
81 {
82  for(const auto& group : labels_) {
83  for(const auto& label : group.second) {
84  config item;
85  label.second.write(item);
86 
87  res.add_child("label", std::move(item));
88  }
89  }
90 }
91 
92 void map_labels::read(const config& cfg)
93 {
94  clear_all();
95 
96  for(const config& i : cfg.child_range("label")) {
97  add_label(*this, i);
98  }
99 
101 }
102 
104 {
105  auto label_map = labels_.find(team_name);
106  if(label_map != labels_.end()) {
107  auto itor = label_map->second.find(loc);
108  if(itor != label_map->second.end()) {
109  return &itor->second;
110  }
111  }
112 
113  return nullptr;
114 }
115 
117 {
118  const terrain_label* res = get_label(loc, team_name());
119 
120  // No such team label. Try to find global label, except if that's what we just did.
121  // NOTE: This also avoid infinite recursion
122  if(res == nullptr && !team_name().empty()) {
123  return get_label(loc, "");
124  }
125 
126  return res;
127 }
128 
129 const std::string& map_labels::team_name() const
130 {
131  if(team_) {
132  return team_->team_name();
133  }
134 
135  static const std::string empty;
136  return empty;
137 }
138 
140 {
141  if(team_ != team) {
142  team_ = team;
143  categories_dirty = true;
144  }
145 }
146 
148  const t_string& text,
149  const int creator,
150  const std::string& team_name,
151  const color_t color,
152  const bool visible_in_fog,
153  const bool visible_in_shroud,
154  const bool immutable,
155  const std::string& category,
156  const t_string& tooltip)
157 {
158  terrain_label* res = nullptr;
159 
160  // See if there is already a label in this location for this team.
161  // (We do not use get_label_private() here because we might need
162  // the label_map as well as the terrain_label.)
163  team_label_map::iterator current_label_map = labels_.find(team_name);
164  label_map::iterator current_label;
165 
166  if(current_label_map != labels_.end() &&
167  (current_label = current_label_map->second.find(loc)) != current_label_map->second.end())
168  {
169  // Found old checking if need to erase it
170  if(text.str().empty()) {
171  // Erase the old label.
172  current_label_map->second.erase(current_label);
173 
174  // Restore the global label in the same spot, if any.
175  if(terrain_label* global_label = get_label_private(loc, "")) {
176  global_label->recalculate();
177  }
178  } else {
179  current_label->second.update_info(
180  text, creator, tooltip, team_name, color, visible_in_fog, visible_in_shroud, immutable, category);
181 
182  res = &current_label->second;
183  }
184  } else if(!text.str().empty()) {
185  // See if we will be replacing a global label.
186  terrain_label* global_label = get_label_private(loc, "");
187 
188  // Add the new label.
189  res = add_label(
190  *this, text, creator, team_name, loc, color, visible_in_fog, visible_in_shroud, immutable, category, tooltip);
191 
192  // Hide the old label.
193  if(global_label != nullptr) {
194  global_label->recalculate();
195  }
196  }
197 
198  categories_dirty = true;
199  return res;
200 }
201 
202 template<typename... T>
204 {
205  categories_dirty = true;
206 
207  terrain_label t(std::forward<T>(args)...);
208  return &(*labels_[t.team_name()].emplace(t.location(), std::move(t)).first).second;
209 }
210 
211 void map_labels::clear(const std::string& team_name, bool force)
212 {
213  team_label_map::iterator i = labels_.find(team_name);
214  if(i != labels_.end()) {
215  clear_map(i->second, force);
216  }
217 
218  i = labels_.find("");
219  if(i != labels_.end()) {
220  clear_map(i->second, force);
221  }
222 
223  categories_dirty = true;
224 }
225 
226 void map_labels::clear_map(label_map& m, bool force)
227 {
228  label_map::iterator i = m.begin();
229  while(i != m.end()) {
230  if(!i->second.immutable() || force) {
231  m.erase(i++);
232  } else {
233  ++i;
234  }
235  }
236 
237  categories_dirty = true;
238 }
239 
241 {
242  labels_.clear();
243 }
244 
246 {
247  for(auto& m : labels_) {
248  for(auto& l : m.second) {
249  l.second.recalculate();
250  }
251  }
252 }
253 
254 void map_labels::enable(bool is_enabled)
255 {
256  if(is_enabled != enabled_) {
257  enabled_ = is_enabled;
259  }
260 }
261 
262 /**
263  * Returns whether or not a global (non-team) label can be shown at a
264  * specified location.
265  * (Global labels are suppressed in favor of team labels.)
266  */
268 {
269  if(team_ == nullptr) {
270  // We're in the editor. All global labels can be shown.
271  return true;
272  }
273 
274  const team_label_map::const_iterator glabels = labels_.find(team_name());
275  return glabels == labels_.end() || glabels->second.find(loc) == glabels->second.end();
276 }
277 
279 {
280  for(auto& m : labels_) {
281  for(auto& l : m.second) {
282  l.second.calculate_shroud();
283  }
284  }
285 }
286 
287 const std::vector<std::string>& map_labels::all_categories() const
288 {
289  if(categories_dirty) {
290  categories_dirty = false;
291  categories.clear();
292  categories.push_back("team");
293 
294  for(std::size_t i = 1; i <= resources::gameboard->teams().size(); i++) {
295  categories.push_back("side:" + std::to_string(i));
296  }
297 
298  std::set<std::string> unique_cats;
299  for(const auto& m : labels_) {
300  for(const auto& l : m.second) {
301  if(l.second.category().empty()) {
302  continue;
303  }
304 
305  unique_cats.insert("cat:" + l.second.category());
306  }
307  }
308 
309  std::copy(unique_cats.begin(), unique_cats.end(), std::back_inserter(categories));
310  }
311 
312  return categories;
313 }
314 
315 /** Create a new label. */
317  const t_string& text,
318  const int creator,
319  const std::string& team_name,
320  const map_location& loc,
321  const color_t color,
322  const bool visible_in_fog,
323  const bool visible_in_shroud,
324  const bool immutable,
325  const std::string& category,
326  const t_string& tooltip)
327  : handle_(0)
328  , text_(text)
329  , tooltip_(tooltip)
330  , category_(category)
331  , team_name_(team_name)
332  , visible_in_fog_(visible_in_fog)
333  , visible_in_shroud_(visible_in_shroud)
334  , immutable_(immutable)
335  , creator_(creator)
336  , color_(color)
337  , parent_(&parent)
338  , loc_(loc)
339 {
340  recalculate();
341 }
342 
343 /** Load label from config. */
345  : handle_(0)
346  , tooltip_handle_(0)
347  , text_()
348  , tooltip_()
349  , team_name_()
350  , visible_in_fog_(true)
351  , visible_in_shroud_(false)
352  , immutable_(true)
353  , creator_(-1)
354  , color_()
355  , parent_(&parent)
356  , loc_()
357 {
358  read(cfg);
359 }
360 
362  : handle_(l.handle_)
364  , text_(l.text_)
365  , tooltip_(l.tooltip_)
366  , category_(l.category_)
371  , creator_(l.creator_)
372  , color_(l.color_)
373  , parent_(l.parent_)
374  , loc_(l.loc_)
375 {
376  l.handle_ = 0;
377  l.tooltip_handle_ = 0;
378 }
379 
381 {
382  clear();
383 }
384 
385 void terrain_label::read(const config& cfg)
386 {
387  const variable_set& vs = *resources::gamedata;
388 
389  loc_ = map_location(cfg, &vs);
391 
392  std::string tmp_color = cfg["color"];
393 
394  text_ = cfg["text"];
395  tooltip_ = cfg["tooltip"];
396  team_name_ = cfg["team_name"].str();
397  visible_in_fog_ = cfg["visible_in_fog"].to_bool(true);
398  visible_in_shroud_ = cfg["visible_in_shroud"].to_bool();
399  immutable_ = cfg["immutable"].to_bool(true);
400  category_ = cfg["category"].str();
401 
402  int side = cfg["side"].to_int(-1);
403  if(side >= 0) {
404  creator_ = side - 1;
405  } else if(cfg["side"].str() == "current") {
406  config::attribute_value current_side = vs.get_variable_const("side_number");
407  if(!current_side.empty()) {
408  creator_ = current_side.to_int();
409  }
410  }
411 
412  // Not moved to rendering, as that would depend on variables at render-time
414 
416  tmp_color = utils::interpolate_variables_into_string(tmp_color, vs);
417 
418  if(!tmp_color.empty()) {
419  try {
420  color = color_t::from_rgb_string(tmp_color);
421  } catch(const std::invalid_argument&) {
422  // Prior to the color_t conversion, labels were written to savefiles with an alpha key, despite alpha not
423  // being accepted in color=. Because of this, this enables the loading of older saves without an exception
424  // throwing.
425  color = color_t::from_rgba_string(tmp_color);
426  }
427  }
428 
429  color_ = color;
430 }
431 
432 void terrain_label::write(config& cfg) const
433 {
434  loc_.write(cfg);
435 
436  cfg["text"] = text();
437  cfg["tooltip"] = tooltip();
438  cfg["team_name"] = (this->team_name());
439  cfg["color"] = color_.to_rgb_string();
440  cfg["visible_in_fog"] = visible_in_fog_;
441  cfg["visible_in_shroud"] = visible_in_shroud_;
442  cfg["immutable"] = immutable_;
443  cfg["category"] = category_;
444  cfg["side"] = creator_ + 1;
445 }
446 
448  const int creator,
449  const t_string& tooltip,
450  const std::string& team_name,
451  const color_t color)
452 {
453  color_ = color;
454  text_ = text;
455  tooltip_ = tooltip;
457  creator_ = creator;
458 
459  recalculate();
460 }
461 
463  const int creator,
464  const t_string& tooltip,
465  const std::string& team_name,
466  const color_t color,
467  const bool visible_in_fog,
468  const bool visible_in_shroud,
469  const bool immutable,
470  const std::string& category)
471 {
476 
477  update_info(text, creator, tooltip, team_name, color);
478 }
479 
481 {
482  if(handle_) {
484  }
485 
486  if(tooltip_.empty() || hidden()) {
488  tooltip_handle_ = 0;
489  return;
490  }
491 
492  // tooltips::update_tooltip(tooltip_handle, get_rect(), tooltip_.str(), "", true);
493 
494  if(tooltip_handle_) {
496  } else {
498  }
499 }
500 
501 SDL_Rect terrain_label::get_rect() const
502 {
503  SDL_Rect rect {0, 0, 0, 0};
504 
506  if(!disp) {
507  return rect;
508  }
509 
510  int hex_size = disp->hex_size();
511 
512  rect.x = disp->get_location_x(loc_) + hex_size / 4;
513  rect.y = disp->get_location_y(loc_);
514  rect.h = disp->hex_size();
515  rect.w = disp->hex_size() - hex_size / 2;
516 
517  return rect;
518 }
519 
520 static int scale_to_map_zoom(int val)
521 {
522  return val * std::max(1.0, display::get_zoom_factor());
523 }
524 
526 {
528  if(!disp) {
529  return;
530  }
531 
532  if(text_.empty() && tooltip_.empty()) {
533  return;
534  }
535 
536  clear();
537 
538  if(!viewable(*disp)) {
539  return;
540  }
541 
542  // Note: the y part of loc_nextx is not used at all.
545  const int xloc = (disp->get_location_x(loc_) + disp->get_location_x(loc_nextx) * 2) / 3;
546  const int yloc = disp->get_location_y(loc_nexty) - scale_to_map_zoom(font::SIZE_NORMAL);
547 
548  // If a color is specified don't allow to override it with markup. (prevents faking map labels for example)
549  // FIXME: @todo Better detect if it's team label and not provided by the scenario.
550  bool use_markup = color_ == font::LABEL_COLOR;
551 
552  font::floating_label flabel(text_.str());
554  flabel.set_color(color_);
555  flabel.set_position(xloc, yloc);
556  flabel.set_clip_rect(disp->map_outside_area());
557  flabel.set_width(scale_to_map_zoom(font::SIZE_NORMAL * 13));
558  flabel.set_height(scale_to_map_zoom(font::SIZE_NORMAL * 4));
559  flabel.set_scroll_mode(font::ANCHOR_LABEL_MAP);
560  flabel.use_markup(use_markup);
561 
563 
565 }
566 
567 /**
568  * This is a lightweight test used to see if labels are revealed as a result
569  * of unit actions (i.e. fog/shroud clearing). It should not contain any tests
570  * that are invariant during unit movement (disregarding potential WML events);
571  * those belong in visible().
572  */
574 {
576  if(!disp) {
577  return false;
578  }
579 
580  // Respect user's label preferences
581  std::string category = "cat:" + category_;
582  std::string creator = "side:" + std::to_string(creator_ + 1);
583  const std::vector<std::string>& hidden_categories = disp->get_disp_context().hidden_label_categories();
584 
585  if(std::find(hidden_categories.begin(), hidden_categories.end(), category) != hidden_categories.end()) {
586  return true;
587  }
588 
589  if(creator_ >= 0 &&
590  std::find(hidden_categories.begin(), hidden_categories.end(), creator) != hidden_categories.end())
591  {
592  return true;
593  }
594 
595  if(!team_name().empty() &&
596  std::find(hidden_categories.begin(), hidden_categories.end(), "team") != hidden_categories.end())
597  {
598  return true;
599  }
600 
601  // Fog can hide some labels.
602  if(!visible_in_fog_ && is_fogged(disp, loc_)) {
603  return true;
604  }
605 
606  // Shroud can hide some labels.
607  if(!visible_in_shroud_ && is_shrouded(disp, loc_)) {
608  return true;
609  }
610 
611  return false;
612 }
613 
614 /**
615  * This is a test used to see if we should bother with the overhead of actually
616  * creating a label. Conditions that can change during unit movement (disregarding
617  * potential WML events) should not be listed here; they belong in hidden().
618  */
619 bool terrain_label::viewable(const display& disp) const
620 {
621  if(!parent_->enabled()) {
622  return false;
623  }
624 
625  // In the editor, all labels are viewable.
626  if(disp.in_editor()) {
627  return true;
628  }
629 
630  // Observers are not privvy to team labels.
631  const bool can_see_team_labels = !disp.get_disp_context().is_observer();
632 
633  // Global labels are shown unless covered by a team label.
634  if(team_name_.empty()) {
635  return !can_see_team_labels || parent_->visible_global_label(loc_);
636  }
637 
638  // Team labels are only shown to members of the team.
639  return can_see_team_labels && parent_->team_name() == team_name_;
640 }
641 
643 {
644  if(handle_) {
646  handle_ = 0;
647  }
648 
649  if(tooltip_handle_) {
651  tooltip_handle_ = 0;
652  }
653 }
const map_labels * parent_
Definition: label.hpp:230
bool empty() const
Tests for an attribute that either was never set or was set to "".
void recalculate_shroud()
Definition: label.cpp:278
const map_location & location() const
Definition: label.hpp:179
const color_t & color() const
Definition: label.hpp:184
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:98
int creator_
Definition: label.hpp:226
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
map_labels & operator=(const map_labels &)
Definition: label.cpp:70
void remove_floating_label(int handle, int fadeout)
removes the floating label given by &#39;handle&#39; from the screen
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:86
static int hex_size()
Function which returns the size of a hex in pixels (from top tip to bottom tip or left edge to right ...
Definition: display.hpp:253
int add_tooltip(const SDL_Rect &origin, const std::string &message, const std::string &action)
Definition: tooltips.cpp:237
void write(config &res) const
Definition: label.cpp:432
const std::vector< std::string > & all_categories() const
Definition: label.cpp:287
Variant for storing WML attributes.
static double get_zoom_factor()
Returns the current zoom factor.
Definition: display.hpp:256
const std::string & category() const
Definition: label.hpp:159
void show_floating_label(int handle, bool value)
hides or shows a floating label
t_string tooltip_
Definition: label.hpp:218
const t_string & tooltip() const
Definition: label.hpp:144
bool visible_in_fog_
Definition: label.hpp:223
const t_string & text() const
Definition: label.hpp:139
bool is_fogged(const display *disp, const map_location &loc)
Rather simple test for a hex being fogged.
Definition: label.cpp:42
child_itors child_range(config_key_type key)
Definition: config.cpp:344
void remove_tooltip(int id)
Definition: tooltips.cpp:227
terrain_label(const terrain_label &)=delete
Delete copy ctor and assignment ops.
std::string to_rgb_string() const
Returns the stored color as an "R,G,B" string.
Definition: color.cpp:107
bool is_shrouded(const display *disp, const map_location &loc)
Our definition of map labels being obscured is if the tile is obscured, or the tile below is obscured...
Definition: label.cpp:32
const std::string & team_name() const
Definition: label.hpp:154
const color_t LABEL_COLOR
bool visible_in_shroud() const
Definition: label.hpp:169
int creator() const
Definition: label.hpp:149
team_label_map labels_
Definition: label.hpp:99
void set_font_size(int font_size)
void rect(const SDL_Rect &rect)
Draw a rectangle.
Definition: draw.cpp:141
game_data * gamedata
Definition: resources.cpp:23
const int SIZE_NORMAL
Definition: constants.cpp:20
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
Definition: location.cpp:360
map_location loc_
virtual bool in_editor() const
Definition: display.hpp:204
bool viewable(const display &disp) const
This is a test used to see if we should bother with the overhead of actually creating a label...
Definition: label.cpp:619
bool visible_in_shroud_
Definition: label.hpp:224
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:75
bool enabled() const
Definition: label.hpp:67
std::map< map_location, terrain_label > label_map
Definition: label.hpp:35
std::vector< std::string > categories
Definition: label.hpp:102
std::string label
What to show in the filter&#39;s drop-down list.
Definition: manager.cpp:217
const terrain_label * set_label(const map_location &loc, const t_string &text, const int creator=-1, const std::string &team="", const color_t color=font::NORMAL_COLOR, const bool visible_in_fog=true, const bool visible_in_shroud=false, const bool immutable=false, const std::string &category="", const t_string &tooltip="")
Definition: label.cpp:147
void clear(const std::string &, bool force)
Definition: label.cpp:211
map_labels(const map_labels &)
Definition: label.cpp:55
const team * team_
Definition: label.hpp:97
game_board * gameboard
Definition: resources.cpp:21
void clear()
Definition: label.cpp:642
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:58
void write(config &res) const
Definition: label.cpp:80
std::string category_
Definition: label.hpp:220
void enable(bool is_enabled)
Definition: label.cpp:254
static int scale_to_map_zoom(int val)
Definition: label.cpp:520
map_display and display: classes which take care of displaying the map and game-data on the screen...
color_t color_
Definition: label.hpp:228
const terrain_label * get_label(const map_location &loc, const std::string &team_name) const
Definition: label.hpp:48
bool immutable_
Definition: label.hpp:225
bool enabled_
Definition: label.hpp:100
int tooltip_handle_
Definition: label.hpp:215
bool visible_global_label(const map_location &) const
Returns whether or not a global (non-team) label can be shown at a specified location.
Definition: label.cpp:267
bool fogged(const map_location &loc) const
Returns true if location (x,y) is covered in fog.
Definition: display.cpp:726
Encapsulates the map of the game.
Definition: location.hpp:38
void set_team(const team *)
Definition: label.cpp:139
bool shrouded(const map_location &loc) const
Returns true if location (x,y) is covered in shroud.
Definition: display.cpp:721
~map_labels()
Definition: label.cpp:65
void recalculate_labels()
Definition: label.cpp:245
SDL_Rect get_rect() const
Definition: label.cpp:501
bool visible_in_fog() const
Definition: label.hpp:164
std::size_t i
Definition: function.cpp:968
bool is_observer() const
Check if we are an observer in this game.
void read(const config &cfg)
Definition: label.cpp:385
void clear_map(label_map &, bool)
Definition: label.cpp:226
int get_location_y(const map_location &loc) const
Definition: display.cpp:736
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:46
const display_context & get_disp_context() const
Definition: display.hpp:178
int add_floating_label(const floating_label &flabel)
add a label floating on the screen above everything else.
const std::string & team_name() const
Definition: label.cpp:129
config & add_child(config_key_type key)
Definition: config.cpp:514
void read(const config &cfg)
Definition: label.cpp:92
std::string team_name_
Definition: label.hpp:221
bool empty() const
Definition: tstring.hpp:187
int get_location_x(const map_location &loc) const
Functions to get the on-screen positions of hexes.
Definition: display.cpp:731
To store label data Class implements logic for rendering.
Definition: label.hpp:110
void recalculate()
Definition: label.cpp:525
virtual config::attribute_value get_variable_const(const std::string &id) const =0
terrain_label * add_label(T &&... args)
Definition: label.cpp:203
double t
Definition: astarsearch.cpp:65
t_string text_
Definition: label.hpp:217
~terrain_label()
Definition: label.cpp:380
bool hidden() const
This is a lightweight test used to see if labels are revealed as a result of unit actions (i...
Definition: label.cpp:573
rect map_outside_area() const
Returns the available area for a map, this may differ from the above.
Definition: display.cpp:564
void calculate_shroud()
Definition: label.cpp:480
void clear_all()
Definition: label.cpp:240
bool immutable() const
Definition: label.hpp:174
virtual const std::vector< std::string > & hidden_label_categories() const =0
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
static color_t from_rgba_string(const std::string &c)
Creates a new color_t object from a string variable in "R,G,B,A" format.
Definition: color.cpp:21
const std::string & str() const
Definition: tstring.hpp:191
t_string interpolate_variables_into_tstring(const t_string &tstr, const variable_set &variables)
Function that does the same as the above, for t_stringS.
bool update_tooltip(int id, const SDL_Rect &origin, const std::string &message)
Definition: tooltips.cpp:205
static color_t from_rgb_string(const std::string &c)
Creates a new opaque color_t object from a string variable in "R,G,B" format.
Definition: color.cpp:42
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
void update_info(const t_string &, const int creator, const t_string &, const std::string &, const color_t)
Definition: label.cpp:447
map_location loc_
Definition: label.hpp:231
const std::string & team_name() const
Definition: team.hpp:284
terrain_label * get_label_private(const map_location &loc, const std::string &team_name)
Definition: label.cpp:103
bool categories_dirty
Definition: label.hpp:103
std::string tooltip
Shown when hovering over an entry in the filter&#39;s drop-down list.
Definition: manager.cpp:219
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:414
void write(config &cfg) const
Definition: location.cpp:212