The Battle for Wesnoth  1.15.1+dev
unit_list.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2018 by the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
14 #define GETTEXT_DOMAIN "wesnoth-lib"
15 
17 
19 #include "gui/core/log.hpp"
20 #include "gui/dialogs/message.hpp"
21 #include "gui/widgets/listbox.hpp"
22 #include "gui/widgets/settings.hpp"
23 #include "gui/widgets/button.hpp"
24 #include "gui/widgets/image.hpp"
25 #include "gui/widgets/label.hpp"
28 #include "gui/widgets/window.hpp"
29 #include "display.hpp"
30 #include "font/text_formatting.hpp"
31 #include "formatter.hpp"
32 #include "units/map.hpp"
33 #include "units/ptr.hpp"
34 #include "units/unit.hpp"
35 
36 #include "utils/functional.hpp"
37 
38 static lg::log_domain log_display("display");
39 #define LOG_DP LOG_STREAM(info, log_display)
40 
41 namespace gui2
42 {
43 namespace dialogs
44 {
45 
46 REGISTER_DIALOG(unit_list)
47 
49  : unit_list_(unit_list)
50  , scroll_to_(scroll_to)
51 {
52 }
53 
54 static std::string format_level_string(const int level)
55 {
56  std::string lvl = std::to_string(level);
57 
58  if(level < 1) {
59  return "<span color='#969696'>" + lvl + "</span>";
60  } else if(level == 1) {
61  return lvl;
62  } else if(level == 2) {
63  return "<b>" + lvl + "</b>";
64  } else { // level must be > 2
65  return"<b><span color='#ffffff'>" + lvl + "</span></b>";
66  }
67 
68 }
69 
70 static std::string format_if_leader(unit_const_ptr u, const std::string& str)
71 {
72  return (*u).can_recruit() ? "<span color='#cdad00'>" + str + "</span>" : str;
73 }
74 
76 {
77  const int moves_left = (*u).movement_left();
78  const int moves_max = (*u).total_movement();
79 
80  std::string color = "#00ff00";
81 
82  if(moves_left == 0) {
83  color = "#ff0000";
84  } else if(moves_left < moves_max) {
85  color = "#ffff00";
86  }
87 
88  return formatter() << "<span color='" << color << "'>" << moves_left << "/" << moves_max << "</span>";
89 }
90 
92 {
93  listbox& list = find_widget<listbox>(&window, "units_list", false);
94 
95  connect_signal_notify_modified(list, std::bind(&unit_list::list_item_clicked, this, std::ref(window)));
96 
97  list.clear();
98 
99  window.keyboard_capture(&list);
100 
101  for(const unit_const_ptr& unit : unit_list_) {
102  std::map<std::string, string_map> row_data;
103  string_map column;
104 
105  column["use_markup"] = "true";
106 
107  column["label"] = format_if_leader(unit, unit->type_name());
108  row_data.emplace("unit_type", column);
109 
110  const std::string& name = !unit->name().empty() ? format_if_leader(unit, unit->name().str()) : font::unicode_en_dash;
111  column["label"] = name;
112  row_data.emplace("unit_name", column);
113 
114  column["label"] = format_movement_string(unit);
115  row_data.emplace("unit_moves", column);
116 
117  std::stringstream hp_str;
118  hp_str << font::span_color(unit->hp_color()) << unit->hitpoints() << "/" << unit->max_hitpoints() << "</span>";
119 
120  column["label"] = hp_str.str();
121  row_data.emplace("unit_hp", column);
122 
123  column["label"] = format_level_string(unit->level());
124  row_data.emplace("unit_level", column);
125 
126  std::stringstream exp_str;
127  exp_str << font::span_color(unit->xp_color());
128  if(unit->can_advance()) {
129  exp_str << unit->experience() << "/" << unit->max_experience();
130  } else {
131  exp_str << font::unicode_en_dash;
132  }
133  exp_str << "</span>";
134 
135  column["label"] = exp_str.str();
136  row_data.emplace("unit_experience", column);
137 
138  column["label"] = utils::join(unit->trait_names(), ", ");
139  row_data.emplace("unit_traits", column);
140 
141  grid* row_grid = &list.add_row(row_data);
142 
143  // NOTE: this needs to be done *after* the row is added
144  // TODO: show custom statuses
146  find_widget<image>(row_grid, "unit_status_petrified", false).set_visible(widget::visibility::invisible);
147  }
148 
150  find_widget<image>(row_grid, "unit_status_poisoned", false).set_visible(widget::visibility::invisible);
151  }
152 
154  find_widget<image>(row_grid, "unit_status_slowed", false).set_visible(widget::visibility::invisible);
155  }
156 
157  if(!unit->invisible(unit->get_location(), false)) {
158  find_widget<image>(row_grid, "unit_status_invisible", false).set_visible(widget::visibility::invisible);
159  }
160  }
161 
162  list.register_translatable_sorting_option(0, [this](const int i) { return unit_list_[i]->type_name().str(); });
163  list.register_translatable_sorting_option(1, [this](const int i) { return unit_list_[i]->name().str(); });
164  list.register_sorting_option(2, [this](const int i) { return unit_list_[i]->movement_left(); });
165  list.register_sorting_option(3, [this](const int i) { return unit_list_[i]->hitpoints(); });
166  list.register_sorting_option(4, [this](const int i) {
167  const unit& u = *unit_list_[i];
168  return std::make_tuple(u.level(), -static_cast<int>(u.experience_to_advance()));
169  });
170  list.register_sorting_option(5, [this](const int i) { return unit_list_[i]->experience(); });
171  list.register_translatable_sorting_option(6, [this](const int i) {
172  return !unit_list_[i]->trait_names().empty() ? unit_list_[i]->trait_names().front().str() : ""; });
173 
174  list_item_clicked(window);
175 }
176 
178 {
179  const int selected_row
180  = find_widget<listbox>(&window, "units_list", false).get_selected_row();
181 
182  if(selected_row == -1) {
183  return;
184  }
185 
186  find_widget<unit_preview_pane>(&window, "unit_details", false)
187  .set_displayed_unit(*unit_list_[selected_row].get());
188 }
189 
191 {
192  if(get_retval() == retval::OK) {
193  const int selected_row = find_widget<listbox>(&window, "units_list", false).get_selected_row();
194 
195  scroll_to_ = unit_list_[selected_row]->get_location();
196  }
197 }
198 
200 {
202  map_location scroll_to;
203 
204  const unit_map& units = gui.get_units();
205  for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
206  if(i->side() != gui.viewing_side()) {
207  continue;
208  }
209 
210  unit_list.push_back(i.get_shared_ptr());
211  }
212 
213  if(unit_list::execute(unit_list, scroll_to)) {
214  gui.scroll_to_tile(scroll_to, display::WARP);
215  gui.select_hex(scroll_to);
216  }
217 }
218 
219 } // namespace dialogs
220 } // namespace gui2
Define the common log macros for the gui toolkit.
boost::intrusive_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:30
unit_list(unit_ptr_vector &unit_list, map_location &scroll_to)
Definition: unit_list.cpp:48
virtual void select_hex(map_location hex)
Definition: display.cpp:1611
unit_iterator end()
Definition: map.hpp:415
This class represents a single unit of a specific type.
Definition: unit.hpp:99
virtual void post_show(window &window) override
Inherited from modal_dialog.
Definition: unit_list.cpp:190
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
bool get_state(const std::string &state) const
Check if the unit is affected by a status effect.
Definition: unit.cpp:1340
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:460
This file contains the window object, this object is a top level container which has the event manage...
void show_unit_list(display &gui)
Definition: unit_list.cpp:199
General purpose widgets.
unit_iterator begin()
Definition: map.hpp:405
The unit is poisoned - it loses health each turn.
Definition: unit.hpp:820
const unit_map & get_units() const
Definition: display.hpp:121
int viewing_side() const
Definition: display.hpp:103
void list_item_clicked(window &window)
Callbacks.
Definition: unit_list.cpp:177
The unit is petrified - it cannot move or be attacked.
Definition: unit.hpp:821
void register_translatable_sorting_option(const int col, translatable_sorter_func_t f)
Registers a special sorting function specifically for translatable values.
Definition: listbox.cpp:632
static std::string format_movement_string(unit_const_ptr u)
Definition: unit_list.cpp:75
virtual void pre_show(window &window) override
Inherited from modal_dialog.
Definition: unit_list.cpp:91
map_location & scroll_to_
Definition: unit_list.hpp:55
Generic file dialog.
Definition: field-fwd.hpp:22
color_t hp_color() const
Color for this unit&#39;s current hitpoints.
Definition: unit.cpp:1121
unsigned int experience_to_advance() const
The number of experience points this unit needs to level up, or 0 if current XP > max XP...
Definition: unit.hpp:502
The listbox class.
Definition: listbox.hpp:40
static const char * name(const std::vector< SDL_Joystick *> &joysticks, const std::size_t index)
Definition: joystick.cpp:48
static std::string format_level_string(const int level)
Definition: unit_list.cpp:54
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
Base container class.
Definition: grid.hpp:30
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:248
The unit is slowed - it moves slower and does less damage.
Definition: unit.hpp:819
This file contains the settings handling of the widget library.
std::ostringstream wrapper.
Definition: formatter.hpp:38
void clear()
Removes all the rows in the listbox, clearing it.
Definition: listbox.cpp:125
color_t xp_color() const
Color for this unit&#39;s XP.
Definition: unit.cpp:1131
const t_string & name() const
Gets this unit&#39;s translatable display name.
Definition: unit.hpp:367
static std::string format_if_leader(unit_const_ptr u, const std::string &str)
Definition: unit_list.cpp:70
int max_experience() const
The max number of experience points this unit can have.
Definition: unit.hpp:490
int level() const
The current level of this unit.
Definition: unit.hpp:520
map_display and display: classes which take care of displaying the map and game-data on the screen...
int moves_left
Definition: pathfind.cpp:161
const std::vector< t_string > & trait_names() const
Gets the names of the currently registered traits.
Definition: unit.hpp:1036
const t_string & type_name() const
Gets the translatable name of this unit&#39;s type.
Definition: unit.hpp:333
Various uncategorised dialogs.
Encapsulates the map of the game.
Definition: location.hpp:42
unit_ptr_vector & unit_list_
Definition: unit_list.hpp:53
bool invisible(const map_location &loc, bool see_all=true) const
Definition: unit.cpp:2417
static lg::log_domain log_display("display")
std::size_t i
Definition: function.cpp:933
const std::string unicode_en_dash
Definition: constants.cpp:39
void scroll_to_tile(const map_location &loc, SCROLL_TYPE scroll_type=ONSCREEN, bool check_fogged=true, bool force=true)
Scroll such that location loc is on-screen.
Definition: display.cpp:2182
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:466
The user set the widget invisible, that means:
std::vector< unit_const_ptr > unit_ptr_vector
Definition: unit_list.hpp:33
std::map< std::string, t_string > string_map
Definition: widget.hpp:24
grid & add_row(const string_map &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Definition: listbox.cpp:66
bool empty() const
Definition: tstring.hpp:182
int experience() const
The current number of experience points this unit has.
Definition: unit.hpp:484
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1266
bool can_advance() const
Checks whether this unit has any options to advance to.
Definition: unit.hpp:232
Container associating units to locations.
Definition: map.hpp:99
Dialog was closed with the OK button.
Definition: retval.hpp:34
static bool execute(unit_ptr_vector &units, map_location &scroll_to)
Definition: unit_list.hpp:42
void register_sorting_option(const int col, const Func &f)
Definition: listbox.hpp:269
const std::string & str() const
Definition: tstring.hpp:186
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:63