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"
2009-07-18 12:04:45 -04:00
# include "input/input_manager.hpp"
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 )
{
if ( event . EventType = = EET_GUI_EVENT | |
2009-09-06 14:45:38 -04:00
( GUIEngine : : getStateManager ( ) - > getGameState ( ) ! = GUIEngine : : GAME & & event . EventType ! = EET_KEY_INPUT_EVENT & &
2009-07-18 13:48:36 -04:00
event . EventType ! = EET_JOYSTICK_INPUT_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
}
else
{
// FIXME : it's 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
}
2009-07-18 13:48:36 -04:00
// to shut up a warning. gcc is too stupid too see the code will never get here
return false ;
2009-07-18 12:04:45 -04:00
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2009-09-27 15:43:22 -04:00
EventPropagation EventHandler : : onGUIEvent ( const SEvent & event )
2009-07-18 12:04:45 -04:00
{
2009-08-28 11:16:57 -04:00
if ( event . EventType = = EET_GUI_EVENT )
2009-07-18 12:04:45 -04:00
{
const s32 id = event . GUIEvent . Caller - > getID ( ) ;
2009-08-28 11:16:57 -04:00
switch ( event . GUIEvent . EventType )
2009-07-18 12:04:45 -04:00
{
case EGET_BUTTON_CLICKED :
case EGET_SCROLL_BAR_CHANGED :
case EGET_CHECKBOX_CHANGED :
case EGET_LISTBOX_SELECTED_AGAIN :
{
2009-09-01 14:11:26 -04:00
Widget * w = GUIEngine : : getWidget ( id ) ;
2009-10-20 14:25:14 -04:00
if ( w = = NULL ) break ;
2009-07-18 12:04:45 -04:00
2009-08-27 14:41:20 -04:00
// FIXME: don't hardcode player 0
return onWidgetActivated ( w , 0 ) ;
2009-07-18 12:04:45 -04:00
}
case EGET_ELEMENT_HOVERED :
{
2009-09-01 14:11:26 -04:00
Widget * w = GUIEngine : : getWidget ( id ) ;
2009-09-01 20:25:17 -04:00
if ( w = = NULL ) break ;
2009-07-18 12:04:45 -04:00
2009-10-31 19:06:58 -04:00
// When a modal dialog is shown, don't select widgets out of the dialog
if ( ModalDialog : : isADialogActive ( ) & & ! ModalDialog : : getCurrent ( ) - > isMyChild ( w ) ) break ;
2009-07-18 12:04:45 -04:00
// select ribbons on hover
2009-09-01 20:25:17 -04:00
if ( w - > m_event_handler ! = NULL & & w - > m_event_handler - > m_type = = WTYPE_RIBBON )
2009-07-18 12:04:45 -04:00
{
RibbonWidget * ribbon = dynamic_cast < RibbonWidget * > ( w - > m_event_handler ) ;
2009-09-27 15:43:22 -04:00
if ( ribbon = = NULL ) break ;
2009-10-28 19:04:38 -04:00
const int playerID = 0 ; // FIXME : don't hardcode player 0
if ( ribbon - > mouseHovered ( w ) = = EVENT_LET ) transmitEvent ( ribbon , ribbon - > m_properties [ PROP_ID ] , playerID ) ;
2009-09-27 15:43:22 -04:00
if ( ribbon - > m_event_handler ! = NULL ) ribbon - > m_event_handler - > mouseHovered ( w ) ;
2009-10-31 15:09:45 -04:00
ribbon - > setFocusForPlayer ( playerID ) ;
2009-07-18 12:04:45 -04:00
}
else
{
// focus on hover for other widgets
2009-10-31 15:09:45 -04:00
const int playerID = 0 ; // FIXME: don't hardcode player 0 ?
w - > setFocusForPlayer ( playerID ) ;
2009-07-18 12:04:45 -04:00
}
break ;
}
/*
case EGET_ELEMENT_LEFT :
{
Widget * el = getWidget ( id ) ;
if ( el = = NULL ) break ;
break ;
}
*/
2009-10-31 19:06:58 -04:00
/*
case EGET_ELEMENT_FOCUSED : // is this still used with the new focus implementation?
2009-07-18 12:04:45 -04:00
{
2009-09-27 15:06:14 -04:00
Widget * w = GUIEngine : : getWidget ( id ) ;
if ( w = = NULL ) break ;
2009-07-18 12:04:45 -04:00
2009-10-31 15:09:45 -04:00
std : : cout < < " ==== irrlicht widget focused : " < < w - > m_properties [ PROP_ID ] < < std : : endl ;
2009-08-28 18:58:32 -04:00
// FIXME: don't hardcode player 0
2009-09-27 15:06:14 -04:00
return w - > focused ( 0 ) ;
2009-07-18 12:04:45 -04:00
break ;
2009-10-31 19:06:58 -04:00
} */
2009-07-18 12:04:45 -04:00
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 ,
*/
2009-09-27 15:43:22 -04:00
return EVENT_LET ;
2009-07-18 12:04:45 -04:00
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2009-09-27 15:43:22 -04:00
EventPropagation EventHandler : : onWidgetActivated ( GUIEngine : : Widget * w , const int playerID )
2009-07-18 12:04:45 -04:00
{
2009-09-04 21:50:37 -04:00
if ( ModalDialog : : isADialogActive ( ) )
2009-07-18 12:04:45 -04:00
{
2009-10-20 14:25:14 -04:00
if ( ModalDialog : : getCurrent ( ) - > processEvent ( w - > m_properties [ PROP_ID ] ) = = EVENT_BLOCK ) return EVENT_BLOCK ;
2009-09-27 15:43:22 -04:00
if ( w - > m_event_handler = = NULL ) return EVENT_LET ;
2009-07-18 12:04:45 -04:00
}
2009-10-21 19:00:12 -04:00
//std::cout << "**** widget activated : " << w->m_properties[PROP_ID].c_str() << " ****" << std::endl;
2009-08-10 20:55:48 -04:00
2009-07-18 12:04:45 -04:00
Widget * parent = w - > m_event_handler ;
2009-08-27 14:41:20 -04:00
if ( w - > m_event_handler ! = NULL )
2009-07-18 12:04:45 -04:00
{
2009-08-02 15:20:27 -04:00
/* Find all parents. Stop looping if a widget event handler's is itself, to not fall
2009-07-18 12:04:45 -04:00
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 . ) */
2009-08-27 14:41:20 -04:00
while ( parent - > m_event_handler ! = NULL & & parent - > m_event_handler ! = parent )
2009-08-02 15:20:27 -04:00
{
2009-08-27 14:41:20 -04:00
parent - > transmitEvent ( w , w - > m_properties [ PROP_ID ] , playerID ) ;
2009-09-05 11:46:24 -04:00
2009-07-18 12:04:45 -04:00
parent = parent - > m_event_handler ;
2009-08-02 15:20:27 -04:00
}
2009-07-18 12:04:45 -04:00
/* notify the found event event handler, and also notify the main callback if the
parent event handler says so */
2009-09-27 15:43:22 -04:00
if ( parent - > transmitEvent ( w , w - > m_properties [ PROP_ID ] , playerID ) = = EVENT_LET )
2009-08-02 15:20:27 -04:00
{
2009-09-05 11:46:24 -04:00
// notify modal dialog too
if ( ModalDialog : : isADialogActive ( ) )
{
2009-10-20 14:29:51 -04:00
if ( ModalDialog : : getCurrent ( ) - > processEvent ( parent - > m_properties [ PROP_ID ] ) = = EVENT_BLOCK ) return EVENT_BLOCK ;
2009-09-05 11:46:24 -04:00
}
2009-10-28 19:04:38 -04:00
transmitEvent ( parent , parent - > m_properties [ PROP_ID ] , playerID ) ;
2009-08-02 15:20:27 -04:00
}
2009-07-18 12:04:45 -04:00
}
2009-10-28 19:04:38 -04:00
else transmitEvent ( w , w - > m_properties [ PROP_ID ] , playerID ) ;
2009-07-18 12:04:45 -04:00
2009-09-27 15:43:22 -04:00
return EVENT_BLOCK ;
2009-07-18 12:04:45 -04:00
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
2009-07-18 12:04:45 -04:00
/**
* Called by the input module
*/
2009-08-27 14:41:20 -04:00
void EventHandler : : processAction ( const int 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
{
case PA_LEFT :
{
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 )
{
transmitEvent ( w , w - > m_properties [ PROP_ID ] , playerID ) ;
}
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 )
{
2009-10-31 15:09:45 -04:00
transmitEvent ( 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_RIGHT :
{
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 )
{
transmitEvent ( widget_to_call , w - > m_properties [ PROP_ID ] , playerID ) ;
}
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 )
{
2009-10-31 15:09:45 -04:00
transmitEvent ( 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 :
2009-08-28 11:16:57 -04:00
navigateUp ( playerID , type , pressedDown ) ;
2009-07-18 12:04:45 -04:00
break ;
case PA_BRAKE :
2009-08-28 11:16:57 -04:00
navigateDown ( playerID , type , pressedDown ) ;
2009-07-18 12:04:45 -04:00
break ;
case PA_RESCUE :
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 :
2009-10-31 19:14:52 -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 ;
// FIXME : consider returned value?
2009-08-27 14:41:20 -04:00
onWidgetActivated ( w , playerID ) ;
2009-07-18 12:04:45 -04:00
}
2009-08-10 20:55:48 -04:00
/*
// 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 ) ;
*/
2009-07-18 12:04:45 -04:00
break ;
default :
return ;
}
}
2009-08-28 11:16:57 -04:00
// -----------------------------------------------------------------------------
void EventHandler : : navigateUp ( const int playerID , Input : : InputType type , const bool pressedDown )
{
2009-10-31 15:09:45 -04:00
std : : cout < < " Naviagte up! \n " ;
2009-08-28 14:46:02 -04:00
IGUIElement * el = NULL , * first = NULL , * closest = NULL ;
2009-08-28 11:16:57 -04:00
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getFocusForPlayer ( playerID ) ;
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 )
{
IGUIListBox * list = dynamic_cast < IGUIListBox * > ( w - > m_element ) ;
assert ( list ! = NULL ) ;
const bool stay_within_list = list - > getSelected ( ) > 0 ;
2009-10-31 15:09:45 -04:00
/*
2009-08-28 11:16:57 -04:00
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 ) ;
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 ( stay_within_list )
{
list - > setSelected ( list - > getSelected ( ) - 1 ) ;
return ;
}
else
{
list - > setSelected ( - 1 ) ;
}
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 ) ;
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-09-27 16:38:40 -04:00
2009-08-28 11:16:57 -04:00
// find closest widget
if ( el ! = NULL & & el - > getTabGroup ( ) ! = NULL & &
el - > getTabGroup ( ) - > getNextElement ( el - > getTabOrder ( ) , true /* reverse */ , false /* group */ , first , closest ) )
{
2009-10-31 15:09:45 -04:00
std : : cout < < " Navigating up to " < < closest - > getID ( ) < < std : : endl ;
2009-09-01 14:11:26 -04:00
Widget * w = GUIEngine : : getWidget ( closest - > getID ( ) ) ;
2009-10-31 15:09:45 -04:00
w - > setFocusForPlayer ( playerID ) ;
2009-08-28 11:16:57 -04:00
// when focusing a list by going up, select the last item of the list
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
{
2009-10-30 20:32:18 -04: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
2009-09-05 13:27:14 -04:00
Widget * w = NULL ;
if ( ModalDialog : : isADialogActive ( ) )
{
// TODO : select last widget in modal dialogs
}
else
{
Screen * screen = GUIEngine : : getCurrentScreen ( ) ;
if ( screen = = NULL ) return ;
w = screen - > getLastWidget ( ) ;
}
2009-08-28 11:16:57 -04:00
2009-10-31 15:09:45 -04:00
if ( w ! = NULL ) w - > setFocusForPlayer ( playerID ) ;
2009-08-28 11:16:57 -04:00
}
}
// -----------------------------------------------------------------------------
void EventHandler : : navigateDown ( const int playerID , Input : : InputType type , const bool pressedDown )
{
2009-10-31 15:09:45 -04:00
std : : cout < < " Naviagte down! \n " ;
2009-08-28 14:46:02 -04:00
IGUIElement * el = NULL , * first = NULL , * closest = NULL ;
2009-08-28 11:16:57 -04:00
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getFocusForPlayer ( playerID ) ;
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 )
{
IGUIListBox * list = dynamic_cast < IGUIListBox * > ( w - > m_element ) ;
assert ( list ! = NULL ) ;
const bool stay_within_list = list - > getSelected ( ) < ( int ) list - > getItemCount ( ) - 1 ;
2009-10-31 15:09:45 -04:00
/*
2009-08-28 11:16:57 -04:00
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 ) ;
2009-10-31 15:09:45 -04:00
} */
if ( stay_within_list )
{
list - > setSelected ( list - > getSelected ( ) + 1 ) ;
return ;
}
else
{
list - > setSelected ( - 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
{
2009-10-31 15:09:45 -04:00
//std::cout << " w->m_tab_down_root=" << w->m_tab_down_root << std::endl;
2009-10-28 20:59:46 -04:00
Widget * down = GUIEngine : : getWidget ( w - > m_tab_down_root ) ;
2009-10-30 20:32:18 -04:00
//std::cout << "navigateDown : setting root to " << w->m_tab_down_root << std::endl;
2009-10-28 20:59:46 -04:00
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-09-27 16:38:40 -04:00
2009-08-28 11:16:57 -04:00
if ( el ! = NULL & & el - > getTabGroup ( ) ! = NULL & &
el - > getTabGroup ( ) - > getNextElement ( el - > getTabOrder ( ) , false , false , first , closest ) )
{
2009-10-31 15:09:45 -04:00
//std::cout << "Navigating down to " << closest->getID() << std::endl;
2009-09-27 16:38:40 -04:00
2009-10-31 15:09:45 -04:00
Widget * w = GUIEngine : : getWidget ( closest - > getID ( ) ) ;
assert ( w ! = NULL ) ;
w - > setFocusForPlayer ( playerID ) ;
// another list exception : when entering a list, select the first item
if ( w - > m_type = = WTYPE_LIST )
2009-08-28 11:16:57 -04:00
{
2009-10-31 15:09:45 -04:00
IGUIListBox * list = ( IGUIListBox * ) ( w - > m_element ) ;
assert ( list ! = NULL ) ;
list - > setSelected ( 0 ) ;
2009-08-28 11:16:57 -04:00
}
}
else
{
2009-10-30 20:32:18 -04:00
std : : cout < < " EventHandler::navigateDown : warp around, selecting the first widget \n " ;
//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(), false, false, first, closest))std::cout << " because el (" << core::stringc(el->getText()).c_str() << ", tab order " << el->getTabOrder() << ") has no known next\n";
2009-10-21 18:51:23 -04:00
//std::cout << "!!! Player " << playerID << " cannot navigating down, no next widget found;\n";
2009-09-27 16:38:40 -04:00
2009-08-28 11:16:57 -04:00
// select the first widget
2009-09-05 13:27:14 -04:00
Widget * w = NULL ;
if ( ModalDialog : : isADialogActive ( ) )
{
// TODO : select first widget in modal dialogs
}
else
{
Screen * screen = GUIEngine : : getCurrentScreen ( ) ;
if ( screen = = NULL ) return ;
w = screen - > getFirstWidget ( ) ;
}
2009-10-31 15:09:45 -04:00
if ( w ! = NULL ) w - > setFocusForPlayer ( playerID ) ;
2009-08-28 11:16:57 -04:00
}
}
// -----------------------------------------------------------------------------
2009-07-18 12:04:45 -04:00
EventHandler * event_handler_singleton = NULL ;
EventHandler * EventHandler : : get ( )
{
if ( event_handler_singleton = = NULL )
{
event_handler_singleton = new EventHandler ( ) ;
}
return event_handler_singleton ;
}