The Battle for Wesnoth  1.17.0-dev
help.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2021
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 raise_draw_event, pump, etc
27 #include "font/constants.hpp" // for relative_size
28 #include "preferences/game.hpp"
29 #include "game_config_manager.hpp"
30 #include "gettext.hpp" // for _
32 #include "help/help_browser.hpp" // for help_browser
33 #include "help/help_impl.hpp" // for hidden_symbol, toplevel, etc
34 #include "key.hpp" // for CKey
35 #include "log.hpp" // for LOG_STREAM, log_domain
36 #include "sdl/surface.hpp" // for surface
37 #include "show_dialog.hpp" // for dialog_frame, etc
38 #include "terrain/terrain.hpp" // for terrain_type
39 #include "units/unit.hpp" // for unit
40 #include "units/types.hpp" // for unit_type, unit_type_data, etc
41 #include "video.hpp" // for CVideo, resize_lock
42 #include "widgets/button.hpp" // for button
43 
44 #include <cassert> // for assert
45 #include <algorithm> // for min
46 #include <ostream> // for basic_ostream, operator<<, etc
47 #include <vector> // for vector, vector<>::iterator
48 #include <SDL2/SDL.h>
49 
50 
51 static lg::log_domain log_display("display");
52 #define WRN_DP LOG_STREAM(warn, log_display)
53 
54 static lg::log_domain log_help("help");
55 #define ERR_HELP LOG_STREAM(err, log_help)
56 
57 namespace help {
58 /**
59  * Open a help dialog using a specified toplevel.
60  *
61  * This would allow for complete customization of the contents, although not in a
62  * very easy way. It's used as the internal implementation of the other help*
63  * functions.
64  *
65  *@pre The help_manager must already exist; this is different to the functions
66  * declared in help.hpp, which is why this one's declaration is in the .cpp
67  * file. Because this takes a section as an argument, it wouldn't make sense
68  * for it to call ensure_cache_lifecycle() internally - if the help_manager
69  * doesn't already exist, that would likely destroy the referenced object at
70  * the point that this function exited.
71  */
72 void show_with_toplevel(const section &toplevel, const std::string& show_topic="", int xloc=-1, int yloc=-1);
73 
74 
76 {
77  auto cache_lifecycle = ensure_cache_lifecycle();
79 }
80 
82 {
83  auto cache_lifecycle = ensure_cache_lifecycle();
85 }
86 
88 {
89  auto cache_lifecycle = ensure_cache_lifecycle();
90  std::string var_id = t.get_cfg()["variation_id"].str();
91  if (var_id.empty())
92  var_id = t.get_cfg()["variation_name"].str();
93  bool hide_help = t.hide_help();
94  bool use_variation = false;
95  if (!var_id.empty()) {
96  const unit_type *parent = unit_types.find(t.id());
97  assert(parent);
98  if (hide_help) {
99  hide_help = parent->hide_help();
100  } else {
101  use_variation = true;
102  }
103  }
104 
105  if (use_variation)
106  help::show_variation_help(t.id(), var_id, hide_help);
107  else
108  help::show_unit_help(t.id(), t.show_variations_in_help(), hide_help);
109 }
110 
112 {
113  assert(!game_cfg);
114  assert(cfg);
115  // This is a global rawpointer in the help:: namespace.
116  game_cfg = cfg;
117 }
118 
119 std::unique_ptr<help_manager> ensure_cache_lifecycle()
120 {
121  // The internals of help_manager are that this global raw pointer is
122  // non-null if and only if an instance of help_manager already exists.
123  if(game_cfg)
124  return nullptr;
125  return std::make_unique<help_manager>(&game_config_manager::get()->game_config());
126 }
127 
129 {
130  game_cfg = nullptr;
133  // These last numbers must be reset so that the content is regenerated.
134  // Upon next start.
137 }
138 
139 /**
140  * Open the help browser, show topic with id show_topic.
141  *
142  * If show_topic is the empty string, the default topic will be shown.
143  */
144 void show_help(const std::string& show_topic, int xloc, int yloc)
145 {
146  auto cache_lifecycle = ensure_cache_lifecycle();
147  show_with_toplevel(default_toplevel, show_topic, xloc, yloc);
148 }
149 
150 /**
151  * Open the help browser, show unit with id unit_id.
152  *
153  * If show_topic is the empty string, the default topic will be shown.
154  */
155 void show_unit_help(const std::string& show_topic, bool has_variations, bool hidden, int xloc, int yloc)
156 {
157  auto cache_lifecycle = ensure_cache_lifecycle();
159  hidden_symbol(hidden) + (has_variations ? ".." : "") + unit_prefix + show_topic, xloc, yloc);
160 }
161 
162 /**
163  * Open the help browser, show terrain with id terrain_id.
164  *
165  * If show_topic is the empty string, the default topic will be shown.
166  */
167 void show_terrain_help(const std::string& show_topic, bool hidden, int xloc, int yloc)
168 {
169  auto cache_lifecycle = ensure_cache_lifecycle();
170  show_with_toplevel(default_toplevel, hidden_symbol(hidden) + terrain_prefix + show_topic, xloc, yloc);
171 }
172 
173 /**
174  * Open the help browser, show the variation of the unit matching.
175  */
176 void show_variation_help(const std::string& unit, const std::string &variation, bool hidden, int xloc, int yloc)
177 {
178  auto cache_lifecycle = ensure_cache_lifecycle();
179  show_with_toplevel(default_toplevel, hidden_symbol(hidden) + variation_prefix + unit + "_" + variation, xloc, yloc);
180 }
181 
182 /**
183  * Open a help dialog using a toplevel other than the default.
184  *
185  * This allows for complete customization of the contents, although not in a
186  * very easy way.
187  */
188 void show_with_toplevel(const section &toplevel_sec,
189  const std::string& show_topic,
190  int xloc, int yloc)
191 {
192  CVideo& video = CVideo::get_singleton();
193 
194  const events::event_context dialog_events_context;
195  const gui::dialog_manager manager;
196 
197  SDL_Rect screen_area = video.screen_area();
198 
199  const int width = std::min<int>(font::relative_size(1200), screen_area.w - font::relative_size(20));
200  const int height = std::min<int>(font::relative_size(850), screen_area.h - font::relative_size(150));
201  const int left_padding = font::relative_size(10);
202  const int right_padding = font::relative_size(10);
203  const int top_padding = font::relative_size(10);
204  const int bot_padding = font::relative_size(10);
205 
206  // If not both locations were supplied, put the dialog in the middle
207  // of the screen.
208  if (yloc <= -1 || xloc <= -1) {
209  xloc = screen_area.w / 2 - width / 2;
210  yloc = screen_area.h / 2 - height / 2;
211  }
212  std::vector<gui::button*> buttons_ptr;
213  gui::button close_button_(video, _("Close"));
214  buttons_ptr.push_back(&close_button_);
215 
217  true, &buttons_ptr);
218  f.layout(xloc, yloc, width, height);
219  f.draw();
220 
221  // Find all unit_types that have not been constructed yet and fill in the information
222  // needed to create the help topics
224 
229  // More units or terrains encountered, update the contents.
234  }
235  try {
236  help_browser hb(video, toplevel_sec);
237  hb.set_location(xloc + left_padding, yloc + top_padding);
238  hb.set_width(width - left_padding - right_padding);
239  hb.set_height(height - top_padding - bot_padding);
240  if (!show_topic.empty()) {
241  hb.show_topic(show_topic);
242  }
243  else {
245  }
246  hb.set_dirty(true);
248  CKey key;
249  for (;;) {
250  events::pump();
252  f.draw();
254  if (key[SDLK_ESCAPE]) {
255  // Escape quits from the dialog.
256  return;
257  }
258  for (std::vector<gui::button*>::iterator button_it = buttons_ptr.begin();
259  button_it != buttons_ptr.end(); ++button_it) {
260  if ((*button_it)->pressed()) {
261  // There is only one button, close.
262  return;
263  }
264  }
265  video.flip();
266  CVideo::delay(10);
267  }
268  }
269  catch (const parse_error& e) {
270  ERR_HELP << _("Parse error when parsing help text:") << " " << e.message << std::endl;
271 #if 0
272  // Displaying in the UI is disabled due to issue #2587
273  std::stringstream msg;
274  msg << _("Parse error when parsing help text:") << " '" << e.message << "'";
275  gui2::show_transient_message("", msg.str());
276 #endif
277  }
278 }
279 
280 } // End namespace help.
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:144
const std::string unit_prefix
Definition: help_impl.cpp:90
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:1262
This class represents a single unit of a specific type.
Definition: unit.hpp:121
void show_terrain_description(const terrain_type &t)
Definition: help.cpp:81
static const style default_style
Definition: show_dialog.hpp:67
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:146
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:188
Definition: video.hpp:32
boost::tribool last_debug_state
Definition: help_impl.cpp:75
int relative_size(int size)
Definition: constants.hpp:30
void flip()
Renders the screen.
Definition: video.cpp:314
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, const bool restore_background)
Shows a transient message to the user.
Thrown when the help system fails to parse something.
Definition: help_impl.hpp:209
std::unique_ptr< help_manager > ensure_cache_lifecycle()
Helper function for any of the show_help functions to control the cache&#39;s lifecycle; can also be used...
Definition: help.cpp:119
void set_width(int w)
Definition: widget.cpp:109
void build_all(unit_type::BUILD_STATUS status)
Makes sure the all unit_types are built to the specified level.
Definition: types.cpp:1304
unit_type_data unit_types
Definition: types.cpp:1481
const config & get_cfg() const
Definition: types.hpp:285
static CVideo & get_singleton()
Definition: video.hpp:49
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
static std::string _(const char *str)
Definition: gettext.hpp:93
const std::string terrain_prefix
Definition: help_impl.cpp:91
int last_num_encountered_terrains
Definition: help_impl.cpp:74
Definitions for the interface to Wesnoth Markup Language (WML).
bool hide_help() const
For instances created from a [terrain_type] tag, the value in the tag (with default false)...
Definition: terrain.hpp:61
A single unit type that the player may recruit.
Definition: types.hpp:45
help::section hidden_sections
Definition: help_impl.cpp:71
const unit_type & type() const
This unit&#39;s type, accounting for gender and variation.
Definition: unit.hpp:346
dimension_measurements layout(int x, int y, int w, int h)
void set_dirty(bool dirty=true)
Definition: widget.cpp:207
static game_config_manager * get()
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
std::string hidden_symbol(bool hidden)
Definition: help_impl.cpp:1515
bool hide_help() const
Definition: types.cpp:627
const game_config_view & game_config() const
std::set< t_translation::terrain_code > & encountered_terrains()
Definition: game.cpp:935
const std::string & id() const
The id for this unit_type.
Definition: types.hpp:144
static lg::log_domain log_display("display")
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:167
virtual void set_location(const SDL_Rect &rect)
Definition: widget.cpp:75
void raise_draw_event()
Definition: events.cpp:774
void show_unit_description(const unit &u)
Definition: help.cpp:75
void pump()
Definition: events.cpp:473
#define ERR_HELP
Definition: help.cpp:55
A button is a control that can be pushed to start an action or close a dialog.
Definition: button.hpp:50
void raise_process_event()
Definition: events.cpp:751
const std::string variation_prefix
Definition: help_impl.cpp:95
void show_topic(const std::string &topic_id)
Display the topic with the specified identifier.
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:155
int last_num_encountered_units
Definition: help_impl.cpp:73
bool show_variations_in_help() const
Whether the unit type has at least one help-visible variation.
Definition: types.cpp:765
const game_config_view * game_cfg
Definition: help_impl.cpp:67
std::set< std::string > & encountered_units()
Definition: game.cpp:930
const bool & debug
help_manager(const game_config_view *game_config)
Definition: help.cpp:111
#define f
const std::string default_show_topic
Definition: help_impl.cpp:88
double t
Definition: astarsearch.cpp:65
void generate_contents()
Generate the help contents from the configurations given to the manager.
Definition: help_impl.cpp:1454
Standard logging facilities (interface).
const std::string & id() const
Definition: terrain.hpp:52
std::string message
Definition: exceptions.hpp:30
static void delay(unsigned int milliseconds)
Waits a given number of milliseconds before returning.
Definition: video.cpp:307
#define e
Definition: help.cpp:57
Class that keeps track of all the keys on the keyboard.
Definition: key.hpp:28
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:277
void set_height(int h)
Definition: widget.cpp:114
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
A help browser widget.
help::section default_toplevel
Definition: help_impl.cpp:69
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:176
static lg::log_domain log_help("help")