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.

839 lines
23 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "OptionsSubKeyboard.h"
  7. #include "EngineInterface.h"
  8. #include "vcontrolslistpanel.h"
  9. #include <vgui_controls/Button.h>
  10. #include <vgui_controls/Label.h>
  11. #include <vgui_controls/ListPanel.h>
  12. #include <vgui_controls/QueryBox.h>
  13. #include <vgui/Cursor.h>
  14. #include <vgui/IVGui.h>
  15. #include <vgui/ISurface.h>
  16. #include "tier1/KeyValues.h"
  17. #include "tier1/convar.h"
  18. #include <vgui/KeyCode.h>
  19. #include <vgui/MouseCode.h>
  20. #include <vgui/ISystem.h>
  21. #include <vgui/IInput.h>
  22. #include "filesystem.h"
  23. #include "tier1/utlbuffer.h"
  24. #include "IGameUIFuncs.h"
  25. #include <vstdlib/IKeyValuesSystem.h>
  26. #include "tier2/tier2.h"
  27. #include "inputsystem/iinputsystem.h"
  28. // memdbgon must be the last include file in a .cpp file!!!
  29. #include "tier0/memdbgon.h"
  30. using namespace vgui;
  31. //-----------------------------------------------------------------------------
  32. // Purpose: Constructor
  33. //-----------------------------------------------------------------------------
  34. COptionsSubKeyboard::COptionsSubKeyboard(vgui::Panel *parent) : PropertyPage(parent, NULL)
  35. {
  36. memset( m_Bindings, 0, sizeof( m_Bindings ));
  37. // create the key bindings list
  38. CreateKeyBindingList();
  39. // Store all current key bindings
  40. SaveCurrentBindings();
  41. // Parse default descriptions
  42. ParseActionDescriptions();
  43. m_pSetBindingButton = new Button(this, "ChangeKeyButton", "");
  44. m_pClearBindingButton = new Button(this, "ClearKeyButton", "");
  45. LoadControlSettings("Resource/OptionsSubKeyboard.res");
  46. m_pSetBindingButton->SetEnabled(false);
  47. m_pClearBindingButton->SetEnabled(false);
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Destructor
  51. //-----------------------------------------------------------------------------
  52. COptionsSubKeyboard::~COptionsSubKeyboard()
  53. {
  54. DeleteSavedBindings();
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Purpose: reloads current keybinding
  58. //-----------------------------------------------------------------------------
  59. void COptionsSubKeyboard::OnResetData()
  60. {
  61. // Populate list based on current settings
  62. FillInCurrentBindings();
  63. if ( IsVisible() )
  64. {
  65. m_pKeyBindList->SetSelectedItem(0);
  66. }
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose: saves out keybinding changes
  70. //-----------------------------------------------------------------------------
  71. void COptionsSubKeyboard::OnApplyChanges()
  72. {
  73. ApplyAllBindings();
  74. }
  75. //-----------------------------------------------------------------------------
  76. // Purpose: Create key bindings list control
  77. //-----------------------------------------------------------------------------
  78. void COptionsSubKeyboard::CreateKeyBindingList()
  79. {
  80. // Create the control
  81. m_pKeyBindList = new VControlsListPanel(this, "listpanel_keybindlist");
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose: binds double-clicking or hitting enter in the keybind list to changing the key
  85. //-----------------------------------------------------------------------------
  86. void COptionsSubKeyboard::OnKeyCodeTyped(vgui::KeyCode code)
  87. {
  88. if (code == KEY_ENTER)
  89. {
  90. OnCommand("ChangeKey");
  91. }
  92. else
  93. {
  94. BaseClass::OnKeyCodeTyped(code);
  95. }
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose: command handler
  99. //-----------------------------------------------------------------------------
  100. void COptionsSubKeyboard::OnCommand( const char *command )
  101. {
  102. if ( !stricmp( command, "Defaults" ) )
  103. {
  104. // open a box asking if we want to restore defaults
  105. QueryBox *box = new QueryBox("#GameUI_KeyboardSettings", "#GameUI_KeyboardSettingsText");
  106. box->AddActionSignalTarget(this);
  107. box->SetOKCommand(new KeyValues("Command", "command", "DefaultsOK"));
  108. box->DoModal();
  109. }
  110. else if ( !stricmp(command, "DefaultsOK"))
  111. {
  112. // Restore defaults from default keybindings file
  113. FillInDefaultBindings();
  114. m_pKeyBindList->RequestFocus();
  115. }
  116. else if ( !m_pKeyBindList->IsCapturing() && !stricmp( command, "ChangeKey" ) )
  117. {
  118. m_pKeyBindList->StartCaptureMode(dc_blank);
  119. }
  120. else if ( !m_pKeyBindList->IsCapturing() && !stricmp( command, "ClearKey" ) )
  121. {
  122. OnKeyCodePressed(KEY_DELETE);
  123. m_pKeyBindList->RequestFocus();
  124. }
  125. else if ( !stricmp(command, "Advanced") )
  126. {
  127. OpenKeyboardAdvancedDialog();
  128. }
  129. else
  130. {
  131. BaseClass::OnCommand( command );
  132. }
  133. }
  134. const char *UTIL_Parse( const char *data, char *token, int sizeofToken )
  135. {
  136. data = engine->ParseFile( data, token, sizeofToken );
  137. return data;
  138. }
  139. static char *UTIL_CopyString( const char *in )
  140. {
  141. int len = strlen( in ) + 1;
  142. char *out = new char[ len ];
  143. Q_strncpy( out, in, len );
  144. return out;
  145. }
  146. #ifndef _XBOX
  147. char *UTIL_va(char *format, ...)
  148. {
  149. va_list argptr;
  150. static char string[4][1024];
  151. static int curstring = 0;
  152. curstring = ( curstring + 1 ) % 4;
  153. va_start (argptr, format);
  154. Q_vsnprintf( string[curstring], 1024, format, argptr );
  155. va_end (argptr);
  156. return string[curstring];
  157. }
  158. #endif
  159. //-----------------------------------------------------------------------------
  160. // Purpose:
  161. //-----------------------------------------------------------------------------
  162. void COptionsSubKeyboard::ParseActionDescriptions( void )
  163. {
  164. char szBinding[256];
  165. char szDescription[256];
  166. KeyValues *item;
  167. // Load the default keys list
  168. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  169. if ( !g_pFullFileSystem->ReadFile( "scripts/kb_act.lst", NULL, buf ) )
  170. return;
  171. const char *data = (const char*)buf.Base();
  172. int sectionIndex = 0;
  173. char token[512];
  174. while ( 1 )
  175. {
  176. data = UTIL_Parse( data, token, sizeof(token) );
  177. // Done.
  178. if ( strlen( token ) <= 0 )
  179. break;
  180. Q_strncpy( szBinding, token, sizeof( szBinding ) );
  181. data = UTIL_Parse( data, token, sizeof(token) );
  182. if ( strlen(token) <= 0 )
  183. {
  184. break;
  185. }
  186. Q_strncpy(szDescription, token, sizeof( szDescription ) );
  187. // Skip '======' rows
  188. if ( szDescription[ 0 ] != '=' )
  189. {
  190. // Flag as special header row if binding is "blank"
  191. if (!stricmp(szBinding, "blank"))
  192. {
  193. // add header item
  194. m_pKeyBindList->AddSection(++sectionIndex, szDescription);
  195. m_pKeyBindList->AddColumnToSection(sectionIndex, "Action", szDescription, SectionedListPanel::COLUMN_BRIGHT, 286);
  196. m_pKeyBindList->AddColumnToSection(sectionIndex, "Key", "#GameUI_KeyButton", SectionedListPanel::COLUMN_BRIGHT, 128);
  197. }
  198. else
  199. {
  200. // Create a new: blank item
  201. item = new KeyValues( "Item" );
  202. // fill in data
  203. item->SetString("Action", szDescription);
  204. item->SetString("Binding", szBinding);
  205. item->SetString("Key", "");
  206. // Add to list
  207. m_pKeyBindList->AddItem(sectionIndex, item);
  208. item->deleteThis();
  209. }
  210. }
  211. }
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Purpose: Search current data set for item which has the specified binding string
  215. // Input : *binding - string to find
  216. // Output : KeyValues or NULL on failure
  217. //-----------------------------------------------------------------------------
  218. KeyValues *COptionsSubKeyboard::GetItemForBinding( const char *binding )
  219. {
  220. static int bindingSymbol = KeyValuesSystem()->GetSymbolForString("Binding");
  221. // Loop through all items
  222. for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
  223. {
  224. KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
  225. if ( !item )
  226. continue;
  227. KeyValues *bindingItem = item->FindKey(bindingSymbol);
  228. const char *bindString = bindingItem->GetString();
  229. // Check the "Binding" key
  230. if (!stricmp(bindString, binding))
  231. return item;
  232. }
  233. // Didn't find it
  234. return NULL;
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Purpose: Bind the specified keyname to the specified item
  238. // Input : *item - Item to which to add the key
  239. // *keyname - The key to be added
  240. //-----------------------------------------------------------------------------
  241. void COptionsSubKeyboard::AddBinding( KeyValues *item, const char *keyname )
  242. {
  243. // See if it's already there as a binding
  244. if ( !stricmp( item->GetString( "Key", "" ), keyname ) )
  245. return;
  246. // Make sure it doesn't live anywhere
  247. RemoveKeyFromBindItems( item, keyname );
  248. const char *binding = item->GetString( "Binding", "" );
  249. // Loop through all the key bindings and set all entries that have
  250. // the same binding. This allows us to have multiple entries pointing
  251. // to the same binding.
  252. for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
  253. {
  254. KeyValues *curitem = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
  255. if ( !curitem )
  256. continue;
  257. const char *curbinding = curitem->GetString( "Binding", "" );
  258. if (!stricmp(curbinding, binding))
  259. {
  260. curitem->SetString( "Key", keyname );
  261. m_pKeyBindList->InvalidateItem(i);
  262. }
  263. }
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Purpose: Remove all keys from list
  267. //-----------------------------------------------------------------------------
  268. void COptionsSubKeyboard::ClearBindItems( void )
  269. {
  270. for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
  271. {
  272. KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
  273. if ( !item )
  274. continue;
  275. // Reset keys
  276. item->SetString( "Key", "" );
  277. m_pKeyBindList->InvalidateItem(i);
  278. }
  279. m_pKeyBindList->InvalidateLayout();
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Purpose: Remove all instances of the specified key from bindings
  283. //-----------------------------------------------------------------------------
  284. void COptionsSubKeyboard::RemoveKeyFromBindItems( KeyValues *org_item, const char *key )
  285. {
  286. Assert( key && key[ 0 ] );
  287. if ( !key || !key[ 0 ] )
  288. return;
  289. int len = Q_strlen( key );
  290. char *pszKey = new char[len + 1];
  291. if ( !pszKey )
  292. return;
  293. Q_memcpy( pszKey, key, len+1 );
  294. for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
  295. {
  296. KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
  297. if ( !item )
  298. continue;
  299. // If it's bound to the primary: then remove it
  300. if ( !stricmp( pszKey, item->GetString( "Key", "" ) ) )
  301. {
  302. bool bClearEntry = true;
  303. if ( org_item )
  304. {
  305. // Only clear it out if the actual binding isn't the same. This allows
  306. // us to have the same key bound to multiple entries in the keybinding list
  307. // if they point to the same command.
  308. const char *org_binding = org_item->GetString( "Binding", "" );
  309. const char *binding = item->GetString( "Binding", "" );
  310. if ( !stricmp( org_binding, binding ) )
  311. {
  312. bClearEntry = false;
  313. }
  314. }
  315. if ( bClearEntry )
  316. {
  317. item->SetString( "Key", "" );
  318. m_pKeyBindList->InvalidateItem(i);
  319. }
  320. }
  321. }
  322. delete [] pszKey;
  323. // Make sure the display is up to date
  324. m_pKeyBindList->InvalidateLayout();
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose: Ask the engine for all bindings and set up the list
  328. //-----------------------------------------------------------------------------
  329. void COptionsSubKeyboard::FillInCurrentBindings( void )
  330. {
  331. // reset the unbind list
  332. // we only unbind keys used by the normal config items (not custom binds)
  333. m_KeysToUnbind.RemoveAll();
  334. // Clear any current settings
  335. ClearBindItems();
  336. bool bJoystick = false;
  337. ConVarRef var( "joystick" );
  338. if ( var.IsValid() )
  339. {
  340. bJoystick = var.GetBool();
  341. }
  342. // NVNT see if we have a falcon connected.
  343. bool bFalcon = false;
  344. ConVarRef falconVar("hap_HasDevice");
  345. if ( var.IsValid() )
  346. {
  347. bFalcon = var.GetBool();
  348. }
  349. for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
  350. {
  351. // Look up binding
  352. const char *binding = gameuifuncs->GetBindingForButtonCode( (ButtonCode_t)i );
  353. if ( !binding )
  354. continue;
  355. // See if there is an item for this one?
  356. KeyValues *item = GetItemForBinding( binding );
  357. if ( item )
  358. {
  359. // Bind it by name
  360. const char *keyName = g_pInputSystem->ButtonCodeToString( (ButtonCode_t)i );
  361. // Already in list, means user had two keys bound to this item. We'll only note the first one we encounter
  362. char const *currentKey = item->GetString( "Key", "" );
  363. if ( currentKey && currentKey[ 0 ] )
  364. {
  365. ButtonCode_t currentBC = (ButtonCode_t)gameuifuncs->GetButtonCodeForBind( currentKey );
  366. // If we're using a joystick, joystick bindings override keyboard ones
  367. bool bShouldOverride = bJoystick && IsJoystickCode((ButtonCode_t)i) && !IsJoystickCode(currentBC);
  368. // NVNT If we're not using a joystick, falcon bindings override keyboard ones
  369. if( !bShouldOverride && bFalcon && IsNovintCode((ButtonCode_t)i) && !IsNovintCode(currentBC) )
  370. bShouldOverride = true;
  371. if ( !bShouldOverride )
  372. continue;
  373. // Remove the key we're about to override from the unbinding list
  374. m_KeysToUnbind.FindAndRemove( currentKey );
  375. }
  376. AddBinding( item, keyName );
  377. // remember to apply unbinding of this key when we apply
  378. m_KeysToUnbind.AddToTail( keyName );
  379. }
  380. }
  381. }
  382. //-----------------------------------------------------------------------------
  383. // Purpose: Clean up memory used by saved bindings
  384. //-----------------------------------------------------------------------------
  385. void COptionsSubKeyboard::DeleteSavedBindings( void )
  386. {
  387. for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
  388. {
  389. if ( m_Bindings[ i ].binding )
  390. {
  391. delete[] m_Bindings[ i ].binding;
  392. m_Bindings[ i ].binding = NULL;
  393. }
  394. }
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Purpose: Copy all bindings into save array
  398. //-----------------------------------------------------------------------------
  399. void COptionsSubKeyboard::SaveCurrentBindings( void )
  400. {
  401. DeleteSavedBindings();
  402. for (int i = 0; i < BUTTON_CODE_LAST; i++)
  403. {
  404. const char *binding = gameuifuncs->GetBindingForButtonCode( (ButtonCode_t)i );
  405. if ( !binding || !binding[0])
  406. continue;
  407. // Copy the binding string
  408. m_Bindings[ i ].binding = UTIL_CopyString( binding );
  409. }
  410. }
  411. //-----------------------------------------------------------------------------
  412. // Purpose: Tells the engine to bind a key
  413. //-----------------------------------------------------------------------------
  414. void COptionsSubKeyboard::BindKey( const char *key, const char *binding )
  415. {
  416. #ifndef _XBOX
  417. engine->ClientCmd_Unrestricted( UTIL_va( "bind \"%s\" \"%s\"\n", key, binding ) );
  418. #else
  419. char buff[256];
  420. Q_snprintf(buff, sizeof(buff), "bind \"%s\" \"%s\"\n", key, binding);
  421. engine->ClientCmd_Unrestricted(buff);
  422. #endif
  423. }
  424. //-----------------------------------------------------------------------------
  425. // Purpose: Tells the engine to unbind a key
  426. //-----------------------------------------------------------------------------
  427. void COptionsSubKeyboard::UnbindKey( const char *key )
  428. {
  429. #ifndef _XBOX
  430. engine->ClientCmd_Unrestricted( UTIL_va( "unbind \"%s\"\n", key ) );
  431. #else
  432. char buff[256];
  433. Q_snprintf(buff, sizeof(buff), "unbind \"%s\"\n", key);
  434. engine->ClientCmd_Unrestricted(buff);
  435. #endif
  436. }
  437. //-----------------------------------------------------------------------------
  438. // Purpose: Go through list and bind specified keys to actions
  439. //-----------------------------------------------------------------------------
  440. void COptionsSubKeyboard::ApplyAllBindings( void )
  441. {
  442. // unbind everything that the user unbound
  443. {for (int i = 0; i < m_KeysToUnbind.Count(); i++)
  444. {
  445. UnbindKey(m_KeysToUnbind[i].String());
  446. }}
  447. m_KeysToUnbind.RemoveAll();
  448. // free binding memory
  449. DeleteSavedBindings();
  450. for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
  451. {
  452. KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
  453. if ( !item )
  454. continue;
  455. // See if it has a binding
  456. const char *binding = item->GetString( "Binding", "" );
  457. if ( !binding || !binding[ 0 ] )
  458. continue;
  459. const char *keyname;
  460. // Check main binding
  461. keyname = item->GetString( "Key", "" );
  462. if ( keyname && keyname[ 0 ] )
  463. {
  464. // Tell the engine
  465. BindKey( keyname, binding );
  466. ButtonCode_t code = g_pInputSystem->StringToButtonCode( keyname );
  467. if ( code != BUTTON_CODE_INVALID )
  468. {
  469. m_Bindings[ code ].binding = UTIL_CopyString( binding );
  470. }
  471. }
  472. }
  473. // Now exec their custom bindings
  474. engine->ClientCmd_Unrestricted( "exec userconfig.cfg\nhost_writeconfig\n" );
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Purpose: Read in defaults from game's default config file and populate list
  478. // using those defaults
  479. //-----------------------------------------------------------------------------
  480. void COptionsSubKeyboard::FillInDefaultBindings( void )
  481. {
  482. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  483. if ( !g_pFullFileSystem->ReadFile( "cfg/config_default.cfg", NULL, buf ) )
  484. return;
  485. // Clear out all current bindings
  486. ClearBindItems();
  487. const char *data = (const char*)buf.Base();
  488. // loop through all the binding
  489. while ( data != NULL )
  490. {
  491. char cmd[64];
  492. data = UTIL_Parse( data, cmd, sizeof(cmd) );
  493. if ( strlen( cmd ) <= 0 )
  494. break;
  495. if ( !stricmp(cmd, "bind") )
  496. {
  497. // Key name
  498. char szKeyName[256];
  499. data = UTIL_Parse( data, szKeyName, sizeof(szKeyName) );
  500. if ( strlen( szKeyName ) <= 0 )
  501. break; // Error
  502. char szBinding[256];
  503. data = UTIL_Parse( data, szBinding, sizeof(szBinding) );
  504. if ( strlen( szKeyName ) <= 0 )
  505. break; // Error
  506. // Find item
  507. KeyValues *item = GetItemForBinding( szBinding );
  508. if ( item )
  509. {
  510. // Bind it
  511. AddBinding( item, szKeyName );
  512. }
  513. }
  514. }
  515. PostActionSignal(new KeyValues("ApplyButtonEnable"));
  516. // Make sure console and escape key are always valid
  517. KeyValues *item = GetItemForBinding( "toggleconsole" );
  518. if (item)
  519. {
  520. // Bind it
  521. AddBinding( item, "`" );
  522. }
  523. item = GetItemForBinding( "cancelselect" );
  524. if (item)
  525. {
  526. // Bind it
  527. AddBinding( item, "ESCAPE" );
  528. }
  529. }
  530. //-----------------------------------------------------------------------------
  531. // Purpose: User clicked on item: remember where last active row/column was
  532. //-----------------------------------------------------------------------------
  533. void COptionsSubKeyboard::ItemSelected(int itemID)
  534. {
  535. m_pKeyBindList->SetItemOfInterest(itemID);
  536. if (m_pKeyBindList->IsItemIDValid(itemID))
  537. {
  538. // find the details, see if we should be enabled/clear/whatever
  539. m_pSetBindingButton->SetEnabled(true);
  540. KeyValues *kv = m_pKeyBindList->GetItemData(itemID);
  541. if (kv)
  542. {
  543. const char *key = kv->GetString("Key", NULL);
  544. if (key && *key)
  545. {
  546. m_pClearBindingButton->SetEnabled(true);
  547. }
  548. else
  549. {
  550. m_pClearBindingButton->SetEnabled(false);
  551. }
  552. if (kv->GetInt("Header"))
  553. {
  554. m_pSetBindingButton->SetEnabled(false);
  555. }
  556. }
  557. }
  558. else
  559. {
  560. m_pSetBindingButton->SetEnabled(false);
  561. m_pClearBindingButton->SetEnabled(false);
  562. }
  563. }
  564. //-----------------------------------------------------------------------------
  565. // Purpose: called when the capture has finished
  566. //-----------------------------------------------------------------------------
  567. void COptionsSubKeyboard::Finish( ButtonCode_t code )
  568. {
  569. int r = m_pKeyBindList->GetItemOfInterest();
  570. // Retrieve clicked row and column
  571. m_pKeyBindList->EndCaptureMode( dc_arrow );
  572. // Find item for this row
  573. KeyValues *item = m_pKeyBindList->GetItemData(r);
  574. if ( item )
  575. {
  576. // Handle keys: but never rebind the escape key
  577. // Esc just exits bind mode silently
  578. if ( code != BUTTON_CODE_NONE && code != KEY_ESCAPE && code != BUTTON_CODE_INVALID )
  579. {
  580. // Bind the named key
  581. AddBinding( item, g_pInputSystem->ButtonCodeToString( code ) );
  582. PostActionSignal( new KeyValues( "ApplyButtonEnable" ) );
  583. }
  584. m_pKeyBindList->InvalidateItem(r);
  585. }
  586. m_pSetBindingButton->SetEnabled(true);
  587. m_pClearBindingButton->SetEnabled(true);
  588. }
  589. //-----------------------------------------------------------------------------
  590. // Purpose: Scans for captured key presses
  591. //-----------------------------------------------------------------------------
  592. void COptionsSubKeyboard::OnThink()
  593. {
  594. BaseClass::OnThink();
  595. if ( m_pKeyBindList->IsCapturing() )
  596. {
  597. ButtonCode_t code = BUTTON_CODE_INVALID;
  598. if ( engine->CheckDoneKeyTrapping( code ) )
  599. {
  600. Finish( code );
  601. }
  602. }
  603. }
  604. //-----------------------------------------------------------------------------
  605. // Purpose: Check for enter key and go into keybinding mode if it was pressed
  606. //-----------------------------------------------------------------------------
  607. void COptionsSubKeyboard::OnKeyCodePressed(vgui::KeyCode code)
  608. {
  609. // Enter key pressed and not already trapping next key/button press
  610. if ( !m_pKeyBindList->IsCapturing() )
  611. {
  612. // Grab which item was set as interesting
  613. int r = m_pKeyBindList->GetItemOfInterest();
  614. // Check that it's visible
  615. int x, y, w, h;
  616. bool visible = m_pKeyBindList->GetCellBounds(r, 1, x, y, w, h);
  617. if (visible)
  618. {
  619. if ( KEY_DELETE == code )
  620. {
  621. // find the current binding and remove it
  622. KeyValues *kv = m_pKeyBindList->GetItemData(r);
  623. const char *key = kv->GetString("Key", NULL);
  624. if (key && *key)
  625. {
  626. RemoveKeyFromBindItems(NULL, key);
  627. }
  628. m_pClearBindingButton->SetEnabled(false);
  629. m_pKeyBindList->InvalidateItem(r);
  630. PostActionSignal(new KeyValues("ApplyButtonEnable"));
  631. // message handled, don't pass on
  632. return;
  633. }
  634. }
  635. }
  636. // Allow base class to process message instead
  637. BaseClass::OnKeyCodePressed( code );
  638. }
  639. //-----------------------------------------------------------------------------
  640. // Purpose: advanced keyboard settings dialog
  641. //-----------------------------------------------------------------------------
  642. class COptionsSubKeyboardAdvancedDlg : public vgui::Frame
  643. {
  644. DECLARE_CLASS_SIMPLE( COptionsSubKeyboardAdvancedDlg, vgui::Frame );
  645. public:
  646. COptionsSubKeyboardAdvancedDlg( vgui::VPANEL hParent ) : BaseClass( NULL, NULL )
  647. {
  648. // parent is ignored, since we want look like we're steal focus from the parent (we'll become modal below)
  649. SetTitle("#GameUI_KeyboardAdvanced_Title", true);
  650. SetSize( 280, 140 );
  651. LoadControlSettings( "resource/OptionsSubKeyboardAdvancedDlg.res" );
  652. MoveToCenterOfScreen();
  653. SetSizeable( false );
  654. SetDeleteSelfOnClose( true );
  655. }
  656. virtual void Activate()
  657. {
  658. BaseClass::Activate();
  659. input()->SetAppModalSurface(GetVPanel());
  660. // reset the data
  661. ConVarRef con_enable( "con_enable" );
  662. if ( con_enable.IsValid() )
  663. {
  664. SetControlInt("ConsoleCheck", con_enable.GetInt() ? 1 : 0);
  665. }
  666. ConVarRef hud_fastswitch( "hud_fastswitch" );
  667. if ( hud_fastswitch.IsValid() )
  668. {
  669. SetControlInt("FastSwitchCheck", hud_fastswitch.GetInt() ? 1 : 0);
  670. }
  671. }
  672. virtual void OnApplyData()
  673. {
  674. // apply data
  675. ConVarRef con_enable( "con_enable" );
  676. con_enable.SetValue( GetControlInt( "ConsoleCheck", 0 ) );
  677. ConVarRef hud_fastswitch( "hud_fastswitch" );
  678. hud_fastswitch.SetValue( GetControlInt( "FastSwitchCheck", 0 ) );
  679. }
  680. virtual void OnCommand( const char *command )
  681. {
  682. if ( !stricmp(command, "OK") )
  683. {
  684. // apply the data
  685. OnApplyData();
  686. Close();
  687. }
  688. else
  689. {
  690. BaseClass::OnCommand( command );
  691. }
  692. }
  693. void OnKeyCodeTyped(KeyCode code)
  694. {
  695. // force ourselves to be closed if the escape key it pressed
  696. if (code == KEY_ESCAPE)
  697. {
  698. Close();
  699. }
  700. else
  701. {
  702. BaseClass::OnKeyCodeTyped(code);
  703. }
  704. }
  705. };
  706. //-----------------------------------------------------------------------------
  707. // Purpose: Open advanced keyboard options
  708. //-----------------------------------------------------------------------------
  709. void COptionsSubKeyboard::OpenKeyboardAdvancedDialog()
  710. {
  711. if (!m_OptionsSubKeyboardAdvancedDlg.Get())
  712. {
  713. m_OptionsSubKeyboardAdvancedDlg = new COptionsSubKeyboardAdvancedDlg(GetVParent());
  714. }
  715. m_OptionsSubKeyboardAdvancedDlg->Activate();
  716. }