Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

361 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "vgui_controls/MessageDialog.h"
  7. #include "vgui/ILocalize.h"
  8. #include "vgui/ISurface.h"
  9. // NOTE: This has to be the last file included!
  10. #include "tier0/memdbgon.h"
  11. //-----------------------------------------------------------------------------
  12. // CMessageDialog
  13. //-----------------------------------------------------------------------------
  14. 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 )
  15. : BaseClass( pParent, "MessageDialog" )
  16. {
  17. SetSize( 500, 200 );
  18. SetDeleteSelfOnClose( true );
  19. SetTitleBarVisible( false );
  20. SetCloseButtonVisible( false );
  21. SetSizeable( false );
  22. m_pControlSettings = NULL;
  23. m_pCreator = pCreator ? pCreator : pParent;
  24. m_nType = nType;
  25. m_pTitle = new vgui::Label( this, "TitleLabel", pTitle );
  26. m_pMsg = new vgui::Label( this, "MessageLabel", pMsg );
  27. m_pAnimatingPanel = new vgui::AnimatingImagePanel( this, "AnimatingPanel" );
  28. m_bShowActivity = bShowActivity;
  29. if ( nType & MD_SIMPLEFRAME )
  30. {
  31. SetPaintBackgroundEnabled( true );
  32. m_pBackground = NULL;
  33. }
  34. else
  35. {
  36. m_pBackground = new vgui::ImagePanel( this, "Background" );
  37. if ( nType & MD_WARNING )
  38. {
  39. m_pBackground->SetName( "WarningBackground" );
  40. }
  41. else if ( nType & MD_ERROR )
  42. {
  43. m_pBackground->SetName( "ErrorBackground" );
  44. }
  45. }
  46. Q_memset( m_pCommands, 0, sizeof( m_pCommands ) );
  47. Q_memset( m_Buttons, 0, sizeof( m_Buttons ) );
  48. if ( pCmdA )
  49. {
  50. const int len = Q_strlen( pCmdA ) + 1;
  51. m_pCommands[BTN_A] = (char*)malloc( len );
  52. Q_strncpy( m_pCommands[BTN_A], pCmdA, len );
  53. }
  54. if ( pCmdB )
  55. {
  56. const int len = Q_strlen( pCmdB ) + 1;
  57. m_pCommands[BTN_B] = (char*)malloc( len );
  58. Q_strncpy( m_pCommands[BTN_B], pCmdB, len );
  59. }
  60. // invalid until pressed
  61. m_ButtonPressed = BTN_INVALID;
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Purpose: Destructor
  65. //-----------------------------------------------------------------------------
  66. CMessageDialog::~CMessageDialog()
  67. {
  68. if ( m_ButtonPressed != BTN_INVALID && ( m_nType & MD_COMMANDAFTERCLOSE ) )
  69. {
  70. // caller wants the command sent after closure
  71. m_pCreator->OnCommand( m_pCommands[m_ButtonPressed] );
  72. }
  73. else if ( m_nType & MD_COMMANDONFORCECLOSE )
  74. {
  75. // caller wants the command sent after closure
  76. m_pCreator->OnCommand( m_pCommands[BTN_A] );
  77. }
  78. for ( int i = 0; i < MAX_BUTTONS; ++i )
  79. {
  80. free( m_pCommands[i] );
  81. m_pCommands[i] = NULL;
  82. delete m_Buttons[i].pIcon;
  83. delete m_Buttons[i].pText;
  84. }
  85. delete m_pTitle;
  86. m_pTitle = NULL;
  87. delete m_pMsg;
  88. m_pMsg = NULL;
  89. delete m_pBackground;
  90. m_pBackground = NULL;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Purpose: Set the keyvalues to pass to LoadControlSettings()
  94. //-----------------------------------------------------------------------------
  95. void CMessageDialog::SetControlSettingsKeys( KeyValues *pKeys )
  96. {
  97. m_pControlSettings = pKeys;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Purpose: Create a new button
  101. //-----------------------------------------------------------------------------
  102. void CMessageDialog::CreateButtonLabel( ButtonLabel_s *pButton, const char *pIcon, const char *pText )
  103. {
  104. pButton->nWide = m_ButtonIconLabelSpace;
  105. pButton->bCreated = true;
  106. pButton->pIcon = new vgui::Label( this, "icon", pIcon );
  107. SETUP_PANEL( pButton->pIcon );
  108. pButton->pIcon->SetFont( m_hButtonFont );
  109. pButton->pIcon->SizeToContents();
  110. pButton->nWide += pButton->pIcon->GetWide();
  111. pButton->pText = new vgui::Label( this, "text", pText );
  112. SETUP_PANEL( pButton->pText );
  113. pButton->pText->SetFont( m_hTextFont );
  114. pButton->pText->SizeToContents();
  115. pButton->pText->SetFgColor( m_ButtonTextColor );
  116. pButton->nWide += pButton->pText->GetWide();
  117. }
  118. //-----------------------------------------------------------------------------
  119. // Purpose: Create and arrange the panel button labels according to the dialog type
  120. //-----------------------------------------------------------------------------
  121. void CMessageDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
  122. {
  123. BaseClass::ApplySchemeSettings( pScheme );
  124. LoadControlSettings( "resource/UI/MessageDialog.res", "GAME", m_pControlSettings );
  125. m_hButtonFont = pScheme->GetFont( "GameUIButtons" );
  126. m_hTextFont = pScheme->GetFont( "MenuLarge" );
  127. if ( m_nType & MD_OK )
  128. {
  129. CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_OK" );
  130. }
  131. else if ( m_nType & MD_CANCEL )
  132. {
  133. CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_Cancel" );
  134. }
  135. else if ( m_nType & MD_OKCANCEL )
  136. {
  137. CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_OK" );
  138. CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_Cancel" );
  139. }
  140. else if ( m_nType & MD_YESNO )
  141. {
  142. CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_Yes" );
  143. CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_No" );
  144. }
  145. // count the buttons and add up their widths
  146. int cButtons = 0;
  147. int nTotalWide = 0;
  148. for ( int i = 0; i < MAX_BUTTONS; ++i )
  149. {
  150. if ( m_Buttons[i].bCreated )
  151. {
  152. ++cButtons;
  153. nTotalWide += m_Buttons[i].nWide;
  154. }
  155. }
  156. // make sure text and icons are center-aligned vertically with each other
  157. int nButtonTall = vgui::surface()->GetFontTall( m_hButtonFont );
  158. int nTextTall = vgui::surface()->GetFontTall( m_hTextFont );
  159. int nVerticalAdjust = ( nButtonTall - nTextTall ) / 2;
  160. // position the buttons with even horizontal spacing
  161. int xpos = 0;
  162. int ypos = GetTall() - max( nButtonTall, nTextTall ) - m_ButtonMargin;
  163. int nSpacing = ( GetWide() - nTotalWide ) / ( cButtons + 1 );
  164. for ( int i = 0; i < MAX_BUTTONS; ++i )
  165. {
  166. if ( m_Buttons[i].bCreated )
  167. {
  168. xpos += nSpacing;
  169. m_Buttons[i].pIcon->SetPos( xpos, ypos );
  170. xpos += m_Buttons[i].pIcon->GetWide() + m_ButtonIconLabelSpace;
  171. m_Buttons[i].pText->SetPos( xpos, ypos + nVerticalAdjust );
  172. xpos += m_Buttons[i].pText->GetWide();
  173. }
  174. }
  175. m_clrNotSimpleBG = pScheme->GetColor( "MessageDialog.MatchmakingBG", Color( 200, 184, 151, 255 ) );
  176. m_clrNotSimpleBGBlack = pScheme->GetColor( "MessageDialog.MatchmakingBGBlack", Color( 52, 48, 55, 255 ) );
  177. if ( !m_bShowActivity )
  178. {
  179. if ( m_pAnimatingPanel )
  180. {
  181. if ( m_pAnimatingPanel->IsVisible() )
  182. {
  183. m_pAnimatingPanel->SetVisible( false );
  184. }
  185. m_pAnimatingPanel->StopAnimation();
  186. }
  187. }
  188. else
  189. {
  190. if ( m_pAnimatingPanel )
  191. {
  192. if ( !m_pAnimatingPanel->IsVisible() )
  193. {
  194. m_pAnimatingPanel->SetVisible( true );
  195. }
  196. m_pAnimatingPanel->StartAnimation();
  197. }
  198. }
  199. MoveToCenterOfScreen();
  200. if ( m_bShowActivity && m_ActivityIndent )
  201. {
  202. // If we're animating, we push our text label in, and reduce its width
  203. int iX,iY,iW,iH;
  204. m_pMsg->GetBounds( iX, iY, iW, iH );
  205. m_pMsg->SetBounds( iX + m_ActivityIndent, iY, max(0,iW-m_ActivityIndent), iH );
  206. }
  207. // Invalidate the scheme on our message label so that it recalculates
  208. // its line breaks in case it was resized when we loaded our .res file.
  209. m_pMsg->InvalidateLayout( false, true );
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Purpose: Create and arrange the panel button labels according to the dialog type
  213. //-----------------------------------------------------------------------------
  214. void CMessageDialog::ApplySettings( KeyValues *inResourceData )
  215. {
  216. BaseClass::ApplySettings( inResourceData );
  217. m_pTitle->SetFgColor( inResourceData->GetColor( "titlecolor" ) );
  218. m_pMsg->SetFgColor( inResourceData->GetColor( "messagecolor" ) );
  219. m_ButtonTextColor = inResourceData->GetColor( "buttontextcolor" );
  220. m_FooterTall = inResourceData->GetInt( "footer_tall", 0 );
  221. m_ButtonMargin = inResourceData->GetInt( "button_margin", 25 );
  222. m_ButtonIconLabelSpace = inResourceData->GetInt( "button_separator", 10 );
  223. m_ActivityIndent = inResourceData->GetInt( "activity_indent", 0 );
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Purpose:
  227. //-----------------------------------------------------------------------------
  228. uint CMessageDialog::GetType( void )
  229. {
  230. return m_nType;
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Purpose:
  234. //-----------------------------------------------------------------------------
  235. void CMessageDialog::DoCommand( int button )
  236. {
  237. if ( button == BTN_INVALID || ( m_nType & MD_COMMANDONFORCECLOSE ) )
  238. {
  239. return;
  240. }
  241. if ( m_pCommands[button] )
  242. {
  243. m_ButtonPressed = button;
  244. if ( !( m_nType & MD_COMMANDAFTERCLOSE ) )
  245. {
  246. // caller wants the command sent before closure
  247. m_pCreator->OnCommand( m_pCommands[m_ButtonPressed] );
  248. }
  249. m_pCreator->OnCommand( "ReleaseModalWindow" );
  250. Close();
  251. }
  252. }
  253. //-----------------------------------------------------------------------------
  254. // Purpose:
  255. //-----------------------------------------------------------------------------
  256. void CMessageDialog::OnKeyCodePressed( vgui::KeyCode code )
  257. {
  258. if ( m_ButtonPressed != BTN_INVALID || GetAlpha() != 255 )
  259. {
  260. // inhibit any further key activity or during transitions
  261. return;
  262. }
  263. switch ( GetBaseButtonCode( code ) )
  264. {
  265. case KEY_XBUTTON_A:
  266. case STEAMCONTROLLER_A:
  267. DoCommand( BTN_A );
  268. break;
  269. case KEY_XBUTTON_B:
  270. case STEAMCONTROLLER_B:
  271. DoCommand( BTN_B );
  272. break;
  273. default:
  274. break;
  275. }
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Purpose:
  279. //-----------------------------------------------------------------------------
  280. void CMessageDialog::PaintBackground( void )
  281. {
  282. int wide, tall;
  283. GetSize( wide, tall );
  284. if ( !( m_nType & MD_SIMPLEFRAME ) )
  285. {
  286. int nAlpha = GetAlpha();
  287. m_clrNotSimpleBG[3] = nAlpha;
  288. m_clrNotSimpleBGBlack[3] = nAlpha;
  289. DrawBox( 0, 0, wide, tall, m_clrNotSimpleBGBlack, 1.0f );
  290. DrawBox( 0, 0, wide, tall - m_FooterTall, m_clrNotSimpleBG, 1.0f );
  291. return;
  292. }
  293. Color col = GetBgColor();
  294. DrawBox( 0, 0, wide, tall, col, 1.0f );
  295. // offset the inset by title
  296. int titleX, titleY, titleWide, titleTall;
  297. m_pTitle->GetBounds( titleX, titleY, titleWide, titleTall );
  298. int y = titleY + titleTall;
  299. // draw an inset
  300. Color darkColor;
  301. darkColor.SetColor( 0.70f * (float)col.r(), 0.70f * (float)col.g(), 0.70f * (float)col.b(), col.a() );
  302. vgui::surface()->DrawSetColor( darkColor );
  303. vgui::surface()->DrawFilledRect( 8, y, wide - 8, tall - 8 );
  304. }