From 64232f0aeca605b1c10c670fc0cf26b407793256 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Tue, 13 Mar 2012 00:48:02 +0200 Subject: [PATCH] Add confirmation menu and make world deletion possible in GUI --- src/CMakeLists.txt | 1 + src/guiConfirmMenu.cpp | 191 +++++++++++++++++++++++++++++++++++++++++ src/guiConfirmMenu.h | 57 ++++++++++++ src/guiMainMenu.cpp | 48 +++++++++-- src/guiMainMenu.h | 9 +- src/main.cpp | 28 ++---- 6 files changed, 304 insertions(+), 30 deletions(-) create mode 100644 src/guiConfirmMenu.cpp create mode 100644 src/guiConfirmMenu.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1818436..e44580b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 index 0000000..2ca4e17 --- /dev/null +++ b/src/guiConfirmMenu.cpp @@ -0,0 +1,191 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola + +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 +#include +#include +#include +#include +#include + +#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 &children = getChildren(); + core::list children_copy; + for(core::list::ConstIterator + i = children.begin(); i != children.end(); i++) + { + children_copy.push_back(*i); + } + for(core::list::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 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 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 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 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." + <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 index 0000000..ab9d6f6 --- /dev/null +++ b/src/guiConfirmMenu.h @@ -0,0 +1,57 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola + +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 + +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 + diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 6d07fe9..a0d8e93 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -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 @@ -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::const_iterator i = m_data->worlds.begin(); + for(std::vector::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(); +} + diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index 08c585b..688e393 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -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 worlds; + std::vector worlds; std::vector 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; diff --git a/src/main.cpp b/src/main.cpp index 2f9c69f..4ce73f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 worldspecs = getAvailableWorlds(); - for(std::vector::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 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<