cleanup in GUI module (moved event handling out of Screen)

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3763 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2009-07-18 16:04:45 +00:00
parent fbc3119dbc
commit b71d1c4557
9 changed files with 457 additions and 380 deletions

View File

@@ -76,6 +76,8 @@ supertuxkart_SOURCES = \
gui/credits.hpp \
gui/engine.cpp \
gui/engine.hpp \
gui/event_handler.cpp \
gui/event_handler.hpp \
gui/kart_selection.cpp \
gui/kart_selection.hpp \
gui/modaldialog.cpp \

View File

@@ -25,6 +25,7 @@
#include "input/input_manager.hpp"
#include "gui/credits.hpp"
#include "gui/screen.hpp"
#include "gui/event_handler.hpp"
#include "gui/kart_selection.hpp"
#include "gui/skin.hpp"
#include "gui/state_manager.hpp"
@@ -50,30 +51,6 @@ namespace GUIEngine
return dt;
}
class IrrlichtEventCore : public IEventReceiver
{
public:
IrrlichtEventCore()
{
}
~IrrlichtEventCore()
{
}
bool OnEvent (const SEvent &event)
{
if(event.EventType == EET_GUI_EVENT ||
(!StateManager::isGameState() && event.EventType != EET_KEY_INPUT_EVENT && event.EventType != EET_JOYSTICK_INPUT_EVENT)
)
{
if(g_current_screen == NULL) return false;
g_current_screen->OnEvent(event);
return false;
}
else
return input_manager->input(event);
}
};
IrrlichtEventCore* g_irrlicht_event_core = NULL;
// -----------------------------------------------------------------------------
IrrlichtDevice* getDevice()
{
@@ -105,8 +82,6 @@ void cleanForGame()
{
clear();
needsUpdate.clearWithoutDeleting();
if(g_irrlicht_event_core == NULL) g_irrlicht_event_core = new IrrlichtEventCore();
g_device->setEventReceiver(g_irrlicht_event_core);
}
// -----------------------------------------------------------------------------
void switchToScreen(const char* screen_name)
@@ -137,16 +112,9 @@ void switchToScreen(const char* screen_name)
g_current_screen = new_screen;
}
// show screen
g_current_screen->addWidgets();
// set event listener
if(g_irrlicht_event_core == NULL) g_irrlicht_event_core = new IrrlichtEventCore();
g_device->setEventReceiver(g_irrlicht_event_core);
//g_env->setUserEventReceiver(g_irrlicht_event_core);
}
// -----------------------------------------------------------------------------
/** to be called after e.g. a resolution switch */
@@ -195,6 +163,9 @@ void init(IrrlichtDevice* device_a, IVideoDriver* driver_a, void (*eventCallback
if (g_font) g_skin->setFont(g_font);
//g_skin->setFont(g_env->getBuiltInFont(), EGDF_TOOLTIP);
// set event receiver
g_device->setEventReceiver(EventHandler::get());
}
// -----------------------------------------------------------------------------
/** transmit event to user event callback (out of encapsulated GUI module) */

372
src/gui/event_handler.cpp Normal file
View File

@@ -0,0 +1,372 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Marianne Gagnon
//
// 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 3
// of the License, or (at your option) 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "gui/event_handler.hpp"
#include "gui/engine.hpp"
#include "gui/modaldialog.hpp"
#include "gui/screen.hpp"
#include "gui/state_manager.hpp"
#include "input/input_manager.hpp"
using GUIEngine::EventHandler;
EventHandler::EventHandler()
{
}
EventHandler::~EventHandler()
{
}
bool EventHandler::OnEvent (const SEvent &event)
{
if(event.EventType == EET_GUI_EVENT ||
(!StateManager::isGameState() && event.EventType != EET_KEY_INPUT_EVENT && event.EventType != EET_JOYSTICK_INPUT_EVENT)
)
{
return onGUIEvent(event);
}
else
{
// FIXME : it's a bit unclean that all input events go trough the gui module
return input_manager->input(event);
}
}
bool EventHandler::onGUIEvent(const SEvent& event)
{
if(event.EventType == EET_GUI_EVENT)
{
const s32 id = event.GUIEvent.Caller->getID();
switch(event.GUIEvent.EventType)
{
case EGET_BUTTON_CLICKED:
case EGET_SCROLL_BAR_CHANGED:
case EGET_CHECKBOX_CHANGED:
case EGET_LISTBOX_SELECTED_AGAIN:
{
Widget* w = GUIEngine::getCurrentScreen()->getWidget(id);
if(w == NULL) break;
return onWidgetActivated(w);
}
case EGET_ELEMENT_HOVERED:
{
Widget* w = GUIEngine::getCurrentScreen()->getWidget(id);
if(w == NULL) break;
// select ribbons on hover
if(w->m_event_handler != NULL && w->m_event_handler->m_type == WTYPE_RIBBON)
{
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(w->m_event_handler);
if(ribbon == NULL) break;
if(ribbon->mouseHovered(w))
transmitEvent(ribbon, ribbon->m_properties[PROP_ID]);
if(ribbon->m_event_handler != NULL) ribbon->m_event_handler->mouseHovered(w);
getGUIEnv()->setFocus(ribbon->m_element);
}
else
{
// focus on hover for other widgets
getGUIEnv()->setFocus(w->m_element);
}
break;
}
/*
case EGET_ELEMENT_LEFT:
{
Widget* el = getWidget(id);
if(el == NULL) break;
break;
}
*/
case EGET_ELEMENT_FOCUSED:
{
Widget* el = GUIEngine::getCurrentScreen()->getWidget(id);
if(el == NULL) break;
el->focused();
break;
}
case EGET_EDITBOX_ENTER:
{
// currently, enter pressed in text ctrl events can only happen in dialogs.
// FIXME : find a cleaner way to route the event to its proper location
if (ModalDialog::isADialogActive()) ModalDialog::onEnterPressed();
break;
}
default:
break;
} // end switch
}
/*
EGET_BUTTON_CLICKED, EGET_SCROLL_BAR_CHANGED, EGET_CHECKBOX_CHANGED, EGET_TAB_CHANGED,
EGET_MENU_ITEM_SELECTED, EGET_COMBO_BOX_CHANGED, EGET_SPINBOX_CHANGED, EGET_EDITBOX_ENTER,
EGET_LISTBOX_CHANGED, EGET_LISTBOX_SELECTED_AGAIN,
EGET_FILE_SELECTED, EGET_FILE_CHOOSE_DIALOG_CANCELLED,
EGET_MESSAGEBOX_YES, EGET_MESSAGEBOX_NO, EGET_MESSAGEBOX_OK, EGET_MESSAGEBOX_CANCEL,
EGET_TABLE_CHANGED, EGET_TABLE_HEADER_CHANGED, EGET_TABLE_SELECTED_AGAIN
EGET_ELEMENT_FOCUS_LOST, EGET_ELEMENT_FOCUSED, EGET_ELEMENT_HOVERED, EGET_ELEMENT_LEFT,
EGET_ELEMENT_CLOSED,
*/
return false;
}
bool EventHandler::onWidgetActivated(Widget* w)
{
if(ModalDialog::isADialogActive() && w->m_event_handler == NULL)
{
ModalDialog::getCurrent()->processEvent(w->m_properties[PROP_ID]);
return false;
}
Widget* parent = w->m_event_handler;
if(w->m_event_handler != NULL)
{
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(parent->m_event_handler != NULL && parent->m_event_handler != parent)
parent = parent->m_event_handler;
/* notify the found event event handler, and also notify the main callback if the
parent event handler says so */
if(parent->transmitEvent(w, w->m_properties[PROP_ID]))
transmitEvent(parent, parent->m_properties[PROP_ID]);
}
else transmitEvent(w, w->m_properties[PROP_ID]);
return true;
}
/**
* Called by the input module
*/
void EventHandler::processAction(const int action, const unsigned int value, Input::InputType type)
{
const bool pressedDown = value > Input::MAX_VALUE*2/3;
if(!pressedDown && type == Input::IT_STICKMOTION) return;
switch(action)
{
case PA_LEFT:
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = GUIEngine::getCurrentScreen()->getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->leftPressed())
transmitEvent(w, w->m_properties[PROP_ID]);
}
break;
case PA_RIGHT:
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = GUIEngine::getCurrentScreen()->getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->rightPressed())
transmitEvent(widget_to_call, w->m_properties[PROP_ID]);
}
break;
case PA_ACCEL:
{
IGUIElement *el, *first=NULL, *closest=NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : GUIEngine::getCurrentScreen()->getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
const bool stay_within_list = list->getSelected() > 0;
if(type == Input::IT_STICKMOTION)
{
// simulate a key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_UP;
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}
if(stay_within_list) break;
else list->setSelected(-1);
}
// find closest widget
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), true /* reverse */, false /* group */, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
// when focusing a list by going up, select the last item of the list
Widget* w = GUIEngine::getCurrentScreen()->getWidget( closest->getID() );
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
list->setSelected( list->getItemCount()-1 );
return;
}
}
else
{
std::cout << "Could not find any!\n";
// select the first widget
Widget* w = GUIEngine::getCurrentScreen()->getLastWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
}
break;
case PA_BRAKE:
{
IGUIElement *el, *first = NULL, *closest = NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : GUIEngine::getCurrentScreen()->getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
const bool stay_within_list = list->getSelected() < (int)list->getItemCount()-1;
if(type == Input::IT_STICKMOTION)
{
// simulate a key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_DOWN;
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}
if(stay_within_list) break;
else list->setSelected(-1);
}
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), false, false, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else
{
// select the first widget
Widget* w = GUIEngine::getCurrentScreen()->getFirstWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
}
break;
case PA_RESCUE:
if(pressedDown)
StateManager::escapePressed();
break;
case PA_FIRE:
if(type == Input::IT_STICKBUTTON)
{
if (pressedDown)
{
IGUIElement* element = GUIEngine::getGUIEnv()->getFocus();
Widget* w = GUIEngine::getCurrentScreen()->getWidget( element->getID() );
if(w == NULL) break;
onWidgetActivated( w );
}
/*
// simulate a 'enter' key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_SPACE; // FIXME : what if keyboard bindings are not set to use this key?
evt.Char = 666; // My magic code to know it's a fake event (FIXME : ugly, but irrlicht doesn't seem to offer better)
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
*/
}
break;
default:
return;
}
}
EventHandler* event_handler_singleton = NULL;
EventHandler* EventHandler::get()
{
if (event_handler_singleton == NULL)
{
event_handler_singleton = new EventHandler();
}
return event_handler_singleton;
}

67
src/gui/event_handler.hpp Normal file
View File

@@ -0,0 +1,67 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Marianne Gagnon
//
// 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 3
// of the License, or (at your option) 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __EVENT_HANDLER_HPP__
#define __EVENT_HANDLER_HPP__
#include "irrlicht.h"
#include "input/input.hpp"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
namespace GUIEngine
{
class Widget;
/**
* Class to handle irrLicht events (GUI and input as well)
* Input events will be redirected to the input module
*/
class EventHandler : public IEventReceiver
{
bool onGUIEvent(const SEvent& event);
bool onWidgetActivated(Widget* w);
public:
EventHandler();
~EventHandler();
/**
* All irrLicht events will go through this (input as well GUI; input events are
* immediately delegated to the input module, GUI events are processed here)
*/
bool OnEvent (const SEvent &event);
/**
* When the input module is done processing an input and mapped it to an action,
* and this action needs to be applied to the GUI (e.g. fire pressed, left
* pressed, etc.) this method is called back by the input module.
*/
void processAction(const int action, const unsigned int value, Input::InputType type);
// singleton
static EventHandler* get();
};
}
#endif

View File

@@ -238,7 +238,7 @@ void Screen::calculateLayout(ptr_vector<Widget>& widgets, Widget* parent)
#if 0
#pragma mark -
#pragma mark Adding widgets
#pragma mark Adding/Removing widgets
#endif
@@ -432,342 +432,4 @@ Widget* Screen::getLastWidget(ptr_vector<Widget>* within_vector)
return NULL;
}
#if 0
#pragma mark -
#pragma mark irrLicht events
#endif
bool Screen::onWidgetActivated(Widget* w)
{
if(ModalDialog::isADialogActive() && w->m_event_handler == NULL)
{
ModalDialog::getCurrent()->processEvent(w->m_properties[PROP_ID]);
return false;
}
Widget* parent = w->m_event_handler;
if(w->m_event_handler != NULL)
{
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(parent->m_event_handler != NULL && parent->m_event_handler != parent)
parent = parent->m_event_handler;
/* notify the found event event handler, and also notify the main callback if the
parent event handler says so */
if(parent->transmitEvent(w, w->m_properties[PROP_ID]))
transmitEvent(parent, parent->m_properties[PROP_ID]);
}
else transmitEvent(w, w->m_properties[PROP_ID]);
return true;
}
void Screen::processAction(const int action, const unsigned int value, Input::InputType type)
{
const bool pressedDown = value > Input::MAX_VALUE*2/3;
if(!pressedDown && type == Input::IT_STICKMOTION) return;
switch(action)
{
case PA_LEFT:
/*
if(type == Input::IT_STICKMOTION)
{
// simulate a key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_LEFT; // FIXME : what if keyboard bindings are not set to use this key?
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}
*/
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->leftPressed())
transmitEvent(w, w->m_properties[PROP_ID]);
}
break;
case PA_RIGHT:
/*
if(type == Input::IT_STICKMOTION)
{
// simulate a key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_RIGHT; // FIXME : what if keyboard bindings are not set to use this key?
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}*/
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->rightPressed())
transmitEvent(widget_to_call, w->m_properties[PROP_ID]);
}
break;
case PA_ACCEL:
{
IGUIElement *el, *first=NULL, *closest=NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
const bool stay_within_list = list->getSelected() > 0;
if(type == Input::IT_STICKMOTION)
{
// simulate a key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_UP;
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}
if(stay_within_list) break;
else list->setSelected(-1);
}
// find closest widget
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), true /* reverse */, false /* group */, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
// when focusing a list by going up, select the last item of the list
Widget* w = getWidget( closest->getID() );
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
list->setSelected( list->getItemCount()-1 );
return;
}
}
else
{
std::cout << "Could not find any!\n";
// select the first widget
Widget* w = getLastWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
}
break;
case PA_BRAKE:
{
IGUIElement *el, *first = NULL, *closest = NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
const bool stay_within_list = list->getSelected() < (int)list->getItemCount()-1;
if(type == Input::IT_STICKMOTION)
{
// simulate a key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_DOWN;
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
}
if(stay_within_list) break;
else list->setSelected(-1);
}
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), false, false, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else
{
// select the first widget
Widget* w = getFirstWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
}
break;
case PA_RESCUE:
if(pressedDown)
StateManager::escapePressed();
break;
case PA_FIRE:
if(type == Input::IT_STICKBUTTON)
{
if (pressedDown)
{
IGUIElement* element = GUIEngine::getGUIEnv()->getFocus();
Widget* w = getWidget( element->getID() );
if(w == NULL) break;
onWidgetActivated( w );
}
/*
// simulate a 'enter' key press
irr::SEvent::SKeyInput evt;
evt.PressedDown = pressedDown;
evt.Key = KEY_SPACE; // FIXME : what if keyboard bindings are not set to use this key?
evt.Char = 666; // My magic code to know it's a fake event (FIXME : ugly, but irrlicht doesn't seem to offer better)
irr::SEvent wrapper;
wrapper.KeyInput = evt;
wrapper.EventType = EET_KEY_INPUT_EVENT;
GUIEngine::getDevice()->postEventFromUser(wrapper);
*/
}
break;
default:
return;
}
}
bool Screen::OnEvent(const SEvent& event)
{
assert(transmitEvent != NULL);
if(event.EventType == EET_GUI_EVENT)
{
const s32 id = event.GUIEvent.Caller->getID();
switch(event.GUIEvent.EventType)
{
case EGET_BUTTON_CLICKED:
case EGET_SCROLL_BAR_CHANGED:
case EGET_CHECKBOX_CHANGED:
case EGET_LISTBOX_SELECTED_AGAIN:
{
Widget* w = getWidget(id);
if(w == NULL) break;
return onWidgetActivated(w);
}
case EGET_ELEMENT_HOVERED:
{
Widget* w = getWidget(id);
if(w == NULL) break;
// select ribbons on hover
if(w->m_event_handler != NULL && w->m_event_handler->m_type == WTYPE_RIBBON)
{
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(w->m_event_handler);
if(ribbon == NULL) break;
if(ribbon->mouseHovered(w))
transmitEvent(ribbon, ribbon->m_properties[PROP_ID]);
if(ribbon->m_event_handler != NULL) ribbon->m_event_handler->mouseHovered(w);
getGUIEnv()->setFocus(ribbon->m_element);
}
else
{
// focus on hover for other widgets
getGUIEnv()->setFocus(w->m_element);
}
break;
}
/*
case EGET_ELEMENT_LEFT:
{
Widget* el = getWidget(id);
if(el == NULL) break;
break;
}
*/
case EGET_ELEMENT_FOCUSED:
{
Widget* el = getWidget(id);
if(el == NULL) break;
el->focused();
break;
}
case EGET_EDITBOX_ENTER:
{
// currently, enter pressed in text ctrl events can only happen in dialogs.
// FIXME : find a cleaner way to route the event to its proper location
if(ModalDialog::isADialogActive()) ModalDialog::onEnterPressed();
break;
}
default:
break;
} // end switch
}
/*
EGET_BUTTON_CLICKED, EGET_SCROLL_BAR_CHANGED, EGET_CHECKBOX_CHANGED, EGET_TAB_CHANGED,
EGET_MENU_ITEM_SELECTED, EGET_COMBO_BOX_CHANGED, EGET_SPINBOX_CHANGED, EGET_EDITBOX_ENTER,
EGET_LISTBOX_CHANGED, EGET_LISTBOX_SELECTED_AGAIN,
EGET_FILE_SELECTED, EGET_FILE_CHOOSE_DIALOG_CANCELLED,
EGET_MESSAGEBOX_YES, EGET_MESSAGEBOX_NO, EGET_MESSAGEBOX_OK, EGET_MESSAGEBOX_CANCEL,
EGET_TABLE_CHANGED, EGET_TABLE_HEADER_CHANGED, EGET_TABLE_SELECTED_AGAIN
EGET_ELEMENT_FOCUS_LOST, EGET_ELEMENT_FOCUSED, EGET_ELEMENT_HOVERED, EGET_ELEMENT_LEFT,
EGET_ELEMENT_CLOSED,
*/
return false;
}

View File

@@ -41,7 +41,7 @@ namespace GUIEngine
void parseScreenFileDiv(irr::io::IrrXMLReader* xml, ptr_vector<Widget>& append_to);
class Screen : public IEventReceiver
class Screen
{
friend class Skin;
@@ -52,7 +52,6 @@ namespace GUIEngine
static void addWidgetsRecursively(ptr_vector<Widget>& widgets, Widget* parent=NULL);
void calculateLayout(ptr_vector<Widget>& widgets, Widget* parent=NULL);
bool onWidgetActivated(Widget* w);
public:
// current mouse position, read-only...
int m_mouse_x, m_mouse_y;
@@ -89,10 +88,6 @@ namespace GUIEngine
const std::string& getName() const { return m_filename; }
void elementsWereDeleted(ptr_vector<Widget>* within_vector = NULL);
virtual bool OnEvent(const SEvent& event);
void processAction(const int action, const unsigned int value, Input::InputType type);
};
}

View File

@@ -77,6 +77,7 @@ namespace GUIEngine
class Widget : public SkinWidgetContainer
{
friend class EventHandler;
protected:
friend class RibbonWidget;
friend class Screen;
@@ -269,7 +270,7 @@ namespace GUIEngine
class RibbonWidget : public Widget
{
friend class RibbonGridWidget;
friend class Screen;
friend class EventHandler;
int m_selection;
RibbonType m_ribbon_type;

View File

@@ -244,6 +244,7 @@
955DE88C1004273B006A4F3C /* check_structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955DE8871004273B006A4F3C /* check_structure.cpp */; };
955DE88D1004273B006A4F3C /* checkline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955DE8891004273B006A4F3C /* checkline.cpp */; };
956D36A710095035007FCB95 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 956D36A610095035007FCB95 /* player.cpp */; };
958330391012248A00C5137E /* event_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 958330381012248A00C5137E /* event_handler.cpp */; };
95CB476C0FF30EF400413BAE /* bezier_curve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95CB476B0FF30EF400413BAE /* bezier_curve.cpp */; };
95D1F5F70FC8C3E300FF6968 /* input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95D1F5F60FC8C3E300FF6968 /* input.cpp */; };
95D1F6190FC8CDBB00FF6968 /* options_screen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95D1F6180FC8CDBB00FF6968 /* options_screen.cpp */; };
@@ -376,6 +377,8 @@
955DE8891004273B006A4F3C /* checkline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkline.cpp; path = ../../tracks/checkline.cpp; sourceTree = SOURCE_ROOT; };
955DE88A1004273B006A4F3C /* checkline.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = checkline.hpp; path = ../../tracks/checkline.hpp; sourceTree = SOURCE_ROOT; };
956D36A610095035007FCB95 /* player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = player.cpp; path = games/supertuxkart/src/config/player.cpp; sourceTree = SYSTEM_DEVELOPER_DIR; };
958330371012248A00C5137E /* event_handler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = event_handler.hpp; path = games/supertuxkart/src/gui/event_handler.hpp; sourceTree = SYSTEM_DEVELOPER_DIR; };
958330381012248A00C5137E /* event_handler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = event_handler.cpp; path = games/supertuxkart/src/gui/event_handler.cpp; sourceTree = SYSTEM_DEVELOPER_DIR; };
95A118290F77EA3100B18B3D /* input.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = input.hpp; path = ../../input/input.hpp; sourceTree = SOURCE_ROOT; };
95A1182A0F77EA3100B18B3D /* input_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = input_manager.cpp; path = ../../input/input_manager.cpp; sourceTree = SOURCE_ROOT; };
95A1182B0F77EA3100B18B3D /* input_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = input_manager.hpp; path = ../../input/input_manager.hpp; sourceTree = SOURCE_ROOT; };
@@ -1022,6 +1025,8 @@
951C35BD0FC066ED00A48379 /* credits.hpp */,
9505577A0F696A900056E88C /* engine.cpp */,
9505577B0F696A900056E88C /* engine.hpp */,
958330381012248A00C5137E /* event_handler.cpp */,
958330371012248A00C5137E /* event_handler.hpp */,
9516162C0FFFB12B004B16D8 /* kart_selection.cpp */,
9516164D0FFFB1F0004B16D8 /* kart_selection.hpp */,
954A57DB0FEC5AE40073C16C /* modaldialog.cpp */,
@@ -2343,6 +2348,7 @@
955DE88C1004273B006A4F3C /* check_structure.cpp in Sources */,
955DE88D1004273B006A4F3C /* checkline.cpp in Sources */,
956D36A710095035007FCB95 /* player.cpp in Sources */,
958330391012248A00C5137E /* event_handler.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -33,6 +33,7 @@
#include "gui/state_manager.hpp"
#include "gui/modaldialog.hpp"
#include "gui/engine.hpp"
#include "gui/event_handler.hpp"
#include "gui/screen.hpp"
#include "input/device_manager.hpp"
#include "input/input.hpp"
@@ -320,7 +321,7 @@ void InputManager::input(Input::InputType type, int deviceID, int btnID, int axi
m_timer_in_use = true;
m_timer = 0.25;
}
GUIEngine::getCurrentScreen()->processAction(action, abs(value), type);
GUIEngine::EventHandler::get()->processAction(action, abs(value), type);
}
}
}