The Battle for Wesnoth  1.19.17+dev
help_impl.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2025
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  * Note:
18  * Prior to the creation of this file, all the code associated to the help
19  * browser existed in a single file src/help.cpp, including all of the
20  * widgets, topic generators, and implementation details. This totaled
21  * ~4000 lines of code.
22  *
23  * I have split it all up now, so that the gui aspects are separated from
24  * the content, the "front facing" part which the rest of the code base
25  * interacts with is in src/help/help.?pp, and the topic generators are
26  * separated. The remaining "guts" are here. It is implemented in a static
27  * singleton pattern, using "extern"'d variables, simply for ease of translation
28  * from the previous state. It would probably be a good idea to rewrite this
29  * guy as a proper C++ object. Feel free to do so, or to adopt some other
30  * design pattern.
31  */
32 
33 #pragma once
34 
35 #include "color.hpp"
36 #include "exceptions.hpp" // for error
37 #include "font/constants.hpp"
38 #include "font/standard_colors.hpp"
39 #include "gettext.hpp"
41 #include "utils/optional_fwd.hpp"
42 
43 #include <cstring>
44 #include <list> // for list
45 #include <memory>
46 #include <sstream>
47 #include <string> // for string, allocator, etc
48 #include <utility> // for pair, make_pair
49 #include <vector> // for vector, etc
50 #include "config.hpp"
51 
52 class game_config_view;
53 class unit_type;
54 
55 namespace help {
56 
57 /** Generate a topic text on the fly. */
59 {
60 public:
61  virtual std::string operator()() const = 0;
62  virtual ~topic_generator() {}
63 };
64 
66  std::string text_;
67 public:
68  text_topic_generator(const std::string& t): text_(t) {}
69  virtual std::string operator()() const { return text_; }
70 };
71 
72 /**
73  * The text displayed in a topic. It is generated on the fly with the information contained in generator_
74  */
76 {
78  mutable std::shared_ptr<topic_generator> generator_;
79 public:
80  explicit topic_text(std::shared_ptr<topic_generator> g):
81  parsed_text_(),
82  generator_(g)
83  {
84  }
85 
86  const config& parsed_text() const;
87 };
88 
89 /** A topic contains a title, an id and some text. */
90 struct topic
91 {
92  topic(const std::string &_title, const std::string &_id, const std::string &_text)
93  : title(_title), id(_id), text(std::make_shared<text_topic_generator>(_text)) {}
94  topic(const std::string &_title, const std::string &_id, std::shared_ptr<topic_generator> g)
95  : title(_title), id(_id), text(std::move(g)) {}
96  /** Two topics are equal if their IDs are equal. */
97  bool operator==(const topic &) const;
98  bool operator!=(const topic &t) const { return !operator==(t); }
99  /** Comparison on the ID. */
100  bool operator<(const topic &) const;
101  std::string title, id;
102  mutable topic_text text;
103 };
104 
105 struct section;
106 typedef std::list<section> section_list;
107 typedef std::list<topic> topic_list;
108 
109 /** A section contains topics and sections along with title and ID. */
110 struct section {
111  /** Two sections are equal if their IDs are equal. */
112  bool operator==(const section &) const;
113  /** Comparison on the ID. */
114  bool operator<(const section &) const;
115 
116  /** Allocate memory for and add the section. */
117  void add_section(const section &s);
118  void add_section(section&& s);
119 
120  void clear();
121  std::string title, id;
124 };
125 
126 
127 /**
128  * To be used as a function object to locate sections and topics with a specified ID.
129  */
130 class has_id
131 {
132 public:
133  has_id(const std::string &id) : id_(id) {}
134  bool operator()(const topic &t) { return t.id == id_; }
135  bool operator()(const section &s) { return s.id == id_; }
136  bool operator()(const section *s) { return s != nullptr && s->id == id_; }
137 private:
138  const std::string id_;
139 };
140 
141 /** To be used as a function object when sorting topic lists on the title. */
143 {
144 public:
145  bool operator()(const topic &t1, const topic &t2)
146  {
147  return translation::compare(t1.title, t2.title) < 0;
148  }
149 };
150 
151 /** To be used as a function object when sorting section lists on the title. */
153 {
154 public:
155  bool operator()(const section& s1, const section& s2)
156  {
157  return translation::compare(s1.title, s2.title) < 0;
158  }
159 };
160 
162 {
163 public:
164  bool operator() (const std::string &s1, const std::string &s2) const {
165  return translation::compare(s1, s2) < 0;
166  }
167 };
168 
169 // Generator stuff below. Maybe move to a separate file? This one is
170 // getting crowded. Dunno if much more is needed though so I'll wait and
171 // see.
172 
173 /** Dispatch generators to their appropriate functions. */
174 void generate_sections(const config& help_cfg, const std::string &generator, section &sec, int level);
175 std::vector<topic> generate_topics(const bool sort_topics,const std::string &generator);
176 std::string generate_topic_text(const std::string &generator, const config& help_cfg, const section &sec);
177 std::string generate_contents_links(const std::string& section_name, const config& help_cfg);
178 std::string generate_contents_links(const section &sec);
179 
180 /** Thrown when the help system fails to parse something. */
181 struct parse_error : public game::error
182 {
183  parse_error(const std::string& msg) : game::error(msg) {}
184 };
185 
186 /**
187  * return a hyperlink with the unit's name and pointing to the unit page
188  * return empty string if this unit is hidden. If not yet discovered add the (?) suffix
189  */
190 std::string make_unit_link(const std::string& type_id);
191 /** return a list of hyperlinks to unit's pages (ordered or not) */
192 std::vector<std::string> make_unit_links_list(
193  const std::vector<std::string>& type_id_list, bool ordered = false);
194 
195 void generate_races_sections(const config& help_cfg, section &sec, int level);
196 void generate_terrain_sections(section &sec, int level);
197 std::vector<topic> generate_unit_topics(const bool, const std::string& race);
198 void generate_unit_sections(const config& help_cfg, section &sec, int level, const bool, const std::string& race);
201  /** Ignore this unit for documentation purposes. */
203  /**
204  * Although the unit itself is hidden, traits reachable via this unit are not hidden.
205  *
206  * This is a bug workaround - traits are defined by WML macros, and therefore the help
207  * system has to use a place where that macro is instanciated to provide the documentation.
208  * None of the normal unit types has the "loyal" trait, but there is a hidden unit which
209  * does, purely to support the help system.
210  */
212 };
213 /**
214  * Return the type of description that should be shown for a unit of
215  * the given kind. This method is intended to filter out information
216  * about units that should not be shown, for example due to not being
217  * encountered.
218  */
220 std::vector<topic> generate_ability_topics(const bool);
221 std::vector<topic> generate_time_of_day_topics(const bool);
222 std::vector<topic> generate_weapon_special_topics(const bool);
223 
224 void generate_era_sections(const config& help_cfg, section &sec, int level);
225 std::vector<topic> generate_faction_topics(const config &, const bool);
226 std::vector<topic> generate_era_topics(const bool, const std::string & era_id);
227 std::vector<topic> generate_trait_topics(const bool);
228 
229 /**
230  * Generate the help contents from the configurations given to the manager.
231  * @returns A pair consisting of the toplevel section and any hidden sections.
232  */
233 std::pair<section, section> generate_contents();
234 
235 /**
236  * Parse a help config, return the top level section. Return an empty
237  * section if cfg is nullptr.
238  */
239 section parse_config(const config& cfg);
240 
241 /** Recursive function used by parse_config. */
242 section parse_config_internal(const config& help_cfg, const config& section_cfg, int level = 0);
243 
244 /**
245  * Return true if the section with id section_id is referenced from
246  * another section in the config, or the toplevel.
247  */
248 bool section_is_referenced(const std::string &section_id, const config &cfg);
249 /**
250  * Return true if the topic with id topic_id is referenced from
251  * another section in the config, or the toplevel.
252  */
253 bool topic_is_referenced(const std::string &topic_id, const config &cfg);
254 
255 /**
256  * Search for the topic with the specified identifier in the section
257  * and its subsections. Return the found topic, or nullptr if none could
258  * be found.
259  */
260 const topic *find_topic(const section &sec, const std::string &id);
261 
262 /**
263  * Search for the section with the specified identifier in the section
264  * and its subsections. Return the found section or nullptr if none could
265  * be found.
266  */
267 const section *find_section(const section &sec, const std::string &id);
268 section *find_section(section &sec, const std::string &id);
269 
270 extern const int max_section_level;
271 // The topic to open by default when opening the help dialog.
272 extern const std::string default_show_topic;
273 extern const std::string unknown_unit_topic;
274 extern const std::string unit_prefix;
275 extern const std::string terrain_prefix;
276 extern const std::string race_prefix;
277 extern const std::string faction_prefix;
278 extern const std::string era_prefix;
279 extern const std::string variation_prefix;
280 extern const std::string ability_prefix;
281 
282 // id starting with '.' are hidden
283 std::string hidden_symbol(bool hidden = true);
284 
285 bool is_visible_id(const std::string &id);
286 
287 /**
288  * Return true if the id is valid for user defined topics and
289  * sections. Some IDs are special, such as toplevel and may not be
290  * be defined in the config.
291  */
292 bool is_valid_id(const std::string &id);
293 
294 } // end namespace help
double t
Definition: astarsearch.cpp:63
double g
Definition: astarsearch.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:157
A class grating read only view to a vector of config objects, viewed as one config with all children ...
To be used as a function object to locate sections and topics with a specified ID.
Definition: help_impl.hpp:131
has_id(const std::string &id)
Definition: help_impl.hpp:133
const std::string id_
Definition: help_impl.hpp:138
bool operator()(const topic &t)
Definition: help_impl.hpp:134
bool operator()(const section &s)
Definition: help_impl.hpp:135
bool operator()(const section *s)
Definition: help_impl.hpp:136
To be used as a function object when sorting section lists on the title.
Definition: help_impl.hpp:153
bool operator()(const section &s1, const section &s2)
Definition: help_impl.hpp:155
bool operator()(const std::string &s1, const std::string &s2) const
Definition: help_impl.hpp:164
text_topic_generator(const std::string &t)
Definition: help_impl.hpp:68
virtual std::string operator()() const
Definition: help_impl.hpp:69
To be used as a function object when sorting topic lists on the title.
Definition: help_impl.hpp:143
bool operator()(const topic &t1, const topic &t2)
Definition: help_impl.hpp:145
Generate a topic text on the fly.
Definition: help_impl.hpp:59
virtual std::string operator()() const =0
virtual ~topic_generator()
Definition: help_impl.hpp:62
The text displayed in a topic.
Definition: help_impl.hpp:76
topic_text(std::shared_ptr< topic_generator > g)
Definition: help_impl.hpp:80
std::shared_ptr< topic_generator > generator_
Definition: help_impl.hpp:78
const config & parsed_text() const
Definition: help_impl.cpp:280
config parsed_text_
Definition: help_impl.hpp:77
A single unit type that the player may recruit.
Definition: types.hpp:43
Definitions for the interface to Wesnoth Markup Language (WML).
const config * cfg
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:199
std::vector< topic > generate_unit_topics(const bool sort_generated, const std::string &race)
Definition: help_impl.cpp:943
std::string hidden_symbol(bool hidden)
Definition: help_impl.cpp:1276
UNIT_DESCRIPTION_TYPE
Definition: help_impl.hpp:199
@ FULL_DESCRIPTION
Definition: help_impl.hpp:200
@ HIDDEN_BUT_SHOW_MACROS
Although the unit itself is hidden, traits reachable via this unit are not hidden.
Definition: help_impl.hpp:211
@ NO_DESCRIPTION
Ignore this unit for documentation purposes.
Definition: help_impl.hpp:202
bool topic_is_referenced(const std::string &topic_id, const config &cfg)
Return true if the topic with id topic_id is referenced from another section in the config,...
Definition: help_impl.cpp:89
std::vector< topic > generate_time_of_day_topics(const bool)
Definition: help_impl.cpp:295
section parse_config_internal(const config &help_cfg, const config &section_cfg, int level)
Recursive function used by parse_config.
Definition: help_impl.cpp:107
void generate_terrain_sections(section &sec, int)
Definition: help_impl.cpp:846
std::string make_unit_link(const std::string &type_id)
return a hyperlink with the unit's name and pointing to the unit page return empty string if this uni...
Definition: help_impl.cpp:688
const std::string unit_prefix
Definition: help_impl.cpp:63
const std::string variation_prefix
Definition: help_impl.cpp:68
bool is_visible_id(const std::string &id)
Definition: help_impl.cpp:1280
std::vector< topic > generate_faction_topics(const config &era, const bool sort_generated)
Definition: help_impl.cpp:531
UNIT_DESCRIPTION_TYPE description_type(const unit_type &type)
Return the type of description that should be shown for a unit of the given kind.
Definition: help_impl.cpp:1072
const std::string race_prefix
Definition: help_impl.cpp:65
const std::string ability_prefix
Definition: help_impl.cpp:69
std::vector< std::string > make_unit_links_list(const std::vector< std::string > &type_id_list, bool ordered)
return a list of hyperlinks to unit's pages (ordered or not)
Definition: help_impl.cpp:714
std::vector< topic > generate_topics(const bool sort_generated, const std::string &generator)
Definition: help_impl.cpp:214
void generate_sections(const config &help_cfg, const std::string &generator, section &sec, int level)
Dispatch generators to their appropriate functions.
Definition: help_impl.cpp:243
const section * find_section(const section &sec, const std::string &id)
Search for the section with the specified identifier in the section and its subsections.
Definition: help_impl.cpp:1200
void generate_races_sections(const config &help_cfg, section &sec, int level)
Definition: help_impl.cpp:729
void generate_unit_sections(const config &, section &sec, int, const bool, const std::string &race)
Definition: help_impl.cpp:912
const std::string terrain_prefix
Definition: help_impl.cpp:64
std::string generate_contents_links(const std::string &section_name, const config &help_cfg)
Definition: help_impl.cpp:1092
std::vector< topic > generate_weapon_special_topics(const bool sort_generated)
Definition: help_impl.cpp:345
std::string generate_topic_text(const std::string &generator, const config &help_cfg, const section &sec)
Definition: help_impl.cpp:262
std::vector< topic > generate_ability_topics(const bool sort_generated)
Definition: help_impl.cpp:435
const std::string unknown_unit_topic
Definition: help_impl.cpp:62
const int max_section_level
Definition: help_impl.cpp:59
bool section_is_referenced(const std::string &section_id, const config &cfg)
Return true if the section with id section_id is referenced from another section in the config,...
Definition: help_impl.cpp:71
bool is_valid_id(const std::string &id)
Return true if the id is valid for user defined topics and sections.
Definition: help_impl.cpp:1289
std::list< topic > topic_list
Definition: help_impl.hpp:107
const topic * find_topic(const section &sec, const std::string &id)
Search for the topic with the specified identifier in the section and its subsections.
Definition: help_impl.cpp:1184
std::vector< topic > generate_era_topics(const bool sort_generated, const std::string &era_id)
Definition: help_impl.cpp:499
std::list< section > section_list
Definition: help_impl.hpp:105
std::vector< topic > generate_trait_topics(const bool sort_generated)
Definition: help_impl.cpp:606
void generate_era_sections(const config &help_cfg, section &sec, int level)
Definition: help_impl.cpp:826
const std::string default_show_topic
Definition: help_impl.cpp:61
std::pair< section, section > generate_contents()
Generate the help contents from the configurations given to the manager.
Definition: help_impl.cpp:1221
section parse_config(const config &cfg)
Parse a help config, return the top level section.
Definition: help_impl.cpp:205
const std::string era_prefix
Definition: help_impl.cpp:67
const std::string faction_prefix
Definition: help_impl.cpp:66
rng * generator
This generator is automatically synced during synced context.
Definition: random.cpp:60
int compare(const std::string &s1, const std::string &s2)
Case-sensitive lexicographical comparison.
Definition: gettext.cpp:502
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:29
Thrown when the help system fails to parse something.
Definition: help_impl.hpp:182
parse_error(const std::string &msg)
Definition: help_impl.hpp:183
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:110
section_list sections
Definition: help_impl.hpp:123
bool operator<(const section &) const
Comparison on the ID.
Definition: help_impl.cpp:1163
void add_section(const section &s)
Allocate memory for and add the section.
Definition: help_impl.cpp:1168
std::string id
Definition: help_impl.hpp:121
std::string title
Definition: help_impl.hpp:121
bool operator==(const section &) const
Two sections are equal if their IDs are equal.
Definition: help_impl.cpp:1158
topic_list topics
Definition: help_impl.hpp:122
A topic contains a title, an id and some text.
Definition: help_impl.hpp:91
topic(const std::string &_title, const std::string &_id, std::shared_ptr< topic_generator > g)
Definition: help_impl.hpp:94
bool operator==(const topic &) const
Two topics are equal if their IDs are equal.
Definition: help_impl.cpp:1148
std::string id
Definition: help_impl.hpp:101
topic(const std::string &_title, const std::string &_id, const std::string &_text)
Definition: help_impl.hpp:92
topic_text text
Definition: help_impl.hpp:102
bool operator!=(const topic &t) const
Definition: help_impl.hpp:98
bool operator<(const topic &) const
Comparison on the ID.
Definition: help_impl.cpp:1153
std::string title
Definition: help_impl.hpp:101
static map_location::direction s