Added README that might be useful for some, added svn:ignore stuff
[supertux.git] / src / gui / menu.cpp
index 7768934..b0394ac 100644 (file)
@@ -42,8 +42,8 @@
 #include "control/joystickkeyboardcontroller.hpp"
 
 static const float MENU_REPEAT_INITIAL = 0.4f;
-static const float MENU_REPEAT_RATE = 0.2f;
-static const float FLICK_CURSOR_TIME = 0.5f;
+static const float MENU_REPEAT_RATE    = 0.1f;
+static const float FLICK_CURSOR_TIME   = 0.5f;
 
 extern SDL_Surface* screen;
 
@@ -182,6 +182,18 @@ MenuItem::change_input(const  std::string& text_)
   input = text_;
 }
 
+void
+MenuItem::set_help(const std::string& help_text)
+{
+  std::string overflow;
+  help = Menu::default_font->wrap_to_width(help_text, 600, &overflow);
+  while (!overflow.empty())
+    {
+      help += "\n";
+      help += Menu::default_font->wrap_to_width(overflow, 600, &overflow);
+    }
+}
+
 std::string MenuItem::get_input_with_symbol(bool active_item)
 {
   if(!active_item) {
@@ -239,7 +251,7 @@ Menu::Menu()
 void
 Menu::set_pos(float x, float y, float rw, float rh)
 {
-  pos_x = x + get_width() * rw;
+  pos_x = x + get_width()  * rw;
   pos_y = y + get_height() * rh;
 }
 
@@ -261,21 +273,24 @@ Menu::additem(MenuItem* item)
   }
 }
 
-void
+MenuItem*
 Menu::add_hl()
 {
-  additem(new MenuItem(MN_HL));
+  MenuItem* item = new MenuItem(MN_HL);
+  additem(item);
+  return item;
 }
 
-void
+MenuItem*
 Menu::add_label(const std::string& text)
 {
   MenuItem* item = new MenuItem(MN_LABEL);
   item->text = text;
   additem(item);
+  return item;
 }
 
-void
+MenuItem*
 Menu::add_controlfield(int id, const std::string& text,
                const std::string& mapping)
 {
@@ -283,48 +298,63 @@ Menu::add_controlfield(int id, const std::string& text,
   item->change_text(text);
        item->change_input(mapping);
   additem(item);
+  return item;
 }
 
-void
+MenuItem*
 Menu::add_entry(int id, const std::string& text)
 {
   MenuItem* item = new MenuItem(MN_ACTION, id);
   item->text = text;
   additem(item);
+  return item;
 }
 
-void
+MenuItem*
 Menu::add_deactive(int id, const std::string& text)
 {
   MenuItem* item = new MenuItem(MN_DEACTIVE, id);
   item->text = text;
   additem(item);
+  return item;
 }
 
-void
+MenuItem*
 Menu::add_toggle(int id, const std::string& text, bool toogled)
 {
   MenuItem* item = new MenuItem(MN_TOGGLE, id);
   item->text = text;
   item->toggled = toogled;
   additem(item);
+  return item;
 }
 
-void
+MenuItem*
+Menu::add_string_select(int id, const std::string& text)
+{
+  MenuItem* item = new MenuItem(MN_STRINGSELECT, id);
+  item->text = text;
+  additem(item);
+  return item;
+}
+
+MenuItem*
 Menu::add_back(const std::string& text)
 {
   MenuItem* item = new MenuItem(MN_BACK);
   item->text = text;
   additem(item);
+  return item;
 }
 
-void
+MenuItem*
 Menu::add_submenu(const std::string& text, Menu* submenu, int id)
 {
   MenuItem* item = new MenuItem(MN_GOTO, id);
   item->text = text;
   item->target_menu = submenu;
   additem(item);
+  return item;
 }
 
 void
@@ -367,6 +397,7 @@ Menu::update()
     menuaction = MENU_ACTION_UP;
     menu_repeat_time = real_time + MENU_REPEAT_RATE;
   }
+
   if(main_controller->pressed(Controller::DOWN)) {
     menuaction = MENU_ACTION_DOWN;
     menu_repeat_time = real_time + MENU_REPEAT_INITIAL;
@@ -376,6 +407,27 @@ Menu::update()
     menuaction = MENU_ACTION_DOWN;
     menu_repeat_time = real_time + MENU_REPEAT_RATE;
   }
+
+  if(main_controller->pressed(Controller::LEFT)) {
+    menuaction = MENU_ACTION_LEFT;
+    menu_repeat_time = real_time + MENU_REPEAT_INITIAL;
+  }
+  if(main_controller->hold(Controller::LEFT) &&
+      menu_repeat_time != 0 && real_time > menu_repeat_time) {
+    menuaction = MENU_ACTION_LEFT;
+    menu_repeat_time = real_time + MENU_REPEAT_RATE;
+  }
+
+  if(main_controller->pressed(Controller::RIGHT)) {
+    menuaction = MENU_ACTION_RIGHT;
+    menu_repeat_time = real_time + MENU_REPEAT_INITIAL;
+  }
+  if(main_controller->hold(Controller::RIGHT) &&
+      menu_repeat_time != 0 && real_time > menu_repeat_time) {
+    menuaction = MENU_ACTION_RIGHT;
+    menu_repeat_time = real_time + MENU_REPEAT_RATE;
+  }
+
   if(main_controller->pressed(Controller::ACTION)
      || main_controller->pressed(Controller::MENU_SELECT)) {
     menuaction = MENU_ACTION_HIT;
@@ -422,6 +474,8 @@ Menu::update()
           items[active_item]->selected--;
         else
           items[active_item]->selected = items[active_item]->list.size()-1;
+        
+        menu_action(items[active_item]);
       }
       break;
 
@@ -431,6 +485,8 @@ Menu::update()
           items[active_item]->selected++;
         else
           items[active_item]->selected = 0;
+        
+        menu_action(items[active_item]);
       }
       break;
 
@@ -455,6 +511,15 @@ Menu::update()
           menu_action(items[active_item]);
           break;
 
+        case MN_STRINGSELECT:
+          if(items[active_item]->selected+1 < items[active_item]->list.size())
+              items[active_item]->selected++;
+          else
+            items[active_item]->selected = 0;
+
+          menu_action(items[active_item]);
+          break;
+
         case MN_TEXTFIELD:
         case MN_NUMFIELD:
           menuaction = MENU_ACTION_DOWN;
@@ -536,6 +601,10 @@ Menu::draw_item(DrawingContext& context, int index)
   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 = 0;
+
+  float left  = pos_x - menu_width/2 + 16;
+  float right = pos_x + menu_width/2 - 16;
+
   if(pitem.list.size() > 0) {
     list_width = (int) text_font->get_text_width(pitem.list[pitem.selected]);
   }
@@ -599,9 +668,6 @@ Menu::draw_item(DrawingContext& context, int index)
     case MN_NUMFIELD:
     case MN_CONTROLFIELD:
       {
-        float left  = pos_x - menu_width/2 + 16;
-        float right = pos_x + menu_width/2 - 16;
-
         if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD)
           {
             if(active_item == index)
@@ -627,34 +693,22 @@ Menu::draw_item(DrawingContext& context, int index)
       }
     case MN_STRINGSELECT:
       {
-        int list_pos_2 = list_width + 16;
-        int list_pos   = list_width/2;
-        int text_pos   = (text_width + 16)/2;
+        float roff = arrow_left->get_width();
+        // Draw left side
+        context.draw_text(text_font, pitem.text,
+                          Vector(left, y_pos - int(text_font->get_height()/2)),
+                          ALIGN_LEFT, LAYER_GUI);
 
-        /* Draw arrows */
+        // Draw right side
         context.draw_surface(arrow_left.get(),
-                             Vector(x_pos - list_pos + text_pos - 17, y_pos - 8),
+                             Vector(right - list_width - roff - roff, y_pos - 8),
                              LAYER_GUI);
         context.draw_surface(arrow_right.get(),
-                             Vector(x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8),
+                             Vector(right - roff, 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(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI - 4);
-        context.draw_filled_rect(
-          Vector(x_pos - list_pos + text_pos, y_pos - 9),
-          Vector(list_pos_2, 18),
-          Color(0, 0, 0, 0.5f), LAYER_GUI - 5);
-
-        context.draw_text(text_font, pitem.list[pitem.selected],
-                                 Vector(pos_x + text_pos, y_pos - int(text_font->get_height()/2)),
-                                 ALIGN_CENTER, LAYER_GUI);
-        context.draw_text(text_font, pitem.text,
-                                 Vector(pos_x  + list_pos_2/2, y_pos - int(text_font->get_height()/2)),
-                                 ALIGN_CENTER, LAYER_GUI);
+        context.draw_text(field_font, pitem.list[pitem.selected],
+                          Vector(right - roff, y_pos - int(text_font->get_height()/2)),
+                          ALIGN_RIGHT, LAYER_GUI);
         break;
       }
     case MN_BACK:
@@ -741,17 +795,17 @@ Menu::draw(DrawingContext& context)
 
   if (effect_progress != 1.0f)
     {
-    if (Menu::previous)
-      {
-        menu_width  = (menu_width  * effect_progress) + (Menu::previous->get_width()  * (1.0f - effect_progress));
-        menu_height = (menu_height * effect_progress) + (Menu::previous->get_height() * (1.0f - effect_progress));
-        //std::cout << effect_progress << " " << this << " " << last_menus.back() << std::endl;
-      }
-    else
-      {
-        menu_width  *= effect_progress;
-        menu_height *= effect_progress;
-      }
+      if (Menu::previous)
+        {
+          menu_width  = (menu_width  * effect_progress) + (Menu::previous->get_width()  * (1.0f - effect_progress));
+          menu_height = (menu_height * effect_progress) + (Menu::previous->get_height() * (1.0f - effect_progress));
+          //std::cout << effect_progress << " " << this << " " << last_menus.back() << std::endl;
+        }
+      else
+        {
+          menu_width  *= effect_progress;
+          menu_height *= effect_progress;
+        }
     }
 
   /* Draw a transparent background */
@@ -767,6 +821,32 @@ Menu::draw(DrawingContext& context)
                            16.0f,
                            LAYER_GUI-10);
 
+  if (!items[active_item]->help.empty())
+    {
+      int text_width  = default_font->get_text_width(items[active_item]->help);
+      int text_height = default_font->get_text_height(items[active_item]->help);
+      
+      Rect text_rect(pos_x - text_width/2 - 8, 
+                     SCREEN_HEIGHT - 48 - text_height/2 - 4,
+                     pos_x + text_width/2 + 8, 
+                     SCREEN_HEIGHT - 48 + text_height/2 + 4);
+        
+      context.draw_filled_rect(Rect(text_rect.p1 - Vector(4,4),
+                                    text_rect.p2 + Vector(4,4)),
+                               Color(0.2f, 0.3f, 0.4f, 0.8f), 
+                               16.0f,
+                               LAYER_GUI-10);
+      
+      context.draw_filled_rect(text_rect,
+                               Color(0.6f, 0.7f, 0.8f, 0.5f), 
+                               16.0f,
+                               LAYER_GUI-10);
+
+      context.draw_text(default_font, items[active_item]->help,
+                        Vector(pos_x, SCREEN_HEIGHT - 48 - text_height/2),
+                        ALIGN_CENTER, LAYER_GUI);
+    }
+
   if (effect_progress == 1.0f)
     for(unsigned int i = 0; i < items.size(); ++i)
       {