The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
show_dialog.cpp
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 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
17 #include "show_dialog.hpp"
18 
19 #include "floating_label.hpp"
20 #include "font/sdl_ttf.hpp"
21 #include "image.hpp"
22 #include "gettext.hpp"
24 #include "help/help.hpp"
26 #include "log.hpp"
27 #include "font/marked-up_text.hpp"
28 #include "font/standard_colors.hpp"
29 #include "sdl/rect.hpp"
30 
31 static lg::log_domain log_display("display");
32 #define ERR_DP LOG_STREAM(err, log_display)
33 #define ERR_G LOG_STREAM(err, lg::general)
34 
35 namespace {
36 bool is_in_dialog = false;
37 }
38 
39 namespace gui {
40 
41 //static initialization
42 const int ButtonHPadding = 10;
43 const int ButtonVPadding = 10;
44 
45 //note: style names are directly related to the panel image file names
47 const dialog_frame::style dialog_frame::message_style("translucent65", 3);
48 const dialog_frame::style dialog_frame::preview_style("../dialogs/selection", 0);
50 
51 const int dialog_frame::title_border_w = 10;
52 const int dialog_frame::title_border_h = 5;
53 
54 
55 
56 bool in_dialog()
57 {
58  return is_in_dialog || gui2::is_in_dialog();
59 }
60 
62 {
63  is_in_dialog = true;
64 }
65 
67 {
69  int mousex, mousey;
70  SDL_GetMouseState(&mousex, &mousey);
71  SDL_Event pb_event;
72  pb_event.type = SDL_MOUSEMOTION;
73  pb_event.motion.state = 0;
74  pb_event.motion.x = mousex;
75  pb_event.motion.y = mousey;
76  pb_event.motion.xrel = 0;
77  pb_event.motion.yrel = 0;
78  SDL_PushEvent(&pb_event);
79 }
80 
82  const style& style, bool auto_restore,
83  std::vector<button*>* buttons, button* help_button) :
84  title_(title),
85  video_(video),
86  dialog_style_(style),
87  buttons_(buttons),
88  help_button_(help_button),
89  restorer_(nullptr),
90  auto_restore_(auto_restore),
91  dim_(),
92  top_(image::get_image("dialogs/" + dialog_style_.panel + "-border-top.png")),
93  bot_(image::get_image("dialogs/" + dialog_style_.panel + "-border-bottom.png")),
94  left_(image::get_image("dialogs/" + dialog_style_.panel + "-border-left.png")),
95  right_(image::get_image("dialogs/" + dialog_style_.panel + "-border-right.png")),
96  top_left_(image::get_image("dialogs/" + dialog_style_.panel + "-border-topleft.png")),
97  bot_left_(image::get_image("dialogs/" + dialog_style_.panel + "-border-botleft.png")),
98  top_right_(image::get_image("dialogs/" + dialog_style_.panel + "-border-topright.png")),
99  bot_right_(image::get_image("dialogs/" + dialog_style_.panel + "-border-botright.png")),
100  bg_(image::get_image("dialogs/" + dialog_style_.panel + "-background.png")),
101  have_border_(top_ != nullptr && bot_ != nullptr && left_ != nullptr && right_ != nullptr),
102  dirty_(true)
103 {
104 }
105 
107 {
108  delete restorer_;
109 }
110 
112  interior(sdl::empty_rect), exterior(sdl::empty_rect), title(sdl::empty_rect), button_row(sdl::empty_rect)
113 {}
114 
116  return layout(rect.x, rect.y, rect.w, rect.h);
117 }
118 
120  int padding = 0;
121  if(have_border_) {
122  padding += top_->h;
123  }
124  if(!title_.empty()) {
126  }
127  return padding;
128 }
129 
130 void dialog_frame::set_dirty(bool dirty) {
131  dirty_ = dirty;
132 }
133 
134 void dialog_frame::handle_window_event(const SDL_Event& event) {
135 
136  if (event.type == SDL_WINDOWEVENT) {
137  switch (event.window.event) {
138  case SDL_WINDOWEVENT_RESIZED:
139  case SDL_WINDOWEVENT_RESTORED:
140  case SDL_WINDOWEVENT_SHOWN:
141  case SDL_WINDOWEVENT_EXPOSED:
142  set_dirty();
143  }
144  }
145 }
146 
147 void dialog_frame::handle_event(const SDL_Event& event) {
148 
149  if (event.type == DRAW_ALL_EVENT) {
150  set_dirty();
151 
152  if (buttons_) {
153  for(std::vector<button *>::iterator it = buttons_->begin(); it != buttons_->end(); ++it) {
154  (*it)->set_dirty(true);
155  }
156  }
157  }
158 
159  if (event.type == DRAW_EVENT || event.type == DRAW_ALL_EVENT) {
160  draw();
161  }
162 }
163 
165  int padding = 0;
166  if(buttons_ != nullptr) {
167  for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
168  padding = std::max<int>((**b).height() + ButtonVPadding, padding);
169  }
170  }
171  if(have_border_) {
172  padding += bot_->h;
173  }
174  return padding;
175 }
176 
179  if(!title_.empty()) {
180  dim_.title = draw_title(nullptr);
182  }
183  if(buttons_ != nullptr) {
184  for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
185  dim_.button_row.w += (**b).width() + ButtonHPadding;
186  dim_.button_row.h = std::max<int>((**b).height() + ButtonVPadding,dim_.button_row.h);
187  }
188 
190  dim_.button_row.y = y + h;
191 
193  }
194 
195  size_t buttons_width = dim_.button_row.w;
196 
197  if(help_button_ != nullptr) {
198  buttons_width += help_button_->width() + ButtonHPadding*2;
199  dim_.button_row.y = y + h;
200  }
201 
202  y -= dim_.title.h;
203  w = std::max(w, std::max(dim_.title.w, static_cast<int>(buttons_width)));
204  h += dim_.title.h + dim_.button_row.h;
205  dim_.button_row.x += x + w;
206 
207  SDL_Rect bounds = video_.screen_area();
208  if(have_border_) {
209  bounds.x += left_->w;
210  bounds.y += top_->h;
211  bounds.w -= left_->w;
212  bounds.h -= top_->h;
213  }
214  if(x < bounds.x) {
215  w += x;
216  x = bounds.x;
217  }
218  if(y < bounds.y) {
219  h += y;
220  y = bounds.y;
221  }
222  if(x > bounds.w) {
223  w = 0;
224  } else if(x + w > bounds.w) {
225  w = bounds.w - x;
226  }
227  if(y > bounds.h) {
228  h = 0;
229  } else if(y + h > bounds.h) {
230  h = bounds.h - y;
231  }
232  dim_.interior.x = x;
233  dim_.interior.y = y;
234  dim_.interior.w = w;
235  dim_.interior.h = h;
236  if(have_border_) {
237  dim_.exterior.x = dim_.interior.x - left_->w;
238  dim_.exterior.y = dim_.interior.y - top_->h;
239  dim_.exterior.w = dim_.interior.w + left_->w + right_->w;
240  dim_.exterior.h = dim_.interior.h + top_->h + bot_->h;
241  } else {
243  }
246  return dim_;
247 }
248 
250 {
251  if(have_border_ == false) {
252  return;
253  }
254 
255  surface top_image(scale_surface(top_, dim_.interior.w, top_->h));
256 
257  if(top_image != nullptr) {
258  video_.blit_surface(dim_.interior.x, dim_.exterior.y, top_image);
259  }
260 
261  surface bot_image(scale_surface(bot_, dim_.interior.w, bot_->h));
262 
263  if(bot_image != nullptr) {
264  video_.blit_surface(dim_.interior.x, dim_.interior.y + dim_.interior.h, bot_image);
265  }
266 
267  surface left_image(scale_surface(left_, left_->w, dim_.interior.h));
268 
269  if(left_image != nullptr) {
270  video_.blit_surface(dim_.exterior.x, dim_.interior.y, left_image);
271  }
272 
273  surface right_image(scale_surface(right_, right_->w, dim_.interior.h));
274 
275  if(right_image != nullptr) {
276  video_.blit_surface(dim_.interior.x + dim_.interior.w, dim_.interior.y, right_image);
277  }
278 
279  if(top_left_ == nullptr || bot_left_ == nullptr || top_right_ == nullptr || bot_right_ == nullptr) {
280  return;
281  }
282 
287 }
288 
290 {
291  delete restorer_;
292  restorer_ = nullptr;
293 }
294 
296 {
297  if(auto_restore_) {
300  }
301 
304  surf = blur_surface(surf, dialog_style_.blur_radius);
305  sdl_blit(surf, nullptr, video_.getSurface(), &dim_.exterior);
306  }
307 
308  if(bg_ == nullptr) {
309  ERR_DP << "could not find dialog background '" << dialog_style_.panel << "'" << std::endl;
310  return;
311  }
312  for(int i = 0; i < dim_.interior.w; i += bg_->w) {
313  for(int j = 0; j < dim_.interior.h; j += bg_->h) {
314  SDL_Rect src {0,0,0,0};
315  src.w = std::min(dim_.interior.w - i, bg_->w);
316  src.h = std::min(dim_.interior.h - j, bg_->h);
317  SDL_Rect dst = src;
318  dst.x = dim_.interior.x + i;
319  dst.y = dim_.interior.y + j;
320  sdl_blit(bg_, &src, video_.getSurface(), &dst);
321  }
322  }
323 }
324 
326 {
327  SDL_Rect rect = CVideo::get_singleton().screen_area();
329  title_, dim_.title.x, dim_.title.y, false, TTF_STYLE_NORMAL);
330 }
331 
333 {
334  if (!dirty_)
335  return;
336 
337  //draw background
338  draw_background();
339 
340  //draw frame border
341  draw_border();
342 
343  //draw title
344  if (!title_.empty()) {
345  draw_title(&video_);
346  }
347 
348  //draw buttons
349  SDL_Rect buttons_area = dim_.button_row;
350  if(buttons_ != nullptr) {
351 #ifdef OK_BUTTON_ON_RIGHT
352  std::reverse(buttons_->begin(),buttons_->end());
353 #endif
354  for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
355  (**b).set_location(buttons_area.x, buttons_area.y);
356  buttons_area.x += (**b).width() + ButtonHPadding;
357  }
358  }
359 
360  if(help_button_ != nullptr) {
361  help_button_->set_location(dim_.interior.x+ButtonHPadding, buttons_area.y);
362  }
363 
364  dirty_ = false;
365 }
366 
367 }
368 
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: image.cpp:920
static const style preview_style
Definition: show_dialog.hpp:68
std::vector< char_t > string
static const style default_style
Definition: show_dialog.hpp:66
void set_dirty(bool dirty=true)
Definition: video.hpp:31
const color_t TITLE_COLOR
bool in_dialog()
Definition: show_dialog.cpp:56
General purpose widgets.
bool is_in_dialog()
Is a dialog open?
Definition: handler.cpp:1034
std::vector< button * > * buttons_
#define DRAW_EVENT
Definition: events.hpp:26
surface_restorer * restorer_
static CVideo & get_singleton()
Definition: video.hpp:43
#define h
surface scale_surface(const surface &surf, int w, int h)
Scale a surface using alpha-weighted modified bilinear filtering Note: causes artifacts with alpha gr...
Definition: utils.cpp:272
void blit_surface(int x, int y, surface surf, SDL_Rect *srcrect=nullptr, SDL_Rect *clip_rect=nullptr)
Draws a surface directly onto the screen framebuffer.
Definition: video.cpp:162
CONSTEXPR const SDL_Rect empty_rect
Definition: rect.hpp:32
surface get_surface_portion(const surface &src, SDL_Rect &area)
Get a portion of the screen.
Definition: utils.cpp:2271
surface & getSurface()
Returns a reference to the framebuffer.
Definition: video.cpp:468
const style & dialog_style_
#define b
const int ButtonHPadding
Definition: show_dialog.cpp:42
dimension_measurements layout(int x, int y, int w, int h)
SDL_Rect draw_title(CVideo *video)
int top_padding() const
int bottom_padding() const
virtual void handle_event(const SDL_Event &)
surface blur_surface(const surface &surf, int depth)
Cross-fades a surface.
Definition: utils.cpp:1462
virtual void set_location(const SDL_Rect &rect)
Definition: widget.cpp:83
int get_max_height(int size)
Definition: sdl_ttf.cpp:407
#define DRAW_ALL_EVENT
Definition: events.hpp:29
std::string title_
static const int title_border_w
Definition: show_dialog.hpp:65
static lg::log_domain log_display("display")
static const style titlescreen_style
Definition: show_dialog.hpp:69
dimension_measurements dim_
size_t i
Definition: function.cpp:933
int w
#define ERR_DP
Definition: show_dialog.cpp:32
const int SIZE_TITLE
Definition: constants.cpp:28
void handle_window_event(const SDL_Event &event)
Contains the SDL_Rect helper code.
SDL_Rect draw_text(surface &dst, const SDL_Rect &area, int size, const color_t &color, const std::string &txt, int x, int y, bool use_tooltips, int style)
Function to draw text on a surface.
this module manages the cache of images.
Definition: image.cpp:103
Standard logging facilities (interface).
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:295
static const int title_border_h
Definition: show_dialog.hpp:65
static void reverse(lua_State *L, StkId from, StkId to)
Definition: lapi.cpp:193
int width() const
Definition: widget.cpp:132
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:33
const int ButtonVPadding
Definition: show_dialog.cpp:43
dialog_frame(CVideo &video, const std::string &title="", const style &dialog_style=default_style, bool auto_restore=true, std::vector< button * > *buttons=nullptr, button *help_button=nullptr)
Definition: show_dialog.cpp:81
static const style message_style
Definition: show_dialog.hpp:67
std::string::const_iterator iterator
Definition: tokenizer.hpp:24