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 "construct_dialog.hpp"
00021 #include "config.hpp"
00022 #include "cursor.hpp"
00023 #include "display.hpp"
00024 #include "events.hpp"
00025 #include "gettext.hpp"
00026 #include "image.hpp"
00027 #include "key.hpp"
00028 #include "sound.hpp"
00029 #include "log.hpp"
00030 #include "marked-up_text.hpp"
00031 #include "thread.hpp"
00032 #include "language.hpp"
00033 #include "sdl_utils.hpp"
00034 #include "tooltips.hpp"
00035 #include "util.hpp"
00036 #include "video.hpp"
00037 #include "widgets/button.hpp"
00038 #include "widgets/menu.hpp"
00039 #include "widgets/progressbar.hpp"
00040 #include "widgets/textbox.hpp"
00041
00042 #include "SDL_ttf.h"
00043
00044 #include <iostream>
00045 #include <numeric>
00046
00047 #define ERR_DP LOG_STREAM(err, display)
00048 #define LOG_DP LOG_STREAM(info, display)
00049 #define DBG_DP LOG_STREAM(debug, display)
00050 #define ERR_G LOG_STREAM(err, general)
00051
00052 namespace gui {
00053
00054
00055
00056 const dialog::style& dialog::default_style = dialog_frame::default_style;
00057 const dialog::style& dialog::message_style = dialog_frame::message_style;
00058 const dialog::style dialog::hotkeys_style("menu2", 0);
00059 const int dialog::message_font_size = font::SIZE_PLUS;
00060 const int dialog::caption_font_size = font::SIZE_LARGE;
00061 const size_t dialog::left_padding = font::relative_size(10);
00062 const size_t dialog::right_padding = font::relative_size(10);
00063 const size_t dialog::image_h_pad = font::relative_size( 10);
00064 const size_t dialog::top_padding = font::relative_size(10);
00065 const size_t dialog::bottom_padding = font::relative_size(10);
00066
00067
00068 #ifdef USE_TINY_GUI
00069 const int dialog::max_menu_width = 300;
00070 #else
00071 const int dialog::max_menu_width = -1;
00072 #endif
00073
00074 }
00075
00076 namespace {
00077
00078 std::vector<std::string> empty_string_vector;
00079
00080 }
00081
00082 namespace gui {
00083
00084 dialog_textbox::~dialog_textbox()
00085 {
00086 delete label_;
00087 }
00088
00089 dialog::dimension_measurements::dimension_measurements() :
00090 x(-1),
00091 y(-1),
00092 interior(empty_rect),
00093 message(empty_rect),
00094 textbox(empty_rect),
00095 menu_width(0),
00096 panes(),
00097 label_x(-1),
00098 label_y(-1),
00099 menu_x(-1),
00100 menu_y(-1),
00101 menu_height(-1),
00102 image_x(-1),
00103 image_y(-1),
00104 caption_x(-1),
00105 caption_y(-1),
00106 buttons()
00107 {
00108
00109
00110
00111 }
00112
00113 dialog::dialog(display &disp, const std::string& title, const std::string& message,
00114 const DIALOG_TYPE type, const style& dialog_style) :
00115 disp_(disp),
00116 image_(NULL),
00117 title_(title),
00118 style_(dialog_style),
00119 title_widget_(NULL),
00120 message_(NULL),
00121 type_(type),
00122 menu_(NULL),
00123 preview_panes_(),
00124 button_pool_(),
00125 standard_buttons_(),
00126 extra_buttons_(),
00127 frame_buttons_(),
00128 topic_(),
00129 help_button_(NULL),
00130 text_widget_(NULL),
00131 frame_(NULL),
00132 dim_(),
00133 result_(CONTINUE_DIALOG)
00134 {
00135 CVideo& screen = disp_.video();
00136
00137 switch(type)
00138 {
00139 case MESSAGE:
00140 default:
00141 break;
00142 case OK_ONLY:
00143 add_button(new standard_dialog_button(screen,_("OK"),0,true), BUTTON_STANDARD);
00144 break;
00145 case YES_NO:
00146 add_button(new standard_dialog_button(screen,_("Yes"),0,false), BUTTON_STANDARD);
00147 add_button(new standard_dialog_button(screen,_("No"),1,true), BUTTON_STANDARD);
00148 break;
00149 case OK_CANCEL:
00150 add_button(new standard_dialog_button(screen,_("OK"),0,false), BUTTON_STANDARD);
00151 add_button(new standard_dialog_button(screen,_("Cancel"),1,true), BUTTON_STANDARD);
00152 break;
00153 case CANCEL_ONLY:
00154 add_button(new standard_dialog_button(screen,_("Cancel"),0,true), BUTTON_STANDARD);
00155 break;
00156 case CLOSE_ONLY:
00157 add_button(new standard_dialog_button(screen,_("Close"),0,true), BUTTON_STANDARD);
00158 break;
00159 }
00160
00161
00162 try {
00163 std::string msg = font::word_wrap_text(message, message_font_size, screen.getx() / 2, screen.gety() / 2);
00164 message_ = new label(screen, msg, message_font_size, font::NORMAL_COLOUR, false);
00165 } catch(utils::invalid_utf8_exception&) {
00166 ERR_DP << "Problem handling utf8 in message '" << message << "'\n";
00167 throw;
00168 }
00169
00170 }
00171
00172 dialog::~dialog()
00173 {
00174 if(menu_ != empty_menu)
00175 {
00176 delete menu_;
00177 }
00178 delete title_widget_;
00179 delete message_;
00180 delete text_widget_;
00181 delete image_;
00182 delete frame_;
00183
00184 button_pool_iterator b;
00185 for (b = button_pool_.begin(); b != button_pool_.end(); ++b) {
00186 delete b->first;
00187 }
00188
00189
00190
00191
00192 }
00193
00194 bool dialog::option_checked(unsigned int option_index)
00195 {
00196 unsigned int i = 0;
00197 button_pool_iterator b;
00198 for (b = button_pool_.begin(); b != button_pool_.end(); ++b) {
00199 if(b->first->is_option()) {
00200 if(option_index == i++) {
00201 return b->first->checked();
00202 }
00203 }
00204 }
00205 return false;
00206 }
00207
00208 void dialog::add_button(dialog_button *const btn, BUTTON_LOCATION loc)
00209 {
00210 std::pair<dialog_button *, BUTTON_LOCATION> new_pair(btn,loc);
00211 button_pool_.push_back(new_pair);
00212 switch(loc)
00213 {
00214 case BUTTON_HELP:
00215 delete help_button_;
00216 help_button_ = btn;
00217 break;
00218 case BUTTON_EXTRA:
00219 case BUTTON_EXTRA_LEFT:
00220 case BUTTON_CHECKBOX:
00221 case BUTTON_CHECKBOX_LEFT:
00222 extra_buttons_.push_back(btn);
00223 break;
00224 case BUTTON_STANDARD:
00225 standard_buttons_.push_back(btn);
00226 break;
00227 default:
00228 break;
00229 }
00230 btn->set_parent(this);
00231 }
00232
00233 void dialog::add_button(dialog_button_info btn_info, BUTTON_LOCATION loc)
00234 {
00235 dialog_button *btn = new dialog_button(disp_.video(), btn_info.label, button::TYPE_PRESS, CONTINUE_DIALOG, btn_info.handler);
00236 add_button(btn, loc);
00237 }
00238
00239 void dialog::add_option(const std::string& label, bool checked, BUTTON_LOCATION loc)
00240 {
00241 gui::dialog_button *btn = new dialog_button(disp_.video(), label, button::TYPE_CHECK);
00242 btn->set_check(checked);
00243 add_button(btn, loc);
00244 }
00245
00246 void dialog::set_textbox(const std::string& text_widget_label,
00247 const std::string& text_widget_text,
00248 const int text_widget_max_chars, const unsigned int text_box_width)
00249 {
00250 label *label_ptr = new label(disp_.video(), text_widget_label, message_font_size, font::NORMAL_COLOUR, false);
00251 const bool editable_textbox = std::find(text_widget_text.begin(),text_widget_text.end(),'\n') == text_widget_text.end();
00252 text_widget_ = new dialog_textbox(label_ptr, disp_.video(), text_box_width, text_widget_text, editable_textbox, text_widget_max_chars);
00253 text_widget_->set_wrap(!editable_textbox);
00254 }
00255
00256 void dialog::set_menu(const std::vector<std::string> &menu_items, menu::sorter* sorter)
00257 {
00258 set_menu(new gui::menu(disp_.video(), menu_items, (type_==MESSAGE),
00259 -1, dialog::max_menu_width, sorter, &menu::default_style, false));
00260 }
00261
00262 void dialog::set_menu_items(const std::vector<std::string> &menu_items)
00263 {
00264 if(menu_ == empty_menu) {
00265 set_menu(menu_items);
00266 } else {
00267 menu_->set_items(menu_items);
00268
00269 for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
00270 (**i).set_selection(menu_->selection());
00271 }
00272 }
00273 }
00274
00275 menu& dialog::get_menu()
00276 {
00277 if(menu_ == NULL)
00278 {
00279 if(empty_menu == NULL) {
00280 empty_menu = new gui::menu(disp_.video(),empty_string_vector,false,-1,-1,NULL,&menu::simple_style);
00281 empty_menu->leave();
00282 }
00283 menu_ = empty_menu;
00284 }
00285 return *menu_;
00286 }
00287
00288 int dialog::show(int xloc, int yloc)
00289 {
00290 layout(xloc, yloc);
00291 return show();
00292 }
00293
00294 int dialog::show()
00295 {
00296 if (disp_.video().faked()) return CLOSE_DIALOG;
00297
00298 if(disp_.video().update_locked()) {
00299 ERR_DP << "display locked ignoring dialog '" << title_ << "' '" << message_->get_text() << "'\n";
00300 return CLOSE_DIALOG;
00301 }
00302
00303 LOG_DP << "showing dialog '" << title_ << "' '" << message_->get_text() << "'\n";
00304 if(dim_.interior == empty_rect) { layout(); }
00305
00306
00307 const events::event_context dialog_events_context;
00308 const dialog_manager manager;
00309 const resize_lock prevent_resizing;
00310
00311
00312 draw_frame();
00313 update_widget_positions();
00314 draw_contents();
00315
00316
00317 dialog_process_info dp_info;
00318 do
00319 {
00320 events::pump();
00321 set_result(process(dp_info));
00322 if(!done()) {
00323 refresh();
00324 }
00325 action(dp_info);
00326 dp_info.cycle();
00327 } while(!done());
00328
00329 clear_background();
00330 return result();
00331 }
00332
00333 void dialog::draw_contents()
00334 {
00335 if(!preview_panes_.empty()) {
00336 for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
00337 preview_pane *pane = *i;
00338 if(!pane->handler_members().empty())
00339 {
00340 pane->draw();
00341 pane->needs_restore_ = false;
00342 }
00343 }
00344 }
00345 events::raise_draw_event();
00346
00347 disp_.flip();
00348 disp_.invalidate_all();
00349 }
00350
00351 dialog_frame& dialog::get_frame()
00352 {
00353 if(frame_ == NULL) {
00354 CVideo& screen = disp_.video();
00355 frame_buttons_.clear();
00356 for(button_iterator b = standard_buttons_.begin(); b != standard_buttons_.end(); ++b)
00357 {
00358 frame_buttons_.push_back(*b);
00359 }
00360 frame_ = new dialog_frame(screen, title_, style_, true, &frame_buttons_, help_button_);
00361 }
00362 return *frame_;
00363 }
00364
00365 void dialog::clear_background() {
00366 delete frame_;
00367 frame_ = NULL;
00368 }
00369
00370 void dialog::draw_frame()
00371 {
00372 get_frame().draw();
00373 }
00374
00375 void dialog::update_widget_positions()
00376 {
00377 if(!preview_panes_.empty()) {
00378 for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
00379 preview_pane *pane = *i;
00380 pane->join();
00381 pane->set_location(dim_.panes.find(pane)->second);
00382 }
00383 }
00384 if(text_widget_) {
00385 text_widget_->join();
00386 text_widget_->set_location(dim_.textbox);
00387 if(text_widget_->get_label()) {
00388 text_widget_->get_label()->set_location(dim_.label_x, dim_.label_y);
00389 }
00390 }
00391 if(get_menu().height() > 0) {
00392 menu_->join();
00393 menu_->set_numeric_keypress_selection(text_widget_ == NULL);
00394 menu_->set_width( dim_.menu_width );
00395 menu_->set_max_width( dim_.menu_width );
00396 if(dim_.menu_height >= 0) {
00397 menu_->set_max_height( dim_.menu_height );
00398 }
00399 menu_->set_location( dim_.menu_x, dim_.menu_y );
00400 }
00401 if(image_) {
00402 image_->join();
00403 image_->set_location(dim_.image_x, dim_.image_y);
00404 if(image_->caption()) {
00405 image_->caption()->set_location(dim_.caption_x, dim_.caption_y);
00406 }
00407 }
00408 button_iterator b;
00409 for(b = extra_buttons_.begin(); b != extra_buttons_.end(); ++b) {
00410 dialog_button *btn = *b;
00411 btn->join();
00412 std::pair<int,int> coords = dim_.buttons.find(btn)->second;
00413 btn->set_location(coords.first, coords.second);
00414 }
00415 for(b = standard_buttons_.begin(); b != standard_buttons_.end(); ++b) {
00416 dialog_button *btn = *b;
00417 btn->join();
00418 }
00419 if(help_button_) {
00420 help_button_->join();
00421 }
00422 message_->set_location(dim_.message);
00423 message_->join();
00424 }
00425
00426 void dialog::refresh()
00427 {
00428 disp_.flip();
00429 disp_.delay(10);
00430 }
00431
00432 dialog::dimension_measurements dialog::layout(int xloc, int yloc)
00433 {
00434 CVideo& screen = disp_.video();
00435 surface const scr = screen.getSurface();
00436
00437 dimension_measurements dim;
00438 dim.x = xloc;
00439 dim.y = yloc;
00440
00441 const bool use_textbox = (text_widget_ != NULL);
00442 int text_widget_width = 0;
00443 int text_widget_height = 0;
00444 if(use_textbox) {
00445 const SDL_Rect& area = font::text_area(text_widget_->text(),message_font_size);
00446 dim.textbox.w = minimum<size_t>(screen.getx()/2,maximum<size_t>(area.w,text_widget_->width()));
00447 dim.textbox.h = minimum<size_t>(screen.gety()/2,maximum<size_t>(area.h,text_widget_->height()));
00448 text_widget_width = dim.textbox.w;
00449 text_widget_width += (text_widget_->get_label() == NULL) ? 0 : text_widget_->get_label()->width();
00450 text_widget_height = dim.textbox.h + message_font_size;
00451 }
00452
00453 const bool use_menu = (get_menu().height() > 0);
00454 if(!message_->get_text().empty()) {
00455 dim.message.w = message_->width();
00456 dim.message.h = message_->height();
00457 }
00458 unsigned int caption_width = 0;
00459 unsigned int caption_height = 0;
00460 if (image_ != NULL && image_->caption() != NULL) {
00461 caption_width = image_->caption()->width();
00462 caption_height = image_->caption()->height();
00463 }
00464
00465 int check_button_height = 0;
00466 int left_check_button_height = 0;
00467 const int button_height_padding = 5;
00468
00469 for(button_pool_const_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
00470 dialog_button const *const btn = b->first;
00471 switch(b->second)
00472 {
00473 case BUTTON_EXTRA:
00474 case BUTTON_CHECKBOX:
00475 check_button_height += btn->height() + button_height_padding;
00476 break;
00477 case BUTTON_EXTRA_LEFT:
00478 case BUTTON_CHECKBOX_LEFT:
00479 left_check_button_height += btn->height() + button_height_padding;
00480 break;
00481 case BUTTON_STANDARD:
00482 default:
00483 break;
00484 }
00485 }
00486 check_button_height = maximum<int>(check_button_height, left_check_button_height);
00487
00488 size_t above_preview_pane_height = 0, above_left_preview_pane_width = 0, above_right_preview_pane_width = 0;
00489 size_t preview_pane_height = 0, left_preview_pane_width = 0, right_preview_pane_width = 0;
00490 if(!preview_panes_.empty()) {
00491 for(pp_const_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
00492 preview_pane const *const pane = *i;
00493 const SDL_Rect& rect = pane->location();
00494 if(pane->show_above() == false) {
00495 preview_pane_height = maximum<size_t>(rect.h,preview_pane_height);
00496 if(pane->left_side()) {
00497 left_preview_pane_width += rect.w;
00498 } else {
00499 right_preview_pane_width += rect.w;
00500 }
00501 } else {
00502 above_preview_pane_height = maximum<size_t>(rect.h,above_preview_pane_height);
00503 if(pane->left_side()) {
00504 above_left_preview_pane_width += rect.w;
00505 } else {
00506 above_right_preview_pane_width += rect.w;
00507 }
00508 }
00509 }
00510 }
00511
00512 const int menu_hpadding = font::relative_size((dim.message.h > 0 && use_menu) ? 10 : 0);
00513 const size_t image_h_padding = (image_ == NULL)? 0 : image_h_pad;
00514 const size_t padding_width = left_padding + right_padding + image_h_padding;
00515 const size_t padding_height = top_padding + bottom_padding + menu_hpadding;
00516 const size_t image_width = (image_ == NULL) ? 0 : image_->width();
00517 const size_t image_height = (image_ == NULL) ? 0 : image_->height();
00518 const size_t total_text_height = dim.message.h + caption_height;
00519
00520 size_t text_width = dim.message.w;
00521 if(caption_width > text_width)
00522 text_width = caption_width;
00523
00524
00525 dim.menu_width = menu_->width();
00526 if(dim.menu_width + image_width + padding_width + left_preview_pane_width + right_preview_pane_width > static_cast<size_t>(scr->w))
00527 dim.menu_width = scr->w - image_width - padding_width - left_preview_pane_width - right_preview_pane_width;
00528 if(dim.menu_width > text_width)
00529 text_width = dim.menu_width;
00530
00531
00532 size_t total_width = image_width + text_width + padding_width;
00533
00534 if(text_widget_width+left_padding+right_padding > total_width)
00535 total_width = text_widget_width+left_padding+right_padding;
00536
00537
00538 if(use_menu && preview_panes_.empty() &&
00539 total_width > dim.menu_width + image_width + padding_width) {
00540 dim.menu_width = total_width - image_width - padding_width;
00541 }
00542
00543 const size_t text_and_image_height = image_height > total_text_height ? image_height : total_text_height;
00544
00545 const int total_height = text_and_image_height + padding_height + menu_->height() +
00546 text_widget_height + check_button_height;
00547
00548 dim.interior.w = maximum<int>(total_width,above_left_preview_pane_width + above_right_preview_pane_width);
00549 dim.interior.h = maximum<int>(total_height,static_cast<int>(preview_pane_height));
00550 dim.interior.x = maximum<int>(0,dim.x >= 0 ? dim.x : scr->w/2 - (dim.interior.w + left_preview_pane_width + right_preview_pane_width)/2);
00551 dim.interior.y = maximum<int>(0,dim.y >= 0 ? dim.y : scr->h/2 - (dim.interior.h + above_preview_pane_height)/2);
00552
00553 DBG_DP << "above_preview_pane_height: " << above_preview_pane_height << "; "
00554 << "dim.interior.y: " << scr->h/2 << " - " << (dim.interior.h + above_preview_pane_height)/2 << " = "
00555 << dim.interior.y << "; " << "dim.interior.h: " << dim.interior.h << "\n";
00556
00557 if(dim.x <= -1 || dim.y <= -1) {
00558 dim.x = dim.interior.x + left_preview_pane_width;
00559 dim.y = dim.interior.y + above_preview_pane_height;
00560 }
00561
00562 if(dim.x + dim.interior.w > scr->w) {
00563 dim.x = scr->w - dim.interior.w;
00564 if(dim.x < dim.interior.x) {
00565 dim.interior.x = dim.x;
00566 }
00567 }
00568
00569 const int frame_top_pad = get_frame().top_padding();
00570 const int frame_bottom_pad = get_frame().bottom_padding();
00571 if(dim.y + dim.interior.h + frame_bottom_pad > scr->h) {
00572 dim.y = maximum<int>(frame_top_pad, scr->h - dim.interior.h - frame_bottom_pad);
00573 if(dim.y < dim.interior.y) {
00574 dim.interior.y = dim.y;
00575 }
00576 }
00577
00578 dim.interior.w += left_preview_pane_width + right_preview_pane_width;
00579 dim.interior.h += above_preview_pane_height;
00580
00581 const int max_height = scr->h - dim.interior.y - frame_bottom_pad;
00582 if(dim.interior.h > max_height) {
00583
00584 const int menu_height = menu_->height();
00585 if(menu_height > 0) {
00586 dim.menu_height = maximum<int>(1, max_height - dim.interior.h + menu_height);
00587 dim.interior.h -= menu_height - dim.menu_height;
00588 }
00589 }
00590
00591
00592 if(!preview_panes_.empty()) {
00593
00594 int left_preview_pane = dim.interior.x;
00595 int right_preview_pane = dim.interior.x + total_width + left_preview_pane_width;
00596 int above_left_preview_pane = dim.interior.x + dim.interior.w/2;
00597 int above_right_preview_pane = above_left_preview_pane;
00598
00599 for(pp_const_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
00600 preview_pane const *const pane = *i;
00601 SDL_Rect area = pane->location();
00602
00603 if(pane->show_above() == false) {
00604 area.y = dim.y;
00605 area.h = dim.interior.h;
00606 if(pane->left_side()) {
00607 area.x = left_preview_pane;
00608 left_preview_pane += area.w;
00609 } else {
00610 area.x = right_preview_pane;
00611 right_preview_pane += area.w;
00612 }
00613 } else {
00614 area.y = dim.interior.y;
00615 area.h = above_preview_pane_height;
00616 if(pane->left_side()) {
00617 area.x = above_left_preview_pane - area.w;
00618 above_left_preview_pane -= area.w;
00619 } else {
00620 area.x = above_right_preview_pane;
00621 above_right_preview_pane += area.w;
00622 }
00623 }
00624 dim.panes[*i] = area;
00625 }
00626 }
00627
00628 const int text_widget_y = dim.y+top_padding+text_and_image_height-6+menu_hpadding;
00629
00630 if(use_textbox) {
00631 dim.textbox.x = dim.x + left_padding + text_widget_width - dim.textbox.w;
00632 dim.textbox.y = text_widget_y + (text_widget_height - dim.textbox.h)/2;
00633 dim.label_x = dim.x+left_padding;
00634 dim.label_y = dim.textbox.y;
00635 }
00636
00637 dim.menu_x = dim.x+image_width+left_padding+image_h_padding;
00638 dim.menu_y = dim.y+top_padding+text_and_image_height+menu_hpadding+ (use_textbox ? text_widget_->location().h + top_padding : 0);
00639
00640 dim.message.x = dim.x + left_padding;
00641 dim.message.y = dim.y + top_padding + caption_height;
00642
00643 if(image_ != NULL) {
00644 const int x = dim.x + left_padding;
00645 const int y = dim.y + top_padding;
00646 dim.message.x += image_width + image_h_padding;
00647 dim.image_x = x;
00648 dim.image_y = y;
00649 dim.caption_x = dim.x + image_width + left_padding + image_h_padding;
00650 dim.caption_y = dim.y + top_padding;
00651 }
00652
00653
00654
00655 if(extra_buttons_.empty() == false) {
00656 int options_y = text_widget_y + text_widget_height + menu_->height() + button_height_padding + menu_hpadding;
00657 int options_left_y = options_y;
00658 for(button_pool_const_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
00659 dialog_button const *const btn = b->first;
00660 std::pair<int,int> coords;
00661 switch(b->second)
00662 {
00663 case BUTTON_EXTRA:
00664 case BUTTON_CHECKBOX:
00665 coords.first = dim.x + total_width - btn->width() - ButtonHPadding;
00666 coords.second = options_y;
00667 dim.buttons[b->first] = coords;
00668 options_y += btn->height() + button_height_padding;
00669 break;
00670 case BUTTON_EXTRA_LEFT:
00671 case BUTTON_CHECKBOX_LEFT:
00672 coords.first = dim.x + ButtonHPadding;
00673 coords.second = options_left_y;
00674 dim.buttons[b->first] = coords;
00675 options_left_y += btn->height() + button_height_padding;
00676 break;
00677 case BUTTON_STANDARD:
00678 default:
00679 break;
00680 }
00681 }
00682 }
00683 set_layout(dim);
00684 return dim;
00685 }
00686
00687 void dialog::set_layout(dimension_measurements &new_dim) {
00688 get_frame().layout(new_dim.interior);
00689 dim_ = new_dim;
00690 }
00691
00692
00693 int dialog::process(dialog_process_info &info)
00694 {
00695
00696 int mousex, mousey;
00697 int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
00698
00699 info.new_right_button = (mouse_flags&SDL_BUTTON_RMASK) != 0;
00700 info.new_left_button = (mouse_flags&SDL_BUTTON_LMASK) != 0;
00701 info.new_key_down = info.key[SDLK_SPACE] || info.key[SDLK_RETURN] ||
00702 info.key[SDLK_ESCAPE] || info.key[SDLK_KP_ENTER];
00703 info.double_clicked = menu_->double_clicked();
00704 get_menu();
00705 const bool use_menu = (menu_ != empty_menu);
00706 const bool use_text_input = (text_widget_!=NULL);
00707 const bool has_input = (use_menu||use_text_input);
00708
00709 if(((!info.key_down && info.key[SDLK_RETURN]) || info.key[SDLK_KP_ENTER] || info.double_clicked) &&
00710 (type_ == YES_NO || type_ == OK_CANCEL || type_ == OK_ONLY || type_ == CLOSE_ONLY)) {
00711
00712 return (use_menu ? menu_->selection() : 0);
00713 }
00714
00715
00716 if(!info.key_down && info.key[SDLK_ESCAPE] && !(type_ == OK_ONLY && has_input)) {
00717 return (CLOSE_DIALOG);
00718 }
00719
00720
00721 if((menu_->selection() != info.selection) || info.first_time) {
00722 info.selection = menu_->selection();
00723 int selection = info.selection;
00724 if(selection < 0) {
00725 selection = 0;
00726 }
00727 if(!preview_panes_.empty()) {
00728 for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
00729 (**i).set_selection(selection);
00730 if(info.first_time) {
00731 (**i).set_dirty();
00732 }
00733 }
00734 }
00735 }
00736
00737 info.first_time = false;
00738
00739 if(use_menu) {
00740
00741 const int selection = menu_->process();
00742 if(selection != -1)
00743 {
00744 return (selection);
00745 }
00746 }
00747
00748 events::raise_process_event();
00749 events::raise_draw_event();
00750
00751
00752 if (info.new_left_button && !info.left_button) {
00753 if (standard_buttons_.empty() && !point_in_rect(mousex,mousey, menu_->location())) {
00754 if (use_menu)
00755 sound::play_UI_sound(game_config::sounds::button_press);
00756 return CLOSE_DIALOG;
00757 }
00758 }
00759
00760
00761
00762
00763 if (info.new_right_button && !info.right_button) {
00764 if( standard_buttons_.empty()
00765 || (!point_in_rect(mousex,mousey,get_frame().get_layout().exterior)
00766 && type_ != YES_NO && !(type_ == OK_ONLY && has_input))) {
00767 sound::play_UI_sound(game_config::sounds::button_press);
00768 return CLOSE_DIALOG;
00769 }
00770 }
00771
00772
00773
00774 if (info.new_key_down && !info.key_down) {
00775 if (standard_buttons_.size() < 2 && !has_input)
00776 return CLOSE_DIALOG;
00777 }
00778
00779
00780 for(button_pool_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
00781 if(b->first->pressed()) {
00782 return b->first->action(info);
00783 }
00784 }
00785
00786 return CONTINUE_DIALOG;
00787 }
00788
00789 int dialog_button::action(dialog_process_info &info) {
00790 if(handler_ != NULL) {
00791 menu &menu_ref = parent_->get_menu();
00792 dialog_button_action::RESULT res = handler_->button_pressed(menu_ref.selection());
00793
00794 if(res == DELETE_ITEM || res == CLOSE_DIALOG) {
00795 return res;
00796 }
00797
00798
00799
00800
00801
00802 info.clear_buttons();
00803 return CONTINUE_DIALOG;
00804 }
00805 return simple_result_;
00806 }
00807
00808 void dialog::action(dialog_process_info& info)
00809 {
00810
00811 if(result() == DELETE_ITEM) {
00812 menu &menu_ref = get_menu();
00813 const int selection = menu_ref.selection();
00814 if(selection >= 0) {
00815 menu_ref.erase_item(selection);
00816 }
00817 if(menu_ref.nitems() == 0) {
00818 set_result(CLOSE_DIALOG);
00819 } else {
00820 set_result(CONTINUE_DIALOG);
00821 info.first_time = true;
00822 }
00823 }
00824 }
00825
00826 int standard_dialog_button::action(dialog_process_info &) {
00827
00828
00829
00830
00831 if(dialog()->get_menu().height() <= 0) {
00832 return simple_result_;
00833 } else if((simple_result_ == 0 && is_last_) || !is_last_) {
00834 return (dialog()->get_menu().selection());
00835 }
00836 return CLOSE_DIALOG;
00837 }
00838
00839 void dialog::set_image(surface surf, const std::string &caption)
00840 {
00841 label *label_ptr = NULL;
00842 if(!caption.empty()) {
00843 label_ptr = new label(disp_.video(), caption, caption_font_size, font::NORMAL_COLOUR, false);
00844 }
00845 set_image( new dialog_image(label_ptr, disp_.video(), surf ));
00846 }
00847
00848 void dialog_image::draw_contents()
00849 {
00850 video().blit_surface(location().x, location().y, surf_);
00851 }
00852
00853 int message_dialog::show(msecs minimum_lifetime)
00854 {
00855 prevent_misclick_until_ = SDL_GetTicks() + minimum_lifetime;
00856 return dialog::show();
00857 }
00858
00859 void message_dialog::action(gui::dialog_process_info &dp_info)
00860 {
00861 dialog::action(dp_info);
00862 if(done() && SDL_GetTicks() < prevent_misclick_until_ && result() != gui::ESCAPE_DIALOG) {
00863
00864 set_result(gui::CONTINUE_DIALOG);
00865 }
00866 }
00867
00868 message_dialog::~message_dialog()
00869 {
00870 }
00871
00872 }