The Battle for Wesnoth  1.17.0-dev
help.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Routines for showing the help-dialog.
18  */
19 
20 #define GETTEXT_DOMAIN "wesnoth-help"
21 
22 #include "help/help.hpp"
23 
24 #include "config.hpp" // for config, etc
25 #include "events.hpp" // for raise_draw_event, pump, etc
26 #include "font/constants.hpp" // for relative_size
27 #include "preferences/game.hpp"
28 #include "game_config_manager.hpp"
29 #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 "sdl/surface.hpp" // for surface
36 #include "show_dialog.hpp" // for dialog_frame, etc
37 #include "terrain/terrain.hpp" // for terrain_type
38 #include "units/unit.hpp" // for unit
39 #include "units/types.hpp" // for unit_type, unit_type_data, etc
40 #include "video.hpp" // for CVideo, resize_lock
41 #include "widgets/button.hpp" // for button
42 
43 #include <cassert> // for assert
44 #include <algorithm> // for min
45 #include <ostream> // for basic_ostream, operator<<, etc
46 #include <vector> // for vector, vector<>::iterator
47 #include <SDL2/SDL.h>
48 
49 
50 static lg::log_domain log_display("display");
51 #define WRN_DP LOG_STREAM(warn, log_display)
52 
53 static lg::log_domain log_help("help");
54 #define ERR_HELP LOG_STREAM(err, log_help)
55 
56 namespace help {
57 /**
58  * Open a help dialog using a specified toplevel.
59  *
60  * This would allow for complete customization of the contents, although not in a
61  * very easy way. It's used as the internal implementation of the other help*
62  * functions.
63  *
64  *@pre The help_manager must already exist; this is different to the functions
65  * declared in help.hpp, which is why this one's declaration is in the .cpp
66  * file. Because this takes a section as an argument, it wouldn't make sense
67  * for it to call ensure_cache_lifecycle() internally - if the help_manager
68  * doesn't already exist, that would likely destroy the referenced object at
69  * the point that this function exited.
70  */
71 void show_with_toplevel(const section &toplevel, const std::string& show_topic="", int xloc=-1, int yloc=-1);
72 
73 
75 {
76  auto cache_lifecycle = ensure_cache_lifecycle();
78 }
79 
81 {
82  auto cache_lifecycle = ensure_cache_lifecycle();
84 }
85 
87 {
88  auto cache_lifecycle = ensure_cache_lifecycle();
89  std::string var_id = t.get_cfg()["variation_id"].str();
90  if (var_id.empty())
91  var_id = t.get_cfg()["variation_name"].str();
92  bool hide_help = t.hide_help();
93  bool use_variation = false;
94  if (!var_id.empty()) {
95  const unit_type *parent = unit_types.find(t.id());
96  assert(parent);
97  if (hide_help) {
98  hide_help = parent->hide_help();
99  } else {
100  use_variation = true;
101  }
102  }
103 
104  if (use_variation)
105  help::show_variation_help(t.id(), var_id, hide_help);
106  else
107  help::show_unit_help(t.id(), t.show_variations_in_help(), hide_help);
108 }
109 
111 {
112  assert(!game_cfg);
113  assert(cfg);
114  // This is a global rawpointer in the help:: namespace.
115  game_cfg = cfg;
116 }
117 
118 std::unique_ptr<help_manager> ensure_cache_lifecycle()
119 {
120  // The internals of help_manager are that this global raw pointer is
121  // non-null if and only if an instance of help_manager already exists.
122  if(game_cfg)
123  return nullptr;
124  return std::make_unique<help_manager>(&game_config_manager::get()->game_config());
125 }
126 
128 {
129  game_cfg = nullptr;
132  // These last numbers must be reset so that the content is regenerated.
133  // Upon next start.
136 }
137 
138 /**
139  * Open the help browser, show topic with id show_topic.
140  *
141  * If show_topic is the empty string, the default topic will be shown.
142  */
143 void show_help(const std::string& show_topic, int xloc, int yloc)
144 {
145  auto cache_lifecycle = ensure_cache_lifecycle();
146  show_with_toplevel(default_toplevel, show_topic, xloc, yloc);
147 }
148 
149 /**
150  * Open the help browser, show unit with id unit_id.
151  *
152  * If show_topic is the empty string, the default topic will be shown.
153  */
154 void show_unit_help(const std::string& show_topic, bool has_variations, bool hidden, int xloc, int yloc)
155 {
156  auto cache_lifecycle = ensure_cache_lifecycle();
158  hidden_symbol(hidden) + (has_variations ? ".." : "") + unit_prefix + show_topic, xloc, yloc);
159 }
160 
161 /**
162  * Open the help browser, show terrain with id terrain_id.
163  *
164  * If show_topic is the empty string, the default topic will be shown.
165  */
166 void show_terrain_help(const std::string& show_topic, bool hidden, int xloc, int yloc)
167 {
168  auto cache_lifecycle = ensure_cache_lifecycle();
169  show_with_toplevel(default_toplevel, hidden_symbol(hidden) + terrain_prefix + show_topic, xloc, yloc);
170 }
171 
172 /**
173  * Open the help browser, show the variation of the unit matching.
174  */
175 void show_variation_help(const std::string& unit, const std::string &variation, bool hidden, int xloc, int yloc)
176 {
177  auto cache_lifecycle = ensure_cache_lifecycle();
178  show_with_toplevel(default_toplevel, hidden_symbol(hidden) + variation_prefix + unit + "_" + variation, xloc, yloc);
179 }
180 
181 /**
182  * Open a help dialog using a toplevel other than the default.
183  *
184  * This allows for complete customization of the contents, although not in a
185  * very easy way.
186  */
187 void show_with_toplevel(const section &toplevel_sec,
188  const std::string& show_topic,
189  int xloc, int yloc)
190 {
191  CVideo& video = CVideo::get_singleton();
192 
193  const events::event_context dialog_events_context;
194  const gui::dialog_manager manager;
195 
196  SDL_Rect screen_area = video.screen_area();
197 
198  const int width = std::min<int>(font::relative_size(1200), screen_area.w - font::relative_size(20));
199  const int height = std::min<int>(font::relative_size(850), screen_area.h - font::relative_size(150));
200  const int left_padding = font::relative_size(10);
201  const int right_padding = font::relative_size(10);
202  const int top_padding = font::relative_size(10);
203  const int bot_padding = font::relative_size(10);
204 
205  // If not both locations were supplied, put the dialog in the middle
206  // of the screen.
207  if (yloc <= -1 || xloc <= -1) {
208  xloc = screen_area.w / 2 - width / 2;
209  yloc = screen_area.h / 2 - height / 2;
210  }
211  std::vector<gui::button*> buttons_ptr;
212  gui::button close_button_(video, _("Close"));
213  buttons_ptr.push_back(&close_button_);
214 
216  true, &buttons_ptr);
217  f.layout(xloc, yloc, width, height);
218  f.draw();
219 
220  // Find all unit_types that have not been constructed yet and fill in the information
221  // needed to create the help topics
223 
228  // More units or terrains encountered, update the contents.
233  }
234  try {
235  help_browser hb(video, toplevel_sec);
236  hb.set_location(xloc + left_padding, yloc + top_padding);
237  hb.set_width(width - left_padding - right_padding);
238  hb.set_height(height - top_padding - bot_padding);
239  if (!show_topic.empty()) {
240  hb.show_topic(show_topic);
241  }
242  else {
244  }
245  hb.set_dirty(true);
247  CKey key;
248  for (;;) {
249  events::pump();
251  f.draw();
253  if (key[SDLK_ESCAPE]) {
254  // Escape quits from the dialog.
255  return;
256  }
257  for (std::vector<gui::button*>::iterator button_it = buttons_ptr.begin();
258  button_it != buttons_ptr.end(); ++button_it) {
259  if ((*button_it)->pressed()) {
260  // There is only one button, close.
261  return;
262  }
263  }
264  video.flip();
265  CVideo::delay(10);
266  }
267  }
268  catch (const parse_error& e) {
269  ERR_HELP << _("Parse error when parsing help text:") << " " << e.message << std::endl;
270 #if 0
271  // Displaying in the UI is disabled due to issue #2587
272  std::stringstream msg;
273  msg << _("Parse error when parsing help text:") << " '" << e.message << "'";
274  gui2::show_transient_message("", msg.str());
275 #endif
276  }
277 }
278 
279 } // 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:143
const std::string unit_prefix
Definition: help_impl.cpp:89
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:1261
This class represents a single unit of a specific type.
Definition: unit.hpp:120
void show_terrain_description(const terrain_type &t)
Definition: help.cpp:80
static const style default_style
Definition: show_dialog.hpp:66
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:145
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:187
Definition: video.hpp:31
boost::tribool last_debug_state
Definition: help_impl.cpp:74
int relative_size(int size)
Definition: constants.hpp:29
void flip()
Renders the screen.
Definition: video.cpp:307
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:208
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:118
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:1303
unit_type_data unit_types
Definition: types.cpp:1480
const config & get_cfg() const
Definition: types.hpp:284
static CVideo & get_singleton()
Definition: video.hpp:48
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
static std::string _(const char *str)
Definition: gettext.hpp:92
const std::string terrain_prefix
Definition: help_impl.cpp:90
int last_num_encountered_terrains
Definition: help_impl.cpp:73
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:60
A single unit type that the player may recruit.
Definition: types.hpp:44
help::section hidden_sections
Definition: help_impl.cpp:70
const unit_type & type() const
This unit&#39;s type, accounting for gender and variation.
Definition: unit.hpp:345
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:86
std::string hidden_symbol(bool hidden)
Definition: help_impl.cpp:1515
bool hide_help() const
Definition: types.cpp:626
const game_config_view & game_config() const
std::set< t_translation::terrain_code > & encountered_terrains()
Definition: game.cpp:934
const std::string & id() const
The id for this unit_type.
Definition: types.hpp:143
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:166
virtual void set_location(const SDL_Rect &rect)
Definition: widget.cpp:75
void raise_draw_event()
Definition: events.cpp:773
void show_unit_description(const unit &u)
Definition: help.cpp:74
void pump()
Definition: events.cpp:472
#define ERR_HELP
Definition: help.cpp:54
A button is a control that can be pushed to start an action or close a dialog.
Definition: button.hpp:49
void raise_process_event()
Definition: events.cpp:750
const std::string variation_prefix
Definition: help_impl.cpp:94
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:154
int last_num_encountered_units
Definition: help_impl.cpp:72
bool show_variations_in_help() const
Whether the unit type has at least one help-visible variation.
Definition: types.cpp:764
const game_config_view * game_cfg
Definition: help_impl.cpp:66
std::set< std::string > & encountered_units()
Definition: game.cpp:929
const bool & debug
help_manager(const game_config_view *game_config)
Definition: help.cpp:110
#define f
const std::string default_show_topic
Definition: help_impl.cpp:87
double t
Definition: astarsearch.cpp:64
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:51
std::string message
Definition: exceptions.hpp:29
static void delay(unsigned int milliseconds)
Waits a given number of milliseconds before returning.
Definition: video.cpp:300
#define e
Definition: help.cpp:56
Class that keeps track of all the keys on the keyboard.
Definition: key.hpp:27
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:270
void set_height(int h)
Definition: widget.cpp:114
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
A help browser widget.
help::section default_toplevel
Definition: help_impl.cpp:68
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:175
static lg::log_domain log_help("help")