X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=lib%2Fgui%2Fmenu.cpp;h=83c16649ca0bf28c523274681867f9b618fe8e7c;hb=f54737bb28bec638b9f436d023b9f21fec2caadd;hp=57adf1002652b7e84283bb93b0404f44b3a670ac;hpb=c5cbd36c2e01d8c807c8c931ca44fb7c1b48ad18;p=supertux.git diff --git a/lib/gui/menu.cpp b/lib/gui/menu.cpp index 57adf1002..83c16649c 100644 --- a/lib/gui/menu.cpp +++ b/lib/gui/menu.cpp @@ -18,6 +18,8 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef WIN32 +#include + #include #include #endif @@ -29,14 +31,13 @@ #include #include -#include "../app/globals.h" -#include "../gui/menu.h" -#include "../video/screen.h" -#include "../video/drawing_context.h" -#include "../app/setup.h" -#include "../special/timer.h" -#include "../app/gettext.h" -#include "../math/vector.h" +#include "app/globals.h" +#include "menu.h" +#include "video/screen.h" +#include "video/drawing_context.h" +#include "app/setup.h" +#include "app/gettext.h" +#include "math/vector.h" using namespace SuperTux; @@ -50,12 +51,17 @@ Surface* SuperTux::arrow_right; std::vector Menu::last_menus; Menu* Menu::current_ = 0; +Font* Menu::default_font; +Font* Menu::active_font; +Font* Menu::deactive_font; +Font* Menu::label_font; +Font* Menu::field_font; /* just displays a Yes/No text that can be used to confirm stuff */ bool SuperTux::confirm_dialog(Surface *background, std::string text) { //Surface* cap_screen = Surface::CaptureScreen(); - + Menu* dialog = new Menu; dialog->additem(MN_DEACTIVE, text,0,0); dialog->additem(MN_HL,"",0,0); @@ -68,44 +74,44 @@ bool SuperTux::confirm_dialog(Surface *background, std::string text) DrawingContext context; while(true) - { - SDL_Event event; - - while (SDL_PollEvent(&event)) { - dialog->event(event); - } + SDL_Event event; - if(background == NULL) - context.draw_gradient(Color(200,240,220), Color(200,200,220), LAYER_BACKGROUND0); - else - context.draw_surface(background, Vector(0,0), LAYER_BACKGROUND0); + while (SDL_PollEvent(&event)) + { + dialog->event(event); + } - dialog->draw(context); - dialog->action(); + if(background == NULL) + context.draw_gradient(Color(200,240,220), Color(200,200,220), LAYER_BACKGROUND0); + else + context.draw_surface(background, Vector(0,0), LAYER_BACKGROUND0); - switch (dialog->check()) - { - case true: - //delete cap_screen; - Menu::set_current(0); - delete dialog; - return true; - break; - case false: - //delete cap_screen; - Menu::set_current(0); - delete dialog; - return false; - break; - default: - break; - } + dialog->draw(context); + dialog->action(); - mouse_cursor->draw(context); - context.do_drawing(); - SDL_Delay(25); - } + switch (dialog->check()) + { + case true: + //delete cap_screen; + Menu::set_current(0); + delete dialog; + return true; + break; + case false: + //delete cap_screen; + Menu::set_current(0); + delete dialog; + return false; + break; + default: + break; + } + + mouse_cursor->draw(context); + context.do_drawing(); + SDL_Delay(25); + } return false; } @@ -124,16 +130,16 @@ void Menu::pop_current() { if (!last_menus.empty()) - { - current_ = last_menus.back(); - current_->effect.start(500); + { + current_ = last_menus.back(); + current_->effect.start(500); - last_menus.pop_back(); - } + last_menus.pop_back(); + } else - { - current_ = 0; - } + { + current_ = 0; + } } void @@ -147,15 +153,23 @@ Menu::set_current(Menu* menu) current_ = menu; } +MenuItem::MenuItem(MenuItemKind _kind, int _id) + : kind(_kind) , id(_id) +{ +} + +MenuItem::MenuItem(MenuItemKind _kind, int _id, const std::string& _text) + : kind(_kind) , id(_id) , text(_text) +{ +} + /* Return a pointer to a new menu item */ MenuItem* -MenuItem::create(MenuItemKind kind_, const char *text_, int init_toggle_, Menu* target_menu_, int id, int* int_p_) +MenuItem::create(MenuItemKind kind_, const std::string& text_, int init_toggle_, Menu* target_menu_, int id_, int* int_p_) { - MenuItem *pnew_item = new MenuItem; + MenuItem *pnew_item = new MenuItem(kind_,id_); - pnew_item->kind = kind_; - pnew_item->text = (char*) malloc(sizeof(char) * (strlen(text_) + 1)); - strcpy(pnew_item->text, text_); + pnew_item->text = text_; if(kind_ == MN_TOGGLE) pnew_item->toggled = init_toggle_; @@ -163,20 +177,11 @@ MenuItem::create(MenuItemKind kind_, const char *text_, int init_toggle_, Menu* pnew_item->toggled = false; pnew_item->target_menu = target_menu_; - pnew_item->input = (char*) malloc(sizeof(char)); - pnew_item->input[0] = '\0'; - if(kind_ == MN_STRINGSELECT) - { - pnew_item->list = (string_list_type*) malloc(sizeof(string_list_type)); - string_list_init(pnew_item->list); - } - else - pnew_item->list = NULL; - - pnew_item->id = id; pnew_item->int_p = int_p_; + pnew_item->selected = 0; + pnew_item->input_flickering = false; pnew_item->input_flickering_timer.init(true); pnew_item->input_flickering_timer.start(FLICK_CURSOR_TIME); @@ -185,25 +190,15 @@ MenuItem::create(MenuItemKind kind_, const char *text_, int init_toggle_, Menu* } void -MenuItem::change_text(const char *text_) +MenuItem::change_text(const std::string& text_) { - if (text_) - { - free(text); - text = (char*) malloc(sizeof(char )*(strlen(text_)+1)); - strcpy(text, text_); - } + text = text_; } void -MenuItem::change_input(const char *text_) +MenuItem::change_input(const std::string& text_) { - if(text) - { - free(input); - input = (char*) malloc(sizeof(char )*(strlen(text_)+1)); - strcpy(input, text_); - } + input = text_; } std::string MenuItem::get_input_with_symbol(bool active_item) @@ -211,22 +206,22 @@ std::string MenuItem::get_input_with_symbol(bool active_item) if(!active_item) input_flickering = true; else - { - if(input_flickering_timer.get_left() < 0) { - if(input_flickering) - input_flickering = false; - else - input_flickering = true; - input_flickering_timer.start(FLICK_CURSOR_TIME); + if(input_flickering_timer.get_left() < 0) + { + if(input_flickering) + input_flickering = false; + else + input_flickering = true; + input_flickering_timer.start(FLICK_CURSOR_TIME); + } } - } char str[1024]; if(input_flickering) - sprintf(str,"%s ",input); + sprintf(str,"%s ",input.c_str()); else - sprintf(str,"%s_",input); + sprintf(str,"%s_",input.c_str()); std::string string = str; @@ -237,51 +232,51 @@ std::string MenuItem::get_input_with_symbol(bool active_item) void Menu::get_controlfield_key_into_input(MenuItem *item) { switch(*item->int_p) - { - case SDLK_UP: - item->change_input(_("Up cursor")); - break; - case SDLK_DOWN: - item->change_input(_("Down cursor")); - break; - case SDLK_LEFT: - item->change_input(_("Left cursor")); - break; - case SDLK_RIGHT: - item->change_input(_("Right cursor")); - break; - case SDLK_RETURN: - item->change_input(_("Return")); - break; - case SDLK_SPACE: - item->change_input(_("Space")); - break; - case SDLK_RSHIFT: - item->change_input(_("Right Shift")); - break; - case SDLK_LSHIFT: - item->change_input(_("Left Shift")); - break; - case SDLK_RCTRL: - item->change_input(_("Right Control")); - break; - case SDLK_LCTRL: - item->change_input(_("Left Control")); - break; - case SDLK_RALT: - item->change_input(_("Right Alt")); - break; - case SDLK_LALT: - item->change_input(_("Left Alt")); - break; - default: { - char tmp[64]; - snprintf(tmp, 64, "%d", *item->int_p); - item->change_input(tmp); + case SDLK_UP: + item->change_input(_("Up cursor")); + break; + case SDLK_DOWN: + item->change_input(_("Down cursor")); + break; + case SDLK_LEFT: + item->change_input(_("Left cursor")); + break; + case SDLK_RIGHT: + item->change_input(_("Right cursor")); + break; + case SDLK_RETURN: + item->change_input(_("Return")); + break; + case SDLK_SPACE: + item->change_input(_("Space")); + break; + case SDLK_RSHIFT: + item->change_input(_("Right Shift")); + break; + case SDLK_LSHIFT: + item->change_input(_("Left Shift")); + break; + case SDLK_RCTRL: + item->change_input(_("Right Control")); + break; + case SDLK_LCTRL: + item->change_input(_("Left Control")); + break; + case SDLK_RALT: + item->change_input(_("Right Alt")); + break; + case SDLK_LALT: + item->change_input(_("Left Alt")); + break; + default: + { + char tmp[64]; + snprintf(tmp, 64, "%d", *item->int_p); + item->change_input(tmp); + } + break; } - break; - } } /* Set ControlField for joystick button */ @@ -292,21 +287,10 @@ void Menu::get_controlfield_js_into_input(MenuItem *item) item->change_input(oss.str().c_str()); } -/* Free a menu and all its items */ Menu::~Menu() { - if(item.size() != 0) - { - for(unsigned int i = 0; i < item.size(); ++i) - { - free(item[i].text); - free(item[i].input); - string_list_free(item[i].list); - } - } } - Menu::Menu() { hit_item = -1; @@ -314,8 +298,8 @@ Menu::Menu() delete_character = 0; mn_input_char = '\0'; - pos_x = screen->w/2; - pos_y = screen->h/2; + pos_x = SCREEN_WIDTH/2; + pos_y = SCREEN_HEIGHT/2; arrange_left = 0; active_item = 0; effect.init(false); @@ -333,6 +317,15 @@ void Menu::additem(MenuItemKind kind_, const std::string& text_, int toggle_, Menu* menu_, int id, int* int_p) { additem(MenuItem::create(kind_, text_.c_str(), toggle_, menu_, id, int_p)); + + /* If a new menu is being built, the active item shouldn't be set to something + that isnt selectable. Keep setting the active item to the most recently + added item until a selectable entry is found. + */ + if (item[active_item].kind == MN_HL + || item[active_item].kind == MN_LABEL + || item[active_item].kind == MN_DEACTIVE) + active_item = item.size() - 1; } /* Add an item to a menu */ @@ -343,10 +336,18 @@ Menu::additem(MenuItem* pmenu_item) delete pmenu_item; } +/* Add an item to a menu */ +void +Menu::additem(const MenuItem& pmenu_item) +{ + item.push_back(pmenu_item); +} + void Menu::clear() { item.clear(); + active_item = 0; } /* Process actions done on the menu */ @@ -355,133 +356,118 @@ Menu::action() { hit_item = -1; if(item.size() != 0) - { - switch(menuaction) { - case MENU_ACTION_UP: - if (active_item > 0) - --active_item; - else - active_item = int(item.size())-1; - break; - - case MENU_ACTION_DOWN: - if(active_item < int(item.size())-1) - ++active_item; - else - active_item = 0; - break; - - case MENU_ACTION_LEFT: - if(item[active_item].kind == MN_STRINGSELECT - && item[active_item].list->num_items != 0) - { - if(item[active_item].list->active_item > 0) - --item[active_item].list->active_item; - else - item[active_item].list->active_item = item[active_item].list->num_items-1; - } - break; - - case MENU_ACTION_RIGHT: - if(item[active_item].kind == MN_STRINGSELECT - && item[active_item].list->num_items != 0) - { - if(item[active_item].list->active_item < item[active_item].list->num_items-1) - ++item[active_item].list->active_item; - else - item[active_item].list->active_item = 0; - } - break; - - case MENU_ACTION_HIT: - { - hit_item = active_item; - switch (item[active_item].kind) + int last_active_item = active_item; + switch(menuaction) { - case MN_GOTO: - if (item[active_item].target_menu != NULL) - Menu::push_current(item[active_item].target_menu); - else - puts("NULLL"); + case MENU_ACTION_UP: + do { + if (active_item > 0) + --active_item; + else + active_item = int(item.size())-1; + } while ((item[active_item].kind == MN_HL + || item[active_item].kind == MN_LABEL + || item[active_item].kind == MN_DEACTIVE) + && (active_item != last_active_item)); + break; - case MN_TOGGLE: - item[active_item].toggled = !item[active_item].toggled; - break; + case MENU_ACTION_DOWN: + do { + if(active_item < int(item.size())-1 ) + ++active_item; + else + active_item = 0; + } while ((item[active_item].kind == MN_HL + || item[active_item].kind == MN_LABEL + || item[active_item].kind == MN_DEACTIVE) + && (active_item != last_active_item)); - case MN_ACTION: - Menu::set_current(0); - item[active_item].toggled = true; - break; - case MN_TEXTFIELD: - case MN_NUMFIELD: - menuaction = MENU_ACTION_DOWN; - action(); break; - case MN_BACK: - Menu::pop_current(); - break; - default: + case MENU_ACTION_LEFT: + if(item[active_item].kind == MN_STRINGSELECT) { + if(item[active_item].selected > 0) + item[active_item].selected--; + else + item[active_item].selected = item[active_item].list.size()-1; + } break; - } - } - break; - case MENU_ACTION_REMOVE: - if(item[active_item].kind == MN_TEXTFIELD - || item[active_item].kind == MN_NUMFIELD) - { - if(item[active_item].input != NULL) - { - int i = strlen(item[active_item].input); + case MENU_ACTION_RIGHT: + if(item[active_item].kind == MN_STRINGSELECT) { + if(item[active_item].selected+1 < item[active_item].list.size()) + item[active_item].selected++; + else + item[active_item].selected = 0; + } + break; - while(delete_character > 0) /* remove charactes */ + case MENU_ACTION_HIT: { - item[active_item].input[i-1] = '\0'; - delete_character--; + hit_item = active_item; + switch (item[active_item].kind) + { + case MN_GOTO: + if (item[active_item].target_menu != NULL) + Menu::push_current(item[active_item].target_menu); + else + puts("NULLL"); + break; + + case MN_TOGGLE: + item[active_item].toggled = !item[active_item].toggled; + break; + + case MN_ACTION: + Menu::set_current(0); + item[active_item].toggled = true; + break; + case MN_TEXTFIELD: + case MN_NUMFIELD: + menuaction = MENU_ACTION_DOWN; + action(); + break; + + case MN_BACK: + Menu::pop_current(); + break; + default: + break; + } } - } - } - break; + break; - case MENU_ACTION_INPUT: - if(item[active_item].kind == MN_TEXTFIELD - || (item[active_item].kind == MN_NUMFIELD && mn_input_char >= '0' && mn_input_char <= '9')) - { - if(item[active_item].input != NULL) - { - int i = strlen(item[active_item].input); - item[active_item].input = (char*) realloc(item[active_item].input,sizeof(char)*(i + 2)); - item[active_item].input[i] = mn_input_char; - item[active_item].input[i+1] = '\0'; - } - else - { - item[active_item].input = (char*) malloc(2*sizeof(char)); - item[active_item].input[0] = mn_input_char; - item[active_item].input[1] = '\0'; - } - } + case MENU_ACTION_REMOVE: + if(item[active_item].kind == MN_TEXTFIELD + || item[active_item].kind == MN_NUMFIELD) + { + if(!item[active_item].input.empty()) + { + int i = item[active_item].input.size(); + + while(delete_character > 0) /* remove charactes */ + { + item[active_item].input.resize(i-1); + delete_character--; + } + } + } + break; - case MENU_ACTION_NONE: - break; - } - } + case MENU_ACTION_INPUT: + if(item[active_item].kind == MN_TEXTFIELD + || (item[active_item].kind == MN_NUMFIELD && mn_input_char >= '0' && mn_input_char <= '9')) + { + item[active_item].input.push_back(mn_input_char); + } - MenuItem& new_item = item[active_item]; - if(new_item.kind == MN_DEACTIVE - || new_item.kind == MN_LABEL - || new_item.kind == MN_HL) - { - // Skip the horzontal line item - if (menuaction != MENU_ACTION_UP && menuaction != MENU_ACTION_DOWN) - menuaction = MENU_ACTION_DOWN; + case MENU_ACTION_NONE: + break; + } + } - if (item.size() > 1) - action(); - } menuaction = MENU_ACTION_NONE; @@ -500,8 +486,8 @@ Menu::check() void Menu::draw_item(DrawingContext& context, - int index, // Position of the current item in the menu - int menu_width, int menu_height) + int index, // Position of the current item in the menu + int menu_width, int menu_height) { MenuItem& pitem = item[index]; @@ -515,223 +501,226 @@ Menu::draw_item(DrawingContext& context, effect_offset = (index % 2) ? effect_time : -effect_time; } - Font* text_font = white_text; + Font* text_font = default_font; int x_pos = pos_x; int y_pos = pos_y + 24*index - menu_height/2 + 12 + effect_offset; int shadow_size = 2; int text_width = int(text_font->get_text_width(pitem.text)); int input_width = int(text_font->get_text_width(pitem.input) + 10); - int list_width = - int(text_font->get_text_width(string_list_active(pitem.list))); - + int list_width = 0; + if(pitem.list.size() > 0) { + list_width = (int) text_font->get_text_width(pitem.list[pitem.selected]); + } + if (arrange_left) x_pos += 24 - menu_width/2 + (text_width + input_width + list_width)/2; if(index == active_item) - { - shadow_size = 3; - text_font = blue_text; - } - - switch (pitem.kind) - { - case MN_DEACTIVE: { - context.draw_text_center(gray_text, pitem.text, - Vector(0, y_pos - int(blue_text->get_height()/2)), - LAYER_GUI); - break; + shadow_size = 3; + text_font = active_font; } - case MN_HL: - { - // TODO - int x = pos_x - menu_width/2; - int y = y_pos - 12 - effect_offset; - /* Draw a horizontal line with a little 3d effect */ - context.draw_filled_rect(Vector(x, y + 6), - Vector(menu_width, 4), Color(150,200,255,225), LAYER_GUI); - context.draw_filled_rect(Vector(x, y + 6), - Vector(menu_width, 2), Color(255,255,255,255), LAYER_GUI); - break; - } - case MN_LABEL: - { - context.draw_text_center(white_big_text, - pitem.text, Vector(0, y_pos - int(white_big_text->get_height()/2)), - LAYER_GUI); - break; - } - case MN_TEXTFIELD: - case MN_NUMFIELD: - case MN_CONTROLFIELD_KB: - case MN_CONTROLFIELD_JS: + switch (pitem.kind) { - int width = text_width + input_width + 5; - int text_pos = screen->w/2 - width/2; - int input_pos = text_pos + text_width + 10; + case MN_DEACTIVE: + { + context.draw_text(deactive_font, pitem.text, + Vector(SCREEN_WIDTH/2, y_pos - int(deactive_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); + break; + } - context.draw_filled_rect( + case MN_HL: + { + // TODO + int x = pos_x - menu_width/2; + int y = y_pos - 12 - effect_offset; + /* Draw a horizontal line with a little 3d effect */ + context.draw_filled_rect(Vector(x, y + 6), + Vector(menu_width, 4), Color(150,200,255,225), LAYER_GUI); + context.draw_filled_rect(Vector(x, y + 6), + Vector(menu_width, 2), Color(255,255,255,255), LAYER_GUI); + break; + } + case MN_LABEL: + { + context.draw_text(label_font, pitem.text, + Vector(SCREEN_WIDTH/2, y_pos - int(label_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); + break; + } + case MN_TEXTFIELD: + case MN_NUMFIELD: + case MN_CONTROLFIELD_KB: + case MN_CONTROLFIELD_JS: + { + int width = text_width + input_width + 5; + int text_pos = SCREEN_WIDTH/2 - width/2; + int input_pos = text_pos + text_width + 10; + + context.draw_filled_rect( Vector(input_pos - 5, y_pos - 10), Vector(input_width + 10, 20), Color(255,255,255,255), LAYER_GUI-5); - context.draw_filled_rect( + context.draw_filled_rect( Vector(input_pos - 4, y_pos - 9), Vector(input_width + 8, 18), Color(0,0,0,128), LAYER_GUI-4); - if(pitem.kind == MN_CONTROLFIELD_KB) - get_controlfield_key_into_input(&pitem); - else if (pitem.kind == MN_CONTROLFIELD_JS) - get_controlfield_js_into_input(&pitem); + if(pitem.kind == MN_CONTROLFIELD_KB) + get_controlfield_key_into_input(&pitem); + else if (pitem.kind == MN_CONTROLFIELD_JS) + get_controlfield_js_into_input(&pitem); - if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD) - { - if(active_item == index) - context.draw_text(gold_text, - pitem.get_input_with_symbol(true), - Vector(input_pos, y_pos - int(gold_text->get_height()/2)), - LAYER_GUI); + if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD) + { + if(active_item == index) + context.draw_text(field_font, + pitem.get_input_with_symbol(true), + Vector(input_pos, y_pos - int(field_font->get_height()/2)), + LEFT_ALLIGN, LAYER_GUI); + else + context.draw_text(field_font, + pitem.get_input_with_symbol(false), + Vector(input_pos, y_pos - int(field_font->get_height()/2)), + LEFT_ALLIGN, LAYER_GUI); + } else - context.draw_text(gold_text, - pitem.get_input_with_symbol(false), - Vector(input_pos, y_pos - int(gold_text->get_height()/2)), - LAYER_GUI); + context.draw_text(field_font, pitem.input, + Vector(input_pos, y_pos - int(field_font->get_height()/2)), + LEFT_ALLIGN, LAYER_GUI); + + context.draw_text(text_font, pitem.text, + Vector(text_pos, y_pos - int(text_font->get_height()/2)), + LEFT_ALLIGN, LAYER_GUI); + break; } - else - context.draw_text(gold_text, pitem.input, - Vector(input_pos, y_pos - int(gold_text->get_height()/2)), - LAYER_GUI); - - context.draw_text(text_font, pitem.text, - Vector(text_pos, y_pos - int(text_font->get_height()/2)), - LAYER_GUI); - break; - } - case MN_STRINGSELECT: - { - int list_pos_2 = list_width + 16; - int list_pos = list_width/2; - int text_pos = (text_width + 16)/2; - - /* Draw arrows */ - context.draw_surface(arrow_left, - Vector(x_pos - list_pos + text_pos - 17, y_pos - 8), - LAYER_GUI); - context.draw_surface(arrow_right, - Vector(x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8), - LAYER_GUI); - - /* Draw input background */ - context.draw_filled_rect( + case MN_STRINGSELECT: + { + int list_pos_2 = list_width + 16; + int list_pos = list_width/2; + int text_pos = (text_width + 16)/2; + + /* Draw arrows */ + context.draw_surface(arrow_left, + Vector(x_pos - list_pos + text_pos - 17, y_pos - 8), + LAYER_GUI); + context.draw_surface(arrow_right, + Vector(x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8), + LAYER_GUI); + + /* Draw input background */ + context.draw_filled_rect( Vector(x_pos - list_pos + text_pos - 1, y_pos - 10), Vector(list_pos_2 + 2, 20), Color(255,255,255,255), LAYER_GUI - 4); - context.draw_filled_rect( + context.draw_filled_rect( Vector(x_pos - list_pos + text_pos, y_pos - 9), Vector(list_pos_2, 18), Color(0,0,0,128), LAYER_GUI - 5); - context.draw_text_center(text_font, string_list_active(pitem.list), - Vector(text_pos, y_pos - int(text_font->get_height()/2)), - LAYER_GUI); - context.draw_text_center(text_font, pitem.text, - Vector(list_pos_2/2, y_pos - int(text_font->get_height()/2)), - LAYER_GUI); - break; - } - case MN_BACK: - { - context.draw_text_center(text_font, pitem.text, - Vector(0, y_pos - int(text_font->get_height()/2)), - LAYER_GUI); - context.draw_surface(back, - Vector(x_pos + text_width/2 + 16, y_pos - 8), - LAYER_GUI); + context.draw_text(text_font, pitem.list[pitem.selected], + Vector(SCREEN_WIDTH/2 + text_pos, y_pos - int(text_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); + context.draw_text(text_font, pitem.text, + Vector(SCREEN_WIDTH/2 + list_pos_2/2, y_pos - int(text_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); + break; + } + case MN_BACK: + { + context.draw_text(text_font, pitem.text, + Vector(SCREEN_WIDTH/2, y_pos - int(text_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); + context.draw_surface(back, + Vector(x_pos + text_width/2 + 16, y_pos - 8), + LAYER_GUI); + break; + } + + case MN_TOGGLE: + { + context.draw_text(text_font, pitem.text, + Vector(SCREEN_WIDTH/2, y_pos - (text_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); + + if(pitem.toggled) + context.draw_surface(checkbox_checked, + Vector(x_pos + (text_width+16)/2, y_pos - 8), + LAYER_GUI + 1); + else + context.draw_surface(checkbox, + Vector(x_pos + (text_width+16)/2, y_pos - 8), + LAYER_GUI + 1); + break; + } + case MN_ACTION: + context.draw_text(text_font, pitem.text, + Vector(SCREEN_WIDTH/2, y_pos - int(text_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); break; - } - case MN_TOGGLE: - { - context.draw_text_center(text_font, pitem.text, - Vector(0, y_pos - (text_font->get_height()/2)), - LAYER_GUI); - - if(pitem.toggled) - context.draw_surface(checkbox_checked, - Vector(x_pos + (text_width+16)/2, y_pos - 8), - LAYER_GUI + 1); - else - context.draw_surface(checkbox, - Vector(x_pos + (text_width+16)/2, y_pos - 8), - LAYER_GUI + 1); + case MN_GOTO: + context.draw_text(text_font, pitem.text, + Vector(SCREEN_WIDTH/2, y_pos - int(text_font->get_height()/2)), + CENTER_ALLIGN, LAYER_GUI); break; } - case MN_ACTION: - context.draw_text_center(text_font, pitem.text, - Vector(0, y_pos - int(text_font->get_height()/2)), - LAYER_GUI); - break; - - case MN_GOTO: - context.draw_text_center(text_font, pitem.text, - Vector(0, y_pos - int(text_font->get_height()/2)), - LAYER_GUI); - break; - } } int Menu::get_width() const -{ - /* The width of the menu has to be more than the width of the text - with the most characters */ - int menu_width = 0; - for(unsigned int i = 0; i < item.size(); ++i) { - int w = strlen(item[i].text) + (item[i].input ? strlen(item[i].input) + 1 : 0) + strlen(string_list_active(item[i].list)); - if( w > menu_width ) - { - menu_width = w; - if( item[i].kind == MN_TOGGLE) - menu_width += 2; - } - } + /* The width of the menu has to be more than the width of the text + with the most characters */ + int menu_width = 0; + for(unsigned int i = 0; i < item.size(); ++i) + { + int w = item[i].text.size() + item[i].input.size() + 1; + if( w > menu_width ) + { + menu_width = w; + if( item[i].kind == MN_TOGGLE) + menu_width += 2; + } + } - return (menu_width * 16 + 24); -} + return (menu_width * 16 + 24); + } int Menu::get_height() const -{ - return item.size() * 24; -} + { + return item.size() * 24; + } /* Draw the current menu. */ void Menu::draw(DrawingContext& context) { + int menu_height = get_height(); - int menu_width = get_width(); + int menu_width = get_width(); /* Draw a transparent background */ context.draw_filled_rect( - Vector(pos_x - menu_width/2, pos_y - 24*item.size()/2 - 10), - Vector(menu_width,menu_height + 20), - Color(150,180,200,125), LAYER_GUI-10); + Vector(pos_x - menu_width/2, pos_y - 24*item.size()/2 - 10), + Vector(menu_width,menu_height + 20), + Color(150,180,200,125), LAYER_GUI-10); for(unsigned int i = 0; i < item.size(); ++i) - { - draw_item(context, i, menu_width, menu_height); - } + { + draw_item(context, i, menu_width, menu_height); + } } MenuItem& Menu::get_item_by_id(int id) { for(std::vector::iterator i = item.begin(); i != item.end(); ++i) - { - if(i->id == id) - return *i; - } + { + if(i->id == id) + return *i; + } assert(false); static MenuItem dummyitem; @@ -757,7 +746,7 @@ Menu::event(SDL_Event& event) { case SDL_KEYDOWN: { - SDLKey key = key = event.key.keysym.sym; + SDLKey key = event.key.keysym.sym; SDLMod keymod; char ch[2]; keymod = SDL_GetModState(); @@ -774,7 +763,7 @@ Menu::event(SDL_Event& event) /* An International Character. */ } - if(item[active_item].kind == MN_CONTROLFIELD_KB) + if(item.size() > 0 && item[active_item].kind == MN_CONTROLFIELD_KB) { if(key == SDLK_ESCAPE) { @@ -802,7 +791,7 @@ Menu::event(SDL_Event& event) menuaction = MENU_ACTION_RIGHT; break; case SDLK_SPACE: - if(item[active_item].kind == MN_TEXTFIELD) + if(item.size() > 0 && item[active_item].kind == MN_TEXTFIELD) { menuaction = MENU_ACTION_INPUT; mn_input_char = ' '; @@ -833,7 +822,7 @@ Menu::event(SDL_Event& event) } } break; - + case SDL_JOYAXISMOTION: if(event.jaxis.axis == joystick_keymap.y_axis) { @@ -851,10 +840,17 @@ Menu::event(SDL_Event& event) joystick_timer.stop(); } break; + case SDL_JOYHATMOTION: + if(event.jhat.value & SDL_HAT_UP) { + menuaction = MENU_ACTION_UP; + } else if(event.jhat.value & SDL_HAT_DOWN) { + menuaction = MENU_ACTION_DOWN; + } + break; case SDL_JOYBUTTONDOWN: - if (item[active_item].kind == MN_CONTROLFIELD_JS) + if (item.size() > 0 && item[active_item].kind == MN_CONTROLFIELD_JS) { - // FIXME: This next line does nothing useable, right? + // FIXME: This next line does nothing useable, right? // *item[active_item].int_p = key; menuaction = MENU_ACTION_DOWN; } @@ -863,13 +859,13 @@ Menu::event(SDL_Event& event) case SDL_MOUSEBUTTONDOWN: { - int x = event.motion.x; - int y = event.motion.y; + int x = int(event.motion.x * float(SCREEN_WIDTH)/screen->w); + int y = int(event.motion.y * float(SCREEN_HEIGHT)/screen->h); if(x > pos_x - get_width()/2 && - x < pos_x + get_width()/2 && - y > pos_y - get_height()/2 && - y < pos_y + get_height()/2) + x < pos_x + get_width()/2 && + y > pos_y - get_height()/2 && + y < pos_y + get_height()/2) { menuaction = MENU_ACTION_HIT; } @@ -878,20 +874,29 @@ Menu::event(SDL_Event& event) case SDL_MOUSEMOTION: { - int x = event.motion.x; - int y = event.motion.y; + int x = int(event.motion.x * float(SCREEN_WIDTH)/screen->w); + int y = int(event.motion.y * float(SCREEN_HEIGHT)/screen->h); if(x > pos_x - get_width()/2 && - x < pos_x + get_width()/2 && - y > pos_y - get_height()/2 && - y < pos_y + get_height()/2) + x < pos_x + get_width()/2 && + y > pos_y - get_height()/2 && + y < pos_y + get_height()/2) { - active_item = (y - (pos_y - get_height()/2)) / 24; - mouse_cursor->set_state(MC_LINK); + int new_active_item = (y - (pos_y - get_height()/2)) / 24; + + /* only change the mouse focus to a selectable item */ + if ((item[new_active_item].kind != MN_HL) + && (item[new_active_item].kind != MN_LABEL) + && (item[new_active_item].kind != MN_DEACTIVE)) + active_item = new_active_item; + + if(MouseCursor::current()) + MouseCursor::current()->set_state(MC_LINK); } else { - mouse_cursor->set_state(MC_NORMAL); + if(MouseCursor::current()) + MouseCursor::current()->set_state(MC_NORMAL); } } break; @@ -901,5 +906,3 @@ Menu::event(SDL_Event& event) } } - -// EOF //