|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "vgui_controls/KeyBindingHelpDialog.h"
#include "vgui_controls/ListPanel.h"
#include "vgui/ISurface.h"
#include "vgui/IVGui.h"
#include "vgui/ILocalize.h"
#include "vgui/IInput.h"
#include "vgui/ISystem.h"
#include "KeyValues.h"
#include "vgui/Cursor.h"
#include "tier1/utldict.h"
#include "vgui_controls/KeyBoardEditorDialog.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
using namespace vgui;
// If the user holds the key bound to help down for this long, then the dialog will stay on automatically
#define KB_HELP_CONTINUE_SHOWING_TIME 1.0
static bool BindingLessFunc( KeyValues * const & lhs, KeyValues * const &rhs ) { KeyValues *p1, *p2;
p1 = const_cast< KeyValues * >( lhs ); p2 = const_cast< KeyValues * >( rhs ); return ( Q_stricmp( p1->GetString( "Action" ), p2->GetString( "Action" ) ) < 0 ) ? true : false; }
CKeyBindingHelpDialog::CKeyBindingHelpDialog( Panel *parent, Panel *panelToView, KeyBindingContextHandle_t handle, KeyCode code, int modifiers ) : BaseClass( parent, "KeyBindingHelpDialog" ), m_Handle( handle ), m_KeyCode( code ), m_Modifiers( modifiers ), m_bPermanent( false ) { Assert( panelToView ); m_hPanel = panelToView;
m_pList = new ListPanel( this, "KeyBindings" ); m_pList->SetIgnoreDoubleClick( true ); m_pList->AddColumnHeader(0, "Action", "#KBEditorBindingName", 175, 0); m_pList->AddColumnHeader(1, "Binding", "#KBEditorBinding", 175, 0); m_pList->AddColumnHeader(2, "Description", "#KBEditorDescription", 300, 0);
LoadControlSettings( "resource/KeyBindingHelpDialog.res" );
if ( panelToView && panelToView->GetName() && panelToView->GetName()[0] ) { SetTitle( panelToView->GetName(), true ); } else { SetTitle( "#KBHelpDialogTitle", true ); }
SetSmallCaption( true ); SetMinimumSize( 400, 400 ); SetMinimizeButtonVisible( false ); SetMaximizeButtonVisible( false ); SetSizeable( true ); SetMoveable( true ); SetMenuButtonVisible( false );
SetVisible( true );
MoveToCenterOfScreen();
PopulateList();
m_flShowTime = system()->GetCurrentTime(); ivgui()->AddTickSignal( GetVPanel(), 0 );
input()->SetAppModalSurface( GetVPanel() ); }
CKeyBindingHelpDialog::~CKeyBindingHelpDialog() { if ( input()->GetAppModalSurface() == GetVPanel() ) { input()->SetAppModalSurface( 0 ); } }
void CKeyBindingHelpDialog::OnTick() { BaseClass::OnTick();
bool keyStillDown = IsHelpKeyStillBeingHeld();
double curtime = system()->GetCurrentTime(); double elapsed = curtime - m_flShowTime; // After a second of holding the key, releasing the key will close the dialog
if ( elapsed > KB_HELP_CONTINUE_SHOWING_TIME ) { if ( !keyStillDown ) { MarkForDeletion(); return; } } // Otherwise, if they tapped the key within a second and now have released...
else if ( !keyStillDown ) { // Continue showing dialog indefinitely
ivgui()->RemoveTickSignal( GetVPanel() ); m_bPermanent = true; } }
// The key originally bound to help was pressed
void CKeyBindingHelpDialog::HelpKeyPressed() { // Don't kill while editor is being shown...
if ( m_hKeyBindingsEditor.Get() ) return;
if ( m_bPermanent ) { MarkForDeletion(); } }
bool CKeyBindingHelpDialog::IsHelpKeyStillBeingHeld() { bool keyDown = input()->IsKeyDown( m_KeyCode ); if ( !keyDown ) return false;
bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT)); bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL)); bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
int modifiers = 0; if ( shift ) { modifiers |= MODIFIER_SHIFT; } if ( ctrl ) { modifiers |= MODIFIER_CONTROL; } if ( alt ) { modifiers |= MODIFIER_ALT; }
if ( modifiers != m_Modifiers ) { return false; }
return true; }
void CKeyBindingHelpDialog::OnCommand( char const *cmd ) { if ( !Q_stricmp( cmd, "OK" ) || !Q_stricmp( cmd, "cancel" ) || !Q_stricmp( cmd, "Close" ) ) { MarkForDeletion(); } else if ( !Q_stricmp( cmd, "edit" ) ) { // Show the keybindings edit dialog
if ( m_hKeyBindingsEditor.Get() ) { delete m_hKeyBindingsEditor.Get(); }
// Don't delete panel if H key is released...
m_hKeyBindingsEditor = new CKeyBoardEditorDialog( this, m_hPanel, m_Handle ); m_hKeyBindingsEditor->DoModal();
ivgui()->RemoveTickSignal( GetVPanel() ); m_bPermanent = true; } else { BaseClass::OnCommand( cmd ); } }
void CKeyBindingHelpDialog::OnKeyCodeTyped(vgui::KeyCode code) { BaseClass::OnKeyCodeTyped( code ); }
void CKeyBindingHelpDialog::GetMappingList( Panel *panel, CUtlVector< PanelKeyBindingMap * >& maps ) { PanelKeyBindingMap *map = panel->GetKBMap(); while ( map ) { maps.AddToTail( map ); map = map->baseMap; } }
void CKeyBindingHelpDialog::AnsiText( char const *token, char *out, size_t buflen ) { out[ 0 ] = 0;
wchar_t *str = g_pVGuiLocalize->Find( token ); if ( !str ) { Q_strncpy( out, token, buflen ); } else { g_pVGuiLocalize->ConvertUnicodeToANSI( str, out, buflen ); } }
struct ListInfo_t { PanelKeyBindingMap *m_pMap; Panel *m_pPanel; };
void CKeyBindingHelpDialog::PopulateList() { m_pList->DeleteAllItems();
int i, j;
CUtlVector< ListInfo_t > maps; vgui::Panel *pPanel = m_hPanel; while ( pPanel->IsKeyBindingChainToParentAllowed() ) { PanelKeyBindingMap *map = pPanel->GetKBMap(); while ( map ) { int k; int c = maps.Count(); for ( k = 0; k < c; ++k ) { if ( maps[k].m_pMap == map ) break; } if ( k == c ) { int iMap = maps.AddToTail( ); maps[iMap].m_pMap = map; maps[iMap].m_pPanel = pPanel; } map = map->baseMap; }
pPanel = pPanel->GetParent(); if ( !pPanel ) break; }
CUtlRBTree< KeyValues *, int > sorted( 0, 0, BindingLessFunc );
// add header item
int c = maps.Count(); for ( i = 0; i < c; ++i ) { PanelKeyBindingMap *m = maps[ i ].m_pMap; pPanel = maps[i].m_pPanel; Assert( m );
int bindings = m->boundkeys.Count(); for ( j = 0; j < bindings; ++j ) { BoundKey_t *kbMap = &m->boundkeys[ j ]; Assert( kbMap );
// Create a new: blank item
KeyValues *item = new KeyValues( "Item" ); // Fill in data
char loc[ 128 ]; Q_snprintf( loc, sizeof( loc ), "#%s", kbMap->bindingname );
char ansi[ 256 ]; AnsiText( loc, ansi, sizeof( ansi ) );
item->SetString( "Action", ansi ); item->SetWString( "Binding", Panel::KeyCodeModifiersToDisplayString( (KeyCode)kbMap->keycode, kbMap->modifiers ) );
// Find the binding
KeyBindingMap_t *bindingMap = pPanel->LookupBinding( kbMap->bindingname ); if ( bindingMap && bindingMap->helpstring ) { AnsiText( bindingMap->helpstring, ansi, sizeof( ansi ) ); item->SetString( "Description", ansi ); } item->SetPtr( "Item", kbMap );
sorted.Insert( item ); }
// Now try and find any "unbound" keys...
int mappings = m->entries.Count(); for ( j = 0; j < mappings; ++j ) { KeyBindingMap_t *kbMap = &m->entries[ j ];
// See if it's bound
CUtlVector< BoundKey_t * > list; pPanel->LookupBoundKeys( kbMap->bindingname, list ); if ( list.Count() > 0 ) continue;
// Not bound, add a placeholder entry
// Create a new: blank item
KeyValues *item = new KeyValues( "Item" ); // fill in data
char loc[ 128 ]; Q_snprintf( loc, sizeof( loc ), "#%s", kbMap->bindingname );
char ansi[ 256 ]; AnsiText( loc, ansi, sizeof( ansi ) );
item->SetString( "Action", ansi ); item->SetWString( "Binding", L"" ); if ( kbMap->helpstring ) { AnsiText( kbMap->helpstring, ansi, sizeof( ansi ) ); item->SetString( "Description", ansi ); }
item->SetPtr( "Unbound", kbMap );
sorted.Insert( item ); } }
for ( j = sorted.FirstInorder() ; j != sorted.InvalidIndex(); j = sorted.NextInorder( j ) ) { KeyValues *item = sorted[ j ];
// Add to list
m_pList->AddItem( item, 0, false, false );
item->deleteThis(); }
sorted.RemoveAll(); }
|