The Battle for Wesnoth  1.15.7+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, "", 0)
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, level + 1);
77  if (expanded(s)) {
78  update_visible_items(s, level + 1);
79  }
80  }
81  }
82  for (const auto &t : sec.topics) {
83  if (is_visible_id(t.id)) {
84  const std::string vis_string = get_string_to_show(t, level + 1);
85  visible_items_.emplace_back(&t, vis_string, level + 1);
86  }
87  }
88 }
89 
90 std::string help_menu::indent_list(const std::string& icon, const unsigned level) {
91  std::stringstream to_show;
92  for (unsigned i = 1; i < level; ++i) {
93  to_show << " "; // Indent 4 spaces
94  }
95 
96  to_show << IMG_TEXT_SEPARATOR << IMAGE_PREFIX << icon;
97  return to_show.str();
98 }
99 
101 {
102  std::stringstream to_show;
103  to_show << indent_list(expanded(sec) ? open_section_img : closed_section_img, level)
104  << IMG_TEXT_SEPARATOR << sec.title;
105  return to_show.str();
106 }
107 
109 {
110  std::stringstream to_show;
111  to_show << indent_list(topic_img, level)
112  << IMG_TEXT_SEPARATOR << topic.title;
113  return to_show.str();
114 }
115 
117 {
118  topic_list::const_iterator tit =
119  std::find(sec.topics.begin(), sec.topics.end(), t);
120  if (tit != sec.topics.end()) {
121  // topic starting with ".." are assumed as rooted in the parent section
122  // and so only expand the parent when selected
123  if (t.id.size()<2 || t.id[0] != '.' || t.id[1] != '.')
124  expand(sec);
125  return true;
126  }
127  for (const auto &s : sec.sections) {
128  if (select_topic_internal(t, s)) {
129  expand(sec);
130  return true;
131  }
132  }
133  return false;
134 }
135 
137 {
138  if (selected_item_ == t) {
139  // The requested topic is already selected.
140  return;
141  }
144  for (std::vector<visible_item>::const_iterator it = visible_items_.begin();
145  it != visible_items_.end(); ++it) {
146  if (*it == t) {
147  selected_item_ = *it;
148  break;
149  }
150  }
152  }
153 }
154 
156 {
157  int res = menu::process();
158  int mousex, mousey;
159  SDL_GetMouseState(&mousex,&mousey);
160 
161  if (!visible_items_.empty() &&
162  static_cast<std::size_t>(res) < visible_items_.size()) {
163 
165  const section* sec = selected_item_.sec;
166  if (sec != nullptr) {
167  // Behavior of the UI, for section headings:
168  // * user single-clicks on the text part: show the ".." topic in the right-hand pane
169  // * user single-clicks on the icon (or to the left of it): expand or collapse the tree view
170  // * user double-clicks anywhere: expand or collapse the tree view
171  // * note: the first click of the double-click has the single-click effect too
172  int x = mousex - menu::location().x;
173 
174  const std::string icon_img = expanded(*sec) ? open_section_img : closed_section_img;
175  // the "thickness" is the width of the left border
176  int text_start = style_->item_size(indent_list(icon_img, selected_item_.level)).w - style_->get_thickness();
177 
178  // NOTE: if you want to forbid click to the left of the icon
179  // also check x >= text_start-image_width(icon_img)
180  if (menu::double_clicked() || x < text_start) {
181  // Open or close a section if we double-click on it
182  // or do simple click on the icon.
183  expanded(*sec) ? contract(*sec) : expand(*sec);
186  } else if (x >= text_start){
187  // click on title open the topic associated to this section
189  }
190  } else if (selected_item_.t != nullptr) {
191  /// Choose a topic if it is clicked.
193  }
194  }
195  return res;
196 }
197 
199 {
200  const topic *ret = chosen_topic_;
201  chosen_topic_ = nullptr;
202  return ret;
203 }
204 
206 {
207  std::vector<std::string> menu_items;
208  for(std::vector<visible_item>::const_iterator items_it = visible_items_.begin(),
209  end = visible_items_.end(); items_it != end; ++items_it) {
210  std::string to_show = items_it->visible_string;
211  if (selected_item_ == *items_it)
212  to_show = std::string("*") + to_show;
213  menu_items.push_back(to_show);
214  }
215  set_items(menu_items, false, true);
216 }
217 
218 help_menu::visible_item::visible_item(const section *_sec, const std::string &vis_string, int lev) :
219  t(nullptr), sec(_sec), visible_string(vis_string), level(lev) {}
220 
221 help_menu::visible_item::visible_item(const topic *_t, const std::string &vis_string, int lev) :
222  t(_t), sec(nullptr), visible_string(vis_string), level(lev) {}
223 
225 {
226  return sec != nullptr && *sec == _sec;
227 }
228 
230 {
231  return t != nullptr && *t == _t;
232 }
233 
235 {
236  return t == vis_item.t && sec == vis_item.sec;
237 }
238 
239 } // 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:100
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:100
topic const * chosen_topic_
Definition: help_menu.hpp:99
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:142
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
visible_item(const section *_sec, const std::string &visible_string, int level)
Definition: help_menu.cpp:218
bool is_visible_id(const std::string &id)
Definition: help_impl.cpp:1465
char const IMAGE_PREFIX
section_list sections
Definition: help_impl.hpp:162
std::string id
Definition: help_impl.hpp:133
void process(int mousex, int mousey)
Definition: tooltips.cpp:193
void display_visible_items()
Draw the currently visible items.
Definition: help_menu.cpp:205
std::string title
Definition: help_impl.hpp:160
const section & toplevel_
Definition: help_menu.hpp:96
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:90
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:97
std::size_t i
Definition: function.cpp:933
static map_location::DIRECTION s
std::vector< visible_item > visible_items_
Definition: help_menu.hpp:95
const std::string menu_contract
bool operator==(const visible_item &vis_item) const
Definition: help_menu.cpp:234
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:136
double t
Definition: astarsearch.cpp:64
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:1162
void play_UI_sound(const std::string &files)
Definition: sound.cpp:1051
A topic contains a title, an id and some text.
Definition: help_impl.hpp:108
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:198
bool silent_
Definition: menu.hpp:215
Definition: help.cpp:55
std::string title
Definition: help_impl.hpp:133
bool select_topic_internal(const topic &t, const section &sec)
Internal recursive thingie.
Definition: help_menu.cpp:116
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:69