The Battle for Wesnoth  1.17.12+dev
menu.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2022
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 
35  enum ROW_TYPE { NORMAL_ROW, SELECTED_ROW, HEADING_ROW };
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 
58  int normal_rgb_, selected_rgb_, heading_rgb_;
59  double normal_alpha_, selected_alpha_, heading_alpha_;
60  int max_img_w_, max_img_h_;
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);
89  int normal_rgb2_, selected_rgb2_, heading_rgb2_;
90  double normal_alpha2_, selected_alpha2_, heading_alpha2_;
91  };
92 
93  friend class style;
94  friend class imgsel_style;
97 
98  struct item
99  {
100  item() : fields(), help(), id(0)
101  {}
102 
103  item(const std::vector<std::string>& fields, std::size_t id)
104  : fields(fields), help(), id(id)
105  {}
106 
107  std::vector<std::string> fields;
108  std::vector<std::string> help;
109  std::size_t id;
110  };
111 
112  class sorter
113  {
114  public:
115  virtual ~sorter() {}
116  virtual bool column_sortable(int column) const = 0;
117  virtual bool less(int column, const item& row1, const item& row2) const = 0;
118  };
119 
120  class basic_sorter : public sorter
121  {
122  public:
123  basic_sorter();
124  virtual ~basic_sorter() {}
125 
126  basic_sorter& set_alpha_sort(int column);
127  basic_sorter& set_numeric_sort(int column);
128  basic_sorter& set_id_sort(int column);
129  basic_sorter& set_redirect_sort(int column, int to);
130  basic_sorter& set_position_sort(int column, const std::vector<int>& pos);
131  protected:
132  virtual bool column_sortable(int column) const;
133  virtual bool less(int column, const item& row1, const item& row2) const;
134 
135  private:
136  std::set<int> alpha_sort_, numeric_sort_, id_sort_;
137  std::map<int,int> redirect_sort_;
138  std::map<int,std::vector<int>> pos_sort_;
139  };
140 
141  menu(const std::vector<std::string>& items,
142  bool click_selects=false, int max_height=-1, int max_width=-1,
143  const sorter* sorter_obj=nullptr, style *menu_style=nullptr, const bool auto_join=true);
144 
145  /** Default implementation, but defined out-of-line for efficiency reasons. */
146  ~menu();
147 
148  int selection() const;
149 
150  void move_selection(std::size_t id);
151  void move_selection_keeping_viewport(std::size_t id);
152  void reset_selection();
153 
154  // allows user to change_item while running (dangerous)
155  void change_item(int pos1,int pos2,const std::string& str);
156 
157  virtual void erase_item(std::size_t index);
158 
159  void set_heading(const std::vector<std::string>& heading);
160 
161  /**
162  * Set new items to show and redraw/recalculate everything. If
163  * strip_spaces is false, spaces will remain at the item edges. If
164  * keep_viewport is true, the menu tries to keep the selection at
165  * the same position as it were before the items were set.
166  */
167  virtual void set_items(const std::vector<std::string>& items, bool strip_spaces=true,
168  bool keep_viewport=false);
169 
170  /**
171  * Set a new max height for this menu. Note that this does not take
172  * effect immediately, only after certain operations that clear
173  * everything, such as set_items().
174  */
175  void set_max_height(const int new_max_height);
176  void set_max_width(const int new_max_width);
177 
178  int get_max_height() const { return max_height_; }
179  int get_max_width() const { return max_width_; }
180 
181  std::size_t number_of_items() const { return items_.size(); }
182 
183  int process();
184 
185  bool double_clicked();
186 
187  void set_click_selects(bool value);
188  void set_numeric_keypress_selection(bool value);
189 
190  // scrollarea override
191  void scroll(unsigned int pos) override;
192 
193  //currently, menus do not manage the memory of their sorter
194  //this should be changed to a more object-oriented approach
195  void set_sorter(sorter *s);
196  void sort_by(int column);
197  int get_sort_by() const {return sortby_;}
198  bool get_sort_reversed() const {return sortreversed_;}
199 
200 protected:
201  bool item_ends_with_image(const std::string& item) const;
202  virtual void handle_event(const SDL_Event& event) override;
203  void set_inner_location(const SDL_Rect& rect) override;
204 
205  bool requires_event_focus(const SDL_Event *event=nullptr) const override;
206  const std::vector<int>& column_widths() const;
207  virtual void draw_row(const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
208 
210  bool silent_;
211 
212  int hit(int x, int y) const;
213 
214  std::pair<int,int> hit_cell(int x, int y) const;
215  int hit_column(int x) const;
216 
217  int hit_heading(int x, int y) const;
218 
219  void invalidate_row(std::size_t id);
220  void invalidate_row_pos(std::size_t pos);
221  void invalidate_heading();
222 
223 private:
224  std::size_t max_items_onscreen() const;
225 
226  std::size_t heading_height() const;
227 
228  int max_height_, max_width_;
229  mutable int max_items_, item_height_;
230 
231  void adjust_viewport_to_selection();
232  void key_press(SDL_Keycode key);
233 
234  std::vector<item> items_;
235  std::vector<std::size_t> item_pos_;
236 
237  std::vector<std::string> heading_;
238  mutable int heading_height_;
239 
240  void create_help_strings();
241  void process_help_string(int mousex, int mousey) override;
242 
243  std::pair<int,int> cur_help_;
244 
245  mutable std::vector<int> column_widths_;
246 
247  std::size_t selected_;
249  bool out_;
251  //std::set<std::size_t> undrawn_items_;
252 
254 
256 
257  void column_widths_item(const std::vector<std::string>& row, std::vector<int>& widths) const;
258 
259  void clear_item(int item);
260  void draw_contents() override;
261 
262  mutable std::map<int,SDL_Rect> itemRects_;
263 
264  SDL_Rect get_item_rect(int item) const;
265  SDL_Rect get_item_rect_internal(std::size_t pos) const;
266  std::size_t get_item_height_internal(const std::vector<std::string>& item) const;
267  std::size_t get_item_height(int item) const;
268  int items_start() const;
269 
270  int items_end() const;
271  int items_height() const;
272 
273  void update_scrollbar_grip_height();
274 
275  /**
276  * variable which determines whether a numeric keypress should
277  * select an item on the dialog
278  */
280  // These two variables are used to get the correct double click
281  // behavior so that a click that causes one double click won't be
282  // counted as a first click in the "next" double click.
285 
286  //ellipsis calculation is slightly off, so default to false
288 
289  const sorter* sorter_;
290  int sortby_;
293 
294  /**
295  * Set new items to show. If strip_spaces is false, spaces will
296  * remain at the item edges.
297  */
298  void fill_items(const std::vector<std::string>& items, bool strip_spaces);
299 
300  void do_sort();
301  void recalculate_pos();
302  void assert_pos();
303 
304  void update_size();
305  enum SELECTION_MOVE_VIEWPORT { MOVE_VIEWPORT, NO_MOVE_VIEWPORT };
306  void set_selection_pos(std::size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
307  void move_selection_to(std::size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
308  void move_selection_up(std::size_t dep);
309  void move_selection_down(std::size_t dep);
310 
311  std::set<int> invalid_;
312 };
313 
314 }
std::size_t id
Definition: menu.hpp:109
bool last_was_doubleclick_
Definition: menu.hpp:284
std::size_t number_of_items() const
Definition: menu.hpp:181
virtual void init()
Definition: menu.hpp:76
virtual void init()
Definition: menu.hpp:42
int max_img_w_
Definition: menu.hpp:60
bool num_selects_
variable which determines whether a numeric keypress should select an item on the dialog ...
Definition: menu.hpp:279
std::map< int, int > redirect_sort_
Definition: menu.hpp:137
int get_max_width() const
Definition: menu.hpp:179
int sortby_
Definition: menu.hpp:290
ROW_TYPE
Definition: menu.hpp:35
int selected_rgb_
Definition: menu.hpp:58
std::map< std::string, texture > img_map_
Definition: menu.hpp:82
std::vector< std::string > heading_
Definition: menu.hpp:237
General purpose widgets.
const std::vector< std::string > items
SELECTION_MOVE_VIEWPORT
Definition: menu.hpp:305
bool show_result_
Definition: menu.hpp:253
#define h
std::vector< int > column_widths_
Definition: menu.hpp:245
std::vector< std::string > help
Definition: menu.hpp:108
static imgsel_style bluebg_style
Definition: menu.hpp:96
std::size_t cell_padding_
Definition: menu.hpp:55
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:32
bool ignore_next_doubleclick_
Definition: menu.hpp:283
bool sortreversed_
Definition: menu.hpp:291
void process(int mousex, int mousey)
Definition: tooltips.cpp:278
virtual ~sorter()
Definition: menu.hpp:115
bool out_
Definition: menu.hpp:249
int get_sort_by() const
Definition: menu.hpp:197
item(const std::vector< std::string > &fields, std::size_t id)
Definition: menu.hpp:103
std::pair< int, int > cur_help_
Definition: menu.hpp:243
std::vector< std::string > fields
Definition: menu.hpp:107
bool get_sort_reversed() const
Definition: menu.hpp:198
int max_width_
Definition: menu.hpp:228
std::vector< std::size_t > item_pos_
Definition: menu.hpp:235
static style & default_style
Definition: menu.hpp:95
int highlight_heading_
Definition: menu.hpp:292
double selected_alpha2_
Definition: menu.hpp:90
const std::string img_base_
Definition: menu.hpp:81
double selected_alpha_
Definition: menu.hpp:59
std::set< int > numeric_sort_
Definition: menu.hpp:136
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
bool previous_button_
Definition: menu.hpp:250
static map_location::DIRECTION s
bool use_ellipsis_
Definition: menu.hpp:287
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:46
int w
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::set< int > invalid_
Definition: menu.hpp:311
std::size_t thickness_
Definition: menu.hpp:56
std::map< int, std::vector< int > > pos_sort_
Definition: menu.hpp:138
int get_max_height() const
Definition: menu.hpp:178
bool click_selects_
Definition: menu.hpp:248
std::size_t font_size_
Definition: menu.hpp:54
std::vector< item > items_
Definition: menu.hpp:234
Functions to load and save images from/to disk.
const sorter * sorter_
Definition: menu.hpp:289
bool double_clicked_
Definition: menu.hpp:255
virtual ~basic_sorter()
Definition: menu.hpp:124
std::size_t selected_
Definition: menu.hpp:247
bool silent_
Definition: menu.hpp:210
Definition: help.cpp:57
int heading_height_
Definition: menu.hpp:238
int max_items_
Definition: menu.hpp:229
std::map< int, SDL_Rect > itemRects_
Definition: menu.hpp:262
style * style_
Definition: menu.hpp:209