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