Counter Strike : Global Offensive Source Code
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.

514 lines
13 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include <vgui_controls/InputDialog.h>
  7. #include <vgui_controls/Label.h>
  8. #include <vgui_controls/Button.h>
  9. #include <vgui_controls/CheckButton.h>
  10. #include <vgui_controls/TextEntry.h>
  11. #include "tier1/keyvalues.h"
  12. #include "tier1/fmtstr.h"
  13. #include "vgui/IInput.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include <tier0/memdbgon.h>
  16. using namespace vgui;
  17. //-----------------------------------------------------------------------------
  18. // Purpose: Constructor
  19. //-----------------------------------------------------------------------------
  20. BaseInputDialog::BaseInputDialog( Panel *parent, const char *title, bool bShowCancelButton /*= true*/ ) :
  21. BaseClass( parent, NULL )
  22. {
  23. m_pContextKeyValues = NULL;
  24. SetDeleteSelfOnClose( true );
  25. SetTitle(title, true);
  26. SetSize(320, 180);
  27. SetSizeable( false );
  28. m_pOKButton = new Button( this, "OKButton", "#VGui_OK" );
  29. m_pOKButton->SetCommand( "OK" );
  30. m_pOKButton->SetAsDefaultButton( true );
  31. if ( bShowCancelButton )
  32. {
  33. m_pCancelButton = new Button( this, "CancelButton", "#VGui_Cancel" );
  34. m_pCancelButton->SetCommand( "Cancel" );
  35. }
  36. else
  37. {
  38. m_pCancelButton = NULL;
  39. }
  40. if ( parent )
  41. {
  42. AddActionSignalTarget( parent );
  43. }
  44. }
  45. BaseInputDialog::~BaseInputDialog()
  46. {
  47. CleanUpContextKeyValues();
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Cleans up the keyvalues
  51. //-----------------------------------------------------------------------------
  52. void BaseInputDialog::CleanUpContextKeyValues()
  53. {
  54. if ( m_pContextKeyValues )
  55. {
  56. m_pContextKeyValues->deleteThis();
  57. m_pContextKeyValues = NULL;
  58. }
  59. }
  60. //-----------------------------------------------------------------------------
  61. // Purpose:
  62. //-----------------------------------------------------------------------------
  63. void BaseInputDialog::DoModal( KeyValues *pContextKeyValues )
  64. {
  65. CleanUpContextKeyValues();
  66. m_pContextKeyValues = pContextKeyValues;
  67. BaseClass::DoModal();
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Purpose: lays out controls
  71. //-----------------------------------------------------------------------------
  72. void BaseInputDialog::PerformLayout()
  73. {
  74. BaseClass::PerformLayout();
  75. int w, h;
  76. GetSize( w, h );
  77. // lay out all the controls
  78. int topy = IsSmallCaption() ? 15 : 30;
  79. int halfw = w / 2;
  80. PerformLayout( 12, topy, w - 24, h - 100 );
  81. if ( m_pCancelButton )
  82. {
  83. m_pOKButton->SetBounds( halfw - 84, h - 30, 72, 24 );
  84. m_pCancelButton->SetBounds( halfw + 12, h - 30, 72, 24 );
  85. }
  86. else
  87. {
  88. m_pOKButton->SetBounds( halfw - 36, h - 30, 72, 24 );
  89. }
  90. }
  91. //-----------------------------------------------------------------------------
  92. // Purpose: handles button commands
  93. //-----------------------------------------------------------------------------
  94. void BaseInputDialog::OnCommand(const char *command)
  95. {
  96. KeyValues *kv = NULL;
  97. if ( !stricmp( command, "OK" ) )
  98. {
  99. kv = new KeyValues( "InputCompleted" );
  100. WriteDataToKeyValues( kv, true );
  101. }
  102. else if ( !stricmp( command, "Cancel" ) )
  103. {
  104. kv = new KeyValues( "InputCanceled" );
  105. WriteDataToKeyValues( kv, false );
  106. }
  107. else
  108. {
  109. BaseClass::OnCommand( command );
  110. return;
  111. }
  112. if ( m_pContextKeyValues )
  113. {
  114. kv->AddSubKey( m_pContextKeyValues );
  115. m_pContextKeyValues = NULL;
  116. }
  117. PostActionSignal( kv );
  118. CloseModal();
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose: Utility dialog, used to ask yes/no questions of the user
  122. //-----------------------------------------------------------------------------
  123. InputMessageBox::InputMessageBox( Panel *parent, const char *title, char const *prompt )
  124. : BaseClass( parent, title )
  125. {
  126. SetSize( 320, 120 );
  127. m_pPrompt = new Label( this, "Prompt", prompt );
  128. }
  129. InputMessageBox::~InputMessageBox()
  130. {
  131. }
  132. void InputMessageBox::PerformLayout( int x, int y, int w, int h )
  133. {
  134. m_pPrompt->SetBounds( x, y, w, 24 );
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose: Constructor
  138. //-----------------------------------------------------------------------------
  139. InputDialog::InputDialog( Panel *parent, const char *title, char const *prompt, char const *defaultValue /*=""*/ ) :
  140. BaseClass(parent, title)
  141. {
  142. SetSize( 320, 120 );
  143. m_pPrompt = new Label( this, "Prompt", prompt );
  144. m_pInput = new TextEntry( this, "Text" );
  145. m_pInput->SetText( defaultValue );
  146. m_pInput->SelectAllText( true );
  147. m_pInput->RequestFocus();
  148. }
  149. InputDialog::~InputDialog()
  150. {
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Sets the dialog to be multiline
  154. //-----------------------------------------------------------------------------
  155. void InputDialog::SetMultiline( bool state )
  156. {
  157. m_pInput->SetMultiline( state );
  158. m_pInput->SetCatchEnterKey( state );
  159. }
  160. //-----------------------------------------------------------------------------
  161. // Allow numeric input only
  162. //-----------------------------------------------------------------------------
  163. void InputDialog::AllowNumericInputOnly( bool bOnlyNumeric )
  164. {
  165. if ( m_pInput )
  166. {
  167. m_pInput->SetAllowNumericInputOnly( bOnlyNumeric );
  168. }
  169. }
  170. //-----------------------------------------------------------------------------
  171. // Purpose: lays out controls
  172. //-----------------------------------------------------------------------------
  173. void InputDialog::PerformLayout( int x, int y, int w, int h )
  174. {
  175. m_pPrompt->SetBounds( x, y, w, 24 );
  176. m_pInput ->SetBounds( x, y + 30, w, m_pInput->IsMultiline() ? h - 30 : 24 );
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Purpose: handles button commands
  180. //-----------------------------------------------------------------------------
  181. void InputDialog::WriteDataToKeyValues( KeyValues *pKV, bool bOk )
  182. {
  183. if ( !bOk )
  184. return; // don't write any data on cancel
  185. int nTextLength = m_pInput->GetTextLength() + 1;
  186. char* txt = (char*)stackalloc( nTextLength * sizeof(char) );
  187. m_pInput->GetText( txt, nTextLength );
  188. pKV->SetString( "text", txt );
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose: Utility dialog, used to let user specify multiple bool/float/string values
  192. //-----------------------------------------------------------------------------
  193. MultiInputDialog::MultiInputDialog( Panel *pParent, const char *pTitle, const char *pOKText /*= "#VGui_OK"*/, const char *pCancelText /*= "#VGui_Cancel"*/ )
  194. : BaseClass( pParent, NULL ), m_pOKCommand( NULL ), m_pCancelCommand( NULL ), m_nCurrentTabPosition( 0 )
  195. {
  196. SetDeleteSelfOnClose( true );
  197. SetTitle( pTitle, true );
  198. m_pOKButton = new Button( this, "OKButton", pOKText );
  199. m_pOKButton->SetCommand( "OK" );
  200. m_pOKButton->SetAsDefaultButton( true );
  201. if ( pCancelText && *pCancelText )
  202. {
  203. m_pCancelButton = new Button( this, "CancelButton", pCancelText );
  204. m_pCancelButton->SetCommand( "Cancel" );
  205. }
  206. else
  207. {
  208. m_pCancelButton = NULL;
  209. }
  210. if ( pParent )
  211. {
  212. AddActionSignalTarget( pParent );
  213. }
  214. }
  215. MultiInputDialog::~MultiInputDialog()
  216. {
  217. SetOKCommand( NULL );
  218. SetCancelCommand( NULL );
  219. }
  220. void MultiInputDialog::SetOKCommand( KeyValues *pOKCommand )
  221. {
  222. if ( m_pOKCommand )
  223. {
  224. m_pOKCommand->deleteThis();
  225. }
  226. m_pOKCommand = pOKCommand;
  227. }
  228. void MultiInputDialog::SetCancelCommand( KeyValues *pCancelCommand )
  229. {
  230. if ( m_pCancelCommand )
  231. {
  232. m_pCancelCommand->deleteThis();
  233. }
  234. m_pCancelCommand = pCancelCommand;
  235. }
  236. void MultiInputDialog::AddText( const char *pText )
  237. {
  238. AddLabel( pText );
  239. m_inputs.AddToTail( NULL );
  240. m_entryTypes.AddToTail( T_NONE );
  241. }
  242. void MultiInputDialog::AddEntry( const char *pName, const char *pPrompt, bool bDefaultValue )
  243. {
  244. m_prompts.AddToTail( NULL );
  245. CheckButton *pCheckButton = new CheckButton( this, pName, pPrompt );
  246. pCheckButton->SetSelected( bDefaultValue );
  247. pCheckButton->SetTabPosition( m_nCurrentTabPosition++ );
  248. if ( m_nCurrentTabPosition == 1 ) // first entry
  249. {
  250. pCheckButton->RequestFocus();
  251. }
  252. m_inputs.AddToTail( pCheckButton );
  253. m_entryTypes.AddToTail( T_BOOL );
  254. }
  255. void MultiInputDialog::AddEntry( const char *pName, const char *pPrompt, float flDefaultValue )
  256. {
  257. AddLabel( pPrompt );
  258. TextEntry *pInput = AddTextEntry( pName, CFmtStr( "%f", flDefaultValue ) );
  259. pInput->SetAllowNumericInputOnly( true );
  260. m_entryTypes.AddToTail( T_FLOAT );
  261. }
  262. void MultiInputDialog::AddEntry( const char *pName, const char *pPrompt, const char *pDefaultValue )
  263. {
  264. AddLabel( pPrompt );
  265. AddTextEntry( pName, pDefaultValue );
  266. m_entryTypes.AddToTail( T_STRING );
  267. }
  268. Label *MultiInputDialog::AddLabel( const char *pText )
  269. {
  270. int index = m_prompts.Count();
  271. Label *pLabel = new Label( this, CFmtStr( "label%d", index ), pText );
  272. m_prompts.AddToTail( pLabel );
  273. return pLabel;
  274. }
  275. TextEntry *MultiInputDialog::AddTextEntry( const char *pName, const char *pDefaultValue )
  276. {
  277. TextEntry *pInput = new TextEntry( this, pName );
  278. pInput->SetText( pDefaultValue );
  279. pInput->SetTabPosition( m_nCurrentTabPosition++ );
  280. if ( m_nCurrentTabPosition == 1 ) // first entry
  281. {
  282. pInput->RequestFocus();
  283. }
  284. m_inputs.AddToTail( pInput );
  285. return pInput;
  286. }
  287. void MultiInputDialog::DoModal()
  288. {
  289. int nCount = m_prompts.Count();
  290. int nEntryHeight = 24 * nCount;
  291. int nDesiredHeight = nEntryHeight + 100;
  292. int nDesiredWidth = GetContentWidth();
  293. nDesiredWidth = MAX( nDesiredWidth, 320 );
  294. SetSize( nDesiredWidth, nDesiredHeight );
  295. BaseClass::DoModal();
  296. }
  297. void MultiInputDialog::PerformLayout()
  298. {
  299. BaseClass::PerformLayout();
  300. int w, h;
  301. GetSize( w, h );
  302. // lay out all the controls
  303. int topy = IsSmallCaption() ? 15 : 30;
  304. int halfw = w / 2;
  305. PerformLayout( 12, topy, w - 24, h - 100 );
  306. int nOkayWidth, nOkayHeight;
  307. m_pOKButton->GetContentSize( nOkayWidth, nOkayHeight );
  308. nOkayWidth += 10;
  309. if ( m_pCancelButton )
  310. {
  311. int nCancelWidth, nCancelHeight;
  312. m_pCancelButton->GetContentSize( nCancelWidth, nCancelHeight );
  313. nCancelWidth += 10;
  314. int nButtonWidths = nOkayWidth + 24 + nCancelWidth;
  315. m_pOKButton->SetBounds( halfw - nButtonWidths/2, h - 30, nOkayWidth, 24 );
  316. m_pCancelButton->SetBounds( halfw + nButtonWidths/2 - nCancelWidth, h - 30, nCancelWidth, 24 );
  317. }
  318. else
  319. {
  320. m_pOKButton->SetBounds( halfw - nOkayWidth/2, h - 30, nOkayWidth, 24 );
  321. }
  322. }
  323. void MultiInputDialog::PerformLayout( int x, int y, int w, int h )
  324. {
  325. y += 10;
  326. int nLabelWidth = GetLabelWidth() + 10;
  327. int nCount = m_prompts.Count();
  328. for ( int i = 0; i < nCount; ++i )
  329. {
  330. if ( m_prompts[ i ] )
  331. {
  332. if ( m_inputs[ i ] )
  333. {
  334. m_prompts[ i ]->SetBounds( x, y, nLabelWidth, 24 );
  335. m_inputs [ i ]->SetBounds( x + nLabelWidth, y, w - nLabelWidth, 24 );
  336. }
  337. else
  338. {
  339. m_prompts[ i ]->SetBounds( x, y, w, 24 );
  340. }
  341. }
  342. else
  343. {
  344. m_inputs[ i ]->SetBounds( x, y, w, 24 );
  345. }
  346. y += 24;
  347. }
  348. }
  349. int MultiInputDialog::GetLabelWidth()
  350. {
  351. int nLabelWidth = 50;
  352. int nCount = m_prompts.Count();
  353. for ( int i = 0; i < nCount; ++i )
  354. {
  355. if ( !m_inputs[ i ] || !m_prompts[ i ] )
  356. continue; // skip text and bools
  357. int w, h;
  358. m_prompts[ i ]->GetContentSize( w, h );
  359. nLabelWidth = MAX( w, nLabelWidth );
  360. }
  361. return nLabelWidth;
  362. }
  363. int MultiInputDialog::GetContentWidth()
  364. {
  365. int nContentWidth = 100;
  366. int nCount = m_prompts.Count();
  367. for ( int i = 0; i < nCount; ++i )
  368. {
  369. int h, nEntryWidth = 0;
  370. Panel *pInput = m_inputs[ i ];
  371. if ( !pInput )
  372. continue;
  373. if ( Label *pPrompt = m_prompts[ i ] )
  374. {
  375. pPrompt->GetContentSize( nEntryWidth, h );
  376. nEntryWidth += 100; // allow room for input
  377. }
  378. else if ( CheckButton *pCheckButton = dynamic_cast< CheckButton* >( pInput ) )
  379. {
  380. pCheckButton->GetContentSize( nEntryWidth, h );
  381. nEntryWidth += 20; // allow room for box
  382. }
  383. nContentWidth = MAX( nContentWidth, nEntryWidth );
  384. }
  385. return nContentWidth;
  386. }
  387. void MultiInputDialog::WriteDataToKeyValues( KeyValues *pKV )
  388. {
  389. int nCount = m_prompts.Count();
  390. for ( int i = 0; i < nCount; ++i )
  391. {
  392. Panel *pInput = m_inputs[ i ];
  393. if ( !pInput )
  394. continue; // T_NONE
  395. if ( m_entryTypes[ i ] == T_BOOL )
  396. {
  397. CheckButton *pCheckButton = dynamic_cast< CheckButton* >( pInput );
  398. pKV->SetBool( pCheckButton->GetName(), pCheckButton->IsSelected() );
  399. }
  400. else
  401. {
  402. TextEntry *pTextEntry = dynamic_cast< TextEntry* >( pInput );
  403. if ( m_entryTypes[ i ] == T_FLOAT )
  404. {
  405. pKV->SetFloat( pTextEntry->GetName(), pTextEntry->GetValueAsFloat() );
  406. }
  407. else
  408. {
  409. char text[ 256 ];
  410. pTextEntry->GetText( text, sizeof( text ) );
  411. pKV->SetString( pTextEntry->GetName(), text );
  412. }
  413. }
  414. }
  415. }
  416. void MultiInputDialog::OnCommand( const char *pCommand )
  417. {
  418. if ( !V_stricmp( pCommand, "OK" ) )
  419. {
  420. KeyValues *pOKCommand = m_pOKCommand ? m_pOKCommand->MakeCopy() : new KeyValues( "InputCompleted" );
  421. WriteDataToKeyValues( pOKCommand );
  422. PostActionSignal( pOKCommand );
  423. }
  424. else if ( !V_stricmp( pCommand, "Cancel" ) )
  425. {
  426. KeyValues *pCancelCommand = m_pCancelCommand ? m_pCancelCommand->MakeCopy() : new KeyValues( "InputCanceled" );
  427. PostActionSignal( pCancelCommand );
  428. }
  429. else
  430. {
  431. BaseClass::OnCommand( pCommand );
  432. return;
  433. }
  434. CloseModal();
  435. }