00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "gui/menu.hpp"
00018
00019 #include <math.h>
00020 #include <stdexcept>
00021
00022 #include "control/joystickkeyboardcontroller.hpp"
00023 #include "gui/menu_item.hpp"
00024 #include "gui/menu_manager.hpp"
00025 #include "gui/mousecursor.hpp"
00026 #include "supertux/globals.hpp"
00027 #include "supertux/screen_manager.hpp"
00028 #include "supertux/resources.hpp"
00029 #include "supertux/timer.hpp"
00030 #include "util/gettext.hpp"
00031 #include "video/drawing_context.hpp"
00032 #include "video/font.hpp"
00033
00034 static const float MENU_REPEAT_INITIAL = 0.4f;
00035 static const float MENU_REPEAT_RATE = 0.1f;
00036
00037 Menu::Menu() :
00038 hit_item(),
00039 pos(),
00040 menuaction(),
00041 delete_character(),
00042 mn_input_char(),
00043 menu_repeat_time(),
00044 close(false),
00045 items(),
00046 effect_progress(),
00047 effect_start_time(),
00048 arrange_left(),
00049 active_item(),
00050 checkbox(),
00051 checkbox_checked(),
00052 back(),
00053 arrow_left(),
00054 arrow_right()
00055 {
00056 MenuManager::all_menus.push_back(this);
00057
00058 hit_item = -1;
00059 menuaction = MENU_ACTION_NONE;
00060 delete_character = 0;
00061 mn_input_char = '\0';
00062
00063 pos.x = SCREEN_WIDTH/2;
00064 pos.y = SCREEN_HEIGHT/2;
00065 arrange_left = 0;
00066 active_item = -1;
00067
00068 effect_progress = 0.0f;
00069 effect_start_time = 0.0f;
00070
00071 checkbox = Surface::create("images/engine/menu/checkbox-unchecked.png");
00072 checkbox_checked = Surface::create("images/engine/menu/checkbox-checked.png");
00073 back = Surface::create("images/engine/menu/arrow-back.png");
00074 arrow_left = Surface::create("images/engine/menu/arrow-left.png");
00075 arrow_right = Surface::create("images/engine/menu/arrow-right.png");
00076 }
00077
00078 Menu::~Menu()
00079 {
00080 MenuManager::all_menus.remove(this);
00081
00082 for(std::vector<MenuItem*>::iterator i = items.begin();
00083 i != items.end(); ++i)
00084 {
00085 delete *i;
00086 }
00087
00088 if (MenuManager::current_ == this)
00089 MenuManager::current_ = NULL;
00090
00091 if (MenuManager::previous == this)
00092 MenuManager::previous = NULL;
00093 }
00094
00095 void
00096 Menu::set_pos(float x, float y, float rw, float rh)
00097 {
00098 pos.x = x + get_width() * rw;
00099 pos.y = y + get_height() * rh;
00100 }
00101
00102
00103 void
00104 Menu::additem(MenuItem* item)
00105 {
00106 items.push_back(item);
00107
00108
00109
00110
00111
00112 if (active_item == -1
00113 && item->kind != MN_HL
00114 && item->kind != MN_LABEL
00115 && item->kind != MN_INACTIVE) {
00116 active_item = items.size() - 1;
00117 }
00118 }
00119
00120 MenuItem*
00121 Menu::add_hl()
00122 {
00123 MenuItem* item = new MenuItem(MN_HL);
00124 additem(item);
00125 return item;
00126 }
00127
00128 MenuItem*
00129 Menu::add_label(const std::string& text)
00130 {
00131 MenuItem* item = new MenuItem(MN_LABEL);
00132 item->text = text;
00133 additem(item);
00134 return item;
00135 }
00136
00137 MenuItem*
00138 Menu::add_controlfield(int id, const std::string& text,
00139 const std::string& mapping)
00140 {
00141 MenuItem* item = new MenuItem(MN_CONTROLFIELD, id);
00142 item->change_text(text);
00143 item->change_input(mapping);
00144 additem(item);
00145 return item;
00146 }
00147
00148 MenuItem*
00149 Menu::add_entry(int id, const std::string& text)
00150 {
00151 MenuItem* item = new MenuItem(MN_ACTION, id);
00152 item->text = text;
00153 additem(item);
00154 return item;
00155 }
00156
00157 MenuItem*
00158 Menu::add_inactive(int id, const std::string& text)
00159 {
00160 MenuItem* item = new MenuItem(MN_INACTIVE, id);
00161 item->text = text;
00162 additem(item);
00163 return item;
00164 }
00165
00166 MenuItem*
00167 Menu::add_toggle(int id, const std::string& text, bool toogled)
00168 {
00169 MenuItem* item = new MenuItem(MN_TOGGLE, id);
00170 item->text = text;
00171 item->toggled = toogled;
00172 additem(item);
00173 return item;
00174 }
00175
00176 MenuItem*
00177 Menu::add_string_select(int id, const std::string& text)
00178 {
00179 MenuItem* item = new MenuItem(MN_STRINGSELECT, id);
00180 item->text = text;
00181 additem(item);
00182 return item;
00183 }
00184
00185 MenuItem*
00186 Menu::add_back(const std::string& text)
00187 {
00188 MenuItem* item = new MenuItem(MN_BACK);
00189 item->text = text;
00190 additem(item);
00191 return item;
00192 }
00193
00194 MenuItem*
00195 Menu::add_submenu(const std::string& text, Menu* submenu, int id)
00196 {
00197 MenuItem* item = new MenuItem(MN_GOTO, id);
00198 item->text = text;
00199 item->target_menu = submenu;
00200 additem(item);
00201 return item;
00202 }
00203
00204 void
00205 Menu::clear()
00206 {
00207 for(std::vector<MenuItem*>::iterator i = items.begin();
00208 i != items.end(); ++i) {
00209 delete *i;
00210 }
00211 items.clear();
00212 active_item = -1;
00213 }
00214
00215
00216 void
00217 Menu::update()
00218 {
00219 int menu_height = (int) get_height();
00220 if (menu_height > SCREEN_HEIGHT)
00221 {
00222 int scroll_offset = (menu_height - SCREEN_HEIGHT) / 2 + 32;
00223 pos.y = SCREEN_HEIGHT/2 - scroll_offset * ((float(active_item) / (items.size()-1)) - 0.5f) * 2.0f;
00224 }
00225
00226 effect_progress = (real_time - effect_start_time) * 6.0f;
00227
00228 if(effect_progress >= 1.0f) {
00229 effect_progress = 1.0f;
00230
00231 if (close) {
00232 MenuManager::current_ = 0;
00233 close = false;
00234 }
00235 }
00236 else if (effect_progress <= 0.0f) {
00237 effect_progress = 0.0f;
00238 }
00239
00240 Controller *controller = g_jk_controller->get_main_controller();
00242 if(controller->pressed(Controller::UP)) {
00243 menuaction = MENU_ACTION_UP;
00244 menu_repeat_time = real_time + MENU_REPEAT_INITIAL;
00245 }
00246 if(controller->hold(Controller::UP) &&
00247 menu_repeat_time != 0 && real_time > menu_repeat_time) {
00248 menuaction = MENU_ACTION_UP;
00249 menu_repeat_time = real_time + MENU_REPEAT_RATE;
00250 }
00251
00252 if(controller->pressed(Controller::DOWN)) {
00253 menuaction = MENU_ACTION_DOWN;
00254 menu_repeat_time = real_time + MENU_REPEAT_INITIAL;
00255 }
00256 if(controller->hold(Controller::DOWN) &&
00257 menu_repeat_time != 0 && real_time > menu_repeat_time) {
00258 menuaction = MENU_ACTION_DOWN;
00259 menu_repeat_time = real_time + MENU_REPEAT_RATE;
00260 }
00261
00262 if(controller->pressed(Controller::LEFT)) {
00263 menuaction = MENU_ACTION_LEFT;
00264 menu_repeat_time = real_time + MENU_REPEAT_INITIAL;
00265 }
00266 if(controller->hold(Controller::LEFT) &&
00267 menu_repeat_time != 0 && real_time > menu_repeat_time) {
00268 menuaction = MENU_ACTION_LEFT;
00269 menu_repeat_time = real_time + MENU_REPEAT_RATE;
00270 }
00271
00272 if(controller->pressed(Controller::RIGHT)) {
00273 menuaction = MENU_ACTION_RIGHT;
00274 menu_repeat_time = real_time + MENU_REPEAT_INITIAL;
00275 }
00276 if(controller->hold(Controller::RIGHT) &&
00277 menu_repeat_time != 0 && real_time > menu_repeat_time) {
00278 menuaction = MENU_ACTION_RIGHT;
00279 menu_repeat_time = real_time + MENU_REPEAT_RATE;
00280 }
00281
00282 if(controller->pressed(Controller::ACTION)
00283 || controller->pressed(Controller::MENU_SELECT)) {
00284 menuaction = MENU_ACTION_HIT;
00285 }
00286 if(controller->pressed(Controller::PAUSE_MENU)) {
00287 menuaction = MENU_ACTION_BACK;
00288 }
00289
00290 hit_item = -1;
00291 if(items.size() == 0)
00292 return;
00293
00294 int last_active_item = active_item;
00295 switch(menuaction) {
00296 case MENU_ACTION_UP:
00297 do {
00298 if (active_item > 0)
00299 --active_item;
00300 else
00301 active_item = int(items.size())-1;
00302 } while ((items[active_item]->kind == MN_HL
00303 || items[active_item]->kind == MN_LABEL
00304 || items[active_item]->kind == MN_INACTIVE)
00305 && (active_item != last_active_item));
00306
00307 break;
00308
00309 case MENU_ACTION_DOWN:
00310 do {
00311 if(active_item < int(items.size())-1 )
00312 ++active_item;
00313 else
00314 active_item = 0;
00315 } while ((items[active_item]->kind == MN_HL
00316 || items[active_item]->kind == MN_LABEL
00317 || items[active_item]->kind == MN_INACTIVE)
00318 && (active_item != last_active_item));
00319
00320 break;
00321
00322 case MENU_ACTION_LEFT:
00323 if(items[active_item]->kind == MN_STRINGSELECT) {
00324 if(items[active_item]->selected > 0)
00325 items[active_item]->selected--;
00326 else
00327 items[active_item]->selected = items[active_item]->list.size()-1;
00328
00329 menu_action(items[active_item]);
00330 }
00331 break;
00332
00333 case MENU_ACTION_RIGHT:
00334 if(items[active_item]->kind == MN_STRINGSELECT) {
00335 if(items[active_item]->selected+1 < items[active_item]->list.size())
00336 items[active_item]->selected++;
00337 else
00338 items[active_item]->selected = 0;
00339
00340 menu_action(items[active_item]);
00341 }
00342 break;
00343
00344 case MENU_ACTION_HIT: {
00345 hit_item = active_item;
00346 switch (items[active_item]->kind) {
00347 case MN_GOTO:
00348 assert(items[active_item]->target_menu != 0);
00349 MenuManager::push_current(items[active_item]->target_menu);
00350 break;
00351
00352 case MN_TOGGLE:
00353 items[active_item]->toggled = !items[active_item]->toggled;
00354 menu_action(items[active_item]);
00355 break;
00356
00357 case MN_CONTROLFIELD:
00358 menu_action(items[active_item]);
00359 break;
00360
00361 case MN_ACTION:
00362 menu_action(items[active_item]);
00363 break;
00364
00365 case MN_STRINGSELECT:
00366 if(items[active_item]->selected+1 < items[active_item]->list.size())
00367 items[active_item]->selected++;
00368 else
00369 items[active_item]->selected = 0;
00370
00371 menu_action(items[active_item]);
00372 break;
00373
00374 case MN_TEXTFIELD:
00375 case MN_NUMFIELD:
00376 menuaction = MENU_ACTION_DOWN;
00377 update();
00378 break;
00379
00380 case MN_BACK:
00381 MenuManager::pop_current();
00382 break;
00383 default:
00384 break;
00385 }
00386 break;
00387 }
00388
00389 case MENU_ACTION_REMOVE:
00390 if(items[active_item]->kind == MN_TEXTFIELD
00391 || items[active_item]->kind == MN_NUMFIELD)
00392 {
00393 if(!items[active_item]->input.empty())
00394 {
00395 int i = items[active_item]->input.size();
00396
00397 while(delete_character > 0)
00398 {
00399 items[active_item]->input.resize(i-1);
00400 delete_character--;
00401 }
00402 }
00403 }
00404 break;
00405
00406 case MENU_ACTION_INPUT:
00407 if(items[active_item]->kind == MN_TEXTFIELD
00408 || (items[active_item]->kind == MN_NUMFIELD
00409 && mn_input_char >= '0' && mn_input_char <= '9'))
00410 {
00411 items[active_item]->input.push_back(mn_input_char);
00412 }
00413 break;
00414
00415 case MENU_ACTION_BACK:
00416 MenuManager::pop_current();
00417 break;
00418
00419 case MENU_ACTION_NONE:
00420 break;
00421 }
00422 menuaction = MENU_ACTION_NONE;
00423
00424 assert(active_item < int(items.size()));
00425 }
00426
00427 int
00428 Menu::check()
00429 {
00430 if (hit_item != -1)
00431 {
00432 int id = items[hit_item]->id;
00433
00434 hit_item = -1;
00435 return id;
00436 }
00437 else
00438 return -1;
00439 }
00440
00441 void
00442 Menu::menu_action(MenuItem* )
00443 {}
00444
00445 void
00446 Menu::draw_item(DrawingContext& context, int index)
00447 {
00448 float menu_height = get_height();
00449 float menu_width = get_width();
00450
00451 MenuItem& pitem = *(items[index]);
00452
00453 Color text_color = default_color;
00454 float x_pos = pos.x;
00455 float y_pos = pos.y + 24*index - menu_height/2 + 12;
00456 int text_width = int(Resources::normal_font->get_text_width(pitem.text));
00457 int input_width = int(Resources::normal_font->get_text_width(pitem.input) + 10);
00458 int list_width = 0;
00459
00460 float left = pos.x - menu_width/2 + 16;
00461 float right = pos.x + menu_width/2 - 16;
00462
00463 if(pitem.list.size() > 0) {
00464 list_width = (int) Resources::normal_font->get_text_width(pitem.list[pitem.selected]);
00465 }
00466
00467 if (arrange_left)
00468 x_pos += 24 - menu_width/2 + (text_width + input_width + list_width)/2;
00469
00470 if(index == active_item)
00471 {
00472 text_color = active_color;
00473 }
00474
00475 if(active_item == index)
00476 {
00477 float blink = (sinf(real_time * M_PI * 1.0f)/2.0f + 0.5f) * 0.5f + 0.25f;
00478 context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2 + 10 - 2, y_pos - 12 - 2),
00479 Vector(pos.x + menu_width/2 - 10 + 2, y_pos + 12 + 2)),
00480 Color(1.0f, 1.0f, 1.0f, blink),
00481 14.0f,
00482 LAYER_GUI-10);
00483 context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2 + 10, y_pos - 12),
00484 Vector(pos.x + menu_width/2 - 10, y_pos + 12)),
00485 Color(1.0f, 1.0f, 1.0f, 0.5f),
00486 12.0f,
00487 LAYER_GUI-10);
00488 }
00489
00490 switch (pitem.kind)
00491 {
00492 case MN_INACTIVE:
00493 {
00494 context.draw_text(Resources::normal_font, pitem.text,
00495 Vector(pos.x, y_pos - int(Resources::normal_font->get_height()/2)),
00496 ALIGN_CENTER, LAYER_GUI, inactive_color);
00497 break;
00498 }
00499
00500 case MN_HL:
00501 {
00502
00503 float x = pos.x - menu_width/2;
00504 float y = y_pos - 12;
00505
00506 context.draw_filled_rect(Vector(x, y + 6),
00507 Vector(menu_width, 4),
00508 Color(0.6f, 0.7f, 1.0f, 1.0f), LAYER_GUI);
00509 context.draw_filled_rect(Vector(x, y + 6),
00510 Vector(menu_width, 2),
00511 Color(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI);
00512 break;
00513 }
00514 case MN_LABEL:
00515 {
00516 context.draw_text(Resources::big_font, pitem.text,
00517 Vector(pos.x, y_pos - int(Resources::big_font->get_height()/2)),
00518 ALIGN_CENTER, LAYER_GUI, label_color);
00519 break;
00520 }
00521 case MN_TEXTFIELD:
00522 case MN_NUMFIELD:
00523 case MN_CONTROLFIELD:
00524 {
00525 if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD)
00526 {
00527 if(active_item == index)
00528 context.draw_text(Resources::normal_font,
00529 pitem.get_input_with_symbol(true),
00530 Vector(right, y_pos - int(Resources::normal_font->get_height()/2)),
00531 ALIGN_RIGHT, LAYER_GUI, field_color);
00532 else
00533 context.draw_text(Resources::normal_font,
00534 pitem.get_input_with_symbol(false),
00535 Vector(right, y_pos - int(Resources::normal_font->get_height()/2)),
00536 ALIGN_RIGHT, LAYER_GUI, field_color);
00537 }
00538 else
00539 context.draw_text(Resources::normal_font, pitem.input,
00540 Vector(right, y_pos - int(Resources::normal_font->get_height()/2)),
00541 ALIGN_RIGHT, LAYER_GUI, field_color);
00542
00543 context.draw_text(Resources::normal_font, pitem.text,
00544 Vector(left, y_pos - int(Resources::normal_font->get_height()/2)),
00545 ALIGN_LEFT, LAYER_GUI, text_color);
00546 break;
00547 }
00548 case MN_STRINGSELECT:
00549 {
00550 float roff = arrow_left->get_width();
00551
00552 context.draw_text(Resources::normal_font, pitem.text,
00553 Vector(left, y_pos - int(Resources::normal_font->get_height()/2)),
00554 ALIGN_LEFT, LAYER_GUI, text_color);
00555
00556
00557 context.draw_surface(arrow_left,
00558 Vector(right - list_width - roff - roff, y_pos - 8),
00559 LAYER_GUI);
00560 context.draw_surface(arrow_right,
00561 Vector(right - roff, y_pos - 8),
00562 LAYER_GUI);
00563 context.draw_text(Resources::normal_font, pitem.list[pitem.selected],
00564 Vector(right - roff, y_pos - int(Resources::normal_font->get_height()/2)),
00565 ALIGN_RIGHT, LAYER_GUI, text_color);
00566 break;
00567 }
00568 case MN_BACK:
00569 {
00570 context.draw_text(Resources::Resources::normal_font, pitem.text,
00571 Vector(pos.x, y_pos - int(Resources::normal_font->get_height()/2)),
00572 ALIGN_CENTER, LAYER_GUI, text_color);
00573 context.draw_surface(back,
00574 Vector(x_pos + text_width/2 + 16, y_pos - 8),
00575 LAYER_GUI);
00576 break;
00577 }
00578
00579 case MN_TOGGLE:
00580 {
00581 context.draw_text(Resources::normal_font, pitem.text,
00582 Vector(pos.x - menu_width/2 + 16, y_pos - (Resources::normal_font->get_height()/2)),
00583 ALIGN_LEFT, LAYER_GUI, text_color);
00584
00585 if(pitem.toggled)
00586 context.draw_surface(checkbox_checked,
00587 Vector(x_pos + (menu_width/2-16) - checkbox->get_width(), y_pos - 8),
00588 LAYER_GUI + 1);
00589 else
00590 context.draw_surface(checkbox,
00591 Vector(x_pos + (menu_width/2-16) - checkbox->get_width(), y_pos - 8),
00592 LAYER_GUI + 1);
00593 break;
00594 }
00595 case MN_ACTION:
00596 context.draw_text(Resources::normal_font, pitem.text,
00597 Vector(pos.x, y_pos - int(Resources::normal_font->get_height()/2)),
00598 ALIGN_CENTER, LAYER_GUI, text_color);
00599 break;
00600
00601 case MN_GOTO:
00602 context.draw_text(Resources::normal_font, pitem.text,
00603 Vector(pos.x, y_pos - int(Resources::normal_font->get_height()/2)),
00604 ALIGN_CENTER, LAYER_GUI, text_color);
00605 break;
00606 }
00607 }
00608
00609 float
00610 Menu::get_width() const
00611 {
00612
00613
00614 float menu_width = 0;
00615 for(unsigned int i = 0; i < items.size(); ++i)
00616 {
00617 FontPtr font = Resources::Resources::normal_font;
00618 if(items[i]->kind == MN_LABEL)
00619 font = Resources::big_font;
00620
00621 float w = font->get_text_width(items[i]->text) +
00622 Resources::big_font->get_text_width(items[i]->input) + 16;
00623 if(items[i]->kind == MN_TOGGLE)
00624 w += 32;
00625 if (items[i]->kind == MN_STRINGSELECT)
00626 w += font->get_text_width(items[i]->list[items[i]->selected]) + 32;
00627
00628
00629 if(w > menu_width)
00630 menu_width = w;
00631 }
00632
00633 return menu_width + 24;
00634 }
00635
00636 float
00637 Menu::get_height() const
00638 {
00639 return items.size() * 24;
00640 }
00641
00642
00643 void
00644 Menu::draw(DrawingContext& context)
00645 {
00646 if(MouseCursor::current()) {
00647 MouseCursor::current()->draw(context);
00648 }
00649
00650 float menu_width = get_width();
00651 float menu_height = get_height();
00652
00653 if (effect_progress != 1.0f)
00654 {
00655 if (close)
00656 {
00657 menu_width = (MenuManager::current_->get_width() * (1.0f - effect_progress));
00658 menu_height = (MenuManager::current_->get_height() * (1.0f - effect_progress));
00659 }
00660 else if (MenuManager::previous)
00661 {
00662 menu_width = (menu_width * effect_progress) + (MenuManager::previous->get_width() * (1.0f - effect_progress));
00663 menu_height = (menu_height * effect_progress) + (MenuManager::previous->get_height() * (1.0f - effect_progress));
00664
00665 }
00666 else
00667 {
00668 menu_width *= effect_progress;
00669 menu_height *= effect_progress;
00670 }
00671 }
00672
00673
00674 context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2-4, pos.y - menu_height/2 - 10-4),
00675 Vector(pos.x + menu_width/2+4, pos.y - menu_height/2 + 10 + menu_height+4)),
00676 Color(0.2f, 0.3f, 0.4f, 0.8f),
00677 20.0f,
00678 LAYER_GUI-10);
00679
00680 context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2, pos.y - menu_height/2 - 10),
00681 Vector(pos.x + menu_width/2, pos.y - menu_height/2 + 10 + menu_height)),
00682 Color(0.6f, 0.7f, 0.8f, 0.5f),
00683 16.0f,
00684 LAYER_GUI-10);
00685
00686 if (!items[active_item]->help.empty())
00687 {
00688 int text_width = (int) Resources::normal_font->get_text_width(items[active_item]->help);
00689 int text_height = (int) Resources::normal_font->get_text_height(items[active_item]->help);
00690
00691 Rectf text_rect(pos.x - text_width/2 - 8,
00692 SCREEN_HEIGHT - 48 - text_height/2 - 4,
00693 pos.x + text_width/2 + 8,
00694 SCREEN_HEIGHT - 48 + text_height/2 + 4);
00695
00696 context.draw_filled_rect(Rectf(text_rect.p1 - Vector(4,4),
00697 text_rect.p2 + Vector(4,4)),
00698 Color(0.2f, 0.3f, 0.4f, 0.8f),
00699 16.0f,
00700 LAYER_GUI-10);
00701
00702 context.draw_filled_rect(text_rect,
00703 Color(0.6f, 0.7f, 0.8f, 0.5f),
00704 16.0f,
00705 LAYER_GUI-10);
00706
00707 context.draw_text(Resources::normal_font, items[active_item]->help,
00708 Vector(pos.x, SCREEN_HEIGHT - 48 - text_height/2),
00709 ALIGN_CENTER, LAYER_GUI);
00710 }
00711
00712 if (effect_progress == 1.0f)
00713 for(unsigned int i = 0; i < items.size(); ++i)
00714 {
00715 draw_item(context, i);
00716 }
00717 }
00718
00719 MenuItem&
00720 Menu::get_item_by_id(int id)
00721 {
00722 for(std::vector<MenuItem*>::iterator i = items.begin();
00723 i != items.end(); ++i) {
00724 MenuItem& item = **i;
00725
00726 if(item.id == id)
00727 return item;
00728 }
00729
00730 throw std::runtime_error("MenuItem not found");
00731 }
00732
00733 const MenuItem&
00734 Menu::get_item_by_id(int id) const
00735 {
00736 for(std::vector<MenuItem*>::const_iterator i = items.begin();
00737 i != items.end(); ++i) {
00738 const MenuItem& item = **i;
00739
00740 if(item.id == id)
00741 return item;
00742 }
00743
00744 throw std::runtime_error("MenuItem not found");
00745 }
00746
00747 int Menu::get_active_item_id()
00748 {
00749 return items[active_item]->id;
00750 }
00751
00752 bool
00753 Menu::is_toggled(int id) const
00754 {
00755 return get_item_by_id(id).toggled;
00756 }
00757
00758 void
00759 Menu::set_toggled(int id, bool toggled)
00760 {
00761 get_item_by_id(id).toggled = toggled;
00762 }
00763
00764 Menu*
00765 Menu::get_parent() const
00766 {
00767 if (MenuManager::last_menus.empty())
00768 return 0;
00769 else
00770 return MenuManager::last_menus.back();
00771 }
00772
00773
00774 void
00775 Menu::event(const SDL_Event& event)
00776 {
00777 if(effect_progress != 1.0f)
00778 return;
00779
00780 switch(event.type) {
00781 case SDL_MOUSEBUTTONDOWN:
00782 {
00783 int x = int(event.motion.x * float(SCREEN_WIDTH)/g_screen->w);
00784 int y = int(event.motion.y * float(SCREEN_HEIGHT)/g_screen->h);
00785
00786 if(x > pos.x - get_width()/2 &&
00787 x < pos.x + get_width()/2 &&
00788 y > pos.y - get_height()/2 &&
00789 y < pos.y + get_height()/2)
00790 {
00791 menuaction = MENU_ACTION_HIT;
00792 }
00793 }
00794 break;
00795
00796 case SDL_MOUSEMOTION:
00797 {
00798 float x = event.motion.x * SCREEN_WIDTH/g_screen->w;
00799 float y = event.motion.y * SCREEN_HEIGHT/g_screen->h;
00800
00801 if(x > pos.x - get_width()/2 &&
00802 x < pos.x + get_width()/2 &&
00803 y > pos.y - get_height()/2 &&
00804 y < pos.y + get_height()/2)
00805 {
00806 int new_active_item
00807 = static_cast<int> ((y - (pos.y - get_height()/2)) / 24);
00808
00809
00810 if ((items[new_active_item]->kind != MN_HL)
00811 && (items[new_active_item]->kind != MN_LABEL)
00812 && (items[new_active_item]->kind != MN_INACTIVE))
00813 active_item = new_active_item;
00814
00815 if(MouseCursor::current())
00816 MouseCursor::current()->set_state(MC_LINK);
00817 }
00818 else
00819 {
00820 if(MouseCursor::current())
00821 MouseCursor::current()->set_state(MC_NORMAL);
00822 }
00823 }
00824 break;
00825
00826 default:
00827 break;
00828 }
00829 }
00830
00831 void
00832 Menu::set_active_item(int id)
00833 {
00834 for(size_t i = 0; i < items.size(); ++i) {
00835 MenuItem* item = items[i];
00836 if(item->id == id) {
00837 active_item = i;
00838 break;
00839 }
00840 }
00841 }
00842
00843