show_dialog.cpp

Go to the documentation of this file.
00001 /* $Id: show_dialog.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
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 //static initialization
00039 const int ButtonHPadding = 10;
00040 const int ButtonVPadding = 10;
00041 
00042 //note: style names are directly related to the panel image file names
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     //draw background
00300     draw_background();
00301 
00302     //draw frame border
00303     draw_border();
00304 
00305     //draw title
00306     if (!title_.empty()) {
00307         draw_title(&video_);
00308     }
00309 
00310     //draw buttons
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 } //end namespace gui
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 /*index*/) 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     //add the components
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     //enter the dialog loop
00408     d.show(xloc, yloc);
00409 
00410     //send back results
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:10 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs