Browse Source

Added love.window.showMessageBox.

It has two variants: showMessageBox(type, title, message [, attachtowindow=true]), and showMessageBox(type, title, message, buttons [, attachtowindow=true]). The former shows a simple message box with a single OK button, and the latter displays several buttons. The buttons argument is an array of button names.

The second variant returns the index of the pressed button, or 0 if the message box was closed some other way. showMessageBox will block until the message box is closed (and it can't be called on a separate thread.)
Alex Szpakowski 11 years ago
parent
commit
3ae336dd43

+ 19 - 0
src/modules/window/Window.cpp

@@ -74,6 +74,16 @@ bool Window::getConstant(Window::Setting in, const char *&out)
 	return settings.find(in, out);
 	return settings.find(in, out);
 }
 }
 
 
+bool Window::getConstant(const char *in, MessageBoxType &out)
+{
+	return messageBoxTypes.find(in, out);
+}
+
+bool Window::getConstant(MessageBoxType in, const char *&out)
+{
+	return messageBoxTypes.find(in, out);
+}
+
 StringMap<Window::Setting, Window::SETTING_MAX_ENUM>::Entry Window::settingEntries[] =
 StringMap<Window::Setting, Window::SETTING_MAX_ENUM>::Entry Window::settingEntries[] =
 {
 {
 	{"fullscreen", SETTING_FULLSCREEN},
 	{"fullscreen", SETTING_FULLSCREEN},
@@ -101,5 +111,14 @@ StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM>::Entry Windo
 
 
 StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM> Window::fullscreenTypes(Window::fullscreenTypeEntries, sizeof(Window::fullscreenTypeEntries));
 StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM> Window::fullscreenTypes(Window::fullscreenTypeEntries, sizeof(Window::fullscreenTypeEntries));
 
 
+StringMap<Window::MessageBoxType, Window::MESSAGEBOX_MAX_ENUM>::Entry Window::messageBoxTypeEntries[] =
+{
+	{"error", Window::MESSAGEBOX_ERROR},
+	{"warning", Window::MESSAGEBOX_WARNING},
+	{"info", Window::MESSAGEBOX_INFO},
+};
+
+StringMap<Window::MessageBoxType, Window::MESSAGEBOX_MAX_ENUM> Window::messageBoxTypes(Window::messageBoxTypeEntries, sizeof(Window::messageBoxTypeEntries));
+
 } // window
 } // window
 } // love
 } // love

+ 31 - 0
src/modules/window/Window.h

@@ -69,12 +69,34 @@ public:
 		FULLSCREEN_TYPE_MAX_ENUM
 		FULLSCREEN_TYPE_MAX_ENUM
 	};
 	};
 
 
+	enum MessageBoxType
+	{
+		MESSAGEBOX_ERROR,
+		MESSAGEBOX_WARNING,
+		MESSAGEBOX_INFO,
+		MESSAGEBOX_MAX_ENUM
+	};
+
 	struct WindowSize
 	struct WindowSize
 	{
 	{
 		int width;
 		int width;
 		int height;
 		int height;
 	};
 	};
 
 
+	struct MessageBoxData
+	{
+		MessageBoxType type;
+
+		std::string title;
+		std::string message;
+
+		std::vector<std::string> buttons;
+		int enterButtonIndex;
+		int escapeButtonIndex;
+
+		bool attachToWindow;
+	};
+
 	virtual ~Window();
 	virtual ~Window();
 
 
 	// Implements Module.
 	// Implements Module.
@@ -127,6 +149,9 @@ public:
 
 
 	virtual const void *getHandle() const = 0;
 	virtual const void *getHandle() const = 0;
 
 
+	virtual bool showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow) = 0;
+	virtual int showMessageBox(const MessageBoxData &data) = 0;
+
 	//virtual static Window *createSingleton() = 0;
 	//virtual static Window *createSingleton() = 0;
 	//virtual static Window *getSingleton() = 0;
 	//virtual static Window *getSingleton() = 0;
 	// No virtual statics, of course, but you are supposed to implement these statics.
 	// No virtual statics, of course, but you are supposed to implement these statics.
@@ -137,6 +162,9 @@ public:
 	static bool getConstant(const char *in, FullscreenType &out);
 	static bool getConstant(const char *in, FullscreenType &out);
 	static bool getConstant(FullscreenType in, const char *&out);
 	static bool getConstant(FullscreenType in, const char *&out);
 
 
+	static bool getConstant(const char *in, MessageBoxType &out);
+	static bool getConstant(MessageBoxType in, const char *&out);
+
 protected:
 protected:
 
 
 	static Window *singleton;
 	static Window *singleton;
@@ -149,6 +177,9 @@ private:
 	static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM>::Entry fullscreenTypeEntries[];
 	static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM>::Entry fullscreenTypeEntries[];
 	static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM> fullscreenTypes;
 	static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM> fullscreenTypes;
 
 
+	static StringMap<MessageBoxType, MESSAGEBOX_MAX_ENUM>::Entry messageBoxTypeEntries[];
+	static StringMap<MessageBoxType, MESSAGEBOX_MAX_ENUM> messageBoxTypes;
+
 }; // Window
 }; // Window
 
 
 struct WindowSettings
 struct WindowSettings

+ 59 - 0
src/modules/window/sdl/Window.cpp

@@ -678,6 +678,65 @@ const void *Window::getHandle() const
 	return window;
 	return window;
 }
 }
 
 
+SDL_MessageBoxFlags Window::convertMessageBoxType(MessageBoxType type) const
+{
+	switch (type)
+	{
+	case MESSAGEBOX_ERROR:
+		return SDL_MESSAGEBOX_ERROR;
+	case MESSAGEBOX_WARNING:
+		return SDL_MESSAGEBOX_WARNING;
+	case MESSAGEBOX_INFO:
+	default:
+		return SDL_MESSAGEBOX_INFORMATION;
+	}
+}
+
+bool Window::showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow)
+{
+	SDL_MessageBoxFlags flags = convertMessageBoxType(type);
+	SDL_Window *sdlwindow = attachtowindow ? window : nullptr;
+
+	return SDL_ShowSimpleMessageBox(flags, title.c_str(), message.c_str(), sdlwindow) >= 0;
+}
+
+int Window::showMessageBox(const MessageBoxData &data)
+{
+	SDL_MessageBoxData sdldata = {};
+
+	sdldata.flags = convertMessageBoxType(data.type);
+	sdldata.title = data.title.c_str();
+	sdldata.message = data.message.c_str();
+	sdldata.window = data.attachToWindow ? window : nullptr;
+
+	sdldata.numbuttons = (int) data.buttons.size();
+
+	std::vector<SDL_MessageBoxButtonData> sdlbuttons;
+
+	for (size_t i = 0; i < data.buttons.size(); i++)
+	{
+		SDL_MessageBoxButtonData sdlbutton = {};
+
+		sdlbutton.buttonid = (int) i;
+		sdlbutton.text = data.buttons[i].c_str();
+
+		if ((int) i == data.enterButtonIndex)
+			sdlbutton.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
+
+		if ((int) i == data.escapeButtonIndex)
+			sdlbutton.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
+
+		sdlbuttons.push_back(sdlbutton);
+	}
+
+	sdldata.buttons = &sdlbuttons[0];
+
+	int pressedbutton = -2;
+	SDL_ShowMessageBox(&sdldata, &pressedbutton);
+
+	return pressedbutton;
+}
+
 love::window::Window *Window::createSingleton()
 love::window::Window *Window::createSingleton()
 {
 {
 	if (!singleton)
 	if (!singleton)

+ 5 - 0
src/modules/window/sdl/Window.h

@@ -87,6 +87,9 @@ public:
 
 
 	const void *getHandle() const;
 	const void *getHandle() const;
 
 
+	bool showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow);
+	int showMessageBox(const MessageBoxData &data);
+
 	static love::window::Window *createSingleton();
 	static love::window::Window *createSingleton();
 	static love::window::Window *getSingleton();
 	static love::window::Window *getSingleton();
 
 
@@ -100,6 +103,8 @@ private:
 	// Update the saved window settings based on the window's actual state.
 	// Update the saved window settings based on the window's actual state.
 	void updateSettings(const WindowSettings &newsettings);
 	void updateSettings(const WindowSettings &newsettings);
 
 
+	SDL_MessageBoxFlags convertMessageBoxType(MessageBoxType type) const;
+
 	std::string windowTitle;
 	std::string windowTitle;
 
 
 	struct _currentMode
 	struct _currentMode

+ 61 - 0
src/modules/window/wrap_Window.cpp

@@ -340,6 +340,66 @@ int w_minimize(lua_State* /*L*/)
 	return 0;
 	return 0;
 }
 }
 
 
+int w_showMessageBox(lua_State *L)
+{
+	Window::MessageBoxData data = {};
+
+	const char *typestr = luaL_checkstring(L, 1);
+	if (!Window::getConstant(typestr, data.type))
+		return luaL_error(L, "Invalid messagebox type: %s", typestr);
+
+	data.title = luaL_checkstring(L, 2);
+	data.message = luaL_checkstring(L, 3);
+
+	// If we have a table argument, we assume a list of button names, which
+	// means we should use the more complex message box API.
+	if (lua_istable(L, 4))
+	{
+		size_t numbuttons = lua_objlen(L, 4);
+		if (numbuttons == 0)
+			return luaL_error(L, "Must have at least one messagebox button.");
+
+		// Array of button names.
+		for (size_t i = 0; i < numbuttons; i++)
+		{
+			lua_rawgeti(L, 4, i + 1);
+			data.buttons.push_back(luax_checkstring(L, -1));
+			lua_pop(L, 1);
+		}
+
+		// Optional table entry specifying the button to use when enter is pressed.
+		lua_getfield(L, 4, "enterbutton");
+		if (!lua_isnoneornil(L, -1))
+			data.enterButtonIndex = luaL_checkint(L, -1) - 1;
+		else
+			data.enterButtonIndex = 0;
+		lua_pop(L, 1);
+
+		// Optional table entry specifying the button to use when esc is pressed.
+		lua_getfield(L, 4, "escapebutton");
+		if (!lua_isnoneornil(L, -1))
+			data.escapeButtonIndex = luaL_checkint(L, -1) - 1;
+		else
+			data.escapeButtonIndex = (int) data.buttons.size() - 1;
+		lua_pop(L, 1);
+
+		data.attachToWindow = luax_optboolean(L, 5, true);
+
+		int pressedbutton = instance()->showMessageBox(data);
+		lua_pushinteger(L, pressedbutton + 1);
+	}
+	else
+	{
+		data.attachToWindow = luax_optboolean(L, 4, true);
+
+		// Display a simple message box.
+		bool success = instance()->showMessageBox(data.type, data.title, data.message, data.attachToWindow);
+		luax_pushboolean(L, success);
+	}
+
+	return 1;
+}
+
 static const luaL_Reg functions[] =
 static const luaL_Reg functions[] =
 {
 {
 	{ "getDisplayCount", w_getDisplayCount },
 	{ "getDisplayCount", w_getDisplayCount },
@@ -363,6 +423,7 @@ static const luaL_Reg functions[] =
 	{ "isVisible", w_isVisible },
 	{ "isVisible", w_isVisible },
 	{ "getPixelScale", w_getPixelScale },
 	{ "getPixelScale", w_getPixelScale },
 	{ "minimize", w_minimize },
 	{ "minimize", w_minimize },
+	{ "showMessageBox", w_showMessageBox },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
 
 

+ 1 - 0
src/modules/window/wrap_Window.h

@@ -50,6 +50,7 @@ int w_hasMouseFocus(lua_State *L);
 int w_isVisible(lua_State *L);
 int w_isVisible(lua_State *L);
 int w_getPixelScale(lua_State *L);
 int w_getPixelScale(lua_State *L);
 int w_minimize(lua_State *L);
 int w_minimize(lua_State *L);
+int w_showMessageBox(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_window(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_window(lua_State *L);
 
 
 } // window
 } // window