|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#include "game_controls/navigationpanel.h"
#include "econ/econ_controls.h"
#include "vgui_controls/Frame.h"
#include "vgui/IInput.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CNavigationPanel );
//-----------------------------------------------------------------------------
class CNavButton : public CExImageButton { DECLARE_CLASS_SIMPLE( CNavButton, CExImageButton ); public: CNavButton( Panel *parent, const char *name, const char *text = "", Panel *pActionSignalTarget = NULL, const char *cmd = NULL ) : CExImageButton( parent, name, text, pActionSignalTarget, cmd ), m_iUserData( -1 ) {}
CNavButton( Panel *parent, const char *name, const wchar_t *wszText = L"", Panel *pActionSignalTarget = NULL, const char *cmd = NULL ) : CExImageButton( parent, name, wszText, pActionSignalTarget, cmd ) , m_iUserData( -1 ) {}
virtual void ApplySettings( KeyValues *pInResourceData ) { BaseClass::ApplySettings( pInResourceData );
if ( m_iUserData < 0 ) { m_iUserData = pInResourceData->GetInt( "userdata", -1 ); AssertMsg( m_iUserData != -1, "Any messages sent for this button will have invalid user data!" ); } }
int m_iUserData; };
//-----------------------------------------------------------------------------
CNavigationPanel::CNavigationPanel( Panel *pParent, const char *pName, bool bAddParentAsActionSignalTarget/*=true*/ ) : BaseClass( pParent, pName ), m_bAutoLayout( false ), m_bAutoScale( true ), m_bDisplayVertical( false ), m_iSelectedButton( 0 ), // m_nAlignment( ALIGN_CENTER ),
m_pKVButtonSettings( NULL ) { if ( bAddParentAsActionSignalTarget && pParent ) { AddActionSignalTarget( pParent ); } }
CNavigationPanel::~CNavigationPanel() { }
void CNavigationPanel::AddButton( int iUserData, const char *pTextToken ) { const int i = m_vecButtons.Count(); CNavButton *pNewButton = new CNavButton( this, CFmtStr( "button_%i", i ).Access(), pTextToken ); pNewButton->m_iUserData = iUserData; pNewButton->InvalidateLayout( true, false ); pNewButton->SetCommand( CFmtStr( "select_%i", i ).Access() ); m_vecButtons.AddToTail( pNewButton ); }
CExImageButton *CNavigationPanel::GetButton( int index ) { return m_vecButtons[ index ]; }
void CNavigationPanel::ApplySettings( KeyValues *pInResourceData ) { BaseClass::ApplySettings( pInResourceData );
/*
const char *pAlignment = pInResourceData->GetString( "align", NULL ); if ( pAlignment ) { if ( !V_strnicmp( pAlignment, "west", 4 ) ) { m_nAlignment = ALIGN_WEST; } else if ( !V_strnicmp( pAlignment, "center", 6 ) ) { m_nAlignment = ALIGN_CENTER; } else if ( !V_strnicmp( pAlignment, "east", 4 ) ) { AssertMsg( 0, "This type of alignment is not supported." ); } } */
m_bAutoLayout = pInResourceData->GetBool( "auto_layout", false ); m_bAutoScale = pInResourceData->GetBool( "auto_scale", true ); m_bDisplayVertical = pInResourceData->GetBool( "display_vertically", false );
KeyValues *pKVButtonSettings = pInResourceData->FindKey( "ButtonSettings" ); AssertMsg( pKVButtonSettings, "This is required" ); if ( !pKVButtonSettings ) { AssertMsg( 0, "No button settings specified. CNavigationPanel is useless without this data." ); return; }
// Cache this off for later
if ( m_pKVButtonSettings ) { m_pKVButtonSettings->deleteThis(); m_pKVButtonSettings = NULL; } m_pKVButtonSettings = pKVButtonSettings->MakeCopy();
// Get individual button data and apply now
KeyValues *pKVButtons = pInResourceData->FindKey( "Buttons" ); if ( !pKVButtons ) return;
// Go through each image description and create a button
if ( m_vecButtons.Count() ) return;
int i = 0; FOR_EACH_SUBKEY( pKVButtons, pKVCurButton ) { CNavButton *pNewButton = new CNavButton( this, pKVCurButton->GetString( "FieldName", pKVCurButton->GetName() ), L"" ); pNewButton->ApplySettings( pKVCurButton ); pNewButton->InvalidateLayout( true, false ); pNewButton->SetCommand( CFmtStr( "select_%i", i ).Access() ); m_vecButtons.AddToTail( pNewButton ); ++i; }
if ( m_vecButtons.IsValidIndex( m_iSelectedButtonDefault ) ) { UpdateButtonSelectionStates( m_iSelectedButtonDefault ); m_vecButtons[ m_iSelectedButtonDefault ]->InvalidateLayout( true );
const int iUserData = m_vecButtons[ m_iSelectedButtonDefault ]->m_iUserData; PostActionSignal( new KeyValues( "NavButtonSelected", "userdata", iUserData ) ); } }
void CNavigationPanel::ApplySchemeSettings( IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); }
void CNavigationPanel::PerformLayout() { if ( !m_vecButtons.Count() ) return;
if ( !m_pKVButtonSettings ) return;
BaseClass::PerformLayout();
// Get from settings
int nSettingWidth = m_pKVButtonSettings->GetInt( "wide" ); int nSettingHeight = m_pKVButtonSettings->GetInt( "tall" );
// Button dimensions for setting positions
int nButtonWidth = nSettingWidth; int nButtonHeight = nSettingHeight;
if ( m_bAutoScale ) { // Get image size
int nImageW, nImageH; m_vecButtons[0]->GetImage()->GetSize( nImageW, nImageH );
int nWidth, nHeight; if ( m_bDisplayVertical ) { nWidth = GetWide(); nHeight = nSettingHeight * nWidth / ( nSettingWidth > 0 ? nSettingWidth : 1 ); } else { nHeight = GetTall(); nWidth = nSettingWidth * nHeight / ( nSettingHeight > 0 ? nSettingHeight : 1 ); }
// Update button dimensions to scaled versions
nButtonWidth = nWidth; nButtonHeight = nHeight; }
FOR_EACH_VEC( m_vecButtons, i ) { if ( m_vecButtons[i] && m_pKVButtonSettings ) { // Apply generic settings
m_vecButtons[i]->ApplySettings( m_pKVButtonSettings ); }
if ( m_bAutoLayout ) { // Display buttons vertically or horizontally?
if ( m_bDisplayVertical ) { m_vecButtons[i]->SetPos( 0, i * ( nButtonHeight + m_nVerticalBuffer ) ); } else { const int nStartX = 0;//0.5f * ( GetWide() - NumButtons() * ( nButtonWidth + m_nHorizontalBuffer ) );
m_vecButtons[i]->SetPos( nStartX + i * ( nButtonWidth + m_nHorizontalBuffer ), 0 ); } }
if ( m_bAutoScale ) { m_vecButtons[i]->SetSize( nButtonWidth, nButtonHeight ); m_vecButtons[i]->GetImage()->SetSize( nButtonWidth, nButtonHeight ); }
m_vecButtons[i]->SetVisible( true ); } }
void CNavigationPanel::OnCommand( const char *pCommand ) { if ( !V_strnicmp( pCommand, "select_", 7 ) ) { const int iButton = atoi( pCommand + 7 ); AssertMsg( m_vecButtons.IsValidIndex( iButton ), "Button index out of range!" ); if ( !m_vecButtons.IsValidIndex( iButton ) ) return;
UpdateButtonSelectionStates( iButton );
const int iUserData = m_vecButtons[ iButton ]->m_iUserData; PostActionSignal( new KeyValues( "NavButtonSelected", "userdata", iUserData ) ); } else { BaseClass::OnCommand( pCommand ); } }
void CNavigationPanel::OnThink() { BaseClass::OnThink();
// Make sure we only ever have one button in the selection state, since it's
// possible to do this if you select a button, then click and drag on another
// button, and release the mouse elsewhere.
if ( !vgui::input()->IsMouseDown( MOUSE_LEFT ) ) { UpdateButtonSelectionStates( m_iSelectedButton ); } }
void CNavigationPanel::UpdateButtonSelectionStates( int iButton ) { if ( m_iSelectedButton != iButton ) { m_iSelectedButton = iButton; }
// Set the correct button as selected, all other buttons as not selected
for ( int i = 0; i < NumButtons(); ++i ) { CNavButton *pCurButton = m_vecButtons[ i ]; if ( !pCurButton ) continue;
bool bShouldSelect = iButton == i; pCurButton->SetSelected( bShouldSelect ); pCurButton->InvalidateLayout(); } }
//-----------------------------------------------------------------------------
#ifdef _DEBUG
class CNavPanelTest : public Frame { DECLARE_CLASS_SIMPLE( CNavPanelTest, Frame );
public: CNavPanelTest( vgui::Panel *pParent ) : Frame( pParent, "NavPanelTest" ) { SetProportional( true ); LoadControlSettings( "Resource/UI/NavigationPanelTest.res" ); } };
CON_COMMAND( open_navpanel_test, "" ) { CNavPanelTest *pPanel = SETUP_PANEL( new CNavPanelTest( NULL ) ); pPanel->SetVisible( true ); pPanel->InvalidateLayout( false, true );
engine->ClientCmd_Unrestricted( "gameui_activate" );
const int nWidth = XRES( 300 ); const int nHeight = YRES( 300 );
pPanel->SetBounds( ( ScreenWidth() - nWidth ) / 2, ( ScreenHeight() - nHeight ) / 2, nWidth, nHeight );
pPanel->Activate(); }
#endif // _DEBUG
|