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