Fix for bug #436 - just clear last_menus when set_current(NULL) is called
[supertux.git] / src / gui / menu.cpp
index 2558359..cc062a0 100644 (file)
@@ -48,20 +48,16 @@ static const float FLICK_CURSOR_TIME   = 0.5f;
 extern SDL_Surface* screen;
 
 std::vector<Menu*> Menu::last_menus;
+std::list<Menu*> Menu::all_menus;
 Menu* Menu::current_ = 0;
 Menu* Menu::previous = 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 confirm_dialog(Surface *background, std::string text)
 {
   //Surface* cap_screen = Surface::CaptureScreen();
   Menu* dialog = new Menu;
-  dialog->add_deactive(-1, text);
+  dialog->add_inactive(-1, text);
   dialog->add_hl();
   dialog->add_entry(true, _("Yes"));
   dialog->add_entry(false, _("No"));
@@ -116,7 +112,7 @@ bool confirm_dialog(Surface *background, std::string text)
 
   return false;
 }
-\f
+
 void
 Menu::push_current(Menu* pmenu)
 {
@@ -141,27 +137,47 @@ Menu::pop_current()
     current_->effect_progress   = 0.0f;
     last_menus.pop_back();
   } else {
-    current_ = 0;
+    set_current(NULL);
   }
 }
 
 void
 Menu::set_current(Menu* menu)
 {
+  if (current_ && current_->close == true)
+    return;
+
   previous = current_;
 
-  last_menus.clear();
+  if (menu) {
+    menu->effect_start_time = real_time;
+    menu->effect_progress = 0.0f;
+    current_ = menu;
+  }
+  else if (current_) {
+    last_menus.clear();                                //NULL new menu pointer => close all menus
+    current_->effect_start_time = real_time;
+    current_->effect_progress = 0.0f;
+    current_->close = true;
+  }
 
-  if (menu)
-    {
-      menu->effect_start_time = real_time;
-      menu->effect_progress = 0.0f;
-    }
-  current_ = menu;
   // just to be sure...
   main_controller->reset();
 }
-\f
+
+void
+Menu::recalc_pos()
+{
+  if (current_)
+    current_->set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
+
+  for(std::list<Menu*>::iterator i = all_menus.begin(); i != all_menus.end(); ++i)
+    {
+      // FIXME: This is of course not quite right, since it ignores any previous set_pos() calls
+      (*i)->set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
+    }
+}
+
 MenuItem::MenuItem(MenuItemKind _kind, int _id)
   : kind(_kind) , id(_id)
 {
@@ -186,11 +202,11 @@ void
 MenuItem::set_help(const std::string& help_text)
 {
   std::string overflow;
-  help = Menu::default_font->wrap_to_width(help_text, 600, &overflow);
+  help = normal_font->wrap_to_width(help_text, 600, &overflow);
   while (!overflow.empty())
     {
       help += "\n";
-      help += Menu::default_font->wrap_to_width(overflow, 600, &overflow);
+      help += normal_font->wrap_to_width(overflow, 600, &overflow);
     }
 }
 
@@ -212,9 +228,11 @@ std::string MenuItem::get_input_with_symbol(bool active_item)
 
   return string;
 }
-\f
+
 Menu::~Menu()
 {
+  all_menus.remove(this);
+
   for(std::vector<MenuItem*>::iterator i = items.begin();
       i != items.end(); ++i)
     delete *i;
@@ -227,7 +245,10 @@ Menu::~Menu()
 }
 
 Menu::Menu()
+    : close(false)
 {
+  all_menus.push_back(this);
+
   hit_item = -1;
   menuaction = MENU_ACTION_NONE;
   delete_character = 0;
@@ -262,13 +283,13 @@ Menu::additem(MenuItem* item)
   items.push_back(item);
 
   /* If a new menu is being built, the active item shouldn't be set to
-   * something that isnt selectable. Set the active_item to the first
-   * selectable item added
+   * something that isn't selectable. Set the active_item to the first
+   * selectable item added.
    */
   if (active_item == -1
       && item->kind != MN_HL
       && item->kind != MN_LABEL
-      && item->kind != MN_DEACTIVE) {
+      && item->kind != MN_INACTIVE) {
     active_item = items.size() - 1;
   }
 }
@@ -292,11 +313,11 @@ Menu::add_label(const std::string& text)
 
 MenuItem*
 Menu::add_controlfield(int id, const std::string& text,
-               const std::string& mapping)
+                const std::string& mapping)
 {
   MenuItem* item = new MenuItem(MN_CONTROLFIELD, id);
   item->change_text(text);
-       item->change_input(mapping);
+        item->change_input(mapping);
   additem(item);
   return item;
 }
@@ -311,9 +332,9 @@ Menu::add_entry(int id, const std::string& text)
 }
 
 MenuItem*
-Menu::add_deactive(int id, const std::string& text)
+Menu::add_inactive(int id, const std::string& text)
 {
-  MenuItem* item = new MenuItem(MN_DEACTIVE, id);
+  MenuItem* item = new MenuItem(MN_INACTIVE, id);
   item->text = text;
   additem(item);
   return item;
@@ -383,7 +404,13 @@ Menu::update()
 
   if(effect_progress >= 1.0f) {
     effect_progress = 1.0f;
-  } else if (effect_progress <= 0.0f) {
+
+    if (close) {
+      current_ = 0;
+      close = false;
+    }
+  }
+  else if (effect_progress <= 0.0f) {
     effect_progress = 0.0f;
   }
 
@@ -450,7 +477,7 @@ Menu::update()
           active_item = int(items.size())-1;
       } while ((items[active_item]->kind == MN_HL
                 || items[active_item]->kind == MN_LABEL
-                || items[active_item]->kind == MN_DEACTIVE)
+                || items[active_item]->kind == MN_INACTIVE)
                && (active_item != last_active_item));
 
       break;
@@ -463,7 +490,7 @@ Menu::update()
           active_item = 0;
       } while ((items[active_item]->kind == MN_HL
                 || items[active_item]->kind == MN_LABEL
-                || items[active_item]->kind == MN_DEACTIVE)
+                || items[active_item]->kind == MN_INACTIVE)
                && (active_item != last_active_item));
 
       break;
@@ -543,7 +570,7 @@ Menu::update()
         {
           int i = items[active_item]->input.size();
 
-          while(delete_character > 0)  /* remove charactes */
+          while(delete_character > 0)        /* remove characters */
           {
             items[active_item]->input.resize(i-1);
             delete_character--;
@@ -594,19 +621,19 @@ Menu::draw_item(DrawingContext& context, int index)
 
   MenuItem& pitem = *(items[index]);
 
-  Font* text_font = default_font;
+  Color text_color = default_color;
   float x_pos       = pos_x;
   float y_pos       = pos_y + 24*index - menu_height/2 + 12;
   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 text_width  = int(normal_font->get_text_width(pitem.text));
+  int input_width = int(normal_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]);
+    list_width = (int) normal_font->get_text_width(pitem.list[pitem.selected]);
   }
 
   if (arrange_left)
@@ -615,7 +642,7 @@ Menu::draw_item(DrawingContext& context, int index)
   if(index == active_item)
     {
       shadow_size = 3;
-      text_font = active_font;
+      text_color = active_color;
     }
 
   if(active_item == index)
@@ -635,11 +662,11 @@ Menu::draw_item(DrawingContext& context, int index)
 
   switch (pitem.kind)
     {
-    case MN_DEACTIVE:
+    case MN_INACTIVE:
       {
-        context.draw_text(deactive_font, pitem.text,
-                          Vector(pos_x, y_pos - int(deactive_font->get_height()/2)),
-                          ALIGN_CENTER, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_CENTER, LAYER_GUI, inactive_color);
         break;
       }
 
@@ -659,9 +686,9 @@ Menu::draw_item(DrawingContext& context, int index)
       }
     case MN_LABEL:
       {
-        context.draw_text(label_font, pitem.text,
-                          Vector(pos_x, y_pos - int(label_font->get_height()/2)),
-                          ALIGN_CENTER, LAYER_GUI);
+        context.draw_text(big_font, pitem.text,
+                          Vector(pos_x, y_pos - int(big_font->get_height()/2)),
+                          ALIGN_CENTER, LAYER_GUI, label_color);
         break;
       }
     case MN_TEXTFIELD:
@@ -671,33 +698,33 @@ Menu::draw_item(DrawingContext& context, int index)
         if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD)
           {
             if(active_item == index)
-              context.draw_text(field_font,
+              context.draw_text(normal_font,
                                 pitem.get_input_with_symbol(true),
-                                Vector(right, y_pos - int(field_font->get_height()/2)),
-                                ALIGN_RIGHT, LAYER_GUI);
+                                Vector(right, y_pos - int(normal_font->get_height()/2)),
+                                ALIGN_RIGHT, LAYER_GUI, field_color);
             else
-              context.draw_text(field_font,
+              context.draw_text(normal_font,
                                 pitem.get_input_with_symbol(false),
-                                Vector(right, y_pos - int(field_font->get_height()/2)),
-                                ALIGN_RIGHT, LAYER_GUI);
+                                Vector(right, y_pos - int(normal_font->get_height()/2)),
+                                ALIGN_RIGHT, LAYER_GUI, field_color);
           }
         else
-          context.draw_text(field_font, pitem.input,
-                            Vector(right, y_pos - int(field_font->get_height()/2)),
-                            ALIGN_RIGHT, LAYER_GUI);
+          context.draw_text(normal_font, pitem.input,
+                            Vector(right, y_pos - int(normal_font->get_height()/2)),
+                            ALIGN_RIGHT, LAYER_GUI, field_color);
 
-        context.draw_text(text_font, pitem.text,
-                          Vector(left, y_pos - int(text_font->get_height()/2)),
-                          ALIGN_LEFT, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(left, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_LEFT, LAYER_GUI, text_color);
         break;
       }
     case MN_STRINGSELECT:
       {
         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);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(left, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_LEFT, LAYER_GUI, text_color);
 
         // Draw right side
         context.draw_surface(arrow_left.get(),
@@ -706,16 +733,16 @@ Menu::draw_item(DrawingContext& context, int index)
         context.draw_surface(arrow_right.get(),
                              Vector(right - roff, y_pos - 8),
                              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);
+        context.draw_text(normal_font, pitem.list[pitem.selected],
+                          Vector(right - roff, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_RIGHT, LAYER_GUI, text_color);
         break;
       }
     case MN_BACK:
       {
-        context.draw_text(text_font, pitem.text,
-                          Vector(pos_x, y_pos - int(text_font->get_height()/2)),
-                          ALIGN_CENTER, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_CENTER, LAYER_GUI, text_color);
         context.draw_surface(back.get(),
                              Vector(x_pos + text_width/2  + 16, y_pos - 8),
                              LAYER_GUI);
@@ -724,9 +751,9 @@ Menu::draw_item(DrawingContext& context, int index)
 
     case MN_TOGGLE:
       {
-        context.draw_text(text_font, pitem.text,
-                          Vector(pos_x - menu_width/2 + 16, y_pos - (text_font->get_height()/2)),
-                          ALIGN_LEFT, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(pos_x - menu_width/2 + 16, y_pos - (normal_font->get_height()/2)),
+                          ALIGN_LEFT, LAYER_GUI, text_color);
 
         if(pitem.toggled)
           context.draw_surface(checkbox_checked.get(),
@@ -739,15 +766,15 @@ Menu::draw_item(DrawingContext& context, int index)
         break;
       }
     case MN_ACTION:
-      context.draw_text(text_font, pitem.text,
-                        Vector(pos_x, y_pos - int(text_font->get_height()/2)),
-                        ALIGN_CENTER, LAYER_GUI);
+      context.draw_text(normal_font, pitem.text,
+                        Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                        ALIGN_CENTER, LAYER_GUI, text_color);
       break;
 
     case MN_GOTO:
-      context.draw_text(text_font, pitem.text,
-                        Vector(pos_x, y_pos - int(text_font->get_height()/2)),
-                        ALIGN_CENTER, LAYER_GUI);
+      context.draw_text(normal_font, pitem.text,
+                        Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                        ALIGN_CENTER, LAYER_GUI, text_color);
       break;
     }
 }
@@ -760,12 +787,12 @@ Menu::get_width() const
   float menu_width = 0;
   for(unsigned int i = 0; i < items.size(); ++i)
   {
-    Font* font = default_font;
+    Font* font = normal_font;
     if(items[i]->kind == MN_LABEL)
-      font = label_font;
+      font = big_font;
 
     float w = font->get_text_width(items[i]->text) +
-        label_font->get_text_width(items[i]->input) + 16;
+        big_font->get_text_width(items[i]->input) + 16;
     if(items[i]->kind == MN_TOGGLE)
       w += 32;
 
@@ -795,7 +822,12 @@ Menu::draw(DrawingContext& context)
 
   if (effect_progress != 1.0f)
     {
-      if (Menu::previous)
+      if (close)
+        {
+          menu_width  = (current_->get_width()  * (1.0f - effect_progress));
+          menu_height = (current_->get_height() * (1.0f - effect_progress));
+        }
+      else 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));
@@ -823,8 +855,8 @@ Menu::draw(DrawingContext& context)
 
   if (!items[active_item]->help.empty())
     {
-      int text_width  = (int) default_font->get_text_width(items[active_item]->help);
-      int text_height = (int) default_font->get_text_height(items[active_item]->help);
+      int text_width  = (int) normal_font->get_text_width(items[active_item]->help);
+      int text_height = (int) normal_font->get_text_height(items[active_item]->help);
       
       Rect text_rect(pos_x - text_width/2 - 8, 
                      SCREEN_HEIGHT - 48 - text_height/2 - 4,
@@ -842,7 +874,7 @@ Menu::draw(DrawingContext& context)
                                16.0f,
                                LAYER_GUI-10);
 
-      context.draw_text(default_font, items[active_item]->help,
+      context.draw_text(normal_font, items[active_item]->help,
                         Vector(pos_x, SCREEN_HEIGHT - 48 - text_height/2),
                         ALIGN_CENTER, LAYER_GUI);
     }
@@ -893,6 +925,12 @@ Menu::is_toggled(int id) const
   return get_item_by_id(id).toggled;
 }
 
+void
+Menu::set_toggled(int id, bool toggled)
+{
+  get_item_by_id(id).toggled = toggled;
+}
+
 Menu*
 Menu::get_parent() const
 {
@@ -941,7 +979,7 @@ Menu::event(const SDL_Event& event)
             /* only change the mouse focus to a selectable item */
             if ((items[new_active_item]->kind != MN_HL)
                 && (items[new_active_item]->kind != MN_LABEL)
-                && (items[new_active_item]->kind != MN_DEACTIVE))
+                && (items[new_active_item]->kind != MN_INACTIVE))
               active_item = new_active_item;
 
             if(MouseCursor::current())