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(), 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:
135  std::set<int> alpha_sort_, numeric_sort_, id_sort_;
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 
226  int max_height_, max_width_;
227  mutable int max_items_, item_height_;
228 
229  void adjust_viewport_to_selection();
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 
266  void update_scrollbar_grip_height();
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();
298  enum SELECTION_MOVE_VIEWPORT { MOVE_VIEWPORT, NO_MOVE_VIEWPORT };
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 }
std::size_t id
Definition: menu.hpp:108
bool last_was_doubleclick_
Definition: menu.hpp:277
std::size_t number_of_items() const
Definition: menu.hpp:180
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:272
std::map< int, int > redirect_sort_
Definition: menu.hpp:136
int get_max_width() const
Definition: menu.hpp:178
int sortby_
Definition: menu.hpp:283
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:235
General purpose widgets.
const std::vector< std::string > items
SELECTION_MOVE_VIEWPORT
Definition: menu.hpp:298
bool show_result_
Definition: menu.hpp:246
#define h
std::vector< int > column_widths_
Definition: menu.hpp:238
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:276
bool sortreversed_
Definition: menu.hpp:284
void process(int mousex, int mousey)
Definition: tooltips.cpp:278
virtual ~sorter()
Definition: menu.hpp:114
bool out_
Definition: menu.hpp:242
int get_sort_by() const
Definition: menu.hpp:196
item(const std::vector< std::string > &fields, std::size_t id)
Definition: menu.hpp:103
std::vector< std::string > fields
Definition: menu.hpp:107
bool get_sort_reversed() const
Definition: menu.hpp:197
int max_width_
Definition: menu.hpp:226
std::vector< std::size_t > item_pos_
Definition: menu.hpp:233
static style & default_style
Definition: menu.hpp:95
int highlight_heading_
Definition: menu.hpp:285
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:135
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
bool previous_button_
Definition: menu.hpp:243
static map_location::DIRECTION s
bool use_ellipsis_
Definition: menu.hpp:280
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:304
std::size_t thickness_
Definition: menu.hpp:56
std::map< int, std::vector< int > > pos_sort_
Definition: menu.hpp:137
int get_max_height() const
Definition: menu.hpp:177
bool click_selects_
Definition: menu.hpp:241
std::size_t font_size_
Definition: menu.hpp:54
std::vector< item > items_
Definition: menu.hpp:232
Functions to load and save images from/to disk.
const sorter * sorter_
Definition: menu.hpp:282
bool double_clicked_
Definition: menu.hpp:248
virtual ~basic_sorter()
Definition: menu.hpp:123
std::size_t selected_
Definition: menu.hpp:240
bool silent_
Definition: menu.hpp:209
int heading_height_
Definition: menu.hpp:236
int max_items_
Definition: menu.hpp:227
std::map< int, SDL_Rect > itemRects_
Definition: menu.hpp:255
style * style_
Definition: menu.hpp:208