show_dialog.cpp

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

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs