2009-07-18 12:04:45 -04:00
// 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.
2009-07-18 13:48:36 -04:00
# include "guiengine/event_handler.hpp"
2009-07-20 00:05:21 -04:00
# include "guiengine/abstract_state_manager.hpp"
2009-07-18 13:48:36 -04:00
# include "guiengine/engine.hpp"
# include "guiengine/modaldialog.hpp"
# include "guiengine/screen.hpp"
2009-07-20 00:05:21 -04:00
# include "guiengine/widget.hpp"
2010-05-02 13:27:17 -04:00
# include "guiengine/widgets/list_widget.hpp"
2010-04-26 10:41:23 -04:00
# include "guiengine/widgets/ribbon_widget.hpp"
2009-07-18 12:04:45 -04:00
# include "input/input_manager.hpp"
2010-04-11 13:13:39 -04:00
# include "states_screens/state_manager.hpp"
2009-07-18 12:04:45 -04:00
using GUIEngine : : EventHandler ;
2009-09-27 15:43:22 -04:00
using GUIEngine : : EventPropagation ;
2009-07-18 12:04:45 -04:00
2009-10-12 19:43:14 -04:00
using namespace irr : : gui ;
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2009-07-18 12:04:45 -04:00
EventHandler : : EventHandler ( )
{
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2009-07-18 12:04:45 -04:00
EventHandler : : ~ EventHandler ( )
{
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2009-07-18 12:04:45 -04:00
bool EventHandler : : OnEvent ( const SEvent & event )
{
2010-05-02 20:50:11 -04:00
if ( event . EventType = = EET_GUI_EVENT )
2009-07-18 12:04:45 -04:00
{
2009-09-27 15:43:22 -04:00
return onGUIEvent ( event ) = = EVENT_BLOCK ;
2009-07-18 12:04:45 -04:00
}
2010-05-02 20:50:11 -04:00
else if ( GUIEngine : : getStateManager ( ) - > getGameState ( ) ! = GUIEngine : : GAME & &
event . EventType ! = EET_KEY_INPUT_EVENT & & event . EventType ! = EET_JOYSTICK_INPUT_EVENT )
{
return false ; // EVENT_LET
}
2010-04-15 20:24:25 -04:00
else if ( event . EventType = = EET_MOUSE_INPUT_EVENT | |
event . EventType = = EET_KEY_INPUT_EVENT | |
event . EventType = = EET_JOYSTICK_INPUT_EVENT )
2009-07-18 12:04:45 -04:00
{
2010-04-15 20:24:25 -04:00
// FIXME? it may be a bit unclean that all input events go trough the gui module
2009-09-27 15:43:22 -04:00
const EventPropagation blockPropagation = input_manager - > input ( event ) ;
return blockPropagation = = EVENT_BLOCK ;
2009-07-18 12:04:45 -04:00
}
2010-04-15 20:24:25 -04:00
else if ( event . EventType = = EET_LOG_TEXT_EVENT )
{
// Ignore 'normal' messages
if ( event . LogEvent . Level > 0 )
{
// Unfortunatly irrlicht produces some internal error/warnings
// messages that can't be avoided (see COpenGLTexture where
// the constructor of COpenGLFBOTexture is used without
// specifying a color format, so the detault format (ECF_UNKOWNO)
// is used, which produces this error message). In non-debug
// mode ignore this error message, but leave it in for debugging.
if ( std : : string ( event . LogEvent . Text ) = = " Unsupported texture format " )
# ifdef DEBUG
printf ( " The following message will not be printed in release mode: \n " ) ;
# else
2010-05-03 13:41:36 -04:00
return true ; // EVENT_BLOCK
2010-04-15 20:24:25 -04:00
# endif
printf ( " Level %d: %s \n " ,
event . LogEvent . Level , event . LogEvent . Text ) ;
}
2010-04-18 08:35:45 -04:00
return true ;
2010-04-15 20:24:25 -04:00
}
2009-07-18 13:48:36 -04:00
2010-04-15 20:24:25 -04:00
// nothing to do with other events
2009-07-18 13:48:36 -04:00
return false ;
2009-07-18 12:04:45 -04:00
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2010-05-03 13:35:52 -04:00
void EventHandler : : processGUIAction ( const PlayerAction action , const unsigned int value ,
Input : : InputType type , const int playerID )
2009-07-18 12:04:45 -04:00
{
const bool pressedDown = value > Input : : MAX_VALUE * 2 / 3 ;
2009-08-27 14:41:20 -04:00
if ( ! pressedDown & & type = = Input : : IT_STICKMOTION ) return ;
2009-07-18 12:04:45 -04:00
2009-08-27 14:41:20 -04:00
switch ( action )
2009-07-18 12:04:45 -04:00
{
2010-05-03 14:56:55 -04:00
case PA_STEER_LEFT :
case PA_MENU_LEFT :
2009-07-18 12:04:45 -04:00
{
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getFocusForPlayer ( playerID ) ;
2009-08-28 11:16:57 -04:00
if ( w = = NULL ) break ;
2009-08-02 14:53:50 -04:00
2009-07-18 12:04:45 -04:00
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
2009-08-02 14:53:50 -04:00
notified of clicks onto themselves so they can toggle their state . )
On the way , also notify everyone in the chain of the left press . */
while ( widget_to_call - > m_event_handler ! = NULL & & widget_to_call - > m_event_handler ! = widget_to_call )
{
2009-10-31 15:09:45 -04:00
if ( widget_to_call - > leftPressed ( playerID ) = = EVENT_LET )
{
2010-04-24 16:08:13 -04:00
sendEventToUser ( w , w - > m_properties [ PROP_ID ] , playerID ) ;
2009-10-31 15:09:45 -04:00
}
2009-07-18 12:04:45 -04:00
widget_to_call = widget_to_call - > m_event_handler ;
2009-08-02 14:53:50 -04:00
}
2009-07-18 12:04:45 -04:00
2009-10-28 19:04:38 -04:00
if ( widget_to_call - > leftPressed ( playerID ) = = EVENT_LET )
{
2010-04-24 16:08:13 -04:00
sendEventToUser ( widget_to_call , widget_to_call - > m_properties [ PROP_ID ] , playerID ) ;
2009-10-28 19:04:38 -04:00
}
2009-07-18 12:04:45 -04:00
}
2009-10-28 19:04:38 -04:00
break ;
2009-07-18 12:04:45 -04:00
2010-05-03 14:56:55 -04:00
case PA_STEER_RIGHT :
case PA_MENU_RIGHT :
2009-07-18 12:04:45 -04:00
{
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getFocusForPlayer ( playerID ) ;
2009-08-28 11:16:57 -04:00
if ( w = = NULL ) break ;
2009-07-18 12:04:45 -04:00
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
2009-08-02 14:53:50 -04:00
notified of clicks onto themselves so they can toggle their state . )
On the way , also notify everyone in the chain of the right press */
2009-08-28 11:16:57 -04:00
while ( widget_to_call - > m_event_handler ! = NULL & & widget_to_call - > m_event_handler ! = widget_to_call )
2009-08-02 14:53:50 -04:00
{
2009-10-31 15:09:45 -04:00
if ( widget_to_call - > rightPressed ( playerID ) = = EVENT_LET )
{
2010-04-24 16:08:13 -04:00
sendEventToUser ( widget_to_call , w - > m_properties [ PROP_ID ] , playerID ) ;
2009-10-31 15:09:45 -04:00
}
2009-07-18 12:04:45 -04:00
widget_to_call = widget_to_call - > m_event_handler ;
2009-08-02 14:53:50 -04:00
}
2009-07-18 12:04:45 -04:00
2009-10-28 19:04:38 -04:00
if ( widget_to_call - > rightPressed ( playerID ) = = EVENT_LET )
{
2010-04-24 16:08:13 -04:00
sendEventToUser ( widget_to_call , widget_to_call - > m_properties [ PROP_ID ] , playerID ) ;
2009-10-28 19:04:38 -04:00
}
2009-07-18 12:04:45 -04:00
}
2009-10-28 19:04:38 -04:00
break ;
2009-07-18 12:04:45 -04:00
case PA_ACCEL :
2010-05-03 14:56:55 -04:00
case PA_MENU_UP :
2009-08-28 11:16:57 -04:00
navigateUp ( playerID , type , pressedDown ) ;
2009-07-18 12:04:45 -04:00
break ;
case PA_BRAKE :
2010-05-03 14:56:55 -04:00
case PA_MENU_DOWN :
2009-08-28 11:16:57 -04:00
navigateDown ( playerID , type , pressedDown ) ;
2009-07-18 12:04:45 -04:00
break ;
case PA_RESCUE :
2010-05-03 14:56:55 -04:00
case PA_MENU_CANCEL :
2009-10-28 19:04:38 -04:00
if ( pressedDown ) GUIEngine : : getStateManager ( ) - > escapePressed ( ) ;
2009-07-18 12:04:45 -04:00
break ;
case PA_FIRE :
2010-05-03 14:56:55 -04:00
case PA_MENU_SELECT :
2009-10-31 19:35:54 -04:00
if ( pressedDown & & ! isWithinATextBox ( ) )
2009-07-18 12:04:45 -04:00
{
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getFocusForPlayer ( playerID ) ;
2009-10-20 14:25:14 -04:00
if ( w = = NULL ) break ;
2010-08-23 20:32:03 -04:00
2009-10-20 14:25:14 -04:00
// FIXME : consider returned value?
2009-08-27 14:41:20 -04:00
onWidgetActivated ( w , playerID ) ;
2009-07-18 12:04:45 -04:00
}
break ;
default :
return ;
}
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2010-05-03 13:39:08 -04:00
EventHandler * event_handler_singleton = NULL ;
EventHandler * EventHandler : : get ( )
{
if ( event_handler_singleton = = NULL )
{
event_handler_singleton = new EventHandler ( ) ;
}
return event_handler_singleton ;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
#if 0
# pragma mark -
# pragma mark Private methods
# endif
2009-08-28 11:16:57 -04:00
void EventHandler : : navigateUp ( const int playerID , Input : : InputType type , const bool pressedDown )
{
2010-02-15 18:32:37 -05:00
//std::cout << "Naviagte up!\n";
2009-08-28 14:46:02 -04:00
IGUIElement * el = NULL , * first = NULL , * closest = NULL ;
2010-03-05 14:45:16 -05:00
if ( type = = Input : : IT_STICKBUTTON & & ! pressedDown )
return ;
2009-08-28 11:16:57 -04:00
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getFocusForPlayer ( playerID ) ;
2010-04-11 13:13:39 -04:00
if ( w ! = NULL )
{
el = w - > getIrrlichtElement ( ) ;
}
2009-08-28 11:16:57 -04:00
// 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 )
{
2010-05-02 13:27:17 -04:00
ListWidget * list = ( ListWidget * ) w ;
2009-08-28 11:16:57 -04:00
2010-05-02 13:27:17 -04:00
const bool stay_within_list = list - > getSelectionID ( ) > 0 ;
2009-08-28 11:16:57 -04:00
2009-10-31 15:09:45 -04:00
if ( stay_within_list )
{
2010-05-02 13:27:17 -04:00
list - > setSelectionID ( list - > getSelectionID ( ) - 1 ) ;
2009-10-31 15:09:45 -04:00
return ;
}
else
{
2010-05-02 13:27:17 -04:00
list - > setSelectionID ( - 1 ) ;
2009-10-31 15:09:45 -04:00
}
2009-08-28 11:16:57 -04:00
}
2009-10-31 15:09:45 -04:00
if ( w ! = NULL & & w - > m_tab_up_root ! = - 1 )
2009-09-27 16:38:40 -04:00
{
2009-10-31 15:09:45 -04:00
Widget * up = GUIEngine : : getWidget ( w - > m_tab_up_root ) ;
assert ( up ! = NULL ) ;
2010-04-11 13:13:39 -04:00
2009-10-31 15:09:45 -04:00
el = up - > getIrrlichtElement ( ) ;
if ( el = = NULL )
{
std : : cerr < < " WARNING : m_tab_down_root is set to an ID for which I can't find the widget \n " ;
return ;
}
2009-09-27 16:38:40 -04:00
}
2009-10-31 15:09:45 -04:00
2009-12-22 15:54:43 -05:00
// don't allow navigating to any widget when a dialog is shown; only navigate to widgets in the dialog
2010-08-15 20:39:53 -04:00
if ( ModalDialog : : isADialogActive ( ) & & ! ModalDialog : : getCurrent ( ) - > isMyIrrChild ( el ) )
2009-12-22 15:54:43 -05:00
{
el = NULL ;
}
2009-09-27 16:38:40 -04:00
2010-06-24 21:13:15 -04:00
bool found = false ;
2009-08-28 11:16:57 -04:00
// find closest widget
2010-06-24 21:13:15 -04:00
if ( el ! = NULL & & el - > getTabGroup ( ) ! = NULL )
2009-08-28 11:16:57 -04:00
{
2010-06-24 21:13:15 -04:00
// if the current widget is e.g. 15, search for widget 14, 13, 12, ... (up to 10 IDs may be missing)
for ( int n = 0 ; n < 10 & & ! found ; n + + )
2009-08-28 11:16:57 -04:00
{
2010-06-24 21:13:15 -04:00
const bool success = el - > getTabGroup ( ) - > getNextElement ( el - > getTabOrder ( ) - n ,
true /* reverse */ , false /* group */ ,
2010-06-26 13:19:12 -04:00
first , closest , true ) ;
2009-08-28 11:16:57 -04:00
2010-06-24 21:13:15 -04:00
if ( success )
{
//std::cout << "Navigating up to " << closest->getID() << std::endl;
Widget * closestWidget = GUIEngine : : getWidget ( closest - > getID ( ) ) ;
if ( playerID ! = PLAYER_ID_GAME_MASTER & & ! closestWidget - > m_supports_multiplayer ) return ;
//FIXME: something's wrong here, I use 'closestWidget', THEN verify it's not NULL xD
closestWidget - > setFocusForPlayer ( playerID ) ;
// when focusing a list by going up, select the last item of the list
if ( closestWidget ! = NULL & & closestWidget - > m_type = = WTYPE_LIST )
{
IGUIListBox * list = ( IGUIListBox * ) ( closestWidget - > m_element ) ;
assert ( list ! = NULL ) ;
list - > setSelected ( list - > getItemCount ( ) - 1 ) ;
return ;
}
found = true ;
}
} // end for
2009-08-28 11:16:57 -04:00
}
2010-06-24 21:13:15 -04:00
if ( ! found )
2009-08-28 11:16:57 -04:00
{
2010-02-15 18:32:37 -05:00
//std::cout << "EventHandler::navigateUp : warp around, selecting the last widget\n";
2009-10-31 15:09:45 -04:00
//if (el == NULL) std::cout << " because el is null\n";
//else if (el->getTabGroup() == NULL) std::cout << " because el's tab group is null\n";
//else if (!el->getTabGroup()->getNextElement(el->getTabOrder(), true, false, first, closest))std::cout << " because el (" << core::stringc(el->getText()).c_str() << ", tab order " << el->getTabOrder() << ") has no known previous\n";
2009-08-28 11:16:57 -04:00
// select the last widget
2010-04-11 13:13:39 -04:00
Widget * lastWidget = NULL ;
2009-09-05 13:27:14 -04:00
if ( ModalDialog : : isADialogActive ( ) )
{
2010-04-11 13:13:39 -04:00
lastWidget = ModalDialog : : getCurrent ( ) - > getLastWidget ( ) ;
2009-09-05 13:27:14 -04:00
}
else
{
Screen * screen = GUIEngine : : getCurrentScreen ( ) ;
if ( screen = = NULL ) return ;
2010-04-11 13:13:39 -04:00
lastWidget = screen - > getLastWidget ( ) ;
2009-09-05 13:27:14 -04:00
}
2009-08-28 11:16:57 -04:00
2010-04-11 13:13:39 -04:00
if ( lastWidget ! = NULL ) lastWidget - > setFocusForPlayer ( playerID ) ;
2009-08-28 11:16:57 -04:00
}
}
// -----------------------------------------------------------------------------
void EventHandler : : navigateDown ( const int playerID , Input : : InputType type , const bool pressedDown )
{
2010-02-15 18:32:37 -05:00
//std::cout << "Naviagte down!\n";
2009-10-31 15:09:45 -04:00
2009-08-28 14:46:02 -04:00
IGUIElement * el = NULL , * first = NULL , * closest = NULL ;
2010-03-05 14:45:16 -05:00
if ( type = = Input : : IT_STICKBUTTON & & ! pressedDown )
return ;
2009-08-28 11:16:57 -04:00
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getFocusForPlayer ( playerID ) ;
2010-04-11 13:13:39 -04:00
if ( w ! = NULL )
{
el = w - > getIrrlichtElement ( ) ;
}
2009-10-21 18:51:23 -04:00
//std::cout << "!!! Player " << playerID << " navigating down of " << w->m_element->getID() << std::endl;
2009-09-27 16:38:40 -04:00
2009-08-28 11:16:57 -04:00
// 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 )
{
2010-05-02 13:27:17 -04:00
ListWidget * list = ( ListWidget * ) w ;
2009-08-28 11:16:57 -04:00
2010-05-02 13:27:17 -04:00
const bool stay_within_list = list - > getSelectionID ( ) < list - > getItemCount ( ) - 1 ;
2009-10-31 15:09:45 -04:00
if ( stay_within_list )
{
2010-05-02 13:27:17 -04:00
list - > setSelectionID ( list - > getSelectionID ( ) + 1 ) ;
2009-10-31 15:09:45 -04:00
return ;
}
else
{
2010-05-02 13:27:17 -04:00
list - > setSelectionID ( - 1 ) ;
2009-08-28 11:16:57 -04:00
}
}
2009-10-29 20:09:32 -04:00
if ( w ! = NULL & & w - > m_tab_down_root ! = - 1 )
2009-10-28 20:59:46 -04:00
{
Widget * down = GUIEngine : : getWidget ( w - > m_tab_down_root ) ;
assert ( down ! = NULL ) ;
el = down - > getIrrlichtElement ( ) ;
2009-10-31 15:09:45 -04:00
if ( el = = NULL )
{
std : : cerr < < " WARNING : m_tab_down_root is set to an ID for which I can't find the widget \n " ;
return ;
}
2009-10-28 20:59:46 -04:00
}
2009-10-31 15:09:45 -04:00
2009-12-22 15:54:43 -05:00
// don't allow navigating to any widget when a dialog is shown; only navigate to widgets in the dialog
2010-08-15 20:39:53 -04:00
if ( ModalDialog : : isADialogActive ( ) & & ! ModalDialog : : getCurrent ( ) - > isMyIrrChild ( el ) )
2009-12-22 15:54:43 -05:00
{
el = NULL ;
}
2009-09-27 16:38:40 -04:00
2010-06-24 21:13:15 -04:00
bool found = false ;
if ( el ! = NULL & & el - > getTabGroup ( ) ! = NULL )
2009-08-28 11:16:57 -04:00
{
2010-06-24 21:13:15 -04:00
// if the current widget is e.g. 5, search for widget 6, 7, 8, 9, ..., 15 (up to 10 IDs may be missing)
for ( int n = 0 ; n < 10 & & ! found ; n + + )
2009-08-28 11:16:57 -04:00
{
2010-06-24 21:13:15 -04:00
const bool success = el - > getTabGroup ( ) - > getNextElement ( el - > getTabOrder ( ) + n ,
2010-06-26 13:19:12 -04:00
false , false , first , closest , true ) ;
2010-06-24 21:13:15 -04:00
if ( success )
{
Widget * closestWidget = GUIEngine : : getWidget ( closest - > getID ( ) ) ;
if ( playerID ! = PLAYER_ID_GAME_MASTER & & ! closestWidget - > m_supports_multiplayer ) return ;
assert ( closestWidget ! = NULL ) ;
closestWidget - > setFocusForPlayer ( playerID ) ;
// another list exception : when entering a list, select the first item
if ( closestWidget - > m_type = = WTYPE_LIST )
{
IGUIListBox * list = ( IGUIListBox * ) ( closestWidget - > m_element ) ;
assert ( list ! = NULL ) ;
2009-10-31 15:09:45 -04:00
2010-06-24 21:13:15 -04:00
list - > setSelected ( 0 ) ;
}
found = true ;
}
} // end for
2009-08-28 11:16:57 -04:00
}
2010-06-24 21:13:15 -04:00
if ( ! found )
2009-08-28 11:16:57 -04:00
{
2009-09-27 16:38:40 -04:00
2009-08-28 11:16:57 -04:00
// select the first widget
2010-04-11 13:13:39 -04:00
Widget * firstWidget = NULL ;
2009-09-05 13:27:14 -04:00
if ( ModalDialog : : isADialogActive ( ) )
{
2010-04-11 13:13:39 -04:00
//std::cout << "w = ModalDialog::getCurrent()->getFirstWidget();\n";
firstWidget = ModalDialog : : getCurrent ( ) - > getFirstWidget ( ) ;
2009-09-05 13:27:14 -04:00
}
else
{
Screen * screen = GUIEngine : : getCurrentScreen ( ) ;
if ( screen = = NULL ) return ;
2010-04-11 13:13:39 -04:00
firstWidget = screen - > getFirstWidget ( ) ;
2009-09-05 13:27:14 -04:00
}
2010-04-11 13:13:39 -04:00
if ( firstWidget ! = NULL ) firstWidget - > setFocusForPlayer ( playerID ) ;
2009-08-28 11:16:57 -04:00
}
}
// -----------------------------------------------------------------------------
2009-07-18 12:04:45 -04:00
2010-04-26 19:41:40 -04:00
void EventHandler : : sendEventToUser ( GUIEngine : : Widget * widget , std : : string & name , const int playerID )
2010-04-24 16:08:13 -04:00
{
getCurrentScreen ( ) - > eventCallback ( widget , name , playerID ) ;
}
// -----------------------------------------------------------------------------
2010-05-03 13:39:08 -04:00
EventPropagation EventHandler : : onWidgetActivated ( GUIEngine : : Widget * w , const int playerID )
2009-07-18 12:04:45 -04:00
{
2010-08-23 20:32:03 -04:00
if ( w - > m_deactivated ) return EVENT_BLOCK ;
2010-05-03 13:39:08 -04:00
if ( ModalDialog : : isADialogActive ( ) )
2009-07-18 12:04:45 -04:00
{
2010-08-23 20:32:03 -04:00
if ( ModalDialog : : getCurrent ( ) - > processEvent ( w - > m_properties [ PROP_ID ] ) = = EVENT_BLOCK )
{
return EVENT_BLOCK ;
}
2010-05-03 13:39:08 -04:00
if ( w - > m_event_handler = = NULL ) return EVENT_LET ;
2009-07-18 12:04:45 -04:00
}
2010-05-03 13:39:08 -04:00
//std::cout << "**** widget activated : " << w->m_properties[PROP_ID].c_str() << " ****" << std::endl;
2010-08-23 20:32:03 -04:00
2010-05-03 13:39:08 -04:00
Widget * parent = w - > m_event_handler ;
if ( w - > m_event_handler ! = NULL )
{
/* Find all parents. 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 - > transmitEvent ( w , w - > m_properties [ PROP_ID ] , playerID ) ;
parent = parent - > m_event_handler ;
}
2010-08-23 20:32:03 -04:00
if ( parent - > m_deactivated ) return EVENT_BLOCK ;
2010-05-03 13:39:08 -04:00
/* 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 ] , playerID ) = = EVENT_LET )
{
// notify modal dialog too
if ( ModalDialog : : isADialogActive ( ) )
{
2010-08-15 19:24:08 -04:00
if ( ModalDialog : : getCurrent ( ) - > processEvent ( parent - > m_properties [ PROP_ID ] ) = = EVENT_BLOCK )
{
return EVENT_BLOCK ;
}
2010-05-03 13:39:08 -04:00
}
sendEventToUser ( parent , parent - > m_properties [ PROP_ID ] , playerID ) ;
}
}
2010-08-23 20:32:03 -04:00
else
{
printf ( " sendEventToUser : '%s' is disabled = '%i' \n " , w - > m_properties [ PROP_ID ] . c_str ( ) , w - > m_deactivated ) ;
sendEventToUser ( w , w - > m_properties [ PROP_ID ] , playerID ) ;
}
2010-05-03 13:39:08 -04:00
return EVENT_BLOCK ;
2009-07-18 12:04:45 -04:00
}
2010-05-03 13:39:08 -04:00
// -----------------------------------------------------------------------------
EventPropagation 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 : : getWidget ( id ) ;
if ( w = = NULL ) break ;
2010-05-15 14:51:29 -04:00
if ( w - > m_deactivated ) return EVENT_BLOCK ;
2010-06-24 14:56:27 -04:00
// These events are only triggered by mouse (or so I hope)
// The player that owns the mouser receives "game master" priviledges
return onWidgetActivated ( w , PLAYER_ID_GAME_MASTER ) ;
2010-05-03 13:39:08 -04:00
// These events are only triggered by keyboard/mouse (or so I hope...)
2010-06-24 14:56:27 -04:00
//const int playerID = input_manager->getPlayerKeyboardID();
//if (input_manager->masterPlayerOnly() && playerID != PLAYER_ID_GAME_MASTER) break;
//else if (playerID != -1) return onWidgetActivated(w, playerID);
//else break;
2010-05-03 13:39:08 -04:00
}
case EGET_ELEMENT_HOVERED :
2010-08-15 19:24:08 -04:00
{
2010-05-03 13:39:08 -04:00
Widget * w = GUIEngine : : getWidget ( id ) ;
2010-08-15 19:24:08 -04:00
2010-05-03 13:39:08 -04:00
if ( w = = NULL ) break ;
2010-08-15 19:24:08 -04:00
2010-05-03 13:39:08 -04:00
if ( ! w - > m_focusable ) return GUIEngine : : EVENT_BLOCK ;
2010-08-15 19:24:08 -04:00
2010-05-03 13:39:08 -04:00
// When a modal dialog is shown, don't select widgets out of the dialog
if ( ModalDialog : : isADialogActive ( ) & & ! ModalDialog : : getCurrent ( ) - > isMyChild ( w ) )
{
// check for parents too before discarding event
if ( w - > m_event_handler ! = NULL )
{
2010-08-15 19:24:08 -04:00
if ( ! ModalDialog : : getCurrent ( ) - > isMyChild ( w - > m_event_handler ) )
{
break ;
}
2010-05-03 13:39:08 -04:00
}
}
2010-08-15 19:24:08 -04:00
2010-05-03 13:39:08 -04:00
// select ribbons on hover
if ( w - > m_event_handler ! = NULL & & w - > m_event_handler - > m_type = = WTYPE_RIBBON )
2010-08-15 19:24:08 -04:00
{
2010-05-03 13:39:08 -04:00
RibbonWidget * ribbon = ( RibbonWidget * ) ( w - > m_event_handler ) ;
if ( ribbon = = NULL ) break ;
2010-06-24 14:56:27 -04:00
// give the mouse "game master" priviledges
const int playerID = PLAYER_ID_GAME_MASTER ; //input_manager->getPlayerKeyboardID();
2010-05-03 13:39:08 -04:00
if ( playerID = = - 1 ) break ;
2010-06-24 14:56:27 -04:00
if ( input_manager - > masterPlayerOnly ( ) & & playerID ! = PLAYER_ID_GAME_MASTER ) break ;
2010-05-03 13:39:08 -04:00
if ( ribbon - > mouseHovered ( w , playerID ) = = EVENT_LET ) sendEventToUser ( ribbon , ribbon - > m_properties [ PROP_ID ] , playerID ) ;
if ( ribbon - > m_event_handler ! = NULL ) ribbon - > m_event_handler - > mouseHovered ( w , playerID ) ;
ribbon - > setFocusForPlayer ( playerID ) ;
}
else
{
// focus on hover for other widgets
2010-06-24 14:56:27 -04:00
// give the mouse "game master" priviledges
const int playerID = PLAYER_ID_GAME_MASTER ; //input_manager->getPlayerKeyboardID();
if ( input_manager - > masterPlayerOnly ( ) & & playerID ! = PLAYER_ID_GAME_MASTER ) break ;
2010-05-03 13:39:08 -04:00
if ( playerID ! = - 1 )
{
// lists don't like that combined with scrollbars
// (FIXME: find why instead of working around)
if ( w - > getType ( ) ! = WTYPE_LIST )
{
w - > setFocusForPlayer ( playerID ) ;
}
}
}
break ;
}
/*
case EGET_ELEMENT_LEFT :
{
Widget * el = getWidget ( id ) ;
if ( el = = NULL ) break ;
break ;
}
*/
case EGET_ELEMENT_FOCUSED :
{
Widget * w = GUIEngine : : getWidget ( id ) ;
if ( w = = NULL ) break ;
// forbid list for gaining "irrLicht focus", then they will process key events and
// we don't want that since we do our own custom processing for keys
if ( w - > m_type = = WTYPE_LIST )
{
2010-06-23 20:45:39 -04:00
// FIXME: fix that better
2010-05-03 13:39:08 -04:00
// cheap way to remove the focus from the element (nope, IGUIEnv::removeFocus doesn't work)
// Obviously will not work if the list is the first item of the screen.
2010-06-23 20:45:39 -04:00
IGUIElement * elem = getCurrentScreen ( ) - > getFirstWidget ( ) - > getIrrlichtElement ( ) ;
if ( elem - > getType ( ) = = EGUIET_LIST_BOX )
{
elem = getCurrentScreen ( ) - > getLastWidget ( ) - > getIrrlichtElement ( ) ;
assert ( elem - > getType ( ) ! = EGUIET_LIST_BOX ) ;
}
GUIEngine : : getGUIEnv ( ) - > setFocus ( elem ) ;
2010-05-03 13:39:08 -04:00
return EVENT_BLOCK ; // confirms to irrLicht that we processed it
}
break ;
}
case EGET_LISTBOX_CHANGED :
{
Widget * w = GUIEngine : : getWidget ( id ) ;
if ( w = = NULL ) break ;
assert ( w - > getType ( ) = = WTYPE_LIST ) ;
const int playerID = input_manager - > getPlayerKeyboardID ( ) ;
2010-05-03 13:40:00 -04:00
if ( input_manager - > masterPlayerOnly ( ) & & playerID ! = PLAYER_ID_GAME_MASTER ) break ;
2010-05-03 13:39:08 -04:00
if ( ! w - > isFocusedForPlayer ( playerID ) ) w - > setFocusForPlayer ( playerID ) ;
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 EVENT_LET ;
}
// -----------------------------------------------------------------------------