source-engine/vgui2/vgui_controls/MessageDialog.cpp

362 lines
10 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "vgui_controls/MessageDialog.h"
#include "vgui/ILocalize.h"
#include "vgui/ISurface.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// CMessageDialog
//-----------------------------------------------------------------------------
CMessageDialog::CMessageDialog( vgui::Panel *pParent, const uint nType, const char *pTitle, const char *pMsg, const char *pCmdA, const char *pCmdB, vgui::Panel *pCreator, bool bShowActivity )
: BaseClass( pParent, "MessageDialog" )
{
SetSize( 500, 200 );
SetDeleteSelfOnClose( true );
SetTitleBarVisible( false );
SetCloseButtonVisible( false );
SetSizeable( false );
m_pControlSettings = NULL;
m_pCreator = pCreator ? pCreator : pParent;
m_nType = nType;
m_pTitle = new vgui::Label( this, "TitleLabel", pTitle );
m_pMsg = new vgui::Label( this, "MessageLabel", pMsg );
m_pAnimatingPanel = new vgui::AnimatingImagePanel( this, "AnimatingPanel" );
m_bShowActivity = bShowActivity;
if ( nType & MD_SIMPLEFRAME )
{
SetPaintBackgroundEnabled( true );
m_pBackground = NULL;
}
else
{
m_pBackground = new vgui::ImagePanel( this, "Background" );
if ( nType & MD_WARNING )
{
m_pBackground->SetName( "WarningBackground" );
}
else if ( nType & MD_ERROR )
{
m_pBackground->SetName( "ErrorBackground" );
}
}
Q_memset( m_pCommands, 0, sizeof( m_pCommands ) );
Q_memset( m_Buttons, 0, sizeof( m_Buttons ) );
if ( pCmdA )
{
const int len = Q_strlen( pCmdA ) + 1;
m_pCommands[BTN_A] = (char*)malloc( len );
Q_strncpy( m_pCommands[BTN_A], pCmdA, len );
}
if ( pCmdB )
{
const int len = Q_strlen( pCmdB ) + 1;
m_pCommands[BTN_B] = (char*)malloc( len );
Q_strncpy( m_pCommands[BTN_B], pCmdB, len );
}
// invalid until pressed
m_ButtonPressed = BTN_INVALID;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CMessageDialog::~CMessageDialog()
{
if ( m_ButtonPressed != BTN_INVALID && ( m_nType & MD_COMMANDAFTERCLOSE ) )
{
// caller wants the command sent after closure
m_pCreator->OnCommand( m_pCommands[m_ButtonPressed] );
}
else if ( m_nType & MD_COMMANDONFORCECLOSE )
{
// caller wants the command sent after closure
m_pCreator->OnCommand( m_pCommands[BTN_A] );
}
for ( int i = 0; i < MAX_BUTTONS; ++i )
{
free( m_pCommands[i] );
m_pCommands[i] = NULL;
delete m_Buttons[i].pIcon;
delete m_Buttons[i].pText;
}
delete m_pTitle;
m_pTitle = NULL;
delete m_pMsg;
m_pMsg = NULL;
delete m_pBackground;
m_pBackground = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Set the keyvalues to pass to LoadControlSettings()
//-----------------------------------------------------------------------------
void CMessageDialog::SetControlSettingsKeys( KeyValues *pKeys )
{
m_pControlSettings = pKeys;
}
//-----------------------------------------------------------------------------
// Purpose: Create a new button
//-----------------------------------------------------------------------------
void CMessageDialog::CreateButtonLabel( ButtonLabel_s *pButton, const char *pIcon, const char *pText )
{
pButton->nWide = m_ButtonIconLabelSpace;
pButton->bCreated = true;
pButton->pIcon = new vgui::Label( this, "icon", pIcon );
SETUP_PANEL( pButton->pIcon );
pButton->pIcon->SetFont( m_hButtonFont );
pButton->pIcon->SizeToContents();
pButton->nWide += pButton->pIcon->GetWide();
pButton->pText = new vgui::Label( this, "text", pText );
SETUP_PANEL( pButton->pText );
pButton->pText->SetFont( m_hTextFont );
pButton->pText->SizeToContents();
pButton->pText->SetFgColor( m_ButtonTextColor );
pButton->nWide += pButton->pText->GetWide();
}
//-----------------------------------------------------------------------------
// Purpose: Create and arrange the panel button labels according to the dialog type
//-----------------------------------------------------------------------------
void CMessageDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/UI/MessageDialog.res", "GAME", m_pControlSettings );
m_hButtonFont = pScheme->GetFont( "GameUIButtons" );
m_hTextFont = pScheme->GetFont( "MenuLarge" );
if ( m_nType & MD_OK )
{
CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_OK" );
}
else if ( m_nType & MD_CANCEL )
{
CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_Cancel" );
}
else if ( m_nType & MD_OKCANCEL )
{
CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_OK" );
CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_Cancel" );
}
else if ( m_nType & MD_YESNO )
{
CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_Yes" );
CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_No" );
}
// count the buttons and add up their widths
int cButtons = 0;
int nTotalWide = 0;
for ( int i = 0; i < MAX_BUTTONS; ++i )
{
if ( m_Buttons[i].bCreated )
{
++cButtons;
nTotalWide += m_Buttons[i].nWide;
}
}
// make sure text and icons are center-aligned vertically with each other
int nButtonTall = vgui::surface()->GetFontTall( m_hButtonFont );
int nTextTall = vgui::surface()->GetFontTall( m_hTextFont );
int nVerticalAdjust = ( nButtonTall - nTextTall ) / 2;
// position the buttons with even horizontal spacing
int xpos = 0;
int ypos = GetTall() - max( nButtonTall, nTextTall ) - m_ButtonMargin;
int nSpacing = ( GetWide() - nTotalWide ) / ( cButtons + 1 );
for ( int i = 0; i < MAX_BUTTONS; ++i )
{
if ( m_Buttons[i].bCreated )
{
xpos += nSpacing;
m_Buttons[i].pIcon->SetPos( xpos, ypos );
xpos += m_Buttons[i].pIcon->GetWide() + m_ButtonIconLabelSpace;
m_Buttons[i].pText->SetPos( xpos, ypos + nVerticalAdjust );
xpos += m_Buttons[i].pText->GetWide();
}
}
m_clrNotSimpleBG = pScheme->GetColor( "MessageDialog.MatchmakingBG", Color( 200, 184, 151, 255 ) );
m_clrNotSimpleBGBlack = pScheme->GetColor( "MessageDialog.MatchmakingBGBlack", Color( 52, 48, 55, 255 ) );
if ( !m_bShowActivity )
{
if ( m_pAnimatingPanel )
{
if ( m_pAnimatingPanel->IsVisible() )
{
m_pAnimatingPanel->SetVisible( false );
}
m_pAnimatingPanel->StopAnimation();
}
}
else
{
if ( m_pAnimatingPanel )
{
if ( !m_pAnimatingPanel->IsVisible() )
{
m_pAnimatingPanel->SetVisible( true );
}
m_pAnimatingPanel->StartAnimation();
}
}
MoveToCenterOfScreen();
if ( m_bShowActivity && m_ActivityIndent )
{
// If we're animating, we push our text label in, and reduce its width
int iX,iY,iW,iH;
m_pMsg->GetBounds( iX, iY, iW, iH );
m_pMsg->SetBounds( iX + m_ActivityIndent, iY, max(0,iW-m_ActivityIndent), iH );
}
// Invalidate the scheme on our message label so that it recalculates
// its line breaks in case it was resized when we loaded our .res file.
m_pMsg->InvalidateLayout( false, true );
}
//-----------------------------------------------------------------------------
// Purpose: Create and arrange the panel button labels according to the dialog type
//-----------------------------------------------------------------------------
void CMessageDialog::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
m_pTitle->SetFgColor( inResourceData->GetColor( "titlecolor" ) );
m_pMsg->SetFgColor( inResourceData->GetColor( "messagecolor" ) );
m_ButtonTextColor = inResourceData->GetColor( "buttontextcolor" );
m_FooterTall = inResourceData->GetInt( "footer_tall", 0 );
m_ButtonMargin = inResourceData->GetInt( "button_margin", 25 );
m_ButtonIconLabelSpace = inResourceData->GetInt( "button_separator", 10 );
m_ActivityIndent = inResourceData->GetInt( "activity_indent", 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
uint CMessageDialog::GetType( void )
{
return m_nType;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMessageDialog::DoCommand( int button )
{
if ( button == BTN_INVALID || ( m_nType & MD_COMMANDONFORCECLOSE ) )
{
return;
}
if ( m_pCommands[button] )
{
m_ButtonPressed = button;
if ( !( m_nType & MD_COMMANDAFTERCLOSE ) )
{
// caller wants the command sent before closure
m_pCreator->OnCommand( m_pCommands[m_ButtonPressed] );
}
m_pCreator->OnCommand( "ReleaseModalWindow" );
Close();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMessageDialog::OnKeyCodePressed( vgui::KeyCode code )
{
if ( m_ButtonPressed != BTN_INVALID || GetAlpha() != 255 )
{
// inhibit any further key activity or during transitions
return;
}
switch ( GetBaseButtonCode( code ) )
{
case KEY_XBUTTON_A:
case STEAMCONTROLLER_A:
DoCommand( BTN_A );
break;
case KEY_XBUTTON_B:
case STEAMCONTROLLER_B:
DoCommand( BTN_B );
break;
default:
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMessageDialog::PaintBackground( void )
{
int wide, tall;
GetSize( wide, tall );
if ( !( m_nType & MD_SIMPLEFRAME ) )
{
int nAlpha = GetAlpha();
m_clrNotSimpleBG[3] = nAlpha;
m_clrNotSimpleBGBlack[3] = nAlpha;
DrawBox( 0, 0, wide, tall, m_clrNotSimpleBGBlack, 1.0f );
DrawBox( 0, 0, wide, tall - m_FooterTall, m_clrNotSimpleBG, 1.0f );
return;
}
Color col = GetBgColor();
DrawBox( 0, 0, wide, tall, col, 1.0f );
// offset the inset by title
int titleX, titleY, titleWide, titleTall;
m_pTitle->GetBounds( titleX, titleY, titleWide, titleTall );
int y = titleY + titleTall;
// draw an inset
Color darkColor;
darkColor.SetColor( 0.70f * (float)col.r(), 0.70f * (float)col.g(), 0.70f * (float)col.b(), col.a() );
vgui::surface()->DrawSetColor( darkColor );
vgui::surface()->DrawFilledRect( 8, y, wide - 8, tall - 8 );
}