Reduce help.hpp to minimum size and dependencies.

Should somewhat speed up (re)compilation.
This commit is contained in:
Guillaume Melquiond 2004-10-31 07:19:44 +00:00
parent 8fe155dd6b
commit 4686661007
2 changed files with 476 additions and 479 deletions

View file

@ -10,31 +10,496 @@
See the COPYING file for more details.
*/
#include "help.hpp"
#include "about.hpp"
#include "cursor.hpp"
#include "events.hpp"
#include "font.hpp"
#include "game_config.hpp"
#include "help.hpp"
#include "image.hpp"
#include "language.hpp"
#include "preferences.hpp"
#include "show_dialog.hpp"
#include "unit.hpp"
#include "util.hpp"
#include "SDL_ttf.h"
#include "widgets/button.hpp"
#include "widgets/menu.hpp"
#include "widgets/scrollbar.hpp"
#include "widgets/widget.hpp"
#include <cassert>
#include <algorithm>
#include <iostream>
#include <list>
#include <locale>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <sstream>
namespace help {
/// Generate the help contents from the configurations given to the
/// manager.
void generate_contents();
struct section;
typedef std::vector<section *> section_list;
struct topic_generator;
class topic_text {
mutable std::string text_;
mutable topic_generator *generator_;
public:
~topic_text();
topic_text(): generator_(NULL) {}
topic_text(std::string const &t): text_(t), generator_(NULL) {}
explicit topic_text(topic_generator *g): generator_(g) {}
topic_text &operator=(topic_generator *g);
topic_text(topic_text const &t);
operator std::string() const;
};
/// A topic contains a title, an id and some text.
struct topic {
topic(const std::string &_title, const std::string &_id, const std::string &_text)
: title(_title), id(_id), text(_text) {}
topic(const std::string &_title, const std::string &_id, topic_generator *g)
: title(_title), id(_id), text(g) {}
topic() : title(""), id(""), text("") {}
/// Two topics are equal if their IDs are equal.
bool operator==(const topic &) const;
/// Comparison on the ID.
bool operator<(const topic &) const;
std::string title, id;
topic_text text;
};
typedef std::list<topic> topic_list;
/// A section contains topics and sections along with title and ID.
struct section {
section(const std::string &_title, const std::string &_id, const topic_list &_topics,
const std::vector<section> &_sections);
section() : title(""), id("") {}
section(const section&);
section& operator=(const section&);
~section();
/// Two sections are equal if their IDs are equal.
bool operator==(const section &) const;
/// Comparison on the ID.
bool operator<(const section &) const;
/// Allocate memory for and add the section.
void add_section(const section &s);
void clear();
std::string title, id;
topic_list topics;
section_list sections;
};
/// To be used as a function object to locate sections and topics
/// with a specified ID.
class has_id {
public:
has_id(const std::string &id) : id_(id) {}
bool operator()(const topic &t) { return t.id == id_; }
bool operator()(const section &s) { return s.id == id_; }
bool operator()(const section *s) { return s != NULL && s->id == id_; }
private:
const std::string id_;
};
/// To be used as a function object when sorting topic lists on the title.
class title_less {
public:
bool operator()(const topic &t1, const topic &t2) { return t1.title < t2.title; }
};
struct delete_section {
void operator()(section *s) { delete s; }
};
struct create_section {
section *operator()(const section *s) { return new section(*s); }
section *operator()(const section &s) { return new section(s); }
};
/// The menu to the left in the help browser, where topics can be
/// navigated through and chosen.
class help_menu : public gui::menu {
public:
help_menu(display& disp, const section &toplevel, int max_height=-1);
void bg_backup();
void bg_restore();
int process(int x, int y, bool button,bool up_arrow,bool down_arrow,
bool page_up, bool page_down, int select_item=-1);
/// Overloaded from menu so that the background can be saved.
void set_loc(int x, int y);
/// Overloaded from menu so that the background can be saved.
void set_width(int w);
/// Overloaded from menu so that the background can be saved.
void set_max_height(const int new_height);
/// Make the topic the currently selected one, and expand all
/// sections that need to be expanded to show it.
void select_topic(const topic &t);
/// If a topic has been chosen, return that topic, otherwise
/// NULL. If one topic is returned, it will not be returned again,
/// if it is not re-chosen.
const topic *chosen_topic();
protected:
void handle_event(const SDL_Event &event);
private:
/// Information about an item that is visible in the menu.
struct visible_item {
visible_item(const section *_sec, const std::string &visible_string);
visible_item(const topic *_t, const std::string &visible_string);
// Invariant, one if these should be NULL. The constructors
// enforce it.
const topic *t;
const section *sec;
std::string visible_string;
bool operator==(const visible_item &vis_item) const;
bool operator==(const section &sec) const;
bool operator==(const topic &t) const;
};
/// Regenerate what items are visible by checking what sections are
/// expanded.
void update_visible_items(const section &top_level, unsigned starting_level=0);
/// Return true if the section is expanded.
bool expanded(const section &sec);
/// Mark a section as expanded. Do not update the visible items or
/// anything.
void expand(const section &sec);
/// Contract (close) a section. That is, mark it as not expanded,
/// visible items are not updated.
void contract(const section &sec);
/// Return the string to use as the menu-string for sections at the
/// specified level.
std::string get_string_to_show(const section &sec, const unsigned level);
/// Return the string to use as the menu-string for topics at the
/// specified level.
std::string get_string_to_show(const topic &topic, const unsigned level);
/// Draw the currently visible items.
void display_visible_items();
/// Internal recursive thingie. did_expand will be true if any
/// section was expanded, otherwise untouched.
bool select_topic_internal(const topic &t, const section &sec);
display &disp_;
std::vector<visible_item> visible_items_;
const section &toplevel_;
std::set<const section*> expanded_;
surface_restorer restorer_;
SDL_Rect rect_;
topic const *chosen_topic_;
int internal_width_;
visible_item selected_item_;
bool selected_;
};
/// Thrown when the help system fails to parse something.
struct parse_error {
parse_error(const std::string& msg) : message(msg) {}
std::string message;
};
/// The area where the content is shown in the help browser.
class help_text_area : public gui::widget, public gui::scrollable {
public:
help_text_area(display &disp, const section &toplevel);
/// Display the topic.
void show_topic(const topic &t);
/// Return the ID that is crossreferenced at the (screen)
/// coordinates x, y. If no cross-reference is there, return the
/// empty string.
std::string ref_at(const int x, const int y);
/// Return the width of the area where text fit.
int text_width() const;
void scroll(int pos);
void set_dirty(bool dirty);
/// Scroll the contents up an amount. If how_much is below zero the
/// amount will depend on the height.
void scroll_up(const int how_much=-1);
/// Scroll the contents down an amount. If how_much is below zero
/// the amount will depend on the height.
void scroll_down(const int how_much=-1);
private:
enum ALIGNMENT {LEFT, MIDDLE, RIGHT, HERE};
/// Convert a string to an alignment. Throw parse_error if
/// unsuccesful.
ALIGNMENT str_to_align(const std::string &s);
/// An item that is displayed in the text area. Contains the surface
/// that should be blitted along with some other information.
struct item {
item(surface surface, int x, int y, const std::string text="",
const std::string reference_to="", bool floating=false,
bool box=false, ALIGNMENT alignment=HERE);
item(surface surface, int x, int y,
bool floating, bool box=false, ALIGNMENT=HERE);
/// Relative coordinates of this item.
SDL_Rect rect;
surface surf;
// If this item contains text, this will contain that text.
std::string text;
// If this item contains a cross-reference, this is the id
// of the referenced topic.
std::string ref_to;
// If this item is floating, that is, if things should be filled
// around it.
bool floating;
bool box;
ALIGNMENT align;
};
/// Function object to find an item at the specified coordinates.
class item_at {
public:
item_at(const int x, const int y) : x_(x), y_(y) {}
bool operator()(const item&) const;
private:
const int x_, y_;
};
/// Update the vector with items, creating surfaces for everything
/// and putting things where they belong. parsed_items should be a
/// vector with parsed strings, such as parse_text returns.
void set_items(const std::vector<std::string> &parsed_items,
const std::string &title);
// Create appropriate items from configs. Items will be added to the
// internal vector. These methods check that the necessary
// attributes are specified.
void handle_ref_cfg(const config &cfg);
void handle_img_cfg(const config &cfg);
void handle_bold_cfg(const config &cfg);
void handle_italic_cfg(const config &cfg);
void handle_header_cfg(const config &cfg);
void handle_jump_cfg(const config &cfg);
void handle_format_cfg(const config &cfg);
void handle_event(const SDL_Event &event);
void draw();
void process();
/// Update the scrollbar to take account for the current items.
void update_scrollbar();
/// Get the current amount of scrolling that should be
/// added/substracted from the locations to get the desired effect.
unsigned get_scroll_offset() const;
/// Add an item with text. If ref_dst is something else than the
/// empty string, the text item will be underlined to show that it
/// is a cross-reference. The item will also remember what the
/// reference points to. If font_size is below zero, the default
/// will be used.
void add_text_item(const std::string text, const std::string ref_dst="",
int font_size=-1, bool bold=false, bool italic=false,
SDL_Color color=font::NORMAL_COLOUR);
/// Add an image item with the specified attributes.
void add_img_item(const std::string path, const std::string alignment, const bool floating,
const bool box);
/// Move the current input point to the next line.
void down_one_line();
/// Adjust the heights of the items in the last row to make it look
/// good .
void adjust_last_row();
/// Return the width that remain on the line the current input point is at.
int get_remaining_width();
/// Return the least x coordinate at which something of the
/// specified height can be drawn at the specified y coordinate
/// without interfering with floating images.
int get_min_x(const int y, const int height=0);
/// Analogous with get_min_x but return the maximum X.
int get_max_x(const int y, const int height=0);
/// Find the lowest y coordinate where a floating img of the
/// specified width and at the specified x coordinate can be
/// placed. Start looking at desired_y and continue downwards. Only
/// check against other floating things, since text and inline
/// images only can be above this place if called correctly.
int get_y_for_floating_img(const int width, const int x, const int desired_y);
/// Add an item to the internal list, update the locations and row
/// height.
void add_item(const item& itm);
std::list<item> items_;
std::list<item *> last_row_;
display &disp_;
const section &toplevel_;
topic const *shown_topic_;
const int title_spacing_;
// The current input location when creating items.
std::pair<int, int> curr_loc_;
const unsigned min_row_height_;
unsigned curr_row_height_;
gui::scrollbar scrollbar_;
bool use_scrollbar_;
gui::button uparrow_, downarrow_;
/// The height of all items in total.
int contents_height_;
};
/// A help browser widget.
class help_browser : public gui::widget {
public:
help_browser(display &disp, const section &toplevel);
// Overloaded from widget so that the layout may be adjusted to fit
// the new dimensions.
void set_location(const SDL_Rect& rect);
void set_location(int x, int y);
void set_width(int w);
void set_height(int h);
void set_dirty(bool dirty);
void adjust_layout();
void process();
/// Display the topic with the specified identifier. Open the menu
/// on the right location and display the topic in the text area.
void show_topic(const std::string &topic_id);
private:
/// Update the current cursor, set it to the reference cursor if
/// mousex, mousey is over a cross-reference, otherwise, set it to
/// the normal cursor.
void update_cursor();
void handle_event(const SDL_Event &event);
void show_topic(const topic &t, bool save_in_history=true);
/// Move in the topic history. Pop an element from from and insert
/// it in to. Pop at the fronts if the maximum number of elements is
/// exceeded.
void move_in_history(std::deque<const topic *> &from, std::deque<const topic *> &to);
display &disp_;
help_menu menu_;
help_text_area text_area_;
const section &toplevel_;
bool ref_cursor_; // If the cursor currently is the hyperlink cursor.
std::deque<const topic *> back_topics_, forward_topics_;
gui::button back_button_, forward_button_;
topic const *shown_topic_;
};
// Generator stuff below. Maybe move to a separate file? This one is
// getting crowded. Dunno if much more is needed though so I'll wait and
// see.
/// Dispatch generators to their appropriate functions.
std::vector<section> generate_sections(const std::string &generator);
std::vector<topic> generate_topics(const std::string &generator);
std::string generate_topic_text(const std::string &generator);
std::string generate_about_text();
std::string generate_traits_text();
std::vector<topic> generate_unit_topics();
enum UNIT_DESCRIPTION_TYPE {FULL_DESCRIPTION, NO_DESCRIPTION, NON_REVEALING_DESCRIPTION};
/// Return the type of description that should be shown for a unit of
/// the given kind. This method is intended to filter out information
/// about units that should not be shown, for example due to not being
/// encountered.
UNIT_DESCRIPTION_TYPE description_type(const unit_type &type);
std::vector<topic> generate_ability_topics();
std::vector<topic> generate_weapon_special_topics();
std::vector<topic> generate_terrains_topics();
/// Parse a help config, return the top level section. Return an empty
/// section if cfg is NULL.
section parse_config(const config *cfg);
/// Recursive function used by parse_config.
void parse_config_internal(const config *help_cfg, const config *section_cfg,
section &sec, int level=0);
/// Return true if the section with id section_id is referenced from
/// another section in the config, or the toplevel.
bool section_is_referenced(const std::string &section_id, const config &cfg);
/// Return true if the topic with id topic_id is referenced from
/// another section in the config, or the toplevel.
bool topic_is_referenced(const std::string &topic_id, const config &cfg);
/// Search for the topic with the specified identifier in the section
/// and its subsections. Return the found topic, or NULL if none could
/// be found.
const topic *find_topic(const section &sec, const std::string &id);
/// Search for the section with the specified identifier in the section
/// and its subsections. Return the found section or NULL if none could
/// be found.
const section *find_section(const section &sec, const std::string &id);
/// Parse a text string. Return a vector with the different parts of the
/// text. Each markup item is a separate part while the text between
/// markups are separate parts.
std::vector<std::string> parse_text(const std::string &text);
/// Convert the contents to wml attributes, surrounded within
/// [element_name]...[/element_name]. Return the resulting WML.
std::string convert_to_wml(const std::string &element_name, const std::string &contents);
/// Return true if s is a representation of a truth value
/// (yes/true/...), otherwise false.
bool get_bool(const std::string &s);
/// Return the color the string represents. Return font::NORMAL_COLOUR if
/// the string is empty or can't be matched against any other color.
SDL_Color string_to_color(const std::string &s);
/// Make a best effort to word wrap s. All parts are less than width.
std::vector<std::string> split_in_width(const std::string &s, const int font_size, const unsigned width);
std::string remove_first_space(const std::string& text);
/// Return a lowercase copy of s.
std::string to_lower(const std::string &s);
/// Return a copy of s with the first letter capitalized.
std::string cap(const std::string &s);
/// Prepend all chars with meaning inside attributes with a backslash.
std::string escape(const std::string &s);
/// Return the first word in s, not removing any spaces in the start of
/// it.
std::string get_first_word(const std::string &s);
} // namespace help
namespace {
const config *game_cfg = NULL;
game_data *game_info = NULL;

View file

@ -12,22 +12,13 @@
#ifndef HELP_HPP_INCLUDED
#define HELP_HPP_INCLUDED
#include "config.hpp"
#include "display.hpp"
#include "font.hpp"
#include "map.hpp"
#include "sdl_utils.hpp"
#include "unit_types.hpp"
#include "widgets/button.hpp"
#include "widgets/menu.hpp"
#include "widgets/scrollbar.hpp"
#include <string>
#include <vector>
#include "widgets/widget.hpp"
#include <set>
#include <queue>
#include <map>
#include <list>
struct config;
struct display;
struct game_data;
struct gamemap;
namespace help {
@ -36,467 +27,8 @@ struct help_manager {
~help_manager();
};
/// Generate the help contents from the configurations given to the
/// manager.
void generate_contents();
struct section;
typedef std::vector<section *> section_list;
struct topic_generator;
class topic_text {
mutable std::string text_;
mutable topic_generator *generator_;
public:
~topic_text();
topic_text(): generator_(NULL) {}
topic_text(std::string const &t): text_(t), generator_(NULL) {}
explicit topic_text(topic_generator *g): generator_(g) {}
topic_text &operator=(topic_generator *g);
topic_text(topic_text const &t);
operator std::string() const;
};
/// A topic contains a title, an id and some text.
struct topic {
topic(const std::string &_title, const std::string &_id, const std::string &_text)
: title(_title), id(_id), text(_text) {}
topic(const std::string &_title, const std::string &_id, topic_generator *g)
: title(_title), id(_id), text(g) {}
topic() : title(""), id(""), text("") {}
/// Two topics are equal if their IDs are equal.
bool operator==(const topic &) const;
/// Comparison on the ID.
bool operator<(const topic &) const;
std::string title, id;
topic_text text;
};
typedef std::list<topic> topic_list;
/// A section contains topics and sections along with title and ID.
struct section {
section(const std::string &_title, const std::string &_id, const topic_list &_topics,
const std::vector<section> &_sections);
section() : title(""), id("") {}
section(const section&);
section& operator=(const section&);
~section();
/// Two sections are equal if their IDs are equal.
bool operator==(const section &) const;
/// Comparison on the ID.
bool operator<(const section &) const;
/// Allocate memory for and add the section.
void add_section(const section &s);
void clear();
std::string title, id;
topic_list topics;
section_list sections;
};
/// To be used as a function object to locate sections and topics
/// with a specified ID.
class has_id {
public:
has_id(const std::string &id) : id_(id) {}
bool operator()(const topic &t) { return t.id == id_; }
bool operator()(const section &s) { return s.id == id_; }
bool operator()(const section *s) { return s != NULL && s->id == id_; }
private:
const std::string id_;
};
/// To be used as a function object when sorting topic lists on the title.
class title_less {
public:
bool operator()(const topic &t1, const topic &t2) { return t1.title < t2.title; }
};
struct delete_section {
void operator()(section *s) { delete s; }
};
struct create_section {
section *operator()(const section *s) { return new section(*s); }
section *operator()(const section &s) { return new section(s); }
};
/// The menu to the left in the help browser, where topics can be
/// navigated through and chosen.
class help_menu : public gui::menu {
public:
help_menu(display& disp, const section &toplevel, int max_height=-1);
void bg_backup();
void bg_restore();
int process(int x, int y, bool button,bool up_arrow,bool down_arrow,
bool page_up, bool page_down, int select_item=-1);
/// Overloaded from menu so that the background can be saved.
void set_loc(int x, int y);
/// Overloaded from menu so that the background can be saved.
void set_width(int w);
/// Overloaded from menu so that the background can be saved.
void set_max_height(const int new_height);
/// Make the topic the currently selected one, and expand all
/// sections that need to be expanded to show it.
void select_topic(const topic &t);
/// If a topic has been chosen, return that topic, otherwise
/// NULL. If one topic is returned, it will not be returned again,
/// if it is not re-chosen.
const topic *chosen_topic();
protected:
void handle_event(const SDL_Event &event);
private:
/// Information about an item that is visible in the menu.
struct visible_item {
visible_item(const section *_sec, const std::string &visible_string);
visible_item(const topic *_t, const std::string &visible_string);
// Invariant, one if these should be NULL. The constructors
// enforce it.
const topic *t;
const section *sec;
std::string visible_string;
bool operator==(const visible_item &vis_item) const;
bool operator==(const section &sec) const;
bool operator==(const topic &t) const;
};
/// Regenerate what items are visible by checking what sections are
/// expanded.
void update_visible_items(const section &top_level, unsigned starting_level=0);
/// Return true if the section is expanded.
bool expanded(const section &sec);
/// Mark a section as expanded. Do not update the visible items or
/// anything.
void expand(const section &sec);
/// Contract (close) a section. That is, mark it as not expanded,
/// visible items are not updated.
void contract(const section &sec);
/// Return the string to use as the menu-string for sections at the
/// specified level.
std::string get_string_to_show(const section &sec, const unsigned level);
/// Return the string to use as the menu-string for topics at the
/// specified level.
std::string get_string_to_show(const topic &topic, const unsigned level);
/// Draw the currently visible items.
void display_visible_items();
/// Internal recursive thingie. did_expand will be true if any
/// section was expanded, otherwise untouched.
bool select_topic_internal(const topic &t, const section &sec);
display &disp_;
std::vector<visible_item> visible_items_;
const section &toplevel_;
std::set<const section*> expanded_;
surface_restorer restorer_;
SDL_Rect rect_;
topic const *chosen_topic_;
int internal_width_;
visible_item selected_item_;
bool selected_;
};
/// Thrown when the help system fails to parse something.
struct parse_error {
parse_error(const std::string& msg) : message(msg) {}
std::string message;
};
/// The area where the content is shown in the help browser.
class help_text_area : public gui::widget, public gui::scrollable {
public:
help_text_area(display &disp, const section &toplevel);
/// Display the topic.
void show_topic(const topic &t);
/// Return the ID that is crossreferenced at the (screen)
/// coordinates x, y. If no cross-reference is there, return the
/// empty string.
std::string ref_at(const int x, const int y);
/// Return the width of the area where text fit.
int text_width() const;
void scroll(int pos);
void set_dirty(bool dirty);
/// Scroll the contents up an amount. If how_much is below zero the
/// amount will depend on the height.
void scroll_up(const int how_much=-1);
/// Scroll the contents down an amount. If how_much is below zero
/// the amount will depend on the height.
void scroll_down(const int how_much=-1);
private:
enum ALIGNMENT {LEFT, MIDDLE, RIGHT, HERE};
/// Convert a string to an alignment. Throw parse_error if
/// unsuccesful.
ALIGNMENT str_to_align(const std::string &s);
/// An item that is displayed in the text area. Contains the surface
/// that should be blitted along with some other information.
struct item {
item(surface surface, int x, int y, const std::string text="",
const std::string reference_to="", bool floating=false,
bool box=false, ALIGNMENT alignment=HERE);
item(surface surface, int x, int y,
bool floating, bool box=false, ALIGNMENT=HERE);
/// Relative coordinates of this item.
SDL_Rect rect;
surface surf;
// If this item contains text, this will contain that text.
std::string text;
// If this item contains a cross-reference, this is the id
// of the referenced topic.
std::string ref_to;
// If this item is floating, that is, if things should be filled
// around it.
bool floating;
bool box;
ALIGNMENT align;
};
/// Function object to find an item at the specified coordinates.
class item_at {
public:
item_at(const int x, const int y) : x_(x), y_(y) {}
bool operator()(const item&) const;
private:
const int x_, y_;
};
/// Update the vector with items, creating surfaces for everything
/// and putting things where they belong. parsed_items should be a
/// vector with parsed strings, such as parse_text returns.
void set_items(const std::vector<std::string> &parsed_items,
const std::string &title);
// Create appropriate items from configs. Items will be added to the
// internal vector. These methods check that the necessary
// attributes are specified.
void handle_ref_cfg(const config &cfg);
void handle_img_cfg(const config &cfg);
void handle_bold_cfg(const config &cfg);
void handle_italic_cfg(const config &cfg);
void handle_header_cfg(const config &cfg);
void handle_jump_cfg(const config &cfg);
void handle_format_cfg(const config &cfg);
void handle_event(const SDL_Event &event);
void draw();
void process();
/// Update the scrollbar to take account for the current items.
void update_scrollbar();
/// Get the current amount of scrolling that should be
/// added/substracted from the locations to get the desired effect.
unsigned get_scroll_offset() const;
/// Add an item with text. If ref_dst is something else than the
/// empty string, the text item will be underlined to show that it
/// is a cross-reference. The item will also remember what the
/// reference points to. If font_size is below zero, the default
/// will be used.
void add_text_item(const std::string text, const std::string ref_dst="",
int font_size=-1, bool bold=false, bool italic=false,
SDL_Color color=font::NORMAL_COLOUR);
/// Add an image item with the specified attributes.
void add_img_item(const std::string path, const std::string alignment, const bool floating,
const bool box);
/// Move the current input point to the next line.
void down_one_line();
/// Adjust the heights of the items in the last row to make it look
/// good .
void adjust_last_row();
/// Return the width that remain on the line the current input point is at.
int get_remaining_width();
/// Return the least x coordinate at which something of the
/// specified height can be drawn at the specified y coordinate
/// without interfering with floating images.
int get_min_x(const int y, const int height=0);
/// Analogous with get_min_x but return the maximum X.
int get_max_x(const int y, const int height=0);
/// Find the lowest y coordinate where a floating img of the
/// specified width and at the specified x coordinate can be
/// placed. Start looking at desired_y and continue downwards. Only
/// check against other floating things, since text and inline
/// images only can be above this place if called correctly.
int get_y_for_floating_img(const int width, const int x, const int desired_y);
/// Add an item to the internal list, update the locations and row
/// height.
void add_item(const item& itm);
std::list<item> items_;
std::list<item *> last_row_;
display &disp_;
const section &toplevel_;
topic const *shown_topic_;
const int title_spacing_;
// The current input location when creating items.
std::pair<int, int> curr_loc_;
const unsigned min_row_height_;
unsigned curr_row_height_;
gui::scrollbar scrollbar_;
bool use_scrollbar_;
gui::button uparrow_, downarrow_;
/// The height of all items in total.
int contents_height_;
};
/// A help browser widget.
class help_browser : public gui::widget {
public:
help_browser(display &disp, const section &toplevel);
// Overloaded from widget so that the layout may be adjusted to fit
// the new dimensions.
void set_location(const SDL_Rect& rect);
void set_location(int x, int y);
void set_width(int w);
void set_height(int h);
void set_dirty(bool dirty);
void adjust_layout();
void process();
/// Display the topic with the specified identifier. Open the menu
/// on the right location and display the topic in the text area.
void show_topic(const std::string &topic_id);
private:
/// Update the current cursor, set it to the reference cursor if
/// mousex, mousey is over a cross-reference, otherwise, set it to
/// the normal cursor.
void update_cursor();
void handle_event(const SDL_Event &event);
void show_topic(const topic &t, bool save_in_history=true);
/// Move in the topic history. Pop an element from from and insert
/// it in to. Pop at the fronts if the maximum number of elements is
/// exceeded.
void move_in_history(std::deque<const topic *> &from, std::deque<const topic *> &to);
display &disp_;
help_menu menu_;
help_text_area text_area_;
const section &toplevel_;
bool ref_cursor_; // If the cursor currently is the hyperlink cursor.
std::deque<const topic *> back_topics_, forward_topics_;
gui::button back_button_, forward_button_;
topic const *shown_topic_;
};
// Generator stuff below. Maybe move to a separate file? This one is
// getting crowded. Dunno if much more is needed though so I'll wait and
// see.
/// Dispatch generators to their appropriate functions.
std::vector<section> generate_sections(const std::string &generator);
std::vector<topic> generate_topics(const std::string &generator);
std::string generate_topic_text(const std::string &generator);
std::string generate_about_text();
std::string generate_traits_text();
std::vector<topic> generate_unit_topics();
enum UNIT_DESCRIPTION_TYPE {FULL_DESCRIPTION, NO_DESCRIPTION, NON_REVEALING_DESCRIPTION};
/// Return the type of description that should be shown for a unit of
/// the given kind. This method is intended to filter out information
/// about units that should not be shown, for example due to not being
/// encountered.
UNIT_DESCRIPTION_TYPE description_type(const unit_type &type);
std::vector<topic> generate_ability_topics();
std::vector<topic> generate_weapon_special_topics();
std::vector<topic> generate_terrains_topics();
/// Parse a help config, return the top level section. Return an empty
/// section if cfg is NULL.
section parse_config(const config *cfg);
/// Recursive function used by parse_config.
void parse_config_internal(const config *help_cfg, const config *section_cfg,
section &sec, int level=0);
/// Return true if the section with id section_id is referenced from
/// another section in the config, or the toplevel.
bool section_is_referenced(const std::string &section_id, const config &cfg);
/// Return true if the topic with id topic_id is referenced from
/// another section in the config, or the toplevel.
bool topic_is_referenced(const std::string &topic_id, const config &cfg);
/// Search for the topic with the specified identifier in the section
/// and its subsections. Return the found topic, or NULL if none could
/// be found.
const topic *find_topic(const section &sec, const std::string &id);
/// Search for the section with the specified identifier in the section
/// and its subsections. Return the found section or NULL if none could
/// be found.
const section *find_section(const section &sec, const std::string &id);
/// Parse a text string. Return a vector with the different parts of the
/// text. Each markup item is a separate part while the text between
/// markups are separate parts.
std::vector<std::string> parse_text(const std::string &text);
/// Convert the contents to wml attributes, surrounded within
/// [element_name]...[/element_name]. Return the resulting WML.
std::string convert_to_wml(const std::string &element_name, const std::string &contents);
/// Return true if s is a representation of a truth value
/// (yes/true/...), otherwise false.
bool get_bool(const std::string &s);
/// Return the color the string represents. Return font::NORMAL_COLOUR if
/// the string is empty or can't be matched against any other color.
SDL_Color string_to_color(const std::string &s);
/// Make a best effort to word wrap s. All parts are less than width.
std::vector<std::string> split_in_width(const std::string &s, const int font_size,
const unsigned width);
std::string remove_first_space(const std::string& text);
/// Return a lowercase copy of s.
std::string to_lower(const std::string &s);
/// Return a copy of s with the first letter capitalized.
std::string cap(const std::string &s);
/// Prepend all chars with meaning inside attributes with a backslash.
std::string escape(const std::string &s);
/// Return the first word in s, not removing any spaces in the start of
/// it.
std::string get_first_word(const std::string &s);
/// Open a help dialog showing the topics with ids topics_to_show and
/// the sections with ids sections_to_show. Subsections and subtopics of
/// the sections will be added recursively according to the help config.