The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
button.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
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 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
17 #include "widgets/button.hpp"
18 
19 #include "global.hpp"
20 
21 #include "filesystem.hpp"
22 #include "font.hpp"
23 #include "game_config.hpp"
24 #include "game_errors.hpp"
25 #include "image.hpp"
26 #include "log.hpp"
27 #include "marked-up_text.hpp"
28 #include "sdl/rect.hpp"
30 #include "sound.hpp"
31 #include "video.hpp"
32 #include "text.hpp"
33 #include "wml_separators.hpp"
34 
35 #include <boost/algorithm/string/predicate.hpp>
36 
37 static lg::log_domain log_display("display");
38 #define ERR_DP LOG_STREAM(err, log_display)
39 
40 namespace gui {
41 
42 const int font_size = font::SIZE_NORMAL;
46 
48  std::string button_image_name, SPACE_CONSUMPTION spacing,
49  const bool auto_join, std::string overlay_image)
50  : widget(video, auto_join), type_(type),
51 #ifdef SDL_GPU
52  label_text_(label), label_image_(),
53  image_(), pressedImage_(), activeImage_(), pressedActiveImage_(),
54  disabledImage_(), pressedDisabledImage_(),
55  overlayImage_(), overlayPressedImage_(), overlayActiveImage_(),
56 #else
57  label_text_(label),
58  image_(nullptr), pressedImage_(nullptr), activeImage_(nullptr), pressedActiveImage_(nullptr),
59  disabledImage_(nullptr), pressedDisabledImage_(nullptr),
60  overlayImage_(nullptr), overlayPressedImage_(nullptr), overlayActiveImage_(nullptr),
61 #endif
62  state_(NORMAL), pressed_(false),
63  spacing_(spacing), base_height_(0), base_width_(0),
64  button_image_name_(), button_overlay_image_name_(overlay_image),
65  button_image_path_suffix_()
66 {
67  if (button_image_name.empty()) {
68 
69  switch (type_) {
70  case TYPE_PRESS:
71  button_image_name_ = "buttons/button_normal/button_H22";
72  break;
73  case TYPE_TURBO:
74  button_image_name_ = "buttons/button_menu/menu_button_copper_H20";
75  break;
76  case TYPE_CHECK:
77  button_image_name_ = "buttons/checkbox";
78  break;
79  case TYPE_RADIO:
80  button_image_name_ = "buttons/radiobox";
81  break;
82  default:
83  break;
84  }
85  } else {
86  button_image_name_ = "buttons/" + button_image_name;
87  }
88 
89  load_images();
90 }
91 
93 
94  std::string size_postfix;
95 
96  switch (location().h) {
97  case 25:
98  size_postfix = "_25";
99  break;
100  case 30:
101  size_postfix = "_30";
102  break;
103  case 60:
104  size_postfix = "_60";
105  break;
106  default:
107  break;
108  }
109 
110 #ifdef SDL_GPU
111  sdl::timage button_image(image::get_texture(button_image_name_ + ".png" + button_image_path_suffix_));
112  sdl::timage pressed_image(image::get_texture(button_image_name_ + "-pressed.png"+ button_image_path_suffix_));
113  sdl::timage active_image(image::get_texture(button_image_name_ + "-active.png"+ button_image_path_suffix_));
114  sdl::timage disabled_image;
115  if (filesystem::file_exists(game_config::path + "/images/" + button_image_name_ + "-disabled.png"))
116  disabled_image = image::get_texture(button_image_name_ + "-disabled.png"+ button_image_path_suffix_);
117  sdl::timage pressed_disabled_image, pressed_active_image, touched_image;
118 
119  if (!button_overlay_image_name_.empty()) {
120  overlayImage_ = image::get_texture(button_overlay_image_name_ + size_postfix + ".png"+ button_image_path_suffix_);
121  overlayPressedImage_ = image::get_texture(button_overlay_image_name_ + size_postfix + "-pressed.png"+ button_image_path_suffix_);
122 
123  if (filesystem::file_exists(game_config::path + "/images/" + button_overlay_image_name_ + size_postfix + "-active.png"))
124  overlayActiveImage_ = image::get_texture(button_overlay_image_name_ + size_postfix + "-active.png"+ button_image_path_suffix_);
125 
126  if (filesystem::file_exists(game_config::path + "/images/" + button_overlay_image_name_ + size_postfix + "-disabled.png"))
127  overlayDisabledImage_ = image::get_texture(button_overlay_image_name_ + size_postfix + "-disabled.png"+ button_image_path_suffix_);
129  overlayDisabledImage_ = image::get_texture(button_overlay_image_name_ + size_postfix + ".png~GS()" + button_image_path_suffix_);
130 
131  if (filesystem::file_exists(game_config::path + "/images/" + button_overlay_image_name_ + size_postfix + "-disabled-pressed.png"))
132  overlayPressedDisabledImage_ = image::get_texture(button_overlay_image_name_ + size_postfix + "-disabled-pressed.png");
134  overlayPressedDisabledImage_ = image::get_texture(button_overlay_image_name_ + size_postfix + "-pressed.png~GS()"+ button_image_path_suffix_);
135  } else {
136  overlayImage_ = sdl::timage();
137  }
138 
139  if (disabled_image.null()) {
140  disabled_image = image::get_texture(button_image_name_ + ".png~GS()" + button_image_path_suffix_);
141  }
142 
143  if (pressed_image.null())
144  pressed_image = button_image;
145 
146  if (active_image.null())
147  active_image = button_image;
148 
149  if (type_ == TYPE_CHECK || type_ == TYPE_RADIO) {
150  touched_image = image::get_texture(button_image_name_ + "-touched.png"+ button_image_path_suffix_);
151  if (touched_image.null())
152  touched_image = pressed_image;
153 
154  pressed_active_image = (image::get_texture(button_image_name_ + "-active-pressed.png"+ button_image_path_suffix_));
155  if (pressed_active_image.null())
156  pressed_active_image = pressed_image;
157 
158  if (filesystem::file_exists(game_config::path + "/images/" + button_image_name_ + size_postfix + "-disabled-pressed.png"))
159  pressed_disabled_image = image::get_texture(button_image_name_ + "-disabled-pressed.png"+ button_image_path_suffix_);
160  if (pressed_disabled_image.null())
161  pressed_disabled_image = image::get_texture(button_image_name_ + "-pressed.png~GS()"+ button_image_path_suffix_);
162  }
163 
164  if (button_image.null()) {
165  ERR_DP << "error initializing button!" << std::endl;
166  throw error();
167  }
168 
169  base_height_ = button_image.height();
170  base_width_ = button_image.width();
171 
172  if (type_ != TYPE_IMAGE) {
174  }
175 
176  image_ = button_image;
177  pressedImage_ = pressed_image;
178  activeImage_ = active_image;
179  disabledImage_ = disabled_image;
180  if (type_ == TYPE_CHECK || type_ == TYPE_RADIO) {
181  pressedDisabledImage_ = pressed_disabled_image;
182  pressedActiveImage_ = pressed_active_image;
183  touchedImage_ = touched_image;
184  }
185 
186  if (type_ == TYPE_IMAGE){
187  calculate_size();
188  }
189 #else
191  surface pressed_image(image::get_image(button_image_name_ + "-pressed.png"+ button_image_path_suffix_));
193  surface disabled_image;
194  if (filesystem::file_exists(game_config::path + "/images/" + button_image_name_ + "-disabled.png"))
195  disabled_image.assign((image::get_image(button_image_name_ + "-disabled.png"+ button_image_path_suffix_)));
196  surface pressed_disabled_image, pressed_active_image, touched_image;
197 
198  if (!button_overlay_image_name_.empty()) {
199 
200  if (button_overlay_image_name_.length() > size_postfix.length() &&
202  button_overlay_image_name_.resize(button_overlay_image_name_.length() - size_postfix.length());
203  }
204 
207 
208  if (filesystem::file_exists(game_config::path + "/images/" + button_overlay_image_name_ + size_postfix + "-active.png"))
210 
211  if (filesystem::file_exists(game_config::path + "/images/" + button_overlay_image_name_ + size_postfix + "-disabled.png"))
215 
216  if (filesystem::file_exists(game_config::path + "/images/" + button_overlay_image_name_ + size_postfix + "-disabled-pressed.png"))
220  } else {
221  overlayImage_.assign(nullptr);
222  }
223 
224  if (disabled_image == nullptr) {
225  disabled_image = image::get_image(button_image_name_ + ".png~GS()" + button_image_path_suffix_);
226  }
227 
228  if (pressed_image.null())
229  pressed_image.assign(button_image);
230 
231  if (active_image.null())
232  active_image.assign(button_image);
233 
234  if (type_ == TYPE_CHECK || type_ == TYPE_RADIO) {
235  touched_image.assign(image::get_image(button_image_name_ + "-touched.png"+ button_image_path_suffix_));
236  if (touched_image.null())
237  touched_image.assign(pressed_image);
238 
239  pressed_active_image.assign(image::get_image(button_image_name_ + "-active-pressed.png"+ button_image_path_suffix_));
240  if (pressed_active_image.null())
241  pressed_active_image.assign(pressed_image);
242 
243  if (filesystem::file_exists(game_config::path + "/images/" + button_image_name_ + size_postfix + "-disabled-pressed.png"))
244  pressed_disabled_image.assign(image::get_image(button_image_name_ + "-disabled-pressed.png"+ button_image_path_suffix_));
245  if (pressed_disabled_image.null())
246  pressed_disabled_image = image::get_image(button_image_name_ + "-pressed.png~GS()"+ button_image_path_suffix_);
247  }
248 
249  if (button_image.null()) {
250  std::string err_msg = "error initializing button images! file name: ";
251  err_msg += button_image_name_;
252  err_msg += ".png";
253  ERR_DP << err_msg << std::endl;
254  throw game::error(err_msg);
255  }
256 
257  base_height_ = button_image->h;
258  base_width_ = button_image->w;
259 
260  if (type_ != TYPE_IMAGE) {
262  }
263 
264  if(type_ == TYPE_PRESS || type_ == TYPE_TURBO) {
265  image_.assign(scale_surface(button_image,location().w,location().h));
266  pressedImage_.assign(scale_surface(pressed_image,location().w,location().h));
267  activeImage_.assign(scale_surface(active_image,location().w,location().h));
268  disabledImage_.assign(scale_surface(disabled_image,location().w,location().h));
269  } else {
270  image_.assign(scale_surface(button_image,button_image->w,button_image->h));
271  activeImage_.assign(scale_surface(active_image,button_image->w,button_image->h));
272  disabledImage_.assign(scale_surface(disabled_image,button_image->w,button_image->h));
273  pressedImage_.assign(scale_surface(pressed_image,button_image->w,button_image->h));
274  if (type_ == TYPE_CHECK || type_ == TYPE_RADIO) {
275  pressedDisabledImage_.assign(scale_surface(pressed_disabled_image,button_image->w,button_image->h));
276  pressedActiveImage_.assign(scale_surface(pressed_active_image, button_image->w, button_image->h));
277  touchedImage_.assign(scale_surface(touched_image, button_image->w, button_image->h));
278  }
279  }
280 
281  if (type_ == TYPE_IMAGE){
282  calculate_size();
283  }
284 #endif
285 }
286 
288 {
289 }
290 
292 {
293  if (type_ == TYPE_IMAGE){
294  SDL_Rect loc_image = location();
295 #ifdef SDL_GPU
296  loc_image.h = image_.height();
297  loc_image.w = image_.width();
298 #else
299  loc_image.h = image_->h;
300  loc_image.w = image_->w;
301 #endif
302  set_location(loc_image);
303  return;
304  }
305  SDL_Rect const &loc = location();
306  bool change_size = loc.h == 0 || loc.w == 0;
307 
308  if (!change_size) {
309  unsigned w = loc.w - (type_ == TYPE_PRESS || type_ == TYPE_TURBO ? horizontal_padding : checkbox_horizontal_padding + base_width_);
310  if (type_ != TYPE_IMAGE)
311  {
312  int fs = font_size;
313  int style = TTF_STYLE_NORMAL;
314  std::string::const_iterator i_beg = label_text_.begin(), i_end = label_text_.end(),
315  i = font::parse_markup(i_beg, i_end, &fs, nullptr, &style);
316  if (i != i_end) {
317  std::string tmp(i, i_end);
318  label_text_.erase(i - i_beg, i_end - i_beg);
319  label_text_ += font::make_text_ellipsis(tmp, fs, w, style);
320  }
321  }
322  }
323 
324  if (type_ != TYPE_IMAGE){
325  textRect_ = font::draw_text(nullptr, screen_area(), font_size,
327  }
328 
329  // TODO: There's a weird text clipping bug, allowing the code below to run fixes it.
330  // The proper fix should possibly be in the draw_contents() function.
331 #if 0
332  if (!change_size)
333  return;
334 #endif
335 
336  set_height(std::max(textRect_.h+vertical_padding,base_height_));
337  if(type_ == TYPE_PRESS || type_ == TYPE_TURBO) {
338  if(spacing_ == MINIMUM_SPACE) {
339  set_width(textRect_.w + horizontal_padding);
340  } else {
341  set_width(std::max(textRect_.w+horizontal_padding,base_width_));
342  }
343  } else {
344  if(label_text_.empty()) {
346  } else {
347  set_width(checkbox_horizontal_padding + textRect_.w + base_width_);
348  }
349  }
350 }
351 
353 {
354  if (type_ != TYPE_CHECK && type_ != TYPE_RADIO && type_ != TYPE_IMAGE)
355  return;
356  STATE new_state;
357 
358  if (check) {
359  new_state = (state_ == ACTIVE || state_ == PRESSED_ACTIVE)? PRESSED_ACTIVE : PRESSED;
360  } else {
361  new_state = (state_ == ACTIVE || state_ == PRESSED_ACTIVE)? ACTIVE : NORMAL;
362  }
363 
364  if (state_ != new_state) {
365  state_ = new_state;
366  set_dirty();
367  }
368 }
369 
370 void button::set_active(bool active)
371 {
372  if ((state_ == NORMAL) && active) {
373  state_ = ACTIVE;
374  set_dirty();
375  } else if ((state_ == ACTIVE) && !active) {
376  state_ = NORMAL;
377  set_dirty();
378  }
379 }
380 
381 bool button::checked() const
382 {
384 }
385 
386 void button::enable(bool new_val)
387 {
388  if(new_val != enabled())
389  {
390  pressed_ = false;
391  // check buttons should keep their state
392  if(type_ != TYPE_CHECK) {
393  state_ = NORMAL;
394  }
395  widget::enable(new_val);
396  }
397 }
398 
400 {
401 #ifdef SDL_GPU
402  sdl::timage image = image_;
403  const int image_w = image_.width();
404 
405  int offset = 0;
406  switch(state_) {
407  case ACTIVE:
408  image = activeImage_;
409  break;
410  case PRESSED:
411  image = pressedImage_;
412  if (type_ == TYPE_PRESS)
413  offset = 1;
414  break;
415  case PRESSED_ACTIVE:
416  image = pressedActiveImage_;
417  break;
418  case TOUCHED_NORMAL:
419  case TOUCHED_PRESSED:
420  image = touchedImage_;
421  break;
422  default:
423  break;
424  }
425 
426  SDL_Rect const &loc = location();
427  SDL_Rect clipArea = loc;
428  const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset;
429  int textx;
430 
431  if (type_ != TYPE_CHECK && type_ != TYPE_RADIO && type_ != TYPE_IMAGE)
432  textx = loc.x + image.width() / 2 - textRect_.w / 2 + offset;
433  else {
434  clipArea.w += image_w + checkbox_horizontal_padding;
435  textx = loc.x + image_w + checkbox_horizontal_padding / 2;
436  }
437 
438  SDL_Color button_color = font::BUTTON_COLOR;
439 
440  if (!enabled()) {
441 
442  if (state_ == PRESSED || state_ == PRESSED_ACTIVE)
443  image = pressedDisabledImage_;
444  else image = disabledImage_;
445 
446  button_color = font::GRAY_COLOR;
447  }
448 
449  sdl::timage overlay;
450  if (!overlayImage_.null()) {
451 
453 
454  if (!overlayPressedImage_.null()) {
455  switch (state_) {
456  case ACTIVE:
457  if (!overlayActiveImage_.null())
458  overlay = overlayActiveImage_;
459  break;
460  case PRESSED:
461  case PRESSED_ACTIVE:
462  case TOUCHED_NORMAL:
463  case TOUCHED_PRESSED:
465  break;
466  default:
467  break;
468  }
469  }
470 
471  }
472 
473  image.set_scale(float(loc.w) / image.width(), float(loc.h) / image.height());
474  overlay.set_scale(float(loc.w) / overlay.width(), float(loc.h) / image.height());
475 
476  video().draw_texture(image, loc.x, loc.y);
477  video().draw_texture(overlay, loc.x, loc.y);
478  if (type_ != TYPE_IMAGE){
479  clipArea.x += offset;
480  clipArea.y += offset;
481  clipArea.w -= 2*offset;
482  clipArea.h -= 2*offset;
483 // label_image_.set_clip(clipArea);
484  video().draw_texture(label_image_, textx, texty);
485  }
486 #else
487  surface image = image_;
488  const int image_w = image_->w;
489 
490  int offset = 0;
491  switch(state_) {
492  case ACTIVE:
493  image = activeImage_;
494  break;
495  case PRESSED:
496  image = pressedImage_;
497  if (type_ == TYPE_PRESS)
498  offset = 1;
499  break;
500  case PRESSED_ACTIVE:
501  image = pressedActiveImage_;
502  break;
503  case TOUCHED_NORMAL:
504  case TOUCHED_PRESSED:
505  image = touchedImage_;
506  break;
507  default:
508  break;
509  }
510 
511  SDL_Rect const &loc = location();
512  SDL_Rect clipArea = loc;
513  const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset;
514  int textx;
515 
516  if (type_ != TYPE_CHECK && type_ != TYPE_RADIO && type_ != TYPE_IMAGE)
517  textx = loc.x + image->w / 2 - textRect_.w / 2 + offset;
518  else {
519  clipArea.w += image_w + checkbox_horizontal_padding;
520  textx = loc.x + image_w + checkbox_horizontal_padding / 2;
521  }
522 
523  SDL_Color button_color = font::BUTTON_COLOR;
524 
525  if (!enabled()) {
526 
527  if (state_ == PRESSED || state_ == PRESSED_ACTIVE)
528  image = pressedDisabledImage_;
529  else image = disabledImage_;
530 
531  button_color = font::GRAY_COLOR;
532  }
533 
534  if (!overlayImage_.null()) {
535 
536  surface noverlay = make_neutral_surface(
538 
539  if (!overlayPressedImage_.null()) {
540  switch (state_) {
541  case ACTIVE:
542  if (!overlayActiveImage_.null())
544  break;
545  case PRESSED:
546  case PRESSED_ACTIVE:
547  case TOUCHED_NORMAL:
548  case TOUCHED_PRESSED:
549  noverlay = make_neutral_surface( enabled() ?
551  break;
552  default:
553  break;
554  }
555  }
556 
557  surface nimage = make_neutral_surface(image);
558  blit_surface(noverlay, nullptr, nimage, nullptr);
559  image = nimage;
560  }
561 
562  video().blit_surface(loc.x, loc.y, image);
563  if (type_ != TYPE_IMAGE){
564  clipArea.x += offset;
565  clipArea.y += offset;
566  clipArea.w -= 2*offset;
567  clipArea.h -= 2*offset;
568  font::draw_text(&video(), clipArea, font_size, button_color, label_text_, textx, texty);
569  }
570 
571  update_rect(loc);
572 #endif
573 }
574 
575 bool button::hit(int x, int y) const
576 {
577  return sdl::point_in_rect(x,y,location());
578 }
579 
580 static bool is_valid_image(const std::string& str) { return !str.empty() && str[0] != IMAGE_PREFIX; }
581 
582 void button::set_image(const std::string& image_file)
583 {
584  if(!is_valid_image(image_file)) {
585  return;
586  }
587 
588  button_image_name_ = "buttons/" + image_file;
589  load_images();
590  set_dirty();
591 }
592 
593 void button::set_overlay(const std::string& image_file)
594 {
595  if(!is_valid_image(image_file)) {
596  return;
597  }
598 
599  button_overlay_image_name_ = image_file;
600  load_images();
601  set_dirty();
602 }
603 
605 {
606  label_text_ = val;
607 
608  //if we have a list of items, use the first one that isn't an image
609  if (std::find(label_text_.begin(), label_text_.end(), COLUMN_SEPARATOR) != label_text_.end()) {
610  const std::vector<std::string>& items = utils::split(label_text_, COLUMN_SEPARATOR);
611  const std::vector<std::string>::const_iterator i = std::find_if(items.begin(),items.end(),is_valid_image);
612  if(i != items.end()) {
613  label_text_ = *i;
614  }
615  }
616 
617  calculate_size();
618 #ifdef SDL_GPU
619  font::ttext text;
620  text.set_text(label_text_, false);
621  label_image_ = text.render_as_texture();
622 #endif
623 
624  set_dirty(true);
625 }
626 
627 void button::mouse_motion(SDL_MouseMotionEvent const &event)
628 {
629  if (hit(event.x, event.y)) {
630  // the cursor is over the widget
631  if (state_ == NORMAL)
632  state_ = ACTIVE;
633  else if (state_ == PRESSED && (type_ == TYPE_CHECK || type_ == TYPE_RADIO))
635  } else {
636  // the cursor is not over the widget
637 
638  if (type_ == TYPE_CHECK || type_ == TYPE_RADIO) {
639 
640  switch (state_) {
641  case TOUCHED_NORMAL:
642  state_ = NORMAL;
643  break;
644  case TOUCHED_PRESSED:
645  state_ = PRESSED;
646  break;
647  case PRESSED_ACTIVE:
648  state_ = PRESSED;
649  break;
650  case ACTIVE:
651  state_ = NORMAL;
652  break;
653  default:
654  break;
655  }
656  } else if ((type_ != TYPE_IMAGE) || state_ != PRESSED)
657  state_ = NORMAL;
658  }
659 }
660 
661 void button::mouse_down(SDL_MouseButtonEvent const &event)
662 {
663  if (hit(event.x, event.y) && event.button == SDL_BUTTON_LEFT) {
664 
665  switch (type_) {
666  case TYPE_RADIO:
667  case TYPE_CHECK:
668  if (state_ == PRESSED_ACTIVE)
670  else if (state_ == ACTIVE)
672  break;
673  case TYPE_TURBO:
675  state_ = PRESSED;
676  break;
677  default:
678  state_ = PRESSED;
679  break;
680  }
681  }
682 }
683 
685  state_ = NORMAL;
686  draw_contents();
687 }
688 
689 void button::mouse_up(SDL_MouseButtonEvent const &event)
690 {
691  if (!(hit(event.x, event.y) && event.button == SDL_BUTTON_LEFT))
692  return;
693 
694  // the user has stopped pressing the mouse left button while on the widget
695  switch (type_) {
696  case TYPE_CHECK:
697 
698  switch (state_) {
699  case TOUCHED_NORMAL:
701  pressed_ = true;
702  break;
703  case TOUCHED_PRESSED:
704  state_ = ACTIVE;
705  pressed_ = true;
706  break;
707  default:
708  break;
709  }
711  break;
712  case TYPE_RADIO:
715  pressed_ = true;
716  // exit(0);
718  }
719  //} else if (state_ == TOUCHED_PRESSED) {
720  // state_ = PRESSED_ACTIVE;
721  //}
722  break;
723  case TYPE_PRESS:
724  if (state_ == PRESSED) {
725  state_ = ACTIVE;
726  pressed_ = true;
728  }
729  break;
730  case TYPE_TURBO:
731  state_ = ACTIVE;
732  break;
733  case TYPE_IMAGE:
734  pressed_ = true;
736  break;
737  }
738 }
739 
740 void button::handle_event(const SDL_Event& event)
741 {
743 
744  if (hidden() || !enabled())
745  return;
746 
747  STATE start_state = state_;
748 
749  if (!mouse_locked())
750  {
751  switch(event.type) {
752  case SDL_MOUSEBUTTONDOWN:
753  mouse_down(event.button);
754  break;
755  case SDL_MOUSEBUTTONUP:
756  mouse_up(event.button);
757  break;
758  case SDL_MOUSEMOTION:
759  mouse_motion(event.motion);
760  break;
761  default:
762  return;
763  }
764  }
765 
766  if (start_state != state_)
767  set_dirty(true);
768 }
769 
771 {
772  if (type_ != TYPE_TURBO) {
773  const bool res = pressed_;
774  pressed_ = false;
775  return res;
776  } else
778 }
779 
780 }
const SDL_Color BUTTON_COLOR
Definition: font.cpp:571
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: image.cpp:878
#define ERR_DP
Definition: button.cpp:38
std::string button_image_name_
Definition: button.hpp:101
bool null() const
Definition: utils.hpp:104
void set_check(bool check)
Definition: button.cpp:352
virtual void mouse_up(const SDL_MouseButtonEvent &event)
Definition: button.cpp:689
button(CVideo &video, const std::string &label, TYPE type=TYPE_PRESS, std::string button_image="", SPACE_CONSUMPTION spacing=DEFAULT_SPACE, const bool auto_join=true, std::string overlay_image="")
Definition: button.cpp:47
std::string button_image_path_suffix_
Definition: button.hpp:103
static void check(LexState *ls, int c)
Definition: lparser.cpp:109
bool enabled() const
Definition: widget.cpp:212
bool pressed_
Definition: button.hpp:95
virtual void enable(bool new_val=true)
Definition: widget.cpp:204
int base_height_
Definition: button.hpp:99
void set_label(const std::string &val)
Definition: button.cpp:604
surface pressedActiveImage_
Definition: button.hpp:85
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
void set_image(const std::string &image_file_base)
Definition: button.cpp:582
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:29
surface pressedImage_
Definition: button.hpp:85
Definition: video.hpp:58
virtual void enable(bool new_val=true)
Definition: button.cpp:386
bool ends_with(const std::string &str, const std::string &suffix)
surface overlayPressedImage_
Definition: button.hpp:85
surface activeImage_
Definition: button.hpp:85
const int horizontal_padding
Definition: button.cpp:43
CVideo & video() const
Definition: widget.hpp:83
General purpose widgets.
surface image_
The image is cached in this surface.
Definition: canvas.cpp:961
void set_width(int w)
Definition: widget.cpp:119
GLuint const GLfloat * val
Definition: glew.h:2614
surface disabledImage_
Definition: button.hpp:85
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
const std::vector< std::string > items
surface scale_surface(const surface &surf, int w, int h)
Definition: utils.cpp:443
void blit_surface(int x, int y, surface surf, SDL_Rect *srcrect=nullptr, SDL_Rect *clip_rect=nullptr)
Definition: video.cpp:290
virtual void mouse_down(const SDL_MouseButtonEvent &event)
Definition: button.cpp:661
void load_images()
Definition: button.cpp:92
-file util.hpp
virtual void draw_contents()
Definition: button.cpp:399
char const IMAGE_PREFIX
int base_width_
Definition: button.hpp:99
void release()
Definition: button.cpp:684
const int SIZE_NORMAL
Definition: font.hpp:58
SDL_Rect screen_area()
Definition: video.cpp:135
void blit_surface(const surface &surf, const SDL_Rect *srcrect, surface &dst, const SDL_Rect *dstrect)
Replacement for sdl_blit.
Definition: utils.cpp:2185
GLintptr offset
Definition: glew.h:1650
bool hidden() const
Definition: widget.cpp:198
void set_dirty(bool dirty=true)
Definition: widget.cpp:217
surface overlayImage_
Definition: button.hpp:85
std::string button_overlay_image_name_
Definition: button.hpp:102
static bool is_valid_image(const std::string &str)
Definition: button.cpp:580
void calculate_size()
Definition: button.cpp:291
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
SPACE_CONSUMPTION spacing_
Definition: button.hpp:97
TYPE type_
Definition: button.hpp:68
surface touchedImage_
Definition: button.hpp:85
virtual void mouse_motion(const SDL_MouseMotionEvent &event)
Definition: button.cpp:627
SPACE_CONSUMPTION
Definition: button.hpp:38
void set_overlay(const std::string &image_file_base)
Definition: button.cpp:593
std::string path
bool pressed()
Definition: button.cpp:770
surface image_
Definition: button.hpp:85
bool point_in_rect(int x, int y, const SDL_Rect &rect)
Tests whether a point is inside a rectangle.
Definition: rect.cpp:47
std::string::const_iterator parse_markup(std::string::const_iterator i1, std::string::const_iterator i2, int *font_size, SDL_Color *color, int *style)
Parses the markup-tags at the front of a string.
SDL_Rect draw_text(surface &dst, const SDL_Rect &area, int size, const SDL_Color &color, const std::string &txt, int x, int y, bool use_tooltips, int style)
Function to draw text on a surface.
GLuint res
Definition: glew.h:9258
virtual void handle_event(const SDL_Event &event)
Definition: button.cpp:740
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:5910
size_t i
Definition: function.cpp:1057
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
bool hit(int x, int y) const
Definition: button.cpp:575
Declarations for File-IO.
surface overlayPressedDisabledImage_
Definition: button.hpp:85
std::string make_text_ellipsis(const std::string &text, int font_size, int max_width, int style)
If the text exceeds the specified max width, end it with an ellipsis (...)
Definition: font.cpp:996
const std::string button_press
surface overlayActiveImage_
Definition: button.hpp:85
const int vertical_padding
Definition: button.cpp:45
std::string label_text_
Definition: button.hpp:76
SDL_Rect textRect_
Definition: button.hpp:90
Contains the SDL_Rect helper code.
char const COLUMN_SEPARATOR
virtual ~button()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: button.cpp:287
bool find(E event, F functor)
Tests whether an event handler is available.
cl_event event
Definition: glew.h:3070
const SDL_Color GRAY_COLOR
Definition: font.cpp:565
surface make_neutral_surface(const surface &surf)
Definition: utils.cpp:135
bool checked() const
Definition: button.cpp:381
this module manages the cache of images.
Definition: image.cpp:75
void play_UI_sound(const std::string &files)
Definition: sound.cpp:842
Standard logging facilities (interface).
bool mouse_locked() const
Definition: widget.cpp:72
void assign(const surface &o)
Definition: utils.hpp:83
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
Definition: text.cpp:360
virtual void set_location(SDL_Rect const &rect)
Definition: widget.cpp:85
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
virtual void handle_event(SDL_Event const &)
Definition: widget.cpp:345
surface pressedDisabledImage_
Definition: button.hpp:85
STATE state_
Definition: button.hpp:93
SDL_Rect const & location() const
Definition: widget.cpp:144
static lg::log_domain log_display("display")
void set_height(int h)
Definition: widget.cpp:124
const int font_size
void update_rect(const SDL_Rect &)
Definition: dummy_video.cpp:27
bool file_exists(const std::string &name)
Returns true if a file or directory with such name already exists.
GLsizei const GLcharARB ** string
Definition: glew.h:4503
Text class.
Definition: text.hpp:66
surface overlayDisabledImage_
Definition: button.hpp:85
const int SIZE_SMALL
Definition: font.hpp:62
void set_active(bool active)
Definition: button.cpp:370
const int checkbox_horizontal_padding
const std::string checkbox_release