The Battle for Wesnoth  1.19.0-dev
menu.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
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 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
18 #include "widgets/menu.hpp"
19 
20 #include "draw.hpp"
21 #include "font/sdl_ttf_compat.hpp"
22 #include "font/standard_colors.hpp"
23 #include "game_config.hpp"
24 #include "language.hpp"
25 #include "picture.hpp"
26 #include "sdl/rect.hpp"
27 #include "sdl/texture.hpp"
28 #include "sound.hpp"
29 #include "video.hpp"
30 
31 
32 namespace {
33  /**
34  * For converting indented_menu_item.indent_level into a width in pixels.
35  * The text size might change, so instead of caching a value pango_line_size
36  * is called repeatedly with this as an argument.
37  */
38  const std::string indent_string{" "};
39 };
40 
41 namespace gui {
42 
43 menu::menu(bool click_selects, int max_height, int max_width, style *menu_style, const bool auto_join)
44 : scrollarea(auto_join), silent_(false),
45  max_height_(max_height), max_width_(max_width),
46  max_items_(-1), item_height_(-1),
47  selected_(0), click_selects_(click_selects), out_(false),
48  previous_button_(true), show_result_(false),
49  double_clicked_(false),
50  num_selects_(true),
51  ignore_next_doubleclick_(false),
52  last_was_doubleclick_(false), use_ellipsis_(false)
53 {
54  style_ = (menu_style) ? menu_style : &default_style;
55  style_->init();
56  fill_items({});
57 }
58 
60 {
61 }
62 
63 void menu::fill_items(const std::vector<indented_menu_item>& items)
64 {
65  for(const auto& itor : items) {
66  const std::size_t id = items_.size();
67  item_pos_.push_back(id);
68  items_.emplace_back(itor, id);
69  }
70 
71  update_size();
72 }
73 
75 {
76  set_full_size(items_.size());
78 }
79 
81 {
82  int h = 0;
83  for(std::size_t i = get_position(),
84  i_end = std::min(items_.size(), i + max_items_onscreen());
85  i < i_end; ++i)
86  h += get_item_rect(i).h;
87  h = std::max(h, height());
88  if (max_height_ > 0 && h > (max_height_)) {
89  h = max_height_;
90  }
91 
92  use_ellipsis_ = false;
93  int w = widest_row_width();
94  if (items_.size() > max_items_onscreen())
95  w += scrollbar_width();
96  w = std::max(w, width());
97  if (max_width_ > 0 && w > (max_width_)) {
98  use_ellipsis_ = true;
99  w = max_width_;
100  }
101 
103  set_measurements(w, h);
104 }
105 
106 int menu::selection() const
107 {
108  if (selected_ >= items_.size()) {
109  return -1;
110  }
111 
112  return items_[selected_].id;
113 }
114 
115 void menu::set_inner_location(const SDL_Rect& /*rect*/)
116 {
117  itemRects_.clear();
119 }
120 
121 void menu::set_items(const std::vector<indented_menu_item>& items, std::optional<std::size_t> selected)
122 {
123  const bool scrolled_to_max = (has_scrollbar() && get_position() == get_max_position());
124  items_.clear();
125  item_pos_.clear();
126  itemRects_.clear();
127  widest_row_width_.reset();
128  //undrawn_items_.clear();
129  max_items_ = -1; // Force recalculation of the max items.
130  item_height_ = -1; // Force recalculation of the item height.
131 
132  if(selected) {
133  selected_ = *selected;
134  } else {
135  selected_ = 0;
136  }
137 
138  fill_items(items);
139  if(scrolled_to_max) {
141  }
142 
144 
146 
147  queue_redraw();
148 }
149 
150 void menu::set_max_height(const int new_max_height)
151 {
152  max_height_ = new_max_height;
153  itemRects_.clear();
154  max_items_ = -1;
155  update_size();
156 }
157 
158 void menu::set_max_width(const int new_max_width)
159 {
160  max_width_ = new_max_width;
161  itemRects_.clear();
162  widest_row_width_.reset();
163  update_size();
164 }
165 
166 std::size_t menu::max_items_onscreen() const
167 {
168  if(max_items_ != -1) {
169  return std::size_t(max_items_);
170  }
171 
172  const std::size_t max_height = (
173  max_height_ == -1
174  ? (video::game_canvas_size().y * 66) / 100
175  : max_height_
176  );
177 
178  std::vector<int> heights;
179  std::size_t n;
180  for(n = 0; n != items_.size(); ++n) {
181  // The for loop, sort and sum around this are unnecessary, because
182  // get_item_height has ignored its argument since Wesnoth 0.6.99.1.
183  // It caches and returns the height of the tallest item.
184  heights.push_back(get_item_height(n));
185  }
186 
187  std::sort(heights.begin(),heights.end(),std::greater<int>());
188  std::size_t sum = 0;
189  for(n = 0; n != items_.size() && sum < max_height; ++n) {
190  sum += heights[n];
191  }
192 
193  if(sum > max_height && n > 1)
194  --n;
195 
196  return max_items_ = n;
197 }
198 
200 {
201  if(click_selects_)
202  return;
204 }
205 
206 void menu::set_selection_pos(std::size_t new_selected, bool silent, SELECTION_MOVE_VIEWPORT move_viewport)
207 {
208  if (new_selected >= items_.size())
209  return;
210 
211  bool changed = false;
212  if (new_selected != selected_) {
214  invalidate_row_pos(new_selected);
215  selected_ = new_selected;
216  changed = true;
217  }
218 
219  if(move_viewport == MOVE_VIEWPORT) {
221  if(!silent_ && !silent && changed) {
223  }
224  }
225 }
226 
227 void menu::move_selection_up(std::size_t dep)
228 {
229  set_selection_pos(selected_ > dep ? selected_ - dep : 0);
230 }
231 
232 void menu::move_selection_down(std::size_t dep)
233 {
234  std::size_t nb_items = items_.size();
235  set_selection_pos(selected_ + dep >= nb_items ? nb_items - 1 : selected_ + dep);
236 }
237 
238 // private function with control over sound and viewport
239 void menu::move_selection_to(std::size_t id, bool silent, SELECTION_MOVE_VIEWPORT move_viewport)
240 {
241  if(id < item_pos_.size()) {
242  set_selection_pos(item_pos_[id], silent, move_viewport);
243  }
244 }
245 
246 // public function
247 void menu::move_selection(std::size_t id)
248 {
249  if(id < item_pos_.size()) {
251  }
252 }
253 
254 // public function
256 {
257  if(id < item_pos_.size()) {
259  }
260 }
261 
263 {
264  set_selection_pos(0, true);
265 }
266 
267 void menu::key_press(SDL_Keycode key)
268 {
269  if (!click_selects_) {
270  switch(key) {
271  case SDLK_UP:
273  break;
274  case SDLK_DOWN:
276  break;
277  case SDLK_PAGEUP:
279  break;
280  case SDLK_PAGEDOWN:
282  break;
283  case SDLK_HOME:
285  break;
286  case SDLK_END:
287  set_selection_pos(items_.size() - 1);
288  break;
289  //case SDLK_RETURN:
290  // double_clicked_ = true;
291  // break;
292  default:
293  break;
294  }
295  }
296 
297  if (num_selects_ && key >= SDLK_1 && key <= SDLK_9)
298  set_selection_pos(key - SDLK_1);
299 }
300 
301 bool menu::requires_event_focus(const SDL_Event* event) const
302 {
303  if(!focus_ || height() == 0 || hidden()) {
304  return false;
305  }
306  if(event == nullptr) {
307  //when event is not specified, signal that focus may be desired later
308  return true;
309  }
310 
311  if(event->type == SDL_KEYDOWN) {
312  SDL_Keycode key = event->key.keysym.sym;
313  if (!click_selects_) {
314  switch(key) {
315  case SDLK_UP:
316  case SDLK_DOWN:
317  case SDLK_PAGEUP:
318  case SDLK_PAGEDOWN:
319  case SDLK_HOME:
320  case SDLK_END:
321  return true;
322  default:
323  break;
324  }
325  }
326  if (num_selects_ && key >= SDLK_1 && key <= SDLK_9) {
327  return true;
328  }
329  }
330  //mouse events are processed regardless of focus
331  return false;
332 }
333 
334 void menu::handle_event(const SDL_Event& event)
335 {
337  if (height()==0 || hidden())
338  return;
339 
340  if(event.type == SDL_KEYDOWN) {
341  // Only pass key events if we have the focus
342  if (focus(&event))
343  key_press(event.key.keysym.sym);
344  } else if(!mouse_locked() && ((event.type == SDL_MOUSEBUTTONDOWN &&
345  (event.button.button == SDL_BUTTON_LEFT || event.button.button == SDL_BUTTON_RIGHT)) ||
346  event.type == DOUBLE_CLICK_EVENT)) {
347 
348  int x = 0;
349  int y = 0;
350  if(event.type == SDL_MOUSEBUTTONDOWN) {
351  x = event.button.x;
352  y = event.button.y;
353  } else {
354  x = reinterpret_cast<std::size_t>(event.user.data1);
355  y = reinterpret_cast<std::size_t>(event.user.data2);
356  }
357 
358  const int item = hit(x,y);
359  if(item != -1) {
360  set_focus(true);
362 
363  if(click_selects_) {
364  show_result_ = true;
365  }
366 
367  if(event.type == DOUBLE_CLICK_EVENT) {
369  ignore_next_doubleclick_ = false;
370  } else {
371  double_clicked_ = true;
372  last_was_doubleclick_ = true;
373  if(!silent_) {
375  }
376  }
377  } else if (last_was_doubleclick_) {
378  // If we have a double click as the next event, it means
379  // this double click was generated from a click that
380  // already has helped in generating a double click.
381  SDL_Event ev;
382  SDL_PeepEvents(&ev, 1, SDL_PEEKEVENT, DOUBLE_CLICK_EVENT, DOUBLE_CLICK_EVENT);
383  if (ev.type == DOUBLE_CLICK_EVENT) {
385  }
386  last_was_doubleclick_ = false;
387  }
388  }
389 
390  } else if(!mouse_locked() && event.type == SDL_MOUSEMOTION) {
391  if(click_selects_) {
392  const int item = hit(event.motion.x,event.motion.y);
393  const bool out = (item == -1);
394  if (out_ != out) {
395  out_ = out;
397  }
398  if (item != -1) {
400  }
401  }
402  }
403 }
404 
406 {
407  if(show_result_) {
408  show_result_ = false;
409  return selected_;
410  } else {
411  return -1;
412  }
413 }
414 
416 {
417  bool old = double_clicked_;
418  double_clicked_ = false;
419  return old;
420 }
421 
422 void menu::set_click_selects(bool value)
423 {
424  click_selects_ = value;
425 }
426 
428 {
429  num_selects_ = value;
430 }
431 
432 void menu::scroll(unsigned int)
433 {
434  itemRects_.clear();
435  queue_redraw();
436 }
437 
438 SDL_Rect menu::style::item_size(const indented_menu_item& imi) const {
439  SDL_Rect res {0,0,0,0};
440 
441  res.w = imi.indent_level * font::pango_line_size(indent_string, get_font_size()).first;
442 
443  if (!imi.icon.empty()) {
444  // Not the first item, add the spacing.
445  res.w += 5;
446 
447  const texture img = image::get_texture(imi.icon);
448  res.w += img.w();
449  res.h = std::max<int>(img.h(), res.h);
450  }
451 
452  if (!imi.text.empty()) {
453  // Not the first item, add the spacing.
454  res.w += 5;
455 
456  const SDL_Rect area {0,0,10000,10000};
457  const SDL_Rect font_size =
458  font::pango_draw_text(false, area, get_font_size(),
459  font::NORMAL_COLOR, imi.text, 0, 0);
460  res.w += font_size.w;
461  res.h = std::max<int>(font_size.h, res.h);
462  }
463  return res;
464 }
465 
466 void menu::style::draw_row_bg(menu& /*menu_ref*/, const std::size_t /*row_index*/, const SDL_Rect& rect, ROW_TYPE type)
467 {
468  int rgb = 0;
469  double alpha = 0.0;
470 
471  switch(type) {
472  case NORMAL_ROW:
473  rgb = normal_rgb_;
474  alpha = normal_alpha_;
475  break;
476  case SELECTED_ROW:
477  rgb = selected_rgb_;
478  alpha = selected_alpha_;
479  break;
480  }
481 
482  // FIXME: make this clearer
483  color_t c((rgb & 0xff0000) >> 16, (rgb & 0xff00) >> 8, rgb & 0xff);
484  c.a = 255 * alpha;
485 
486  draw::fill(rect, c);
487 }
488 
489 void menu::style::draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type)
490 {
491  if(rect.w == 0 || rect.h == 0) {
492  return;
493  }
494  draw_row_bg(menu_ref, row_index, rect, type);
495 
496  SDL_Rect minirect = rect;
497  minirect.x += thickness_;
498  minirect.y += thickness_;
499  minirect.w -= 2*thickness_;
500  minirect.h -= 2*thickness_;
501  menu_ref.draw_row(row_index, minirect, type);
502 }
503 
505 {
506  if(!widest_row_width_) {
507  int widest = 0;
508  for(const auto& row : items_) {
509  const SDL_Rect size = style_->item_size(row.fields);
510  widest = std::max(widest, size.w);
511  }
512  // Assume there's text at the end of the item, and add padding accordingly.
513  widest_row_width_ = static_cast<int>(widest + style_->get_cell_padding());
514  }
515 
516  return *widest_row_width_;
517 }
518 
519 bool menu::hit_on_indent_or_icon(std::size_t row_index, int x) const
520 {
521  if(row_index >= items_.size()) {
522  return false;
523  }
524 
525  // The virtual method item_size() is overloaded by imgsel_style::item_size(),
526  // which adds borders on both sides. Call it twice and remove one side's padding.
527  const auto& imi = items_[row_index].fields;
528  int width_used_so_far = style_->item_size({imi.indent_level, imi.icon, ""}).w;
529  width_used_so_far -= style_->item_size({0, "", ""}).w / 2;
530 
531  const SDL_Rect& loc = inner_location();
532  if (current_language_rtl()) {
533  // inner_location() already takes account of the scrollbar width
534  return x > loc.x + loc.w - width_used_so_far;
535  }
536  return x < loc.x + width_used_so_far;
537 }
538 
539 void menu::draw_row(const std::size_t row_index, const SDL_Rect& loc, ROW_TYPE)
540 {
541  //called from style, draws one row's contents in a generic and adaptable way
542  const auto& imi = items_[row_index].fields;
543  rect area = video::game_canvas();
544  bool lang_rtl = current_language_rtl();
545 
546  // There's nothing to draw for the indent, just mark the space as used
547  int width_used_so_far = imi.indent_level * font::pango_line_size(indent_string, style_->get_font_size()).first;
548 
549  if (!imi.icon.empty()) {
550  const texture img = image::get_texture(imi.icon);
551  int img_w = img.w();
552  int img_h = img.h();
553  const int remaining_width = max_width_ < 0 ? area.w : std::min<int>(max_width_, loc.w - width_used_so_far);
554  if(img && img_w <= remaining_width && loc.y + img_h < area.h) {
555  const std::size_t y = loc.y + (loc.h - img_h)/2;
556  const std::size_t x = loc.x + (lang_rtl ? loc.w - width_used_so_far - img_w : width_used_so_far);
557  draw::blit(img, {int(x), int(y), img_w, img_h});
558 
559  // If there wasn't space for the icon, it doesn't get drawn, nor does the width get used.
560  // If it is drawn, add 5 pixels of padding.
561  width_used_so_far += img_w + 5;
562  }
563  }
564 
565  // Expected to be non-empty, but I guess a unit type could have a blank name
566  if (!imi.text.empty()) {
567  const auto text_size = font::pango_line_size(imi.text, style_->get_font_size());
568  const std::size_t x = loc.x + (lang_rtl ? std::max(0, loc.w - width_used_so_far - text_size.first) : width_used_so_far);
569  const std::size_t y = loc.y + (loc.h - text_size.second)/2;
570  rect text_loc = loc;
571  text_loc.w = loc.w - (width_used_so_far) - 2 * style_->get_thickness();
572  text_loc.h = text_size.second;
573  font::pango_draw_text(true, text_loc, style_->get_font_size(), font::NORMAL_COLOR, imi.text,
574  x, y);
575  }
576 }
577 
579 {
580  for(std::size_t i = 0; i != item_pos_.size(); ++i) {
583  }
584 }
585 
586 int menu::hit(int x, int y) const
587 {
588  const SDL_Rect& loc = inner_location();
589  if (x >= loc.x && x < loc.x + loc.w && y >= loc.y && y < loc.y + loc.h) {
590  for(std::size_t i = 0; i != items_.size(); ++i) {
591  const SDL_Rect& rect = get_item_rect(i);
592  if (y >= rect.y && y < rect.y + rect.h)
593  return i;
594  }
595  }
596 
597  return -1;
598 }
599 
600 SDL_Rect menu::get_item_rect(int item) const
601 {
603 }
604 
605 SDL_Rect menu::get_item_rect_internal(std::size_t item) const
606 {
607  unsigned int first_item_on_screen = get_position();
608  if (item < first_item_on_screen ||
609  item >= first_item_on_screen + max_items_onscreen()) {
610  return sdl::empty_rect;
611  }
612 
613  const std::map<int,SDL_Rect>::const_iterator i = itemRects_.find(item);
614  if(i != itemRects_.end())
615  return i->second;
616 
617  const SDL_Rect& loc = inner_location();
618 
619  int y = loc.y;
620  if (item != first_item_on_screen) {
621  const SDL_Rect& prev = get_item_rect_internal(item-1);
622  y = prev.y + prev.h;
623  }
624 
625  rect res(loc.x, y, loc.w, get_item_height(item));
626 
627  const point canvas_size = video::game_canvas_size();
628 
629  if(res.x > canvas_size.x) {
630  return sdl::empty_rect;
631  } else if(res.x + res.w > canvas_size.x) {
632  res.w = canvas_size.x - res.x;
633  }
634 
635  if(res.y > canvas_size.y) {
636  return sdl::empty_rect;
637  } else if(res.y + res.h > canvas_size.y) {
638  res.h = canvas_size.y - res.y;
639  }
640 
641  //only insert into the cache if the menu's co-ordinates have
642  //been initialized
643  if (loc.x > 0 && loc.y > 0)
644  itemRects_.emplace(item, res);
645 
646  return res;
647 }
648 
650 {
651  return style_->item_size(imi).h;
652 }
653 
654 std::size_t menu::get_item_height(int) const
655 {
656  // This could probably return the height of a single line of Pango text, plus
657  // padding. However, keeping compatibility with the current numbers means
658  // less unknowns about what the numbers should actually be.
659  if(item_height_ != -1)
660  return std::size_t(item_height_);
661 
662  std::size_t max_height = 0;
663  for(const auto& item : items_) {
664  max_height = std::max<int>(max_height,get_item_height_internal(item.fields));
665  }
666 
667  return item_height_ = max_height;
668 }
669 
670 void menu::invalidate_row(std::size_t id)
671 {
672  if(id >= items_.size()) {
673  return;
674  }
675 
677 }
678 
679 void menu::invalidate_row_pos(std::size_t pos)
680 {
681  if(pos >= items_.size()) {
682  return;
683  }
684 
685  invalidate_row(items_[pos].id);
686 }
687 
688 }
map_location prev
Definition: astarsearch.cpp:64
virtual SDL_Rect item_size(const indented_menu_item &imi) const
Definition: menu.cpp:438
std::size_t get_thickness() const
Definition: menu_style.cpp:55
std::size_t get_font_size() const
Definition: menu_style.cpp:53
virtual void draw_row_bg(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:466
std::size_t get_cell_padding() const
Definition: menu_style.cpp:54
virtual void init()
Definition: menu.hpp:56
virtual void draw_row(menu &menu_ref, const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:489
Superclass of the help_menu, which displays the left-hand pane of the GUI1 help browser.
Definition: menu.hpp:46
void reset_selection()
Definition: menu.cpp:262
bool requires_event_focus(const SDL_Event *event=nullptr) const override
Definition: menu.cpp:301
int max_items_
Definition: menu.hpp:193
int process()
Definition: menu.cpp:405
void draw_contents() override
Definition: menu.cpp:578
bool show_result_
Definition: menu.hpp:212
void move_selection_up(std::size_t dep)
Definition: menu.cpp:227
bool click_selects_
Definition: menu.hpp:207
std::size_t get_item_height_internal(const indented_menu_item &imi) const
Definition: menu.cpp:649
std::optional< int > widest_row_width_
Cached return value of widest_row_width(), calculated on demand when calling that function.
Definition: menu.hpp:204
SDL_Rect get_item_rect_internal(std::size_t pos) const
Definition: menu.cpp:605
int widest_row_width() const
Definition: menu.cpp:504
void set_max_width(const int new_max_width)
Definition: menu.cpp:158
bool out_
Definition: menu.hpp:208
std::size_t selected_
Definition: menu.hpp:206
int item_height_
Definition: menu.hpp:193
void set_selection_pos(std::size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT)
Definition: menu.cpp:206
void set_max_height(const int new_max_height)
Set a new max height for this menu.
Definition: menu.cpp:150
std::vector< std::size_t > item_pos_
Definition: menu.hpp:199
bool last_was_doubleclick_
Definition: menu.hpp:240
std::map< int, SDL_Rect > itemRects_
Definition: menu.hpp:218
void adjust_viewport_to_selection()
Definition: menu.cpp:199
bool use_ellipsis_
Definition: menu.hpp:243
menu(bool click_selects=false, int max_height=-1, int max_width=-1, style *menu_style=nullptr, const bool auto_join=true)
Definition: menu.cpp:43
void invalidate_row_pos(std::size_t pos)
Definition: menu.cpp:679
static style & default_style
Definition: menu.hpp:106
SELECTION_MOVE_VIEWPORT
Definition: menu.hpp:251
@ NO_MOVE_VIEWPORT
Definition: menu.hpp:251
@ MOVE_VIEWPORT
Definition: menu.hpp:251
int selection() const
Definition: menu.cpp:106
void set_inner_location(const SDL_Rect &rect) override
Definition: menu.cpp:115
style * style_
Definition: menu.hpp:170
~menu()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: menu.cpp:59
virtual void handle_event(const SDL_Event &event) override
Definition: menu.cpp:334
void update_size()
Definition: menu.cpp:80
void move_selection_down(std::size_t dep)
Definition: menu.cpp:232
bool double_clicked_
Definition: menu.hpp:214
int hit(int x, int y) const
Definition: menu.cpp:586
void move_selection_keeping_viewport(std::size_t id)
Definition: menu.cpp:255
virtual void set_items(const std::vector< indented_menu_item > &items, std::optional< std::size_t > selected)
Set new items to show and redraw/recalculate everything.
Definition: menu.cpp:121
std::size_t max_items_onscreen() const
Definition: menu.cpp:166
void key_press(SDL_Keycode key)
Definition: menu.cpp:267
std::size_t get_item_height(int item) const
Definition: menu.cpp:654
void set_click_selects(bool value)
Definition: menu.cpp:422
virtual void draw_row(const std::size_t row_index, const SDL_Rect &rect, ROW_TYPE type)
Definition: menu.cpp:539
void fill_items(const std::vector< indented_menu_item > &imi)
Set new items to show.
Definition: menu.cpp:63
bool double_clicked()
Definition: menu.cpp:415
bool silent_
Definition: menu.hpp:171
void move_selection_to(std::size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT)
Definition: menu.cpp:239
void update_scrollbar_grip_height()
Definition: menu.cpp:74
void scroll(unsigned int pos) override
Definition: menu.cpp:432
void set_numeric_keypress_selection(bool value)
Definition: menu.cpp:427
int max_height_
Definition: menu.hpp:192
void move_selection(std::size_t id)
Definition: menu.cpp:247
SDL_Rect get_item_rect(int item) const
Definition: menu.cpp:600
std::vector< item > items_
Definition: menu.hpp:198
int max_width_
Definition: menu.hpp:192
bool num_selects_
variable which determines whether a numeric keypress should select an item on the dialog
Definition: menu.hpp:235
bool hit_on_indent_or_icon(std::size_t row_index, int x) const
Returns true if a mouse-click with the given x-coordinate, and an appropriate y-coordinate would lie ...
Definition: menu.cpp:519
ROW_TYPE
Definition: menu.hpp:49
@ SELECTED_ROW
Definition: menu.hpp:49
@ NORMAL_ROW
Definition: menu.hpp:49
void invalidate_row(std::size_t id)
Definition: menu.cpp:670
bool ignore_next_doubleclick_
Definition: menu.hpp:239
unsigned get_max_position() const
Definition: scrollarea.cpp:86
bool has_scrollbar() const
Definition: scrollarea.cpp:33
void set_shown_size(unsigned h)
Definition: scrollarea.cpp:106
void adjust_position(unsigned pos)
Definition: scrollarea.cpp:96
unsigned get_position() const
Definition: scrollarea.cpp:81
void set_full_size(unsigned h)
Definition: scrollarea.cpp:113
void set_position(unsigned pos)
Definition: scrollarea.cpp:91
rect inner_location() const
Definition: scrollarea.cpp:134
virtual void handle_event(const SDL_Event &event)
Definition: scrollarea.cpp:147
unsigned scrollbar_width() const
Definition: scrollarea.cpp:142
bool focus(const SDL_Event *event)
Definition: widget.cpp:136
void set_measurements(int w, int h)
Definition: widget.cpp:108
int width() const
Definition: widget.cpp:113
void queue_redraw()
Indicate that the widget should be redrawn.
Definition: widget.cpp:215
int height() const
Definition: widget.cpp:118
void set_focus(bool focus)
Definition: widget.cpp:128
bool hidden() const
Definition: widget.cpp:161
bool mouse_locked() const
Definition: widget.cpp:64
bool focus_
Definition: widget.hpp:90
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
int w() const
The draw-space width of the texture, in pixels.
Definition: texture.hpp:105
int h() const
The draw-space height of the texture, in pixels.
Definition: texture.hpp:114
Drawing functions, for drawing things on the screen.
#define DOUBLE_CLICK_EVENT
Definition: events.hpp:24
std::size_t i
Definition: function.cpp:968
int w
bool current_language_rtl()
Definition: language.cpp:54
void fill(const SDL_Rect &rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Fill an area with the given colour.
Definition: draw.cpp:50
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:310
void rect(const SDL_Rect &rect)
Draw a rectangle.
Definition: draw.cpp:150
rect pango_draw_text(bool actually_draw, const rect &area, int size, const color_t &color, const std::string &text, int x, int y, bool use_tooltips, pango_text::FONT_STYLE style)
Draws text on the screen.
std::pair< int, int > pango_line_size(const std::string &line, int font_size, font::pango_text::FONT_STYLE font_style)
Determine the width and height of a line of text given a certain font size.
const color_t NORMAL_COLOR
std::string selected
const std::string menu_select
const std::string button_press
General purpose widgets.
texture get_texture(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image texture suitable for hardware-accelerated rendering.
Definition: picture.cpp:960
const std::vector< std::string > items
constexpr const SDL_Rect empty_rect
Definition: rect.hpp:30
void play_UI_sound(const std::string &files)
Definition: sound.cpp:1064
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
point game_canvas_size()
The size of the game canvas, in drawing coordinates / game pixels.
Definition: video.cpp:434
rect game_canvas()
The game canvas area, in drawing coordinates.
Definition: video.cpp:429
Contains the SDL_Rect helper code.
Transitional API for porting SDL_ttf-based code to Pango.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
The only kind of row still supported by the menu class.
Definition: menu.hpp:33
std::string text
Definition: menu.hpp:38
int indent_level
An amount of blank space at the start of the row, measured in tab-stops (so 1 is around 4 en-widths)
Definition: menu.hpp:35
std::string icon
If non-empty, a picture to display before the text.
Definition: menu.hpp:37
indented_menu_item fields
Definition: menu.hpp:115
Holds a 2D point.
Definition: point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:47
mock_char c
static map_location::DIRECTION n
#define h