Add confirmation menu and make world deletion possible in GUI
authorPerttu Ahola <celeron55@gmail.com>
Mon, 12 Mar 2012 22:48:02 +0000 (00:48 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 12 Mar 2012 22:48:05 +0000 (00:48 +0200)
src/CMakeLists.txt
src/guiConfirmMenu.cpp [new file with mode: 0644]
src/guiConfirmMenu.h [new file with mode: 0644]
src/guiMainMenu.cpp
src/guiMainMenu.h
src/main.cpp

index 18184365f165f2c7e13c6c81cd29147caa5d23e0..e44580bc463dcc6a2b28fd14c510c2e7ced35b47 100644 (file)
@@ -180,6 +180,7 @@ set(minetest_SRCS
        guiDeathScreen.cpp
        guiChatConsole.cpp
        guiCreateWorld.cpp
+       guiConfirmMenu.cpp
        client.cpp
        tile.cpp
        game.cpp
diff --git a/src/guiConfirmMenu.cpp b/src/guiConfirmMenu.cpp
new file mode 100644 (file)
index 0000000..2ca4e17
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "guiConfirmMenu.h"
+#include "debug.h"
+#include "serialization.h"
+#include <string>
+#include <IGUICheckBox.h>
+#include <IGUIEditBox.h>
+#include <IGUIButton.h>
+#include <IGUIStaticText.h>
+#include <IGUIFont.h>
+
+#include "gettext.h"
+
+enum
+{
+       GUI_ID_YES = 101,
+       GUI_ID_NO,
+};
+
+GUIConfirmMenu::GUIConfirmMenu(gui::IGUIEnvironment* env,
+               gui::IGUIElement* parent, s32 id,
+               IMenuManager *menumgr,
+               ConfirmDest *dest,
+               std::wstring message_text
+):
+       GUIModalMenu(env, parent, id, menumgr),
+       m_dest(dest),
+       m_message_text(message_text)
+{
+}
+
+GUIConfirmMenu::~GUIConfirmMenu()
+{
+       removeChildren();
+       if(m_dest)
+               delete m_dest;
+}
+
+void GUIConfirmMenu::removeChildren()
+{
+       const core::list<gui::IGUIElement*> &children = getChildren();
+       core::list<gui::IGUIElement*> children_copy;
+       for(core::list<gui::IGUIElement*>::ConstIterator
+                       i = children.begin(); i != children.end(); i++)
+       {
+               children_copy.push_back(*i);
+       }
+       for(core::list<gui::IGUIElement*>::Iterator
+                       i = children_copy.begin();
+                       i != children_copy.end(); i++)
+       {
+               (*i)->remove();
+       }
+}
+
+void GUIConfirmMenu::regenerateGui(v2u32 screensize)
+{
+       /*
+               Remove stuff
+       */
+       removeChildren();
+       
+       /*
+               Calculate new sizes and positions
+       */
+       core::rect<s32> rect(
+                       screensize.X/2 - 580/2,
+                       screensize.Y/2 - 300/2,
+                       screensize.X/2 + 580/2,
+                       screensize.Y/2 + 300/2
+       );
+       
+       DesiredRect = rect;
+       recalculateAbsolutePosition(false);
+
+       v2s32 size = rect.getSize();
+
+       /*
+               Add stuff
+       */
+       {
+               core::rect<s32> rect(0, 0, 300, 20);
+               rect += v2s32(size.X/2-300/2, size.Y/2-30/2-25);
+               Environment->addStaticText(m_message_text.c_str(),
+                       rect, false, true, this, -1);
+       }
+       changeCtype("");
+       int bw = 100;
+       {
+               core::rect<s32> rect(0, 0, bw, 30);
+               rect = rect + v2s32(size.X/2-bw/2-bw/2-5, size.Y/2-30/2+25);
+               Environment->addButton(rect, this, GUI_ID_NO,
+                       wgettext("No"));
+       }
+       {
+               core::rect<s32> rect(0, 0, bw, 30);
+               rect = rect + v2s32(size.X/2-bw/2+bw/2+5, size.Y/2-30/2+25);
+               Environment->addButton(rect, this, GUI_ID_YES,
+                       wgettext("Yes"));
+       }
+       changeCtype("C");
+}
+
+void GUIConfirmMenu::drawMenu()
+{
+       gui::IGUISkin* skin = Environment->getSkin();
+       if (!skin)
+               return;
+       video::IVideoDriver* driver = Environment->getVideoDriver();
+       
+       video::SColor bgcolor(140,0,0,0);
+       driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
+
+       gui::IGUIElement::draw();
+}
+
+void GUIConfirmMenu::acceptInput(bool answer)
+{
+       if(m_dest)
+               m_dest->answer(answer);
+}
+
+bool GUIConfirmMenu::OnEvent(const SEvent& event)
+{
+       if(event.EventType==EET_KEY_INPUT_EVENT)
+       {
+               if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
+               {
+                       acceptInput(false);
+                       quitMenu();
+                       return true;
+               }
+               if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
+               {
+                       acceptInput(true);
+                       quitMenu();
+                       return true;
+               }
+       }
+       if(event.EventType==EET_GUI_EVENT)
+       {
+               if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
+                               && isVisible())
+               {
+                       if(!canTakeFocus(event.GUIEvent.Element))
+                       {
+                               dstream<<"GUIConfirmMenu: Not allowing focus change."
+                                               <<std::endl;
+                               // Returning true disables focus change
+                               return true;
+                       }
+               }
+               if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
+               {
+                       switch(event.GUIEvent.Caller->getID())
+                       {
+                       case GUI_ID_YES:
+                               acceptInput(true);
+                               quitMenu();
+                               // quitMenu deallocates menu
+                               return true;
+                       case GUI_ID_NO:
+                               acceptInput(false);
+                               quitMenu();
+                               // quitMenu deallocates menu
+                               return true;
+                       }
+               }
+       }
+
+       return Parent ? Parent->OnEvent(event) : false;
+}
+
diff --git a/src/guiConfirmMenu.h b/src/guiConfirmMenu.h
new file mode 100644 (file)
index 0000000..ab9d6f6
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef GUICONFIRMMENU_HEADER
+#define GUICONFIRMMENU_HEADER
+
+#include "common_irrlicht.h"
+#include "modalMenu.h"
+#include "utility.h"
+#include <string>
+
+struct ConfirmDest
+{
+       virtual void answer(bool answer) = 0;
+       virtual ~ConfirmDest() {};
+};
+
+class GUIConfirmMenu : public GUIModalMenu
+{
+public:
+       GUIConfirmMenu(gui::IGUIEnvironment* env,
+                       gui::IGUIElement* parent, s32 id,
+                       IMenuManager *menumgr,
+                       ConfirmDest *dest,
+                       std::wstring message_text);
+       ~GUIConfirmMenu();
+       
+       void removeChildren();
+       // Remove and re-add (or reposition) stuff
+       void regenerateGui(v2u32 screensize);
+       void drawMenu();
+       void acceptInput(bool answer);
+       bool OnEvent(const SEvent& event);
+       
+private:
+       ConfirmDest *m_dest;
+       std::wstring m_message_text;
+};
+
+#endif
+
index 6d07fe9733c6e6df46556a4da1446d8a242066d6..a0d8e93ec21f5f54800b845f685a9352532652b7 100644 (file)
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "guiKeyChangeMenu.h"
 #include "guiCreateWorld.h"
 #include "guiMessageMenu.h"
+#include "guiConfirmMenu.h"
 #include "debug.h"
 #include "serialization.h"
 #include <string>
@@ -47,6 +48,22 @@ struct CreateWorldDestMainMenu : public CreateWorldDest
        GUIMainMenu *m_menu;
 };
 
+struct ConfirmDestDeleteWorld : public ConfirmDest
+{
+       ConfirmDestDeleteWorld(WorldSpec spec, GUIMainMenu *menu):
+               m_spec(spec),
+               m_menu(menu)
+       {}
+       void answer(bool answer)
+       {
+               if(answer == false)
+                       return;
+               m_menu->deleteWorld(m_spec);
+       }
+       WorldSpec m_spec;
+       GUIMainMenu *m_menu;
+};
+
 enum
 {
        GUI_ID_QUIT_BUTTON = 101,
@@ -312,9 +329,9 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
                gui::IGUIListBox *e = Environment->addListBox(rect, this,
                                GUI_ID_WORLD_LISTBOX);
                e->setDrawBackground(true);
-               for(std::list<std::wstring>::const_iterator i = m_data->worlds.begin();
+               for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
                                i != m_data->worlds.end(); i++){
-                       e->addItem(i->c_str());
+                       e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
                }
                e->setSelected(m_data->selected_world);
        }
@@ -458,9 +475,21 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
                                return true;
                        }
                        case GUI_ID_DELETE_WORLD_BUTTON: {
-                               acceptInput();
-                               m_data->delete_world = true;
-                               quitMenu();
+                               MainMenuData cur;
+                               readInput(&cur);
+                               if(cur.selected_world == -1){
+                                       (new GUIMessageMenu(env, parent, -1, menumgr,
+                                                       wgettext("Cannot delete world: Nothing selected"))
+                                                       )->drop();
+                               } else {
+                                       WorldSpec spec = m_data->worlds[cur.selected_world];
+                                       ConfirmDestDeleteWorld *dest = new
+                                                       ConfirmDestDeleteWorld(spec, this);
+                                       (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
+                                                       (std::wstring(wgettext("Delete world "))
+                                                       +L"\""+narrow_to_wide(spec.name)+L"\"?").c_str()
+                                                       ))->drop();
+                               }
                                return true;
                        }
                        case GUI_ID_CREATE_WORLD_BUTTON: {
@@ -516,3 +545,12 @@ void GUIMainMenu::createNewWorld(std::wstring name, std::string gameid)
        quitMenu();
 }
 
+void GUIMainMenu::deleteWorld(WorldSpec spec)
+{
+       if(!spec.isValid())
+               return;
+       acceptInput();
+       m_data->delete_world_spec = spec;
+       quitMenu();
+}
+
index 08c585b88b038d870c2808888cf438b7794fd0b0..688e393ad5ca90f6f626d18d76c77815fcf5e881 100644 (file)
@@ -44,11 +44,11 @@ struct MainMenuData
        bool enable_damage;
        int selected_world;
        // Actions
-       bool delete_world;
+       WorldSpec delete_world_spec;
        std::wstring create_world_name;
        std::string create_world_gameid;
 
-       std::list<std::wstring> worlds;
+       std::vector<WorldSpec> worlds;
        std::vector<SubgameSpec> games;
 
        MainMenuData():
@@ -58,9 +58,7 @@ struct MainMenuData
                // Server opts
                creative_mode(false),
                enable_damage(false),
-               selected_world(0),
-               // Actions
-               delete_world(false)
+               selected_world(0)
        {}
 };
 
@@ -84,6 +82,7 @@ public:
        { return m_accepted; }
        bool OnEvent(const SEvent& event);
        void createNewWorld(std::wstring name, std::string gameid);
+       void deleteWorld(WorldSpec spec);
        
 private:
        MainMenuData *m_data;
index 2f9c69fe1eaa02746831d7f67fe80bda4fb067a1..4ce73f633df6a103a752297d9c20c9adf72c3fd3 100644 (file)
@@ -1271,14 +1271,10 @@ int main(int argc, char *argv[])
                                menudata.opaque_water = g_settings->getBool("opaque_water");
                                menudata.creative_mode = g_settings->getBool("creative_mode");
                                menudata.enable_damage = g_settings->getBool("enable_damage");
-                               // Get world listing for the menu
-                               std::vector<WorldSpec> worldspecs = getAvailableWorlds();
-                               for(std::vector<WorldSpec>::const_iterator i = worldspecs.begin();
-                                               i != worldspecs.end(); i++)
-                                       menudata.worlds.push_back(narrow_to_wide(
-                                                       i->name + " [" + i->gameid + "]"));
                                // Default to selecting nothing
                                menudata.selected_world = -1;
+                               // Get world listing for the menu
+                               std::vector<WorldSpec> worldspecs = getAvailableWorlds();
                                // If there is only one world, select it
                                if(worldspecs.size() == 1){
                                        menudata.selected_world = 0;
@@ -1300,10 +1296,10 @@ int main(int argc, char *argv[])
                                                gameid = g_settings->get("default_game");
                                        WorldSpec spec(commanded_world, "--world", gameid);
                                        worldspecs.push_back(spec);
-                                       menudata.worlds.push_back(narrow_to_wide(spec.name)
-                                                       +L" ["+narrow_to_wide(spec.gameid)+L"]");
                                        menudata.selected_world = menudata.worlds.size()-1;
                                }
+                               // Copy worldspecs to menu
+                               menudata.worlds = worldspecs;
 
                                if(skip_main_menu == false)
                                {
@@ -1364,22 +1360,14 @@ int main(int argc, char *argv[])
                                }
                                
                                // Delete world if requested
-                               if(menudata.delete_world)
+                               if(menudata.delete_world_spec.isValid())
                                {
-                                       if(menudata.selected_world == -1){
-                                               error_message = L"Cannot delete world: "
-                                                               L"no world selected";
-                                               errorstream<<wide_to_narrow(error_message)<<std::endl;
-                                               continue;
-                                       }
-                                       /*bool r = fs::RecursiveDeleteContent(worldspec.path);
+                                       bool r = fs::RecursiveDeleteContent(
+                                                       menudata.delete_world_spec.path);
                                        if(r == false){
                                                error_message = L"World delete failed";
                                                errorstream<<wide_to_narrow(error_message)<<std::endl;
-                                       }*/
-                                       // TODO: Some kind of a yes/no dialog is needed.
-                                       error_message = L"This doesn't do anything currently.";
-                                       errorstream<<wide_to_narrow(error_message)<<std::endl;
+                                       }
                                        continue;
                                }