summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2005-06-05 18:17:04 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2005-06-05 18:17:04 +0000
commit732d52d4fcb3a1ae644e6d82b2b69fbfa2efaf51 (patch)
treef09bb3b8c34cdfd78f8346460fabac7b2f21ddf8
parentaba239393ecd298e8ffd16e0b6a5d86837c594ae (diff)
downloadmana-732d52d4fcb3a1ae644e6d82b2b69fbfa2efaf51.tar.gz
mana-732d52d4fcb3a1ae644e6d82b2b69fbfa2efaf51.tar.bz2
mana-732d52d4fcb3a1ae644e6d82b2b69fbfa2efaf51.tar.xz
mana-732d52d4fcb3a1ae644e6d82b2b69fbfa2efaf51.zip
Using custom focus handler to work around problem with multiple widgets
requesting modal focus using a stack based approach.
-rw-r--r--src/Makefile.am6
-rw-r--r--src/gui/focushandler.cpp65
-rw-r--r--src/gui/focushandler.h64
-rw-r--r--src/gui/gui.cpp5
-rw-r--r--src/gui/gui.h1
-rw-r--r--src/gui/inttextbox.cpp10
-rw-r--r--src/gui/inttextbox.h44
-rw-r--r--src/gui/window.cpp14
-rw-r--r--src/gui/window.h1
-rw-r--r--src/gui/windowcontainer.h3
10 files changed, 177 insertions, 36 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 85878bbb..2c579825 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,6 +25,8 @@ tmw_SOURCES = graphic/spriteset.cpp \
gui/confirm_dialog.h \
gui/equipment.cpp \
gui/equipment.h \
+ gui/focushandler.cpp \
+ gui/focushandler.h \
gui/gui.cpp \
gui/gui.h \
gui/help.cpp \
@@ -142,7 +144,7 @@ INCLUDES = \
-DTMW_DATADIR=\""$(pkgdatadir)/"\"
# the library search path.
-tmw_LDFLAGS = $(all_libraries) $(LIBSDL_RPATH) -lguichan_sdl -lguichan `pkg-config --libs libxml-2.0`
+tmw_LDFLAGS = $(all_libraries) $(LIBSDL_RPATH) `pkg-config --libs libxml-2.0`
tmw_CXXFLAGS = -Wall $(OPENGL_CFLAGS) $(LIBSDL_CFLAGS) `pkg-config --cflags libxml-2.0`
-tmw_LDADD = $(LIBSDL_LIBS) -lguichan $(OPENGL_LIBS) -lphysfs
+tmw_LDADD = $(LIBSDL_LIBS) -lguichan_sdl -lguichan $(OPENGL_LIBS) -lphysfs
tmw_TARGET = tmw
diff --git a/src/gui/focushandler.cpp b/src/gui/focushandler.cpp
new file mode 100644
index 00000000..94d54f50
--- /dev/null
+++ b/src/gui/focushandler.cpp
@@ -0,0 +1,65 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "focushandler.h"
+
+
+void FocusHandler::requestModalFocus(gcn::Widget *widget)
+{
+ /* If there is another widget with modal focus, remove its modal focus
+ * and put it on the modal widget stack.
+ */
+ if (mModalFocusedWidget != NULL && mModalFocusedWidget != widget)
+ {
+ modalStack.push_front(mModalFocusedWidget);
+ mModalFocusedWidget = NULL;
+ }
+
+ gcn::FocusHandler::requestModalFocus(widget);
+}
+
+void FocusHandler::releaseModalFocus(gcn::Widget *widget)
+{
+ modalStack.remove(widget);
+
+ if (mModalFocusedWidget == widget)
+ {
+ gcn::FocusHandler::releaseModalFocus(widget);
+
+ /* Check if there were any previously modal widgets that'd still like
+ * to regain their modal focus.
+ */
+ if (modalStack.size() > 0)
+ {
+ gcn::FocusHandler::requestModalFocus(modalStack.front());
+ modalStack.pop_front();
+ }
+ }
+}
+
+void FocusHandler::remove(gcn::Widget *widget)
+{
+ releaseModalFocus(widget);
+
+ gcn::FocusHandler::remove(widget);
+}
diff --git a/src/gui/focushandler.h b/src/gui/focushandler.h
new file mode 100644
index 00000000..39eda8bb
--- /dev/null
+++ b/src/gui/focushandler.h
@@ -0,0 +1,64 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_FOCUSHANDLER_H
+#define _TMW_FOCUSHANDLER_H
+
+#include <guichan.hpp>
+
+/**
+ * The focus handler. This focus handler does exactly the same as the Guichan
+ * focus handler, but keeps a stack of modal widgets to be able to handle
+ * multiple modal focus requests.
+ */
+class FocusHandler : public gcn::FocusHandler
+{
+ public:
+ /**
+ * Sets modal focus to a widget. When there is already a modal widget
+ * then that widget loses modal focus and will regain it after this
+ * widget releases his modal focus.
+ */
+ void requestModalFocus(gcn::Widget *widget);
+
+ /**
+ * Releases modal focus of a widget. When this widget had modal focus
+ * and there are other widgets that had also requested modal focus,
+ * then modal focus will be transfered to the last of those.
+ */
+ void releaseModalFocus(gcn::Widget *widget);
+
+ /**
+ * Removes a widget from the focus handler. Also makes sure no dangling
+ * pointers remain in modal focus stack.
+ */
+ void remove(gcn::Widget *widget);
+
+ private:
+ /**
+ * Stack of widgets that have requested modal forcus.
+ */
+ std::list<gcn::Widget*> modalStack;
+};
+
+#endif
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index e3b5a0bb..73e77073 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -24,6 +24,7 @@
#include "gui.h"
#include "window.h"
#include "windowcontainer.h"
+#include "focushandler.h"
#include "../engine.h"
#include "../net/protocol.h"
#include "../main.h"
@@ -60,6 +61,10 @@ Gui::Gui(Graphics *graphics)
gcn::Image::setImageLoader(imageLoader);
+ // Set focus handler
+ delete mFocusHandler;
+ mFocusHandler = new FocusHandler();
+
// Initialize top GUI widget
guiTop = new WindowContainer();
guiTop->setDimension(gcn::Rectangle(0, 0, screen->w, screen->h));
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 1c8ccb34..057753d4 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -77,6 +77,7 @@ class Gui : public gcn::Gui, public gcn::MouseListener
#endif
gcn::ImageLoader *imageLoader; /**< For loading images */
gcn::ImageFont *guiFont; /**< The global GUI font */
+ gcn::FocusHandler *focusHandler; /**< The focus handler */
};
extern Gui *gui; /**< The GUI system */
diff --git a/src/gui/inttextbox.cpp b/src/gui/inttextbox.cpp
index e28040d2..16650799 100644
--- a/src/gui/inttextbox.cpp
+++ b/src/gui/inttextbox.cpp
@@ -23,13 +23,13 @@
#include "inttextbox.h"
-IntTextBox::IntTextBox()
- : value(0)
+IntTextBox::IntTextBox():
+ value(0)
{
}
-IntTextBox::IntTextBox(int i)
- : value(i)
+IntTextBox::IntTextBox(int i):
+ value(i)
{
}
@@ -72,5 +72,3 @@ void IntTextBox::setInt(int i)
setText(s.str());
setCaretPosition(s.str().length() + 1);
}
-
-
diff --git a/src/gui/inttextbox.h b/src/gui/inttextbox.h
index eda5ff78..c9eec49e 100644
--- a/src/gui/inttextbox.h
+++ b/src/gui/inttextbox.h
@@ -30,27 +30,45 @@
#include "textbox.h"
/**
- * IntTextBox
- * TextBox which only accepts numbers as input
+ * TextBox which only accepts numbers as input.
*/
class IntTextBox : public TextBox
{
- int min; //min value
- int max; //max value
-
- int value; //current value
-
- IntTextBox(const std::string&) { }
-
public:
+ /**
+ * Constructor.
+ */
IntTextBox();
- IntTextBox(int);
- void keyPress(const gcn::Key &);
+ /**
+ * Constructor, sets initial value.
+ */
+ IntTextBox(int value);
+
+ /**
+ * Sets the minimum and maximum values of the text box.
+ */
+ void setRange(int minimum, int maximum);
- void setRange(int, int);
+ /**
+ * Returns the value in the text box.
+ */
int getInt();
- void setInt(int);
+
+ /**
+ * Set the value of the text box to the specified value.
+ */
+ void setInt(int value);
+
+ /**
+ * Responds to key presses.
+ */
+ void keyPress(const gcn::Key &key);
+
+ private:
+ int min; /**< Minimum value */
+ int max; /**< Maximum value */
+ int value; /**< Current value */
};
#endif
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index 1245c977..980f8270 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -32,7 +32,6 @@ ImageRect Window::border;
Window::Window(const std::string& caption, bool modal, Window *parent):
gcn::Window(caption),
- prevModal(NULL),
parent(parent),
snapSize(8),
modal(modal),
@@ -85,9 +84,6 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
if (modal)
{
- gcn::FocusHandler *focusHandler = _getFocusHandler();
- prevModal = focusHandler->getModalFocused();
- focusHandler->releaseModalFocus(prevModal);
requestModalFocus();
}
}
@@ -114,16 +110,6 @@ Window::~Window()
config.removeListener("guialpha", this);
delete chrome;
-
- if (hasModalFocus())
- {
- releaseModalFocus();
- }
-
- if (prevModal)
- {
- prevModal->requestModalFocus();
- }
}
void Window::setWindowContainer(WindowContainer *wc)
diff --git a/src/gui/window.h b/src/gui/window.h
index c9fa1f12..95db2f4b 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -153,7 +153,6 @@ class Window : public gcn::Window, public ConfigListener
protected:
gcn::Container *chrome; /**< Contained container */
- gcn::Widget *prevModal; /**< Previous modal widget */
Window *parent; /**< The parent window */
int snapSize; /**< Snap distance to window edge */
bool modal; /**< Window is modal */
diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h
index b0596f33..c2cf59fd 100644
--- a/src/gui/windowcontainer.h
+++ b/src/gui/windowcontainer.h
@@ -53,6 +53,9 @@ class WindowContainer : public gcn::Container {
void scheduleDelete(gcn::Widget *widget);
protected:
+ /**
+ * List of widgets that are scheduled to be deleted.
+ */
std::list<gcn::Widget*> deathList;
};