The Battle for Wesnoth  1.19.4+dev
help_menu.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
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 #include "help/help_menu.hpp"
17 
18 #include "game_config.hpp" // for menu_contract, menu_expand
19 #include "help/help_impl.hpp" // for section, topic, topic_list, etc
20 #include "sound.hpp" // for play_UI_sound
21 #include "sdl/input.hpp" // for get_mouse_state
22 
23 #include <algorithm> // for find
24 #include <list> // for _List_const_iterator, etc
25 #include <utility> // for pair
26 
27 namespace help {
28 
29 help_menu::help_menu(const section& toplevel, int max_height) :
30  gui::menu(true, max_height, -1, &gui::menu::bluebg_style),
31  visible_items_(),
32  toplevel_(toplevel),
33  expanded_(),
34  chosen_topic_(nullptr),
35  selected_item_(&toplevel, 0)
36 {
37  silent_ = true; //silence the default menu sounds
40  if (!visible_items_.empty())
42 }
43 
44 bool help_menu::expanded(const section &sec) const
45 {
46  return expanded_.find(&sec) != expanded_.end();
47 }
48 
49 void help_menu::expand(const section &sec)
50 {
51  if (sec.id != "toplevel" && expanded_.insert(&sec).second) {
53  }
54 }
55 
56 void help_menu::contract(const section &sec)
57 {
58  if (expanded_.erase(&sec)) {
60  }
61 }
62 
63 void help_menu::update_visible_items(const section &sec, unsigned level)
64 {
65  if (level == 0) {
66  // Clear if this is the top level, otherwise append items.
67  visible_items_.clear();
68  }
69  for (const auto &s : sec.sections) {
70  if (is_visible_id(s.id)) {
71  visible_items_.emplace_back(&s, level + 1);
72  if (expanded(s)) {
74  }
75  }
76  }
77  for (const auto &t : sec.topics) {
78  if (is_visible_id(t.id)) {
79  visible_items_.emplace_back(&t, level + 1);
80  }
81  }
82 }
83 
85 {
86  topic_list::const_iterator tit =
87  std::find(sec.topics.begin(), sec.topics.end(), t);
88  if (tit != sec.topics.end()) {
89  // topic starting with ".." are assumed as rooted in the parent section
90  // and so only expand the parent when selected
91  if (t.id.size()<2 || t.id[0] != '.' || t.id[1] != '.')
92  expand(sec);
93  return true;
94  }
95  for (const auto &s : sec.sections) {
96  if (select_topic_internal(t, s)) {
97  expand(sec);
98  return true;
99  }
100  }
101  return false;
102 }
103 
105 {
106  if (selected_item_ == t) {
107  // The requested topic is already selected.
108  return;
109  }
112  for (std::vector<visible_item>::const_iterator it = visible_items_.begin();
113  it != visible_items_.end(); ++it) {
114  if (*it == t) {
115  selected_item_ = *it;
116  break;
117  }
118  }
120  }
121 }
122 
124 {
125  int res = menu::process();
126  int mousex, mousey;
127  sdl::get_mouse_state(&mousex, &mousey);
128 
129  if (!visible_items_.empty()
130  && static_cast<std::size_t>(res) < visible_items_.size())
131  {
133  const section* sec = selected_item_.sec;
134  if (sec != nullptr) {
135  // Behavior of the UI, for section headings:
136  // * user single-clicks on the text part: show the ".." topic in the right-hand pane
137  // * user single-clicks on the icon (or to the left of it): expand or collapse the tree view
138  // * user double-clicks anywhere: expand or collapse the tree view
139  // * note: the first click of the double-click has the single-click effect too
140  if (menu::double_clicked() || hit_on_indent_or_icon(static_cast<std::size_t>(res), mousex)) {
141  // Open or close a section if we double-click on it
142  // or do simple click on the icon.
143  expanded(*sec) ? contract(*sec) : expand(*sec);
146  } else {
147  // click on title open the topic associated to this section
149  }
150  } else if (selected_item_.t != nullptr) {
151  // Choose a topic if it is clicked.
153  }
154  }
155  return res;
156 }
157 
159 {
160  const topic *ret = chosen_topic_;
161  chosen_topic_ = nullptr;
162  return ret;
163 }
164 
166 {
167  std::vector<gui::indented_menu_item> menu_items;
168  utils::optional<std::size_t> selected;
169  for(std::vector<visible_item>::const_iterator items_it = visible_items_.begin(),
170  end = visible_items_.end(); items_it != end; ++items_it) {
171  if (selected_item_ == *items_it)
172  selected = menu_items.size();
173  menu_items.push_back(items_it->get_menu_item(*this));
174  }
175  set_items(menu_items, selected);
176 }
177 
179  t(nullptr), sec(_sec), level(lev) {}
180 
182  t(_t), sec(nullptr), level(lev) {}
183 
185 {
186  if(sec) {
187  const auto& img = parent.expanded(*sec) ? open_section_img : closed_section_img;
188  return {level, img, sec->title};
189  }
190 
191  // As sec was a nullptr, this must have a non-null topic
192  return {level, topic_img, t->title};
193 }
194 
196 {
197  return sec != nullptr && *sec == _sec;
198 }
199 
201 {
202  return t != nullptr && *t == _t;
203 }
204 
206 {
207  return t == vis_item.t && sec == vis_item.sec;
208 }
209 
210 } // end namespace help
double t
Definition: astarsearch.cpp:63
virtual void set_items(const std::vector< indented_menu_item > &items, utils::optional< std::size_t > selected)
Set new items to show and redraw/recalculate everything.
Definition: menu.cpp:121
bool silent_
Definition: menu.hpp:171
bool hit_on_indent_or_icon(std::size_t row_index, int x) const
Returns true if a mouse-click with the given x-coordinate, and an appropriate y-coordinate would lie ...
Definition: menu.cpp:519
The menu to the left in the help browser, where topics can be navigated through and chosen.
Definition: help_menu.hpp:33
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:63
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:104
void expand(const section &sec)
Mark a section as expanded.
Definition: help_menu.cpp:49
topic const * chosen_topic_
Definition: help_menu.hpp:105
bool expanded(const section &sec) const
Return true if the section is expanded.
Definition: help_menu.cpp:44
const section & toplevel_
Definition: help_menu.hpp:103
std::set< const section * > expanded_
Definition: help_menu.hpp:104
bool select_topic_internal(const topic &t, const section &sec)
Internal recursive thingie.
Definition: help_menu.cpp:84
const topic * chosen_topic()
If a topic has been chosen, return that topic, otherwise nullptr.
Definition: help_menu.cpp:158
std::vector< visible_item > visible_items_
Definition: help_menu.hpp:102
help_menu(const section &toplevel, int max_height=-1)
Definition: help_menu.cpp:29
void contract(const section &sec)
Contract (close) a section.
Definition: help_menu.cpp:56
void display_visible_items()
Draw the currently visible items.
Definition: help_menu.cpp:165
visible_item selected_item_
Definition: help_menu.hpp:106
Contains functions for cleanly handling SDL input.
std::string selected
const std::string menu_expand
const std::string menu_contract
General purpose widgets.
Definition: help.cpp:53
const std::string open_section_img
Definition: help_impl.cpp:85
bool is_visible_id(const std::string &id)
Definition: help_impl.cpp:1630
const std::string closed_section_img
Definition: help_impl.cpp:84
const std::string topic_img
Definition: help_impl.cpp:83
help::section default_toplevel
Definition: help_impl.cpp:68
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:1298
uint32_t get_mouse_state(int *x, int *y)
A wrapper for SDL_GetMouseState that gives coordinates in draw space.
Definition: input.cpp:27
void play_UI_sound(const std::string &files)
Definition: sound.cpp:1066
void process(int mousex, int mousey)
Definition: tooltips.cpp:340
The only kind of row still supported by the menu class.
Definition: menu.hpp:33
Information about an item that is visible in the menu.
Definition: help_menu.hpp:53
visible_item(const section *_sec, int level)
Definition: help_menu.cpp:178
gui::indented_menu_item get_menu_item(const help_menu &parent) const
Definition: help_menu.cpp:184
bool operator==(const visible_item &sec) const
Definition: help_menu.cpp:205
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:146
section_list sections
Definition: help_impl.hpp:166
std::string id
Definition: help_impl.hpp:164
topic_list topics
Definition: help_impl.hpp:165
A topic contains a title, an id and some text.
Definition: help_impl.hpp:113
static map_location::DIRECTION s