The Battle for Wesnoth  1.19.0-dev
menu.hpp
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 #pragma once
17 
18 #include <optional>
19 #include <map>
20 #include <set>
21 
22 #include "scrollarea.hpp"
23 
24 namespace gui {
25 
26 /**
27  * The only kind of row still supported by the menu class.
28  *
29  * If comparing to 1.17.24 or before, these three items were held as a single string, thus a single member
30  * of the "fields" and a single "column" of the multi-column support.
31  */
33 {
34  /** An amount of blank space at the start of the row, measured in tab-stops (so 1 is around 4 en-widths) */
36  /** If non-empty, a picture to display before the text */
37  std::string icon;
38  std::string text;
39 };
40 
41 /**
42  * Superclass of the help_menu, which displays the left-hand pane of the GUI1 help browser.
43  * Historically a more generic class, but now only used for that singular purpose.
44  */
45 class menu : public scrollarea
46 {
47 public:
48 
50  //basic menu style
51  class style
52  {
53  public:
54  style();
55  virtual ~style();
56  virtual void init() {}
57 
58  virtual SDL_Rect item_size(const indented_menu_item& imi) const;
59  virtual void draw_row_bg(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
60  virtual void draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
61  std::size_t get_font_size() const;
62  std::size_t get_cell_padding() const;
63  std::size_t get_thickness() const;
64 
65  protected:
66  std::size_t font_size_;
67  std::size_t cell_padding_;
68  std::size_t thickness_; //additional cell padding for style use only
69 
72  };
73 
74  //image-border selection style
75  class imgsel_style : public style
76  {
77  public:
78  imgsel_style(const std::string &img_base, bool has_bg,
79  int normal_rgb, int selected_rgb,
80  double normal_alpha, double selected_alpha);
81  virtual ~imgsel_style();
82 
83  virtual SDL_Rect item_size(const indented_menu_item& imi) const;
84  virtual void draw_row_bg(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
85  virtual void draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
86 
87  virtual void init() { load_images(); }
88  bool load_images();
89  void unload_images();
90 
91  protected:
92  const std::string img_base_;
93  std::map<std::string,texture> img_map_;
94 
95  private:
96  bool load_image(const std::string &img_sub);
102  };
103 
104  friend class style;
105  friend class imgsel_style;
108 
109  struct item
110  {
111  item(const indented_menu_item& fields, std::size_t id)
112  : fields(fields), id(id)
113  {}
114 
116  std::size_t id;
117  };
118 
119  menu(
120  bool click_selects=false, int max_height=-1, int max_width=-1,
121  style *menu_style=nullptr, const bool auto_join=true);
122 
123  /** Default implementation, but defined out-of-line for efficiency reasons. */
124  ~menu();
125 
126  int selection() const;
127 
128  void move_selection(std::size_t id);
129  void move_selection_keeping_viewport(std::size_t id);
130  void reset_selection();
131 
132  /**
133  * Set new items to show and redraw/recalculate everything. The menu tries
134  * to keep the selection at the same position as it were before the items
135  * were set.
136  */
137  virtual void set_items(const std::vector<indented_menu_item>& items, std::optional<std::size_t> selected);
138 
139  /**
140  * Set a new max height for this menu. Note that this does not take
141  * effect immediately, only after certain operations that clear
142  * everything, such as set_items().
143  */
144  void set_max_height(const int new_max_height);
145  void set_max_width(const int new_max_width);
146 
147  int get_max_height() const { return max_height_; }
148  int get_max_width() const { return max_width_; }
149 
150  std::size_t number_of_items() const { return items_.size(); }
151 
152  int process();
153 
154  bool double_clicked();
155 
156  void set_click_selects(bool value);
157  void set_numeric_keypress_selection(bool value);
158 
159  // scrollarea override
160  void scroll(unsigned int pos) override;
161 
162 protected:
163  virtual void handle_event(const SDL_Event& event) override;
164  void set_inner_location(const SDL_Rect& rect) override;
165 
166  bool requires_event_focus(const SDL_Event *event=nullptr) const override;
167  int widest_row_width() const;
168  virtual void draw_row(const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
169 
171  bool silent_;
172 
173  int hit(int x, int y) const;
174 
175  /**
176  * Returns true if a mouse-click with the given x-coordinate, and an
177  * appropriate y-coordinate would lie within the indent or icon part of
178  * the given row.
179  *
180  * The unusual combination of arguments fit with this being called when
181  * handling a mouse event, where we already know which row was selected,
182  * and are just inquiring a bit more about the details of that row.
183  */
184  bool hit_on_indent_or_icon(std::size_t row_index, int x) const;
185 
186  void invalidate_row(std::size_t id);
187  void invalidate_row_pos(std::size_t pos);
188 
189 private:
190  std::size_t max_items_onscreen() const;
191 
193  mutable int max_items_, item_height_;
194 
196  void key_press(SDL_Keycode key);
197 
198  std::vector<item> items_;
199  std::vector<std::size_t> item_pos_;
200 
201  /**
202  * Cached return value of widest_row_width(), calculated on demand when calling that function.
203  */
204  mutable std::optional<int> widest_row_width_;
205 
206  std::size_t selected_;
208  bool out_;
210  //std::set<std::size_t> undrawn_items_;
211 
213 
215 
216  void draw_contents() override;
217 
218  mutable std::map<int,SDL_Rect> itemRects_;
219 
220  SDL_Rect get_item_rect(int item) const;
221  SDL_Rect get_item_rect_internal(std::size_t pos) const;
222  std::size_t get_item_height_internal(const indented_menu_item& imi) const;
223  std::size_t get_item_height(int item) const;
224  int items_start() const;
225 
226  int items_end() const;
227  int items_height() const;
228 
230 
231  /**
232  * variable which determines whether a numeric keypress should
233  * select an item on the dialog
234  */
236  // These two variables are used to get the correct double click
237  // behavior so that a click that causes one double click won't be
238  // counted as a first click in the "next" double click.
241 
242  //ellipsis calculation is slightly off, so default to false
244 
245  /**
246  * Set new items to show.
247  */
248  void fill_items(const std::vector<indented_menu_item>& imi);
249 
250  void update_size();
252  void set_selection_pos(std::size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
253  void move_selection_to(std::size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
254  void move_selection_up(std::size_t dep);
255  void move_selection_down(std::size_t dep);
256 
257  std::set<int> invalid_;
258 };
259 
260 }
std::map< std::string, texture > img_map_
Definition: menu.hpp:93
const std::string img_base_
Definition: menu.hpp:92
virtual SDL_Rect item_size(const indented_menu_item &imi) const
Definition: menu_style.cpp:213
virtual void draw_row(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu_style.cpp:124
imgsel_style(const std::string &img_base, bool has_bg, int normal_rgb, int selected_rgb, double normal_alpha, double selected_alpha)
Definition: menu_style.cpp:43
virtual void init()
Definition: menu.hpp:87
bool load_image(const std::string &img_sub)
Definition: menu_style.cpp:57
virtual void draw_row_bg(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu_style.cpp:114
virtual SDL_Rect item_size(const indented_menu_item &imi) const
Definition: menu.cpp:438
std::size_t get_thickness() const
Definition: menu_style.cpp:55
std::size_t get_font_size() const
Definition: menu_style.cpp:53
std::size_t font_size_
Definition: menu.hpp:66
double normal_alpha_
Definition: menu.hpp:71
double selected_alpha_
Definition: menu.hpp:71
virtual void draw_row_bg(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:466
std::size_t get_cell_padding() const
Definition: menu_style.cpp:54
std::size_t thickness_
Definition: menu.hpp:68
int normal_rgb_
Definition: menu.hpp:70
virtual void init()
Definition: menu.hpp:56
int selected_rgb_
Definition: menu.hpp:70
virtual ~style()
Definition: menu_style.cpp:41
std::size_t cell_padding_
Definition: menu.hpp:67
virtual void draw_row(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:489
Superclass of the help_menu, which displays the left-hand pane of the GUI1 help browser.
Definition: menu.hpp:46
void reset_selection()
Definition: menu.cpp:262
bool requires_event_focus(const SDL_Event *event=nullptr) const override
Definition: menu.cpp:301
int max_items_
Definition: menu.hpp:193
int process()
Definition: menu.cpp:405
void draw_contents() override
Definition: menu.cpp:578
bool show_result_
Definition: menu.hpp:212
void move_selection_up(std::size_t dep)
Definition: menu.cpp:227
bool click_selects_
Definition: menu.hpp:207
std::size_t get_item_height_internal(const indented_menu_item &imi) const
Definition: menu.cpp:649
std::optional< int > widest_row_width_
Cached return value of widest_row_width(), calculated on demand when calling that function.
Definition: menu.hpp:204
SDL_Rect get_item_rect_internal(std::size_t pos) const
Definition: menu.cpp:605
int widest_row_width() const
Definition: menu.cpp:504
void set_max_width(const int new_max_width)
Definition: menu.cpp:158
bool out_
Definition: menu.hpp:208
int items_height() const
std::size_t selected_
Definition: menu.hpp:206
int item_height_
Definition: menu.hpp:193
void set_selection_pos(std::size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT)
Definition: menu.cpp:206
void set_max_height(const int new_max_height)
Set a new max height for this menu.
Definition: menu.cpp:150
std::vector< std::size_t > item_pos_
Definition: menu.hpp:199
bool last_was_doubleclick_
Definition: menu.hpp:240
std::map< int, SDL_Rect > itemRects_
Definition: menu.hpp:218
void adjust_viewport_to_selection()
Definition: menu.cpp:199
bool use_ellipsis_
Definition: menu.hpp:243
menu(bool click_selects=false, int max_height=-1, int max_width=-1, style *menu_style=nullptr, const bool auto_join=true)
Definition: menu.cpp:43
void invalidate_row_pos(std::size_t pos)
Definition: menu.cpp:679
int get_max_height() const
Definition: menu.hpp:147
static style & default_style
Definition: menu.hpp:106
int items_start() const
SELECTION_MOVE_VIEWPORT
Definition: menu.hpp:251
@ NO_MOVE_VIEWPORT
Definition: menu.hpp:251
@ MOVE_VIEWPORT
Definition: menu.hpp:251
int selection() const
Definition: menu.cpp:106
void set_inner_location(const SDL_Rect &rect) override
Definition: menu.cpp:115
style * style_
Definition: menu.hpp:170
~menu()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: menu.cpp:59
bool previous_button_
Definition: menu.hpp:209
virtual void handle_event(const SDL_Event &event) override
Definition: menu.cpp:334
void update_size()
Definition: menu.cpp:80
std::size_t number_of_items() const
Definition: menu.hpp:150
void move_selection_down(std::size_t dep)
Definition: menu.cpp:232
bool double_clicked_
Definition: menu.hpp:214
int hit(int x, int y) const
Definition: menu.cpp:586
void move_selection_keeping_viewport(std::size_t id)
Definition: menu.cpp:255
virtual void set_items(const std::vector< indented_menu_item > &items, std::optional< std::size_t > selected)
Set new items to show and redraw/recalculate everything.
Definition: menu.cpp:121
std::size_t max_items_onscreen() const
Definition: menu.cpp:166
void key_press(SDL_Keycode key)
Definition: menu.cpp:267
int items_end() const
std::size_t get_item_height(int item) const
Definition: menu.cpp:654
void set_click_selects(bool value)
Definition: menu.cpp:422
virtual void draw_row(const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:539
int get_max_width() const
Definition: menu.hpp:148
std::set< int > invalid_
Definition: menu.hpp:257
void fill_items(const std::vector< indented_menu_item > &imi)
Set new items to show.
Definition: menu.cpp:63
bool double_clicked()
Definition: menu.cpp:415
bool silent_
Definition: menu.hpp:171
void move_selection_to(std::size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT)
Definition: menu.cpp:239
void update_scrollbar_grip_height()
Definition: menu.cpp:74
void scroll(unsigned int pos) override
Definition: menu.cpp:432
void set_numeric_keypress_selection(bool value)
Definition: menu.cpp:427
int max_height_
Definition: menu.hpp:192
void move_selection(std::size_t id)
Definition: menu.cpp:247
SDL_Rect get_item_rect(int item) const
Definition: menu.cpp:600
std::vector< item > items_
Definition: menu.hpp:198
static imgsel_style bluebg_style
Definition: menu.hpp:107
int max_width_
Definition: menu.hpp:192
bool num_selects_
variable which determines whether a numeric keypress should select an item on the dialog
Definition: menu.hpp:235
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
ROW_TYPE
Definition: menu.hpp:49
@ SELECTED_ROW
Definition: menu.hpp:49
@ NORMAL_ROW
Definition: menu.hpp:49
void invalidate_row(std::size_t id)
Definition: menu.cpp:670
bool ignore_next_doubleclick_
Definition: menu.hpp:239
std::string selected
General purpose widgets.
const std::vector< std::string > items
The only kind of row still supported by the menu class.
Definition: menu.hpp:33
std::string text
Definition: menu.hpp:38
int indent_level
An amount of blank space at the start of the row, measured in tab-stops (so 1 is around 4 en-widths)
Definition: menu.hpp:35
std::string icon
If non-empty, a picture to display before the text.
Definition: menu.hpp:37
std::size_t id
Definition: menu.hpp:116
indented_menu_item fields
Definition: menu.hpp:115
item(const indented_menu_item &fields, std::size_t id)
Definition: menu.hpp:111
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:47