summaryrefslogtreecommitdiff
path: root/game/client/game_controls/navigationpanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/game_controls/navigationpanel.cpp')
-rw-r--r--game/client/game_controls/navigationpanel.cpp324
1 files changed, 324 insertions, 0 deletions
diff --git a/game/client/game_controls/navigationpanel.cpp b/game/client/game_controls/navigationpanel.cpp
new file mode 100644
index 0000000..0cf616d
--- /dev/null
+++ b/game/client/game_controls/navigationpanel.cpp
@@ -0,0 +1,324 @@
+//========= 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