Guichan library and few examples, by Lubomyr
This commit is contained in:
995
project/jni/guichan/src/gui.cpp
Normal file
995
project/jni/guichan/src/gui.cpp
Normal file
@@ -0,0 +1,995 @@
|
||||
/* _______ __ __ __ ______ __ __ _______ __ __
|
||||
* / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
|
||||
* / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
|
||||
* / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
|
||||
* / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
|
||||
* /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
|
||||
* \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
|
||||
*
|
||||
* 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/gui.hpp"
|
||||
|
||||
#include "guichan/basiccontainer.hpp"
|
||||
#include "guichan/exception.hpp"
|
||||
#include "guichan/focushandler.hpp"
|
||||
#include "guichan/graphics.hpp"
|
||||
#include "guichan/input.hpp"
|
||||
#include "guichan/keyinput.hpp"
|
||||
#include "guichan/keylistener.hpp"
|
||||
#include "guichan/mouseinput.hpp"
|
||||
#include "guichan/mouselistener.hpp"
|
||||
#include "guichan/widget.hpp"
|
||||
|
||||
namespace gcn
|
||||
{
|
||||
Gui::Gui()
|
||||
:mTop(NULL),
|
||||
mGraphics(NULL),
|
||||
mInput(NULL),
|
||||
mTabbing(true),
|
||||
mShiftPressed(false),
|
||||
mMetaPressed(false),
|
||||
mControlPressed(false),
|
||||
mAltPressed(false),
|
||||
mLastMousePressButton(0),
|
||||
mLastMousePressTimeStamp(0),
|
||||
mLastMouseX(0),
|
||||
mLastMouseY(0),
|
||||
mClickCount(1),
|
||||
mLastMouseDragButton(0)
|
||||
{
|
||||
mFocusHandler = new FocusHandler();
|
||||
}
|
||||
|
||||
Gui::~Gui()
|
||||
{
|
||||
if (Widget::widgetExists(mTop))
|
||||
{
|
||||
setTop(NULL);
|
||||
}
|
||||
|
||||
delete mFocusHandler;
|
||||
}
|
||||
|
||||
void Gui::setTop(Widget* top)
|
||||
{
|
||||
if (mTop != NULL)
|
||||
{
|
||||
mTop->_setFocusHandler(NULL);
|
||||
}
|
||||
if (top != NULL)
|
||||
{
|
||||
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(Input* input)
|
||||
{
|
||||
mInput = input;
|
||||
}
|
||||
|
||||
Input* Gui::getInput() const
|
||||
{
|
||||
return mInput;
|
||||
}
|
||||
|
||||
void Gui::logic()
|
||||
{
|
||||
if (mTop == NULL)
|
||||
{
|
||||
throw GCN_EXCEPTION("No top widget set");
|
||||
}
|
||||
|
||||
handleModalFocus();
|
||||
handleModalMouseInputFocus();
|
||||
|
||||
if (mInput != NULL)
|
||||
{
|
||||
mInput->_pollInput();
|
||||
|
||||
handleKeyInput();
|
||||
handleMouseInput();
|
||||
|
||||
} // end if
|
||||
|
||||
mTop->logic();
|
||||
}
|
||||
|
||||
void Gui::draw()
|
||||
{
|
||||
if (mTop == NULL)
|
||||
{
|
||||
throw GCN_EXCEPTION("No top widget set");
|
||||
}
|
||||
if (mGraphics == NULL)
|
||||
{
|
||||
throw GCN_EXCEPTION("No graphics set");
|
||||
}
|
||||
|
||||
if (!mTop->isVisible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mGraphics->_beginDraw();
|
||||
|
||||
// If top has a frame,
|
||||
// draw it before drawing top
|
||||
if (mTop->getFrameSize() > 0)
|
||||
{
|
||||
Rectangle rec = mTop->getDimension();
|
||||
rec.x -= mTop->getFrameSize();
|
||||
rec.y -= mTop->getFrameSize();
|
||||
rec.width += 2 * mTop->getFrameSize();
|
||||
rec.height += 2 * mTop->getFrameSize();
|
||||
mGraphics->pushClipArea(rec);
|
||||
mTop->drawFrame(mGraphics);
|
||||
mGraphics->popClipArea();
|
||||
}
|
||||
|
||||
mGraphics->pushClipArea(mTop->getDimension());
|
||||
mTop->draw(mGraphics);
|
||||
mGraphics->popClipArea();
|
||||
|
||||
mGraphics->_endDraw();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
while (!mInput->isMouseQueueEmpty())
|
||||
{
|
||||
MouseInput mouseInput = mInput->dequeueMouseInput();
|
||||
|
||||
// Save the current mouse state. It will be needed if modal focus
|
||||
// changes or modal mouse input focus changes.
|
||||
mLastMouseX = mouseInput.getX();
|
||||
mLastMouseY = mouseInput.getY();
|
||||
|
||||
switch (mouseInput.getType())
|
||||
{
|
||||
case MouseInput::PRESSED:
|
||||
handleMousePressed(mouseInput);
|
||||
break;
|
||||
case MouseInput::RELEASED:
|
||||
handleMouseReleased(mouseInput);
|
||||
break;
|
||||
case MouseInput::MOVED:
|
||||
handleMouseMoved(mouseInput);
|
||||
break;
|
||||
case MouseInput::WHEEL_MOVED_DOWN:
|
||||
handleMouseWheelMovedDown(mouseInput);
|
||||
break;
|
||||
case MouseInput::WHEEL_MOVED_UP:
|
||||
handleMouseWheelMovedUp(mouseInput);
|
||||
break;
|
||||
default:
|
||||
throw GCN_EXCEPTION("Unknown mouse input type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::handleKeyInput()
|
||||
{
|
||||
while (!mInput->isKeyQueueEmpty())
|
||||
{
|
||||
KeyInput keyInput = mInput->dequeueKeyInput();
|
||||
|
||||
// Save modifiers state
|
||||
mShiftPressed = keyInput.isShiftPressed();
|
||||
mMetaPressed = keyInput.isMetaPressed();
|
||||
mControlPressed = keyInput.isControlPressed();
|
||||
mAltPressed = keyInput.isAltPressed();
|
||||
|
||||
KeyEvent keyEventToGlobalKeyListeners(NULL,
|
||||
mShiftPressed,
|
||||
mControlPressed,
|
||||
mAltPressed,
|
||||
mMetaPressed,
|
||||
keyInput.getType(),
|
||||
keyInput.isNumericPad(),
|
||||
keyInput.getKey());
|
||||
|
||||
distributeKeyEventToGlobalKeyListeners(keyEventToGlobalKeyListeners);
|
||||
|
||||
// If a global key listener consumes the event it will not be
|
||||
// sent further to the source of the event.
|
||||
if (keyEventToGlobalKeyListeners.isConsumed())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool keyEventConsumed = false;
|
||||
|
||||
// Send key inputs to the focused widgets
|
||||
if (mFocusHandler->getFocused() != NULL)
|
||||
{
|
||||
KeyEvent keyEvent(getKeyEventSource(),
|
||||
mShiftPressed,
|
||||
mControlPressed,
|
||||
mAltPressed,
|
||||
mMetaPressed,
|
||||
keyInput.getType(),
|
||||
keyInput.isNumericPad(),
|
||||
keyInput.getKey());
|
||||
|
||||
|
||||
if (!mFocusHandler->getFocused()->isFocusable())
|
||||
{
|
||||
mFocusHandler->focusNone();
|
||||
}
|
||||
else
|
||||
{
|
||||
distributeKeyEvent(keyEvent);
|
||||
}
|
||||
|
||||
keyEventConsumed = keyEvent.isConsumed();
|
||||
}
|
||||
|
||||
// If the key event hasn't been consumed and
|
||||
// tabbing is enable check for tab press and
|
||||
// change focus.
|
||||
if (!keyEventConsumed
|
||||
&& mTabbing
|
||||
&& keyInput.getKey().getValue() == Key::TAB
|
||||
&& keyInput.getType() == KeyInput::PRESSED)
|
||||
{
|
||||
if (keyInput.isShiftPressed())
|
||||
{
|
||||
mFocusHandler->tabPrevious();
|
||||
}
|
||||
else
|
||||
{
|
||||
mFocusHandler->tabNext();
|
||||
}
|
||||
}
|
||||
|
||||
} // end while
|
||||
}
|
||||
|
||||
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* 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;
|
||||
std::deque<Widget*>::iterator iter;
|
||||
for (iter = mWidgetWithMouseQueue.begin();
|
||||
iter != mWidgetWithMouseQueue.end();
|
||||
iter++)
|
||||
{
|
||||
Widget* 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() != NULL
|
||||
&& 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 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
while (parent != NULL)
|
||||
{
|
||||
parent = (Widget*)widget->getParent();
|
||||
|
||||
// Check if the widget is present in the "widget with mouse" queue.
|
||||
bool widgetIsPresentInQueue = false;
|
||||
std::deque<Widget*>::iterator iter;
|
||||
for (iter = mWidgetWithMouseQueue.begin();
|
||||
iter != mWidgetWithMouseQueue.end();
|
||||
iter++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
Widget* swap = widget;
|
||||
widget = parent;
|
||||
parent = (Widget*)swap->getParent();
|
||||
}
|
||||
|
||||
if (mFocusHandler->getDraggedWidget() != NULL)
|
||||
{
|
||||
distributeMouseEvent(mFocusHandler->getDraggedWidget(),
|
||||
MouseEvent::DRAGGED,
|
||||
mLastMouseDragButton,
|
||||
mouseInput.getX(),
|
||||
mouseInput.getY());
|
||||
}
|
||||
else
|
||||
{
|
||||
Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
|
||||
distributeMouseEvent(sourceWidget,
|
||||
MouseEvent::MOVED,
|
||||
mouseInput.getButton(),
|
||||
mouseInput.getX(),
|
||||
mouseInput.getY());
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::handleMousePressed(const MouseInput& mouseInput)
|
||||
{
|
||||
Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
|
||||
|
||||
if (mFocusHandler->getDraggedWidget() != NULL)
|
||||
{
|
||||
sourceWidget = mFocusHandler->getDraggedWidget();
|
||||
}
|
||||
|
||||
int sourceWidgetX, sourceWidgetY;
|
||||
sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
|
||||
|
||||
if ((mFocusHandler->getModalFocused() != NULL
|
||||
&& sourceWidget->isModalFocused())
|
||||
|| mFocusHandler->getModalFocused() == NULL)
|
||||
{
|
||||
sourceWidget->requestFocus();
|
||||
}
|
||||
|
||||
if (mouseInput.getTimeStamp() - mLastMousePressTimeStamp < 250
|
||||
&& mLastMousePressButton == mouseInput.getButton())
|
||||
{
|
||||
mClickCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mClickCount = 1;
|
||||
}
|
||||
|
||||
distributeMouseEvent(sourceWidget,
|
||||
MouseEvent::PRESSED,
|
||||
mouseInput.getButton(),
|
||||
mouseInput.getX(),
|
||||
mouseInput.getY());
|
||||
|
||||
mFocusHandler->setLastWidgetPressed(sourceWidget);
|
||||
|
||||
mFocusHandler->setDraggedWidget(sourceWidget);
|
||||
mLastMouseDragButton = mouseInput.getButton();
|
||||
|
||||
mLastMousePressButton = mouseInput.getButton();
|
||||
mLastMousePressTimeStamp = mouseInput.getTimeStamp();
|
||||
}
|
||||
|
||||
void Gui::handleMouseWheelMovedDown(const MouseInput& mouseInput)
|
||||
{
|
||||
Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
|
||||
|
||||
if (mFocusHandler->getDraggedWidget() != NULL)
|
||||
{
|
||||
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() != NULL)
|
||||
{
|
||||
sourceWidget = mFocusHandler->getDraggedWidget();
|
||||
}
|
||||
|
||||
int sourceWidgetX, sourceWidgetY;
|
||||
sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
|
||||
|
||||
distributeMouseEvent(sourceWidget,
|
||||
MouseEvent::WHEEL_MOVED_UP,
|
||||
mouseInput.getButton(),
|
||||
mouseInput.getX(),
|
||||
mouseInput.getY());
|
||||
}
|
||||
|
||||
void Gui::handleMouseReleased(const MouseInput& mouseInput)
|
||||
{
|
||||
Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
|
||||
|
||||
if (mFocusHandler->getDraggedWidget() != NULL)
|
||||
{
|
||||
if (sourceWidget != mFocusHandler->getLastWidgetPressed())
|
||||
{
|
||||
mFocusHandler->setLastWidgetPressed(NULL);
|
||||
}
|
||||
|
||||
sourceWidget = mFocusHandler->getDraggedWidget();
|
||||
}
|
||||
|
||||
int sourceWidgetX, sourceWidgetY;
|
||||
sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
|
||||
|
||||
distributeMouseEvent(sourceWidget,
|
||||
MouseEvent::RELEASED,
|
||||
mouseInput.getButton(),
|
||||
mouseInput.getX(),
|
||||
mouseInput.getY());
|
||||
|
||||
if (mouseInput.getButton() == mLastMousePressButton
|
||||
&& mFocusHandler->getLastWidgetPressed() == sourceWidget)
|
||||
{
|
||||
distributeMouseEvent(sourceWidget,
|
||||
MouseEvent::CLICKED,
|
||||
mouseInput.getButton(),
|
||||
mouseInput.getX(),
|
||||
mouseInput.getY());
|
||||
|
||||
mFocusHandler->setLastWidgetPressed(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLastMousePressButton = 0;
|
||||
mClickCount = 0;
|
||||
}
|
||||
|
||||
if (mFocusHandler->getDraggedWidget() != NULL)
|
||||
{
|
||||
mFocusHandler->setDraggedWidget(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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 != NULL)
|
||||
{
|
||||
Widget* 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* widget = getWidgetAt(x, y);
|
||||
|
||||
if (mFocusHandler->getModalMouseInputFocused() != NULL
|
||||
&& !widget->isModalMouseInputFocused())
|
||||
{
|
||||
return mFocusHandler->getModalMouseInputFocused();
|
||||
}
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
Widget* Gui::getKeyEventSource()
|
||||
{
|
||||
Widget* widget = mFocusHandler->getFocused();
|
||||
|
||||
while (widget->_getInternalFocusHandler() != NULL
|
||||
&& widget->_getInternalFocusHandler()->getFocused() != NULL)
|
||||
{
|
||||
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() != NULL
|
||||
&& !widget->isModalFocused()
|
||||
&& !force)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFocusHandler->getModalMouseInputFocused() != NULL
|
||||
&& !widget->isModalMouseInputFocused()
|
||||
&& !force)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MouseEvent mouseEvent(source,
|
||||
mShiftPressed,
|
||||
mControlPressed,
|
||||
mAltPressed,
|
||||
mMetaPressed,
|
||||
type,
|
||||
button,
|
||||
x,
|
||||
y,
|
||||
mClickCount);
|
||||
|
||||
while (parent != NULL)
|
||||
{
|
||||
// If the widget has been removed due to input
|
||||
// cancel the distribution.
|
||||
if (!Widget::widgetExists(widget))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
parent = (Widget*)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*>::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:
|
||||
throw GCN_EXCEPTION("Unknown mouse event type.");
|
||||
}
|
||||
}
|
||||
|
||||
if (toSourceOnly)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Widget* swap = widget;
|
||||
widget = parent;
|
||||
parent = (Widget*)swap->getParent();
|
||||
|
||||
// If a non modal focused widget has been reach
|
||||
// and we have modal focus cancel the distribution.
|
||||
if (mFocusHandler->getModalFocused() != NULL
|
||||
&& !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() != NULL
|
||||
&& !widget->isModalMouseInputFocused())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::distributeKeyEvent(KeyEvent& keyEvent)
|
||||
{
|
||||
Widget* parent = keyEvent.getSource();
|
||||
Widget* widget = keyEvent.getSource();
|
||||
|
||||
if (mFocusHandler->getModalFocused() != NULL
|
||||
&& !widget->isModalFocused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFocusHandler->getModalMouseInputFocused() != NULL
|
||||
&& !widget->isModalMouseInputFocused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (parent != NULL)
|
||||
{
|
||||
// If the widget has been removed due to input
|
||||
// cancel the distribution.
|
||||
if (!Widget::widgetExists(widget))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
parent = (Widget*)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*>::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:
|
||||
throw GCN_EXCEPTION("Unknown key event type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget* swap = widget;
|
||||
widget = parent;
|
||||
parent = (Widget*)swap->getParent();
|
||||
|
||||
// If a non modal focused widget has been reach
|
||||
// and we have modal focus cancel the distribution.
|
||||
if (mFocusHandler->getModalFocused() != NULL
|
||||
&& !widget->isModalFocused())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::distributeKeyEventToGlobalKeyListeners(KeyEvent& keyEvent)
|
||||
{
|
||||
KeyListenerListIterator it;
|
||||
|
||||
for (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:
|
||||
throw GCN_EXCEPTION("Unknown key event type.");
|
||||
}
|
||||
|
||||
if (keyEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::handleModalMouseInputFocus()
|
||||
{
|
||||
// Check if modal mouse input focus has been gained by a widget.
|
||||
if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus()
|
||||
!= mFocusHandler->getModalMouseInputFocused())
|
||||
&& (mFocusHandler->getLastWidgetWithModalMouseInputFocus() == NULL))
|
||||
{
|
||||
handleModalFocusGained();
|
||||
mFocusHandler->setLastWidgetWithModalMouseInputFocus(mFocusHandler->getModalMouseInputFocused());
|
||||
}
|
||||
// Check if modal mouse input focus has been released.
|
||||
else if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus()
|
||||
!= mFocusHandler->getModalMouseInputFocused())
|
||||
&& (mFocusHandler->getLastWidgetWithModalMouseInputFocus() != NULL))
|
||||
{
|
||||
handleModalFocusReleased();
|
||||
mFocusHandler->setLastWidgetWithModalMouseInputFocus(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::handleModalFocus()
|
||||
{
|
||||
// Check if modal focus has been gained by a widget.
|
||||
if ((mFocusHandler->getLastWidgetWithModalFocus()
|
||||
!= mFocusHandler->getModalFocused())
|
||||
&& (mFocusHandler->getLastWidgetWithModalFocus() == NULL))
|
||||
{
|
||||
handleModalFocusGained();
|
||||
mFocusHandler->setLastWidgetWithModalFocus(mFocusHandler->getModalFocused());
|
||||
}
|
||||
// Check if modal focus has been released.
|
||||
else if ((mFocusHandler->getLastWidgetWithModalFocus()
|
||||
!= mFocusHandler->getModalFocused())
|
||||
&& (mFocusHandler->getLastWidgetWithModalFocus() != NULL))
|
||||
{
|
||||
handleModalFocusReleased();
|
||||
mFocusHandler->setLastWidgetWithModalFocus(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::handleModalFocusGained()
|
||||
{
|
||||
// Distribute an event to all widgets in the "widget with mouse" queue.
|
||||
while (!mWidgetWithMouseQueue.empty())
|
||||
{
|
||||
Widget* 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 != NULL)
|
||||
{
|
||||
parent = (Widget*)widget->getParent();
|
||||
|
||||
// Check if the widget is present in the "widget with mouse" queue.
|
||||
bool widgetIsPresentInQueue = false;
|
||||
std::deque<Widget*>::iterator iter;
|
||||
for (iter = mWidgetWithMouseQueue.begin();
|
||||
iter != mWidgetWithMouseQueue.end();
|
||||
iter++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
Widget* swap = widget;
|
||||
widget = parent;
|
||||
parent = (Widget*)swap->getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user