mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-26 13:34:22 +01:00
736 lines
17 KiB
C++
736 lines
17 KiB
C++
/* _______ __ __ __ ______ __ __ _______ __ __
|
|
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
|
|
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
|
|
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
|
|
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
|
|
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
|
|
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
|
|
*
|
|
* 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);
|
|
}
|
|
}
|
|
}
|