DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

MenuWidget.h (40639B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 #ifndef __MENU_WIDGET_H__
     29 #define __MENU_WIDGET_H__
     30 
     31 class idMenuHandler;
     32 class idMenuWidget;
     33 
     34 enum menuOption_t {
     35 	OPTION_INVALID = -1,
     36 	OPTION_BUTTON_TEXT,
     37 	OPTION_SLIDER_BAR,
     38 	OPTION_SLIDER_TEXT,
     39 	OPTION_SLIDER_TOGGLE,
     40 	OPTION_BUTTON_INFO,
     41 	OPTION_BUTTON_FULL_TEXT_SLIDER,
     42 	MAX_MENU_OPTION_TYPES
     43 };
     44 
     45 enum widgetEvent_t {
     46 	WIDGET_EVENT_PRESS,
     47 	WIDGET_EVENT_RELEASE,
     48 	WIDGET_EVENT_ROLL_OVER,
     49 	WIDGET_EVENT_ROLL_OUT,
     50 	WIDGET_EVENT_FOCUS_ON,
     51 	WIDGET_EVENT_FOCUS_OFF,
     52 	
     53 	WIDGET_EVENT_SCROLL_UP_LSTICK,
     54 	WIDGET_EVENT_SCROLL_UP_LSTICK_RELEASE,
     55 	WIDGET_EVENT_SCROLL_DOWN_LSTICK,
     56 	WIDGET_EVENT_SCROLL_DOWN_LSTICK_RELEASE,
     57 	WIDGET_EVENT_SCROLL_LEFT_LSTICK,
     58 	WIDGET_EVENT_SCROLL_LEFT_LSTICK_RELEASE,
     59 	WIDGET_EVENT_SCROLL_RIGHT_LSTICK,
     60 	WIDGET_EVENT_SCROLL_RIGHT_LSTICK_RELEASE,
     61 
     62 	WIDGET_EVENT_SCROLL_UP_RSTICK,
     63 	WIDGET_EVENT_SCROLL_UP_RSTICK_RELEASE,
     64 	WIDGET_EVENT_SCROLL_DOWN_RSTICK,
     65 	WIDGET_EVENT_SCROLL_DOWN_RSTICK_RELEASE,
     66 	WIDGET_EVENT_SCROLL_LEFT_RSTICK,
     67 	WIDGET_EVENT_SCROLL_LEFT_RSTICK_RELEASE,
     68 	WIDGET_EVENT_SCROLL_RIGHT_RSTICK,
     69 	WIDGET_EVENT_SCROLL_RIGHT_RSTICK_RELEASE,
     70 
     71 	WIDGET_EVENT_SCROLL_UP,
     72 	WIDGET_EVENT_SCROLL_UP_RELEASE,
     73 	WIDGET_EVENT_SCROLL_DOWN,
     74 	WIDGET_EVENT_SCROLL_DOWN_RELEASE,
     75 	WIDGET_EVENT_SCROLL_LEFT,
     76 	WIDGET_EVENT_SCROLL_LEFT_RELEASE,
     77 	WIDGET_EVENT_SCROLL_RIGHT,
     78 	WIDGET_EVENT_SCROLL_RIGHT_RELEASE,
     79 
     80 	WIDGET_EVENT_DRAG_START,
     81 	WIDGET_EVENT_DRAG_STOP,
     82 
     83 	WIDGET_EVENT_SCROLL_PAGEDWN,
     84 	WIDGET_EVENT_SCROLL_PAGEDWN_RELEASE,
     85 	WIDGET_EVENT_SCROLL_PAGEUP,
     86 	WIDGET_EVENT_SCROLL_PAGEUP_RELEASE,
     87 
     88 	WIDGET_EVENT_SCROLL,
     89 	WIDGET_EVENT_SCROLL_RELEASE,
     90 	WIDGET_EVENT_BACK,
     91 	WIDGET_EVENT_COMMAND,
     92 	WIDGET_EVENT_TAB_NEXT,
     93 	WIDGET_EVENT_TAB_PREV,
     94 	MAX_WIDGET_EVENT
     95 };
     96 
     97 enum scrollType_t {
     98 	SCROLL_SINGLE,		// scroll a single unit
     99 	SCROLL_PAGE,		// scroll a page
    100 	SCROLL_FULL,		// scroll all the way to the end
    101 	SCROLL_TOP,			// scroll to the first selection
    102 	SCROLL_END,			// scroll to the last selection
    103 };
    104 
    105 enum widgetAction_t {
    106 	WIDGET_ACTION_NONE,
    107 	WIDGET_ACTION_COMMAND,
    108 	WIDGET_ACTION_FUNCTION,					// call the SWF function
    109 	WIDGET_ACTION_SCROLL_VERTICAL,			// scroll something. takes one param = amount to scroll (can be negative)
    110 	WIDGET_ACTION_SCROLL_VERTICAL_VARIABLE,
    111 	WIDGET_ACTION_SCROLL_PAGE,
    112 	WIDGET_ACTION_SCROLL_HORIZONTAL,		// scroll something. takes one param = amount to scroll (can be negative)
    113 	WIDGET_ACTION_SCROLL_TAB,
    114 	WIDGET_ACTION_START_REPEATER,
    115 	WIDGET_ACTION_STOP_REPEATER,
    116 	WIDGET_ACTION_ADJUST_FIELD,
    117 	WIDGET_ACTION_PRESS_FOCUSED,
    118 	WIDGET_ACTION_JOY3_ON_PRESS,
    119 	WIDGET_ACTION_JOY4_ON_PRESS,
    120 	//
    121 	WIDGET_ACTION_GOTO_MENU,
    122 	WIDGET_ACTION_GO_BACK,
    123 	WIDGET_ACTION_EXIT_GAME,
    124 	WIDGET_ACTION_LAUNCH_MULTIPLAYER,
    125 	WIDGET_ACTION_MENU_BAR_SELECT,
    126 	WIDGET_ACTION_EMAIL_HOVER,
    127 	// PDA USER DATA ACTIONS
    128 	WIDGET_ACTION_PDA_SELECT_USER,
    129 	WIDGET_ACTION_SELECT_GAMERTAG,
    130 	WIDGET_ACTION_PDA_SELECT_NAV,
    131 	WIDGET_ACTION_SELECT_PDA_AUDIO,
    132 	WIDGET_ACTION_SELECT_PDA_VIDEO,
    133 	WIDGET_ACTION_SELECT_PDA_ITEM,
    134 	WIDGET_ACTION_SCROLL_DRAG,
    135 	// PDA EMAIL ACTIONS
    136 	WIDGET_ACTION_PDA_SELECT_EMAIL,
    137 	WIDGET_ACTION_PDA_CLOSE,
    138 	WIDGET_ACTION_REFRESH,
    139 	WIDGET_ACTION_MUTE_PLAYER,
    140 	MAX_WIDGET_ACTION
    141 };
    142 
    143 enum actionHandler_t {
    144 	WIDGET_ACTION_EVENT_SCROLL_UP_START_REPEATER,
    145 	WIDGET_ACTION_EVENT_SCROLL_UP_START_REPEATER_VARIABLE,
    146 	WIDGET_ACTION_EVENT_SCROLL_DOWN_START_REPEATER,
    147 	WIDGET_ACTION_EVENT_SCROLL_DOWN_START_REPEATER_VARIABLE,
    148 	WIDGET_ACTION_EVENT_SCROLL_LEFT_START_REPEATER,
    149 	WIDGET_ACTION_EVENT_SCROLL_RIGHT_START_REPEATER,
    150 	WIDGET_ACTION_EVENT_SCROLL_PAGE_DOWN_START_REPEATER,
    151 	WIDGET_ACTION_EVENT_SCROLL_PAGE_UP_START_REPEATER,
    152 	WIDGET_ACTION_EVENT_STOP_REPEATER,
    153 	WIDGET_ACTION_EVENT_TAB_NEXT,
    154 	WIDGET_ACTION_EVENT_TAB_PREV,
    155 	WIDGET_ACTION_EVENT_DRAG_START,
    156 	WIDGET_ACTION_EVENT_DRAG_STOP,
    157 	WIDGET_ACTION_EVENT_JOY3_ON_PRESS,
    158 };
    159 
    160 struct widgetTransition_t {
    161 	widgetTransition_t() :
    162 		animationName( NULL ) {
    163 
    164 	}
    165 
    166 	const char *						animationName;			// name of the animation to run
    167 	idStaticList< const char *, 4 >		prefixes;				// prefixes to try to use for animation
    168 };
    169 
    170 
    171 /*
    172 ================================================
    173 scoreboardInfo_t
    174 ================================================
    175 */
    176 struct scoreboardInfo_t {
    177 	scoreboardInfo_t() :
    178 		index( -1 ),
    179 		voiceState( VOICECHAT_DISPLAY_NONE ) {
    180 	}
    181 
    182 	idList< idStr, TAG_IDLIB_LIST_MENU> values;
    183 	int						index;
    184 	voiceStateDisplay_t		voiceState;
    185 };
    186 
    187 /*
    188 ================================================
    189 idSort_SavesByDate
    190 ================================================
    191 */
    192 class idSort_SavesByDate : public idSort_Quick< idSaveGameDetails, idSort_SavesByDate > {
    193 public:
    194 	int Compare( const idSaveGameDetails & a, const idSaveGameDetails & b ) const {
    195 		return b.date - a.date;
    196 	}
    197 };
    198 
    199 /*
    200 ================================================
    201 idMenuDataSource
    202 ================================================
    203 */
    204 class idMenuDataSource {
    205 public:
    206 	virtual ~idMenuDataSource() { }
    207 
    208 	virtual void				LoadData()							= 0;
    209 	virtual void				CommitData()						= 0;
    210 	virtual bool				IsDataChanged() const				= 0;
    211 	virtual idSWFScriptVar		GetField( const int fieldIndex ) const	= 0;
    212 	virtual void				AdjustField( const int fieldIndex, const int adjustAmount ) = 0;
    213 };
    214 
    215 /*
    216 ================================================
    217 idWidgetEvent
    218 ================================================
    219 */
    220 class idWidgetEvent {
    221 public:
    222 	idWidgetEvent() :
    223 		type( WIDGET_EVENT_PRESS ),
    224 		arg( 0 ),
    225 		thisObject( NULL ) {
    226 
    227 	}
    228 
    229 	idWidgetEvent( const widgetEvent_t type_, const int arg_, idSWFScriptObject * thisObject_, const idSWFParmList & parms_ ) :
    230 		type( type_  ),
    231 		arg( arg_ ),
    232 		thisObject( thisObject_ ),
    233 		parms( parms_ ) {
    234 	}
    235 
    236 	widgetEvent_t			type;
    237 	int						arg;
    238 	idSWFScriptObject *		thisObject;
    239 	idSWFParmList 			parms;
    240 };
    241 
    242 /*
    243 ================================================
    244 idWidgetAction
    245 ================================================
    246 */
    247 class idWidgetAction {
    248 public:
    249 	idWidgetAction() :
    250 		action( WIDGET_ACTION_NONE ),
    251 		scriptFunction( NULL ) {
    252 	}
    253 
    254 	idWidgetAction( const idWidgetAction & src ) {
    255 		action = src.action;
    256 		parms = src.parms;
    257 		scriptFunction = src.scriptFunction;
    258 		if ( scriptFunction != NULL ) {
    259 			scriptFunction->AddRef();
    260 		}
    261 	}
    262 
    263 	~idWidgetAction() {
    264 		if ( scriptFunction != NULL ) {
    265 			scriptFunction->Release();
    266 		}
    267 	}
    268 
    269 	void operator=( const idWidgetAction & src ) {
    270 		action = src.action;
    271 		parms = src.parms;
    272 		scriptFunction = src.scriptFunction;
    273 		if ( scriptFunction != NULL ) {
    274 			scriptFunction->AddRef();
    275 		}
    276 	}
    277 
    278 	bool operator==( const idWidgetAction & otherAction ) const {
    279 		if ( GetType() != otherAction.GetType()
    280 				|| GetParms().Num() != otherAction.GetParms().Num() ) {
    281 			return false;
    282 		}
    283 
    284 		// everything else is equal, so check all parms. NOTE: this assumes we are only sending
    285 		// integral types.
    286 		for ( int i = 0; i < GetParms().Num(); ++i ) {
    287 			if ( GetParms()[ i ].GetType() != otherAction.GetParms()[ i ].GetType() 
    288 				|| GetParms()[ i ].ToInteger() != otherAction.GetParms()[ i ].ToInteger() ) {
    289 				return false;
    290 			}
    291 		}
    292 
    293 		return true;
    294 	}
    295 
    296 	void Set( idSWFScriptFunction * function ) {
    297 		action = WIDGET_ACTION_FUNCTION;
    298 		if ( scriptFunction != NULL ) {
    299 			scriptFunction->Release();
    300 		}
    301 		scriptFunction = function;
    302 		scriptFunction->AddRef();
    303 	}
    304 
    305 	void Set( widgetAction_t action_ ) {
    306 		action = action_;
    307 		parms.Clear();
    308 	}
    309 
    310 	void Set( widgetAction_t action_, const idSWFScriptVar & var1 ) {
    311 		action = action_;
    312 		parms.Clear();
    313 		parms.Append( var1 );
    314 	}
    315 
    316 	void Set( widgetAction_t action_, const idSWFScriptVar & var1, const idSWFScriptVar & var2 ) {
    317 		action = action_;
    318 		parms.Clear();
    319 		parms.Append( var1 );
    320 		parms.Append( var2 );
    321 	}
    322 
    323 	void Set( widgetAction_t action_, const idSWFScriptVar & var1, const idSWFScriptVar & var2, const idSWFScriptVar & var3 ) {
    324 		action = action_;
    325 		parms.Clear();
    326 		parms.Append( var1 );
    327 		parms.Append( var2 );
    328 		parms.Append( var3 );
    329 	}
    330 
    331 	void Set( widgetAction_t action_, const idSWFScriptVar & var1, const idSWFScriptVar & var2, const idSWFScriptVar & var3, const idSWFScriptVar & var4 ) {
    332 		action = action_;
    333 		parms.Clear();
    334 		parms.Append( var1 );
    335 		parms.Append( var2 );
    336 		parms.Append( var3 );
    337 		parms.Append( var4 );
    338 	}
    339 
    340 	idSWFScriptFunction *	GetScriptFunction() { return scriptFunction; }
    341 	const widgetAction_t	GetType() const { return action; }
    342 	const idSWFParmList &	GetParms() const { return parms; }
    343 
    344 private:
    345 	widgetAction_t			action;
    346 	idSWFParmList			parms;
    347 	idSWFScriptFunction *	scriptFunction;
    348 };
    349 
    350 typedef idList< idMenuWidget *, TAG_IDLIB_LIST_MENU > idMenuWidgetList;
    351 
    352 /*
    353 ================================================
    354 idMenuWidget
    355 
    356 We're using a model/view architecture, so this is the combination of both model and view.  The
    357 other part of the view is the SWF itself.
    358 ================================================
    359 */
    360 class idMenuWidget {
    361 public:
    362 
    363 	/*
    364 	================================================
    365 	WrapWidgetSWFEvent
    366 	================================================
    367 	*/
    368 	class WrapWidgetSWFEvent : public idSWFScriptFunction_RefCounted {
    369 	public:
    370 		WrapWidgetSWFEvent( idMenuWidget * widget, const widgetEvent_t event, const int eventArg ) :
    371 			targetWidget( widget ),
    372 			targetEvent( event ),
    373 			targetEventArg( eventArg ) {
    374 		}
    375 
    376 		idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
    377 				targetWidget->ReceiveEvent( idWidgetEvent( targetEvent, targetEventArg, thisObject, parms ) );
    378 			return idSWFScriptVar();
    379 		}
    380 
    381 	private:
    382 		idMenuWidget *	targetWidget;
    383 		widgetEvent_t	targetEvent;
    384 		int				targetEventArg;
    385 	};
    386 
    387 
    388 	enum widgetState_t {
    389 		WIDGET_STATE_HIDDEN,	// hidden
    390 		WIDGET_STATE_NORMAL,	// normal
    391 		WIDGET_STATE_SELECTING,	// going into the selected state
    392 		WIDGET_STATE_SELECTED,	// fully selected
    393 		WIDGET_STATE_DISABLED,	// disabled
    394 		WIDGET_STATE_MAX
    395 	};
    396 
    397 										idMenuWidget();
    398 
    399 	virtual								~idMenuWidget();
    400 
    401 	void								Cleanup();
    402 	// typically this is where the allocations for a widget will occur: sub widgets, etc.
    403 	// Note that SWF sprite objects may not be accessible at this point.
    404 	virtual void						Initialize( idMenuHandler * data ) { menuData = data; }
    405 
    406 	// takes the information described in this widget and applies it to a given script object.
    407 	// the script object should point to the root that you want to run from. Running this will
    408 	// also create the sprite binding, if any.
    409 	virtual void						Update() {}
    410 	virtual void						Show();
    411 	virtual void						Hide();
    412 
    413 	widgetState_t						GetState() const { return widgetState; }
    414 	void								SetState( const widgetState_t state );
    415 
    416 	// actually binds the sprite. this must be called after setting sprite path!
    417 	idSWFSpriteInstance *				GetSprite() { return boundSprite; }
    418 	idSWF *								GetSWFObject();
    419 	idMenuHandler *						GetMenuData();
    420 	bool								BindSprite( idSWFScriptObject & root );
    421 	void								ClearSprite();
    422 
    423 	void								SetSpritePath( const char * arg1, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL );
    424 	void								SetSpritePath( const idList< idStr > & spritePath_, const char * arg1 = NULL, const char * arg2 = NULL, const char * arg3 = NULL, const char * arg4 = NULL, const char * arg5 = NULL );
    425 	idList< idStr, TAG_IDLIB_LIST_MENU > &					GetSpritePath() { return spritePath; }
    426 	int									GetRefCount() const { return refCount; }
    427 	void						AddRef() { refCount++; }
    428 	void						Release() { assert( refCount > 0 ); if ( --refCount == 0 && !noAutoFree ) { delete this; } }
    429 
    430 	//------------------------
    431 	// Event Handling
    432 	//------------------------
    433 	virtual bool						HandleAction( idWidgetAction & action, const idWidgetEvent & event, idMenuWidget * widget, bool forceHandled = false );
    434 	virtual void						ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event ) { }
    435 	void								SendEventToObservers( const idWidgetEvent & event );
    436 	void								RegisterEventObserver( idMenuWidget * observer );
    437 	void								ReceiveEvent( const idWidgetEvent & event );
    438 
    439 	// Executes an event in the context of this widget.  Only rarely should this be called
    440 	// directly.  Instead calls should go through ReceiveEvent which will propagate the event
    441 	// through the standard focus order.
    442 	virtual bool						ExecuteEvent( const idWidgetEvent & event );
    443 
    444 	// returns the list of actions for a given event, or NULL if no actions are registered for
    445 	// that event.  Events should not be directly added to the returned list.  Instead use
    446 	// AddEventAction for adding new events.
    447 	idList< idWidgetAction, TAG_IDLIB_LIST_MENU > *			GetEventActions( const widgetEvent_t eventType );
    448 
    449 	// allocates an action for the given event
    450 	idWidgetAction &					AddEventAction( const widgetEvent_t eventType );
    451 	void								ClearEventActions();
    452 
    453 	//------------------------
    454 	// Data modeling
    455 	//------------------------
    456 	void								SetDataSource( idMenuDataSource * dataSource, const int fieldIndex );
    457 	idMenuDataSource *					GetDataSource() { return dataSource; }
    458 	void								SetDataSourceFieldIndex( const int dataSourceFieldIndex_ ) { dataSourceFieldIndex = dataSourceFieldIndex_; }
    459 	int									GetDataSourceFieldIndex() const { return dataSourceFieldIndex; }
    460 
    461 	idMenuWidget *						GetFocus() { return ( focusIndex >= 0 && focusIndex < children.Num() ) ? children[ focusIndex ] : NULL; }
    462 	int									GetFocusIndex() const { return focusIndex; }
    463 	void								SetFocusIndex( const int index, bool skipSound = false );
    464 
    465 	//------------------------
    466 	// Hierarchy
    467 	//------------------------
    468 	idMenuWidgetList &					GetChildren() { return children; }
    469 	const idMenuWidgetList &			GetChildren() const { return children; }
    470 	idMenuWidget &						GetChildByIndex( const int index ) const { return *children[ index ]; }
    471 
    472 	void								AddChild( idMenuWidget * widget );
    473 	void								RemoveChild( idMenuWidget * widget );
    474 	bool								HasChild( idMenuWidget * widget );
    475 	void								RemoveAllChildren();
    476 
    477 	idMenuWidget *						GetParent() { return parent; }
    478 	const idMenuWidget *				GetParent() const { return parent; }
    479 	void								SetParent( idMenuWidget * parent_ ) { parent = parent_; }
    480 	void								SetSWFObj( idSWF * obj ) { swfObj = obj; }
    481 	bool								GetHandlerIsParent() { return handlerIsParent; }
    482 	void								SetHandlerIsParent( bool val ) { handlerIsParent = val; }
    483 	void								SetNoAutoFree( bool b ) { noAutoFree = b; }
    484 
    485 protected:
    486 	void								ForceFocusIndex( const int index ) { focusIndex = index; }
    487 
    488 protected:
    489 	bool								handlerIsParent;
    490 	idMenuHandler *						menuData;
    491 	idSWF *								swfObj;
    492 	idSWFSpriteInstance *				boundSprite;
    493 	idMenuWidget *						parent;
    494 	idList< idStr, TAG_IDLIB_LIST_MENU >						spritePath;
    495 	idMenuWidgetList											children;
    496 	idMenuWidgetList											observers;
    497 
    498 	static const int INVALID_ACTION_INDEX = -1;
    499 	idList< idList< idWidgetAction, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU >		eventActions;
    500 	idStaticList< int, MAX_WIDGET_EVENT >	eventActionLookup;
    501 
    502 	idMenuDataSource *					dataSource;
    503 	int									dataSourceFieldIndex;
    504 
    505 	int									focusIndex;
    506 
    507 	widgetState_t						widgetState;
    508 	int									refCount;
    509 	bool								noAutoFree;
    510 };
    511 
    512 /*
    513 ================================================
    514 idMenuWidget_Button
    515 
    516 This might be better named "ComboButton", as it contains behavior for several controls along
    517 with standard button behavior.
    518 ================================================
    519 */
    520 class idMenuWidget_Button : public idMenuWidget {
    521 public:
    522 
    523 	enum animState_t {
    524 		ANIM_STATE_UP,			// standard
    525 		ANIM_STATE_DOWN,		// pressed down
    526 		ANIM_STATE_OVER,		// hovered over this
    527 		ANIM_STATE_MAX
    528 	};
    529 
    530 	idMenuWidget_Button() :
    531 		animState( ANIM_STATE_UP ),
    532 		img( NULL ),
    533 		ignoreColor( false ) {
    534 	}
    535 
    536 	virtual ~idMenuWidget_Button() {}
    537 
    538 	virtual bool			ExecuteEvent( const idWidgetEvent & event );
    539 	virtual void			Update();
    540 
    541 	//---------------
    542 	// Model
    543 	//---------------
    544 	void					SetLabel( const idStr & label ) { btnLabel = label; }
    545 	const idStr &			GetLabel() const { return btnLabel; }
    546 	void					SetValues( idList< idStr > & list );
    547 	const idStr &			GetValue( int index ) const;
    548 	void					SetImg( const idMaterial * val ) { img = val; }
    549 	const idMaterial *		GetImg() { return img; }
    550 	void					SetDescription( const char * desc_ ) { description = desc_; }
    551 	const idStr &			GetDescription() const { return description; }
    552 
    553 	void					SetIgnoreColor( const bool b ) { ignoreColor = b; }
    554 
    555 	animState_t				GetAnimState() const { return animState; }
    556 	void					SetAnimState( const animState_t state ) { animState = state; }
    557 	void					SetOnPressFunction( idSWFScriptFunction * func ) { scriptFunction = func; }
    558 
    559 protected:
    560 	void					SetupTransitionInfo( widgetTransition_t & trans, const widgetState_t buttonState, const animState_t sourceAnimState, const animState_t destAnimState ) const;
    561 	void					AnimateToState( const animState_t targetState, const bool force = false );
    562 
    563 	idList< idStr, TAG_IDLIB_LIST_MENU >			values;
    564 	idStr					btnLabel;
    565 	idStr					description;
    566 	animState_t				animState;
    567 	const idMaterial * 		img;
    568 	idSWFScriptFunction *	scriptFunction;
    569 	bool					ignoreColor;
    570 };
    571 
    572 /*
    573 ================================================
    574 idMenuWidget_LobbyButton
    575 ================================================
    576 */
    577 class idMenuWidget_LobbyButton : public idMenuWidget_Button {
    578 public:	
    579 	idMenuWidget_LobbyButton() :
    580 		voiceState( VOICECHAT_DISPLAY_NONE ) {
    581 	}
    582 
    583 	virtual void			Update();
    584 	void					SetButtonInfo( idStr name_, voiceStateDisplay_t voiceState_ );
    585 	bool					IsValid() { return !name.IsEmpty(); }
    586 
    587 protected:
    588 	idStr					name;
    589 	voiceStateDisplay_t		voiceState;
    590 };
    591 
    592 /*
    593 ================================================
    594 idMenuWidget_ScoreboardButton
    595 ================================================
    596 */
    597 class idMenuWidget_ScoreboardButton : public idMenuWidget_Button {
    598 public:	
    599 	idMenuWidget_ScoreboardButton() :
    600 		voiceState( VOICECHAT_DISPLAY_NONE ),
    601 		index( -1 ) {
    602 	}
    603 
    604 	virtual void			Update();
    605 	void					SetButtonInfo( int index_, idList< idStr > & list, voiceStateDisplay_t voiceState_ );
    606 
    607 protected:
    608 	voiceStateDisplay_t		voiceState;
    609 	int						index;
    610 };
    611 
    612 /*
    613 ================================================
    614 idMenuWidget_ControlButton
    615 ================================================
    616 */
    617 class idMenuWidget_ControlButton : public idMenuWidget_Button {
    618 public:
    619 	idMenuWidget_ControlButton() : 
    620 		optionType( OPTION_BUTTON_TEXT ),
    621 		disabled( false ) {
    622 	}
    623 
    624 	virtual void			Update();
    625 	void					SetOptionType( const menuOption_t type ) { optionType = type; }
    626 	menuOption_t			GetOptionType() const { return optionType; }
    627 	void					SetupEvents( int delay, int index );
    628 	void					SetDisabled( bool disable ) { disabled = disable; }
    629 
    630 protected:
    631 	menuOption_t			optionType;
    632 	bool					disabled;
    633 };
    634 
    635 /*
    636 ================================================
    637 idMenuWidget_ServerButton
    638 ================================================
    639 */
    640 class idMenuWidget_ServerButton : public idMenuWidget_Button {
    641 public:
    642 
    643 	idMenuWidget_ServerButton() :
    644 		players( 0 ),
    645 		index( 0 ),
    646 		maxPlayers( 0 ),
    647 		joinable( false ),
    648 		validMap( false ) {
    649 	}
    650 
    651 	virtual void			Update();
    652 	void					SetButtonInfo( idStr name_, idStrId mapName_, idStr modeName_, int index_ = 0, int players_ = 0, int maxPlayers_ = 0, bool joinable_ = false, bool validMap_ = false );
    653 	bool					IsValid() { return !serverName.IsEmpty(); }
    654 	bool					CanJoin() { return ( joinable && validMap ); }
    655 
    656 protected:
    657 	idStr					serverName;
    658 	int						index;
    659 	int						players;
    660 	int						maxPlayers;
    661 	bool					joinable;
    662 	bool					validMap;
    663 	idStrId					mapName;
    664 	idStr					modeName;	
    665 };
    666 
    667 /*
    668 ================================================
    669 idMenuWidget_NavButton
    670 ================================================
    671 */
    672 class idMenuWidget_NavButton : public idMenuWidget_Button {
    673 public:
    674 
    675 	enum navWidgetState_t {
    676 		NAV_WIDGET_LEFT,		// option on left side
    677 		NAV_WIDGET_RIGHT,		// option on right side
    678 		NAV_WIDGET_SELECTED		// option is selected
    679 	};
    680 
    681 	idMenuWidget_NavButton() : 
    682 		navIndex( 0 ),
    683 		xPos( 0 ) {
    684 	}
    685 
    686 	virtual bool			ExecuteEvent( const idWidgetEvent & event );
    687 	virtual void			Update();
    688 
    689 	void					SetNavIndex( int i, const navWidgetState_t type ) { navIndex = i; navState = type; }
    690 	void					SetPosition( float pos ) { xPos = pos; }
    691 
    692 private:
    693 
    694 	int						navIndex;
    695 	float					xPos;
    696 	navWidgetState_t		navState;
    697 
    698 };
    699 
    700 /*
    701 ================================================
    702 idMenuWidget_NavButton
    703 ================================================
    704 */
    705 class idMenuWidget_MenuButton : public idMenuWidget_Button {
    706 public:
    707 
    708 	idMenuWidget_MenuButton() : 
    709 		xPos( 0 ) {
    710 	}
    711 
    712 	virtual void			Update();
    713 	void					SetPosition( float pos ) { xPos = pos; }
    714 
    715 private:
    716 
    717 	float					xPos;
    718 
    719 };
    720 
    721 /*
    722 ================================================
    723 idMenuWidget_List
    724 
    725 Stores a list of widgets but displays only a segment of them at a time.
    726 ================================================
    727 */
    728 class idMenuWidget_List : public idMenuWidget {
    729 public:
    730 	idMenuWidget_List() :
    731 		numVisibleOptions( 0 ),
    732 		viewOffset( 0 ),
    733 		viewIndex( 0 ),
    734 		allowWrapping( false ) {
    735 
    736 	}
    737 
    738 	virtual void				Update();
    739 	virtual bool				HandleAction( idWidgetAction & action, const idWidgetEvent & event, idMenuWidget * widget, bool forceHandled = false );
    740 	virtual void				ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
    741 	virtual void				Scroll( const int scrollIndexAmount, const bool wrapAround = false );
    742 	virtual void				ScrollOffset( const int scrollIndexAmount );
    743 	virtual int					GetTotalNumberOfOptions() const { return GetChildren().Num(); }
    744 	virtual bool				PrepareListElement( idMenuWidget & widget, const int childIndex ) { return true; }
    745 
    746 	bool						IsWrappingAllowed() const { return allowWrapping; }
    747 	void						SetWrappingAllowed( const bool allow ) { allowWrapping = allow; }
    748 
    749 	void						SetNumVisibleOptions( const int numVisibleOptions_ ) { numVisibleOptions = numVisibleOptions_; }
    750 	int							GetNumVisibleOptions() const { return numVisibleOptions; }
    751 
    752 	int							GetViewOffset() const { return viewOffset; }
    753 	void						SetViewOffset( const int offset ) { viewOffset = offset; }
    754 
    755 	int							GetViewIndex() const { return viewIndex; }
    756 	void						SetViewIndex( const int index ) { viewIndex = index; }
    757 
    758 	void						CalculatePositionFromIndexDelta( int & outIndex, int & outOffset, const int currentIndex, const int currentOffset, const int windowSize, const int maxSize, const int indexDelta, const bool allowWrapping, const bool wrapAround = false ) const;
    759 	void						CalculatePositionFromOffsetDelta( int & outIndex, int & outOffset, const int currentIndex, const int currentOffset, const int windowSize, const int maxSize, const int offsetDelta ) const;
    760 
    761 private:
    762 	int							numVisibleOptions;
    763 	int							viewOffset;
    764 	int							viewIndex;
    765 	bool						allowWrapping;
    766 };
    767 
    768 class idBrowserEntry_t {
    769 public:
    770 	idStr serverName;
    771 	int	index;
    772 	int players;
    773 	int maxPlayers;
    774 	bool joinable;
    775 	bool validMap;
    776 	idStrId mapName;
    777 	idStr modeName;
    778 };
    779 
    780 /*
    781 ================================================
    782 idMenuWidget_GameBrowserList
    783 ================================================
    784 */
    785 class idMenuWidget_GameBrowserList : public idMenuWidget_List {
    786 public:
    787 	virtual void				Update();
    788 	virtual bool				PrepareListElement( idMenuWidget & widget, const int childIndex );
    789 	virtual int					GetTotalNumberOfOptions() const;
    790 	void						ClearGames();
    791 	void						AddGame( idStr name_, idStrId mapName_, idStr modeName_, int index_ = 0, int players_ = 0, int maxPlayers_ = 0, bool joinable_ = false, bool validMap_ = false );
    792 	int							GetServerIndex();
    793 private:
    794 	idList< idBrowserEntry_t >	games;
    795 };
    796 
    797 /*
    798 ================================================
    799 idMenuWidget_Carousel
    800 Displays a list of items in a looping carousel pattern 
    801 ================================================
    802 */
    803 class idMenuWidget_Carousel : public idMenuWidget {
    804 public:
    805 
    806 	idMenuWidget_Carousel() :
    807 		numVisibleOptions( 0 ),
    808 		viewIndex( 0 ),
    809 		moveToIndex( 0 ),
    810 		scrollLeft( false ),
    811 		fastScroll( false ),
    812 		moveDiff( 0 ) {
    813 	}
    814 
    815 	virtual void				Initialize( idMenuHandler * data );
    816 	virtual void				Update();
    817 	virtual bool				HandleAction( idWidgetAction & action, const idWidgetEvent & event, idMenuWidget * widget, bool forceHandled = false );
    818 	virtual int					GetTotalNumberOfOptions() const { return imgList.Num(); }
    819 	virtual bool				PrepareListElement( idMenuWidget & widget, const int childIndex ) { return true; }
    820 
    821 	void						SetNumVisibleOptions( const int numVisibleOptions_ ) { numVisibleOptions = numVisibleOptions_; }
    822 	int							GetNumVisibleOptions() const { return numVisibleOptions; }
    823 		
    824 	void						MoveToIndex( int index, bool instant = false );
    825 	void						MoveToFirstItem( bool instant = true );
    826 	void						MoveToLastItem( bool instant = true );
    827 	int							GetMoveToIndex() { return moveToIndex; }
    828 	void						SetMoveToIndex( int index ) { moveToIndex = index; }
    829 	void						SetViewIndex( int index ) { viewIndex = index; }
    830 	int							GetViewIndex() const { return viewIndex; }
    831 	void						SetListImages( idList<const idMaterial *> & list );
    832 	void						SetMoveDiff( int val ) { moveDiff = val; }
    833 	int							GetMoveDiff() { return moveDiff; }
    834 	bool						GetScrollLeft() { return scrollLeft; }
    835 
    836 private:
    837 
    838 	int							numVisibleOptions;
    839 	int							viewIndex;
    840 	int							moveToIndex;
    841 	int							moveDiff;
    842 	bool						fastScroll;
    843 	bool						scrollLeft;
    844 	idList<const idMaterial *>	imgList;
    845 
    846 };
    847 
    848 /*
    849 ================================================
    850 idMenuWidget_Help
    851 
    852 Knows how to display help tooltips by observing events from other widgets
    853 ================================================
    854 */
    855 class idMenuWidget_Help : public idMenuWidget {
    856 public:
    857 	virtual void Update();
    858 	virtual void ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
    859 
    860 private:
    861 	idStr		lastFocusedMessage;		// message from last widget that had focus
    862 	idStr		lastHoveredMessage;		// message from last widget that was hovered over
    863 	bool		hideMessage;
    864 };
    865 
    866 /*
    867 ================================================
    868 idMenuWidget_CommandBar
    869 ================================================
    870 */
    871 class idMenuWidget_CommandBar : public idMenuWidget {
    872 public:
    873 	enum button_t {
    874 		BUTTON_JOY1,
    875 		BUTTON_JOY2,
    876 		BUTTON_JOY3,
    877 		BUTTON_JOY4,
    878 		BUTTON_JOY10,
    879 		BUTTON_TAB,
    880 		MAX_BUTTONS
    881 	};
    882 
    883 	enum alignment_t {
    884 		LEFT,
    885 		RIGHT
    886 	};
    887 
    888 	struct buttonInfo_t {
    889 		idStr			label;			// empty labels are treated as hidden buttons
    890 		idWidgetAction	action;
    891 	};
    892 
    893 	idMenuWidget_CommandBar() :
    894 		alignment( LEFT ) {
    895 
    896 		buttons.SetNum( MAX_BUTTONS );
    897 	}
    898 
    899 	virtual void		Update();
    900 	virtual bool		ExecuteEvent( const idWidgetEvent & event );
    901 
    902 	buttonInfo_t *		GetButton( const button_t button ) { return &buttons[ button ]; }
    903 	void				ClearAllButtons();
    904 
    905 	alignment_t			GetAlignment() const { return alignment; }
    906 	void				SetAlignment( const alignment_t alignment_ ) { alignment = alignment_; }
    907 
    908 private:
    909 	idStaticList< buttonInfo_t, MAX_BUTTONS >	buttons;
    910 	alignment_t									alignment;
    911 };
    912 
    913 /*
    914 ================================================
    915 	idMenuWidget_DynamicList
    916 ================================================
    917 */
    918 class idMenuWidget_LobbyList : public idMenuWidget_List {
    919 public:
    920 	idMenuWidget_LobbyList() :
    921 		numEntries( 0 ) {
    922 	}
    923 	  
    924 	virtual void				Update();
    925 	virtual bool				PrepareListElement( idMenuWidget & widget, const int childIndex );
    926 	virtual int					GetTotalNumberOfOptions() const { return numEntries; }
    927 	void						SetEntryData( int index, idStr name, voiceStateDisplay_t voiceState );
    928 	void						SetHeadingInfo( idList< idStr > & list );
    929 	void						SetNumEntries( int num ) { numEntries = num; }
    930 	int							GetNumEntries() { return numEntries; }
    931 	void						SetRefreshFunction( const char* func );
    932 private:
    933 	idList< idStr, TAG_IDLIB_LIST_MENU >	headings;
    934 	int							numEntries;
    935 };
    936 
    937 /*
    938 ================================================
    939 idMenuWidget_DynamicList
    940 ================================================
    941 */
    942 class idMenuWidget_DynamicList : public idMenuWidget_List {
    943 public:
    944 
    945 	idMenuWidget_DynamicList() : 
    946 		controlList( false ),
    947 		ignoreColor( false ) {
    948 	}
    949 
    950 	virtual void				Update();
    951 	virtual void				Initialize( idMenuHandler * data );
    952 	virtual int					GetTotalNumberOfOptions() const;
    953 	virtual bool				PrepareListElement( idMenuWidget & widget, const int childIndex );
    954 
    955 	virtual void				Recalculate();
    956 	virtual void				SetListData( idList< idList< idStr, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU > & list );
    957 	
    958 	void						SetControlList( bool val ) { controlList = val; }
    959 	void						SetIgnoreColor( bool val ) { ignoreColor = val; }
    960 
    961 protected:
    962 	idList< idList< idStr, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU >	listItemInfo;
    963 	bool						controlList;
    964 	bool						ignoreColor;
    965 };
    966 
    967 /*
    968 ================================================
    969 idMenuWidget_ScoreboardList
    970 ================================================
    971 */
    972 class idMenuWidget_ScoreboardList : public idMenuWidget_DynamicList {
    973 public:
    974 	  virtual void				Update();
    975 	  virtual int				GetTotalNumberOfOptions() const;
    976 };
    977 
    978 /*
    979 ================================================
    980 idMenuWidget_NavBar
    981 
    982 The nav bar is set up with the main option being at the safe frame line.
    983 ================================================
    984 */
    985 class idMenuWidget_NavBar : public idMenuWidget_DynamicList {
    986 public:
    987 
    988 			idMenuWidget_NavBar() : 
    989 				initialPos( 0.0f ),
    990 				buttonPos( 0.0f ),
    991 				leftSpacer( 0.0f ),
    992 				rightSpacer( 0.0f ),
    993 				selectedSpacer( 0.0f ) {		
    994 			}
    995 
    996 	virtual void				Update();
    997 	virtual void				Initialize( idMenuHandler * data );
    998 	virtual void				SetInitialXPos( float pos ) { initialPos = pos; }
    999 	virtual void				SetButtonSpacing( float lSpace, float rSpace, float sSpace ) { leftSpacer = lSpace; rightSpacer = rSpace; selectedSpacer = sSpace; }
   1000 	virtual bool				PrepareListElement( idMenuWidget & widget, const int navIndex );
   1001 	virtual void				SetListHeadings( idList< idStr > & list );
   1002 	virtual int					GetTotalNumberOfOptions() const;
   1003 
   1004 private:
   1005 
   1006 	idList< idStr, TAG_IDLIB_LIST_MENU >		headings;
   1007 	float				initialPos;
   1008 	float				buttonPos;
   1009 	float				leftSpacer;
   1010 	float				rightSpacer;
   1011 	float				selectedSpacer;
   1012 
   1013 };
   1014 
   1015 /*
   1016 ================================================
   1017 idMenuWidget_NavBar
   1018 
   1019 The nav bar is set up with the main option being at the safe frame line.
   1020 ================================================
   1021 */
   1022 class idMenuWidget_MenuBar : public idMenuWidget_DynamicList {
   1023 public:
   1024 
   1025 	idMenuWidget_MenuBar() :
   1026 		totalWidth( 0.0f ),
   1027 		buttonPos( 0.0f ),
   1028 		rightSpacer( 0.0f ) {
   1029 	}
   1030 
   1031 	virtual void				Update();
   1032 	virtual void				Initialize( idMenuHandler * data );
   1033 	virtual void				SetButtonSpacing( float rSpace ) { rightSpacer = rSpace; }
   1034 	virtual bool				PrepareListElement( idMenuWidget & widget, const int navIndex );
   1035 	virtual void				SetListHeadings( idList< idStr > & list );
   1036 	virtual int					GetTotalNumberOfOptions() const;
   1037 
   1038 private: 
   1039 
   1040 	idList< idStr, TAG_IDLIB_LIST_MENU >				headings;
   1041 	float						totalWidth;
   1042 	float						buttonPos;
   1043 	float						rightSpacer;
   1044 		
   1045 };
   1046 
   1047 /*
   1048 ================================================
   1049 idMenuWidget_PDA_UserData
   1050 ================================================
   1051 */
   1052 class idMenuWidget_PDA_UserData : public idMenuWidget {
   1053 public:
   1054 					idMenuWidget_PDA_UserData() : 
   1055 						pdaIndex( 0 ) {
   1056 					}
   1057 virtual ~idMenuWidget_PDA_UserData() {}
   1058 	virtual void	Update();
   1059 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1060 
   1061 private:
   1062 	int		pdaIndex;
   1063 };
   1064 
   1065 /*
   1066 ================================================
   1067 idMenuWidget_DynamicList
   1068 ================================================
   1069 */
   1070 class idMenuWidget_ScrollBar : public idMenuWidget {
   1071 public:
   1072 	idMenuWidget_ScrollBar() : 
   1073 		yTop( 0.0f ),
   1074 		yBot( 0.0f ),
   1075 		dragging( false ) {
   1076 	}
   1077 
   1078 	virtual void	Initialize( idMenuHandler * data );
   1079 	virtual void	Update();
   1080 	virtual bool	HandleAction( idWidgetAction & action, const idWidgetEvent & event, idMenuWidget * widget, bool forceHandled = false );
   1081 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1082 
   1083 	void			CalcTopAndBottom();
   1084 	void			CalculatePosition( float x, float y );
   1085 
   1086 	float			yTop;
   1087 	float			yBot;
   1088 	bool			dragging;
   1089 };
   1090 
   1091 /*
   1092 ================================================
   1093 idMenuWidget_InfoBox
   1094 ================================================
   1095 */
   1096 class idMenuWidget_InfoBox: public idMenuWidget {
   1097 public:
   1098 	idMenuWidget_InfoBox() :
   1099 		scrollbar( NULL ) {
   1100 	}
   1101 
   1102 	virtual void	Initialize( idMenuHandler * data );
   1103 	virtual void	Update();
   1104 	virtual bool	HandleAction( idWidgetAction & action, const idWidgetEvent & event, idMenuWidget * widget, bool forceHandled = false );
   1105 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1106 	void			SetHeading( idStr val ) { heading = val; }
   1107 	void			SetBody( idStr val ) { info = val; }
   1108 	void			ResetInfoScroll();
   1109 	void			Scroll( int d );
   1110 	int				GetScroll();
   1111 	int				GetMaxScroll();
   1112 	void			SetScroll( int scroll );
   1113 	void			SetScrollbar( idMenuWidget_ScrollBar * bar );
   1114 private:
   1115 	idMenuWidget_ScrollBar *	scrollbar;
   1116 	idStr						heading;
   1117 	idStr						info;
   1118 };
   1119 
   1120 /*
   1121 ================================================
   1122 idMenuWidget_PDA_Objective
   1123 ================================================
   1124 */
   1125 class idMenuWidget_PDA_Objective: public idMenuWidget {
   1126 public:
   1127 	idMenuWidget_PDA_Objective() :
   1128 		pdaIndex( 0 ) {
   1129 		}
   1130 	virtual void	Update();
   1131 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1132 private:
   1133 	int		pdaIndex;
   1134 };
   1135 
   1136 /*
   1137 ================================================
   1138 idMenuWidget_Shell_SaveInfo
   1139 ================================================
   1140 */
   1141 class idMenuWidget_Shell_SaveInfo: public idMenuWidget {
   1142 public:
   1143 	idMenuWidget_Shell_SaveInfo() :
   1144 		loadIndex( 0 ),
   1145 		forSaveScreen( false ) {
   1146 	}
   1147 	virtual void	Update();
   1148 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1149 
   1150 	void			SetForSaveScreen( bool val ) { forSaveScreen = val; }
   1151 private:
   1152 	int		loadIndex;
   1153 	bool	forSaveScreen;
   1154 };
   1155 
   1156 /*
   1157 ================================================
   1158 idMenuWidget_PDA_AudioFiles
   1159 ================================================
   1160 */
   1161 class idMenuWidget_PDA_AudioFiles: public idMenuWidget {
   1162 public:
   1163 	idMenuWidget_PDA_AudioFiles() :
   1164 		pdaIndex( 0 ) {
   1165 		}
   1166 	virtual ~idMenuWidget_PDA_AudioFiles();
   1167 	virtual void	Update();
   1168 	virtual void	Initialize( idMenuHandler * data );
   1169 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1170 private:
   1171 	int								pdaIndex;
   1172 	idList< idList< idStr, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU >		audioFileNames;
   1173 };
   1174 
   1175 /*
   1176 ================================================
   1177 idMenuWidget_PDA_AudioFiles
   1178 ================================================
   1179 */
   1180 class idMenuWidget_PDA_EmailInbox: public idMenuWidget {
   1181 public:
   1182 	idMenuWidget_PDA_EmailInbox() :
   1183 		pdaIndex( 0 ),
   1184 		emailList( NULL ),
   1185 		scrollbar( NULL ) {
   1186 	}
   1187 	virtual void	Update();
   1188 	virtual void	Initialize( idMenuHandler * data );
   1189 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1190 
   1191 	idMenuWidget_DynamicList *	GetEmailList() { return emailList; }
   1192 	idMenuWidget_ScrollBar *	GetScrollbar() { return scrollbar; }
   1193 private:
   1194 	idMenuWidget_DynamicList *		emailList;
   1195 	idMenuWidget_ScrollBar *		scrollbar;
   1196 	int								pdaIndex;
   1197 	idList< idList< idStr, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU >		emailInfo;
   1198 };
   1199 
   1200 /*
   1201 ================================================
   1202 	idMenuWidget_PDA_AudioFiles
   1203 ================================================
   1204 */
   1205 class idMenuWidget_ItemAssignment: public idMenuWidget {
   1206 public:
   1207 	idMenuWidget_ItemAssignment() : 
   1208 		slotIndex( 0 ) {
   1209 	}
   1210 
   1211 	virtual void	Update();
   1212 	void			SetIcon( int index, const idMaterial * icon );
   1213 	void			FindFreeSpot();
   1214 	int				GetSlotIndex() { return slotIndex; }
   1215 	void			SetSlotIndex( int num ) { slotIndex = num; }
   1216 private:
   1217 	const idMaterial * images[ NUM_QUICK_SLOTS ];
   1218 	int				slotIndex;
   1219 
   1220 };
   1221 
   1222 
   1223 /*
   1224 ================================================
   1225 idMenuWidget_PDA_AudioFiles
   1226 ================================================
   1227 */
   1228 class idMenuWidget_PDA_VideoInfo: public idMenuWidget {
   1229 public:
   1230 	virtual void	Update();
   1231 	virtual void	ObserveEvent( const idMenuWidget & widget, const idWidgetEvent & event );
   1232 private:
   1233 	int				videoIndex;
   1234 };
   1235 
   1236 
   1237 /*
   1238 ================================================
   1239 idWidgetActionHandler
   1240 ================================================
   1241 */
   1242 class idWidgetActionHandler : public idSWFScriptFunction_RefCounted {
   1243 public:
   1244 	idWidgetActionHandler( idMenuWidget * widget, actionHandler_t actionEventType, widgetEvent_t _event ) :
   1245 		targetWidget( widget ),
   1246 		type( actionEventType ),
   1247 		targetEvent( _event ) {
   1248 
   1249 	}
   1250 
   1251 	idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) {
   1252 
   1253 		idWidgetAction action;
   1254 		bool handled = false;
   1255 		switch ( type ) {
   1256 			case WIDGET_ACTION_EVENT_SCROLL_DOWN_START_REPEATER: {
   1257 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_VERTICAL, 1 );
   1258 				handled = true;
   1259 				break;
   1260 			}
   1261 			case WIDGET_ACTION_EVENT_SCROLL_UP_START_REPEATER: {
   1262 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_VERTICAL, -1 );
   1263 				handled = true;
   1264 				break;
   1265 			}
   1266 			case WIDGET_ACTION_EVENT_SCROLL_DOWN_START_REPEATER_VARIABLE: {
   1267 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_VERTICAL_VARIABLE, 1 );
   1268 				handled = true;
   1269 				break;
   1270 			}
   1271 			case WIDGET_ACTION_EVENT_SCROLL_UP_START_REPEATER_VARIABLE: {
   1272 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_VERTICAL_VARIABLE, -1 );
   1273 				handled = true;
   1274 				break;
   1275 			}
   1276 			case WIDGET_ACTION_EVENT_SCROLL_PAGE_DOWN_START_REPEATER: {
   1277 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_PAGE, 1 );
   1278 				handled = true;
   1279 				break;
   1280 			}
   1281 			case WIDGET_ACTION_EVENT_SCROLL_PAGE_UP_START_REPEATER: {
   1282 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_PAGE, -1 );
   1283 				handled = true;
   1284 				break;
   1285 			}
   1286 			case WIDGET_ACTION_EVENT_STOP_REPEATER: {
   1287 				action.Set( (widgetAction_t)WIDGET_ACTION_STOP_REPEATER );
   1288 				handled = true;
   1289 				break;
   1290 			}
   1291 	   		case WIDGET_ACTION_EVENT_TAB_NEXT: {
   1292 				action.Set( (widgetAction_t)WIDGET_ACTION_SCROLL_TAB, 1 );
   1293 				handled = true;				
   1294 				break;
   1295 			}
   1296 			case WIDGET_ACTION_EVENT_TAB_PREV: {
   1297 				action.Set( (widgetAction_t)WIDGET_ACTION_SCROLL_TAB, -1 );
   1298 				handled = true;				
   1299 				break;
   1300 			}
   1301 			case WIDGET_ACTION_EVENT_JOY3_ON_PRESS: {
   1302 				action.Set( (widgetAction_t)WIDGET_ACTION_JOY3_ON_PRESS );
   1303 				handled = true;
   1304 				break;
   1305 			}
   1306 			case WIDGET_ACTION_EVENT_SCROLL_LEFT_START_REPEATER: {
   1307 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_HORIZONTAL, -1 );
   1308 				handled = true;
   1309 				break;
   1310 			}
   1311 			case WIDGET_ACTION_EVENT_SCROLL_RIGHT_START_REPEATER: {
   1312 				action.Set( (widgetAction_t)WIDGET_ACTION_START_REPEATER, WIDGET_ACTION_SCROLL_HORIZONTAL, 1 );
   1313 				handled = true;
   1314 				break;
   1315 			}
   1316 			case WIDGET_ACTION_EVENT_DRAG_START: {
   1317 				action.Set( (widgetAction_t)WIDGET_ACTION_SCROLL_DRAG );
   1318 				handled = true;
   1319 				break;
   1320 			}
   1321 			case WIDGET_ACTION_EVENT_DRAG_STOP: {
   1322 				action.Set( (widgetAction_t)WIDGET_ACTION_EVENT_DRAG_STOP );
   1323 				handled = true;
   1324 				break;
   1325 			}
   1326 		}
   1327 
   1328 		if ( handled ) {
   1329 			targetWidget->HandleAction( action, idWidgetEvent( targetEvent, 0, thisObject, parms ), targetWidget );
   1330 		}
   1331 
   1332 		return idSWFScriptVar();
   1333 	}
   1334 
   1335 private:
   1336 	idMenuWidget *	targetWidget;
   1337 	actionHandler_t type;
   1338 	widgetEvent_t targetEvent;
   1339 };
   1340 
   1341 #endif