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