summaryrefslogtreecommitdiff
path: root/src/gui/base
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2014-03-01 19:13:11 +0300
committerAndrei Karas <akaras@inbox.ru>2014-03-01 19:13:11 +0300
commita260aeab234704ace8ba672b1d1ce57e18425e07 (patch)
treee215c6eeeae7e6c2ca4f4453718cef6ca9a8af6a /src/gui/base
parent382067b05c4fe97bcf0da0143405375ec295f7c6 (diff)
parent2c62286a7ecf246e8a445dd7d00f618efae2a96a (diff)
downloadplus-a260aeab234704ace8ba672b1d1ce57e18425e07.tar.gz
plus-a260aeab234704ace8ba672b1d1ce57e18425e07.tar.bz2
plus-a260aeab234704ace8ba672b1d1ce57e18425e07.tar.xz
plus-a260aeab234704ace8ba672b1d1ce57e18425e07.zip
Merge branch 'master' into stable
Diffstat (limited to 'src/gui/base')
-rw-r--r--src/gui/base/basiccontainer.cpp384
-rw-r--r--src/gui/base/basiccontainer.hpp218
-rw-r--r--src/gui/base/gui.cpp763
-rw-r--r--src/gui/base/gui.hpp515
-rw-r--r--src/gui/base/widgets/button.cpp192
-rw-r--r--src/gui/base/widgets/button.hpp222
-rw-r--r--src/gui/base/widgets/checkbox.cpp151
-rw-r--r--src/gui/base/widgets/checkbox.hpp183
-rw-r--r--src/gui/base/widgets/container.cpp136
-rw-r--r--src/gui/base/widgets/container.hpp177
-rw-r--r--src/gui/base/widgets/label.cpp122
-rw-r--r--src/gui/base/widgets/label.hpp156
-rw-r--r--src/gui/base/widgets/listbox.cpp240
-rw-r--r--src/gui/base/widgets/listbox.hpp277
-rw-r--r--src/gui/base/widgets/radiobutton.cpp203
-rw-r--r--src/gui/base/widgets/radiobutton.hpp228
-rw-r--r--src/gui/base/widgets/scrollarea.cpp597
-rw-r--r--src/gui/base/widgets/scrollarea.hpp549
-rw-r--r--src/gui/base/widgets/slider.cpp230
-rw-r--r--src/gui/base/widgets/slider.hpp297
-rw-r--r--src/gui/base/widgets/textbox.cpp344
-rw-r--r--src/gui/base/widgets/textbox.hpp311
-rw-r--r--src/gui/base/widgets/textfield.cpp163
-rw-r--r--src/gui/base/widgets/textfield.hpp192
24 files changed, 6850 insertions, 0 deletions
diff --git a/src/gui/base/basiccontainer.cpp b/src/gui/base/basiccontainer.cpp
new file mode 100644
index 000000000..f323366ad
--- /dev/null
+++ b/src/gui/base/basiccontainer.cpp
@@ -0,0 +1,384 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/basiccontainer.hpp"
+
+#include <algorithm>
+
+#include "debug.h"
+
+namespace gcn
+{
+ BasicContainer::~BasicContainer()
+ {
+ clear();
+ }
+
+ void BasicContainer::moveToTop(Widget* widget)
+ {
+ for (WidgetListIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ if (*iter == widget)
+ {
+ mWidgets.erase(iter);
+ mWidgets.push_back(widget);
+ return;
+ }
+ }
+ }
+
+ void BasicContainer::moveToBottom(Widget* widget)
+ {
+ WidgetListIterator iter;
+ iter = std::find(mWidgets.begin(), mWidgets.end(), widget);
+
+ if (iter == mWidgets.end())
+ return;
+
+ mWidgets.erase(iter);
+ mWidgets.insert(mWidgets.begin(), widget);
+ }
+
+ void BasicContainer::death(const Event& event)
+ {
+ WidgetListIterator iter;
+ iter = std::find(mWidgets.begin(), mWidgets.end(), event.getSource());
+
+ if (iter == mWidgets.end())
+ return;
+
+ mWidgets.erase(iter);
+ }
+
+ Rect BasicContainer::getChildrenArea()
+ {
+ return Rect(0, 0, getWidth(), getHeight());
+ }
+
+ void BasicContainer::focusNext()
+ {
+ WidgetListConstIterator it;
+
+ for (it = mWidgets.begin(); it != mWidgets.end(); ++ it)
+ {
+ if ((*it)->isFocused())
+ break;
+ }
+
+ WidgetListConstIterator end = it;
+
+ if (it == mWidgets.end())
+ it = mWidgets.begin();
+
+ ++ it;
+
+ for ( ; it != end; ++ it)
+ {
+ if (it == mWidgets.end())
+ it = mWidgets.begin();
+
+ if ((*it)->isFocusable())
+ {
+ (*it)->requestFocus();
+ return;
+ }
+ }
+ }
+
+ void BasicContainer::focusPrevious()
+ {
+ WidgetListReverseIterator it;
+
+ for (it = mWidgets.rbegin(); it != mWidgets.rend(); ++ it)
+ {
+ if ((*it)->isFocused())
+ break;
+ }
+
+ const WidgetListReverseIterator end = it;
+
+ ++ it;
+
+ if (it == mWidgets.rend())
+ it = mWidgets.rbegin();
+
+ for ( ; it != end; ++ it)
+ {
+ if (it == mWidgets.rend())
+ it = mWidgets.rbegin();
+
+ if ((*it)->isFocusable())
+ {
+ (*it)->requestFocus();
+ return;
+ }
+ }
+ }
+
+ Widget *BasicContainer::getWidgetAt(int x, int y)
+ {
+ const Rect r = getChildrenArea();
+
+ if (!r.isPointInRect(x, y))
+ return nullptr;
+
+ x -= r.x;
+ y -= r.y;
+
+ for (WidgetListReverseIterator it = mWidgets.rbegin();
+ it != mWidgets.rend(); ++ it)
+ {
+ if ((*it)->isVisible() && (*it)->getDimension()
+ .isPointInRect(x, y))
+ {
+ return (*it);
+ }
+ }
+
+ return nullptr;
+ }
+
+ void BasicContainer::logic()
+ {
+ BLOCK_START("BasicContainer::logic")
+ logicChildren();
+ BLOCK_END("BasicContainer::logic")
+ }
+
+ void BasicContainer::_setFocusHandler(FocusHandler* focusHandler)
+ {
+ Widget::_setFocusHandler(focusHandler);
+
+ if (mInternalFocusHandler)
+ return;
+
+ for (WidgetListConstIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ (*iter)->_setFocusHandler(focusHandler);
+ }
+ }
+
+ void BasicContainer::add(Widget* widget)
+ {
+ mWidgets.push_back(widget);
+
+ if (!mInternalFocusHandler)
+ widget->_setFocusHandler(_getFocusHandler());
+ else
+ widget->_setFocusHandler(mInternalFocusHandler);
+
+ widget->_setParent(this);
+ widget->addDeathListener(this);
+ }
+
+ void BasicContainer::remove(Widget* widget)
+ {
+ for (WidgetListIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ if (*iter == widget)
+ {
+ mWidgets.erase(iter);
+ widget->_setFocusHandler(nullptr);
+ widget->_setParent(nullptr);
+ widget->removeDeathListener(this);
+ return;
+ }
+ }
+ }
+
+ void BasicContainer::clear()
+ {
+ for (WidgetListConstIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ (*iter)->_setFocusHandler(nullptr);
+ (*iter)->_setParent(nullptr);
+ (*iter)->removeDeathListener(this);
+ }
+
+ mWidgets.clear();
+ }
+
+ void BasicContainer::drawChildren(Graphics* graphics)
+ {
+ BLOCK_START("BasicContainer::drawChildren")
+
+ graphics->pushClipArea(getChildrenArea());
+
+ for (WidgetListConstIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ Widget *const widget = *iter;
+ if (widget->isVisible())
+ {
+ // If the widget has a frame,
+ // draw it before drawing the widget
+ if (widget->getFrameSize() > 0)
+ {
+ Rect rec = widget->getDimension();
+ const int frame = widget->getFrameSize();
+ const int frame2 = frame * 2;
+ rec.x -= frame;
+ rec.y -= frame;
+ rec.width += frame2;
+ rec.height += frame2;
+ graphics->pushClipArea(rec);
+ BLOCK_START("BasicContainer::drawChildren 1")
+ widget->drawFrame(graphics);
+ BLOCK_END("BasicContainer::drawChildren 1")
+ graphics->popClipArea();
+ }
+
+ graphics->pushClipArea(widget->getDimension());
+ BLOCK_START("BasicContainer::drawChildren 2")
+ widget->draw(graphics);
+ BLOCK_END("BasicContainer::drawChildren 2")
+ graphics->popClipArea();
+ }
+ }
+
+ graphics->popClipArea();
+ BLOCK_END("BasicContainer::drawChildren")
+ }
+
+ void BasicContainer::logicChildren()
+ {
+ BLOCK_START("BasicContainer::logicChildren")
+ for (WidgetListConstIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ (*iter)->logic();
+ }
+ BLOCK_END("BasicContainer::logicChildren")
+ }
+
+ void BasicContainer::showWidgetPart(Widget* widget, Rect area)
+ {
+ const Rect widgetArea = getChildrenArea();
+
+ area.x += widget->getX();
+ area.y += widget->getY();
+
+ if (area.x + area.width > widgetArea.width)
+ {
+ widget->setX(widget->getX() - area.x
+ - area.width + widgetArea.width);
+ }
+
+ if (area.y + area.height > widgetArea.height)
+ {
+ widget->setY(widget->getY() - area.y
+ - area.height + widgetArea.height);
+ }
+
+ if (area.x < 0)
+ widget->setX(widget->getX() - area.x);
+
+ if (area.y < 0)
+ widget->setY(widget->getY() - area.y);
+ }
+
+ void BasicContainer::setInternalFocusHandler(FocusHandler* focusHandler)
+ {
+ Widget::setInternalFocusHandler(focusHandler);
+
+ for (WidgetListConstIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ if (!mInternalFocusHandler)
+ (*iter)->_setFocusHandler(_getFocusHandler());
+ else
+ (*iter)->_setFocusHandler(mInternalFocusHandler);
+ }
+ }
+
+ Widget* BasicContainer::findWidgetById(const std::string& id)
+ {
+ for (WidgetListConstIterator iter = mWidgets.begin();
+ iter != mWidgets.end(); ++ iter)
+ {
+ if ((*iter)->getId() == id)
+ return (*iter);
+
+ BasicContainer *const basicContainer
+ = dynamic_cast<BasicContainer *const>(*iter);
+
+ if (basicContainer)
+ {
+ Widget *const widget = basicContainer->findWidgetById(id);
+
+ if (widget)
+ return widget;
+ }
+ }
+
+ return nullptr;
+ }
+} // namespace gcn
diff --git a/src/gui/base/basiccontainer.hpp b/src/gui/base/basiccontainer.hpp
new file mode 100644
index 000000000..e1947c652
--- /dev/null
+++ b/src/gui/base/basiccontainer.hpp
@@ -0,0 +1,218 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_BASICCONTAINER_HPP
+#define GCN_BASICCONTAINER_HPP
+
+#include <vector>
+
+#include "gui/widgets/widget.h"
+
+#include "listeners/deathlistener.h"
+
+namespace gcn
+{
+ /**
+ * A base class for containers. The class implements the most
+ * common things for a container. If you are implementing a
+ * container, consider inheriting from this class.
+ *
+ * @see Container
+ * @since 0.6.0
+ */
+ class BasicContainer : public Widget,
+ public DeathListener
+ {
+ public:
+ explicit BasicContainer(const Widget2 *const widget) :
+ Widget(widget),
+ DeathListener(),
+ mWidgets()
+ { }
+
+ A_DELETE_COPY(BasicContainer)
+
+ /**
+ * Destructor
+ */
+ virtual ~BasicContainer();
+
+ /**
+ * Shows a certain part of a widget in the basic container.
+ * Used when widgets want a specific part to be visible in
+ * its parent. An example is a TextArea that wants a specific
+ * part of its text to be visible when a TextArea is a child
+ * of a ScrollArea.
+ *
+ * @param widget The widget whom wants a specific part of
+ * itself to be visible.
+ * @param rectangle The rectangle to be visible.
+ */
+ virtual void showWidgetPart(Widget* widget, Rect area);
+
+ // Inherited from Widget
+
+ virtual void moveToTop(Widget* widget);
+
+ virtual void moveToBottom(Widget* widget);
+
+ virtual Rect getChildrenArea() A_WARN_UNUSED;
+
+ virtual void focusNext();
+
+ virtual void focusPrevious();
+
+ virtual void logic();
+
+ virtual void _setFocusHandler(FocusHandler* focusHandler);
+
+ void setInternalFocusHandler(FocusHandler* focusHandler);
+
+ virtual Widget *getWidgetAt(int x, int y) A_WARN_UNUSED;
+
+
+ // Inherited from DeathListener
+
+ virtual void death(const Event& event);
+
+ protected:
+ /**
+ * Adds a widget to the basic container.
+ *
+ * @param widget The widget to add.
+ * @see remove, clear
+ */
+ void add(Widget* widget);
+
+ /**
+ * Removes a widget from the basic container.
+ *
+ * @param widget The widget to remove.
+ * @see add, clear
+ */
+ virtual void remove(Widget* widget);
+
+ /**
+ * Clears the basic container from all widgets.
+ *
+ * @see remove, clear
+ */
+ virtual void clear();
+
+ /**
+ * Draws the children widgets of the basic container.
+ *
+ * @param graphics A graphics object to draw with.
+ */
+ virtual void drawChildren(Graphics* graphics);
+
+ /**
+ * Calls logic for the children widgets of the basic
+ * container.
+ */
+ virtual void logicChildren();
+
+ /**
+ * Finds a widget given an id. This function can be useful
+ * when implementing a GUI generator for Guichan, such as
+ * the ability to create a Guichan GUI from an XML file.
+ *
+ * @param id The id to find a widget by.
+ * @return The widget with the corrosponding id,
+ NULL of no widget is found.
+ */
+ virtual Widget* findWidgetById(const std::string& id) A_WARN_UNUSED;
+
+ /**
+ * Typedef.
+ */
+ typedef std::vector<Widget *> WidgetList;
+
+ /**
+ * Typedef.
+ */
+ typedef WidgetList::iterator WidgetListIterator;
+
+ /**
+ * Typedef.
+ */
+ typedef WidgetList::const_iterator WidgetListConstIterator;
+
+ /**
+ * Typedef.
+ */
+ typedef WidgetList::reverse_iterator WidgetListReverseIterator;
+
+ /**
+ * Typedef.
+ */
+ typedef WidgetList::const_reverse_iterator WidgetListCReverseIterator;
+
+ /**
+ * Holds all widgets of the basic container.
+ */
+ WidgetList mWidgets;
+ };
+} // namespace gcn
+
+#endif // end GCN_BASICCONTAINER_HPP
diff --git a/src/gui/base/gui.cpp b/src/gui/base/gui.cpp
new file mode 100644
index 000000000..8985ec062
--- /dev/null
+++ b/src/gui/base/gui.cpp
@@ -0,0 +1,763 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/gui.hpp"
+
+#include "gui/widgets/widget.h"
+
+#include "gui/focushandler.h"
+
+#include "input/mouseinput.h"
+
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+#include "debug.h"
+
+namespace gcn
+{
+ Gui::Gui() :
+ mTop(nullptr),
+ mGraphics(nullptr),
+ mInput(nullptr),
+ mFocusHandler(new FocusHandler),
+ mTabbing(true),
+ mKeyListeners(),
+ mShiftPressed(false),
+ mMetaPressed(false),
+ mControlPressed(false),
+ mAltPressed(false),
+ mLastMousePressButton(0),
+ mLastMousePressTimeStamp(0),
+ mLastMouseX(0),
+ mLastMouseY(0),
+ mClickCount(1),
+ mLastMouseDragButton(0),
+ mWidgetWithMouseQueue()
+ {
+ }
+
+ Gui::~Gui()
+ {
+ if (Widget::widgetExists(mTop))
+ setTop(nullptr);
+
+ delete mFocusHandler;
+ mFocusHandler = nullptr;
+ }
+
+ void Gui::setTop(Widget* top)
+ {
+ if (mTop)
+ mTop->_setFocusHandler(nullptr);
+ if (top)
+ top->_setFocusHandler(mFocusHandler);
+
+ mTop = top;
+ }
+
+ Widget* Gui::getTop() const
+ {
+ return mTop;
+ }
+
+ void Gui::setGraphics(Graphics* graphics)
+ {
+ mGraphics = graphics;
+ }
+
+ Graphics* Gui::getGraphics() const
+ {
+ return mGraphics;
+ }
+
+ void Gui::setInput(SDLInput* input)
+ {
+ mInput = input;
+ }
+
+ SDLInput* Gui::getInput() const
+ {
+ return mInput;
+ }
+
+ void Gui::logic()
+ {
+ }
+
+ void Gui::draw()
+ {
+ }
+
+ void Gui::focusNone()
+ {
+ mFocusHandler->focusNone();
+ }
+
+ void Gui::setTabbingEnabled(bool tabbing)
+ {
+ mTabbing = tabbing;
+ }
+
+ bool Gui::isTabbingEnabled()
+ {
+ return mTabbing;
+ }
+
+ void Gui::addGlobalKeyListener(KeyListener* keyListener)
+ {
+ mKeyListeners.push_back(keyListener);
+ }
+
+ void Gui::removeGlobalKeyListener(KeyListener* keyListener)
+ {
+ mKeyListeners.remove(keyListener);
+ }
+
+ void Gui::handleMouseInput()
+ {
+ }
+
+ void Gui::handleKeyInput()
+ {
+ }
+
+ void Gui::handleMouseMoved(const MouseInput& mouseInput)
+ {
+ // Check if the mouse leaves the application window.
+ if (!mWidgetWithMouseQueue.empty() && (mouseInput.getX() < 0
+ || mouseInput.getY() < 0 || !mTop->getDimension().isPointInRect(
+ mouseInput.getX(), mouseInput.getY())))
+ {
+ // Distribute an event to all widgets in the
+ // "widget with mouse" queue.
+ while (!mWidgetWithMouseQueue.empty())
+ {
+ Widget *const widget = mWidgetWithMouseQueue.front();
+
+ if (Widget::widgetExists(widget))
+ {
+ distributeMouseEvent(widget,
+ MouseEvent::EXITED,
+ mouseInput.getButton(),
+ mouseInput.getX(),
+ mouseInput.getY(),
+ true,
+ true);
+ }
+
+ mWidgetWithMouseQueue.pop_front();
+ }
+
+ return;
+ }
+
+ // Check if there is a need to send mouse exited events by
+ // traversing the "widget with mouse" queue.
+ bool widgetWithMouseQueueCheckDone = mWidgetWithMouseQueue.empty();
+ while (!widgetWithMouseQueueCheckDone)
+ {
+ unsigned int iterations = 0;
+ for (std::deque<Widget*>::iterator
+ iter = mWidgetWithMouseQueue.begin();
+ iter != mWidgetWithMouseQueue.end();
+ ++ iter)
+ {
+ Widget *const widget = *iter;
+
+ // If a widget in the "widget with mouse queue" doesn't
+ // exists anymore it should be removed from the queue.
+ if (!Widget::widgetExists(widget))
+ {
+ mWidgetWithMouseQueue.erase(iter);
+ break;
+ }
+ else
+ {
+ int x, y;
+ widget->getAbsolutePosition(x, y);
+
+ if (x > mouseInput.getX()
+ || y > mouseInput.getY()
+ || x + widget->getWidth() <= mouseInput.getX()
+ || y + widget->getHeight() <= mouseInput.getY()
+ || !widget->isVisible())
+ {
+ distributeMouseEvent(widget,
+ MouseEvent::EXITED,
+ mouseInput.getButton(),
+ mouseInput.getX(),
+ mouseInput.getY(),
+ true,
+ true);
+ mClickCount = 1;
+ mLastMousePressTimeStamp = 0;
+ mWidgetWithMouseQueue.erase(iter);
+ break;
+ }
+ }
+
+ iterations++;
+ }
+
+ widgetWithMouseQueueCheckDone =
+ (iterations == mWidgetWithMouseQueue.size());
+ }
+
+ // Check all widgets below the mouse to see if they are
+ // present in the "widget with mouse" queue. If a widget
+ // is not then it should be added and an entered event should
+ // be sent to it.
+ Widget* parent = getMouseEventSource(
+ mouseInput.getX(), mouseInput.getY());
+ Widget* widget = parent;
+
+ // If a widget has modal mouse input focus then it will
+ // always be returned from getMouseEventSource, but we only wan't to
+ // send mouse entered events if the mouse has actually entered the
+ // widget with modal mouse input focus, hence we need to check if
+ // that's the case. If it's not we should simply ignore to send any
+ // mouse entered events.
+ if (mFocusHandler->getModalMouseInputFocused()
+ && widget == mFocusHandler->getModalMouseInputFocused()
+ && Widget::widgetExists(widget))
+ {
+ int x, y;
+ widget->getAbsolutePosition(x, y);
+
+ if (x > mouseInput.getX() || y > mouseInput.getY()
+ || x + widget->getWidth() <= mouseInput.getX()
+ || y + widget->getHeight() <= mouseInput.getY())
+ {
+ parent = nullptr;
+ }
+ }
+
+ while (parent)
+ {
+ parent = widget->getParent();
+
+ // Check if the widget is present in the "widget with mouse" queue.
+ bool widgetIsPresentInQueue = false;
+ FOR_EACH (std::deque<Widget*>::const_iterator,
+ iter, mWidgetWithMouseQueue)
+ {
+ if (*iter == widget)
+ {
+ widgetIsPresentInQueue = true;
+ break;
+ }
+ }
+
+ // Widget is not present, send an entered event and add
+ // it to the "widget with mouse" queue.
+ if (!widgetIsPresentInQueue
+ && Widget::widgetExists(widget))
+ {
+ distributeMouseEvent(widget,
+ MouseEvent::ENTERED,
+ mouseInput.getButton(),
+ mouseInput.getX(),
+ mouseInput.getY(),
+ true,
+ true);
+ mWidgetWithMouseQueue.push_front(widget);
+ }
+
+ const Widget *const swap = widget;
+ widget = parent;
+ parent = swap->getParent();
+ }
+
+ if (mFocusHandler->getDraggedWidget())
+ {
+ distributeMouseEvent(mFocusHandler->getDraggedWidget(),
+ MouseEvent::DRAGGED,
+ mLastMouseDragButton,
+ mouseInput.getX(),
+ mouseInput.getY());
+ }
+ else
+ {
+ Widget *const sourceWidget = getMouseEventSource(
+ mouseInput.getX(), mouseInput.getY());
+
+ distributeMouseEvent(sourceWidget,
+ MouseEvent::MOVED,
+ mouseInput.getButton(),
+ mouseInput.getX(),
+ mouseInput.getY());
+ }
+ }
+
+ void Gui::handleMouseWheelMovedDown(const MouseInput& mouseInput)
+ {
+ Widget* sourceWidget = getMouseEventSource(
+ mouseInput.getX(), mouseInput.getY());
+
+ if (mFocusHandler->getDraggedWidget())
+ sourceWidget = mFocusHandler->getDraggedWidget();
+
+ int sourceWidgetX, sourceWidgetY;
+ sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
+
+ distributeMouseEvent(sourceWidget,
+ MouseEvent::WHEEL_MOVED_DOWN,
+ mouseInput.getButton(),
+ mouseInput.getX(),
+ mouseInput.getY());
+ }
+
+ void Gui::handleMouseWheelMovedUp(const MouseInput& mouseInput)
+ {
+ Widget* sourceWidget = getMouseEventSource(
+ mouseInput.getX(), mouseInput.getY());
+
+ if (mFocusHandler->getDraggedWidget())
+ sourceWidget = mFocusHandler->getDraggedWidget();
+
+ int sourceWidgetX, sourceWidgetY;
+ sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
+
+ distributeMouseEvent(sourceWidget,
+ MouseEvent::WHEEL_MOVED_UP,
+ mouseInput.getButton(),
+ mouseInput.getX(),
+ mouseInput.getY());
+ }
+
+ Widget* Gui::getWidgetAt(int x, int y)
+ {
+ // If the widget's parent has no child then we have found the widget..
+ Widget* parent = mTop;
+ Widget* child = mTop;
+
+ while (child)
+ {
+ Widget *const swap = child;
+ int parentX, parentY;
+ parent->getAbsolutePosition(parentX, parentY);
+ child = parent->getWidgetAt(x - parentX, y - parentY);
+ parent = swap;
+ }
+
+ return parent;
+ }
+
+ Widget* Gui::getMouseEventSource(int x, int y)
+ {
+ Widget *const widget = getWidgetAt(x, y);
+
+ // +++ possible nullpointer
+ if (mFocusHandler->getModalMouseInputFocused()
+ && !widget->isModalMouseInputFocused())
+ {
+ return mFocusHandler->getModalMouseInputFocused();
+ }
+
+ return widget;
+ }
+
+ Widget* Gui::getKeyEventSource()
+ {
+ Widget* widget = mFocusHandler->getFocused();
+
+ // +++ possible nullpointer
+ while (widget->_getInternalFocusHandler()
+ && widget->_getInternalFocusHandler()->getFocused())
+ {
+ widget = widget->_getInternalFocusHandler()->getFocused();
+ }
+
+ return widget;
+ }
+
+ void Gui::distributeMouseEvent(Widget* source,
+ int type,
+ int button,
+ int x,
+ int y,
+ bool force,
+ bool toSourceOnly)
+ {
+ Widget* parent = source;
+ Widget* widget = source;
+
+ if (mFocusHandler->getModalFocused()
+ && !widget->isModalFocused()
+ && !force)
+ {
+ return;
+ }
+
+ if (mFocusHandler->getModalMouseInputFocused()
+ && !widget->isModalMouseInputFocused()
+ && !force)
+ {
+ return;
+ }
+
+ MouseEvent mouseEvent(source,
+ mShiftPressed,
+ mControlPressed,
+ mAltPressed,
+ mMetaPressed,
+ type,
+ button,
+ x,
+ y,
+ mClickCount);
+
+ while (parent)
+ {
+ // If the widget has been removed due to input
+ // cancel the distribution.
+ if (!Widget::widgetExists(widget))
+ break;
+
+ parent = widget->getParent();
+
+ if (widget->isEnabled() || force)
+ {
+ int widgetX, widgetY;
+ widget->getAbsolutePosition(widgetX, widgetY);
+
+ mouseEvent.mX = x - widgetX;
+ mouseEvent.mY = y - widgetY;
+
+ std::list<MouseListener*> mouseListeners
+ = widget->_getMouseListeners();
+
+ // Send the event to all mouse listeners of the widget.
+ for (std::list<MouseListener*>::const_iterator
+ it = mouseListeners.begin();
+ it != mouseListeners.end();
+ ++it)
+ {
+ switch (mouseEvent.getType())
+ {
+ case MouseEvent::ENTERED:
+ (*it)->mouseEntered(mouseEvent);
+ break;
+ case MouseEvent::EXITED:
+ (*it)->mouseExited(mouseEvent);
+ break;
+ case MouseEvent::MOVED:
+ (*it)->mouseMoved(mouseEvent);
+ break;
+ case MouseEvent::PRESSED:
+ (*it)->mousePressed(mouseEvent);
+ break;
+ case MouseEvent::RELEASED:
+ (*it)->mouseReleased(mouseEvent);
+ break;
+ case MouseEvent::WHEEL_MOVED_UP:
+ (*it)->mouseWheelMovedUp(mouseEvent);
+ break;
+ case MouseEvent::WHEEL_MOVED_DOWN:
+ (*it)->mouseWheelMovedDown(mouseEvent);
+ break;
+ case MouseEvent::DRAGGED:
+ (*it)->mouseDragged(mouseEvent);
+ break;
+ case MouseEvent::CLICKED:
+ (*it)->mouseClicked(mouseEvent);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (toSourceOnly)
+ break;
+ }
+
+ const Widget *const swap = widget;
+ widget = parent;
+ parent = swap->getParent();
+
+ // If a non modal focused widget has been reach
+ // and we have modal focus cancel the distribution.
+ if (mFocusHandler->getModalFocused()
+ && !widget->isModalFocused())
+ {
+ break;
+ }
+
+ // If a non modal mouse input focused widget has been reach
+ // and we have modal mouse input focus cancel the distribution.
+ if (mFocusHandler->getModalMouseInputFocused()
+ && !widget->isModalMouseInputFocused())
+ {
+ break;
+ }
+ }
+ }
+
+ void Gui::distributeKeyEvent(KeyEvent& keyEvent)
+ {
+ Widget* parent = keyEvent.getSource();
+ Widget* widget = keyEvent.getSource();
+
+ if (mFocusHandler->getModalFocused()
+ && !widget->isModalFocused())
+ {
+ return;
+ }
+
+ if (mFocusHandler->getModalMouseInputFocused()
+ && !widget->isModalMouseInputFocused())
+ {
+ return;
+ }
+
+ while (parent)
+ {
+ // If the widget has been removed due to input
+ // cancel the distribution.
+ if (!Widget::widgetExists(widget))
+ break;
+
+ parent = widget->getParent();
+
+ if (widget->isEnabled())
+ {
+ std::list<KeyListener*> keyListeners
+ = widget->_getKeyListeners();
+
+ // Send the event to all key listeners of the source widget.
+ for (std::list<KeyListener*>::const_iterator
+ it = keyListeners.begin();
+ it != keyListeners.end();
+ ++it)
+ {
+ switch (keyEvent.getType())
+ {
+ case KeyEvent::PRESSED:
+ (*it)->keyPressed(keyEvent);
+ break;
+ case KeyEvent::RELEASED:
+ (*it)->keyReleased(keyEvent);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ const Widget *const swap = widget;
+ widget = parent;
+ parent = swap->getParent();
+
+ // If a non modal focused widget has been reach
+ // and we have modal focus cancel the distribution.
+ if (mFocusHandler->getModalFocused()
+ && !widget->isModalFocused())
+ {
+ break;
+ }
+ }
+ }
+
+ void Gui::distributeKeyEventToGlobalKeyListeners(KeyEvent& keyEvent)
+ {
+ for (KeyListenerListIterator it = mKeyListeners.begin();
+ it != mKeyListeners.end(); ++ it)
+ {
+ switch (keyEvent.getType())
+ {
+ case KeyEvent::PRESSED:
+ (*it)->keyPressed(keyEvent);
+ break;
+ case KeyEvent::RELEASED:
+ (*it)->keyReleased(keyEvent);
+ break;
+ default:
+ break;
+ }
+
+ if (keyEvent.isConsumed())
+ break;
+ }
+ }
+
+ void Gui::handleModalMouseInputFocus()
+ {
+ BLOCK_START("Gui::handleModalMouseInputFocus")
+ // Check if modal mouse input focus has been gained by a widget.
+ if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus()
+ != mFocusHandler->getModalMouseInputFocused())
+ && (!mFocusHandler->getLastWidgetWithModalMouseInputFocus()))
+ {
+ handleModalFocusGained();
+ mFocusHandler->setLastWidgetWithModalMouseInputFocus(
+ mFocusHandler->getModalMouseInputFocused());
+ }
+ // Check if modal mouse input focus has been released.
+ else if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus()
+ != mFocusHandler->getModalMouseInputFocused())
+ && (mFocusHandler->getLastWidgetWithModalMouseInputFocus()))
+ {
+ handleModalFocusReleased();
+ mFocusHandler->setLastWidgetWithModalMouseInputFocus(nullptr);
+ }
+ BLOCK_END("Gui::handleModalMouseInputFocus")
+ }
+
+ void Gui::handleModalFocus()
+ {
+ BLOCK_START("Gui::handleModalFocus")
+ // Check if modal focus has been gained by a widget.
+ if ((mFocusHandler->getLastWidgetWithModalFocus()
+ != mFocusHandler->getModalFocused())
+ && (!mFocusHandler->getLastWidgetWithModalFocus()))
+ {
+ handleModalFocusGained();
+ mFocusHandler->setLastWidgetWithModalFocus(
+ mFocusHandler->getModalFocused());
+ }
+ // Check if modal focus has been released.
+ else if ((mFocusHandler->getLastWidgetWithModalFocus()
+ != mFocusHandler->getModalFocused())
+ && (mFocusHandler->getLastWidgetWithModalFocus()))
+ {
+ handleModalFocusReleased();
+ mFocusHandler->setLastWidgetWithModalFocus(nullptr);
+ }
+ BLOCK_END("Gui::handleModalFocus")
+ }
+
+ void Gui::handleModalFocusGained()
+ {
+ // Distribute an event to all widgets in the "widget with mouse" queue.
+ while (!mWidgetWithMouseQueue.empty())
+ {
+ Widget *const widget = mWidgetWithMouseQueue.front();
+
+ if (Widget::widgetExists(widget))
+ {
+ distributeMouseEvent(widget,
+ MouseEvent::EXITED,
+ mLastMousePressButton,
+ mLastMouseX,
+ mLastMouseY,
+ true,
+ true);
+ }
+
+ mWidgetWithMouseQueue.pop_front();
+ }
+
+ mFocusHandler->setLastWidgetWithModalMouseInputFocus(
+ mFocusHandler->getModalMouseInputFocused());
+ }
+
+ void Gui::handleModalFocusReleased()
+ {
+ // Check all widgets below the mouse to see if they are
+ // present in the "widget with mouse" queue. If a widget
+ // is not then it should be added and an entered event should
+ // be sent to it.
+ Widget* widget = getMouseEventSource(mLastMouseX, mLastMouseY);
+ Widget* parent = widget;
+
+ while (parent)
+ {
+ parent = widget->getParent();
+
+ // Check if the widget is present in the "widget with mouse" queue.
+ bool widgetIsPresentInQueue = false;
+ FOR_EACH (std::deque<Widget*>::const_iterator,
+ iter, mWidgetWithMouseQueue)
+ {
+ if (*iter == widget)
+ {
+ widgetIsPresentInQueue = true;
+ break;
+ }
+ }
+
+ // Widget is not present, send an entered event and add
+ // it to the "widget with mouse" queue.
+ if (!widgetIsPresentInQueue && Widget::widgetExists(widget))
+ {
+ distributeMouseEvent(widget,
+ MouseEvent::ENTERED,
+ mLastMousePressButton,
+ mLastMouseX,
+ mLastMouseY,
+ false,
+ true);
+ mWidgetWithMouseQueue.push_front(widget);
+ }
+
+ const Widget *const swap = widget;
+ widget = parent;
+ parent = swap->getParent();
+ }
+ }
+} // namespace gcn
diff --git a/src/gui/base/gui.hpp b/src/gui/base/gui.hpp
new file mode 100644
index 000000000..4ea923400
--- /dev/null
+++ b/src/gui/base/gui.hpp
@@ -0,0 +1,515 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_GUI_HPP
+#define GCN_GUI_HPP
+
+#include <list>
+#include <deque>
+
+#include "localconsts.h"
+
+class Event;
+class FocusHandler;
+class Graphics;
+class KeyEvent;
+class KeyListener;
+class MouseInput;
+class SDLInput;
+class Widget;
+
+namespace gcn
+{
+ // The following comment will appear in the doxygen main page.
+ /**
+ * @mainpage
+ * @section Introduction
+ * This documentation is mostly intended as a reference to the API.
+ * If you want to get started with Guichan, we suggest you check out
+ * the programs in the examples directory of the Guichan release.
+ * @n
+ * @n
+ * This documentation is, and will always be, work in progress.
+ * If you find any errors, typos or inconsistencies, or if you feel
+ * something needs to be explained in more detail - don't hesitate to
+ * tell us.
+ */
+
+ /**
+ * Contains a Guichan GUI. This is the core class of Guichan to which
+ * implementations of back ends are passed, to make Guichan work with
+ * a specific library, and to where the top widget (root widget of GUI)
+ * is added. If you want to be able to have more then one widget in your
+ * GUI, the top widget should be a container.
+ *
+ * A Gui object cannot work properly without passing back end
+ * implementations to it. A Gui object must have an implementation of a
+ * Graphics and an implementation of Input.
+ *
+ * NOTE: A complete GUI also must have the ability to load images.
+ * Images are loaded with the Image class, so to make Guichan
+ * able to load images an implementation of ImageLoader must be
+ * passed to Image.
+ *
+ * @see Graphics, Input, Image
+ */
+ class Gui
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ Gui();
+
+ A_DELETE_COPY(Gui)
+
+ /**
+ * Destructor.
+ */
+ virtual ~Gui();
+
+ /**
+ * Sets the top widget. The top widget is the root widget
+ * of the GUI. If you want a GUI to be able to contain more
+ * than one widget the top widget should be a container.
+ *
+ * @param top The top widget.
+ * @see Container
+ * @since 0.1.0
+ */
+ virtual void setTop(Widget* top);
+
+ /**
+ * Gets the top widget. The top widget is the root widget
+ * of the GUI.
+ *
+ * @return The top widget. NULL if no top widget has been set.
+ * @since 0.1.0
+ */
+ virtual Widget* getTop() const A_WARN_UNUSED;
+
+ /**
+ * Sets the graphics object to use for drawing.
+ *
+ * @param graphics The graphics object to use for drawing.
+ * @see getGraphics, AllegroGraphics, HGEGraphics,
+ * OpenLayerGraphics, OpenGLGraphics, SDLGraphics
+ * @since 0.1.0
+ */
+ virtual void setGraphics(Graphics* graphics);
+
+ /**
+ * Gets the graphics object used for drawing.
+ *
+ * @return The graphics object used for drawing. NULL if no
+ * graphics object has been set.
+ * @see setGraphics, AllegroGraphics, HGEGraphics,
+ * OpenLayerGraphics, OpenGLGraphics, SDLGraphics
+ * @since 0.1.0
+ */
+ virtual Graphics* getGraphics() const A_WARN_UNUSED;
+
+ /**
+ * Sets the input object to use for input handling.
+ *
+ * @param input The input object to use for input handling.
+ * @see getInput, AllegroInput, HGEInput, OpenLayerInput,
+ * SDLInput
+ * @since 0.1.0
+ */
+ virtual void setInput(SDLInput* input);
+
+ /**
+ * Gets the input object being used for input handling.
+ *
+ * @return The input object used for handling input. NULL if no
+ * input object has been set.
+ * @see setInput, AllegroInput, HGEInput, OpenLayerInput,
+ * SDLInput
+ * @since 0.1.0
+ */
+ virtual SDLInput* getInput() const A_WARN_UNUSED;
+
+ /**
+ * Performs logic of the GUI. By calling this function all logic
+ * functions down in the GUI heirarchy will be called. When logic
+ * is called for Gui, user input will be handled.
+ *
+ * @see Widget::logic
+ * @since 0.1.0
+ */
+ virtual void logic();
+
+ /**
+ * Draws the GUI. By calling this funcion all draw functions
+ * down in the GUI hierarchy will be called. When draw is called
+ * the used Graphics object will be initialised and drawing of
+ * the top widget will commence.
+ *
+ * @see Widget::draw
+ * @since 0.1.0
+ */
+ virtual void draw();
+
+ /**
+ * Focuses none of the widgets in the Gui.
+ *
+ * @since 0.1.0
+ */
+ virtual void focusNone();
+
+ /**
+ * Sets tabbing enabled, or not. Tabbing is the usage of
+ * changing focus by utilising the tab key.
+ *
+ * @param tabbing True if tabbing should be enabled, false
+ * otherwise.
+ * @see isTabbingEnabled
+ * @since 0.1.0
+ */
+ virtual void setTabbingEnabled(bool tabbing);
+
+ /**
+ * Checks if tabbing is enabled.
+ *
+ * @return True if tabbing is enabled, false otherwise.
+ * @see setTabbingEnabled
+ * @since 0.1.0
+ */
+ virtual bool isTabbingEnabled();
+
+ /**
+ * Adds a global key listener to the Gui. A global key listener
+ * will receive all key events generated from the GUI and global
+ * key listeners will receive the events before key listeners
+ * of widgets.
+ *
+ * @param keyListener The key listener to add.
+ * @see removeGlobalKeyListener
+ * @since 0.5.0
+ */
+ virtual void addGlobalKeyListener(KeyListener* keyListener);
+
+ /**
+ * Removes global key listener from the Gui.
+ *
+ * @param keyListener The key listener to remove.
+ * @throws Exception if the key listener hasn't been added.
+ * @see addGlobalKeyListener
+ * @since 0.5.0
+ */
+ virtual void removeGlobalKeyListener(KeyListener* keyListener);
+
+ protected:
+ /**
+ * Handles all mouse input.
+ *
+ * @since 0.6.0
+ */
+ virtual void handleMouseInput();
+
+ /**
+ * Handles key input.
+ *
+ * @since 0.6.0
+ */
+ virtual void handleKeyInput();
+
+ /**
+ * Handles mouse moved input.
+ *
+ * @param mouseInput The mouse input to handle.
+ * @since 0.6.0
+ */
+ virtual void handleMouseMoved(const MouseInput& mouseInput);
+
+ /**
+ *
+ * Handles mouse wheel moved down input.
+ *
+ * @param mouseInput The mouse input to handle.
+ * @since 0.6.0
+ */
+ virtual void handleMouseWheelMovedDown(const MouseInput& mouseInput);
+
+ /**
+ * Handles mouse wheel moved up input.
+ *
+ * @param mouseInput The mouse input to handle.
+ * @since 0.6.0
+ */
+ virtual void handleMouseWheelMovedUp(const MouseInput& mouseInput);
+
+ /**
+ * Handles modal focus. Modal focus needs to be checked at
+ * each logic iteration as it might be necessary to distribute
+ * mouse entered or mouse exited events.
+ *
+ * @since 0.8.0
+ */
+ virtual void handleModalFocus();
+
+ /**
+ * Handles modal mouse input focus. Modal mouse input focus needs
+ * to be checked at each logic iteration as it might be necessary to
+ * distribute mouse entered or mouse exited events.
+ *
+ * @since 0.8.0
+ */
+ virtual void handleModalMouseInputFocus();
+
+ /**
+ * Handles modal focus gained. If modal focus has been gained it might
+ * be necessary to distribute mouse entered or mouse exited events.
+ *
+ * @since 0.8.0
+ */
+ virtual void handleModalFocusGained();
+
+ /**
+ * Handles modal mouse input focus gained. If modal focus has been
+ * gained it might be necessary to distribute mouse entered or mouse
+ * exited events.
+ *
+ * @since 0.8.0
+ */
+ virtual void handleModalFocusReleased();
+
+ /**
+ * Distributes a mouse event.
+ *
+ * @param type The type of the event to distribute,
+ * @param button The button of the event (if any used) to distribute.
+ * @param x The x coordinate of the event.
+ * @param y The y coordinate of the event.
+ * @param fource indicates whether the distribution should be forced or not.
+ * A forced distribution distributes the event even if a widget
+ * is not enabled, not visible, another widget has modal
+ * focus or another widget has modal mouse input focus.
+ * Default value is false.
+ * @param toSourceOnly indicates whether the distribution should be to the
+ * source widget only or to it's parent's mouse listeners
+ * as well.
+ *
+ * @since 0.6.0
+ */
+ virtual void distributeMouseEvent(Widget* source,
+ int type,
+ int button,
+ int x,
+ int y,
+ bool force = false,
+ bool toSourceOnly = false);
+
+ /**
+ * Distributes a key event.
+ *
+ * @param keyEvent The key event to distribute.
+
+ * @since 0.6.0
+ */
+ virtual void distributeKeyEvent(KeyEvent& keyEvent);
+
+ /**
+ * Distributes a key event to the global key listeners.
+ *
+ * @param keyEvent The key event to distribute.
+ *
+ * @since 0.6.0
+ */
+ virtual void distributeKeyEventToGlobalKeyListeners(KeyEvent&
+ keyEvent);
+
+ /**
+ * Gets the widget at a certain position.
+ *
+ * @return The widget at a certain position.
+ * @since 0.6.0
+ */
+ virtual Widget* getWidgetAt(int x, int y) A_WARN_UNUSED;
+
+ /**
+ * Gets the source of the mouse event.
+ *
+ * @return The source widget of the mouse event.
+ * @since 0.6.0
+ */
+ virtual Widget* getMouseEventSource(int x, int y) A_WARN_UNUSED;
+
+ /**
+ * Gets the source of the key event.
+ *
+ * @return The source widget of the key event.
+ * @since 0.6.0
+ */
+ virtual Widget* getKeyEventSource() A_WARN_UNUSED;
+
+ /**
+ * Holds the top widget.
+ */
+ Widget* mTop;
+
+ /**
+ * Holds the graphics implementation used.
+ */
+ Graphics* mGraphics;
+
+ /**
+ * Holds the input implementation used.
+ */
+ SDLInput* mInput;
+
+ /**
+ * Holds the focus handler for the Gui.
+ */
+ FocusHandler* mFocusHandler;
+
+ /**
+ * True if tabbing is enabled, false otherwise.
+ */
+ bool mTabbing;
+
+ /**
+ * Typedef.
+ */
+ typedef std::list<KeyListener*> KeyListenerList;
+
+ /**
+ * Typedef.
+ */
+ typedef KeyListenerList::iterator KeyListenerListIterator;
+
+ /**
+ * Holds the global key listeners of the Gui.
+ */
+ KeyListenerList mKeyListeners;
+
+ /**
+ * True if shift is pressed, false otherwise.
+ */
+ bool mShiftPressed;
+
+ /**
+ * True if meta is pressed, false otherwise.
+ */
+ bool mMetaPressed;
+
+ /**
+ * True if control is pressed, false otherwise.
+ */
+ bool mControlPressed;
+
+ /**
+ * True if alt is pressed, false otherwise.
+ */
+ bool mAltPressed;
+
+ /**
+ * Holds the last mouse button pressed.
+ */
+ unsigned int mLastMousePressButton;
+
+ /**
+ * Holds the last mouse press time stamp.
+ */
+ int mLastMousePressTimeStamp;
+
+ /**
+ * Holds the last mouse x coordinate.
+ */
+ int mLastMouseX;
+
+ /**
+ * Holds the last mouse y coordinate.
+ */
+ int mLastMouseY;
+
+ /**
+ * Holds the current click count. Used to keep track
+ * of clicks for a the last pressed button.
+ */
+ int mClickCount;
+
+ /**
+ * Holds the last button used when a drag of a widget
+ * was initiated. Used to be able to release a drag
+ * when the same button is released.
+ */
+ int mLastMouseDragButton;
+
+ /**
+ * Holds a stack with all the widgets with the mouse.
+ * Used to properly distribute mouse events.
+ */
+ std::deque<Widget*> mWidgetWithMouseQueue;
+ };
+} // namespace gcn
+
+#endif // end GCN_GUI_HPP
+
+/* yakslem - "Women, it's a constant struggle."
+ * finalman - "Yes, but sometimes they succeed with their guesses."
+ * yaklsem - "...eh...I was talking about love."
+ * finalman - "Oh...ok..."
+ * An awkward silence followed.
+ */
diff --git a/src/gui/base/widgets/button.cpp b/src/gui/base/widgets/button.cpp
new file mode 100644
index 000000000..2d6afa672
--- /dev/null
+++ b/src/gui/base/widgets/button.cpp
@@ -0,0 +1,192 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/button.hpp"
+
+#include "events/mouseevent.h"
+
+#include "render/graphics.h"
+
+#include "debug.h"
+
+namespace gcn
+{
+ Button::Button(const Widget2 *const widget) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ FocusListener(),
+ mCaption(),
+ mHasMouse(false),
+ mKeyPressed(false),
+ mMousePressed(false),
+ mAlignment(Graphics::CENTER),
+ mSpacing(4)
+ {
+ setFocusable(true);
+ adjustSize();
+ setFrameSize(1);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ addFocusListener(this);
+ }
+
+ Button::Button(const Widget2 *const widget,
+ const std::string& caption) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ FocusListener(),
+ mCaption(caption),
+ mHasMouse(false),
+ mKeyPressed(false),
+ mMousePressed(false),
+ mAlignment(Graphics::CENTER),
+ mSpacing(4)
+ {
+ setFocusable(true);
+ adjustSize();
+ setFrameSize(1);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ addFocusListener(this);
+ }
+
+ void Button::setCaption(const std::string& caption)
+ {
+ mCaption = caption;
+ }
+
+ const std::string& Button::getCaption() const
+ {
+ return mCaption;
+ }
+
+ void Button::setAlignment(Graphics::Alignment alignment)
+ {
+ mAlignment = alignment;
+ }
+
+ Graphics::Alignment Button::getAlignment() const
+ {
+ return mAlignment;
+ }
+
+ void Button::setSpacing(unsigned int spacing)
+ {
+ mSpacing = spacing;
+ }
+
+ unsigned int Button::getSpacing() const
+ {
+ return mSpacing;
+ }
+
+ void Button::adjustSize()
+ {
+ }
+
+ bool Button::isPressed() const
+ {
+ if (mMousePressed)
+ return mHasMouse;
+ else
+ return mKeyPressed;
+ }
+
+ void Button::mousePressed(MouseEvent& mouseEvent)
+ {
+ if (mouseEvent.getButton() == MouseEvent::LEFT)
+ {
+ mMousePressed = true;
+ mouseEvent.consume();
+ }
+ }
+
+ void Button::mouseExited(MouseEvent& mouseEvent A_UNUSED)
+ {
+ mHasMouse = false;
+ }
+
+ void Button::mouseEntered(MouseEvent& mouseEvent A_UNUSED)
+ {
+ mHasMouse = true;
+ }
+
+ void Button::mouseDragged(MouseEvent& mouseEvent)
+ {
+ mouseEvent.consume();
+ }
+
+ void Button::focusLost(const Event& event A_UNUSED)
+ {
+ mMousePressed = false;
+ mKeyPressed = false;
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/button.hpp b/src/gui/base/widgets/button.hpp
new file mode 100644
index 000000000..99e5db4f4
--- /dev/null
+++ b/src/gui/base/widgets/button.hpp
@@ -0,0 +1,222 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_BUTTON_HPP
+#define GCN_BUTTON_HPP
+
+#include <string>
+
+#include "listeners/focuslistener.h"
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+#include "gui/widgets/widget.h"
+
+#include "render/graphics.h"
+
+namespace gcn
+{
+ /**
+ * An implementation of a regular clickable button. A button is capable of
+ * displaying a caption.
+ *
+ * If a button is clicked an action event will be sent to all action listener's
+ * of the button.
+ *
+ * @see ImageButton
+ */
+ class Button : public Widget,
+ public MouseListener,
+ public KeyListener,
+ public FocusListener
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ explicit Button(const Widget2 *const widget);
+
+ /**
+ * Constructor. The button will be automatically resized
+ * to fit the caption.
+ *
+ * @param caption The caption of the button.
+ */
+ Button(const Widget2 *const widget,
+ const std::string& caption);
+
+ A_DELETE_COPY(Button)
+
+ /**
+ * Sets the caption of the button. It's advisable to call
+ * adjustSize after setting of the caption to adjust the
+ * button's size to fit the caption.
+ *
+ * @param caption The caption of the button.
+ * @see getCaption, adjustSize
+ */
+ void setCaption(const std::string& caption);
+
+ /**
+ * Gets the caption of the button.
+ *
+ * @return The caption of the button.
+ */
+ const std::string& getCaption() const;
+
+ /**
+ * Sets the alignment of the caption. The alignment is relative
+ * to the center of the button.
+ *
+ * @param alignment The alignment of the caption.
+ * @see getAlignment, Graphics
+ */
+ void setAlignment(Graphics::Alignment alignment);
+
+ /**
+ * Gets the alignment of the caption.
+ *
+ * @return The alignment of the caption.
+ * @see setAlignment, Graphics
+ */
+ Graphics::Alignment getAlignment() const;
+
+ /**
+ * Sets the spacing between the border of the button and its caption.
+ *
+ * @param spacing The default value for spacing is 4 and can be changed
+ * using this method.
+ * @see getSpacing
+ */
+ void setSpacing(unsigned int spacing);
+
+ /**
+ * Gets the spacing between the border of the button and its caption.
+ *
+ * @return spacing.
+ * @see setSpacing
+ */
+ unsigned int getSpacing() const;
+
+ /**
+ * Adjusts the button's size to fit the caption.
+ */
+ void adjustSize();
+
+
+ // Inherited from FocusListener
+
+ virtual void focusLost(const Event& event);
+
+ // Inherited from MouseListener
+
+ virtual void mousePressed(MouseEvent& mouseEvent) override;
+
+ virtual void mouseEntered(MouseEvent& mouseEvent) override;
+
+ virtual void mouseExited(MouseEvent& mouseEvent) override;
+
+ virtual void mouseDragged(MouseEvent& mouseEvent) override;
+
+ protected:
+ /**
+ * Checks if the button is pressed. Convenient method to use
+ * when overloading the draw method of the button.
+ *
+ * @return True if the button is pressed, false otherwise.
+ */
+ bool isPressed() const;
+
+ /**
+ * Holds the caption of the button.
+ */
+ std::string mCaption;
+
+ /**
+ * True if the mouse is ontop of the button, false otherwise.
+ */
+ bool mHasMouse;
+
+ /**
+ * True if a key has been pressed, false otherwise.
+ */
+ bool mKeyPressed;
+
+ /**
+ * True if a mouse has been pressed, false otherwise.
+ */
+ bool mMousePressed;
+
+ /**
+ * Holds the alignment of the caption.
+ */
+ Graphics::Alignment mAlignment;
+
+ /**
+ * Holds the spacing between the border and the caption.
+ */
+ unsigned int mSpacing;
+ };
+} // namespace gcn
+
+#endif // end GCN_BUTTON_HPP
diff --git a/src/gui/base/widgets/checkbox.cpp b/src/gui/base/widgets/checkbox.cpp
new file mode 100644
index 000000000..476fb3c6b
--- /dev/null
+++ b/src/gui/base/widgets/checkbox.cpp
@@ -0,0 +1,151 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/checkbox.hpp"
+
+#include "debug.h"
+
+namespace gcn
+{
+
+ CheckBox::CheckBox(const Widget2 *const widget) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mSelected(false),
+ mCaption()
+ {
+ setFocusable(true);
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ CheckBox::CheckBox(const Widget2 *const widget,
+ const std::string &caption,
+ bool selected) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mSelected(selected),
+ mCaption()
+ {
+ setCaption(caption);
+
+ setFocusable(true);
+ addMouseListener(this);
+ addKeyListener(this);
+
+ adjustSize();
+ }
+
+ bool CheckBox::isSelected() const
+ {
+ return mSelected;
+ }
+
+ void CheckBox::setSelected(bool selected)
+ {
+ mSelected = selected;
+ }
+
+ const std::string &CheckBox::getCaption() const
+ {
+ return mCaption;
+ }
+
+ void CheckBox::setCaption(const std::string& caption)
+ {
+ mCaption = caption;
+ }
+
+ void CheckBox::keyPressed(KeyEvent& keyEvent A_UNUSED)
+ {
+ }
+
+ void CheckBox::mouseClicked(MouseEvent& mouseEvent)
+ {
+ if (mouseEvent.getButton() == MouseEvent::LEFT)
+ {
+ toggleSelected();
+ }
+ }
+
+ void CheckBox::mouseDragged(MouseEvent& mouseEvent)
+ {
+ mouseEvent.consume();
+ }
+
+ void CheckBox::adjustSize()
+ {
+ }
+
+ void CheckBox::toggleSelected()
+ {
+ mSelected = !mSelected;
+ distributeActionEvent();
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/checkbox.hpp b/src/gui/base/widgets/checkbox.hpp
new file mode 100644
index 000000000..6fcb04767
--- /dev/null
+++ b/src/gui/base/widgets/checkbox.hpp
@@ -0,0 +1,183 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_CHECKBOX_HPP
+#define GCN_CHECKBOX_HPP
+
+#include <string>
+
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+#include "gui/widgets/widget.h"
+
+namespace gcn
+{
+ /**
+ * An implementation of a check box where a user can select or deselect
+ * the check box and where the status of the check box is displayed to the user.
+ * A check box is capable of displaying a caption.
+ *
+ * If a check box's state changes an action event will be sent to all action
+ * listeners of the check box.
+ */
+ class CheckBox :
+ public Widget,
+ public MouseListener,
+ public KeyListener
+ {
+ public:
+ /**
+ * Contructor.
+ */
+ explicit CheckBox(const Widget2 *const widget);
+
+ /**
+ * Constructor. The check box will be automatically resized
+ * to fit the caption.
+ *
+ * @param caption The caption of the check box.
+ * @param marked True if the check box is selected, false otherwise.
+ */
+ CheckBox(const Widget2 *const widget,
+ const std::string &caption,
+ bool selected = false);
+
+ A_DELETE_COPY(CheckBox)
+
+ /**
+ * Destructor.
+ */
+ virtual ~CheckBox()
+ { }
+
+ /**
+ * Checks if the check box is selected.
+ *
+ * @return True if the check box is selected, false otherwise.
+ * @see setSelected
+ */
+ bool isSelected() const;
+
+ /**
+ * Sets the check box to be selected or not.
+ *
+ * @param selected True if the check box should be set as selected.
+ * @see isSelected
+ */
+ void setSelected(bool selected);
+
+ /**
+ * Gets the caption of the check box.
+ *
+ * @return The caption of the check box.
+ * @see setCaption
+ */
+ const std::string &getCaption() const;
+
+ /**
+ * Sets the caption of the check box. It's advisable to call
+ * adjustSize after setting of the caption to adjust the
+ * check box's size to fit the caption.
+ *
+ * @param caption The caption of the check box.
+ * @see getCaption, adjustSize
+ */
+ void setCaption(const std::string& caption);
+
+ /**
+ * Adjusts the check box's size to fit the caption.
+ */
+ void adjustSize();
+
+ // Inherited from KeyListener
+
+ virtual void keyPressed(KeyEvent& keyEvent) override;
+
+ // Inherited from MouseListener
+
+ virtual void mouseClicked(MouseEvent& mouseEvent) override;
+
+ virtual void mouseDragged(MouseEvent& mouseEvent) override;
+
+
+ protected:
+ /**
+ * Toggles the check box between being selected and
+ * not being selected.
+ */
+ virtual void toggleSelected();
+
+ /**
+ * True if the check box is selected, false otherwise.
+ */
+ bool mSelected;
+
+ /**
+ * Holds the caption of the check box.
+ */
+ std::string mCaption;
+ };
+} // namespace gcn
+
+#endif // end GCN_CHECKBOX_HPP
diff --git a/src/gui/base/widgets/container.cpp b/src/gui/base/widgets/container.cpp
new file mode 100644
index 000000000..53a900ec4
--- /dev/null
+++ b/src/gui/base/widgets/container.cpp
@@ -0,0 +1,136 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/container.hpp"
+
+
+#include "render/graphics.h"
+
+#include "debug.h"
+
+namespace gcn
+{
+
+ Container::Container(const Widget2 *const widget) :
+ BasicContainer(widget),
+ mOpaque(true)
+ {
+ }
+
+ Container::~Container()
+ {
+ }
+
+ void Container::draw(Graphics* graphics)
+ {
+ BLOCK_START("Container::draw")
+ if (isOpaque())
+ {
+ graphics->setColor(getBaseColor());
+ graphics->fillRectangle(Rect(0, 0, getWidth(), getHeight()));
+ }
+
+ drawChildren(graphics);
+ BLOCK_END("Container::draw")
+ }
+
+ void Container::setOpaque(bool opaque)
+ {
+ mOpaque = opaque;
+ }
+
+ bool Container::isOpaque() const
+ {
+ return mOpaque;
+ }
+
+ void Container::add(Widget* widget)
+ {
+ BasicContainer::add(widget);
+ }
+
+ void Container::add(Widget* widget, int x, int y)
+ {
+ widget->setPosition(x, y);
+ BasicContainer::add(widget);
+ }
+
+ void Container::remove(Widget* widget)
+ {
+ BasicContainer::remove(widget);
+ }
+
+ void Container::clear()
+ {
+ BasicContainer::clear();
+ }
+
+ Widget* Container::findWidgetById(const std::string &id)
+ {
+ return BasicContainer::findWidgetById(id);
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/container.hpp b/src/gui/base/widgets/container.hpp
new file mode 100644
index 000000000..3e6c0a587
--- /dev/null
+++ b/src/gui/base/widgets/container.hpp
@@ -0,0 +1,177 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_CONTAINER_HPP
+#define GCN_CONTAINER_HPP
+
+#include "gui/base/basiccontainer.hpp"
+
+namespace gcn
+{
+ /**
+ * An implementation of a container able to contain other widgets. A widget's
+ * position in the container is relative to the container itself and not the screen.
+ * A container is the most common widget to use as the Gui's top widget as makes the Gui
+ * able to contain more than one widget.
+ *
+ * @see Gui::setTop
+ */
+ class Container: public BasicContainer
+ {
+ public:
+ /**
+ * Constructor. A container is opauqe as default, if you want a
+ * none opaque container call setQpaque(false).
+ *
+ * @see setOpaque, isOpaque
+ */
+ explicit Container(const Widget2 *const widget);
+
+ /**
+ * Destructor.
+ */
+ virtual ~Container();
+
+ /**
+ * Sets the container to be opaque or not. If the container
+ * is opaque its background will be drawn, if it's not opaque
+ * its background will not be drawn, and thus making the container
+ * completely transparent.
+ *
+ * NOTE: This is not the same as to set visibility. A non visible
+ * container will not itself nor will it draw its content.
+ *
+ * @param opaque True if the container should be opaque, false otherwise.
+ * @see isOpaque
+ */
+ void setOpaque(bool opaque);
+
+ /**
+ * Checks if the container is opaque or not.
+ *
+ * @return True if the container is opaque, false otherwise.
+ * @see setOpaque
+ */
+ bool isOpaque() const;
+
+ /**
+ * Adds a widget to the container.
+ *
+ * @param widget The widget to add.
+ * @see remove, clear
+ */
+ virtual void add(Widget* widget);
+
+ /**
+ * Adds a widget to the container and also specifies the widget's
+ * position in the container. The position is relative to the container
+ * and not relative to the screen.
+ *
+ * @param widget The widget to add.
+ * @param x The x coordinate for the widget.
+ * @param y The y coordinate for the widget.
+ * @see remove, clear
+ */
+ virtual void add(Widget* widget, int x, int y);
+
+ /**
+ * Removes a widget from the Container.
+ *
+ * @param widget The widget to remove.
+ * @throws Exception when the widget has not been added to the
+ * container.
+ * @see add, clear
+ */
+ virtual void remove(Widget* widget);
+
+ /**
+ * Clears the container of all widgets.
+ *
+ * @see add, remove
+ */
+ virtual void clear();
+
+ /**
+ * Finds a widget given an id.
+ *
+ * @param id The id to find a widget by.
+ * @return A widget with a corrosponding id, NULL if no widget
+ * is found.
+ * @see Widget::setId
+ */
+ virtual Widget* findWidgetById(const std::string &id);
+
+
+ // Inherited from Widget
+
+ virtual void draw(Graphics* graphics);
+
+ protected:
+ /**
+ * True if the container is opaque, false otherwise.
+ */
+ bool mOpaque;
+ };
+} // namespace gcn
+
+#endif // end GCN_CONTAINER_HPP
diff --git a/src/gui/base/widgets/label.cpp b/src/gui/base/widgets/label.cpp
new file mode 100644
index 000000000..d2293a957
--- /dev/null
+++ b/src/gui/base/widgets/label.cpp
@@ -0,0 +1,122 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/label.hpp"
+
+#include "gui/font.h"
+
+#include "render/graphics.h"
+
+#include "debug.h"
+
+namespace gcn
+{
+ Label::Label(const Widget2 *const widget) :
+ Widget(widget),
+ mCaption(),
+ mAlignment(Graphics::LEFT)
+ {
+ }
+
+ Label::Label(const Widget2 *const widget,
+ const std::string& caption) :
+ Widget(widget),
+ mCaption(caption),
+ mAlignment(Graphics::LEFT)
+ {
+ setWidth(getFont()->getWidth(caption));
+ setHeight(getFont()->getHeight());
+ }
+
+ const std::string &Label::getCaption() const
+ {
+ return mCaption;
+ }
+
+ void Label::setCaption(const std::string& caption)
+ {
+ mCaption = caption;
+ }
+
+ void Label::setAlignment(Graphics::Alignment alignment)
+ {
+ mAlignment = alignment;
+ }
+
+ Graphics::Alignment Label::getAlignment() const
+ {
+ return mAlignment;
+ }
+
+ void Label::draw(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void Label::adjustSize()
+ {
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/label.hpp b/src/gui/base/widgets/label.hpp
new file mode 100644
index 000000000..fd0d54f8e
--- /dev/null
+++ b/src/gui/base/widgets/label.hpp
@@ -0,0 +1,156 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_LABEL_HPP
+#define GCN_LABEL_HPP
+
+#include <string>
+
+#include "gui/widgets/widget.h"
+
+#include "render/graphics.h"
+
+namespace gcn
+{
+ /**
+ * Implementation of a label capable of displaying a caption.
+ */
+ class Label: public Widget
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ explicit Label(const Widget2 *const widget);
+
+ /**
+ * Constructor. The label will be automatically resized
+ * to fit the caption.
+ *
+ * @param caption The caption of the label.
+ */
+ Label(const Widget2 *const widget,
+ const std::string& caption);
+
+ A_DELETE_COPY(Label)
+
+ /**
+ * Gets the caption of the label.
+ *
+ * @return The caption of the label.
+ * @see setCaption
+ */
+ const std::string &getCaption() const;
+
+ /**
+ * Sets the caption of the label. It's advisable to call
+ * adjustSize after setting of the caption to adjust the
+ * label's size to fit the caption.
+ *
+ * @param caption The caption of the label.
+ * @see getCaption, adjustSize
+ */
+ void setCaption(const std::string& caption);
+
+ /**
+ * Sets the alignment of the caption. The alignment is relative
+ * to the center of the label.
+ *
+ * @param alignemnt The alignment of the caption of the label.
+ * @see getAlignment, Graphics
+ */
+ void setAlignment(Graphics::Alignment alignment);
+
+ /**
+ * Gets the alignment of the caption. The alignment is relative to
+ * the center of the label.
+ *
+ * @return The alignment of caption of the label.
+ * @see setAlignmentm Graphics
+ */
+ Graphics::Alignment getAlignment() const;
+
+ /**
+ * Adjusts the label's size to fit the caption.
+ */
+ void adjustSize();
+
+
+ // Inherited from Widget
+
+ virtual void draw(Graphics* graphics);
+
+ protected:
+ /**
+ * Holds the caption of the label.
+ */
+ std::string mCaption;
+
+ /**
+ * Holds the alignment of the caption.
+ */
+ Graphics::Alignment mAlignment;
+ };
+} // namespace gcn
+
+#endif // end GCN_LABEL_HPP
diff --git a/src/gui/base/widgets/listbox.cpp b/src/gui/base/widgets/listbox.cpp
new file mode 100644
index 000000000..2e9606f0a
--- /dev/null
+++ b/src/gui/base/widgets/listbox.cpp
@@ -0,0 +1,240 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/listbox.hpp"
+
+#include "gui/font.h"
+
+#include "gui/models/listmodel.h"
+
+#include "listeners/selectionlistener.h"
+
+#include "debug.h"
+
+namespace gcn
+{
+ ListBox::ListBox(const Widget2 *const widget) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mSelected(-1),
+ mListModel(nullptr),
+ mWrappingEnabled(false),
+ mSelectionListeners()
+ {
+ setWidth(100);
+ setFocusable(true);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ ListBox::ListBox(const Widget2 *const widget,
+ ListModel *listModel) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mSelected(-1),
+ mListModel(listModel),
+ mWrappingEnabled(false),
+ mSelectionListeners()
+ {
+ setWidth(100);
+ adjustSize();
+ setFocusable(true);
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ void ListBox::draw(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ListBox::logic()
+ {
+ }
+
+ int ListBox::getSelected() const
+ {
+ return mSelected;
+ }
+
+ void ListBox::setSelected(int selected)
+ {
+ if (!mListModel)
+ {
+ mSelected = -1;
+ }
+ else
+ {
+ if (selected < 0)
+ mSelected = -1;
+ else if (selected >= mListModel->getNumberOfElements())
+ mSelected = mListModel->getNumberOfElements() - 1;
+ else
+ mSelected = selected;
+ }
+
+ Rect scroll;
+
+ if (mSelected < 0)
+ scroll.y = 0;
+ else
+ scroll.y = getRowHeight() * mSelected;
+
+ scroll.height = getRowHeight();
+ showPart(scroll);
+
+ distributeValueChangedEvent();
+ }
+
+ void ListBox::keyPressed(KeyEvent &keyEvent A_UNUSED)
+ {
+ }
+
+ void ListBox::mousePressed(MouseEvent &mouseEvent A_UNUSED)
+ {
+ }
+
+ void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
+ {
+ if (isFocused())
+ {
+ if (getSelected() > 0 )
+ setSelected(getSelected() - 1);
+
+ mouseEvent.consume();
+ }
+ }
+
+ void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
+ {
+ if (isFocused())
+ {
+ setSelected(getSelected() + 1);
+
+ mouseEvent.consume();
+ }
+ }
+
+ void ListBox::mouseDragged(MouseEvent& mouseEvent)
+ {
+ mouseEvent.consume();
+ }
+
+ void ListBox::setListModel(ListModel *listModel)
+ {
+ mSelected = -1;
+ mListModel = listModel;
+ adjustSize();
+ }
+
+ ListModel* ListBox::getListModel()
+ {
+ return mListModel;
+ }
+
+ void ListBox::adjustSize()
+ {
+ }
+
+ bool ListBox::isWrappingEnabled() const
+ {
+ return mWrappingEnabled;
+ }
+
+ void ListBox::setWrappingEnabled(bool wrappingEnabled)
+ {
+ mWrappingEnabled = wrappingEnabled;
+ }
+
+ void ListBox::addSelectionListener(SelectionListener* selectionListener)
+ {
+ mSelectionListeners.push_back(selectionListener);
+ }
+
+ void ListBox::removeSelectionListener(SelectionListener* selectionListener)
+ {
+ mSelectionListeners.remove(selectionListener);
+ }
+
+ void ListBox::distributeValueChangedEvent()
+ {
+ for (SelectionListenerIterator iter = mSelectionListeners.begin();
+ iter != mSelectionListeners.end();
+ ++ iter)
+ {
+ SelectionEvent event(this);
+ (*iter)->valueChanged(event);
+ }
+ }
+
+ unsigned int ListBox::getRowHeight() const
+ {
+ return getFont()->getHeight();
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/listbox.hpp b/src/gui/base/widgets/listbox.hpp
new file mode 100644
index 000000000..079e5a7d5
--- /dev/null
+++ b/src/gui/base/widgets/listbox.hpp
@@ -0,0 +1,277 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_LISTBOX_HPP
+#define GCN_LISTBOX_HPP
+
+#include <list>
+
+#include "gui/widgets/widget.h"
+
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+class ListModel;
+class SelectionListener;
+
+namespace gcn
+{
+ /**
+ * An implementation of a list box where an item can be selected.
+ *
+ * To be able display a list the list box uses a user provided list model.
+ * A list model can be any class that implements the ListModel interface.
+ *
+ * If an item is selected in the list box a select event will be sent to
+ * all selection listeners of the list box. If an item is selected by using
+ * a mouse click or by using the enter or space key an action event will be
+ * sent to all action listeners of the list box.
+ */
+ class ListBox :
+ public Widget,
+ public MouseListener,
+ public KeyListener
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ explicit ListBox(const Widget2 *const widget);
+
+ /**
+ * Constructor.
+ *
+ * @param listModel the list model to use.
+ */
+ ListBox(const Widget2 *const widget,
+ ListModel *listModel);
+
+ A_DELETE_COPY(ListBox)
+
+ /**
+ * Destructor.
+ */
+ virtual ~ListBox()
+ { }
+
+ /**
+ * Gets the selected item as an index in the list model.
+ *
+ * @return the selected item as an index in the list model.
+ * @see setSelected
+ */
+ int getSelected() const;
+
+ /**
+ * Sets the selected item. The selected item is represented by
+ * an index from the list model.
+ *
+ * @param selected the selected item as an index from the list model.
+ * @see getSelected
+ */
+ void setSelected(int selected);
+
+ /**
+ * Sets the list model to use.
+ *
+ * @param listModel the list model to use.
+ * @see getListModel
+ */
+ void setListModel(ListModel *listModel);
+
+ /**
+ * Gets the list model used.
+ *
+ * @return the list model used.
+ * @see setListModel
+ */
+ ListModel *getListModel();
+
+ /**
+ * Adjusts the size of the list box to fit it's list model.
+ */
+ void adjustSize();
+
+ /**
+ * Checks whether the list box wraps when selecting items with a
+ * keyboard.
+ *
+ * Wrapping means that the selection of items will be wrapped. That is,
+ * if the first item is selected and up is pressed, the last item will
+ * get selected. If the last item is selected and down is pressed, the
+ * first item will get selected.
+ *
+ * @return true if wrapping is enabled, fasle otherwise.
+ * @see setWrappingEnabled
+ */
+ bool isWrappingEnabled() const;
+
+ /**
+ * Sets the list box to wrap or not when selecting items with a
+ * keyboard.
+ *
+ * Wrapping means that the selection of items will be wrapped. That is,
+ * if the first item is selected and up is pressed, the last item will
+ * get selected. If the last item is selected and down is pressed, the
+ * first item will get selected.
+ *
+ * @see isWrappingEnabled
+ */
+ void setWrappingEnabled(bool wrappingEnabled);
+
+ /**
+ * Adds a selection listener to the list box. When the selection
+ * changes an event will be sent to all selection listeners of the
+ * list box.
+ *
+ * If you delete your selection listener, be sure to also remove it
+ * using removeSelectionListener().
+ *
+ * @param selectionListener The selection listener to add.
+ * @since 0.8.0
+ */
+ void addSelectionListener(SelectionListener* selectionListener);
+
+ /**
+ * Removes a selection listener from the list box.
+ *
+ * @param selectionListener The selection listener to remove.
+ * @since 0.8.0
+ */
+ void removeSelectionListener(SelectionListener* selectionListener);
+
+ /**
+ * Gets the height of a row. Should be overridden if another row
+ * height than the font height is preferred.
+ *
+ * @return The height of a row.
+ * @since 0.8.0
+ */
+ virtual unsigned int getRowHeight() const;
+
+
+ // Inherited from Widget
+
+ virtual void draw(Graphics* graphics);
+
+ virtual void logic();
+
+
+ // Inherited from KeyListener
+
+ virtual void keyPressed(KeyEvent& keyEvent) override;
+
+
+ // Inherited from MouseListener
+
+ virtual void mousePressed(MouseEvent& mouseEvent) override;
+
+ virtual void mouseWheelMovedUp(MouseEvent& mouseEvent) override;
+
+ virtual void mouseWheelMovedDown(MouseEvent& mouseEvent) override;
+
+ virtual void mouseDragged(MouseEvent& mouseEvent) override;
+
+
+ protected:
+ /**
+ * Distributes a value changed event to all selection listeners
+ * of the list box.
+ *
+ * @since 0.8.0
+ */
+ void distributeValueChangedEvent();
+
+ /**
+ * The selected item as an index in the list model.
+ */
+ int mSelected;
+
+ /**
+ * The list model to use.
+ */
+ ListModel *mListModel;
+
+ /**
+ * True if wrapping is enabled, false otherwise.
+ */
+ bool mWrappingEnabled;
+
+ /**
+ * Typdef.
+ */
+ typedef std::list<SelectionListener*> SelectionListenerList;
+
+ /**
+ * The selection listeners of the list box.
+ */
+ SelectionListenerList mSelectionListeners;
+
+ /**
+ * Typedef.
+ */
+ typedef SelectionListenerList::iterator SelectionListenerIterator;
+ };
+} // namespace gcn
+
+#endif // end GCN_LISTBOX_HPP
diff --git a/src/gui/base/widgets/radiobutton.cpp b/src/gui/base/widgets/radiobutton.cpp
new file mode 100644
index 000000000..f9d68555a
--- /dev/null
+++ b/src/gui/base/widgets/radiobutton.cpp
@@ -0,0 +1,203 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/radiobutton.hpp"
+
+#include "debug.h"
+
+namespace gcn
+{
+ RadioButton::GroupMap RadioButton::mGroupMap;
+
+ RadioButton::RadioButton(const Widget2 *const widget) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mSelected(false),
+ mCaption(),
+ mGroup()
+ {
+ setSelected(false);
+
+ setFocusable(true);
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ RadioButton::RadioButton(const Widget2 *const widget,
+ const std::string &caption,
+ const std::string &group,
+ bool selected) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mSelected(false),
+ mCaption(),
+ mGroup()
+ {
+ setCaption(caption);
+ setGroup(group);
+ setSelected(selected);
+
+ setFocusable(true);
+ addMouseListener(this);
+ addKeyListener(this);
+
+ adjustSize();
+ }
+
+ RadioButton::~RadioButton()
+ {
+ // Remove us from the group list
+ setGroup("");
+ }
+
+ bool RadioButton::isSelected() const
+ {
+ return mSelected;
+ }
+
+ void RadioButton::setSelected(bool selected)
+ {
+ if (selected && mGroup != "")
+ {
+ for (GroupIterator iter = mGroupMap.lower_bound(mGroup),
+ iterEnd = mGroupMap.upper_bound(mGroup);
+ iter != iterEnd;
+ ++ iter)
+ {
+ if (iter->second->isSelected())
+ iter->second->setSelected(false);
+ }
+ }
+
+ mSelected = selected;
+ }
+
+ const std::string &RadioButton::getCaption() const
+ {
+ return mCaption;
+ }
+
+ void RadioButton::setCaption(const std::string &caption)
+ {
+ mCaption = caption;
+ }
+
+ void RadioButton::keyPressed(KeyEvent& keyEvent A_UNUSED)
+ {
+ }
+
+ void RadioButton::mouseClicked(MouseEvent& mouseEvent)
+ {
+ if (mouseEvent.getButton() == MouseEvent::LEFT)
+ {
+ setSelected(true);
+ distributeActionEvent();
+ }
+ }
+
+ void RadioButton::mouseDragged(MouseEvent& mouseEvent)
+ {
+ mouseEvent.consume();
+ }
+
+ void RadioButton::setGroup(const std::string &group)
+ {
+ if (mGroup != "")
+ {
+ for (GroupIterator iter = mGroupMap.lower_bound(mGroup),
+ iterEnd = mGroupMap.upper_bound(mGroup);
+ iter != iterEnd;
+ ++ iter)
+ {
+ if (iter->second == this)
+ {
+ mGroupMap.erase(iter);
+ break;
+ }
+ }
+ }
+
+ if (group != "")
+ {
+ mGroupMap.insert(
+ std::pair<std::string, RadioButton *>(group, this));
+ }
+
+ mGroup = group;
+ }
+
+ const std::string &RadioButton::getGroup() const
+ {
+ return mGroup;
+ }
+
+ void RadioButton::adjustSize()
+ {
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/radiobutton.hpp b/src/gui/base/widgets/radiobutton.hpp
new file mode 100644
index 000000000..a86a4eed3
--- /dev/null
+++ b/src/gui/base/widgets/radiobutton.hpp
@@ -0,0 +1,228 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_RADIOBUTTON_HPP
+#define GCN_RADIOBUTTON_HPP
+
+#include <map>
+#include <string>
+
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+#include "gui/widgets/widget.h"
+
+namespace gcn
+{
+ /**
+ * An implementation of a radio button where a user can select or deselect
+ * the radio button and where the status of the radio button is displayed to the user.
+ * A radio button can belong to a group and when a radio button belongs to a
+ * group only one radio button can be selected in the group. A radio button is
+ * capable of displaying a caption.
+ *
+ * If a radio button's state changes an action event will be sent to all action
+ * listeners of the check box.
+ */
+ class RadioButton :
+ public Widget,
+ public MouseListener,
+ public KeyListener
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ explicit RadioButton(const Widget2 *const widget);
+
+ /**
+ * Constructor. The radio button will be automatically resized
+ * to fit the caption.
+ *
+ * @param caption The caption of the radio button.
+ * @param group The group the radio button should belong to.
+ * @param selected True if the radio button should be selected.
+ */
+ RadioButton(const Widget2 *const widget,
+ const std::string &caption,
+ const std::string &group,
+ bool selected = false);
+
+ A_DELETE_COPY(RadioButton)
+
+ /**
+ * Destructor.
+ */
+ virtual ~RadioButton();
+
+ /**
+ * Checks if the radio button is selected.
+ *
+ * @return True if the radio button is selecte, false otherwise.
+ * @see setSelected
+ */
+ bool isSelected() const;
+
+ /**
+ * Sets the radio button to selected or not.
+ *
+ * @param selected True if the radio button should be selected,
+ * false otherwise.
+ * @see isSelected
+ */
+ void setSelected(bool selected);
+
+ /**
+ * Gets the caption of the radio button.
+ *
+ * @return The caption of the radio button.
+ * @see setCaption
+ */
+ const std::string &getCaption() const;
+
+ /**
+ * Sets the caption of the radio button. It's advisable to call
+ * adjustSize after setting of the caption to adjust the
+ * radio button's size to fit the caption.
+ *
+ * @param caption The caption of the radio button.
+ * @see getCaption, adjustSize
+ */
+ void setCaption(const std::string &caption);
+
+ /**
+ * Sets the group the radio button should belong to. Note that
+ * a radio button group is unique per application, not per Gui object
+ * as the group is stored in a static map.
+ *
+ * @param group The name of the group.
+ * @see getGroup
+ */
+ void setGroup(const std::string &group);
+
+ /**
+ * Gets the group the radio button belongs to.
+ *
+ * @return The group the radio button belongs to.
+ * @see setGroup
+ */
+ const std::string &getGroup() const;
+
+ /**
+ * Adjusts the radio button's size to fit the caption.
+ */
+ void adjustSize();
+
+
+ // Inherited from KeyListener
+
+ virtual void keyPressed(KeyEvent& keyEvent) override;
+
+
+ // Inherited from MouseListener
+
+ virtual void mouseClicked(MouseEvent& mouseEvent) override;
+
+ virtual void mouseDragged(MouseEvent& mouseEvent) override;
+
+ protected:
+ /**
+ * Draws the box.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawBox(Graphics *graphics) = 0;
+
+ /**
+ * True if the radio button is selected, false otherwise.
+ */
+ bool mSelected;
+
+ /**
+ * Holds the caption of the radio button.
+ */
+ std::string mCaption;
+
+ /**
+ * Holds the group of the radio button.
+ */
+ std::string mGroup;
+
+ /**
+ * Typdef.
+ */
+ typedef std::multimap<std::string, RadioButton *> GroupMap;
+
+ /**
+ * Typdef.
+ */
+ typedef GroupMap::iterator GroupIterator;
+
+ /**
+ * Holds all available radio button groups.
+ */
+ static GroupMap mGroupMap;
+ };
+} // namespace gcn
+
+#endif // end GCN_RADIOBUTTON_HPP
diff --git a/src/gui/base/widgets/scrollarea.cpp b/src/gui/base/widgets/scrollarea.cpp
new file mode 100644
index 000000000..665830ce4
--- /dev/null
+++ b/src/gui/base/widgets/scrollarea.cpp
@@ -0,0 +1,597 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/scrollarea.hpp"
+
+#include "debug.h"
+
+namespace gcn
+{
+ ScrollArea::ScrollArea(const Widget2 *const widget) :
+ gcn::BasicContainer(widget),
+ MouseListener(),
+ mVScroll(0),
+ mHScroll(0),
+ mScrollbarWidth(12),
+ mHPolicy(SHOW_AUTO),
+ mVPolicy(SHOW_AUTO),
+ mVBarVisible(false),
+ mHBarVisible(false),
+ mUpButtonPressed(false),
+ mDownButtonPressed(false),
+ mLeftButtonPressed(false),
+ mRightButtonPressed(false),
+ mUpButtonScrollAmount(10),
+ mDownButtonScrollAmount(10),
+ mLeftButtonScrollAmount(10),
+ mRightButtonScrollAmount(10),
+ mIsVerticalMarkerDragged(false),
+ mIsHorizontalMarkerDragged(false),
+ mHorizontalMarkerDragOffset(0),
+ mVerticalMarkerDragOffset(0),
+ mOpaque(true)
+ {
+ addMouseListener(this);
+ }
+
+ ScrollArea::ScrollArea(const Widget2 *const widget,
+ Widget *const content) :
+ gcn::BasicContainer(widget),
+ MouseListener(),
+ mVScroll(0),
+ mHScroll(0),
+ mScrollbarWidth(12),
+ mHPolicy(SHOW_AUTO),
+ mVPolicy(SHOW_AUTO),
+ mVBarVisible(false),
+ mHBarVisible(false),
+ mUpButtonPressed(false),
+ mDownButtonPressed(false),
+ mLeftButtonPressed(false),
+ mRightButtonPressed(false),
+ mUpButtonScrollAmount(10),
+ mDownButtonScrollAmount(10),
+ mLeftButtonScrollAmount(10),
+ mRightButtonScrollAmount(10),
+ mIsVerticalMarkerDragged(false),
+ mIsHorizontalMarkerDragged(false),
+ mHorizontalMarkerDragOffset(0),
+ mVerticalMarkerDragOffset(0),
+ mOpaque(true)
+ {
+ setContent(content);
+ addMouseListener(this);
+ }
+
+ ScrollArea::ScrollArea(const Widget2 *const widget,
+ Widget *content,
+ ScrollPolicy hPolicy,
+ ScrollPolicy vPolicy) :
+ gcn::BasicContainer(widget),
+ MouseListener(),
+ mVScroll(0),
+ mHScroll(0),
+ mScrollbarWidth(12),
+ mHPolicy(hPolicy),
+ mVPolicy(vPolicy),
+ mVBarVisible(false),
+ mHBarVisible(false),
+ mUpButtonPressed(false),
+ mDownButtonPressed(false),
+ mLeftButtonPressed(false),
+ mRightButtonPressed(false),
+ mUpButtonScrollAmount(10),
+ mDownButtonScrollAmount(10),
+ mLeftButtonScrollAmount(10),
+ mRightButtonScrollAmount(10),
+ mIsVerticalMarkerDragged(false),
+ mIsHorizontalMarkerDragged(false),
+ mHorizontalMarkerDragOffset(0),
+ mVerticalMarkerDragOffset(0),
+ mOpaque(true)
+ {
+ setContent(content);
+ addMouseListener(this);
+ }
+
+ ScrollArea::~ScrollArea()
+ {
+ setContent(nullptr);
+ }
+
+ void ScrollArea::setContent(Widget* widget)
+ {
+ if (widget)
+ {
+ clear();
+ add(widget);
+ widget->setPosition(0, 0);
+ }
+ else
+ {
+ clear();
+ }
+
+ checkPolicies();
+ }
+
+ Widget* ScrollArea::getContent()
+ {
+ if (!mWidgets.empty())
+ return *mWidgets.begin();
+
+ return nullptr;
+ }
+
+ void ScrollArea::setHorizontalScrollPolicy(ScrollPolicy hPolicy)
+ {
+ mHPolicy = hPolicy;
+ checkPolicies();
+ }
+
+ ScrollArea::ScrollPolicy ScrollArea::getHorizontalScrollPolicy() const
+ {
+ return mHPolicy;
+ }
+
+ void ScrollArea::setVerticalScrollPolicy(ScrollPolicy vPolicy)
+ {
+ mVPolicy = vPolicy;
+ checkPolicies();
+ }
+
+ ScrollArea::ScrollPolicy ScrollArea::getVerticalScrollPolicy() const
+ {
+ return mVPolicy;
+ }
+
+ void ScrollArea::setScrollPolicy(ScrollPolicy hPolicy,
+ ScrollPolicy vPolicy)
+ {
+ mHPolicy = hPolicy;
+ mVPolicy = vPolicy;
+ checkPolicies();
+ }
+
+ void ScrollArea::setVerticalScrollAmount(int vScroll)
+ {
+ const int max = getVerticalMaxScroll();
+
+ mVScroll = vScroll;
+
+ if (vScroll > max)
+ mVScroll = max;
+
+ if (vScroll < 0)
+ mVScroll = 0;
+ }
+
+ int ScrollArea::getVerticalScrollAmount() const
+ {
+ return mVScroll;
+ }
+
+ void ScrollArea::setHorizontalScrollAmount(int hScroll)
+ {
+ const int max = getHorizontalMaxScroll();
+
+ mHScroll = hScroll;
+
+ if (hScroll > max)
+ mHScroll = max;
+ else if (hScroll < 0)
+ mHScroll = 0;
+ }
+
+ int ScrollArea::getHorizontalScrollAmount() const
+ {
+ return mHScroll;
+ }
+
+ void ScrollArea::setScrollAmount(int hScroll, int vScroll)
+ {
+ setHorizontalScrollAmount(hScroll);
+ setVerticalScrollAmount(vScroll);
+ }
+
+ int ScrollArea::getHorizontalMaxScroll()
+ {
+ checkPolicies();
+
+ const Widget *const content = getContent();
+ if (!content)
+ return 0;
+
+ const int value = content->getWidth() - getChildrenArea().width +
+ 2 * content->getFrameSize();
+
+ if (value < 0)
+ return 0;
+
+ return value;
+ }
+
+ int ScrollArea::getVerticalMaxScroll()
+ {
+ checkPolicies();
+
+ const Widget *const content = getContent();
+ if (!content)
+ return 0;
+
+ int value;
+
+ value = content->getHeight() - getChildrenArea().height +
+ 2 * content->getFrameSize();
+
+ if (value < 0)
+ return 0;
+
+ return value;
+ }
+
+ void ScrollArea::setScrollbarWidth(int width)
+ {
+ if (width > 0)
+ mScrollbarWidth = width;
+ }
+
+ int ScrollArea::getScrollbarWidth() const
+ {
+ return mScrollbarWidth;
+ }
+
+ void ScrollArea::mouseReleased(MouseEvent& mouseEvent)
+ {
+ mUpButtonPressed = false;
+ mDownButtonPressed = false;
+ mLeftButtonPressed = false;
+ mRightButtonPressed = false;
+ mIsHorizontalMarkerDragged = false;
+ mIsVerticalMarkerDragged = false;
+
+ mouseEvent.consume();
+ }
+
+ void ScrollArea::draw(Graphics *graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawHBar(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawVBar(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawBackground(Graphics *graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawUpButton(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawDownButton(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawLeftButton(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawRightButton(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawVMarker(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::drawHMarker(Graphics* graphics A_UNUSED)
+ {
+ }
+
+ void ScrollArea::logic()
+ {
+ BLOCK_START("ScrollArea::logic")
+ checkPolicies();
+
+ setVerticalScrollAmount(getVerticalScrollAmount());
+ setHorizontalScrollAmount(getHorizontalScrollAmount());
+
+ Widget *const content = getContent();
+ if (content)
+ {
+ const int frameSize = content->getFrameSize();
+ content->setPosition(-mHScroll + frameSize, -mVScroll + frameSize);
+ content->logic();
+ }
+ BLOCK_END("ScrollArea::logic")
+ }
+
+ void ScrollArea::checkPolicies()
+ {
+ const int w = getWidth();
+ const int h = getHeight();
+
+ mHBarVisible = false;
+ mVBarVisible = false;
+
+ const Widget *const content = getContent();
+ if (!content)
+ {
+ mHBarVisible = (mHPolicy == SHOW_ALWAYS);
+ mVBarVisible = (mVPolicy == SHOW_ALWAYS);
+ return;
+ }
+
+ if (mHPolicy == SHOW_AUTO &&
+ mVPolicy == SHOW_AUTO)
+ {
+ if (content->getWidth() <= w
+ && content->getHeight() <= h)
+ {
+ mHBarVisible = false;
+ mVBarVisible = false;
+ }
+
+ if (content->getWidth() > w)
+ {
+ mHBarVisible = true;
+ }
+
+ if ((content->getHeight() > h)
+ || (mHBarVisible && content->getHeight()
+ > h - mScrollbarWidth))
+ {
+ mVBarVisible = true;
+ }
+
+ if (mVBarVisible && content->getWidth() > w - mScrollbarWidth)
+ mHBarVisible = true;
+
+ return;
+ }
+
+ switch (mHPolicy)
+ {
+ case SHOW_NEVER:
+ mHBarVisible = false;
+ break;
+
+ case SHOW_ALWAYS:
+ mHBarVisible = true;
+ break;
+
+ case SHOW_AUTO:
+ if (mVPolicy == SHOW_NEVER)
+ {
+ mHBarVisible = (content->getWidth() > w);
+ }
+ else // (mVPolicy == SHOW_ALWAYS)
+ {
+ mHBarVisible = (content->getWidth()
+ > w - mScrollbarWidth);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (mVPolicy)
+ {
+ case SHOW_NEVER:
+ mVBarVisible = false;
+ break;
+
+ case SHOW_ALWAYS:
+ mVBarVisible = true;
+ break;
+
+ case SHOW_AUTO:
+ if (mHPolicy == SHOW_NEVER)
+ {
+ mVBarVisible = (content->getHeight() > h);
+ }
+ else // (mHPolicy == SHOW_ALWAYS)
+ {
+ mVBarVisible = (content->getHeight()
+ > h - mScrollbarWidth);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ Rect ScrollArea::getChildrenArea()
+ {
+ const Rect area = Rect(0, 0,
+ mVBarVisible ? (getWidth() - mScrollbarWidth) : getWidth(),
+ mHBarVisible ? (getHeight() - mScrollbarWidth) : getHeight());
+
+ if (area.width < 0 || area.height < 0)
+ return Rect();
+
+ return area;
+ }
+
+ void ScrollArea::showWidgetPart(Widget* widget, Rect area)
+ {
+ const Widget *const content = getContent();
+ if (widget != content)
+ return;
+
+ BasicContainer::showWidgetPart(widget, area);
+
+ setHorizontalScrollAmount(content->getFrameSize()
+ - content->getX());
+ setVerticalScrollAmount(content->getFrameSize()
+ - content->getY());
+ }
+
+ Widget *ScrollArea::getWidgetAt(int x, int y)
+ {
+ if (getChildrenArea().isPointInRect(x, y))
+ return getContent();
+
+ return nullptr;
+ }
+
+ void ScrollArea::mouseWheelMovedUp(MouseEvent& mouseEvent)
+ {
+ if (mouseEvent.isConsumed())
+ return;
+
+ setVerticalScrollAmount(getVerticalScrollAmount()
+ - getChildrenArea().height / 8);
+
+ mouseEvent.consume();
+ }
+
+ void ScrollArea::mouseWheelMovedDown(MouseEvent& mouseEvent)
+ {
+ if (mouseEvent.isConsumed())
+ return;
+
+ setVerticalScrollAmount(getVerticalScrollAmount()
+ + getChildrenArea().height / 8);
+
+ mouseEvent.consume();
+ }
+
+ void ScrollArea::setWidth(int width)
+ {
+ Widget::setWidth(width);
+ checkPolicies();
+ }
+
+ void ScrollArea::setHeight(int height)
+ {
+ Widget::setHeight(height);
+ checkPolicies();
+ }
+
+ void ScrollArea::setDimension(const Rect& dimension)
+ {
+ Widget::setDimension(dimension);
+ checkPolicies();
+ }
+
+ void ScrollArea::setLeftButtonScrollAmount(int amount)
+ {
+ mLeftButtonScrollAmount = amount;
+ }
+
+ void ScrollArea::setRightButtonScrollAmount(int amount)
+ {
+ mRightButtonScrollAmount = amount;
+ }
+
+ void ScrollArea::setUpButtonScrollAmount(int amount)
+ {
+ mUpButtonScrollAmount = amount;
+ }
+
+ void ScrollArea::setDownButtonScrollAmount(int amount)
+ {
+ mDownButtonScrollAmount = amount;
+ }
+
+ int ScrollArea::getLeftButtonScrollAmount() const
+ {
+ return mLeftButtonScrollAmount;
+ }
+
+ int ScrollArea::getRightButtonScrollAmount() const
+ {
+ return mRightButtonScrollAmount;
+ }
+
+ int ScrollArea::getUpButtonScrollAmount() const
+ {
+ return mUpButtonScrollAmount;
+ }
+
+ int ScrollArea::getDownButtonScrollAmount() const
+ {
+ return mDownButtonScrollAmount;
+ }
+
+ void ScrollArea::setOpaque(bool opaque)
+ {
+ mOpaque = opaque;
+ }
+
+ bool ScrollArea::isOpaque() const
+ {
+ return mOpaque;
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/scrollarea.hpp b/src/gui/base/widgets/scrollarea.hpp
new file mode 100644
index 000000000..879792019
--- /dev/null
+++ b/src/gui/base/widgets/scrollarea.hpp
@@ -0,0 +1,549 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_SCROLLAREA_HPP
+#define GCN_SCROLLAREA_HPP
+
+#include "gui/base/basiccontainer.hpp"
+#include "listeners/mouselistener.h"
+
+namespace gcn
+{
+ /**
+ * Implementation if a scrollable area used to view widgets larger than the scroll area.
+ * A scroll area can be customized to always show scroll bars or to show them only when
+ * necessary.
+ */
+ class ScrollArea:
+ public BasicContainer,
+ public MouseListener
+ {
+ public:
+ /**
+ * Scrollpolicies for the horizontal and vertical scrollbar.
+ * The policies are:
+ *
+ * SHOW_ALWAYS - Always show the scrollbars no matter what.
+ * SHOW_NEVER - Never show the scrollbars no matter waht.
+ * SHOW_AUTO - Show the scrollbars only when needed. That is if the
+ * content grows larger then the ScrollArea.
+ */
+ enum ScrollPolicy
+ {
+ SHOW_ALWAYS = 0,
+ SHOW_NEVER,
+ SHOW_AUTO
+ };
+
+ /**
+ * Constructor.
+ */
+ explicit ScrollArea(const Widget2 *const widget);
+
+ /**
+ * Constructor.
+ *
+ * @param content The content of the scroll area.
+ */
+ ScrollArea(const Widget2 *const widget,
+ Widget *const content);
+
+ /**
+ * Constructor.
+ *
+ * @param content The content of the scroll area.
+ * @param hPolicy The policy for the horizontal scrollbar. See enum with
+ * policies.
+ * @param vPolicy The policy for the vertical scrollbar. See enum with
+ * policies.
+ */
+ ScrollArea(const Widget2 *const widget,
+ Widget *content,
+ ScrollPolicy hPolicy,
+ ScrollPolicy vPolicy);
+
+ A_DELETE_COPY(ScrollArea)
+
+ /**
+ * Destructor.
+ */
+ virtual ~ScrollArea();
+
+ /**
+ * Sets the content.
+ *
+ * @param widget The content of the scroll area.
+ */
+ void setContent(Widget* widget);
+
+ /**
+ * Gets the content.
+ *
+ * @return The content of the scroll area.
+ */
+ Widget* getContent();
+
+ /**
+ * Sets the horizontal scrollbar policy. See enum with policies.
+ *
+ * @param hPolicy The policy for the horizontal scrollbar.
+ * @see getHorizontalScrollPolicy
+ */
+ void setHorizontalScrollPolicy(ScrollPolicy hPolicy);
+
+ /**
+ * Gets the horizontal scrollbar policy. See enum with policies.
+ *
+ * @return The policy for the horizontal scrollbar policy.
+ * @see setHorizontalScrollPolicy, setScrollPolicy
+ */
+ ScrollPolicy getHorizontalScrollPolicy() const;
+
+ /**
+ * Sets the vertical scrollbar policy. See enum with policies.
+ *
+ * @param vPolicy The policy for the vertical scrollbar.
+ * @see getVerticalScrollPolicy
+ */
+ void setVerticalScrollPolicy(ScrollPolicy vPolicy);
+
+ /**
+ * Gets the vertical scrollbar policy. See enum with policies.
+ *
+ * @return The policy for the vertical scrollbar.
+ * @see setVerticalScrollPolicy, setScrollPolicy
+ */
+ ScrollPolicy getVerticalScrollPolicy() const;
+
+ /**
+ * Sets the horizontal and vertical scrollbar policy.
+ *
+ * @param hPolicy The policy for the horizontal scrollbar.
+ * @param vPolicy The policy for the vertical scrollbar.
+ * @see getVerticalScrollPolicy, getHorizontalScrollPolicy
+ */
+ void setScrollPolicy(ScrollPolicy hPolicy, ScrollPolicy vPolicy);
+
+ /**
+ * Sets the amount to scroll vertically.
+ *
+ * @param vScroll The amount to scroll.
+ * @see getVerticalScrollAmount
+ */
+ void setVerticalScrollAmount(int vScroll);
+
+ /**
+ * Gets the amount that is scrolled vertically.
+ *
+ * @return The scroll amount on vertical scroll.
+ * @see setVerticalScrollAmount, setScrollAmount
+ */
+ int getVerticalScrollAmount() const;
+
+ /**
+ * Sets the amount to scroll horizontally.
+ *
+ * @param hScroll The amount to scroll.
+ * @see getHorizontalScrollAmount
+ */
+ void setHorizontalScrollAmount(int hScroll);
+
+ /**
+ * Gets the amount that is scrolled horizontally.
+ *
+ * @return The scroll amount on horizontal scroll.
+ * @see setHorizontalScrollAmount, setScrollAmount
+ */
+ int getHorizontalScrollAmount() const;
+
+ /**
+ * Sets the amount to scroll horizontally and vertically.
+ *
+ * @param hScroll The amount to scroll on horizontal scroll.
+ * @param vScroll The amount to scroll on vertical scroll.
+ * @see getHorizontalScrollAmount, getVerticalScrollAmount
+ */
+ void setScrollAmount(int hScroll, int vScroll);
+
+ /**
+ * Gets the maximum amount of horizontal scroll.
+ *
+ * @return The horizontal max scroll.
+ */
+ int getHorizontalMaxScroll();
+
+ /**
+ * Gets the maximum amount of vertical scroll.
+ *
+ * @return The vertical max scroll.
+ */
+ int getVerticalMaxScroll();
+
+ /**
+ * Sets the width of the scroll bars.
+ *
+ * @param width The width of the scroll bars.
+ * @see getScrollbarWidth
+ */
+ void setScrollbarWidth(int width);
+
+ /**
+ * Gets the width of the scroll bars.
+ *
+ * @return the width of the ScrollBar.
+ * @see setScrollbarWidth
+ */
+ int getScrollbarWidth() const;
+
+ /**
+ * Sets the amount to scroll in pixels when the left scroll button is
+ * pushed.
+ *
+ * @param amount The amount to scroll in pixels.
+ * @see getLeftButtonScrollAmount
+ */
+ void setLeftButtonScrollAmount(int amount);
+
+ /**
+ * Sets the amount to scroll in pixels when the right scroll button is
+ * pushed.
+ *
+ * @param amount The amount to scroll in pixels.
+ * @see getRightButtonScrollAmount
+ */
+ void setRightButtonScrollAmount(int amount);
+
+ /**
+ * Sets the amount to scroll in pixels when the up scroll button is
+ * pushed.
+ *
+ * @param amount The amount to scroll in pixels.
+ * @see getUpButtonScrollAmount
+ */
+ void setUpButtonScrollAmount(int amount);
+
+ /**
+ * Sets the amount to scroll in pixels when the down scroll button is
+ * pushed.
+ *
+ * @param amount The amount to scroll in pixels.
+ * @see getDownButtonScrollAmount
+ */
+ void setDownButtonScrollAmount(int amount);
+
+ /**
+ * Gets the amount to scroll in pixels when the left scroll button is
+ * pushed.
+ *
+ * @return The amount to scroll in pixels.
+ * @see setLeftButtonScrollAmount
+ */
+ int getLeftButtonScrollAmount() const;
+
+ /**
+ * Gets the amount to scroll in pixels when the right scroll button is
+ * pushed.
+ *
+ * @return The amount to scroll in pixels.
+ * @see setRightButtonScrollAmount
+ */
+ int getRightButtonScrollAmount() const;
+
+ /**
+ * Gets the amount to scroll in pixels when the up scroll button is
+ * pushed.
+ *
+ * @return The amount to scroll in pixels.
+ * @see setUpButtonScrollAmount
+ */
+ int getUpButtonScrollAmount() const;
+
+ /**
+ * Gets the amount to scroll in pixels when the down scroll button is
+ * pushed.
+ *
+ * @return The amount to scroll in pixels.
+ * @see setDownButtonScrollAmount
+ */
+ int getDownButtonScrollAmount() const;
+
+ /**
+ * Sets the scroll area to be opaque, that is sets the scoll area
+ * to display its background.
+ *
+ * @param opaque True if the scoll area should be opaque, false otherwise.
+ */
+ void setOpaque(bool opaque);
+
+ /**
+ * Checks if the scroll area is opaque, that is if the scroll area
+ * displays its background.
+ *
+ * @return True if the scroll area is opaque, false otherwise.
+ */
+ bool isOpaque() const;
+
+ // Inherited from BasicContainer
+
+ virtual void showWidgetPart(Widget* widget, Rect area);
+
+ virtual Rect getChildrenArea();
+
+ virtual Widget *getWidgetAt(int x, int y);
+
+
+ // Inherited from Widget
+
+ virtual void draw(Graphics *graphics);
+
+ virtual void logic();
+
+ void setWidth(int width);
+
+ void setHeight(int height);
+
+ void setDimension(const Rect& dimension);
+
+
+ // Inherited from MouseListener
+
+ virtual void mouseReleased(MouseEvent& mouseEvent) override;
+
+ virtual void mouseWheelMovedUp(MouseEvent& mouseEvent) override;
+
+ virtual void mouseWheelMovedDown(MouseEvent& mouseEvent) override;
+
+ protected:
+ /**
+ * Draws the background of the scroll area, that is
+ * the area behind the content.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawBackground(Graphics *graphics);
+
+ /**
+ * Draws the up button.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawUpButton(Graphics *graphics);
+
+ /**
+ * Draws the down button.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawDownButton(Graphics *graphics);
+
+ /**
+ * Draws the left button.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawLeftButton(Graphics *graphics);
+
+ /**
+ * Draws the right button.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawRightButton(Graphics *graphics);
+
+ /**
+ * Draws the vertical scroll bar.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawVBar(Graphics* graphics);
+
+ /**
+ * Draws the horizontal scroll bar.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawHBar(Graphics* graphics);
+
+ /**
+ * Draws the vertical marker.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawVMarker(Graphics* graphics);
+
+ /**
+ * Draws the horizontal marker.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawHMarker(Graphics* graphics);
+
+ /**
+ * Checks the policies for the scroll bars.
+ */
+ virtual void checkPolicies();
+
+ /**
+ * Holds the vertical scroll amount.
+ */
+ int mVScroll;
+
+ /**
+ * Holds the horizontal scroll amount.
+ */
+ int mHScroll;
+
+ /**
+ * Holds the width of the scroll bars.
+ */
+ int mScrollbarWidth;
+
+ /**
+ * Holds the horizontal scroll bar policy.
+ */
+ ScrollPolicy mHPolicy;
+
+ /**
+ * Holds the vertical scroll bar policy.
+ */
+ ScrollPolicy mVPolicy;
+
+ /**
+ * True if the vertical scroll bar is visible, false otherwise.
+ */
+ bool mVBarVisible;
+
+ /**
+ * True if the horizontal scroll bar is visible, false otherwise.
+ */
+ bool mHBarVisible;
+
+ /**
+ * True if the up button is pressed, false otherwise.
+ */
+ bool mUpButtonPressed;
+
+ /**
+ * True if the down button is pressed, false otherwise.
+ */
+ bool mDownButtonPressed;
+
+ /**
+ * True if the left button is pressed, false otherwise.
+ */
+ bool mLeftButtonPressed;
+
+ /**
+ * True if the right button is pressed, false otherwise.
+ */
+ bool mRightButtonPressed;
+
+ /**
+ * Holds the up button scroll amount.
+ */
+ int mUpButtonScrollAmount;
+
+ /**
+ * Holds the down button scroll amount.
+ */
+ int mDownButtonScrollAmount;
+
+ /**
+ * Holds the left button scroll amount.
+ */
+ int mLeftButtonScrollAmount;
+
+ /**
+ * Holds the right button scroll amount.
+ */
+ int mRightButtonScrollAmount;
+
+ /**
+ * True if the vertical marked is dragged.
+ */
+ bool mIsVerticalMarkerDragged;
+
+ /**
+ * True if the horizontal marked is dragged.
+ */
+ bool mIsHorizontalMarkerDragged;
+
+ /**
+ * Holds the horizontal markers drag offset.
+ */
+ int mHorizontalMarkerDragOffset;
+
+ /**
+ * Holds the vertical markers drag offset.
+ */
+ int mVerticalMarkerDragOffset;
+
+ /**
+ * True if the scroll area should be opaque (that is
+ * display its background), false otherwise.
+ */
+ bool mOpaque;
+ };
+} // namespace gcn
+
+#endif // end GCN_SCROLLAREA_HPP
diff --git a/src/gui/base/widgets/slider.cpp b/src/gui/base/widgets/slider.cpp
new file mode 100644
index 000000000..40c73ceb5
--- /dev/null
+++ b/src/gui/base/widgets/slider.cpp
@@ -0,0 +1,230 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/slider.hpp"
+
+#include "debug.h"
+
+namespace gcn
+{
+ Slider::Slider(const Widget2 *const widget,
+ const double scaleEnd) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mDragged(false),
+ mValue(0),
+ mStepLength(scaleEnd / 10),
+ mMarkerLength(10),
+ mScaleStart(0),
+ mScaleEnd(scaleEnd),
+ mOrientation(HORIZONTAL)
+ {
+ setFocusable(true);
+ setFrameSize(1);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ Slider::Slider(const Widget2 *const widget,
+ const double scaleStart,
+ const double scaleEnd) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mDragged(false),
+ mValue(scaleStart),
+ mStepLength((scaleEnd - scaleStart) / 10),
+ mMarkerLength(10),
+ mScaleStart(scaleStart),
+ mScaleEnd(scaleEnd),
+ mOrientation(HORIZONTAL)
+ {
+ setFocusable(true);
+ setFrameSize(1);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ void Slider::setScale(double scaleStart, double scaleEnd)
+ {
+ mScaleStart = scaleStart;
+ mScaleEnd = scaleEnd;
+ }
+
+ double Slider::getScaleStart() const
+ {
+ return mScaleStart;
+ }
+
+ void Slider::setScaleStart(double scaleStart)
+ {
+ mScaleStart = scaleStart;
+ }
+
+ double Slider::getScaleEnd() const
+ {
+ return mScaleEnd;
+ }
+
+ void Slider::setScaleEnd(double scaleEnd)
+ {
+ mScaleEnd = scaleEnd;
+ }
+
+ void Slider::setValue(double value)
+ {
+ if (value > getScaleEnd())
+ {
+ mValue = getScaleEnd();
+ return;
+ }
+
+ if (value < getScaleStart())
+ {
+ mValue = getScaleStart();
+ return;
+ }
+
+ mValue = value;
+ }
+
+ double Slider::getValue() const
+ {
+ return mValue;
+ }
+
+ int Slider::getMarkerLength() const
+ {
+ return mMarkerLength;
+ }
+
+ void Slider::setMarkerLength(int length)
+ {
+ mMarkerLength = length;
+ }
+
+ void Slider::setOrientation(Slider::Orientation orientation)
+ {
+ mOrientation = orientation;
+ }
+
+ Slider::Orientation Slider::getOrientation() const
+ {
+ return mOrientation;
+ }
+
+ double Slider::markerPositionToValue(int v) const
+ {
+ int w;
+ if (getOrientation() == HORIZONTAL)
+ w = getWidth();
+ else
+ w = getHeight();
+
+ const double pos = v / (static_cast<double>(w) - getMarkerLength());
+ return (1.0 - pos) * getScaleStart() + pos * getScaleEnd();
+ }
+
+ int Slider::valueToMarkerPosition(double value) const
+ {
+ int v;
+ if (getOrientation() == HORIZONTAL)
+ v = getWidth();
+ else
+ v = getHeight();
+
+ const int w = static_cast<int>((v - getMarkerLength())
+ * (value - getScaleStart())
+ / (getScaleEnd() - getScaleStart()));
+
+ if (w < 0)
+ return 0;
+
+ if (w > v - getMarkerLength())
+ return v - getMarkerLength();
+
+ return w;
+ }
+
+ void Slider::setStepLength(double length)
+ {
+ mStepLength = length;
+ }
+
+ double Slider::getStepLength() const
+ {
+ return mStepLength;
+ }
+
+ int Slider::getMarkerPosition() const
+ {
+ return valueToMarkerPosition(getValue());
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/slider.hpp b/src/gui/base/widgets/slider.hpp
new file mode 100644
index 000000000..9d5adc6d8
--- /dev/null
+++ b/src/gui/base/widgets/slider.hpp
@@ -0,0 +1,297 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_SLIDER_HPP
+#define GCN_SLIDER_HPP
+
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+#include "gui/widgets/widget.h"
+
+namespace gcn
+{
+ /**
+ * An implementation of a slider where a user can select different values by
+ * sliding between a start value and an end value of a scale.
+ *
+ * If the selected value is changed an action event will be sent to all
+ * action listeners of the slider.
+ */
+ class Slider :
+ public Widget,
+ public MouseListener,
+ public KeyListener
+ {
+ public:
+ /**
+ * Draw orientations for the slider. A slider can be drawn vertically or
+ * horizontally.
+ */
+ enum Orientation
+ {
+ HORIZONTAL = 0,
+ VERTICAL
+ };
+
+ /**
+ * Constructor. The default start value of the slider scale is zero.
+ *
+ * @param scaleEnd The end value of the slider scale.
+ */
+ explicit Slider(const Widget2 *const widget,
+ const double scaleEnd = 1.0);
+
+ /**
+ * Constructor.
+ *
+ * @param scaleStart The start value of the slider scale.
+ * @param scaleEnd The end value of the slider scale.
+ */
+ Slider(const Widget2 *const widget,
+ const double scaleStart,
+ const double scaleEnd);
+
+ A_DELETE_COPY(Slider)
+
+ /**
+ * Destructor.
+ */
+ virtual ~Slider()
+ { }
+
+ /**
+ * Sets the scale of the slider.
+ *
+ * @param scaleStart The start value of the scale.
+ * @param scaleEnd tThe end of value the scale.
+ * @see getScaleStart, getScaleEnd
+ */
+ void setScale(double scaleStart, double scaleEnd);
+
+ /**
+ * Gets the start value of the scale.
+ *
+ * @return The start value of the scale.
+ * @see setScaleStart, setScale
+ */
+ double getScaleStart() const;
+
+ /**
+ * Sets the start value of the scale.
+ *
+ * @param scaleStart The start value of the scale.
+ * @see getScaleStart
+ */
+ void setScaleStart(double scaleStart);
+
+ /**
+ * Gets the end value of the scale.
+ *
+ * @return The end value of the scale.
+ * @see setScaleEnd, setScale
+ */
+ double getScaleEnd() const;
+
+ /**
+ * Sets the end value of the scale.
+ *
+ * @param scaleEnd The end value of the scale.
+ * @see getScaleEnd
+ */
+ void setScaleEnd(double scaleEnd);
+
+ /**
+ * Gets the current selected value.
+ *
+ * @return The current selected value.
+ * @see setValue
+ */
+ double getValue() const;
+
+ /**
+ * Sets the current selected value.
+ *
+ * @param value The current selected value.
+ * @see getValue
+ */
+ void setValue(double value);
+
+ /**
+ * Sets the length of the marker.
+ *
+ * @param length The length for the marker.
+ * @see getMarkerLength
+ */
+ void setMarkerLength(int length);
+
+ /**
+ * Gets the length of the marker.
+ *
+ * @return The length of the marker.
+ * @see setMarkerLength
+ */
+ int getMarkerLength() const;
+
+ /**
+ * Sets the orientation of the slider. A slider can be drawn vertically
+ * or horizontally.
+ *
+ * @param orientation The orientation of the slider.
+ * @see getOrientation
+ */
+ void setOrientation(Orientation orientation);
+
+ /**
+ * Gets the orientation of the slider. A slider can be drawn vertically
+ * or horizontally.
+ *
+ * @return The orientation of the slider.
+ * @see setOrientation
+ */
+ Orientation getOrientation() const;
+
+ /**
+ * Sets the step length. The step length is used when the keys LEFT
+ * and RIGHT are pressed to step in the scale.
+ *
+ * @param length The step length.
+ * @see getStepLength
+ */
+ void setStepLength(double length);
+
+ /**
+ * Gets the step length. The step length is used when the keys LEFT
+ * and RIGHT are pressed to step in the scale.
+ *
+ * @return the step length.
+ * @see setStepLength
+ */
+ double getStepLength() const;
+
+ protected:
+ /**
+ * Converts a marker position to a value in the scale.
+ *
+ * @param position The position to convert.
+ * @return A scale value corresponding to the position.
+ * @see valueToMarkerPosition
+ */
+ virtual double markerPositionToValue(int position) const;
+
+ /**
+ * Converts a value to a marker position.
+ *
+ * @param value The value to convert.
+ * @return A marker position corresponding to the value.
+ * @see markerPositionToValue
+ */
+ virtual int valueToMarkerPosition(double value) const;
+
+ /**
+ * Gets the marker position of the current selected value.
+ *
+ * @return The marker position of the current selected value.
+ */
+ virtual int getMarkerPosition() const;
+
+ /**
+ * True if the slider is dragged, false otherwise.
+ */
+ bool mDragged;
+
+ /**
+ * Holds the current selected value.
+ */
+ double mValue;
+
+ /**
+ * Holds the step length. The step length is used when the keys LEFT
+ * and RIGHT are pressed to step in the scale.
+ */
+ double mStepLength;
+
+ /**
+ * Holds the length of the marker.
+ */
+ int mMarkerLength;
+
+ /**
+ * Holds the start value of the scale.
+ */
+ double mScaleStart;
+
+ /**
+ * Holds the end value of the scale.
+ */
+ double mScaleEnd;
+
+ /**
+ * Holds the orientation of the slider. A slider can be drawn
+ * vertically or horizontally.
+ */
+ Orientation mOrientation;
+ };
+} // namespace gcn
+
+#endif // end GCN_SLIDER_HPP
diff --git a/src/gui/base/widgets/textbox.cpp b/src/gui/base/widgets/textbox.cpp
new file mode 100644
index 000000000..f74db9a29
--- /dev/null
+++ b/src/gui/base/widgets/textbox.cpp
@@ -0,0 +1,344 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/textbox.hpp"
+
+#include "gui/font.h"
+
+#include "render/graphics.h"
+
+#include "debug.h"
+
+namespace gcn
+{
+ TextBox::TextBox(const Widget2 *const widget) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mTextRows(),
+ mCaretColumn(0),
+ mCaretRow(0),
+ mEditable(true),
+ mOpaque(true)
+ {
+ setText("");
+ setFocusable(true);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ adjustSize();
+ }
+
+ TextBox::TextBox(const Widget2 *const widget,
+ const std::string& text) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mTextRows(),
+ mCaretColumn(0),
+ mCaretRow(0),
+ mEditable(true),
+ mOpaque(true)
+ {
+ setText(text);
+ setFocusable(true);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ adjustSize();
+ }
+
+ void TextBox::setText(const std::string& text)
+ {
+ mCaretColumn = 0;
+ mCaretRow = 0;
+
+ mTextRows.clear();
+
+ size_t pos, lastPos = 0;
+ int length;
+ do
+ {
+ pos = text.find("\n", lastPos);
+
+ if (pos != std::string::npos)
+ length = static_cast<int>(pos - lastPos);
+ else
+ length = static_cast<int>(text.size() - lastPos);
+ std::string sub = text.substr(lastPos, length);
+ mTextRows.push_back(sub);
+ lastPos = pos + 1;
+ } while (pos != std::string::npos);
+
+ adjustSize();
+ }
+
+/*
+ void TextBox::draw(Graphics* graphics)
+ {
+ }
+*/
+
+ void TextBox::drawCaret(Graphics* graphics, int x, int y)
+ {
+ graphics->setColor(mForegroundColor);
+ graphics->drawLine(x, getFont()->getHeight() + y, x, y);
+ }
+
+ void TextBox::mousePressed(MouseEvent& mouseEvent)
+ {
+ if (mouseEvent.getButton() == MouseEvent::LEFT)
+ {
+ mCaretRow = mouseEvent.getY() / getFont()->getHeight();
+
+ const int sz = static_cast<int>(mTextRows.size());
+ if (mCaretRow >= sz)
+ mCaretRow = sz - 1;
+
+ mCaretColumn = getFont()->getStringIndexAt(
+ mTextRows[mCaretRow], mouseEvent.getX());
+ }
+ }
+
+ void TextBox::mouseDragged(MouseEvent& mouseEvent)
+ {
+ mouseEvent.consume();
+ }
+
+ void TextBox::keyPressed(KeyEvent& keyEvent A_UNUSED)
+ {
+ }
+
+ void TextBox::adjustSize()
+ {
+ int width = 0;
+ for (size_t i = 0, sz = mTextRows.size(); i < sz; ++i)
+ {
+ const int w = getFont()->getWidth(mTextRows[i]);
+ if (width < w)
+ width = w;
+ }
+
+ setWidth(width + 1);
+ setHeight(static_cast<int>(getFont()->getHeight() * mTextRows.size()));
+ }
+
+ void TextBox::setCaretPosition(unsigned int position)
+ {
+ for (int row = 0, sz = static_cast<int>(mTextRows.size());
+ row < sz; row ++)
+ {
+ if (position <= mTextRows[row].size())
+ {
+ mCaretRow = row;
+ mCaretColumn = position;
+ return; // we are done
+ }
+ else
+ {
+ position--;
+ }
+ }
+
+ // position beyond end of text
+ mCaretRow = static_cast<int>(mTextRows.size() - 1);
+ mCaretColumn = static_cast<int>(mTextRows[mCaretRow].size());
+ }
+
+ unsigned int TextBox::getCaretPosition() const
+ {
+ int pos = 0, row;
+
+ for (row = 0; row < mCaretRow; row++)
+ pos += static_cast<int>(mTextRows[row].size());
+
+ return pos + mCaretColumn;
+ }
+
+ void TextBox::setCaretRowColumn(int row, int column)
+ {
+ setCaretRow(row);
+ setCaretColumn(column);
+ }
+
+ void TextBox::setCaretRow(int row)
+ {
+ mCaretRow = row;
+
+ const int sz = static_cast<int>(mTextRows.size());
+ if (mCaretRow >= sz)
+ mCaretRow = sz - 1;
+
+ if (mCaretRow < 0)
+ mCaretRow = 0;
+
+ setCaretColumn(mCaretColumn);
+ }
+
+ unsigned int TextBox::getCaretRow() const
+ {
+ return mCaretRow;
+ }
+
+ void TextBox::setCaretColumn(int column)
+ {
+ mCaretColumn = column;
+
+ const int sz = static_cast<int>(mTextRows[mCaretRow].size());
+ if (mCaretColumn > sz)
+ mCaretColumn = sz;
+
+ if (mCaretColumn < 0)
+ mCaretColumn = 0;
+ }
+
+ unsigned int TextBox::getCaretColumn() const
+ {
+ return mCaretColumn;
+ }
+
+ const std::string& TextBox::getTextRow(int row) const
+ {
+ return mTextRows[row];
+ }
+
+ void TextBox::setTextRow(int row, const std::string& text)
+ {
+ mTextRows[row] = text;
+
+ if (mCaretRow == row)
+ setCaretColumn(mCaretColumn);
+
+ adjustSize();
+ }
+
+ unsigned int TextBox::getNumberOfRows() const
+ {
+ return static_cast<int>(mTextRows.size());
+ }
+
+ std::string TextBox::getText() const
+ {
+ if (mTextRows.empty())
+ return std::string("");
+
+ int i;
+ std::string text;
+
+ const int sz = static_cast<int>(mTextRows.size());
+ for (i = 0; i < sz - 1; ++ i)
+ text.append(mTextRows[i]).append("\n");
+ text.append(mTextRows[i]);
+
+ return text;
+ }
+
+ void TextBox::fontChanged()
+ {
+ adjustSize();
+ }
+
+ void TextBox::scrollToCaret()
+ {
+ Rect scroll;
+ scroll.x = getFont()->getWidth(
+ mTextRows[mCaretRow].substr(0, mCaretColumn));
+ scroll.y = getFont()->getHeight() * mCaretRow;
+ scroll.width = getFont()->getWidth(" ");
+
+ // add 2 for some extra space
+ scroll.height = getFont()->getHeight() + 2;
+
+ showPart(scroll);
+ }
+
+ void TextBox::setEditable(bool editable)
+ {
+ mEditable = editable;
+ }
+
+ bool TextBox::isEditable() const
+ {
+ return mEditable;
+ }
+
+ void TextBox::addRow(const std::string &row)
+ {
+ mTextRows.push_back(row);
+ adjustSize();
+ }
+
+ bool TextBox::isOpaque()
+ {
+ return mOpaque;
+ }
+
+ void TextBox::setOpaque(bool opaque)
+ {
+ mOpaque = opaque;
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/textbox.hpp b/src/gui/base/widgets/textbox.hpp
new file mode 100644
index 000000000..148b4f007
--- /dev/null
+++ b/src/gui/base/widgets/textbox.hpp
@@ -0,0 +1,311 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_TEXTBOX_HPP
+#define GCN_TEXTBOX_HPP
+
+#include <string>
+#include <vector>
+
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+#include "gui/widgets/widget.h"
+
+namespace gcn
+{
+ /**
+ * An implementation of a text box where a user can enter text that contains of many lines.
+ */
+ class TextBox:
+ public Widget,
+ public MouseListener,
+ public KeyListener
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ explicit TextBox(const Widget2 *const widget);
+
+ /**
+ * Constructor.
+ *
+ * @param text The default text of the text box.
+ */
+ TextBox(const Widget2 *const widget,
+ const std::string& text);
+
+ A_DELETE_COPY(TextBox)
+
+ /**
+ * Sets the text of the text box.
+ *
+ * @param text The text of the text box.
+ * @see getText
+ */
+ void setText(const std::string& text);
+
+ /**
+ * Gets the text of the text box.
+ *
+ * @return The text of the text box.
+ * @see setText
+ */
+ std::string getText() const;
+
+ /**
+ * Gets a certain row from the text.
+ *
+ * @param row The number of the row to get from the text.
+ * @return A row from the text of the text box.
+ * @see setTextRow
+ */
+ const std::string& getTextRow(int row) const;
+
+ /**
+ * Sets the text of a certain row of the text.
+ *
+ * @param row The number of the row to set in the text.
+ * @param text The text to set in the given row number.
+ * @see getTextRow
+ */
+ void setTextRow(int row, const std::string& text);
+
+ /**
+ * Gets the number of rows in the text.
+ *
+ * @return The number of rows in the text.
+ */
+ unsigned int getNumberOfRows() const;
+
+ /**
+ * Gets the caret position in the text.
+ *
+ * @return The caret position in the text.
+ * @see setCaretPosition
+ */
+ unsigned int getCaretPosition() const;
+
+ /**
+ * Sets the position of the caret in the text.
+ *
+ * @param position the positon of the caret.
+ * @see getCaretPosition
+ */
+ void setCaretPosition(unsigned int position);
+
+ /**
+ * Gets the row number where the caret is currently located.
+ *
+ * @return The row number where the caret is currently located.
+ * @see setCaretRow
+ */
+ unsigned int getCaretRow() const;
+
+ /**
+ * Sets the row where the caret should be currently located.
+ *
+ * @param The row where the caret should be currently located.
+ * @see getCaretRow
+ */
+ void setCaretRow(int row);
+
+ /**
+ * Gets the column where the caret is currently located.
+ *
+ * @return The column where the caret is currently located.
+ * @see setCaretColumn
+ */
+ unsigned int getCaretColumn() const;
+
+ /**
+ * Sets the column where the caret should be currently located.
+ *
+ * @param The column where the caret should be currently located.
+ * @see getCaretColumn
+ */
+ void setCaretColumn(int column);
+
+ /**
+ * Sets the row and the column where the caret should be curretly
+ * located.
+ *
+ * @param row The row where the caret should be currently located.
+ * @param column The column where the caret should be currently located.
+ * @see getCaretRow, getCaretColumn
+ */
+ void setCaretRowColumn(int row, int column);
+
+ /**
+ * Scrolls the text to the caret if the text box is in a scroll area.
+ *
+ * @see ScrollArea
+ */
+ virtual void scrollToCaret();
+
+ /**
+ * Checks if the text box is editable.
+ *
+ * @return True it the text box is editable, false otherwise.
+ * @see setEditable
+ */
+ bool isEditable() const;
+
+ /**
+ * Sets the text box to be editable or not.
+ *
+ * @param editable True if the text box should be editable, false otherwise.
+ */
+ void setEditable(bool editable);
+
+ /**
+ * Adds a row of text to the end of the text.
+ *
+ * @param row The row to add.
+ */
+ virtual void addRow(const std::string &row);
+
+ /**
+ * Checks if the text box is opaque. An opaque text box will draw
+ * it's background and it's text. A non opaque text box only draw it's
+ * text making it transparent.
+ *
+ * @return True if the text box is opaque, false otherwise.
+ * @see setOpaque
+ */
+ bool isOpaque();
+
+ /**
+ * Sets the text box to be opaque or not. An opaque text box will draw
+ * it's background and it's text. A non opaque text box only draw it's
+ * text making it transparent.
+ *
+ * @param opaque True if the text box should be opaque, false otherwise.
+ * @see isOpaque
+ */
+ void setOpaque(bool opaque);
+
+
+ // Inherited from Widget
+
+// virtual void draw(Graphics* graphics);
+
+ virtual void fontChanged();
+
+
+ // Inherited from KeyListener
+
+ virtual void keyPressed(KeyEvent& keyEvent) override;
+
+
+ // Inherited from MouseListener
+
+ virtual void mousePressed(MouseEvent& mouseEvent) override;
+
+ virtual void mouseDragged(MouseEvent& mouseEvent) override;
+
+ protected:
+ /**
+ * Draws the caret. Overloaded this method if you want to
+ * change the style of the caret.
+ *
+ * @param graphics a Graphics object to draw with.
+ * @param x the x position.
+ * @param y the y position.
+ */
+ virtual void drawCaret(Graphics* graphics, int x, int y);
+
+ /**
+ * Adjusts the text box's size to fit the text.
+ */
+ virtual void adjustSize();
+
+ /**
+ * Holds all the rows of the text.
+ */
+ std::vector<std::string> mTextRows;
+
+ /**
+ * Holds the current column of the caret.
+ */
+ int mCaretColumn;
+
+ /**
+ * Holds the current row of the caret.
+ */
+ int mCaretRow;
+
+ /**
+ * True if the text box is editable, false otherwise.
+ */
+ bool mEditable;
+
+ /**
+ * True if the text box is editable, false otherwise.
+ */
+ bool mOpaque;
+ };
+} // namespace gcn
+
+#endif // end GCN_TEXTBOX_HPP
diff --git a/src/gui/base/widgets/textfield.cpp b/src/gui/base/widgets/textfield.cpp
new file mode 100644
index 000000000..c2cead500
--- /dev/null
+++ b/src/gui/base/widgets/textfield.cpp
@@ -0,0 +1,163 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "gui/base/widgets/textfield.hpp"
+
+#include "gui/font.h"
+
+#include "debug.h"
+
+namespace gcn
+{
+ TextField::TextField(const Widget2 *const widget) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mText(),
+ mCaretPosition(0),
+ mXScroll(0)
+ {
+ setFocusable(true);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ TextField::TextField(const Widget2 *const widget,
+ const std::string& text) :
+ Widget(widget),
+ MouseListener(),
+ KeyListener(),
+ mText(text),
+ mCaretPosition(0),
+ mXScroll(0)
+ {
+ adjustSize();
+
+ setFocusable(true);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ void TextField::setText(const std::string& text)
+ {
+ const size_t sz = text.size();
+ if (sz < mCaretPosition)
+ mCaretPosition = sz;
+ mText = text;
+ }
+
+ void TextField::drawCaret(Graphics* graphics A_UNUSED, int x A_UNUSED)
+ {
+ }
+
+ void TextField::mousePressed(MouseEvent& mouseEvent)
+ {
+ if (mouseEvent.getButton() == MouseEvent::LEFT)
+ {
+ mCaretPosition = getFont()->getStringIndexAt(
+ mText, mouseEvent.getX() + mXScroll);
+ fixScroll();
+ }
+ }
+
+ void TextField::mouseDragged(MouseEvent& mouseEvent)
+ {
+ mouseEvent.consume();
+ }
+
+ void TextField::adjustSize()
+ {
+ }
+
+ void TextField::adjustHeight()
+ {
+ }
+
+ void TextField::fixScroll()
+ {
+ }
+
+ void TextField::setCaretPosition(unsigned int position A_UNUSED)
+ {
+ }
+
+ unsigned int TextField::getCaretPosition() const
+ {
+ return mCaretPosition;
+ }
+
+ const std::string& TextField::getText() const
+ {
+ return mText;
+ }
+
+ void TextField::fontChanged()
+ {
+ }
+} // namespace gcn
diff --git a/src/gui/base/widgets/textfield.hpp b/src/gui/base/widgets/textfield.hpp
new file mode 100644
index 000000000..e9df238ba
--- /dev/null
+++ b/src/gui/base/widgets/textfield.hpp
@@ -0,0 +1,192 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCN_TEXTFIELD_HPP
+#define GCN_TEXTFIELD_HPP
+
+#include "listeners/keylistener.h"
+#include "listeners/mouselistener.h"
+
+#include "gui/widgets/widget.h"
+
+#include <string>
+
+namespace gcn
+{
+ /**
+ * An implementation of a text field where a user can enter a line of text.
+ */
+ class TextField:
+ public Widget,
+ public MouseListener,
+ public KeyListener
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ explicit TextField(const Widget2 *const widget);
+
+ /**
+ * Constructor. The text field will be automatically resized
+ * to fit the text.
+ *
+ * @param text The default text of the text field.
+ */
+ TextField(const Widget2 *const widget,
+ const std::string& text);
+
+ A_DELETE_COPY(TextField)
+
+ /**
+ * Sets the text of the text field.
+ *
+ * @param text The text of the text field.
+ * @see getText
+ */
+ void setText(const std::string& text);
+
+ /**
+ * Gets the text of the text field.
+ *
+ * @return The text of the text field.
+ * @see setText
+ */
+ const std::string& getText() const;
+
+ /**
+ * Adjusts the size of the text field to fit the text.
+ */
+ void adjustSize();
+
+ /**
+ * Adjusts the height of the text field to fit caption.
+ */
+ void adjustHeight();
+
+ /**
+ * Sets the caret position. As there is only one line of text
+ * in a text field the position is the caret's x coordinate.
+ *
+ * @param position The caret position.
+ * @see getCaretPosition
+ */
+ void setCaretPosition(unsigned int position);
+
+ /**
+ * Gets the caret position. As there is only one line of text
+ * in a text field the position is the caret's x coordinate.
+ *
+ * @return The caret position.
+ * @see setCaretPosition
+ */
+ unsigned int getCaretPosition() const;
+
+
+ // Inherited from Widget
+
+ virtual void fontChanged();
+
+ // Inherited from MouseListener
+
+ virtual void mousePressed(MouseEvent& mouseEvent) override;
+
+ virtual void mouseDragged(MouseEvent& mouseEvent) override;
+
+ protected:
+ /**
+ * Draws the caret. Overloaded this method if you want to
+ * change the style of the caret.
+ *
+ * @param graphics the Graphics object to draw with.
+ * @param x the caret's x-position.
+ */
+ virtual void drawCaret(Graphics* graphics, int x);
+
+ /**
+ * Scrolls the text horizontally so that the caret shows if needed.
+ * The method is used any time a user types in the text field so the
+ * caret always will be shown.
+ */
+ void fixScroll();
+
+ /**
+ * Holds the text of the text box.
+ */
+ std::string mText;
+
+ /**
+ * Holds the caret position.
+ */
+ unsigned int mCaretPosition;
+
+ /**
+ * Holds the amount scrolled in x. If a user types more characters than
+ * the text field can display, due to the text field being to small, the
+ * text needs to scroll in order to show the last type character.
+ */
+ int mXScroll;
+ };
+} // namespace gcn
+
+#endif // end GCN_TEXTFIELD_HPP