515 lines
13 KiB
C++
515 lines
13 KiB
C++
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||
//
|
||
// Purpose:
|
||
//
|
||
//=============================================================================//
|
||
|
||
#include <vgui_controls/InputDialog.h>
|
||
#include <vgui_controls/Label.h>
|
||
#include <vgui_controls/Button.h>
|
||
#include <vgui_controls/CheckButton.h>
|
||
#include <vgui_controls/TextEntry.h>
|
||
#include "tier1/keyvalues.h"
|
||
#include "tier1/fmtstr.h"
|
||
#include "vgui/IInput.h"
|
||
|
||
// memdbgon must be the last include file in a .cpp file!!!
|
||
#include <tier0/memdbgon.h>
|
||
|
||
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();
|
||
}
|