The Battle for Wesnoth  1.15.2+dev
help_menu.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 #include "help/help_menu.hpp"
16 
17 #include "game_config.hpp" // for menu_contract, menu_expand
18 #include "help/help_impl.hpp" // for section, topic, topic_list, etc
19 #include "sound.hpp" // for play_UI_sound
20 #include "wml_separators.hpp" // for IMG_TEXT_SEPARATOR, etc
21 
22 #include <algorithm> // for find
23 #include <iostream> // for basic_ostream, operator<<, etc
24 #include <list> // for _List_const_iterator, etc
25 #include <utility> // for pair
26 #include <SDL2/SDL.h>
27 
28 class CVideo; // lines 56-56
29 
30 namespace help {
31 
32 help_menu::help_menu(CVideo &video, const section& toplevel, int max_height) :
33  gui::menu(video, empty_string_vector, true, max_height, -1, nullptr, &gui::menu::bluebg_style),
34  visible_items_(),
35  toplevel_(toplevel),
36  expanded_(),
37  restorer_(),
38  chosen_topic_(nullptr),
39  selected_item_(&toplevel, "")
40 {
41  silent_ = true; //silence the default menu sounds
44  if (!visible_items_.empty())
46 }
47 
48 bool help_menu::expanded(const section &sec)
49 {
50  return expanded_.find(&sec) != expanded_.end();
51 }
52 
53 void help_menu::expand(const section &sec)
54 {
55  if (sec.id != "toplevel" && expanded_.insert(&sec).second) {
57  }
58 }
59 
60 void help_menu::contract(const section &sec)
61 {
62  if (expanded_.erase(&sec)) {
64  }
65 }
66 
67 void help_menu::update_visible_items(const section &sec, unsigned level)
68 {
69  if (level == 0) {
70  // Clear if this is the top level, otherwise append items.
71  visible_items_.clear();
72  }
73  for (const auto &s : sec.sections) {
74  if (is_visible_id(s.id)) {
75  const std::string vis_string = get_string_to_show(s, level + 1);
76  visible_items_.emplace_back(&s, vis_string);
77  if (expanded(s)) {
78  update_visible_items(s, level + 1);
79  }
80  }
81  }
82  topic_list::const_iterator topic_it;
83  for (topic_it = sec.topics.begin(); topic_it != sec.topics.end(); ++topic_it) {
84  if (is_visible_id(topic_it->id)) {
85  const std::string vis_string = get_string_to_show(*topic_it, level + 1);
86  visible_items_.emplace_back(&(*topic_it), vis_string);
87  }
88  }
89 }
90 
91 std::string help_menu::indent_list(const std::string& icon, const unsigned level) {
92  std::stringstream to_show;
93  for (unsigned i = 1; i < level; ++i) {
94  to_show << " "; // Indent 4 spaces
95  }
96 
97  to_show << IMG_TEXT_SEPARATOR << IMAGE_PREFIX << icon;
98  return to_show.str();
99 }
100 
101 std::string help_menu::get_string_to_show(const section &sec, const unsigned level)
102 {
103  std::stringstream to_show;
104  to_show << indent_list(expanded(sec) ? open_section_img : closed_section_img, level)
105  << IMG_TEXT_SEPARATOR << sec.title;
106  return to_show.str();
107 }
108 
109 std::string help_menu::get_string_to_show(const topic &topic, const unsigned level)
110 {
111  std::stringstream to_show;
112  to_show << indent_list(topic_img, level)
113  << IMG_TEXT_SEPARATOR << topic.title;
114  return to_show.str();
115 }
116 
118 {
119  topic_list::const_iterator tit =
120  std::find(sec.topics.begin(), sec.topics.end(), t);
121  if (tit != sec.topics.end()) {
122  // topic starting with ".." are assumed as rooted in the parent section
123  // and so only expand the parent when selected
124  if (t.id.size()<2 || t.id[0] != '.' || t.id[1] != '.')
125  expand(sec);
126  return true;
127  }
128  for (const auto &s : sec.sections) {
129  if (select_topic_internal(t, s)) {
130  expand(sec);
131  return true;
132  }
133  }
134  return false;
135 }
136 
138 {
139  if (selected_item_ == t) {
140  // The requested topic is already selected.
141  return;
142  }
145  for (std::vector<visible_item>::const_iterator it = visible_items_.begin();
146  it != visible_items_.end(); ++it) {
147  if (*it == t) {
148  selected_item_ = *it;
149  break;
150  }
151  }
153  }
154 }
155 
157 {
158  int res = menu::process();
159  int mousex, mousey;
160  SDL_GetMouseState(&mousex,&mousey);
161 
162  if (!visible_items_.empty() &&
163  static_cast<std::size_t>(res) < visible_items_.size()) {
164 
166  const section* sec = selected_item_.sec;
167  if (sec != nullptr) {
168  // Check how we click on the section
169  int x = mousex - menu::location().x;
170 
171  const std::string icon_img = expanded(*sec) ? open_section_img : closed_section_img;
172  // we remove the right thickness (ne present between icon and text)
173  int text_start = style_->item_size(indent_list(icon_img, sec->level)).w - style_->get_thickness();
174 
175  // NOTE: if you want to forbid click to the left of the icon
176  // also check x >= text_start-image_width(icon_img)
177  if (menu::double_clicked() || x < text_start) {
178  // Open or close a section if we double-click on it
179  // or do simple click on the icon.
180  expanded(*sec) ? contract(*sec) : expand(*sec);
183  } else if (x >= text_start){
184  // click on title open the topic associated to this section
186  }
187  } else if (selected_item_.t != nullptr) {
188  /// Choose a topic if it is clicked.
190  }
191  }
192  return res;
193 }
194 
196 {
197  const topic *ret = chosen_topic_;
198  chosen_topic_ = nullptr;
199  return ret;
200 }
201 
203 {
204  std::vector<std::string> menu_items;
205  for(std::vector<visible_item>::const_iterator items_it = visible_items_.begin(),
206  end = visible_items_.end(); items_it != end; ++items_it) {
207  std::string to_show = items_it->visible_string;
208  if (selected_item_ == *items_it)
209  to_show = std::string("*") + to_show;
210  menu_items.push_back(to_show);
211  }
212  set_items(menu_items, false, true);
213 }
214 
215 help_menu::visible_item::visible_item(const section *_sec, const std::string &vis_string) :
216  t(nullptr), sec(_sec), visible_string(vis_string) {}
217 
218 help_menu::visible_item::visible_item(const topic *_t, const std::string &vis_string) :
219  t(_t), sec(nullptr), visible_string(vis_string) {}
220 
222 {
223  return sec != nullptr && *sec == _sec;
224 }
225 
227 {
228  return t != nullptr && *t == _t;
229 }
230 
232 {
233  return t == vis_item.t && sec == vis_item.sec;
234 }
235 
236 } // end namespace help
void contract(const section &sec)
Contract (close) a section.
Definition: help_menu.cpp:60
std::string get_string_to_show(const section &sec, const unsigned level)
Return the string to use as the menu-string for sections at the specified level.
Definition: help_menu.cpp:101
char const IMG_TEXT_SEPARATOR
std::string id
Definition: help_impl.hpp:160
const std::string open_section_img
Definition: help_impl.cpp:86
const std::string topic_img
Definition: help_impl.cpp:84
visible_item selected_item_
Definition: help_menu.hpp:99
topic const * chosen_topic_
Definition: help_menu.hpp:98
visible_item(const section *_sec, const std::string &visible_string)
Definition: help_menu.cpp:215
const std::string closed_section_img
Definition: help_impl.cpp:85
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:141
const std::string menu_expand
Definition: video.hpp:31
General purpose widgets.
virtual SDL_Rect item_size(const std::string &item) const
Definition: menu.cpp:793
std::vector< std::string > empty_string_vector
Definition: help_impl.cpp:77
bool expanded(const section &sec)
Return true if the section is expanded.
Definition: help_menu.cpp:48
bool is_visible_id(const std::string &id)
Definition: help_impl.cpp:1416
char const IMAGE_PREFIX
section_list sections
Definition: help_impl.hpp:162
std::string id
Definition: help_impl.hpp:132
void process(int mousex, int mousey)
Definition: tooltips.cpp:193
void display_visible_items()
Draw the currently visible items.
Definition: help_menu.cpp:202
std::string title
Definition: help_impl.hpp:160
const section & toplevel_
Definition: help_menu.hpp:95
std::string indent_list(const std::string &icon, const unsigned level)
Return the string to use as the prefix for the icon part of the menu-string at the specified level...
Definition: help_menu.cpp:91
Information about an item that is visible in the menu.
Definition: help_menu.hpp:49
void expand(const section &sec)
Mark a section as expanded.
Definition: help_menu.cpp:53
help_menu(CVideo &video, const section &toplevel, int max_height=-1)
Definition: help_menu.cpp:32
virtual void set_items(const std::vector< std::string > &items, bool strip_spaces=true, bool keep_viewport=false)
Set new items to show and redraw/recalculate everything.
Definition: menu.cpp:436
std::set< const section * > expanded_
Definition: help_menu.hpp:96
std::size_t i
Definition: function.cpp:933
static map_location::DIRECTION s
std::vector< visible_item > visible_items_
Definition: help_menu.hpp:94
const std::string menu_contract
bool operator==(const visible_item &vis_item) const
Definition: help_menu.cpp:231
void select_topic(const topic &t)
Make the topic the currently selected one, and expand all sections that need to be expanded to show i...
Definition: help_menu.cpp:137
double t
Definition: astarsearch.cpp:64
bool find(E event, F functor)
Tests whether an event handler is available.
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:1115
void play_UI_sound(const std::string &files)
Definition: sound.cpp:1019
A topic contains a title, an id and some text.
Definition: help_impl.hpp:107
void update_visible_items(const section &top_level, unsigned starting_level=0)
Regenerate what items are visible by checking what sections are expanded.
Definition: help_menu.cpp:67
const topic * chosen_topic()
If a topic has been chosen, return that topic, otherwise nullptr.
Definition: help_menu.cpp:195
bool silent_
Definition: menu.hpp:215
Definition: help.cpp:55
std::string title
Definition: help_impl.hpp:132
bool select_topic_internal(const topic &t, const section &sec)
Internal recursive thingie.
Definition: help_menu.cpp:117
topic_list topics
Definition: help_impl.hpp:161
style * style_
Definition: menu.hpp:214
std::size_t get_thickness() const
Definition: menu_style.cpp:58
help::section default_toplevel
Definition: help_impl.cpp:68