//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include #include #include #include #include #include "tier1/keyvalues.h" #include "tier1/fmtstr.h" #include "vgui/IInput.h" // memdbgon must be the last include file in a .cpp file!!! #include using namespace vgui; //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- BaseInputDialog::BaseInputDialog( Panel *parent, const char *title, bool bShowCancelButton /*= true*/ ) : BaseClass( parent, NULL ) { m_pContextKeyValues = NULL; SetDeleteSelfOnClose( true ); SetTitle(title, true); SetSize(320, 180); SetSizeable( false ); m_pOKButton = new Button( this, "OKButton", "#VGui_OK" ); m_pOKButton->SetCommand( "OK" ); m_pOKButton->SetAsDefaultButton( true ); if ( bShowCancelButton ) { m_pCancelButton = new Button( this, "CancelButton", "#VGui_Cancel" ); m_pCancelButton->SetCommand( "Cancel" ); } else { m_pCancelButton = NULL; } if ( parent ) { AddActionSignalTarget( parent ); } } BaseInputDialog::~BaseInputDialog() { CleanUpContextKeyValues(); } //----------------------------------------------------------------------------- // Purpose: Cleans up the keyvalues //----------------------------------------------------------------------------- void BaseInputDialog::CleanUpContextKeyValues() { if ( m_pContextKeyValues ) { m_pContextKeyValues->deleteThis(); m_pContextKeyValues = NULL; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void BaseInputDialog::DoModal( KeyValues *pContextKeyValues ) { CleanUpContextKeyValues(); m_pContextKeyValues = pContextKeyValues; BaseClass::DoModal(); } //----------------------------------------------------------------------------- // Purpose: lays out controls //----------------------------------------------------------------------------- void BaseInputDialog::PerformLayout() { BaseClass::PerformLayout(); int w, h; GetSize( w, h ); // lay out all the controls int topy = IsSmallCaption() ? 15 : 30; int halfw = w / 2; PerformLayout( 12, topy, w - 24, h - 100 ); if ( m_pCancelButton ) { m_pOKButton->SetBounds( halfw - 84, h - 30, 72, 24 ); m_pCancelButton->SetBounds( halfw + 12, h - 30, 72, 24 ); } else { m_pOKButton->SetBounds( halfw - 36, h - 30, 72, 24 ); } } //----------------------------------------------------------------------------- // Purpose: handles button commands //----------------------------------------------------------------------------- void BaseInputDialog::OnCommand(const char *command) { KeyValues *kv = NULL; if ( !stricmp( command, "OK" ) ) { kv = new KeyValues( "InputCompleted" ); WriteDataToKeyValues( kv, true ); } else if ( !stricmp( command, "Cancel" ) ) { kv = new KeyValues( "InputCanceled" ); WriteDataToKeyValues( kv, false ); } else { BaseClass::OnCommand( command ); return; } if ( m_pContextKeyValues ) { kv->AddSubKey( m_pContextKeyValues ); m_pContextKeyValues = NULL; } PostActionSignal( kv ); CloseModal(); } //----------------------------------------------------------------------------- // Purpose: Utility dialog, used to ask yes/no questions of the user //----------------------------------------------------------------------------- InputMessageBox::InputMessageBox( Panel *parent, const char *title, char const *prompt ) : BaseClass( parent, title ) { SetSize( 320, 120 ); m_pPrompt = new Label( this, "Prompt", prompt ); } InputMessageBox::~InputMessageBox() { } void InputMessageBox::PerformLayout( int x, int y, int w, int h ) { m_pPrompt->SetBounds( x, y, w, 24 ); } //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- InputDialog::InputDialog( Panel *parent, const char *title, char const *prompt, char const *defaultValue /*=""*/ ) : BaseClass(parent, title) { SetSize( 320, 120 ); m_pPrompt = new Label( this, "Prompt", prompt ); m_pInput = new TextEntry( this, "Text" ); m_pInput->SetText( defaultValue ); m_pInput->SelectAllText( true ); m_pInput->RequestFocus(); } InputDialog::~InputDialog() { } //----------------------------------------------------------------------------- // Sets the dialog to be multiline //----------------------------------------------------------------------------- void InputDialog::SetMultiline( bool state ) { m_pInput->SetMultiline( state ); m_pInput->SetCatchEnterKey( state ); } //----------------------------------------------------------------------------- // Allow numeric input only //----------------------------------------------------------------------------- void InputDialog::AllowNumericInputOnly( bool bOnlyNumeric ) { if ( m_pInput ) { m_pInput->SetAllowNumericInputOnly( bOnlyNumeric ); } } //----------------------------------------------------------------------------- // Purpose: lays out controls //----------------------------------------------------------------------------- void InputDialog::PerformLayout( int x, int y, int w, int h ) { m_pPrompt->SetBounds( x, y, w, 24 ); m_pInput ->SetBounds( x, y + 30, w, m_pInput->IsMultiline() ? h - 30 : 24 ); } //----------------------------------------------------------------------------- // Purpose: handles button commands //----------------------------------------------------------------------------- void InputDialog::WriteDataToKeyValues( KeyValues *pKV, bool bOk ) { if ( !bOk ) return; // don't write any data on cancel int nTextLength = m_pInput->GetTextLength() + 1; char* txt = (char*)stackalloc( nTextLength * sizeof(char) ); m_pInput->GetText( txt, nTextLength ); pKV->SetString( "text", txt ); } //----------------------------------------------------------------------------- // Purpose: Utility dialog, used to let user specify multiple bool/float/string values //----------------------------------------------------------------------------- MultiInputDialog::MultiInputDialog( Panel *pParent, const char *pTitle, const char *pOKText /*= "#VGui_OK"*/, const char *pCancelText /*= "#VGui_Cancel"*/ ) : BaseClass( pParent, NULL ), m_pOKCommand( NULL ), m_pCancelCommand( NULL ), m_nCurrentTabPosition( 0 ) { SetDeleteSelfOnClose( true ); SetTitle( pTitle, true ); m_pOKButton = new Button( this, "OKButton", pOKText ); m_pOKButton->SetCommand( "OK" ); m_pOKButton->SetAsDefaultButton( true ); if ( pCancelText && *pCancelText ) { m_pCancelButton = new Button( this, "CancelButton", pCancelText ); m_pCancelButton->SetCommand( "Cancel" ); } else { m_pCancelButton = NULL; } if ( pParent ) { AddActionSignalTarget( pParent ); } } MultiInputDialog::~MultiInputDialog() { SetOKCommand( NULL ); SetCancelCommand( NULL ); } void MultiInputDialog::SetOKCommand( KeyValues *pOKCommand ) { if ( m_pOKCommand ) { m_pOKCommand->deleteThis(); } m_pOKCommand = pOKCommand; } void MultiInputDialog::SetCancelCommand( KeyValues *pCancelCommand ) { if ( m_pCancelCommand ) { m_pCancelCommand->deleteThis(); } m_pCancelCommand = pCancelCommand; } void MultiInputDialog::AddText( const char *pText ) { AddLabel( pText ); m_inputs.AddToTail( NULL ); m_entryTypes.AddToTail( T_NONE ); } void MultiInputDialog::AddEntry( const char *pName, const char *pPrompt, bool bDefaultValue ) { m_prompts.AddToTail( NULL ); CheckButton *pCheckButton = new CheckButton( this, pName, pPrompt ); pCheckButton->SetSelected( bDefaultValue ); pCheckButton->SetTabPosition( m_nCurrentTabPosition++ ); if ( m_nCurrentTabPosition == 1 ) // first entry { pCheckButton->RequestFocus(); } m_inputs.AddToTail( pCheckButton ); m_entryTypes.AddToTail( T_BOOL ); } void MultiInputDialog::AddEntry( const char *pName, const char *pPrompt, float flDefaultValue ) { AddLabel( pPrompt ); TextEntry *pInput = AddTextEntry( pName, CFmtStr( "%f", flDefaultValue ) ); pInput->SetAllowNumericInputOnly( true ); m_entryTypes.AddToTail( T_FLOAT ); } void MultiInputDialog::AddEntry( const char *pName, const char *pPrompt, const char *pDefaultValue ) { AddLabel( pPrompt ); AddTextEntry( pName, pDefaultValue ); m_entryTypes.AddToTail( T_STRING ); } Label *MultiInputDialog::AddLabel( const char *pText ) { int index = m_prompts.Count(); Label *pLabel = new Label( this, CFmtStr( "label%d", index ), pText ); m_prompts.AddToTail( pLabel ); return pLabel; } TextEntry *MultiInputDialog::AddTextEntry( const char *pName, const char *pDefaultValue ) { TextEntry *pInput = new TextEntry( this, pName ); pInput->SetText( pDefaultValue ); pInput->SetTabPosition( m_nCurrentTabPosition++ ); if ( m_nCurrentTabPosition == 1 ) // first entry { pInput->RequestFocus(); } m_inputs.AddToTail( pInput ); return pInput; } void MultiInputDialog::DoModal() { int nCount = m_prompts.Count(); int nEntryHeight = 24 * nCount; int nDesiredHeight = nEntryHeight + 100; int nDesiredWidth = GetContentWidth(); nDesiredWidth = MAX( nDesiredWidth, 320 ); SetSize( nDesiredWidth, nDesiredHeight ); BaseClass::DoModal(); } void MultiInputDialog::PerformLayout() { BaseClass::PerformLayout(); int w, h; GetSize( w, h ); // lay out all the controls int topy = IsSmallCaption() ? 15 : 30; int halfw = w / 2; PerformLayout( 12, topy, w - 24, h - 100 ); int nOkayWidth, nOkayHeight; m_pOKButton->GetContentSize( nOkayWidth, nOkayHeight ); nOkayWidth += 10; if ( m_pCancelButton ) { int nCancelWidth, nCancelHeight; m_pCancelButton->GetContentSize( nCancelWidth, nCancelHeight ); nCancelWidth += 10; int nButtonWidths = nOkayWidth + 24 + nCancelWidth; m_pOKButton->SetBounds( halfw - nButtonWidths/2, h - 30, nOkayWidth, 24 ); m_pCancelButton->SetBounds( halfw + nButtonWidths/2 - nCancelWidth, h - 30, nCancelWidth, 24 ); } else { m_pOKButton->SetBounds( halfw - nOkayWidth/2, h - 30, nOkayWidth, 24 ); } } void MultiInputDialog::PerformLayout( int x, int y, int w, int h ) { y += 10; int nLabelWidth = GetLabelWidth() + 10; int nCount = m_prompts.Count(); for ( int i = 0; i < nCount; ++i ) { if ( m_prompts[ i ] ) { if ( m_inputs[ i ] ) { m_prompts[ i ]->SetBounds( x, y, nLabelWidth, 24 ); m_inputs [ i ]->SetBounds( x + nLabelWidth, y, w - nLabelWidth, 24 ); } else { m_prompts[ i ]->SetBounds( x, y, w, 24 ); } } else { m_inputs[ i ]->SetBounds( x, y, w, 24 ); } y += 24; } } int MultiInputDialog::GetLabelWidth() { int nLabelWidth = 50; int nCount = m_prompts.Count(); for ( int i = 0; i < nCount; ++i ) { if ( !m_inputs[ i ] || !m_prompts[ i ] ) continue; // skip text and bools int w, h; m_prompts[ i ]->GetContentSize( w, h ); nLabelWidth = MAX( w, nLabelWidth ); } return nLabelWidth; } int MultiInputDialog::GetContentWidth() { int nContentWidth = 100; int nCount = m_prompts.Count(); for ( int i = 0; i < nCount; ++i ) { int h, nEntryWidth = 0; Panel *pInput = m_inputs[ i ]; if ( !pInput ) continue; if ( Label *pPrompt = m_prompts[ i ] ) { pPrompt->GetContentSize( nEntryWidth, h ); nEntryWidth += 100; // allow room for input } else if ( CheckButton *pCheckButton = dynamic_cast< CheckButton* >( pInput ) ) { pCheckButton->GetContentSize( nEntryWidth, h ); nEntryWidth += 20; // allow room for box } nContentWidth = MAX( nContentWidth, nEntryWidth ); } return nContentWidth; } void MultiInputDialog::WriteDataToKeyValues( KeyValues *pKV ) { int nCount = m_prompts.Count(); for ( int i = 0; i < nCount; ++i ) { Panel *pInput = m_inputs[ i ]; if ( !pInput ) continue; // T_NONE if ( m_entryTypes[ i ] == T_BOOL ) { CheckButton *pCheckButton = dynamic_cast< CheckButton* >( pInput ); pKV->SetBool( pCheckButton->GetName(), pCheckButton->IsSelected() ); } else { TextEntry *pTextEntry = dynamic_cast< TextEntry* >( pInput ); if ( m_entryTypes[ i ] == T_FLOAT ) { pKV->SetFloat( pTextEntry->GetName(), pTextEntry->GetValueAsFloat() ); } else { char text[ 256 ]; pTextEntry->GetText( text, sizeof( text ) ); pKV->SetString( pTextEntry->GetName(), text ); } } } } void MultiInputDialog::OnCommand( const char *pCommand ) { if ( !V_stricmp( pCommand, "OK" ) ) { KeyValues *pOKCommand = m_pOKCommand ? m_pOKCommand->MakeCopy() : new KeyValues( "InputCompleted" ); WriteDataToKeyValues( pOKCommand ); PostActionSignal( pOKCommand ); } else if ( !V_stricmp( pCommand, "Cancel" ) ) { KeyValues *pCancelCommand = m_pCancelCommand ? m_pCancelCommand->MakeCopy() : new KeyValues( "InputCanceled" ); PostActionSignal( pCancelCommand ); } else { BaseClass::OnCommand( pCommand ); return; } CloseModal(); }