//========= 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 ); }