The Battle for Wesnoth  1.17.17+dev
menu.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2023
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 <map>
19 #include <set>
20 
21 #include "scrollarea.hpp"
22 
23 class texture;
24 
25 namespace image{
26  class locator;
27 }
28 
29 namespace gui {
30 
31 class menu : public scrollarea
32 {
33 public:
34 
36  //basic menu style
37  class style
38  {
39  public:
40  style();
41  virtual ~style();
42  virtual void init() {}
43 
44  virtual SDL_Rect item_size(const std::string& item) const;
45  virtual void draw_row_bg(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
46  virtual void draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
47  void scale_images(int max_width, int max_height);
48  void adjust_image_bounds(int& w, int& h) const;
49  std::size_t get_font_size() const;
50  std::size_t get_cell_padding() const;
51  std::size_t get_thickness() const;
52 
53  protected:
54  std::size_t font_size_;
55  std::size_t cell_padding_;
56  std::size_t thickness_; //additional cell padding for style use only
57 
61  };
62 
63  //image-border selection style
64  class imgsel_style : public style
65  {
66  public:
67  imgsel_style(const std::string &img_base, bool has_bg,
68  int normal_rgb, int selected_rgb, int heading_rgb,
69  double normal_alpha, double selected_alpha, double heading_alpha);
70  virtual ~imgsel_style();
71 
72  virtual SDL_Rect item_size(const std::string& item) const;
73  virtual void draw_row_bg(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
74  virtual void draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
75 
76  virtual void init() { load_images(); }
77  bool load_images();
78  void unload_images();
79 
80  protected:
81  const std::string img_base_;
82  std::map<std::string,texture> img_map_;
83 
84  private:
85  bool load_image(const std::string &img_sub);
91  };
92 
93  friend class style;
94  friend class imgsel_style;
97 
98  struct item
99  {
100  item() : fields(), id(0)
101  {}
102 
103  item(const std::vector<std::string>& fields, std::size_t id)
104  : fields(fields), id(id)
105  {}
106 
107  std::vector<std::string> fields;
108  std::size_t id;
109  };
110 
111  class sorter
112  {
113  public:
114  virtual ~sorter() {}
115  virtual bool column_sortable(int column) const = 0;
116  virtual bool less(int column, const item& row1, const item& row2) const = 0;
117  };
118 
119  class basic_sorter : public sorter
120  {
121  public:
122  basic_sorter();
123  virtual ~basic_sorter() {}
124 
125  basic_sorter& set_alpha_sort(int column);
126  basic_sorter& set_numeric_sort(int column);
127  basic_sorter& set_id_sort(int column);
128  basic_sorter& set_redirect_sort(int column, int to);
129  basic_sorter& set_position_sort(int column, const std::vector<int>& pos);
130  protected:
131  virtual bool column_sortable(int column) const;
132  virtual bool less(int column, const item& row1, const item& row2) const;
133 
134  private:
136  std::map<int,int> redirect_sort_;
137  std::map<int,std::vector<int>> pos_sort_;
138  };
139 
140  menu(const std::vector<std::string>& items,
141  bool click_selects=false, int max_height=-1, int max_width=-1,
142  const sorter* sorter_obj=nullptr, style *menu_style=nullptr, const bool auto_join=true);
143 
144  /** Default implementation, but defined out-of-line for efficiency reasons. */
145  ~menu();
146 
147  int selection() const;
148 
149  void move_selection(std::size_t id);
150  void move_selection_keeping_viewport(std::size_t id);
151  void reset_selection();
152 
153  // allows user to change_item while running (dangerous)
154  void change_item(int pos1,int pos2,const std::string& str);
155 
156  virtual void erase_item(std::size_t index);
157 
158  void set_heading(const std::vector<std::string>& heading);
159 
160  /**
161  * Set new items to show and redraw/recalculate everything. If
162  * strip_spaces is false, spaces will remain at the item edges. If
163  * keep_viewport is true, the menu tries to keep the selection at
164  * the same position as it were before the items were set.
165  */
166  virtual void set_items(const std::vector<std::string>& items, bool strip_spaces=true,
167  bool keep_viewport=false);
168 
169  /**
170  * Set a new max height for this menu. Note that this does not take
171  * effect immediately, only after certain operations that clear
172  * everything, such as set_items().
173  */
174  void set_max_height(const int new_max_height);
175  void set_max_width(const int new_max_width);
176 
177  int get_max_height() const { return max_height_; }
178  int get_max_width() const { return max_width_; }
179 
180  std::size_t number_of_items() const { return items_.size(); }
181 
182  int process();
183 
184  bool double_clicked();
185 
186  void set_click_selects(bool value);
187  void set_numeric_keypress_selection(bool value);
188 
189  // scrollarea override
190  void scroll(unsigned int pos) override;
191 
192  //currently, menus do not manage the memory of their sorter
193  //this should be changed to a more object-oriented approach
194  void set_sorter(sorter *s);
195  void sort_by(int column);
196  int get_sort_by() const {return sortby_;}
197  bool get_sort_reversed() const {return sortreversed_;}
198 
199 protected:
200  bool item_ends_with_image(const std::string& item) const;
201  virtual void handle_event(const SDL_Event& event) override;
202  void set_inner_location(const SDL_Rect& rect) override;
203 
204  bool requires_event_focus(const SDL_Event *event=nullptr) const override;
205  const std::vector<int>& column_widths() const;
206  virtual void draw_row(const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
207 
209  bool silent_;
210 
211  int hit(int x, int y) const;
212 
213  int hit_column(int x) const;
214 
215  int hit_heading(int x, int y) const;
216 
217  void invalidate_row(std::size_t id);
218  void invalidate_row_pos(std::size_t pos);
219  void invalidate_heading();
220 
221 private:
222  std::size_t max_items_onscreen() const;
223 
224  std::size_t heading_height() const;
225 
227  mutable int max_items_, item_height_;
228 
230  void key_press(SDL_Keycode key);
231 
232  std::vector<item> items_;
233  std::vector<std::size_t> item_pos_;
234 
235  std::vector<std::string> heading_;
236  mutable int heading_height_;
237 
238  mutable std::vector<int> column_widths_;
239 
240  std::size_t selected_;
242  bool out_;
244  //std::set<std::size_t> undrawn_items_;
245 
247 
249 
250  void column_widths_item(const std::vector<std::string>& row, std::vector<int>& widths) const;
251 
252  void clear_item(int item);
253  void draw_contents() override;
254 
255  mutable std::map<int,SDL_Rect> itemRects_;
256 
257  SDL_Rect get_item_rect(int item) const;
258  SDL_Rect get_item_rect_internal(std::size_t pos) const;
259  std::size_t get_item_height_internal(const std::vector<std::string>& item) const;
260  std::size_t get_item_height(int item) const;
261  int items_start() const;
262 
263  int items_end() const;
264  int items_height() const;
265 
267 
268  /**
269  * variable which determines whether a numeric keypress should
270  * select an item on the dialog
271  */
273  // These two variables are used to get the correct double click
274  // behavior so that a click that causes one double click won't be
275  // counted as a first click in the "next" double click.
278 
279  //ellipsis calculation is slightly off, so default to false
281 
282  const sorter* sorter_;
283  int sortby_;
286 
287  /**
288  * Set new items to show. If strip_spaces is false, spaces will
289  * remain at the item edges.
290  */
291  void fill_items(const std::vector<std::string>& items, bool strip_spaces);
292 
293  void do_sort();
294  void recalculate_pos();
295  void assert_pos();
296 
297  void update_size();
299  void set_selection_pos(std::size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
300  void move_selection_to(std::size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
301  void move_selection_up(std::size_t dep);
302  void move_selection_down(std::size_t dep);
303 
304  std::set<int> invalid_;
305 };
306 
307 }
basic_sorter & set_id_sort(int column)
Definition: menu.cpp:60
basic_sorter & set_numeric_sort(int column)
Definition: menu.cpp:54
basic_sorter & set_position_sort(int column, const std::vector< int > &pos)
Definition: menu.cpp:75
std::map< int, std::vector< int > > pos_sort_
Definition: menu.hpp:137
std::set< int > numeric_sort_
Definition: menu.hpp:135
virtual ~basic_sorter()
Definition: menu.hpp:123
virtual bool less(int column, const item &row1, const item &row2) const
Definition: menu.cpp:92
basic_sorter & set_redirect_sort(int column, int to)
Definition: menu.cpp:66
virtual bool column_sortable(int column) const
Definition: menu.cpp:81
basic_sorter & set_alpha_sort(int column)
Definition: menu.cpp:48
std::set< int > alpha_sort_
Definition: menu.hpp:135
std::set< int > id_sort_
Definition: menu.hpp:135
std::map< int, int > redirect_sort_
Definition: menu.hpp:136
virtual SDL_Rect item_size(const std::string &item) const
Definition: menu_style.cpp:240
std::map< std::string, texture > img_map_
Definition: menu.hpp:82
const std::string img_base_
Definition: menu.hpp:81
virtual void draw_row(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu_style.cpp:151
double heading_alpha2_
Definition: menu.hpp:90
imgsel_style(const std::string &img_base, bool has_bg, int normal_rgb, int selected_rgb, int heading_rgb, double normal_alpha, double selected_alpha, double heading_alpha)
Definition: menu_style.cpp:46
virtual void init()
Definition: menu.hpp:76
double selected_alpha2_
Definition: menu.hpp:90
bool load_image(const std::string &img_sub)
Definition: menu_style.cpp:82
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:141
virtual ~sorter()
Definition: menu.hpp:114
virtual bool column_sortable(int column) const =0
virtual bool less(int column, const item &row1, const item &row2) const =0
std::size_t get_thickness() const
Definition: menu_style.cpp:58
void scale_images(int max_width, int max_height)
Definition: menu_style.cpp:60
int heading_rgb_
Definition: menu.hpp:58
void adjust_image_bounds(int &w, int &h) const
Definition: menu_style.cpp:66
std::size_t get_font_size() const
Definition: menu_style.cpp:56
std::size_t font_size_
Definition: menu.hpp:54
virtual SDL_Rect item_size(const std::string &item) const
Definition: menu.cpp:728
double heading_alpha_
Definition: menu.hpp:59
int max_img_w_
Definition: menu.hpp:60
int max_img_h_
Definition: menu.hpp:60
double normal_alpha_
Definition: menu.hpp:59
double selected_alpha_
Definition: menu.hpp:59
virtual void draw_row_bg(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:761
std::size_t get_cell_padding() const
Definition: menu_style.cpp:57
std::size_t thickness_
Definition: menu.hpp:56
int normal_rgb_
Definition: menu.hpp:58
virtual void init()
Definition: menu.hpp:42
int selected_rgb_
Definition: menu.hpp:58
virtual ~style()
Definition: menu_style.cpp:44
std::size_t cell_padding_
Definition: menu.hpp:55
virtual void draw_row(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:788
void reset_selection()
Definition: menu.cpp:507
bool requires_event_focus(const SDL_Event *event=nullptr) const override
Definition: menu.cpp:546
void do_sort()
Definition: menu.cpp:229
int max_items_
Definition: menu.hpp:227
int process()
Definition: menu.cpp:663
void draw_contents() override
Definition: menu.cpp:937
bool show_result_
Definition: menu.hpp:246
void move_selection_up(std::size_t dep)
Definition: menu.cpp:472
bool click_selects_
Definition: menu.hpp:241
int heading_height_
Definition: menu.hpp:236
SDL_Rect get_item_rect_internal(std::size_t pos) const
Definition: menu.cpp:991
int highlight_heading_
Definition: menu.hpp:285
void set_sorter(sorter *s)
Definition: menu.cpp:696
bool get_sort_reversed() const
Definition: menu.hpp:197
void sort_by(int column)
Definition: menu.cpp:707
const sorter * sorter_
Definition: menu.hpp:282
void set_max_width(const int new_max_width)
Definition: menu.cpp:406
bool out_
Definition: menu.hpp:242
int items_height() const
std::size_t selected_
Definition: menu.hpp:240
void recalculate_pos()
Definition: menu.cpp:250
int item_height_
Definition: menu.hpp:227
void set_selection_pos(std::size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT)
Definition: menu.cpp:451
void set_max_height(const int new_max_height)
Set a new max height for this menu.
Definition: menu.cpp:398
std::size_t get_item_height_internal(const std::vector< std::string > &item) const
Definition: menu.cpp:1035
std::vector< std::size_t > item_pos_
Definition: menu.hpp:233
void clear_item(int item)
Definition: menu.cpp:840
bool last_was_doubleclick_
Definition: menu.hpp:277
void fill_items(const std::vector< std::string > &items, bool strip_spaces)
Set new items to show.
Definition: menu.cpp:174
std::map< int, SDL_Rect > itemRects_
Definition: menu.hpp:255
void adjust_viewport_to_selection()
Definition: menu.cpp:444
std::vector< std::string > heading_
Definition: menu.hpp:235
bool item_ends_with_image(const std::string &item) const
Definition: menu.cpp:821
bool use_ellipsis_
Definition: menu.hpp:280
void invalidate_row_pos(std::size_t pos)
Definition: menu.cpp:1077
int sortby_
Definition: menu.hpp:283
int get_max_height() const
Definition: menu.hpp:177
static style & default_style
Definition: menu.hpp:95
void column_widths_item(const std::vector< std::string > &row, std::vector< int > &widths) const
Definition: menu.cpp:807
int items_start() const
SELECTION_MOVE_VIEWPORT
Definition: menu.hpp:298
@ NO_MOVE_VIEWPORT
Definition: menu.hpp:298
@ MOVE_VIEWPORT
Definition: menu.hpp:298
int selection() const
Definition: menu.cpp:301
int get_sort_by() const
Definition: menu.hpp:196
void set_inner_location(const SDL_Rect &rect) override
Definition: menu.cpp:310
style * style_
Definition: menu.hpp:208
void set_heading(const std::vector< std::string > &heading)
Definition: menu.cpp:356
~menu()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: menu.cpp:170
bool previous_button_
Definition: menu.hpp:243
int hit_column(int x) const
Definition: menu.cpp:963
virtual void handle_event(const SDL_Event &event) override
Definition: menu.cpp:579
void update_size()
Definition: menu.cpp:274
std::size_t number_of_items() const
Definition: menu.hpp:180
void move_selection_down(std::size_t dep)
Definition: menu.cpp:477
bool double_clicked_
Definition: menu.hpp:248
int hit(int x, int y) const
Definition: menu.cpp:949
const std::vector< int > & column_widths() const
Definition: menu.cpp:828
void move_selection_keeping_viewport(std::size_t id)
Definition: menu.cpp:500
std::size_t max_items_onscreen() const
Definition: menu.cpp:414
void key_press(SDL_Keycode key)
Definition: menu.cpp:512
menu(const std::vector< std::string > &items, bool click_selects=false, int max_height=-1, int max_width=-1, const sorter *sorter_obj=nullptr, style *menu_style=nullptr, const bool auto_join=true)
Definition: menu.cpp:150
int items_end() const
std::size_t get_item_height(int item) const
Definition: menu.cpp:1055
void set_click_selects(bool value)
Definition: menu.cpp:680
virtual void erase_item(std::size_t index)
Definition: menu.cpp:327
virtual void draw_row(const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:848
int get_max_width() const
Definition: menu.hpp:178
std::set< int > invalid_
Definition: menu.hpp:304
bool double_clicked()
Definition: menu.cpp:673
bool silent_
Definition: menu.hpp:209
void move_selection_to(std::size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT)
Definition: menu.cpp:484
void assert_pos()
Definition: menu.cpp:259
void update_scrollbar_grip_height()
Definition: menu.cpp:268
void scroll(unsigned int pos) override
Definition: menu.cpp:690
int hit_heading(int x, int y) const
Definition: menu.cpp:975
void set_numeric_keypress_selection(bool value)
Definition: menu.cpp:685
int max_height_
Definition: menu.hpp:226
bool sortreversed_
Definition: menu.hpp:284
void move_selection(std::size_t id)
Definition: menu.cpp:492
SDL_Rect get_item_rect(int item) const
Definition: menu.cpp:986
std::vector< item > items_
Definition: menu.hpp:232
std::size_t heading_height() const
Definition: menu.cpp:1046
static imgsel_style bluebg_style
Definition: menu.hpp:96
int max_width_
Definition: menu.hpp:226
bool num_selects_
variable which determines whether a numeric keypress should select an item on the dialog
Definition: menu.hpp:272
ROW_TYPE
Definition: menu.hpp:35
@ SELECTED_ROW
Definition: menu.hpp:35
@ NORMAL_ROW
Definition: menu.hpp:35
@ HEADING_ROW
Definition: menu.hpp:35
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:367
void invalidate_heading()
Definition: menu.cpp:1086
void invalidate_row(std::size_t id)
Definition: menu.cpp:1068
bool ignore_next_doubleclick_
Definition: menu.hpp:276
std::vector< int > column_widths_
Definition: menu.hpp:238
void change_item(int pos1, int pos2, const std::string &str)
Definition: menu.cpp:316
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
int w
General purpose widgets.
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:414
Functions to load and save images from/to disk.
const std::vector< std::string > items
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:72
std::vector< std::string > fields
Definition: menu.hpp:107
std::size_t id
Definition: menu.hpp:108
item(const std::vector< std::string > &fields, std::size_t id)
Definition: menu.hpp:103
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:47
static map_location::DIRECTION s
#define h