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