The Battle for Wesnoth  1.15.0-dev
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 #if 0
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 #endif
159 }
160 
162  int padding = 0;
163  if(buttons_ != nullptr) {
164  for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
165  padding = std::max<int>((**b).height() + ButtonVPadding, padding);
166  }
167  }
168  if(have_border_) {
169  padding += bot_->h;
170  }
171  return padding;
172 }
173 
176  if(!title_.empty()) {
177  dim_.title = draw_title(nullptr);
179  }
180  if(buttons_ != nullptr) {
181  for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
182  dim_.button_row.w += (**b).width() + ButtonHPadding;
183  dim_.button_row.h = std::max<int>((**b).height() + ButtonVPadding,dim_.button_row.h);
184  }
185 
187  dim_.button_row.y = y + h;
188 
190  }
191 
192  std::size_t buttons_width = dim_.button_row.w;
193 
194  if(help_button_ != nullptr) {
195  buttons_width += help_button_->width() + ButtonHPadding*2;
196  dim_.button_row.y = y + h;
197  }
198 
199  y -= dim_.title.h;
200  w = std::max(w, std::max(dim_.title.w, static_cast<int>(buttons_width)));
201  h += dim_.title.h + dim_.button_row.h;
202  dim_.button_row.x += x + w;
203 
204  SDL_Rect bounds = video_.screen_area();
205  if(have_border_) {
206  bounds.x += left_->w;
207  bounds.y += top_->h;
208  bounds.w -= left_->w;
209  bounds.h -= top_->h;
210  }
211  if(x < bounds.x) {
212  w += x;
213  x = bounds.x;
214  }
215  if(y < bounds.y) {
216  h += y;
217  y = bounds.y;
218  }
219  if(x > bounds.w) {
220  w = 0;
221  } else if(x + w > bounds.w) {
222  w = bounds.w - x;
223  }
224  if(y > bounds.h) {
225  h = 0;
226  } else if(y + h > bounds.h) {
227  h = bounds.h - y;
228  }
229  dim_.interior.x = x;
230  dim_.interior.y = y;
231  dim_.interior.w = w;
232  dim_.interior.h = h;
233  if(have_border_) {
234  dim_.exterior.x = dim_.interior.x - left_->w;
235  dim_.exterior.y = dim_.interior.y - top_->h;
236  dim_.exterior.w = dim_.interior.w + left_->w + right_->w;
237  dim_.exterior.h = dim_.interior.h + top_->h + bot_->h;
238  } else {
240  }
243  return dim_;
244 }
245 
247 {
248  if(have_border_ == false) {
249  return;
250  }
251 
252  surface top_image(scale_surface(top_, dim_.interior.w, top_->h));
253 
254  if(top_image != nullptr) {
255  video_.blit_surface(dim_.interior.x, dim_.exterior.y, top_image);
256  }
257 
258  surface bot_image(scale_surface(bot_, dim_.interior.w, bot_->h));
259 
260  if(bot_image != nullptr) {
261  video_.blit_surface(dim_.interior.x, dim_.interior.y + dim_.interior.h, bot_image);
262  }
263 
264  surface left_image(scale_surface(left_, left_->w, dim_.interior.h));
265 
266  if(left_image != nullptr) {
267  video_.blit_surface(dim_.exterior.x, dim_.interior.y, left_image);
268  }
269 
270  surface right_image(scale_surface(right_, right_->w, dim_.interior.h));
271 
272  if(right_image != nullptr) {
273  video_.blit_surface(dim_.interior.x + dim_.interior.w, dim_.interior.y, right_image);
274  }
275 
276  if(top_left_ == nullptr || bot_left_ == nullptr || top_right_ == nullptr || bot_right_ == nullptr) {
277  return;
278  }
279 
284 }
285 
287 {
288  delete restorer_;
289  restorer_ = nullptr;
290 }
291 
293 {
294  if(auto_restore_) {
297  }
298 
301  surf = blur_surface(surf, dialog_style_.blur_radius);
302  sdl_blit(surf, nullptr, video_.getSurface(), &dim_.exterior);
303  }
304 
305  if(bg_ == nullptr) {
306  ERR_DP << "could not find dialog background '" << dialog_style_.panel << "'" << std::endl;
307  return;
308  }
309  for(int i = 0; i < dim_.interior.w; i += bg_->w) {
310  for(int j = 0; j < dim_.interior.h; j += bg_->h) {
311  SDL_Rect src {0,0,0,0};
312  src.w = std::min(dim_.interior.w - i, bg_->w);
313  src.h = std::min(dim_.interior.h - j, bg_->h);
314  SDL_Rect dst = src;
315  dst.x = dim_.interior.x + i;
316  dst.y = dim_.interior.y + j;
317  sdl_blit(bg_, &src, video_.getSurface(), &dst);
318  }
319  }
320 }
321 
323 {
324  SDL_Rect rect = video->screen_area();
326  title_, dim_.title.x, dim_.title.y, false, TTF_STYLE_NORMAL);
327 }
328 
330 {
331  if (!dirty_)
332  return;
333 
334  //draw background
335  draw_background();
336 
337  //draw frame border
338  draw_border();
339 
340  //draw title
341  if (!title_.empty()) {
342  draw_title(&video_);
343  }
344 
345  //draw buttons
346  SDL_Rect buttons_area = dim_.button_row;
347  if(buttons_ != nullptr) {
348 #ifdef OK_BUTTON_ON_RIGHT
349  std::reverse(buttons_->begin(),buttons_->end());
350 #endif
351  for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
352  (**b).set_location(buttons_area.x, buttons_area.y);
353  buttons_area.x += (**b).width() + ButtonHPadding;
354  }
355  }
356 
357  if(help_button_ != nullptr) {
358  help_button_->set_location(dim_.interior.x+ButtonHPadding, buttons_area.y);
359  }
360 
361  dirty_ = false;
362 }
363 
364 }
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: image.cpp:1038
static const style preview_style
Definition: show_dialog.hpp:68
std::vector< char_t > string
int top_padding() const
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:273
static const style default_style
Definition: show_dialog.hpp:66
void set_dirty(bool dirty=true)
Definition: video.hpp:35
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:977
std::vector< button * > * buttons_
surface_restorer * restorer_
#define h
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
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:112
surface & getSurface()
Returns a reference to the framebuffer.
Definition: video.cpp:421
const style & dialog_style_
int bottom_padding() const
#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)
virtual void handle_event(const SDL_Event &)
virtual void set_location(const SDL_Rect &rect)
Definition: widget.cpp:83
int get_max_height(int size)
Definition: sdl_ttf.cpp:407
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
std::size_t i
Definition: function.cpp:933
dimension_measurements dim_
surface get_surface_portion(const surface &src, SDL_Rect &area)
Get a portion of the screen.
Definition: utils.cpp:2272
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:33
int width() const
Definition: widget.cpp:132
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.
constexpr const SDL_Rect empty_rect
Definition: rect.hpp:31
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:102
Standard logging facilities (interface).
surface blur_surface(const surface &surf, int depth)
Cross-fades a surface.
Definition: utils.cpp:1463
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
const int ButtonVPadding
Definition: show_dialog.cpp:43
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:205
static const style message_style
Definition: show_dialog.hpp:67
std::string::const_iterator iterator
Definition: tokenizer.hpp:24