00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "global.hpp"
00017
00018 #define GETTEXT_DOMAIN "wesnoth-lib"
00019
00020 #include "display.hpp"
00021 #include "gettext.hpp"
00022 #include "gui/auxiliary/event/handler.hpp"
00023 #include "help.hpp"
00024 #include "log.hpp"
00025 #include "marked-up_text.hpp"
00026
00027
00028 static lg::log_domain log_display("display");
00029 #define ERR_DP LOG_STREAM(err, log_display)
00030 #define ERR_G LOG_STREAM(err, lg::general)
00031
00032 namespace {
00033 bool is_in_dialog = false;
00034 }
00035
00036 namespace gui {
00037
00038
00039 const int ButtonHPadding = 10;
00040 const int ButtonVPadding = 10;
00041
00042
00043 const dialog_frame::style dialog_frame::default_style("opaque", 0);
00044 const dialog_frame::style dialog_frame::message_style("translucent65", 3);
00045 const dialog_frame::style dialog_frame::preview_style("../misc/selection", 0);
00046 const dialog_frame::style dialog_frame::titlescreen_style("translucent54", 1);
00047
00048 const int dialog_frame::title_border_w = 10;
00049 const int dialog_frame::title_border_h = 5;
00050
00051
00052
00053 bool in_dialog()
00054 {
00055 return is_in_dialog || gui2::is_in_dialog();
00056 }
00057
00058 dialog_manager::dialog_manager() : cursor::setter(cursor::NORMAL), reset_to(is_in_dialog)
00059 {
00060 is_in_dialog = true;
00061 }
00062
00063 dialog_manager::~dialog_manager()
00064 {
00065 is_in_dialog = reset_to;
00066 int mousex, mousey;
00067 SDL_GetMouseState(&mousex, &mousey);
00068 SDL_Event pb_event;
00069 pb_event.type = SDL_MOUSEMOTION;
00070 pb_event.motion.state = 0;
00071 pb_event.motion.x = mousex;
00072 pb_event.motion.y = mousey;
00073 pb_event.motion.xrel = 0;
00074 pb_event.motion.yrel = 0;
00075 SDL_PushEvent(&pb_event);
00076 }
00077
00078 dialog_frame::dialog_frame(CVideo &video, const std::string& title,
00079 const style& style, bool auto_restore,
00080 std::vector<button*>* buttons, button* help_button) :
00081 title_(title),
00082 video_(video),
00083 dialog_style_(style),
00084 buttons_(buttons),
00085 help_button_(help_button),
00086 restorer_(NULL),
00087 auto_restore_(auto_restore),
00088 dim_(),
00089 top_(image::get_image("dialogs/" + dialog_style_.panel + "-border-top.png")),
00090 bot_(image::get_image("dialogs/" + dialog_style_.panel + "-border-bottom.png")),
00091 left_(image::get_image("dialogs/" + dialog_style_.panel + "-border-left.png")),
00092 right_(image::get_image("dialogs/" + dialog_style_.panel + "-border-right.png")),
00093 top_left_(image::get_image("dialogs/" + dialog_style_.panel + "-border-topleft.png")),
00094 bot_left_(image::get_image("dialogs/" + dialog_style_.panel + "-border-botleft.png")),
00095 top_right_(image::get_image("dialogs/" + dialog_style_.panel + "-border-topright.png")),
00096 bot_right_(image::get_image("dialogs/" + dialog_style_.panel + "-border-botright.png")),
00097 bg_(image::get_image("dialogs/" + dialog_style_.panel + "-background.png")),
00098 have_border_(top_ != NULL && bot_ != NULL && left_ != NULL && right_ != NULL)
00099 {
00100 }
00101
00102 dialog_frame::~dialog_frame()
00103 {
00104 delete restorer_;
00105 }
00106
00107 dialog_frame::dimension_measurements::dimension_measurements() :
00108 interior(empty_rect), exterior(empty_rect), title(empty_rect), button_row(empty_rect)
00109 {}
00110
00111 dialog_frame::dimension_measurements dialog_frame::layout(SDL_Rect const& rect) {
00112 return layout(rect.x, rect.y, rect.w, rect.h);
00113 }
00114
00115 int dialog_frame::top_padding() const {
00116 int padding = 0;
00117 if(have_border_) {
00118 padding += top_->h;
00119 }
00120 if(!title_.empty()) {
00121 padding += font::get_max_height(font::SIZE_LARGE) + 2*dialog_frame::title_border_h;
00122 }
00123 return padding;
00124 }
00125
00126 int dialog_frame::bottom_padding() const {
00127 int padding = 0;
00128 if(buttons_ != NULL) {
00129 for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
00130 padding = std::max<int>((**b).height() + ButtonVPadding, padding);
00131 }
00132 }
00133 if(have_border_) {
00134 padding += bot_->h;
00135 }
00136 return padding;
00137 }
00138
00139 dialog_frame::dimension_measurements dialog_frame::layout(int x, int y, int w, int h) {
00140 dim_ = dimension_measurements();
00141 if(!title_.empty()) {
00142 dim_.title = draw_title(NULL);
00143 dim_.title.w += title_border_w;
00144 }
00145 if(buttons_ != NULL) {
00146 for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
00147 dim_.button_row.w += (**b).width() + ButtonHPadding;
00148 dim_.button_row.h = std::max<int>((**b).height() + ButtonVPadding,dim_.button_row.h);
00149 }
00150
00151 dim_.button_row.x = -dim_.button_row.w;
00152 dim_.button_row.y = y + h;
00153
00154 dim_.button_row.w += ButtonHPadding;
00155 }
00156
00157 size_t buttons_width = dim_.button_row.w;
00158
00159 if(help_button_ != NULL) {
00160 buttons_width += help_button_->width() + ButtonHPadding*2;
00161 dim_.button_row.y = y + h;
00162 }
00163
00164 y -= dim_.title.h;
00165 w = std::max<int>(w,std::max<int>(int(dim_.title.w),int(buttons_width)));
00166 h += dim_.title.h + dim_.button_row.h;
00167 dim_.button_row.x += x + w;
00168
00169 SDL_Rect bounds = screen_area();
00170 if(have_border_) {
00171 bounds.x += left_->w;
00172 bounds.y += top_->h;
00173 bounds.w -= left_->w;
00174 bounds.h -= top_->h;
00175 }
00176 if(x < bounds.x) {
00177 w += x;
00178 x = bounds.x;
00179 }
00180 if(y < bounds.y) {
00181 h += y;
00182 y = bounds.y;
00183 }
00184 if(x > bounds.w) {
00185 w = 0;
00186 } else if(x + w > bounds.w) {
00187 w = bounds.w - x;
00188 }
00189 if(y > bounds.h) {
00190 h = 0;
00191 } else if(y + h > bounds.h) {
00192 h = bounds.h - y;
00193 }
00194 dim_.interior.x = x;
00195 dim_.interior.y = y;
00196 dim_.interior.w = w;
00197 dim_.interior.h = h;
00198 if(have_border_) {
00199 dim_.exterior.x = dim_.interior.x - left_->w;
00200 dim_.exterior.y = dim_.interior.y - top_->h;
00201 dim_.exterior.w = dim_.interior.w + left_->w + right_->w;
00202 dim_.exterior.h = dim_.interior.h + top_->h + bot_->h;
00203 } else {
00204 dim_.exterior = dim_.interior;
00205 }
00206 dim_.title.x = dim_.interior.x + title_border_w;
00207 dim_.title.y = dim_.interior.y + title_border_h;
00208 return dim_;
00209 }
00210
00211 void dialog_frame::draw_border()
00212 {
00213 if(have_border_ == false) {
00214 return;
00215 }
00216
00217 surface top_image(scale_surface(top_, dim_.interior.w, top_->h));
00218
00219 if(top_image != NULL) {
00220 video_.blit_surface(dim_.interior.x, dim_.exterior.y, top_image);
00221 }
00222
00223 surface bot_image(scale_surface(bot_, dim_.interior.w, bot_->h));
00224
00225 if(bot_image != NULL) {
00226 video_.blit_surface(dim_.interior.x, dim_.interior.y + dim_.interior.h, bot_image);
00227 }
00228
00229 surface left_image(scale_surface(left_, left_->w, dim_.interior.h));
00230
00231 if(left_image != NULL) {
00232 video_.blit_surface(dim_.exterior.x, dim_.interior.y, left_image);
00233 }
00234
00235 surface right_image(scale_surface(right_, right_->w, dim_.interior.h));
00236
00237 if(right_image != NULL) {
00238 video_.blit_surface(dim_.interior.x + dim_.interior.w, dim_.interior.y, right_image);
00239 }
00240
00241 update_rect(dim_.exterior);
00242
00243 if(top_left_ == NULL || bot_left_ == NULL || top_right_ == NULL || bot_right_ == NULL) {
00244 return;
00245 }
00246
00247 video_.blit_surface(dim_.interior.x - left_->w, dim_.interior.y - top_->h, top_left_);
00248 video_.blit_surface(dim_.interior.x - left_->w, dim_.interior.y + dim_.interior.h + bot_->h - bot_left_->h, bot_left_);
00249 video_.blit_surface(dim_.interior.x + dim_.interior.w + right_->w - top_right_->w, dim_.interior.y - top_->h, top_right_);
00250 video_.blit_surface(dim_.interior.x + dim_.interior.w + right_->w - bot_right_->w, dim_.interior.y + dim_.interior.h + bot_->h - bot_right_->h, bot_right_);
00251 }
00252
00253 void dialog_frame::clear_background()
00254 {
00255 delete restorer_;
00256 restorer_ = NULL;
00257 }
00258
00259 void dialog_frame::draw_background()
00260 {
00261 if(auto_restore_) {
00262 clear_background();
00263 restorer_ = new surface_restorer(&video_, dim_.exterior);
00264 }
00265
00266 if (dialog_style_.blur_radius) {
00267 surface surf = ::get_surface_portion(video_.getSurface(), dim_.exterior);
00268 surf = blur_surface(surf, dialog_style_.blur_radius, false);
00269 sdl_blit(surf, NULL, video_.getSurface(), &dim_.exterior);
00270 }
00271
00272 if(bg_ == NULL) {
00273 ERR_DP << "could not find dialog background '" << dialog_style_.panel << "'\n";
00274 return;
00275 }
00276 for(int i = 0; i < dim_.interior.w; i += bg_->w) {
00277 for(int j = 0; j < dim_.interior.h; j += bg_->h) {
00278 SDL_Rect src = {0,0,0,0};
00279 src.w = std::min(dim_.interior.w - i, bg_->w);
00280 src.h = std::min(dim_.interior.h - j, bg_->h);
00281 SDL_Rect dst = src;
00282 dst.x = dim_.interior.x + i;
00283 dst.y = dim_.interior.y + j;
00284 sdl_blit(bg_, &src, video_.getSurface(), &dst);
00285 }
00286 }
00287 }
00288
00289 SDL_Rect dialog_frame::draw_title(CVideo* video)
00290 {
00291 SDL_Rect rect = {0, 0, 10000, 10000};
00292 rect = screen_area();
00293 return font::draw_text(video, rect, font::SIZE_LARGE, font::TITLE_COLOR,
00294 title_, dim_.title.x, dim_.title.y, false, TTF_STYLE_BOLD);
00295 }
00296
00297 void dialog_frame::draw()
00298 {
00299
00300 draw_background();
00301
00302
00303 draw_border();
00304
00305
00306 if (!title_.empty()) {
00307 draw_title(&video_);
00308 }
00309
00310
00311 SDL_Rect buttons_area = dim_.button_row;
00312 if(buttons_ != NULL) {
00313 #ifdef OK_BUTTON_ON_RIGHT
00314 std::reverse(buttons_->begin(),buttons_->end());
00315 #endif
00316 for(std::vector<button*>::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) {
00317 (**b).set_location(buttons_area.x, buttons_area.y);
00318 buttons_area.x += (**b).width() + ButtonHPadding;
00319 }
00320 }
00321
00322 if(help_button_ != NULL) {
00323 help_button_->set_location(dim_.interior.x+ButtonHPadding, buttons_area.y);
00324 }
00325 }
00326
00327 }
00328
00329 namespace {
00330
00331 struct help_handler : public hotkey::command_executor
00332 {
00333 help_handler(display& disp, const std::string& topic) : disp_(disp), topic_(topic)
00334 {}
00335
00336 private:
00337 void show_help()
00338 {
00339 if(topic_.empty() == false) {
00340 help::show_help(disp_,topic_);
00341 }
00342 }
00343
00344 bool can_execute_command(hotkey::HOTKEY_COMMAND cmd, int ) const
00345 {
00346 return (topic_.empty() == false && cmd == hotkey::HOTKEY_HELP) || cmd == hotkey::HOTKEY_SCREENSHOT;
00347 }
00348
00349 display& disp_;
00350 std::string topic_;
00351 };
00352
00353 }
00354
00355 namespace gui
00356 {
00357
00358 int show_dialog(display& screen, surface image,
00359 const std::string& caption, const std::string& message,
00360 DIALOG_TYPE type,
00361 const std::vector<std::string>* menu_items,
00362 const std::vector<preview_pane*>* preview_panes,
00363 const std::string& text_widget_label,
00364 std::string* text_widget_text,
00365 const int text_widget_max_chars,
00366 std::vector<check_item>* options,
00367 int xloc,
00368 int yloc,
00369 const dialog_frame::style* dialog_style,
00370 std::vector<dialog_button_info>* action_buttons,
00371 const menu::sorter* sorter,
00372 menu::style* menu_style)
00373 {
00374 std::string title;
00375 if (image.null()) title = caption;
00376 const dialog::style& style = (dialog_style)? *dialog_style : dialog::default_style;
00377 CVideo &disp = screen.video();
00378
00379 gui::dialog d(screen, title, message, type, style);
00380
00381
00382 if(!image.null()) {
00383 d.set_image(image, caption);
00384 }
00385 if(menu_items) {
00386 d.set_menu( new gui::menu(disp,*menu_items,type == MESSAGE,-1,dialog::max_menu_width,sorter,menu_style,false));
00387 }
00388 if(preview_panes) {
00389 for(unsigned int i=0; i < preview_panes->size(); ++i) {
00390 d.add_pane((*preview_panes)[i]);
00391 }
00392 }
00393 if(text_widget_text) {
00394 d.set_textbox(text_widget_label,*text_widget_text, text_widget_max_chars);
00395 }
00396 if(options) {
00397 for(unsigned int i=0; i < options->size(); ++i) {
00398 check_item& item = (*options)[i];
00399 d.add_option(item.label, item.checked);
00400 }
00401 }
00402 if(action_buttons) {
00403 for(unsigned int i=0; i < action_buttons->size(); ++i) {
00404 d.add_button((*action_buttons)[i]);
00405 }
00406 }
00407
00408 d.show(xloc, yloc);
00409
00410
00411 if(options) {
00412 for(unsigned int i=0; i < options->size(); ++i)
00413 {
00414 (*options)[i].checked = d.option_checked(i);
00415 }
00416 }
00417 if(text_widget_text) {
00418 *text_widget_text = d.textbox_text();
00419 }
00420 return d.result();
00421 }
00422
00423 }
00424