The Battle for Wesnoth  1.19.1+dev
help.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
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 /**
17  * @file
18  * Routines for showing the help-dialog.
19  */
20 
21 #define GETTEXT_DOMAIN "wesnoth-help"
22 
23 #include "help/help.hpp"
24 
25 #include "config.hpp" // for config, etc
26 #include "events.hpp" // for draw, pump, etc
27 #include "font/constants.hpp" // for relative_size
29 #include "game_config_manager.hpp"
30 #include "gettext.hpp" // for _
31 #include "help/help_browser.hpp" // for help_browser
32 #include "help/help_impl.hpp" // for hidden_symbol, toplevel, etc
33 #include "key.hpp" // for CKey
34 #include "log.hpp" // for LOG_STREAM, log_domain
35 #include "show_dialog.hpp" // for dialog_frame, etc
36 #include "terrain/terrain.hpp" // for terrain_type
37 #include "units/unit.hpp" // for unit
38 #include "units/types.hpp" // for unit_type, unit_type_data, etc
39 #include "video.hpp" // for game_canvas_size
40 #include "widgets/button.hpp" // for button
41 
42 #include <cassert> // for assert
43 #include <algorithm> // for min
44 #include <vector> // for vector, vector<>::iterator
45 
46 
47 static lg::log_domain log_display("display");
48 #define WRN_DP LOG_STREAM(warn, log_display)
49 
50 static lg::log_domain log_help("help");
51 #define ERR_HELP LOG_STREAM(err, log_help)
52 
53 namespace help {
54 /**
55  * Open a help dialog using a specified toplevel.
56  *
57  * This would allow for complete customization of the contents, although not in a
58  * very easy way. It's used as the internal implementation of the other help*
59  * functions.
60  *
61  *@pre The help_manager must already exist; this is different to the functions
62  * declared in help.hpp, which is why this one's declaration is in the .cpp
63  * file. Because this takes a section as an argument, it wouldn't make sense
64  * for it to call ensure_cache_lifecycle() internally - if the help_manager
65  * doesn't already exist, that would likely destroy the referenced object at
66  * the point that this function exited.
67  */
68 void show_with_toplevel(const section &toplevel, const std::string& show_topic="", int xloc=-1, int yloc=-1);
69 
70 
72 {
73  auto cache_lifecycle = ensure_cache_lifecycle();
75 }
76 
78 {
79  auto cache_lifecycle = ensure_cache_lifecycle();
80  help::show_terrain_help(t.id(), t.hide_help());
81 }
82 
84 {
85  auto cache_lifecycle = ensure_cache_lifecycle();
86  std::string var_id = t.get_cfg()["variation_id"].str();
87  if (var_id.empty())
88  var_id = t.get_cfg()["variation_name"].str();
89  bool hide_help = t.hide_help();
90  bool use_variation = false;
91  if (!var_id.empty()) {
92  const unit_type *parent = unit_types.find(t.id());
93  assert(parent);
94  if (hide_help) {
95  hide_help = parent->hide_help();
96  } else {
97  use_variation = true;
98  }
99  }
100 
101  if (use_variation)
102  help::show_variation_help(t.id(), var_id, hide_help);
103  else
104  help::show_unit_help(t.id(), t.show_variations_in_help(), hide_help);
105 }
106 
108 {
109  assert(!game_cfg);
110  assert(cfg);
111  // This is a global rawpointer in the help:: namespace.
112  game_cfg = cfg;
113 }
114 
115 std::unique_ptr<help_manager> ensure_cache_lifecycle()
116 {
117  // The internals of help_manager are that this global raw pointer is
118  // non-null if and only if an instance of help_manager already exists.
119  if(game_cfg)
120  return nullptr;
121  return std::make_unique<help_manager>(&game_config_manager::get()->game_config());
122 }
123 
125 {
126  game_cfg = nullptr;
129  // These last numbers must be reset so that the content is regenerated.
130  // Upon next start.
133 }
134 
135 /**
136  * Open the help browser, show topic with id show_topic.
137  *
138  * If show_topic is the empty string, the default topic will be shown.
139  */
140 void show_help(const std::string& show_topic, int xloc, int yloc)
141 {
142  auto cache_lifecycle = ensure_cache_lifecycle();
143  show_with_toplevel(default_toplevel, show_topic, xloc, yloc);
144 }
145 
146 /**
147  * Open the help browser, show unit with id unit_id.
148  *
149  * If show_topic is the empty string, the default topic will be shown.
150  */
151 void show_unit_help(const std::string& show_topic, bool has_variations, bool hidden, int xloc, int yloc)
152 {
153  auto cache_lifecycle = ensure_cache_lifecycle();
155  hidden_symbol(hidden) + (has_variations ? ".." : "") + unit_prefix + show_topic, xloc, yloc);
156 }
157 
158 /**
159  * Open the help browser, show terrain with id terrain_id.
160  *
161  * If show_topic is the empty string, the default topic will be shown.
162  */
163 void show_terrain_help(const std::string& show_topic, bool hidden, int xloc, int yloc)
164 {
165  auto cache_lifecycle = ensure_cache_lifecycle();
166  show_with_toplevel(default_toplevel, hidden_symbol(hidden) + terrain_prefix + show_topic, xloc, yloc);
167 }
168 
169 /**
170  * Open the help browser, show the variation of the unit matching.
171  */
172 void show_variation_help(const std::string& unit, const std::string &variation, bool hidden, int xloc, int yloc)
173 {
174  auto cache_lifecycle = ensure_cache_lifecycle();
175  show_with_toplevel(default_toplevel, hidden_symbol(hidden) + variation_prefix + unit + "_" + variation, xloc, yloc);
176 }
177 
178 /**
179  * Open a help dialog using a toplevel other than the default.
180  *
181  * This allows for complete customization of the contents, although not in a
182  * very easy way.
183  */
184 void show_with_toplevel(const section &toplevel_sec,
185  const std::string& show_topic,
186  int xloc, int yloc)
187 {
188  const events::event_context dialog_events_context;
189  const gui::dialog_manager manager;
190 
191  point canvas_size = video::game_canvas_size();
192 
193  const int width = std::min<int>(font::relative_size(1200), canvas_size.x - font::relative_size(20));
194  const int height = std::min<int>(font::relative_size(850), canvas_size.y - font::relative_size(150));
195  const int left_padding = font::relative_size(10);
196  const int right_padding = font::relative_size(10);
197  const int top_padding = font::relative_size(10);
198  const int bot_padding = font::relative_size(10);
199 
200  // If not both locations were supplied, put the dialog in the middle
201  // of the screen.
202  if (yloc <= -1 || xloc <= -1) {
203  xloc = canvas_size.x / 2 - width / 2;
204  yloc = canvas_size.y / 2 - height / 2;
205  }
206  std::vector<gui::button*> buttons_ptr;
207  gui::button close_button_(_("Close"));
208  buttons_ptr.push_back(&close_button_);
209 
211  _("Help"), gui::dialog_frame::default_style, &buttons_ptr
212  );
213  f.layout(xloc, yloc, width, height);
214 
215  // Find all unit_types that have not been constructed yet and fill in the information
216  // needed to create the help topics
218 
219  if (prefs::get().encountered_units().size() != size_t(last_num_encountered_units) ||
220  prefs::get().encountered_terrains().size() != size_t(last_num_encountered_terrains) ||
223  {
224  // More units or terrains encountered, update the contents.
229  }
230  try {
231  help_browser hb(toplevel_sec);
232  hb.set_location(xloc + left_padding, yloc + top_padding);
233  hb.set_width(width - left_padding - right_padding);
234  hb.set_height(height - top_padding - bot_padding);
235  if (!show_topic.empty()) {
236  hb.show_topic(show_topic);
237  }
238  else {
240  }
241  hb.queue_redraw();
242  events::draw();
243  CKey key;
244  for (;;) {
245  events::pump();
247  if (key[SDLK_ESCAPE]) {
248  // Escape quits from the dialog.
249  return;
250  }
251  for (std::vector<gui::button*>::iterator button_it = buttons_ptr.begin();
252  button_it != buttons_ptr.end(); ++button_it) {
253  if ((*button_it)->pressed()) {
254  // There is only one button, close.
255  return;
256  }
257  }
258  // This also rate limits to vsync
259  events::draw();
260  }
261  }
262  catch (const parse_error& e) {
263  ERR_HELP << _("Parse error when parsing help text:") << " " << e.message;
264 #if 0
265  // Displaying in the UI is disabled due to issue #2587
266  std::stringstream msg;
267  msg << _("Parse error when parsing help text:") << " '" << e.message << "'";
269 #endif
270  }
271 }
272 
273 } // End namespace help.
double t
Definition: astarsearch.cpp:63
Class that keeps track of all the keys on the keyboard.
Definition: key.hpp:29
static game_config_manager * get()
A class grating read only view to a vector of config objects, viewed as one config with all children ...
static const style default_style
Definition: show_dialog.hpp:65
void set_width(int w)
Definition: widget.cpp:98
void set_height(int h)
Definition: widget.cpp:103
virtual void set_location(const SDL_Rect &rect)
Definition: widget.cpp:69
void queue_redraw()
Indicate that the widget should be redrawn.
Definition: widget.cpp:215
A help browser widget.
void show_topic(const std::string &topic_id)
Display the topic with the specified identifier.
std::set< t_translation::terrain_code > & encountered_terrains()
std::set< std::string > & encountered_units()
static prefs & get()
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition: types.cpp:1267
void build_all(unit_type::BUILD_STATUS status)
Makes sure the all unit_types are built to the specified level.
Definition: types.cpp:1309
A single unit type that the player may recruit.
Definition: types.hpp:43
@ HELP_INDEXED
Definition: types.hpp:74
bool hide_help() const
Definition: types.cpp:624
This class represents a single unit of a specific type.
Definition: unit.hpp:133
static std::string _(const char *str)
Definition: gettext.hpp:93
const unit_type & type() const
This unit's type, accounting for gender and variation.
Definition: unit.hpp:355
static lg::log_domain log_display("display")
#define ERR_HELP
Definition: help.cpp:51
static lg::log_domain log_help("help")
Standard logging facilities (interface).
void draw()
Trigger a draw cycle.
Definition: events.cpp:751
void raise_process_event()
Definition: events.cpp:756
void pump()
Process all events currently in the queue.
Definition: events.cpp:479
int relative_size(int size)
Definition: constants.hpp:30
Game configuration data as global variables.
Definition: build_info.cpp:61
const bool & debug
Definition: game_config.cpp:92
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
Definition: help.cpp:53
std::string hidden_symbol(bool hidden)
Definition: help_impl.cpp:1626
std::unique_ptr< help_manager > ensure_cache_lifecycle()
Helper function for any of the show_help functions to control the cache's lifecycle; can also be used...
Definition: help.cpp:115
void show_help(const std::string &show_topic, int xloc, int yloc)
Open the help browser, show topic with id show_topic.
Definition: help.cpp:140
int last_num_encountered_units
Definition: help_impl.cpp:72
const std::string unit_prefix
Definition: help_impl.cpp:89
const std::string variation_prefix
Definition: help_impl.cpp:94
void show_variation_help(const std::string &unit, const std::string &variation, bool hidden, int xloc, int yloc)
Open the help browser, show the variation of the unit matching.
Definition: help.cpp:172
void show_terrain_description(const terrain_type &t)
Definition: help.cpp:77
void show_with_toplevel(const section &toplevel, const std::string &show_topic="", int xloc=-1, int yloc=-1)
Open a help dialog using a specified toplevel.
Definition: help.cpp:184
void show_terrain_help(const std::string &show_topic, bool hidden, int xloc, int yloc)
Open the help browser, show terrain with id terrain_id.
Definition: help.cpp:163
void show_unit_help(const std::string &show_topic, bool has_variations, bool hidden, int xloc, int yloc)
Open the help browser, show unit with id unit_id.
Definition: help.cpp:151
void generate_contents()
Generate the help contents from the configurations given to the manager.
Definition: help_impl.cpp:1565
const std::string terrain_prefix
Definition: help_impl.cpp:90
boost::tribool last_debug_state
Definition: help_impl.cpp:74
help::section default_toplevel
Definition: help_impl.cpp:68
void show_unit_description(const unit &u)
Definition: help.cpp:71
const game_config_view * game_cfg
Definition: help_impl.cpp:66
int last_num_encountered_terrains
Definition: help_impl.cpp:73
help::section hidden_sections
Definition: help_impl.cpp:70
const std::string default_show_topic
Definition: help_impl.cpp:87
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
point game_canvas_size()
The size of the game canvas, in drawing coordinates / game pixels.
Definition: video.cpp:434
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
This file contains object "key", which is used to store information about keys while annotation parsi...
help_manager(const game_config_view *game_config)
Definition: help.cpp:107
Thrown when the help system fails to parse something.
Definition: help_impl.hpp:213
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:145
Holds a 2D point.
Definition: point.hpp:25
unit_type_data unit_types
Definition: types.cpp:1486
#define e
#define f