summaryrefslogtreecommitdiff
path: root/src/guichan/widget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/guichan/widget.cpp')
-rw-r--r--src/guichan/widget.cpp735
1 files changed, 735 insertions, 0 deletions
diff --git a/src/guichan/widget.cpp b/src/guichan/widget.cpp
new file mode 100644
index 000000000..7dfc7e10d
--- /dev/null
+++ b/src/guichan/widget.cpp
@@ -0,0 +1,735 @@
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * 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 "guichan/widget.hpp"
+
+#include "guichan/actionevent.hpp"
+#include "guichan/actionlistener.hpp"
+#include "guichan/basiccontainer.hpp"
+#include "guichan/deathlistener.hpp"
+#include "guichan/defaultfont.hpp"
+#include "guichan/event.hpp"
+#include "guichan/exception.hpp"
+#include "guichan/focushandler.hpp"
+#include "guichan/graphics.hpp"
+#include "guichan/keyinput.hpp"
+#include "guichan/keylistener.hpp"
+#include "guichan/mouseinput.hpp"
+#include "guichan/mouselistener.hpp"
+#include "guichan/widgetlistener.hpp"
+
+namespace gcn
+{
+ Font* Widget::mGlobalFont = NULL;
+ DefaultFont Widget::mDefaultFont;
+ std::list<Widget*> Widget::mWidgets;
+
+ Widget::Widget()
+ : mForegroundColor(0x000000),
+ mBackgroundColor(0xffffff),
+ mBaseColor(0x808090),
+ mSelectionColor(0xc3d9ff),
+ mFocusHandler(NULL),
+ mInternalFocusHandler(NULL),
+ mParent(NULL),
+ mFrameSize(0),
+ mFocusable(false),
+ mVisible(true),
+ mTabIn(true),
+ mTabOut(true),
+ mEnabled(true),
+ mCurrentFont(NULL)
+ {
+ mWidgets.push_back(this);
+ }
+
+ Widget::~Widget()
+ {
+ DeathListenerIterator iter;
+
+ for (iter = mDeathListeners.begin(); iter != mDeathListeners.end(); ++iter)
+ {
+ Event event(this);
+ (*iter)->death(event);
+ }
+
+ _setFocusHandler(NULL);
+
+ mWidgets.remove(this);
+ }
+
+ void Widget::drawFrame(Graphics* graphics)
+ {
+ Color faceColor = getBaseColor();
+ Color highlightColor, shadowColor;
+ int alpha = getBaseColor().a;
+ int width = getWidth() + getFrameSize() * 2 - 1;
+ int height = getHeight() + getFrameSize() * 2 - 1;
+ highlightColor = faceColor + 0x303030;
+ highlightColor.a = alpha;
+ shadowColor = faceColor - 0x303030;
+ shadowColor.a = alpha;
+
+ unsigned int i;
+ for (i = 0; i < getFrameSize(); ++i)
+ {
+ graphics->setColor(shadowColor);
+ graphics->drawLine(i,i, width - i, i);
+ graphics->drawLine(i,i + 1, i, height - i - 1);
+ graphics->setColor(highlightColor);
+ graphics->drawLine(width - i,i + 1, width - i, height - i);
+ graphics->drawLine(i,height - i, width - i - 1, height - i);
+ }
+ }
+
+ void Widget::_setParent(Widget* parent)
+ {
+ mParent = parent;
+ }
+
+ Widget* Widget::getParent() const
+ {
+ return mParent;
+ }
+
+ void Widget::setWidth(int width)
+ {
+ Rectangle newDimension = mDimension;
+ newDimension.width = width;
+
+ setDimension(newDimension);
+ }
+
+ int Widget::getWidth() const
+ {
+ return mDimension.width;
+ }
+
+ void Widget::setHeight(int height)
+ {
+ Rectangle newDimension = mDimension;
+ newDimension.height = height;
+
+ setDimension(newDimension);
+ }
+
+ int Widget::getHeight() const
+ {
+ return mDimension.height;
+ }
+
+ void Widget::setX(int x)
+ {
+ Rectangle newDimension = mDimension;
+ newDimension.x = x;
+
+ setDimension(newDimension);
+ }
+
+ int Widget::getX() const
+ {
+ return mDimension.x;
+ }
+
+ void Widget::setY(int y)
+ {
+ Rectangle newDimension = mDimension;
+ newDimension.y = y;
+
+ setDimension(newDimension);
+ }
+
+ int Widget::getY() const
+ {
+ return mDimension.y;
+ }
+
+ void Widget::setPosition(int x, int y)
+ {
+ Rectangle newDimension = mDimension;
+ newDimension.x = x;
+ newDimension.y = y;
+
+ setDimension(newDimension);
+ }
+
+ void Widget::setDimension(const Rectangle& dimension)
+ {
+ Rectangle oldDimension = mDimension;
+ mDimension = dimension;
+
+ if (mDimension.width != oldDimension.width
+ || mDimension.height != oldDimension.height)
+ {
+ distributeResizedEvent();
+ }
+
+ if (mDimension.x != oldDimension.x
+ || mDimension.y != oldDimension.y)
+ {
+ distributeMovedEvent();
+ }
+ }
+
+ void Widget::setFrameSize(unsigned int frameSize)
+ {
+ mFrameSize = frameSize;
+ }
+
+ unsigned int Widget::getFrameSize() const
+ {
+ return mFrameSize;
+ }
+
+ const Rectangle& Widget::getDimension() const
+ {
+ return mDimension;
+ }
+
+ const std::string& Widget::getActionEventId() const
+ {
+ return mActionEventId;
+ }
+
+ void Widget::setActionEventId(const std::string& actionEventId)
+ {
+ mActionEventId = actionEventId;
+ }
+
+ bool Widget::isFocused() const
+ {
+ if (!mFocusHandler)
+ {
+ return false;
+ }
+
+ return (mFocusHandler->isFocused(this));
+ }
+
+ void Widget::setFocusable(bool focusable)
+ {
+ if (!focusable && isFocused())
+ {
+ mFocusHandler->focusNone();
+ }
+
+ mFocusable = focusable;
+ }
+
+ bool Widget::isFocusable() const
+ {
+ return mFocusable && isVisible() && isEnabled();
+ }
+
+ void Widget::requestFocus()
+ {
+ if (mFocusHandler == NULL)
+ {
+ throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
+ }
+
+ if (isFocusable())
+ {
+ mFocusHandler->requestFocus(this);
+ }
+ }
+
+ void Widget::requestMoveToTop()
+ {
+ if (mParent)
+ {
+ mParent->moveToTop(this);
+ }
+ }
+
+ void Widget::requestMoveToBottom()
+ {
+ if (mParent)
+ {
+ mParent->moveToBottom(this);
+ }
+ }
+
+ void Widget::setVisible(bool visible)
+ {
+ if (!visible && isFocused())
+ {
+ mFocusHandler->focusNone();
+ }
+
+ if (visible)
+ {
+ distributeShownEvent();
+ }
+ else if(!visible)
+ {
+ distributeHiddenEvent();
+ }
+
+ mVisible = visible;
+ }
+
+ bool Widget::isVisible() const
+ {
+ if (getParent() == NULL)
+ {
+ return mVisible;
+ }
+ else
+ {
+ return mVisible && getParent()->isVisible();
+ }
+ }
+
+ void Widget::setBaseColor(const Color& color)
+ {
+ mBaseColor = color;
+ }
+
+ const Color& Widget::getBaseColor() const
+ {
+ return mBaseColor;
+ }
+
+ void Widget::setForegroundColor(const Color& color)
+ {
+ mForegroundColor = color;
+ }
+
+ const Color& Widget::getForegroundColor() const
+ {
+ return mForegroundColor;
+ }
+
+ void Widget::setBackgroundColor(const Color& color)
+ {
+ mBackgroundColor = color;
+ }
+
+ const Color& Widget::getBackgroundColor() const
+ {
+ return mBackgroundColor;
+ }
+
+ void Widget::setSelectionColor(const Color& color)
+ {
+ mSelectionColor = color;
+ }
+
+ const Color& Widget::getSelectionColor() const
+ {
+ return mSelectionColor;
+ }
+
+ void Widget::_setFocusHandler(FocusHandler* focusHandler)
+ {
+ if (mFocusHandler)
+ {
+ releaseModalFocus();
+ mFocusHandler->remove(this);
+ }
+
+ if (focusHandler)
+ {
+ focusHandler->add(this);
+ }
+
+ mFocusHandler = focusHandler;
+ }
+
+ FocusHandler* Widget::_getFocusHandler()
+ {
+ return mFocusHandler;
+ }
+
+ void Widget::addActionListener(ActionListener* actionListener)
+ {
+ mActionListeners.push_back(actionListener);
+ }
+
+ void Widget::removeActionListener(ActionListener* actionListener)
+ {
+ mActionListeners.remove(actionListener);
+ }
+
+ void Widget::addDeathListener(DeathListener* deathListener)
+ {
+ mDeathListeners.push_back(deathListener);
+ }
+
+ void Widget::removeDeathListener(DeathListener* deathListener)
+ {
+ mDeathListeners.remove(deathListener);
+ }
+
+ void Widget::addKeyListener(KeyListener* keyListener)
+ {
+ mKeyListeners.push_back(keyListener);
+ }
+
+ void Widget::removeKeyListener(KeyListener* keyListener)
+ {
+ mKeyListeners.remove(keyListener);
+ }
+
+ void Widget::addFocusListener(FocusListener* focusListener)
+ {
+ mFocusListeners.push_back(focusListener);
+ }
+
+ void Widget::removeFocusListener(FocusListener* focusListener)
+ {
+ mFocusListeners.remove(focusListener);
+ }
+
+ void Widget::addMouseListener(MouseListener* mouseListener)
+ {
+ mMouseListeners.push_back(mouseListener);
+ }
+
+ void Widget::removeMouseListener(MouseListener* mouseListener)
+ {
+ mMouseListeners.remove(mouseListener);
+ }
+
+ void Widget::addWidgetListener(WidgetListener* widgetListener)
+ {
+ mWidgetListeners.push_back(widgetListener);
+ }
+
+ void Widget::removeWidgetListener(WidgetListener* widgetListener)
+ {
+ mWidgetListeners.remove(widgetListener);
+ }
+
+ void Widget::getAbsolutePosition(int& x, int& y) const
+ {
+ if (getParent() == NULL)
+ {
+ x = mDimension.x;
+ y = mDimension.y;
+ return;
+ }
+
+ int parentX;
+ int parentY;
+
+ getParent()->getAbsolutePosition(parentX, parentY);
+
+ x = parentX + mDimension.x + getParent()->getChildrenArea().x;
+ y = parentY + mDimension.y + getParent()->getChildrenArea().y;
+ }
+
+ Font* Widget::getFont() const
+ {
+ if (mCurrentFont == NULL)
+ {
+ if (mGlobalFont == NULL)
+ {
+ return &mDefaultFont;
+ }
+
+ return mGlobalFont;
+ }
+
+ return mCurrentFont;
+ }
+
+ void Widget::setGlobalFont(Font* font)
+ {
+ mGlobalFont = font;
+
+ std::list<Widget*>::iterator iter;
+ for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter)
+ {
+ if ((*iter)->mCurrentFont == NULL)
+ {
+ (*iter)->fontChanged();
+ }
+ }
+ }
+
+ void Widget::setFont(Font* font)
+ {
+ mCurrentFont = font;
+ fontChanged();
+ }
+
+ bool Widget::widgetExists(const Widget* widget)
+ {
+ bool result = false;
+
+ std::list<Widget*>::iterator iter;
+ for (iter = mWidgets.begin(); iter != mWidgets.end(); ++iter)
+ {
+ if (*iter == widget)
+ {
+ return true;
+ }
+ }
+
+ return result;
+ }
+
+ bool Widget::isTabInEnabled() const
+ {
+ return mTabIn;
+ }
+
+ void Widget::setTabInEnabled(bool enabled)
+ {
+ mTabIn = enabled;
+ }
+
+ bool Widget::isTabOutEnabled() const
+ {
+ return mTabOut;
+ }
+
+ void Widget::setTabOutEnabled(bool enabled)
+ {
+ mTabOut = enabled;
+ }
+
+ void Widget::setSize(int width, int height)
+ {
+ Rectangle newDimension = mDimension;
+ newDimension.width = width;
+ newDimension.height = height;
+
+ setDimension(newDimension);
+ }
+
+ void Widget::setEnabled(bool enabled)
+ {
+ mEnabled = enabled;
+ }
+
+ bool Widget::isEnabled() const
+ {
+ return mEnabled && isVisible();
+ }
+
+ void Widget::requestModalFocus()
+ {
+ if (mFocusHandler == NULL)
+ {
+ throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
+ }
+
+ mFocusHandler->requestModalFocus(this);
+ }
+
+ void Widget::requestModalMouseInputFocus()
+ {
+ if (mFocusHandler == NULL)
+ {
+ throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
+ }
+
+ mFocusHandler->requestModalMouseInputFocus(this);
+ }
+
+ void Widget::releaseModalFocus()
+ {
+ if (mFocusHandler == NULL)
+ {
+ return;
+ }
+
+ mFocusHandler->releaseModalFocus(this);
+ }
+
+ void Widget::releaseModalMouseInputFocus()
+ {
+ if (mFocusHandler == NULL)
+ {
+ return;
+ }
+
+ mFocusHandler->releaseModalMouseInputFocus(this);
+ }
+
+ bool Widget::isModalFocused() const
+ {
+ if (mFocusHandler == NULL)
+ {
+ throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
+ }
+
+ if (getParent() != NULL)
+ {
+ return (mFocusHandler->getModalFocused() == this)
+ || getParent()->isModalFocused();
+ }
+
+ return mFocusHandler->getModalFocused() == this;
+ }
+
+ bool Widget::isModalMouseInputFocused() const
+ {
+ if (mFocusHandler == NULL)
+ {
+ throw GCN_EXCEPTION("No focushandler set (did you add the widget to the gui?).");
+ }
+
+ if (getParent() != NULL)
+ {
+ return (mFocusHandler->getModalMouseInputFocused() == this)
+ || getParent()->isModalMouseInputFocused();
+ }
+
+ return mFocusHandler->getModalMouseInputFocused() == this;
+ }
+
+ Widget *Widget::getWidgetAt(int x, int y)
+ {
+ return NULL;
+ }
+
+ const std::list<MouseListener*>& Widget::_getMouseListeners()
+ {
+ return mMouseListeners;
+ }
+
+ const std::list<KeyListener*>& Widget::_getKeyListeners()
+ {
+ return mKeyListeners;
+ }
+
+ const std::list<FocusListener*>& Widget::_getFocusListeners()
+ {
+ return mFocusListeners;
+ }
+
+ Rectangle Widget::getChildrenArea()
+ {
+ return Rectangle(0, 0, 0, 0);
+ }
+
+ FocusHandler* Widget::_getInternalFocusHandler()
+ {
+ return mInternalFocusHandler;
+ }
+
+ void Widget::setInternalFocusHandler(FocusHandler* focusHandler)
+ {
+ mInternalFocusHandler = focusHandler;
+ }
+
+ void Widget::setId(const std::string& id)
+ {
+ mId = id;
+ }
+
+ const std::string& Widget::getId()
+ {
+ return mId;
+ }
+
+ void Widget::distributeResizedEvent()
+ {
+ WidgetListenerIterator iter;
+
+ for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter)
+ {
+ Event event(this);
+ (*iter)->widgetResized(event);
+ }
+ }
+
+ void Widget::distributeMovedEvent()
+ {
+ WidgetListenerIterator iter;
+
+ for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter)
+ {
+ Event event(this);
+ (*iter)->widgetMoved(event);
+ }
+ }
+
+ void Widget::distributeHiddenEvent()
+ {
+ WidgetListenerIterator iter;
+
+ for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter)
+ {
+ Event event(this);
+ (*iter)->widgetHidden(event);
+ }
+ }
+
+ void Widget::distributeActionEvent()
+ {
+ ActionListenerIterator iter;
+ for (iter = mActionListeners.begin(); iter != mActionListeners.end(); ++iter)
+ {
+ ActionEvent actionEvent(this, mActionEventId);
+ (*iter)->action(actionEvent);
+ }
+ }
+
+ void Widget::distributeShownEvent()
+ {
+ WidgetListenerIterator iter;
+
+ for (iter = mWidgetListeners.begin(); iter != mWidgetListeners.end(); ++iter)
+ {
+ Event event(this);
+ (*iter)->widgetShown(event);
+ }
+ }
+
+ void Widget::showPart(Rectangle rectangle)
+ {
+ if (mParent != NULL)
+ {
+ mParent->showWidgetPart(this, rectangle);
+ }
+ }
+}