From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/vgui2/vgui_controls/Panel.cpp | 16902 ++++++++++++++++----------------- 1 file changed, 8451 insertions(+), 8451 deletions(-) (limited to 'mp/src/vgui2/vgui_controls/Panel.cpp') diff --git a/mp/src/vgui2/vgui_controls/Panel.cpp b/mp/src/vgui2/vgui_controls/Panel.cpp index 7fb2e630..3f3634fe 100644 --- a/mp/src/vgui2/vgui_controls/Panel.cpp +++ b/mp/src/vgui2/vgui_controls/Panel.cpp @@ -1,8451 +1,8451 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - - -#include -#include -#include -#include -#include // isdigit() - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "vgui_controls/Menu.h" -#include "vgui_controls/MenuItem.h" - -#include "UtlSortVector.h" - -#include "tier1/utldict.h" -#include "tier1/utlbuffer.h" -#include "mempool.h" -#include "filesystem.h" -#include "tier0/icommandline.h" - -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include - -using namespace vgui; - -#define TRIPLE_PRESS_MSEC 300 - - -extern int GetBuildModeDialogCount(); - -static char *CopyString( const char *in ) -{ - if ( !in ) - return NULL; - - int len = strlen( in ); - char *n = new char[ len + 1 ]; - Q_strncpy( n, in, len + 1 ); - return n; -} - -#if defined( VGUI_USEDRAGDROP ) -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct vgui::DragDrop_t -{ - DragDrop_t() : - m_bDragEnabled( false ), - m_bShowDragHelper( true ), - m_bDropEnabled( false ), - m_bDragStarted( false ), - m_nDragStartTolerance( 8 ), - m_bDragging( false ), - m_lDropHoverTime( 0 ), - m_bDropMenuShown( false ), - m_bPreventChaining( false ) - { - m_nStartPos[ 0 ] = m_nStartPos[ 1 ] = 0; - m_nLastPos[ 0 ] = m_nLastPos[ 1 ] = 0; - } - - // Drag related data - bool m_bDragEnabled; - bool m_bShowDragHelper; - bool m_bDragging; - bool m_bDragStarted; - // How many pixels the dragged box must move before showing the outline rect... - int m_nDragStartTolerance; - int m_nStartPos[ 2 ]; - int m_nLastPos[ 2 ]; - CUtlVector< KeyValues * > m_DragData; - CUtlVector< PHandle > m_DragPanels; - - // Drop related data - bool m_bDropEnabled; - // A droppable panel can have a hover context menu, which will show up after m_flHoverContextTime of hovering - float m_flHoverContextTime; - - PHandle m_hCurrentDrop; - // Amount of time hovering over current drop target - long m_lDropHoverTime; - bool m_bDropMenuShown; - DHANDLE< Menu > m_hDropContextMenu; - - // Misc data - bool m_bPreventChaining; -}; - -//----------------------------------------------------------------------------- -// Purpose: Helper for painting to the full screen... -//----------------------------------------------------------------------------- -class CDragDropHelperPanel : public Panel -{ - DECLARE_CLASS_SIMPLE( CDragDropHelperPanel, Panel ); -public: - CDragDropHelperPanel(); - - virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups); - virtual void PostChildPaint(); - - void AddPanel( Panel *current ); - - void RemovePanel( Panel *search ); - -private: - struct DragHelperPanel_t - { - PHandle m_hPanel; - }; - - CUtlVector< DragHelperPanel_t > m_PaintList; -}; - -vgui::DHANDLE< CDragDropHelperPanel > s_DragDropHelper; -#endif - -#if defined( VGUI_USEKEYBINDINGMAPS ) - -BoundKey_t::BoundKey_t(): - isbuiltin( true ), - bindingname( 0 ), - keycode( KEY_NONE ), - modifiers( 0 ) -{ -} - -BoundKey_t::BoundKey_t( const BoundKey_t& src ) -{ - isbuiltin = src.isbuiltin; - bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname ); - keycode = src.keycode; - modifiers = src.modifiers; -} - -BoundKey_t& BoundKey_t::operator =( const BoundKey_t& src ) -{ - if ( this == &src ) - return *this; - isbuiltin = src.isbuiltin; - bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname ); - keycode = src.keycode; - modifiers = src.modifiers; - return *this; -} - - -BoundKey_t::~BoundKey_t() -{ - if ( !isbuiltin ) - { - delete[] bindingname; - } -} - -KeyBindingMap_t::KeyBindingMap_t() : - bindingname( 0 ), - func( 0 ), - helpstring( 0 ), - docstring( 0 ), - passive( false ) -{ -} - -KeyBindingMap_t::KeyBindingMap_t( const KeyBindingMap_t& src ) -{ - bindingname = src.bindingname; - helpstring = src.helpstring; - docstring = src.docstring; - - func = src.func; - passive = src.passive; -} - -KeyBindingMap_t::~KeyBindingMap_t() -{ -} - -class CKeyBindingsMgr -{ -public: - - CKeyBindingsMgr() : - m_Bindings( 0, 0, KeyBindingContextHandleLessFunc ), - m_nKeyBindingContexts( 0 ) - { - } - - struct KBContext_t - { - KBContext_t() : - m_KeyBindingsFile( UTL_INVAL_SYMBOL ), - m_KeyBindingsPathID( UTL_INVAL_SYMBOL ) - { - m_Handle = INVALID_KEYBINDINGCONTEXT_HANDLE; - } - - KBContext_t( const KBContext_t& src ) - { - m_Handle = src.m_Handle; - m_KeyBindingsFile = src.m_KeyBindingsFile; - m_KeyBindingsPathID = src.m_KeyBindingsPathID; - int c = src.m_Panels.Count(); - for ( int i = 0; i < c; ++i ) - { - m_Panels.AddToTail( src.m_Panels[ i ] ); - } - } - - KeyBindingContextHandle_t m_Handle; - CUtlSymbol m_KeyBindingsFile; - CUtlSymbol m_KeyBindingsPathID; - CUtlVector< Panel * > m_Panels; - }; - - static bool KeyBindingContextHandleLessFunc( const KBContext_t& lhs, const KBContext_t& rhs ) - { - return lhs.m_Handle < rhs.m_Handle; - } - - KeyBindingContextHandle_t CreateContext( char const *filename, char const *pathID ) - { - KBContext_t entry; - - entry.m_Handle = (KeyBindingContextHandle_t)++m_nKeyBindingContexts; - entry.m_KeyBindingsFile = filename; - if ( pathID ) - { - entry.m_KeyBindingsPathID = pathID; - } - else - { - entry.m_KeyBindingsPathID = UTL_INVAL_SYMBOL; - } - - m_Bindings.Insert( entry ); - - return entry.m_Handle; - } - - void AddPanelToContext( KeyBindingContextHandle_t handle, Panel *panel ) - { - if ( !panel->GetName() || !panel->GetName()[ 0 ] ) - { - Warning( "Can't add Keybindings Context for unnamed panels\n" ); - return; - } - - KBContext_t *entry = Find( handle ); - Assert( entry ); - if ( entry ) - { - int idx = entry->m_Panels.Find( panel ); - if ( idx == entry->m_Panels.InvalidIndex() ) - { - entry->m_Panels.AddToTail( panel ); - } - } - } - - void OnPanelDeleted( KeyBindingContextHandle_t handle, Panel *panel ) - { - KBContext_t *kb = Find( handle ); - if ( kb ) - { - kb->m_Panels.FindAndRemove( panel ); - } - } - - KBContext_t *Find( KeyBindingContextHandle_t handle ) - { - KBContext_t search; - search.m_Handle = handle; - int idx = m_Bindings.Find( search ); - if ( idx == m_Bindings.InvalidIndex() ) - { - return NULL; - } - return &m_Bindings[ idx ]; - } - - char const *GetKeyBindingsFile( KeyBindingContextHandle_t handle ) - { - KBContext_t *kb = Find( handle ); - if ( kb ) - { - return kb->m_KeyBindingsFile.String(); - } - Assert( 0 ); - return ""; - } - - char const *GetKeyBindingsFilePathID( KeyBindingContextHandle_t handle ) - { - KBContext_t *kb = Find( handle ); - if ( kb ) - { - return kb->m_KeyBindingsPathID.String(); - } - Assert( 0 ); - return NULL; - } - - int GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle ) - { - KBContext_t *kb = Find( handle ); - if ( kb ) - { - return kb->m_Panels.Count(); - } - Assert( 0 ); - return 0; - } - - //----------------------------------------------------------------------------- - // Purpose: static method - // Input : index - - // Output : Panel - //----------------------------------------------------------------------------- - Panel *GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index ) - { - KBContext_t *kb = Find( handle ); - if ( kb ) - { - Assert( index >= 0 && index < kb->m_Panels.Count() ); - return kb->m_Panels[ index ]; - } - Assert( 0 ); - return 0; - } - - CUtlRBTree< KBContext_t, int > m_Bindings; - int m_nKeyBindingContexts; -}; - -static CKeyBindingsMgr g_KBMgr; - -//----------------------------------------------------------------------------- -// Purpose: Static method to allocate a context -// Input : - -// Output : KeyBindingContextHandle_t -//----------------------------------------------------------------------------- -KeyBindingContextHandle_t Panel::CreateKeyBindingsContext( char const *filename, char const *pathID /*=0*/ ) -{ - return g_KBMgr.CreateContext( filename, pathID ); -} - - -//----------------------------------------------------------------------------- -// Purpose: static method -// Input : - -// Output : int -//----------------------------------------------------------------------------- -int Panel::GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle ) -{ - return g_KBMgr.GetPanelsWithKeyBindingsCount( handle ); -} - -//----------------------------------------------------------------------------- -// Purpose: static method -// Input : index - -// Output : Panel -//----------------------------------------------------------------------------- -Panel *Panel::GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index ) -{ - return g_KBMgr.GetPanelWithKeyBindings( handle, index ); -} - - -//----------------------------------------------------------------------------- -// Returns the number of keybindings -//----------------------------------------------------------------------------- -int Panel::GetKeyMappingCount( ) -{ - int nCount = 0; - PanelKeyBindingMap *map = GetKBMap(); - while ( map ) - { - nCount += map->entries.Count(); - map = map->baseMap; - } - return nCount; -} - - -//----------------------------------------------------------------------------- -// Purpose: static method. Reverts key bindings for all registered panels (panels with keybindings actually -// loaded from file -// Input : - -//----------------------------------------------------------------------------- -void Panel::RevertKeyBindings( KeyBindingContextHandle_t handle ) -{ - int c = GetPanelsWithKeyBindingsCount( handle ); - for ( int i = 0; i < c; ++i ) - { - Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); - Assert( kbPanel ); - kbPanel->RevertKeyBindingsToDefault(); - } -} - -static void BufPrint( CUtlBuffer& buf, int level, char const *fmt, ... ) -{ - char string[ 2048 ]; - va_list argptr; - va_start( argptr, fmt ); - _vsnprintf( string, sizeof( string ) - 1, fmt, argptr ); - va_end( argptr ); - string[ sizeof( string ) - 1 ] = 0; - - while ( --level >= 0 ) - { - buf.Printf( " " ); - } - buf.Printf( "%s", string ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : handle - -//----------------------------------------------------------------------------- -void Panel::SaveKeyBindings( KeyBindingContextHandle_t handle ) -{ - char const *filename = g_KBMgr.GetKeyBindingsFile( handle ); - char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle ); - - SaveKeyBindingsToFile( handle, filename, pathID ); -} - -//----------------------------------------------------------------------------- -// Purpose: static method. Saves key binding files out for all keybindings -// Input : - -//----------------------------------------------------------------------------- -void Panel::SaveKeyBindingsToFile( KeyBindingContextHandle_t handle, char const *filename, char const *pathID /*= 0*/ ) -{ - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - - BufPrint( buf, 0, "keybindings\n" ); - BufPrint( buf, 0, "{\n" ); - - int c = GetPanelsWithKeyBindingsCount( handle ); - for ( int i = 0; i < c; ++i ) - { - Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); - Assert( kbPanel ); - if ( !kbPanel ) - continue; - - Assert( kbPanel->GetName() ); - Assert( kbPanel->GetName()[ 0 ] ); - - if ( !kbPanel->GetName() || !kbPanel->GetName()[ 0 ] ) - continue; - - BufPrint( buf, 1, "\"%s\"\n", kbPanel->GetName() ); - BufPrint( buf, 1, "{\n" ); - - kbPanel->SaveKeyBindingsToBuffer( 2, buf ); - - BufPrint( buf, 1, "}\n" ); - } - - BufPrint( buf, 0, "}\n" ); - - if ( g_pFullFileSystem->FileExists( filename, pathID ) && - !g_pFullFileSystem->IsFileWritable( filename, pathID ) ) - { - Warning( "Panel::SaveKeyBindings '%s' is read-only!!!\n", filename ); - } - - FileHandle_t h = g_pFullFileSystem->Open( filename, "wb", pathID ); - if ( FILESYSTEM_INVALID_HANDLE != h ) - { - g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), h ); - g_pFullFileSystem->Close( h ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : handle - -// *panelOfInterest - -//----------------------------------------------------------------------------- -void Panel::LoadKeyBindingsForOnePanel( KeyBindingContextHandle_t handle, Panel *panelOfInterest ) -{ - if ( !panelOfInterest ) - return; - if ( !panelOfInterest->GetName() ) - return; - if ( !panelOfInterest->GetName()[ 0 ] ) - return; - - char const *filename = g_KBMgr.GetKeyBindingsFile( handle ); - char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle ); - - KeyValues *kv = new KeyValues( "keybindings" ); - if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) ) - { - int c = GetPanelsWithKeyBindingsCount( handle ); - for ( int i = 0; i < c; ++i ) - { - Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); - Assert( kbPanel ); - - char const *panelName = kbPanel->GetName(); - if ( !panelName ) - { - continue; - } - - if ( Q_stricmp( panelOfInterest->GetName(), panelName ) ) - continue; - - KeyValues *subKey = kv->FindKey( panelName, false ); - if ( !subKey ) - { - Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName ); - continue; - } - - kbPanel->ParseKeyBindings( subKey ); - } - } - kv->deleteThis(); -} - -//----------------------------------------------------------------------------- -// Purpose: static method. Loads all key bindings again -// Input : - -//----------------------------------------------------------------------------- - -void Panel::ReloadKeyBindings( KeyBindingContextHandle_t handle ) -{ - char const *filename = g_KBMgr.GetKeyBindingsFile( handle ); - char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle ); - - KeyValues *kv = new KeyValues( "keybindings" ); - if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) ) - { - int c = GetPanelsWithKeyBindingsCount( handle ); - for ( int i = 0; i < c; ++i ) - { - Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); - Assert( kbPanel ); - - char const *panelName = kbPanel->GetName(); - if ( !panelName ) - { - continue; - } - - KeyValues *subKey = kv->FindKey( panelName, false ); - if ( !subKey ) - { - Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName ); - continue; - } - - kbPanel->ParseKeyBindings( subKey ); - } - } - kv->deleteThis(); -} -#endif // VGUI_USEKEYBINDINGMAPS - -DECLARE_BUILD_FACTORY( Panel ); - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -Panel::Panel() -{ - Init(0, 0, 64, 24); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -Panel::Panel(Panel *parent) -{ - Init(0, 0, 64, 24); - SetParent(parent); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -Panel::Panel(Panel *parent, const char *panelName) -{ - Init(0, 0, 64, 24); - SetName(panelName); - SetParent(parent); - SetBuildModeEditable(true); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -Panel::Panel( Panel *parent, const char *panelName, HScheme scheme ) -{ - Init(0, 0, 64, 24); - SetName(panelName); - SetParent(parent); - SetBuildModeEditable(true); - SetScheme( scheme ); -} - -//----------------------------------------------------------------------------- -// Purpose: Setup -//----------------------------------------------------------------------------- -void Panel::Init( int x, int y, int wide, int tall ) -{ - _panelName = NULL; - _tooltipText = NULL; - _pinToSibling = NULL; - m_hMouseEventHandler = NULL; - _pinCornerToSibling = PIN_TOPLEFT; - _pinToSiblingCorner = PIN_TOPLEFT; - - // get ourselves an internal panel - _vpanel = ivgui()->AllocPanel(); - ipanel()->Init(_vpanel, this); - - SetPos(x, y); - SetSize(wide, tall); - _flags.SetFlag( NEEDS_LAYOUT | NEEDS_SCHEME_UPDATE | NEEDS_DEFAULT_SETTINGS_APPLIED ); - _flags.SetFlag( AUTODELETE_ENABLED | PAINT_BORDER_ENABLED | PAINT_BACKGROUND_ENABLED | PAINT_ENABLED ); -#if defined( VGUI_USEKEYBINDINGMAPS ) - _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT ); -#endif - m_nPinDeltaX = m_nPinDeltaY = 0; - m_nResizeDeltaX = m_nResizeDeltaY = 0; - _autoResizeDirection = AUTORESIZE_NO; - _pinCorner = PIN_TOPLEFT; - _cursor = dc_arrow; - _border = NULL; - _buildGroup = UTLHANDLE_INVALID; - _tabPosition = 0; - m_iScheme = 0; - m_bIsSilent = false; - m_bParentNeedsCursorMoveEvents = false; - - _buildModeFlags = 0; // not editable or deletable in buildmode dialog by default - - m_pTooltips = NULL; - m_bToolTipOverridden = false; - - m_flAlpha = 255.0f; - m_nPaintBackgroundType = 0; - - //============================================================================= - // HPE_BEGIN: - // [tj] Default to rounding all corners (for draw style 2) - //============================================================================= - m_roundedCorners = PANEL_ROUND_CORNER_ALL; - //============================================================================= - // HPE_END - //============================================================================= - - m_nBgTextureId1 = -1; - m_nBgTextureId2 = -1; - m_nBgTextureId3 = -1; - m_nBgTextureId4 = -1; -#if defined( VGUI_USEDRAGDROP ) - m_pDragDrop = new DragDrop_t; - -#endif - - m_lLastDoublePressTime = 0L; - -#if defined( VGUI_USEKEYBINDINGMAPS ) - m_hKeyBindingsContext = INVALID_KEYBINDINGCONTEXT_HANDLE; -#endif - - REGISTER_COLOR_AS_OVERRIDABLE( _fgColor, "fgcolor_override" ); - REGISTER_COLOR_AS_OVERRIDABLE( _bgColor, "bgcolor_override" ); - - m_bIsConsoleStylePanel = false; - m_NavUp = NULL; - m_NavDown = NULL; - m_NavLeft = NULL; - m_NavRight = NULL; - m_NavToRelay = NULL; - m_NavActivate = NULL; - m_NavBack = NULL; - m_sNavUpName = NULL; - m_sNavDownName = NULL; - m_sNavLeftName = NULL; - m_sNavRightName = NULL; - m_sNavToRelayName = NULL; - m_sNavActivateName = NULL; - m_sNavBackName = NULL; - - m_PassUnhandledInput = true; - m_LastNavDirection = ND_NONE; - m_bWorldPositionCurrentFrame = false; - m_bForceStereoRenderToFrameBuffer = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- -Panel::~Panel() -{ - // @note Tom Bui: only cleanup if we've created it - if ( !m_bToolTipOverridden ) - { - if ( m_pTooltips ) - { - delete m_pTooltips; - } - } -#if defined( VGUI_USEKEYBINDINGMAPS ) - if ( IsValidKeyBindingsContext() ) - { - g_KBMgr.OnPanelDeleted( m_hKeyBindingsContext, this ); - } -#endif // VGUI_USEKEYBINDINGMAPS -#if defined( VGUI_USEDRAGDROP ) - if ( m_pDragDrop->m_bDragging ) - { - OnFinishDragging( false, (MouseCode)-1 ); - } -#endif // VGUI_USEDRAGDROP - - _flags.ClearFlag( AUTODELETE_ENABLED ); - _flags.SetFlag( MARKED_FOR_DELETION ); - - // remove panel from any list - SetParent((VPANEL)NULL); - - // Stop our children from pointing at us, and delete them if possible - while (ipanel()->GetChildCount(GetVPanel())) - { - VPANEL child = ipanel()->GetChild(GetVPanel(), 0); - if (ipanel()->IsAutoDeleteSet(child)) - { - ipanel()->DeletePanel(child); - } - else - { - ipanel()->SetParent(child, NULL); - } - } - - // delete VPanel - ivgui()->FreePanel(_vpanel); - // free our name - delete [] _panelName; - - if ( _tooltipText && _tooltipText[0] ) - { - delete [] _tooltipText; - } - - delete [] _pinToSibling; - - _vpanel = NULL; -#if defined( VGUI_USEDRAGDROP ) - delete m_pDragDrop; -#endif // VGUI_USEDRAGDROP -} - -//----------------------------------------------------------------------------- -// Purpose: fully construct this panel so its ready for use right now (i.e fonts loaded, colors set, default label text set, ...) -//----------------------------------------------------------------------------- -void Panel::MakeReadyForUse() -{ -// PerformApplySchemeSettings(); - UpdateSiblingPin(); - surface()->SolveTraverse( GetVPanel(), true ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetName( const char *panelName ) -{ - // No change? - if ( _panelName && - panelName && - !Q_strcmp( _panelName, panelName ) ) - { - return; - } - - if (_panelName) - { - delete [] _panelName; - _panelName = NULL; - } - - if (panelName) - { - int len = Q_strlen(panelName) + 1; - _panelName = new char[ len ]; - Q_strncpy( _panelName, panelName, len ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: returns the given name of the panel -//----------------------------------------------------------------------------- -const char *Panel::GetName() -{ - if (_panelName) - return _panelName; - - return ""; -} - -//----------------------------------------------------------------------------- -// Purpose: returns the name of the module that this instance of panel was compiled into -//----------------------------------------------------------------------------- -const char *Panel::GetModuleName() -{ - return vgui::GetControlsModuleName(); -} - -//----------------------------------------------------------------------------- -// Purpose: returns the classname of the panel (as specified in the panelmaps) -//----------------------------------------------------------------------------- -const char *Panel::GetClassName() -{ - // loop up the panel map name - PanelMessageMap *panelMap = GetMessageMap(); - if ( panelMap ) - { - return panelMap->pfnClassName(); - } - - return "Panel"; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetPos(int x, int y) -{ - if (!CommandLine()->FindParm("-hushasserts")) - { - Assert( abs(x) < 32768 && abs(y) < 32768 ); - } - ipanel()->SetPos(GetVPanel(), x, y); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::GetPos(int &x, int &y) -{ - ipanel()->GetPos(GetVPanel(), x, y); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetSize(int wide, int tall) -{ - Assert( abs(wide) < 32768 && abs(tall) < 32768 ); - ipanel()->SetSize(GetVPanel(), wide, tall); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::GetSize(int &wide, int &tall) -{ - ipanel()->GetSize(GetVPanel(), wide, tall); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetBounds(int x, int y, int wide, int tall) -{ - SetPos(x,y); - SetSize(wide,tall); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::GetBounds(int &x, int &y, int &wide, int &tall) -{ - GetPos(x, y); - GetSize(wide, tall); -} - -//----------------------------------------------------------------------------- -// Purpose: returns safe handle to parent -//----------------------------------------------------------------------------- -VPANEL Panel::GetVParent() -{ - if ( ipanel() ) - { - return ipanel()->GetParent(GetVPanel()); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: returns a pointer to a controls version of a Panel pointer -//----------------------------------------------------------------------------- -Panel *Panel::GetParent() -{ - // get the parent and convert it to a Panel * - // this is OK, the hierarchy is guaranteed to be all from the same module, except for the root node - // the root node always returns NULL when a GetParent() is done so everything is OK - if ( ipanel() ) - { - VPANEL parent = ipanel()->GetParent(GetVPanel()); - if (parent) - { - Panel *pParent = ipanel()->GetPanel(parent, GetControlsModuleName()); - Assert(!pParent || !strcmp(pParent->GetModuleName(), GetControlsModuleName())); - return pParent; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Screen size change notification handler -//----------------------------------------------------------------------------- -void Panel::OnScreenSizeChanged(int nOldWide, int nOldTall) -{ - // post to all children - for (int i = 0; i < ipanel()->GetChildCount(GetVPanel()); i++) - { - VPANEL child = ipanel()->GetChild(GetVPanel(), i); - PostMessage(child, new KeyValues("OnScreenSizeChanged", "oldwide", nOldWide, "oldtall", nOldTall), NULL); - } - - // make any currently fullsize window stay fullsize - int x, y, wide, tall; - GetBounds(x, y, wide, tall); - int screenWide, screenTall; - surface()->GetScreenSize(screenWide, screenTall); - if (x == 0 && y == 0 && nOldWide == wide && tall == nOldTall) - { - // fullsize - surface()->GetScreenSize(wide, tall); - SetBounds(0, 0, wide, tall); - } - - // panel needs to re-get it's scheme settings - _flags.SetFlag( NEEDS_SCHEME_UPDATE ); - - // invalidate our settings - InvalidateLayout(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetVisible(bool state) -{ - ipanel()->SetVisible(GetVPanel(), state); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool Panel::IsVisible() -{ - if (ipanel()) - { - return ipanel()->IsVisible(GetVPanel()); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetEnabled(bool state) -{ - if (state != ipanel()->IsEnabled( GetVPanel())) - { - ipanel()->SetEnabled(GetVPanel(), state); - InvalidateLayout(false); - Repaint(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool Panel::IsEnabled() -{ - return ipanel()->IsEnabled(GetVPanel()); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool Panel::IsPopup() -{ - return ipanel()->IsPopup(GetVPanel()); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::Repaint() -{ - _flags.SetFlag( NEEDS_REPAINT ); - if (surface()) - { - surface()->Invalidate(GetVPanel()); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::Think() -{ - if (IsVisible()) - { - // update any tooltips - if (m_pTooltips) - { - m_pTooltips->PerformLayout(); - } - if ( _flags.IsFlagSet( NEEDS_LAYOUT ) ) - { - InternalPerformLayout(); - } - } - - OnThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::PaintTraverse( bool repaint, bool allowForce ) -{ - if ( m_bWorldPositionCurrentFrame ) - { - surface()->SolveTraverse( GetVPanel() ); - } - - if ( !IsVisible() ) - { - return; - } - - float oldAlphaMultiplier = surface()->DrawGetAlphaMultiplier(); - float newAlphaMultiplier = oldAlphaMultiplier * m_flAlpha * 1.0f/255.0f; - - if ( IsXbox() && !newAlphaMultiplier ) - { - // xbox optimization not suitable for pc - // xbox panels are compliant and can early out and not traverse their children - // when they have no opacity - return; - } - - if ( !repaint && - allowForce && - _flags.IsFlagSet( NEEDS_REPAINT ) ) - { - repaint = true; - _flags.ClearFlag( NEEDS_REPAINT ); - } - - VPANEL vpanel = GetVPanel(); - - bool bPushedViewport = false; - if( GetForceStereoRenderToFrameBuffer() ) - { - CMatRenderContextPtr pRenderContext( materials ); - if( pRenderContext->GetRenderTarget() ) - { - surface()->PushFullscreenViewport(); - bPushedViewport = true; - } - } - - int clipRect[4]; - ipanel()->GetClipRect( vpanel, clipRect[0], clipRect[1], clipRect[2], clipRect[3] ); - if ( ( clipRect[2] <= clipRect[0] ) || ( clipRect[3] <= clipRect[1] ) ) - { - repaint = false; - } - - // set global alpha - surface()->DrawSetAlphaMultiplier( newAlphaMultiplier ); - - bool bBorderPaintFirst = _border ? _border->PaintFirst() : false; - - // draw the border first if requested to - if ( bBorderPaintFirst && repaint && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != null ) ) - { - // Paint the border over the background with no inset - surface()->PushMakeCurrent( vpanel, false ); - PaintBorder(); - surface()->PopMakeCurrent( vpanel ); - } - - if ( repaint ) - { - // draw the background with no inset - if ( _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) ) - { - surface()->PushMakeCurrent( vpanel, false ); - PaintBackground(); - surface()->PopMakeCurrent( vpanel ); - } - - // draw the front of the panel with the inset - if ( _flags.IsFlagSet( PAINT_ENABLED ) ) - { - surface()->PushMakeCurrent( vpanel, true ); - Paint(); - surface()->PopMakeCurrent( vpanel ); - } - } - - // traverse and paint all our children - CUtlVector< VPANEL > &children = ipanel()->GetChildren( vpanel ); - int childCount = children.Count(); - for (int i = 0; i < childCount; i++) - { - VPANEL child = children[ i ]; - bool bVisible = ipanel()->IsVisible( child ); - - if ( surface()->ShouldPaintChildPanel( child ) ) - { - if ( bVisible ) - { - ipanel()->PaintTraverse( child, repaint, allowForce ); - } - } - else - { - // Invalidate the child panel so that it gets redrawn - surface()->Invalidate( child ); - - // keep traversing the tree, just don't allow anyone to paint after here - if ( bVisible ) - { - ipanel()->PaintTraverse( child, false, false ); - } - } - } - - // draw the border last - if ( repaint ) - { - if ( !bBorderPaintFirst && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != null ) ) - { - // Paint the border over the background with no inset - surface()->PushMakeCurrent( vpanel, false ); - PaintBorder(); - surface()->PopMakeCurrent( vpanel ); - } - -#ifdef _DEBUG - // IsBuildGroupEnabled recurses up all the parents and ends up being very expensive as it wanders all over memory - if ( GetBuildModeDialogCount() && IsBuildGroupEnabled() ) //&& HasFocus() ) - { - // outline all selected panels - CUtlVector *controlGroup = _buildGroup->GetControlGroup(); - for (int i=0; i < controlGroup->Size(); ++i) - { - // outline all selected panels - CUtlVector *controlGroup = _buildGroup->GetControlGroup(); - for (int i=0; i < controlGroup->Size(); ++i) - { - surface()->PushMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel(), false ); - ((*controlGroup)[i].Get())->PaintBuildOverlay(); - surface()->PopMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel() ); - } - - _buildGroup->DrawRulers(); - } - } -#endif - - // All of our children have painted, etc, now allow painting in top of them - if ( _flags.IsFlagSet( POST_CHILD_PAINT_ENABLED ) ) - { - surface()->PushMakeCurrent( vpanel, false ); - PostChildPaint(); - surface()->PopMakeCurrent( vpanel ); - } - } - - surface()->DrawSetAlphaMultiplier( oldAlphaMultiplier ); - - surface()->SwapBuffers( vpanel ); - - if( bPushedViewport ) - { - surface()->PopFullscreenViewport(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::PaintBorder() -{ - _border->Paint(GetVPanel()); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::PaintBackground() -{ - int wide, tall; - GetSize( wide, tall ); - if ( m_SkipChild.Get() && m_SkipChild->IsVisible() ) - { - if ( GetPaintBackgroundType() == 2 ) - { - int cornerWide, cornerTall; - GetCornerTextureSize( cornerWide, cornerTall ); - - Color col = GetBgColor(); - DrawHollowBox( 0, 0, wide, tall, col, 1.0f ); - - wide -= 2 * cornerWide; - tall -= 2 * cornerTall; - - FillRectSkippingPanel( GetBgColor(), cornerWide, cornerTall, wide, tall, m_SkipChild.Get() ); - } - else - { - FillRectSkippingPanel( GetBgColor(), 0, 0, wide, tall, m_SkipChild.Get() ); - } - } - else - { - Color col = GetBgColor(); - - switch ( m_nPaintBackgroundType ) - { - default: - case 0: - { - surface()->DrawSetColor(col); - surface()->DrawFilledRect(0, 0, wide, tall); - } - break; - case 1: - { - DrawTexturedBox( 0, 0, wide, tall, col, 1.0f ); - } - break; - case 2: - { - DrawBox( 0, 0, wide, tall, col, 1.0f ); - } - break; - case 3: - { - DrawBoxFade( 0, 0, wide, tall, col, 1.0f, 255, 0, true ); - } - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::Paint() -{ - // empty on purpose - // PaintBackground is painted and default behavior is for Paint to do nothing -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::PostChildPaint() -{ - // Empty on purpose - // This is called if _postChildPaintEnabled is true and allows painting to - // continue on the surface after all of the panel's children have painted - // themselves. Allows drawing an overlay on top of the children, etc. -} - -//----------------------------------------------------------------------------- -// Purpose: Draws a black rectangle around the panel. -//----------------------------------------------------------------------------- -void Panel::PaintBuildOverlay() -{ - int wide,tall; - GetSize(wide,tall); - surface()->DrawSetColor(0, 0, 0, 255); - - surface()->DrawFilledRect(0,0,wide,2); //top - surface()->DrawFilledRect(0,tall-2,wide,tall); //bottom - surface()->DrawFilledRect(0,2,2,tall-2); //left - surface()->DrawFilledRect(wide-2,2,wide,tall-2); //right -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the panel's draw code will fully cover it's area -//----------------------------------------------------------------------------- -bool Panel::IsOpaque() -{ - // FIXME: Add code to account for the 'SkipChild' functionality in Frame - if ( IsVisible() && _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) && ( _bgColor[3] == 255 ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the settings are aligned to the right of the screen -//----------------------------------------------------------------------------- -bool Panel::IsRightAligned() -{ - return (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED); -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the settings are aligned to the bottom of the screen -//----------------------------------------------------------------------------- -bool Panel::IsBottomAligned() -{ - return (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED); -} - -//----------------------------------------------------------------------------- -// Purpose: sets the parent -//----------------------------------------------------------------------------- -void Panel::SetParent(Panel *newParent) -{ - // Assert that the parent is from the same module as the child - // FIXME: !!! work out how to handle this properly! - // Assert(!newParent || !strcmp(newParent->GetModuleName(), GetControlsModuleName())); - - if (newParent) - { - SetParent(newParent->GetVPanel()); - } - else - { - SetParent((VPANEL)NULL); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetParent(VPANEL newParent) -{ - if (newParent) - { - ipanel()->SetParent(GetVPanel(), newParent); - } - else - { - ipanel()->SetParent(GetVPanel(), NULL); - } - - if (GetVParent() && !IsPopup()) - { - SetProportional(ipanel()->IsProportional(GetVParent())); - - // most of the time KBInput == parents kbinput - if (ipanel()->IsKeyBoardInputEnabled(GetVParent()) != IsKeyBoardInputEnabled()) - { - SetKeyBoardInputEnabled(ipanel()->IsKeyBoardInputEnabled(GetVParent())); - } - - if (ipanel()->IsMouseInputEnabled(GetVParent()) != IsMouseInputEnabled()) - { - SetMouseInputEnabled(ipanel()->IsMouseInputEnabled(GetVParent())); - } - } - - UpdateSiblingPin(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::OnChildAdded(VPANEL child) -{ - Assert( !_flags.IsFlagSet( IN_PERFORM_LAYOUT ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: default message handler -//----------------------------------------------------------------------------- -void Panel::OnSizeChanged(int newWide, int newTall) -{ - InvalidateLayout(); // our size changed so force us to layout again -} - -//----------------------------------------------------------------------------- -// Purpose: sets Z ordering - lower numbers are always behind higher z's -//----------------------------------------------------------------------------- -void Panel::SetZPos(int z) -{ - ipanel()->SetZPos(GetVPanel(), z); -} - -//----------------------------------------------------------------------------- -// Purpose: sets Z ordering - lower numbers are always behind higher z's -//----------------------------------------------------------------------------- -int Panel::GetZPos() -{ - return ( ipanel()->GetZPos( GetVPanel() ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: sets alpha modifier for panel and all child panels [0..255] -//----------------------------------------------------------------------------- -void Panel::SetAlpha(int alpha) -{ - m_flAlpha = alpha; -} - -//----------------------------------------------------------------------------- -// Purpose: data accessor -//----------------------------------------------------------------------------- -int Panel::GetAlpha() -{ - return (int)m_flAlpha; -} - -//----------------------------------------------------------------------------- -// Purpose: Moves the panel to the front of the z-order -//----------------------------------------------------------------------------- -void Panel::MoveToFront(void) -{ - // FIXME: only use ipanel() as per src branch? - if (IsPopup()) - { - surface()->BringToFront(GetVPanel()); - } - else - { - ipanel()->MoveToFront(GetVPanel()); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Iterates up the hierarchy looking for a particular parent -//----------------------------------------------------------------------------- -bool Panel::HasParent(VPANEL potentialParent) -{ - if (!potentialParent) - return false; - - return ipanel()->HasParent(GetVPanel(), potentialParent); -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the index of a child panel by string name -// Output : int - -1 if no panel of that name is found -//----------------------------------------------------------------------------- -int Panel::FindChildIndexByName(const char *childName) -{ - for (int i = 0; i < GetChildCount(); i++) - { - Panel *pChild = GetChild(i); - if (!pChild) - continue; - - if (!stricmp(pChild->GetName(), childName)) - { - return i; - } - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds a child panel by string name -// Output : Panel * - NULL if no panel of that name is found -//----------------------------------------------------------------------------- -Panel *Panel::FindChildByName(const char *childName, bool recurseDown) -{ - for (int i = 0; i < GetChildCount(); i++) - { - Panel *pChild = GetChild(i); - if (!pChild) - continue; - - if (!V_stricmp(pChild->GetName(), childName)) - { - return pChild; - } - - if (recurseDown) - { - Panel *panel = pChild->FindChildByName(childName, recurseDown); - if ( panel ) - { - return panel; - } - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds a sibling panel by name -//----------------------------------------------------------------------------- -Panel *Panel::FindSiblingByName(const char *siblingName) -{ - if ( !GetVParent() ) - return NULL; - - int siblingCount = ipanel()->GetChildCount(GetVParent()); - for (int i = 0; i < siblingCount; i++) - { - VPANEL sibling = ipanel()->GetChild(GetVParent(), i); - Panel *panel = ipanel()->GetPanel(sibling, GetControlsModuleName()); - if (!stricmp(panel->GetName(), siblingName)) - { - return panel; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Dispatches immediately a message to the parent -//----------------------------------------------------------------------------- -void Panel::CallParentFunction(KeyValues *message) -{ - if (GetVParent()) - { - ipanel()->SendMessage(GetVParent(), message, GetVPanel()); - } - if (message) - { - message->deleteThis(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: if set to true, panel automatically frees itself when parent is deleted -//----------------------------------------------------------------------------- -void Panel::SetAutoDelete( bool state ) -{ - _flags.SetFlag( AUTODELETE_ENABLED, state ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool Panel::IsAutoDeleteSet() -{ - return _flags.IsFlagSet( AUTODELETE_ENABLED ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Just calls 'delete this' -//----------------------------------------------------------------------------- -void Panel::DeletePanel() -{ - // Avoid re-entrancy - _flags.SetFlag( MARKED_FOR_DELETION ); - _flags.ClearFlag( AUTODELETE_ENABLED ); - delete this; -} - -//----------------------------------------------------------------------------- -// Purpose: data accessor -//----------------------------------------------------------------------------- -HScheme Panel::GetScheme() -{ - if (m_iScheme) - { - return m_iScheme; // return our internal scheme - } - - if (GetVParent()) // recurse down the heirarchy - { - return ipanel()->GetScheme(GetVParent()); - } - - return scheme()->GetDefaultScheme(); -} - -//----------------------------------------------------------------------------- -// Purpose: set the scheme to render this panel with by name -//----------------------------------------------------------------------------- -void Panel::SetScheme(const char *tag) -{ - if (strlen(tag) > 0 && scheme()->GetScheme(tag)) // check the scheme exists - { - SetScheme(scheme()->GetScheme(tag)); - } -} - -//----------------------------------------------------------------------------- -// Purpose: set the scheme to render this panel with -//----------------------------------------------------------------------------- -void Panel::SetScheme(HScheme scheme) -{ - if (scheme != m_iScheme) - { - m_iScheme = scheme; - - // This will cause the new scheme to be applied at a later point -// InvalidateLayout( false, true ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: returns the char of this panels hotkey -//----------------------------------------------------------------------------- -Panel *Panel::HasHotkey(wchar_t key) -{ - return NULL; -} - -#if defined( VGUI_USEDRAGDROP ) -static vgui::PHandle g_DragDropCapture; -#endif // VGUI_USEDRAGDROP - -void Panel::InternalCursorMoved(int x, int y) -{ -#if defined( VGUI_USEDRAGDROP ) - if ( g_DragDropCapture.Get() ) - { - bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted; - - g_DragDropCapture->OnContinueDragging(); - - if ( started ) - { - bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE ); - if ( isEscapeKeyDown ) - { - g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1, true ); - } - return; - } - } -#endif // VGUI_USEDRAGDROP - - if ( !ShouldHandleInputMessage() ) - return; - - if ( IsCursorNone() ) - return; - - if ( !IsMouseInputEnabled() ) - { - return; - } - - if (IsBuildGroupEnabled()) - { - if ( _buildGroup->CursorMoved(x, y, this) ) - { - return; - } - } - - if (m_pTooltips) - { - if ( _tooltipText ) - { - m_pTooltips->SetText( _tooltipText ); - } - m_pTooltips->ShowTooltip(this); - } - - ScreenToLocal(x, y); - - OnCursorMoved(x, y); -} - -void Panel::InternalCursorEntered() -{ - if (IsCursorNone() || !IsMouseInputEnabled()) - return; - - if (IsBuildGroupEnabled()) - return; - - if (m_pTooltips) - { - m_pTooltips->ResetDelay(); - - if ( _tooltipText ) - { - m_pTooltips->SetText( _tooltipText ); - } - m_pTooltips->ShowTooltip(this); - } - - OnCursorEntered(); -} - -void Panel::InternalCursorExited() -{ - if (IsCursorNone() || !IsMouseInputEnabled()) - return; - - if (IsBuildGroupEnabled()) - return; - - if (m_pTooltips) - { - m_pTooltips->HideTooltip(); - } - - OnCursorExited(); -} - -bool Panel::IsChildOfSurfaceModalPanel() -{ - VPANEL appModalPanel = input()->GetAppModalSurface(); - if ( !appModalPanel ) - return true; - - if ( ipanel()->HasParent( GetVPanel(), appModalPanel ) ) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsChildOfModalSubTree() -{ - VPANEL subTree = input()->GetModalSubTree(); - if ( !subTree ) - return true; - - if ( HasParent( subTree ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if message is being subverted due to modal subtree logic -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -static bool ShouldHandleInputMessage( VPANEL p ) -{ - // If there is not modal subtree, then always handle the msg - if ( !input()->GetModalSubTree() ) - return true; - - // What state are we in? - bool bChildOfModal = false; - VPANEL subTree = input()->GetModalSubTree(); - if ( !subTree ) - { - bChildOfModal = true; - } - else if ( ipanel()->HasParent( p, subTree ) ) - { - bChildOfModal = true; - } - - if ( input()->ShouldModalSubTreeReceiveMessages() ) - return bChildOfModal; - - return !bChildOfModal; -} - -bool Panel::ShouldHandleInputMessage() -{ - return ::ShouldHandleInputMessage( GetVPanel() ); -} - -void Panel::InternalMousePressed(int code) -{ - long curtime = system()->GetTimeMillis(); - if ( IsTriplePressAllowed() ) - { - long elapsed = curtime - m_lLastDoublePressTime; - if ( elapsed < TRIPLE_PRESS_MSEC ) - { - InternalMouseTriplePressed( code ); - return; - } - } - - // The menu system passively watches for mouse released messages so it - // can clear any open menus if the release is somewhere other than on a menu - Menu::OnInternalMousePressed( this, (MouseCode)code ); - - if ( !ShouldHandleInputMessage() ) - return; - - if ( IsCursorNone() ) - return; - - if ( !IsMouseInputEnabled()) - { -#if defined( VGUI_USEDRAGDROP ) - DragDropStartDragging(); -#endif - return; - } - - if (IsBuildGroupEnabled()) - { - if ( _buildGroup->MousePressed((MouseCode)code, this) ) - { - return; - } - } - - Panel *pMouseHandler = m_hMouseEventHandler.Get(); - if ( pMouseHandler ) - { - pMouseHandler->OnMousePressed( (MouseCode)code ); - } - else - { - OnMousePressed( (MouseCode)code ); - } - -#if defined( VGUI_USEDRAGDROP ) - DragDropStartDragging(); -#endif -} - -void Panel::InternalMouseDoublePressed(int code) -{ - m_lLastDoublePressTime = system()->GetTimeMillis(); - - if ( !ShouldHandleInputMessage() ) - return; - - if ( IsCursorNone() ) - return; - - if ( !IsMouseInputEnabled()) - { - return; - } - - if (IsBuildGroupEnabled()) - { - if ( _buildGroup->MouseDoublePressed((MouseCode)code, this) ) - { - return; - } - } - - Panel *pMouseHandler = m_hMouseEventHandler.Get(); - if ( pMouseHandler ) - { - pMouseHandler->OnMouseDoublePressed( (MouseCode)code ); - } - else - { - OnMouseDoublePressed( (MouseCode)code ); - } -} - -#if defined( VGUI_USEDRAGDROP ) -void Panel::SetStartDragWhenMouseExitsPanel( bool state ) -{ - _flags.SetFlag( DRAG_REQUIRES_PANEL_EXIT, state ); -} - -bool Panel::IsStartDragWhenMouseExitsPanel() const -{ - return _flags.IsFlagSet( DRAG_REQUIRES_PANEL_EXIT ); -} -#endif // VGUI_USEDRAGDROP - -void Panel::SetTriplePressAllowed( bool state ) -{ - _flags.SetFlag( TRIPLE_PRESS_ALLOWED, state ); -} - -bool Panel::IsTriplePressAllowed() const -{ - return _flags.IsFlagSet( TRIPLE_PRESS_ALLOWED ); -} - -void Panel::InternalMouseTriplePressed( int code ) -{ - Assert( IsTriplePressAllowed() ); - m_lLastDoublePressTime = 0L; - - if ( !ShouldHandleInputMessage() ) - return; - - if ( IsCursorNone() ) - return; - - if ( !IsMouseInputEnabled()) - { -#if defined( VGUI_USEDRAGDROP ) - DragDropStartDragging(); -#endif - return; - } - - if (IsBuildGroupEnabled()) - { - return; - } - - OnMouseTriplePressed((MouseCode)code); -#if defined( VGUI_USEDRAGDROP ) - DragDropStartDragging(); -#endif -} - -void Panel::InternalMouseReleased(int code) -{ -#if defined( VGUI_USEDRAGDROP ) - if ( g_DragDropCapture.Get() ) - { - bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted; - g_DragDropCapture->OnFinishDragging( true, (MouseCode)code ); - if ( started ) - { - return; - } - } -#endif - - if ( !ShouldHandleInputMessage() ) - return; - - if ( IsCursorNone() ) - return; - - if ( !IsMouseInputEnabled()) - { - return; - } - - if (IsBuildGroupEnabled()) - { - if ( _buildGroup->MouseReleased((MouseCode)code, this) ) - { - return; - } - } - - OnMouseReleased((MouseCode)code); -} - -void Panel::InternalMouseWheeled(int delta) -{ - if (IsBuildGroupEnabled() || !IsMouseInputEnabled()) - { - return; - } - - if ( !ShouldHandleInputMessage() ) - return; - - OnMouseWheeled(delta); -} - -void Panel::InternalKeyCodePressed(int code) -{ - if ( !ShouldHandleInputMessage() ) - return; - - if (IsKeyBoardInputEnabled()) - { - OnKeyCodePressed((KeyCode)code); - } - else - { - CallParentFunction(new KeyValues("KeyCodePressed", "code", code)); - } -} - -#if defined( VGUI_USEKEYBINDINGMAPS ) -//----------------------------------------------------------------------------- -// Purpose: -// Input : *bindingName - -// keycode - -// modifiers - -//----------------------------------------------------------------------------- -void Panel::AddKeyBinding( char const *bindingName, int keycode, int modifiers ) -{ - PanelKeyBindingMap *map = LookupMapForBinding( bindingName ); - if ( !map ) - { - Assert( 0 ); - return; - } - - BoundKey_t kb; - kb.isbuiltin = false; - kb.bindingname = CopyString( bindingName ); - kb.keycode = keycode; - kb.modifiers = modifiers; - - map->boundkeys.AddToTail( kb ); -} - -KeyBindingMap_t *Panel::LookupBinding( char const *bindingName ) -{ - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - int c = map->entries.Count(); - for( int i = 0; i < c ; ++i ) - { - KeyBindingMap_t *binding = &map->entries[ i ]; - if ( !Q_stricmp( binding->bindingname, bindingName ) ) - return binding; - } - - map = map->baseMap; - } - - return NULL; -} - -PanelKeyBindingMap *Panel::LookupMapForBinding( char const *bindingName ) -{ - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - int c = map->entries.Count(); - for( int i = 0; i < c ; ++i ) - { - KeyBindingMap_t *binding = &map->entries[ i ]; - if ( !Q_stricmp( binding->bindingname, bindingName ) ) - return map; - } - - map = map->baseMap; - } - - return NULL; -} - -KeyBindingMap_t *Panel::LookupBindingByKeyCode( KeyCode code, int modifiers ) -{ - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - int c = map->boundkeys.Count(); - for( int i = 0; i < c ; ++i ) - { - BoundKey_t *kb = &map->boundkeys[ i ]; - if ( kb->keycode == code && kb->modifiers == modifiers ) - { - KeyBindingMap_t *binding = LookupBinding( kb->bindingname ); - Assert( binding ); - if ( binding ) - { - return binding; - } - } - } - - map = map->baseMap; - } - - return NULL; -} - -BoundKey_t *Panel::LookupDefaultKey( char const *bindingName ) -{ - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - int c = map->defaultkeys.Count(); - for( int i = 0; i < c ; ++i ) - { - BoundKey_t *kb = &map->defaultkeys[ i ]; - if ( !Q_stricmp( kb->bindingname, bindingName ) ) - { - return kb; - } - } - - map = map->baseMap; - } - return NULL; -} - -void Panel::LookupBoundKeys( char const *bindingName, CUtlVector< BoundKey_t * >& list ) -{ - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - int c = map->boundkeys.Count(); - for( int i = 0; i < c ; ++i ) - { - BoundKey_t *kb = &map->boundkeys[ i ]; - if ( !Q_stricmp( kb->bindingname, bindingName ) ) - { - list.AddToTail( kb ); - } - } - - map = map->baseMap; - } -} - -void Panel::RevertKeyBindingsToDefault() -{ - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - map->boundkeys.RemoveAll(); - map->boundkeys = map->defaultkeys; - - map = map->baseMap; - } -} - -void Panel::RemoveAllKeyBindings() -{ - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - map->boundkeys.RemoveAll(); - map = map->baseMap; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void Panel::ReloadKeyBindings() -{ - RevertKeyBindingsToDefault(); - LoadKeyBindingsForOnePanel( GetKeyBindingsContext(), this ); -} - -#define MAKE_STRING( x ) #x -#define KEY_NAME( str, disp ) { KEY_##str, MAKE_STRING( KEY_##str ), disp } - -struct KeyNames_t -{ - KeyCode code; - char const *string; - char const *displaystring; -}; - -static KeyNames_t g_KeyNames[] = -{ -KEY_NAME( NONE, "None" ), -KEY_NAME( 0, "0" ), -KEY_NAME( 1, "1" ), -KEY_NAME( 2, "2" ), -KEY_NAME( 3, "3" ), -KEY_NAME( 4, "4" ), -KEY_NAME( 5, "5" ), -KEY_NAME( 6, "6" ), -KEY_NAME( 7, "7" ), -KEY_NAME( 8, "8" ), -KEY_NAME( 9, "9" ), -KEY_NAME( A, "A" ), -KEY_NAME( B, "B" ), -KEY_NAME( C, "C" ), -KEY_NAME( D, "D" ), -KEY_NAME( E, "E" ), -KEY_NAME( F, "F" ), -KEY_NAME( G, "G" ), -KEY_NAME( H, "H" ), -KEY_NAME( I, "I" ), -KEY_NAME( J, "J" ), -KEY_NAME( K, "K" ), -KEY_NAME( L, "L" ), -KEY_NAME( M, "M" ), -KEY_NAME( N, "N" ), -KEY_NAME( O, "O" ), -KEY_NAME( P, "P" ), -KEY_NAME( Q, "Q" ), -KEY_NAME( R, "R" ), -KEY_NAME( S, "S" ), -KEY_NAME( T, "T" ), -KEY_NAME( U, "U" ), -KEY_NAME( V, "V" ), -KEY_NAME( W, "W" ), -KEY_NAME( X, "X" ), -KEY_NAME( Y, "Y" ), -KEY_NAME( Z, "Z" ), -KEY_NAME( PAD_0, "Key Pad 0" ), -KEY_NAME( PAD_1, "Key Pad 1" ), -KEY_NAME( PAD_2, "Key Pad 2" ), -KEY_NAME( PAD_3, "Key Pad 3" ), -KEY_NAME( PAD_4, "Key Pad 4" ), -KEY_NAME( PAD_5, "Key Pad 5" ), -KEY_NAME( PAD_6, "Key Pad 6" ), -KEY_NAME( PAD_7, "Key Pad 7" ), -KEY_NAME( PAD_8, "Key Pad 8" ), -KEY_NAME( PAD_9, "Key Pad 9" ), -KEY_NAME( PAD_DIVIDE, "Key Pad /" ), -KEY_NAME( PAD_MULTIPLY, "Key Pad *" ), -KEY_NAME( PAD_MINUS, "Key Pad -" ), -KEY_NAME( PAD_PLUS, "Key Pad +" ), -KEY_NAME( PAD_ENTER, "Key Pad Enter" ), -KEY_NAME( PAD_DECIMAL, "Key Pad ." ), -KEY_NAME( LBRACKET, "[" ), -KEY_NAME( RBRACKET, "]" ), -KEY_NAME( SEMICOLON, "," ), -KEY_NAME( APOSTROPHE, "'" ), -KEY_NAME( BACKQUOTE, "`" ), -KEY_NAME( COMMA, "," ), -KEY_NAME( PERIOD, "." ), -KEY_NAME( SLASH, "/" ), -KEY_NAME( BACKSLASH, "\\" ), -KEY_NAME( MINUS, "-" ), -KEY_NAME( EQUAL, "=" ), -KEY_NAME( ENTER, "Enter" ), -KEY_NAME( SPACE, "Space" ), -KEY_NAME( BACKSPACE, "Backspace" ), -KEY_NAME( TAB, "Tab" ), -KEY_NAME( CAPSLOCK, "Caps Lock" ), -KEY_NAME( NUMLOCK, "Num Lock" ), -KEY_NAME( ESCAPE, "Escape" ), -KEY_NAME( SCROLLLOCK, "Scroll Lock" ), -KEY_NAME( INSERT, "Ins" ), -KEY_NAME( DELETE, "Del" ), -KEY_NAME( HOME, "Home" ), -KEY_NAME( END, "End" ), -KEY_NAME( PAGEUP, "PgUp" ), -KEY_NAME( PAGEDOWN, "PgDn" ), -KEY_NAME( BREAK, "Break" ), -KEY_NAME( LSHIFT, "Shift" ), -KEY_NAME( RSHIFT, "Shift" ), -KEY_NAME( LALT, "Alt" ), -KEY_NAME( RALT, "Alt" ), -KEY_NAME( LCONTROL, "Ctrl" ), -KEY_NAME( RCONTROL, "Ctrl" ), -KEY_NAME( LWIN, "Windows" ), -KEY_NAME( RWIN, "Windows" ), -KEY_NAME( APP, "App" ), -KEY_NAME( UP, "Up" ), -KEY_NAME( LEFT, "Left" ), -KEY_NAME( DOWN, "Down" ), -KEY_NAME( RIGHT, "Right" ), -KEY_NAME( F1, "F1" ), -KEY_NAME( F2, "F2" ), -KEY_NAME( F3, "F3" ), -KEY_NAME( F4, "F4" ), -KEY_NAME( F5, "F5" ), -KEY_NAME( F6, "F6" ), -KEY_NAME( F7, "F7" ), -KEY_NAME( F8, "F8" ), -KEY_NAME( F9, "F9" ), -KEY_NAME( F10, "F10" ), -KEY_NAME( F11, "F11" ), -KEY_NAME( F12, "F12" ), -KEY_NAME( CAPSLOCKTOGGLE, "Caps Lock Toggle" ), -KEY_NAME( NUMLOCKTOGGLE, "Num Lock Toggle" ), -KEY_NAME( SCROLLLOCKTOGGLE, "Scroll Lock Toggle" ), -}; - -char const *Panel::KeyCodeToString( KeyCode code ) -{ - int c = ARRAYSIZE( g_KeyNames ); - for ( int i = 0; i < c ; ++i ) - { - if ( g_KeyNames[ i ].code == code ) - return g_KeyNames[ i ].string; - } - - return ""; -} - -wchar_t const *Panel::KeyCodeToDisplayString( KeyCode code ) -{ - int c = ARRAYSIZE( g_KeyNames ); - for ( int i = 0; i < c ; ++i ) - { - if ( g_KeyNames[ i ].code == code ) - { - char const *str = g_KeyNames[ i ].displaystring; - wchar_t *wstr = g_pVGuiLocalize->Find( str ); - if ( wstr ) - { - return wstr; - } - - static wchar_t buf[ 64 ]; - g_pVGuiLocalize->ConvertANSIToUnicode( str, buf, sizeof( buf ) ); - return buf; - } - } - - return L""; -} - -static void AddModifierToString( char const *modifiername, char *buf, size_t bufsize ) -{ - char add[ 32 ]; - if ( Q_strlen( buf ) > 0 ) - { - Q_snprintf( add, sizeof( add ), "+%s", modifiername ); - } - else - { - Q_strncpy( add, modifiername, sizeof( add ) ); - } - - Q_strncat( buf, add, bufsize, COPY_ALL_CHARACTERS ); - -} - -wchar_t const *Panel::KeyCodeModifiersToDisplayString( KeyCode code, int modifiers ) -{ - char sz[ 256 ]; - sz[ 0 ] = 0; - - if ( modifiers & MODIFIER_SHIFT ) - { - AddModifierToString( "Shift", sz, sizeof( sz ) ); - } - if ( modifiers & MODIFIER_CONTROL ) - { - AddModifierToString( "Ctrl", sz, sizeof( sz ) ); - } - if ( modifiers & MODIFIER_ALT ) - { - AddModifierToString( "Alt", sz, sizeof( sz ) ); - } - - if ( Q_strlen( sz ) > 0 ) - { - Q_strncat( sz, "+", sizeof( sz ), COPY_ALL_CHARACTERS ); - } - - static wchar_t unicode[ 256 ]; - V_swprintf_safe( unicode, L"%S%s", sz, Panel::KeyCodeToDisplayString( (KeyCode)code ) ); - return unicode; -} - -KeyCode Panel::StringToKeyCode( char const *str ) -{ - int c = ARRAYSIZE( g_KeyNames ); - for ( int i = 0; i < c ; ++i ) - { - if ( !Q_stricmp( str, g_KeyNames[ i ].string ) ) - return g_KeyNames[ i ].code; - } - - return KEY_NONE; -} - -static void WriteKeyBindingToBuffer( CUtlBuffer& buf, int level, const BoundKey_t& binding ) -{ - BufPrint( buf, level, "\"keycode\"\t\"%s\"\n", Panel::KeyCodeToString( (KeyCode)binding.keycode ) ); - if ( binding.modifiers & MODIFIER_SHIFT ) - { - BufPrint( buf, level, "\"shift\"\t\"1\"\n" ); - } - if ( binding.modifiers & MODIFIER_CONTROL ) - { - BufPrint( buf, level, "\"ctrl\"\t\"1\"\n" ); - } - if ( binding.modifiers & MODIFIER_ALT ) - { - BufPrint( buf, level, "\"alt\"\t\"1\"\n" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -// *pathID - -//----------------------------------------------------------------------------- -void Panel::SaveKeyBindingsToBuffer( int level, CUtlBuffer& buf ) -{ - Assert( IsValidKeyBindingsContext() ); - - Assert( buf.IsText() ); - - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - int c = map->boundkeys.Count(); - for( int i = 0; i < c ; ++i ) - { - const BoundKey_t& binding = map->boundkeys[ i ]; - - // Spew to file - BufPrint( buf, level, "\"%s\"\n", binding.bindingname ); - BufPrint( buf, level, "{\n" ); - - WriteKeyBindingToBuffer( buf, level + 1, binding ); - - BufPrint( buf, level, "}\n" ); - } - - map = map->baseMap; - } -} - -bool Panel::ParseKeyBindings( KeyValues *kv ) -{ - Assert( IsValidKeyBindingsContext() ); - if ( !IsValidKeyBindingsContext() ) - return false; - - // To have KB the panel must have a name - Assert( GetName() && GetName()[ 0 ] ); - if ( !GetName() || !GetName()[ 0 ] ) - return false; - - bool success = false; - - g_KBMgr.AddPanelToContext( GetKeyBindingsContext(), this ); - - RemoveAllKeyBindings(); - - // Walk through bindings - for ( KeyValues *binding = kv->GetFirstSubKey(); binding != NULL; binding = binding->GetNextKey() ) - { - char const *bindingName = binding->GetName(); - if ( !bindingName || !bindingName[ 0 ] ) - continue; - - KeyBindingMap_t *b = LookupBinding( bindingName ); - if ( b ) - { - success = true; - const char *keycode = binding->GetString( "keycode", "" ); - int modifiers = 0; - if ( binding->GetInt( "shift", 0 ) != 0 ) - { - modifiers |= MODIFIER_SHIFT; - } - if ( binding->GetInt( "ctrl", 0 ) != 0 ) - { - modifiers |= MODIFIER_CONTROL; - } - if ( binding->GetInt( "alt", 0 ) != 0 ) - { - modifiers |= MODIFIER_ALT; - } - - KeyBindingMap_t *bound = LookupBindingByKeyCode( StringToKeyCode( keycode ), modifiers ); - if ( !bound ) - { - AddKeyBinding( bindingName, StringToKeyCode( keycode ), modifiers ); - } - } - else - { - Warning( "KeyBinding for panel '%s' contained unknown binding '%s'\n", GetName() ? GetName() : "???", bindingName ); - } - } - - // Now for each binding which is currently "unbound" to any key, use the default binding - PanelKeyBindingMap *map = GetKBMap(); - while( map ) - { - int c = map->entries.Count(); - for( int i = 0; i < c ; ++i ) - { - KeyBindingMap_t *binding = &map->entries[ i ]; - - // See if there is a bound key - CUtlVector< BoundKey_t * > list; - LookupBoundKeys( binding->bindingname, list ); - if ( list.Count() == 0 ) - { - // Assign the default binding to this key - BoundKey_t *defaultKey = LookupDefaultKey( binding->bindingname ); - if ( defaultKey ) - { - KeyBindingMap_t *alreadyBound = LookupBindingByKeyCode( (KeyCode)defaultKey->keycode, defaultKey->modifiers ); - if ( alreadyBound ) - { - Warning( "No binding for '%s', defautl key already bound to '%s'\n", binding->bindingname, alreadyBound->bindingname ); - } - else - { - AddKeyBinding( defaultKey->bindingname, defaultKey->keycode, defaultKey->modifiers ); - } - } - } - } - - map = map->baseMap; - } - - return success; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : handle - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void Panel::SetKeyBindingsContext( KeyBindingContextHandle_t handle ) -{ - Assert( !IsValidKeyBindingsContext() || handle == GetKeyBindingsContext() ); - g_KBMgr.AddPanelToContext( handle, this ); - m_hKeyBindingsContext = handle; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : KeyBindingContextHandle_t -//----------------------------------------------------------------------------- -KeyBindingContextHandle_t Panel::GetKeyBindingsContext() const -{ - return m_hKeyBindingsContext; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsValidKeyBindingsContext() const -{ - return GetKeyBindingsContext() != INVALID_KEYBINDINGCONTEXT_HANDLE; -} - -char const *Panel::GetKeyBindingsFile() const -{ - Assert( IsValidKeyBindingsContext() ); - return g_KBMgr.GetKeyBindingsFile( GetKeyBindingsContext() ); -} - -char const *Panel::GetKeyBindingsFilePathID() const -{ - Assert( IsValidKeyBindingsContext() ); - return g_KBMgr.GetKeyBindingsFilePathID( GetKeyBindingsContext() ); -} - -void Panel::EditKeyBindings() -{ - Assert( 0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Set this to false to disallow IsKeyRebound chaining to GetParent() Panels... -// Input : state - -//----------------------------------------------------------------------------- -void Panel::SetAllowKeyBindingChainToParent( bool state ) -{ - _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT, state ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsKeyBindingChainToParentAllowed() const -{ - return _flags.IsFlagSet( ALLOW_CHAIN_KEYBINDING_TO_PARENT ); -} - -bool Panel::IsKeyOverridden( KeyCode code, int modifiers ) -{ - // By default assume all keys should pass through binding system - return false; -} - -bool Panel::IsKeyRebound( KeyCode code, int modifiers ) -{ - if ( IsKeyBoardInputEnabled() ) - { - KeyBindingMap_t* binding = LookupBindingByKeyCode( code, modifiers ); - // Only dispatch if we're part of the current modal subtree - if ( binding && IsChildOfSurfaceModalPanel() ) - { - // Found match, post message to panel - if ( binding->func ) - { - // dispatch the func - (this->*binding->func)(); - } - else - { - Assert( 0 ); - } - - if ( !binding->passive ) - { - // Exit this function... - return true; - } - } - } - - // Chain to parent - Panel* pParent = GetParent(); - if ( IsKeyBindingChainToParentAllowed() && pParent && !IsKeyOverridden( code, modifiers ) ) - return pParent->IsKeyRebound( code, modifiers ); - - // No suitable binding found - return false; -} - -static bool s_bSuppressRebindChecks = false; -#endif // VGUI_USEKEYBINDINGMAPS - -void Panel::InternalKeyCodeTyped( int code ) -{ - if ( !ShouldHandleInputMessage() ) - { - input()->OnKeyCodeUnhandled( code ); - return; - } - - if (IsKeyBoardInputEnabled()) - { - 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; - } - - // Things in build mode don't have accelerators - if (IsBuildGroupEnabled()) - { - _buildGroup->KeyCodeTyped((KeyCode)code, this); - return; - } - - if ( !s_bSuppressRebindChecks && IsKeyRebound( (KeyCode)code, modifiers ) ) - { - return; - } - - bool oldVal = s_bSuppressRebindChecks; - s_bSuppressRebindChecks = true; - OnKeyCodeTyped((KeyCode)code); - s_bSuppressRebindChecks = oldVal; - } - else - { - if ( GetVPanel() == surface()->GetEmbeddedPanel() ) - { - input()->OnKeyCodeUnhandled( code ); - } - CallParentFunction(new KeyValues("KeyCodeTyped", "code", code)); - } -} - -void Panel::InternalKeyTyped(int unichar) -{ - if ( !ShouldHandleInputMessage() ) - return; - - if (IsKeyBoardInputEnabled()) - { - if ( IsBuildGroupEnabled() ) - { - if ( _buildGroup->KeyTyped( (wchar_t)unichar, this ) ) - { - return; - } - } - - OnKeyTyped((wchar_t)unichar); - } - else - { - CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar)); - } -} - -void Panel::InternalKeyCodeReleased(int code) -{ - if ( !ShouldHandleInputMessage() ) - return; - - if (IsKeyBoardInputEnabled()) - { - if (IsBuildGroupEnabled()) - { - if ( _buildGroup->KeyCodeReleased((KeyCode)code, this) ) - { - return; - } - } - - OnKeyCodeReleased((KeyCode)code); - } - else - { - CallParentFunction(new KeyValues("KeyCodeReleased", "code", code)); - } -} - -void Panel::InternalKeyFocusTicked() -{ - if (IsBuildGroupEnabled()) - return; - - OnKeyFocusTicked(); -} - -void Panel::InternalMouseFocusTicked() -{ - if (IsBuildGroupEnabled()) - { - // must repaint so the numbers will be accurate - if (_buildGroup->HasRulersOn()) - { - PaintTraverse(true); - } - return; - } - - // update cursor - InternalSetCursor(); - OnMouseFocusTicked(); -} - - -void Panel::InternalSetCursor() -{ - bool visible = IsVisible(); - - if (visible) - { -#if defined( VGUI_USEDRAGDROP ) - // Drag drop is overriding cursor? - if ( m_pDragDrop->m_bDragging || - g_DragDropCapture.Get() != NULL ) - return; -#endif - // chain up and make sure all our parents are also visible - VPANEL p = GetVParent(); - while (p) - { - visible &= ipanel()->IsVisible(p); - p = ipanel()->GetParent(p); - } - - // only change the cursor if this panel is visible, and if its part of the main VGUI tree - if (visible && HasParent(surface()->GetEmbeddedPanel())) - { - HCursor cursor = GetCursor(); - - if (IsBuildGroupEnabled()) - { - cursor = _buildGroup->GetCursor(this); - } - - if (input()->GetCursorOveride()) - { - cursor = input()->GetCursorOveride(); - } - - surface()->SetCursor(cursor); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame the panel is visible, designed to be overridden -//----------------------------------------------------------------------------- -void Panel::OnThink() -{ -#if defined( VGUI_USEDRAGDROP ) - if ( IsPC() && - m_pDragDrop->m_bDragEnabled && - m_pDragDrop->m_bDragging && - m_pDragDrop->m_bDragStarted ) - { - bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE ); - if ( isEscapeKeyDown ) - { - OnContinueDragging(); - OnFinishDragging( true, (MouseCode)-1, true ); - return; - } - - if ( m_pDragDrop->m_hCurrentDrop != 0 ) - { - if ( !input()->IsMouseDown( MOUSE_LEFT ) ) - { - OnContinueDragging(); - OnFinishDragging( true, (MouseCode)-1 ); - return; - } - - // allow the cursor to change based upon things like changing keystate, etc. - surface()->SetCursor( m_pDragDrop->m_hCurrentDrop->GetDropCursor( m_pDragDrop->m_DragData ) ); - - if ( !m_pDragDrop->m_bDropMenuShown ) - { - // See if the hover time has gotten larger - float hoverSeconds = ( system()->GetTimeMillis() - m_pDragDrop->m_lDropHoverTime ) * 0.001f; - DragDrop_t *dropInfo = m_pDragDrop->m_hCurrentDrop->GetDragDropInfo(); - - if ( dropInfo->m_flHoverContextTime != 0.0f ) - { - if ( hoverSeconds >= dropInfo->m_flHoverContextTime ) - { - m_pDragDrop->m_bDropMenuShown = true; - - CUtlVector< KeyValues * > data; - - GetDragData( data ); - - int x, y; - input()->GetCursorPos( x, y ); - - if ( m_pDragDrop->m_hDropContextMenu.Get() ) - { - delete m_pDragDrop->m_hDropContextMenu.Get(); - } - - Menu *menu = new Menu( m_pDragDrop->m_hCurrentDrop.Get(), "DropContext" ); - - bool useMenu = m_pDragDrop->m_hCurrentDrop->GetDropContextMenu( menu, data ); - if ( useMenu ) - { - m_pDragDrop->m_hDropContextMenu = menu; - - menu->SetPos( x, y ); - menu->SetVisible( true ); - menu->MakePopup(); - surface()->MovePopupToFront( menu->GetVPanel() ); - if ( menu->GetItemCount() > 0 ) - { - int id = menu->GetMenuID( 0 ); - menu->SetCurrentlyHighlightedItem( id ); - MenuItem *item = menu->GetMenuItem( id ); - item->SetArmed( true ); - } - } - else - { - delete menu; - } - - m_pDragDrop->m_hCurrentDrop->OnDropContextHoverShow( data ); - } - } - } - } - } -#endif -} - -// input messages handlers (designed for override) -void Panel::OnCursorMoved(int x, int y) -{ - if( ParentNeedsCursorMoveEvents() ) - { - // figure out x and y in parent space - int thisX, thisY; - ipanel()->GetPos( GetVPanel(), thisX, thisY ); - CallParentFunction( new KeyValues( "OnCursorMoved", "x", x + thisX, "y", y + thisY ) ); - } -} - -void Panel::OnCursorEntered() -{ -} - -void Panel::OnCursorExited() -{ -} - -void Panel::OnMousePressed(MouseCode code) -{ -} - -void Panel::OnMouseDoublePressed(MouseCode code) -{ -} - -void Panel::OnMouseTriplePressed(MouseCode code) -{ -} - -void Panel::OnMouseReleased(MouseCode code) -{ -} - -void Panel::OnMouseWheeled(int delta) -{ - CallParentFunction(new KeyValues("MouseWheeled", "delta", delta)); -} - -// base implementation forwards Key messages to the Panel's parent - override to 'swallow' the input -void Panel::OnKeyCodePressed(KeyCode code) -{ - static ConVarRef vgui_nav_lock( "vgui_nav_lock" ); - - bool handled = false; - switch( GetBaseButtonCode( code ) ) - { - case KEY_XBUTTON_UP: - case KEY_XSTICK1_UP: - case KEY_XSTICK2_UP: - case KEY_UP: - if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateUp() ) - { - vgui_nav_lock.SetValue( 1 ); - vgui::surface()->PlaySound( "UI/menu_focus.wav" ); - handled = true; - } - break; - case KEY_XBUTTON_DOWN: - case KEY_XSTICK1_DOWN: - case KEY_XSTICK2_DOWN: - case KEY_DOWN: - if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateDown() ) - { - vgui_nav_lock.SetValue( 1 ); - vgui::surface()->PlaySound( "UI/menu_focus.wav" ); - handled = true; - } - break; - case KEY_XBUTTON_LEFT: - case KEY_XSTICK1_LEFT: - case KEY_XSTICK2_LEFT: - case KEY_LEFT: - if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateLeft() ) - { - vgui_nav_lock.SetValue( 1 ); - vgui::surface()->PlaySound( "UI/menu_focus.wav" ); - handled = true; - } - break; - case KEY_XBUTTON_RIGHT: - case KEY_XSTICK1_RIGHT: - case KEY_XSTICK2_RIGHT: - case KEY_RIGHT: - if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateRight() ) - { - vgui_nav_lock.SetValue( 1 ); - vgui::surface()->PlaySound( "UI/menu_focus.wav" ); - handled = true; - } - break; - case KEY_XBUTTON_B: - if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateBack() ) - { - vgui_nav_lock.SetValue( 1 ); - vgui::surface()->PlaySound( "UI/menu_focus.wav" ); - handled = true; - } - break; - } - - if( !handled && !m_PassUnhandledInput ) - return; - - CallParentFunction(new KeyValues("KeyCodePressed", "code", code)); -} - -void Panel::OnKeyCodeTyped(KeyCode keycode) -{ - vgui::KeyCode code = GetBaseButtonCode( keycode ); - - // handle focus change - if ( IsX360() || IsConsoleStylePanel() ) - { - // eat these typed codes, will get handled in OnKeyCodePressed - switch ( code ) - { - case KEY_XBUTTON_UP: - case KEY_XSTICK1_UP: - case KEY_XSTICK2_UP: - case KEY_XBUTTON_DOWN: - case KEY_XSTICK1_DOWN: - case KEY_XSTICK2_DOWN: - case KEY_XBUTTON_LEFT: - case KEY_XSTICK1_LEFT: - case KEY_XSTICK2_LEFT: - case KEY_XBUTTON_RIGHT: - case KEY_XSTICK1_RIGHT: - case KEY_XSTICK2_RIGHT: - case KEY_XBUTTON_A: - case KEY_XBUTTON_B: - case KEY_XBUTTON_X: - case KEY_XBUTTON_Y: - case KEY_XBUTTON_LEFT_SHOULDER: - case KEY_XBUTTON_RIGHT_SHOULDER: - case KEY_XBUTTON_BACK: - case KEY_XBUTTON_START: - case KEY_XBUTTON_STICK1: - case KEY_XBUTTON_STICK2: - case KEY_XBUTTON_LTRIGGER: - case KEY_XBUTTON_RTRIGGER: - - case KEY_UP: - case KEY_DOWN: - case KEY_LEFT: - case KEY_RIGHT: - return; - } - - // legacy handling - need to re-enable for older apps? - /* - if ( code == KEY_XSTICK1_RIGHT || code == KEY_XBUTTON_RIGHT ) - { - RequestFocusNext(); - return; - } - else if ( code == KEY_XSTICK1_LEFT || code == KEY_XBUTTON_LEFT ) - { - RequestFocusPrev(); - return; - } - */ - } - - if (code == KEY_TAB) - { - bool bShiftDown = input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT); - - if ( IsConsoleStylePanel() ) - { - if ( bShiftDown ) - { - NavigateUp(); - } - else - { - NavigateDown(); - } - } - else - { - // if shift is down goto previous tab position, otherwise goto next - if ( bShiftDown ) - { - RequestFocusPrev(); - } - else - { - RequestFocusNext(); - } - } - } - else - { - // forward up - if ( GetVPanel() == surface()->GetEmbeddedPanel() ) - { - input()->OnKeyCodeUnhandled( keycode ); - } - CallParentFunction(new KeyValues("KeyCodeTyped", "code", keycode)); - } -} - -void Panel::OnKeyTyped(wchar_t unichar) -{ - CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar)); -} - -void Panel::OnKeyCodeReleased(KeyCode code) -{ - CallParentFunction(new KeyValues("KeyCodeReleased", "code", code)); -} - -void Panel::OnKeyFocusTicked() -{ - CallParentFunction(new KeyValues("KeyFocusTicked")); -} - -void Panel::OnMouseFocusTicked() -{ - CallParentFunction(new KeyValues("OnMouseFocusTicked")); -} - -bool Panel::IsWithin(int x,int y) -{ - // check against our clip rect - int clipRect[4]; - ipanel()->GetClipRect(GetVPanel(), clipRect[0], clipRect[1], clipRect[2], clipRect[3]); - - if (x < clipRect[0]) - { - return false; - } - - if (y < clipRect[1]) - { - return false; - } - - if (x >= clipRect[2]) - { - return false; - } - - if (y >= clipRect[3]) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: determines which is the topmost panel under the coordinates (x, y) -//----------------------------------------------------------------------------- -VPANEL Panel::IsWithinTraverse(int x, int y, bool traversePopups) -{ - // if this one is not visible, its children won't be either - // also if it doesn't want mouse input its children can't get it either - if (!IsVisible() || !IsMouseInputEnabled()) - return NULL; - - if (traversePopups) - { - // check popups first - int i; - CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() ); - int childCount = children.Count(); - for (i = childCount - 1; i >= 0; i--) - { - VPANEL panel = children[ i ]; - if (ipanel()->IsPopup(panel)) - { - panel = ipanel()->IsWithinTraverse(panel, x, y, true); - if (panel != null) - { - return panel; - } - } - } - - // check children recursive, if you find one, just return first one - // this checks in backwards order so the last child drawn for this panel is chosen which - // coincides to how it would be visibly displayed - for (i = childCount - 1; i >= 0; i--) - { - VPANEL panel = children[ i ]; - // we've already checked popups so ignore - if (!ipanel()->IsPopup(panel)) - { - panel = ipanel()->IsWithinTraverse(panel, x, y, true); - if (panel != 0) - { - return panel; - } - } - } - - // check ourself - if ( !IsMouseInputDisabledForThisPanel() && IsWithin(x, y) ) - { - return GetVPanel(); - } - } - else - { - // since we're not checking popups, it must be within us, so we can check ourself first - if (IsWithin(x, y)) - { - // check children recursive, if you find one, just return first one - // this checks in backwards order so the last child drawn for this panel is chosen which - // coincides to how it would be visibly displayed - CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() ); - int childCount = children.Count(); - for (int i = childCount - 1; i >= 0; i--) - { - VPANEL panel = children[ i ]; - // ignore popups - if (!ipanel()->IsPopup(panel)) - { - panel = ipanel()->IsWithinTraverse(panel, x, y, false); - if (panel != 0) - { - return panel; - } - } - } - - // not a child, must be us - if ( !IsMouseInputDisabledForThisPanel() ) - return GetVPanel(); - } - } - - return NULL; -} - -void Panel::LocalToScreen(int& x,int& y) -{ - int px, py; - ipanel()->GetAbsPos(GetVPanel(), px, py); - - x = x + px; - y = y + py; -} - -void Panel::ScreenToLocal(int& x,int& y) -{ - int px, py; - ipanel()->GetAbsPos(GetVPanel(), px, py); - - x = x - px; - y = y - py; -} - -void Panel::ParentLocalToScreen(int &x, int &y) -{ - int px, py; - ipanel()->GetAbsPos(GetVParent(), px, py); - - x = x + px; - y = y + py; -} - -void Panel::MakePopup(bool showTaskbarIcon,bool disabled) -{ - surface()->CreatePopup(GetVPanel(), false, showTaskbarIcon,disabled); -} - -void Panel::SetCursor(HCursor cursor) -{ - _cursor = cursor; -} - -HCursor Panel::GetCursor() -{ - return _cursor; -} - -void Panel::SetCursorAlwaysVisible( bool visible ) -{ - surface()->SetCursorAlwaysVisible( visible ); -} - -void Panel::SetMinimumSize(int wide,int tall) -{ - ipanel()->SetMinimumSize(GetVPanel(), wide, tall); -} - -void Panel::GetMinimumSize(int& wide,int &tall) -{ - ipanel()->GetMinimumSize(GetVPanel(), wide, tall); -} - -bool Panel::IsBuildModeEditable() -{ - return true; -} - -void Panel::SetBuildModeEditable(bool state) -{ - if (state) - { - _buildModeFlags |= BUILDMODE_EDITABLE; - } - else - { - _buildModeFlags &= ~BUILDMODE_EDITABLE; - } -} - -//----------------------------------------------------------------------------- -// Purpose: data accessor -//----------------------------------------------------------------------------- -bool Panel::IsBuildModeDeletable() -{ - return (_buildModeFlags & BUILDMODE_DELETABLE); -} - -//----------------------------------------------------------------------------- -// Purpose: data accessor -//----------------------------------------------------------------------------- -void Panel::SetBuildModeDeletable(bool state) -{ - if (state) - { - _buildModeFlags |= BUILDMODE_DELETABLE; - } - else - { - _buildModeFlags &= ~BUILDMODE_DELETABLE; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool Panel::IsBuildModeActive() -{ - return _buildGroup ? _buildGroup->IsEnabled() : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::GetClipRect(int& x0,int& y0,int& x1,int& y1) -{ - ipanel()->GetClipRect(GetVPanel(), x0, y0, x1, y1); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int Panel::GetChildCount() -{ - if (ipanel()) - { - return ipanel()->GetChildCount(GetVPanel()); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: returns a child by the specified index -//----------------------------------------------------------------------------- -Panel *Panel::GetChild(int index) -{ - // get the child and cast it to a panel - // this assumes that the child is from the same module as the this (precondition) - return ipanel()->GetPanel(ipanel()->GetChild(GetVPanel(), index), GetControlsModuleName()); -} - -CUtlVector< VPANEL > &Panel::GetChildren() -{ - return ipanel()->GetChildren(GetVPanel()); -} - -//----------------------------------------------------------------------------- -// Purpose: moves the key focus back -//----------------------------------------------------------------------------- -bool Panel::RequestFocusPrev(VPANEL panel) -{ - // chain to parent - if (GetVParent()) - { - return ipanel()->RequestFocusPrev(GetVParent(), GetVPanel()); - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool Panel::RequestFocusNext(VPANEL panel) -{ - // chain to parent - if (GetVParent()) - { - return ipanel()->RequestFocusNext(GetVParent(), GetVPanel()); - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the panel to have the current sub focus -// Input : direction - the direction in which focus travelled to arrive at this panel; forward = 1, back = -1 -//----------------------------------------------------------------------------- -void Panel::RequestFocus(int direction) -{ - // NOTE: This doesn't make any sense if we don't have keyboard input enabled - Assert( ( IsX360() || IsConsoleStylePanel() ) || IsKeyBoardInputEnabled() ); - // ivgui()->DPrintf2("RequestFocus(%s, %s)\n", GetName(), GetClassName()); - OnRequestFocus(GetVPanel(), NULL); -} - -//----------------------------------------------------------------------------- -// Purpose: Called after a panel requests focus to fix up the whole chain -//----------------------------------------------------------------------------- -void Panel::OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel) -{ - CallParentFunction(new KeyValues("OnRequestFocus", "subFocus", subFocus, "defaultPanel", defaultPanel)); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -VPANEL Panel::GetCurrentKeyFocus() -{ - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the panel has focus -//----------------------------------------------------------------------------- -bool Panel::HasFocus() -{ - if (input()->GetFocus() == GetVPanel()) - { - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetTabPosition(int position) -{ - _tabPosition = position; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int Panel::GetTabPosition() -{ - return _tabPosition; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::InternalFocusChanged(bool lost) -{ - /* - //if focus is gained tell the focusNavGroup about it so its current can be correct - if( (!lost) && (_focusNavGroup!=null) ) - { - _focusNavGroup->setCurrentPanel(this); - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: Called when a panel loses it's mouse capture -//----------------------------------------------------------------------------- -void Panel::OnMouseCaptureLost() -{ - if (m_pTooltips) - { - m_pTooltips->ResetDelay(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::AddActionSignalTarget(Panel *messageTarget) -{ - HPanel target = ivgui()->PanelToHandle(messageTarget->GetVPanel()); - if (!_actionSignalTargetDar.HasElement(target)) - { - _actionSignalTargetDar.AddElement(target); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::AddActionSignalTarget(VPANEL messageTarget) -{ - HPanel target = ivgui()->PanelToHandle(messageTarget); - if (!_actionSignalTargetDar.HasElement(target)) - { - _actionSignalTargetDar.AddElement(target); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::RemoveActionSignalTarget(Panel *oldTarget) -{ - _actionSignalTargetDar.RemoveElement(ivgui()->PanelToHandle(oldTarget->GetVPanel())); -} - -//----------------------------------------------------------------------------- -// Purpose: Sends a message to all the panels that have requested action signals -//----------------------------------------------------------------------------- -void Panel::PostActionSignal( KeyValues *message ) -{ - if ( m_bIsSilent != true ) - { - // add who it was from the message - message->SetPtr("panel", this); - int i; - for (i = _actionSignalTargetDar.GetCount() - 1; i > 0; i--) - { - VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]); - if (panel) - { - ivgui()->PostMessage(panel, message->MakeCopy(), GetVPanel()); - } - } - - // do this so we can save on one MakeCopy() call - if (i == 0) - { - VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]); - if (panel) - { - ivgui()->PostMessage(panel, message, GetVPanel()); - return; - } - } - } - message->deleteThis(); -} - -void Panel::SetBorder(IBorder *border) -{ - _border = border; - - if (border) - { - int x, y, x2, y2; - border->GetInset(x, y, x2, y2); - ipanel()->SetInset(GetVPanel(), x, y, x2, y2); - - // update our background type based on the bord - SetPaintBackgroundType(border->GetBackgroundType()); - } - else - { - ipanel()->SetInset(GetVPanel(), 0, 0, 0, 0); - } -} - -IBorder *Panel::GetBorder() -{ - return _border; -} - - -void Panel::SetPaintBorderEnabled(bool state) -{ - _flags.SetFlag( PAINT_BORDER_ENABLED, state ); -} - -void Panel::SetPaintBackgroundEnabled(bool state) -{ - _flags.SetFlag( PAINT_BACKGROUND_ENABLED, state ); -} - -void Panel::SetPaintBackgroundType( int type ) -{ - // HACK only 0 through 2 supported for now - m_nPaintBackgroundType = clamp( type, 0, 2 ); -} - -void Panel::SetPaintEnabled(bool state) -{ - _flags.SetFlag( PAINT_ENABLED, state ); -} - -void Panel::SetPostChildPaintEnabled(bool state) -{ - _flags.SetFlag( POST_CHILD_PAINT_ENABLED, state ); -} - -void Panel::GetInset(int& left,int& top,int& right,int& bottom) -{ - ipanel()->GetInset(GetVPanel(), left, top, right, bottom); -} - -void Panel::GetPaintSize(int& wide,int& tall) -{ - GetSize(wide, tall); - if (_border != null) - { - int left,top,right,bottom; - _border->GetInset(left,top,right,bottom); - - wide -= (left+right); - tall -= (top+bottom); - } -} - -int Panel::GetWide() -{ - int wide, tall; - ipanel()->GetSize(GetVPanel(), wide, tall); - return wide; -} - -void Panel::SetWide(int wide) -{ - ipanel()->SetSize(GetVPanel(), wide, GetTall()); -} - -int Panel::GetTall() -{ - int wide, tall; - ipanel()->GetSize(GetVPanel(), wide, tall); - return tall; -} - -void Panel::SetTall(int tall) -{ - ipanel()->SetSize(GetVPanel(), GetWide(), tall); -} - -void Panel::SetBuildGroup(BuildGroup* buildGroup) -{ - //TODO: remove from old group - - Assert(buildGroup != NULL); - - _buildGroup = buildGroup; - - _buildGroup->PanelAdded(this); -} - -bool Panel::IsBuildGroupEnabled() -{ - if ( !_buildGroup.IsValid() ) - return false; - - bool enabled = _buildGroup->IsEnabled(); - if ( enabled ) - return enabled; - - if ( GetParent() && GetParent()->IsBuildGroupEnabled() ) - return true; - - return false; -} - -void Panel::SetBgColor(Color color) -{ - _bgColor = color; -} - -void Panel::SetFgColor(Color color) -{ - _fgColor = color; -} - -Color Panel::GetBgColor() -{ - return _bgColor; -} - -Color Panel::GetFgColor() -{ - return _fgColor; -} - -void Panel::InternalPerformLayout() -{ - // Don't layout if we're still waiting for our scheme to be applied. - // At worst, it leads to crashes, at best it does work that we'll redo as soon as the scheme has been applied. - if ( _flags.IsFlagSet( NEEDS_SCHEME_UPDATE ) ) - return; - - _flags.SetFlag( IN_PERFORM_LAYOUT ); - // make sure the scheme has been applied - _flags.ClearFlag( NEEDS_LAYOUT ); - PerformLayout(); - _flags.ClearFlag( IN_PERFORM_LAYOUT ); -} - -void Panel::PerformLayout() -{ - // this should be overridden to relayout controls -} - -void Panel::InvalidateLayout( bool layoutNow, bool reloadScheme ) -{ - _flags.SetFlag( NEEDS_LAYOUT ); - - if (reloadScheme) - { - // make all our children reload the scheme - _flags.SetFlag( NEEDS_SCHEME_UPDATE ); - - for (int i = 0; i < GetChildCount(); i++) - { - vgui::Panel* panel = GetChild(i); - if( panel ) - { - panel->InvalidateLayout(layoutNow, true); - } - } - - PerformApplySchemeSettings(); - } - - if (layoutNow) - { - InternalPerformLayout(); - Repaint(); - } -} - -bool Panel::IsCursorNone() -{ - HCursor cursor = GetCursor(); - - if (!cursor) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the cursor is currently over the panel -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsCursorOver(void) -{ - int x, y; - input()->GetCursorPos(x, y); - return IsWithin(x, y); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when a panel receives a command message from another panel -//----------------------------------------------------------------------------- -void Panel::OnCommand(const char *command) -{ - if ( !Q_stricmp( "performlayout", command ) ) - { - InvalidateLayout(); - } - else if ( !Q_stricmp( "reloadscheme", command ) ) - { - InvalidateLayout( false, true ); - } - else - { - // if noone else caught this, pass along to the listeners - // (this is useful for generic dialogs - otherwise, commands just get ignored) - KeyValues *msg = new KeyValues( command ); - PostActionSignal( msg ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: panel gained focus message -//----------------------------------------------------------------------------- -void Panel::OnSetFocus() -{ - Repaint(); -} - -//----------------------------------------------------------------------------- -// Purpose: panel lost focus message -//----------------------------------------------------------------------------- -void Panel::OnKillFocus() -{ - Repaint(); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the object up to be deleted next frame -//----------------------------------------------------------------------------- -void Panel::MarkForDeletion() -{ - if ( _flags.IsFlagSet( MARKED_FOR_DELETION ) ) - return; - - _flags.SetFlag( MARKED_FOR_DELETION ); - _flags.ClearFlag( AUTODELETE_ENABLED ); - - if (ivgui()->IsRunning()) - { - ivgui()->MarkPanelForDeletion(GetVPanel()); - } - // direct delete is never safe because even if ivgui is shutdown we manually do RunFrame() - // and we can enter here in a think traverse and then delete from underneath ourselves - /*else - { - delete this; - }*/ -} - -//----------------------------------------------------------------------------- -// Purpose: return true if this object require a perform layout -//----------------------------------------------------------------------------- -bool Panel::IsLayoutInvalid() -{ - return _flags.IsFlagSet( NEEDS_LAYOUT ); -} - - -//----------------------------------------------------------------------------- -// Sets the pin corner + resize mode for resizing panels -//----------------------------------------------------------------------------- -void Panel::SetAutoResize( PinCorner_e pinCorner, AutoResize_e resizeDir, - int nPinOffsetX, int nPinOffsetY, int nUnpinnedCornerOffsetX, int nUnpinnedCornerOffsetY ) -{ - _pinCorner = pinCorner; - _autoResizeDirection = resizeDir; - m_nPinDeltaX = nPinOffsetX; - m_nPinDeltaY = nPinOffsetY; - m_nResizeDeltaX = nUnpinnedCornerOffsetX; - m_nResizeDeltaY = nUnpinnedCornerOffsetY; -} - - -//----------------------------------------------------------------------------- -// Sets the pin corner for non-resizing panels -//----------------------------------------------------------------------------- -void Panel::SetPinCorner( PinCorner_e pinCorner, int nOffsetX, int nOffsetY ) -{ - _pinCorner = pinCorner; - _autoResizeDirection = AUTORESIZE_NO; - m_nPinDeltaX = nOffsetX; - m_nPinDeltaY = nOffsetY; - m_nResizeDeltaX = 0; - m_nResizeDeltaY = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: data accessor -//----------------------------------------------------------------------------- -Panel::PinCorner_e Panel::GetPinCorner() -{ - return (PinCorner_e)_pinCorner; -} - - -//----------------------------------------------------------------------------- -// Gets the relative offset of the control from the pin corner -//----------------------------------------------------------------------------- -void Panel::GetPinOffset( int &dx, int &dy ) -{ - dx = m_nPinDeltaX; - dy = m_nPinDeltaY; -} - - -//----------------------------------------------------------------------------- -// Purpose: data accessor -//----------------------------------------------------------------------------- -Panel::AutoResize_e Panel::GetAutoResize() -{ - return (AutoResize_e)_autoResizeDirection; -} - - -//----------------------------------------------------------------------------- -// Gets the relative offset of the control from the pin corner -//----------------------------------------------------------------------------- -void Panel::GetResizeOffset( int &dx, int &dy ) -{ - dx = m_nResizeDeltaX; - dy = m_nResizeDeltaY; -} - -//----------------------------------------------------------------------------- -// Tells this panel that it should pin itself to the corner of a specified sibling panel -//----------------------------------------------------------------------------- -void Panel::PinToSibling( const char *pszSibling, PinCorner_e pinOurCorner, PinCorner_e pinSibling ) -{ - _pinCornerToSibling = pinOurCorner; - _pinToSiblingCorner = pinSibling; - - if ( _pinToSibling && pszSibling && !Q_strcmp( _pinToSibling, pszSibling ) ) - return; - - if (_pinToSibling) - { - delete [] _pinToSibling; - _pinToSibling = NULL; - } - - if (pszSibling) - { - int len = Q_strlen(pszSibling) + 1; - _pinToSibling = new char[ len ]; - Q_strncpy( _pinToSibling, pszSibling, len ); - } - m_pinSibling = NULL; - - UpdateSiblingPin(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::UpdateSiblingPin( void ) -{ - if ( !_pinToSibling ) - { - ipanel()->SetSiblingPin(GetVPanel(), NULL); - return; - } - - if ( !m_pinSibling.Get() ) - { - // Resolve our sibling now - m_pinSibling = FindSiblingByName( _pinToSibling ); - } - - if ( m_pinSibling.Get() ) - { - ipanel()->SetSiblingPin( GetVPanel(), m_pinSibling->GetVPanel(), _pinCornerToSibling, _pinToSiblingCorner ); - } - else - { - ipanel()->SetSiblingPin(GetVPanel(), NULL); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::ApplySchemeSettings(IScheme *pScheme) -{ - // get colors - SetFgColor(GetSchemeColor("Panel.FgColor", pScheme)); - SetBgColor(GetSchemeColor("Panel.BgColor", pScheme)); - -#if defined( VGUI_USEDRAGDROP ) - m_clrDragFrame = pScheme->GetColor("DragDrop.DragFrame", Color(255, 255, 255, 192)); - m_clrDropFrame = pScheme->GetColor("DragDrop.DropFrame", Color(150, 255, 150, 255)); - - m_infoFont = pScheme->GetFont( "DefaultVerySmall" ); -#endif - // mark us as no longer needing scheme settings applied - _flags.ClearFlag( NEEDS_SCHEME_UPDATE ); - - if ( IsBuildGroupEnabled() ) - { - _buildGroup->ApplySchemeSettings(pScheme); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if the panel needs it's scheme info setup -//----------------------------------------------------------------------------- -void Panel::PerformApplySchemeSettings() -{ - if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) ) - { - InternalInitDefaultValues( GetAnimMap() ); - } - - if ( _flags.IsFlagSet( NEEDS_SCHEME_UPDATE ) ) - { - VPROF( "ApplySchemeSettings" ); - IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); - AssertOnce( pScheme ); - if ( pScheme ) // this should NEVER be null, but if it is bad things would happen in ApplySchemeSettings... - { - ApplySchemeSettings( pScheme ); - //_needsSchemeUpdate = false; - - ApplyOverridableColors(); - - UpdateSiblingPin(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Loads panel details related to autoresize from the resource info -//----------------------------------------------------------------------------- -#if defined( _DEBUG ) -static Panel *lastWarningParent = 0; -#endif - -void Panel::ApplyAutoResizeSettings(KeyValues *inResourceData) -{ - int x, y; - GetPos(x, y); - - int wide, tall; - GetSize( wide, tall ); - - AutoResize_e autoResize = (AutoResize_e)inResourceData->GetInt( "AutoResize", AUTORESIZE_NO ); - PinCorner_e pinCorner = (PinCorner_e)inResourceData->GetInt( "PinCorner", PIN_TOPLEFT ); - - // By default, measure unpinned corner for the offset - int pw = wide, pt = tall; - if ( GetParent() ) - { - GetParent()->GetSize( pw, pt ); -#if defined( _DEBUG ) - if ( pw == 64 && pt == 24 ) - { - if ( GetParent() != lastWarningParent ) - { - lastWarningParent = GetParent(); - Warning( "Resize parent (panel(%s) -> parent(%s)) not sized yet!!!\n", GetName(), GetParent()->GetName() ); - } - } -#endif - } - - int nPinnedCornerOffsetX = 0, nPinnedCornerOffsetY = 0; - int nUnpinnedCornerOffsetX = 0, nUnpinnedCornerOffsetY = 0; - switch( pinCorner ) - { - case PIN_TOPLEFT: - nPinnedCornerOffsetX = x; - nPinnedCornerOffsetY = y; - nUnpinnedCornerOffsetX = (x + wide) - pw; - nUnpinnedCornerOffsetY = (y + tall) - pt; - break; - - case PIN_TOPRIGHT: - nPinnedCornerOffsetX = (x + wide) - pw; - nPinnedCornerOffsetY = y; - nUnpinnedCornerOffsetX = x; - nUnpinnedCornerOffsetY = (y + tall) - pt; - break; - - case PIN_BOTTOMLEFT: - nPinnedCornerOffsetX = x; - nPinnedCornerOffsetY = (y + tall) - pt; - nUnpinnedCornerOffsetX = (x + wide) - pw; - nUnpinnedCornerOffsetY = y; - break; - - case PIN_BOTTOMRIGHT: - nPinnedCornerOffsetX = (x + wide) - pw; - nPinnedCornerOffsetY = (y + tall) - pt; - nUnpinnedCornerOffsetX = x; - nUnpinnedCornerOffsetY = y; - break; - } - - // Allow specific overrides in the resource file - if ( IsProportional() ) - { - if ( inResourceData->FindKey( "PinnedCornerOffsetX" ) ) - { - nPinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetX" ) ); - } - if ( inResourceData->FindKey( "PinnedCornerOffsetY" ) ) - { - nPinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetY" ) ); - } - if ( inResourceData->FindKey( "UnpinnedCornerOffsetX" ) ) - { - nUnpinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetX" ) ); - } - if ( inResourceData->FindKey( "UnpinnedCornerOffsetY" ) ) - { - nUnpinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetY" ) ); - } - } - else - { - nPinnedCornerOffsetX = inResourceData->GetInt( "PinnedCornerOffsetX", nPinnedCornerOffsetX ); - nPinnedCornerOffsetY = inResourceData->GetInt( "PinnedCornerOffsetY", nPinnedCornerOffsetY ); - nUnpinnedCornerOffsetX = inResourceData->GetInt( "UnpinnedCornerOffsetX", nUnpinnedCornerOffsetX ); - nUnpinnedCornerOffsetY = inResourceData->GetInt( "UnpinnedCornerOffsetY", nUnpinnedCornerOffsetY ); - } - - if ( autoResize == AUTORESIZE_NO ) - { - nUnpinnedCornerOffsetX = nUnpinnedCornerOffsetY = 0; - } - - SetAutoResize( pinCorner, autoResize, nPinnedCornerOffsetX, nPinnedCornerOffsetY, nUnpinnedCornerOffsetX, nUnpinnedCornerOffsetY ); -} - -ConVar panel_test_title_safe( "panel_test_title_safe", "0", FCVAR_CHEAT, "Test vgui panel positioning with title safe indentation" ); - - - -//----------------------------------------------------------------------------- -// Purpose: Loads panel details from the resource info -//----------------------------------------------------------------------------- -void Panel::ApplySettings(KeyValues *inResourceData) -{ - // First restore to default values - if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) ) - { - InternalInitDefaultValues( GetAnimMap() ); - } - - // Let PanelAnimationVars auto-retrieve settings (we restore defaults above - // since a script might be missing certain values) - InternalApplySettings( GetAnimMap(), inResourceData ); - - // clear any alignment flags - _buildModeFlags &= ~(BUILDMODE_SAVE_XPOS_RIGHTALIGNED | BUILDMODE_SAVE_XPOS_CENTERALIGNED | BUILDMODE_SAVE_YPOS_BOTTOMALIGNED | BUILDMODE_SAVE_YPOS_CENTERALIGNED | BUILDMODE_SAVE_WIDE_FULL | BUILDMODE_SAVE_TALL_FULL | BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT); - - // get the position - int alignScreenWide, alignScreenTall; // screen dimensions used for pinning in splitscreen - surface()->GetScreenSize( alignScreenWide, alignScreenTall ); - - int screenWide = alignScreenWide; - int screenTall = alignScreenTall; - - // temporarily remove the override to get the fullscreen dimensions - if ( surface()->IsScreenSizeOverrideActive() ) - { - surface()->ForceScreenSizeOverride( false, 0, 0 ); - surface()->GetScreenSize( screenWide, screenTall ); - - // restore the override - surface()->ForceScreenSizeOverride( true, alignScreenWide, alignScreenTall ); - } - - int parentX = 0; - int parentY = 0; - - // flag to cause windows to get screenWide and screenTall from their parents, - // this allows children windows to use fill and right/bottom alignment even - // if their parent does not use the full screen. - if ( inResourceData->GetInt( "proportionalToParent", 0 ) == 1 ) - { - _buildModeFlags |= BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT; - if ( GetParent() != NULL ) - { - GetParent()->GetBounds( parentX, parentY, alignScreenWide, alignScreenTall ); - } - } - - int x, y; - GetPos(x, y); - const char *xstr = inResourceData->GetString( "xpos", NULL ); - const char *ystr = inResourceData->GetString( "ypos", NULL ); - - if (xstr) - { - // look for alignment flags - if (xstr[0] == 'r' || xstr[0] == 'R') - { - _buildModeFlags |= BUILDMODE_SAVE_XPOS_RIGHTALIGNED; - xstr++; - } - else if (xstr[0] == 'c' || xstr[0] == 'C') - { - _buildModeFlags |= BUILDMODE_SAVE_XPOS_CENTERALIGNED; - xstr++; - } - - // get the value - x = atoi(xstr); - // scale the x up to our screen co-ords - if ( IsProportional() ) - { - x = scheme()->GetProportionalScaledValueEx(GetScheme(), x); - } - // now correct the alignment - if (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED) - { - x = alignScreenWide - x; - } - else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED) - { - x = (alignScreenWide / 2) + x; - } - } - - if (ystr) - { - // look for alignment flags - if (ystr[0] == 'r' || ystr[0] == 'R') - { - _buildModeFlags |= BUILDMODE_SAVE_YPOS_BOTTOMALIGNED; - ystr++; - } - else if (ystr[0] == 'c' || ystr[0] == 'C') - { - _buildModeFlags |= BUILDMODE_SAVE_YPOS_CENTERALIGNED; - ystr++; - } - y = atoi(ystr); - if (IsProportional()) - { - // scale the y up to our screen co-ords - y = scheme()->GetProportionalScaledValueEx(GetScheme(), y); - } - // now correct the alignment - if (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED) - { - y = alignScreenTall - y; - } - else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED) - { - y = (alignScreenTall / 2) + y; - } - } - - bool bUsesTitleSafeArea = false; - int titleSafeWide = 0; - int titleSafeTall = 0; - - Rect_t excludeEdgeFromTitleSafe; // if a side is set to != 0, don't title safe relative to that edge - excludeEdgeFromTitleSafe.x = 0; - excludeEdgeFromTitleSafe.y = 0; - excludeEdgeFromTitleSafe.width = 0; - excludeEdgeFromTitleSafe.height = 0; - - if ( IsX360() || panel_test_title_safe.GetBool() ) - { - // "usetitlesafe" "1" - required inner 90% - // "usetitlesafe" "2" - suggested inner 85% - - int iUseTitleSafeValue = 0; - if ( inResourceData->FindKey( "usetitlesafe" ) ) - { - iUseTitleSafeValue = inResourceData->GetInt( "usetitlesafe" ); - bUsesTitleSafeArea = ( iUseTitleSafeValue > 0 ); - } - - if( bUsesTitleSafeArea ) - { - titleSafeWide = screenWide * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f ); - titleSafeTall = screenTall * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f ); - - // Don't title safe internal boundaries for split screen viewports - int splitX = 0; - int splitY = 0; - vgui::surface()->OffsetAbsPos( splitX, splitY ); - - bool bHorizontalSplit = ( alignScreenTall != screenTall ); - bool bVerticalSplit = ( alignScreenWide != screenWide ); - - if ( bHorizontalSplit ) - { - // top or bottom? - if ( splitY != parentY ) - { - excludeEdgeFromTitleSafe.y = 1; - } - else - { - excludeEdgeFromTitleSafe.height = 1; - } - } - - if ( bVerticalSplit ) - { - // left or right - if ( splitX != parentX ) - { - excludeEdgeFromTitleSafe.x = 1; - } - else - { - excludeEdgeFromTitleSafe.width = 1; - } - } - - if ( _buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED ) - { - if ( !excludeEdgeFromTitleSafe.width ) - { - x -= titleSafeWide; // right edge - } - } - else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED) - { - } - else if ( !excludeEdgeFromTitleSafe.x ) - { - x += titleSafeWide; // left edge - } - - if ( _buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED ) - { - if ( !excludeEdgeFromTitleSafe.height ) - { - y -= titleSafeTall; // bottom edge - } - } - else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED) - { - } - else if ( !excludeEdgeFromTitleSafe.y ) - { - y += titleSafeTall; // top edge - } - } - } - SetNavUp( inResourceData->GetString("navUp") ); - SetNavDown( inResourceData->GetString("navDown") ); - SetNavLeft( inResourceData->GetString("navLeft") ); - SetNavRight( inResourceData->GetString("navRight") ); - SetNavToRelay( inResourceData->GetString("navToRelay") ); - SetNavActivate( inResourceData->GetString("navActivate") ); - SetNavBack( inResourceData->GetString("navBack") ); - - SetPos(x, y); - - if (inResourceData->FindKey( "zpos" )) - { - SetZPos( inResourceData->GetInt( "zpos" ) ); - } - - // size - int wide, tall; - GetSize( wide, tall ); - - const char *wstr = inResourceData->GetString( "wide", NULL ); - if ( wstr ) - { - if (wstr[0] == 'f' || wstr[0] == 'F') - { - _buildModeFlags |= BUILDMODE_SAVE_WIDE_FULL; - wstr++; - } - wide = atoi(wstr); - if ( IsProportional() ) - { - // scale the width up to our screen co-ords - wide = scheme()->GetProportionalScaledValueEx(GetScheme(), wide); - } - // now correct the alignment - if (_buildModeFlags & BUILDMODE_SAVE_WIDE_FULL) - { - wide = alignScreenWide - wide; - } - } - - // allow tall to be use the "fill" option, set to the height of the parent/screen - wstr = inResourceData->GetString( "tall", NULL ); - if ( wstr ) - { - if (wstr[0] == 'f' || wstr[0] == 'F') - { - _buildModeFlags |= BUILDMODE_SAVE_TALL_FULL; - wstr++; - } - tall = atoi(wstr); - if ( IsProportional() ) - { - // scale the height up to our screen co-ords - tall = scheme()->GetProportionalScaledValueEx(GetScheme(), tall); - } - // now correct the alignment - if (_buildModeFlags & BUILDMODE_SAVE_TALL_FULL) - { - tall = alignScreenTall - tall; - } - } - - if( bUsesTitleSafeArea ) - { - if ( _buildModeFlags & BUILDMODE_SAVE_WIDE_FULL ) - { - if ( !excludeEdgeFromTitleSafe.x ) - wide -= titleSafeWide; - - if ( !excludeEdgeFromTitleSafe.width ) - wide -= titleSafeWide; - } - - if ( _buildModeFlags & BUILDMODE_SAVE_TALL_FULL ) - { - if ( !excludeEdgeFromTitleSafe.y ) - tall -= titleSafeTall; - - if ( !excludeEdgeFromTitleSafe.height ) - tall -= titleSafeTall; - } - } - - SetSize( wide, tall ); - - // NOTE: This has to happen after pos + size is set - ApplyAutoResizeSettings( inResourceData ); - - // only get colors if we're ignoring the scheme - if (inResourceData->GetInt("IgnoreScheme", 0)) - { - PerformApplySchemeSettings(); - } - - // state - int state = inResourceData->GetInt("visible", 1); - if (state == 0) - { - SetVisible(false); - } - else if (state == 1) - { - SetVisible(true); - } - - SetEnabled( inResourceData->GetInt("enabled", true) ); - - bool bMouseEnabled = inResourceData->GetInt( "mouseinputenabled", true ); - if ( !bMouseEnabled ) - { - SetMouseInputEnabled( false ); - } - - // tab order - SetTabPosition(inResourceData->GetInt("tabPosition", 0)); - - const char *tooltip = inResourceData->GetString("tooltiptext", NULL); - if (tooltip && *tooltip) - { - GetTooltip()->SetText(tooltip); - } - - // paint background? - int nPaintBackground = inResourceData->GetInt("paintbackground", -1); - if (nPaintBackground >= 0) - { - SetPaintBackgroundEnabled( nPaintBackground != 0 ); - } - - // paint border? - int nPaintBorder = inResourceData->GetInt("paintborder", -1); - if (nPaintBorder >= 0) - { - SetPaintBorderEnabled( nPaintBorder != 0 ); - } - - // border? - const char *pBorder = inResourceData->GetString( "border", "" ); - if ( *pBorder ) - { - IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); - SetBorder( pScheme->GetBorder( pBorder ) ); - } - - // check to see if we have a new name assigned - const char *newName = inResourceData->GetString("fieldName", NULL); - if ( newName ) - { - // Only slam the name if the new one differs... - SetName(newName); - } - - // check to see if we need to render to the frame buffer even if - // stereo mode is trying to render all of the ui to a render target - m_bForceStereoRenderToFrameBuffer = inResourceData->GetBool( "ForceStereoRenderToFrameBuffer", false ); - - //============================================================================= - // HPE_BEGIN: - // [pfreese] Support for reading rounded corner flags - //============================================================================= - int roundedCorners = inResourceData->GetInt( "RoundedCorners", -1 ); - if ( roundedCorners >= 0 ) - { - m_roundedCorners = roundedCorners; - } - //============================================================================= - // HPE_END - //============================================================================= - - const char *pszSiblingName = inResourceData->GetString("pin_to_sibling", NULL); - PinCorner_e pinOurCornerToSibling = (PinCorner_e)inResourceData->GetInt( "pin_corner_to_sibling", PIN_TOPLEFT ); - PinCorner_e pinSiblingCorner = (PinCorner_e)inResourceData->GetInt( "pin_to_sibling_corner", PIN_TOPLEFT ); - PinToSibling( pszSiblingName, pinOurCornerToSibling, pinSiblingCorner ); - - - // Allow overriding of colors. Used mostly by HUD elements, where scheme color usage is often undesired. - IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); - for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) - { - // Need to ensure the key exists, so we don't overwrite existing colors when it's not set. - if ( inResourceData->FindKey( m_OverridableColorEntries[i].m_pszScriptName, false ) ) - { - // Get the color as a string - test whether it is an actual color or a reference to a scheme color - const char *pColorStr = inResourceData->GetString( m_OverridableColorEntries[i].m_pszScriptName ); - Color &clrDest = m_OverridableColorEntries[i].m_colFromScript; - if ( pColorStr[0] == '.' || isdigit( pColorStr[0] ) ) - { - float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f; - sscanf( pColorStr, "%f %f %f %f", &r, &g, &b, &a ); - clrDest[0] = (unsigned char)r; - clrDest[1] = (unsigned char)g; - clrDest[2] = (unsigned char)b; - clrDest[3] = (unsigned char)a; - } - else - { - // First character wasn't a digit or a decimal - do a scheme color lookup - clrDest = pScheme->GetColor( pColorStr, Color( 255, 255, 255, 255 ) ); - } - - (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript; - m_OverridableColorEntries[i].m_bOverridden = true; - } - } - - const char *pKeyboardInputEnabled = inResourceData->GetString( "keyboardinputenabled", NULL ); - if ( pKeyboardInputEnabled && pKeyboardInputEnabled[0] ) - { - SetKeyBoardInputEnabled( atoi( pKeyboardInputEnabled ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Saves out a resource description of this panel -//----------------------------------------------------------------------------- -void Panel::GetSettings( KeyValues *outResourceData ) -{ - // control class name (so it can be recreated later if needed) - outResourceData->SetString( "ControlName", GetClassName() ); - - // name - outResourceData->SetString( "fieldName", _panelName ); - - // positioning - int screenWide, screenTall; - surface()->GetScreenSize(screenWide, screenTall); - int x, y; - GetPos( x, y ); - if ( IsProportional() ) - { - x = scheme()->GetProportionalNormalizedValueEx( GetScheme(), x ); - y = scheme()->GetProportionalNormalizedValueEx( GetScheme(), y ); - } - // correct for alignment - if (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED) - { - x = screenWide - x; - char xstr[32]; - Q_snprintf(xstr, sizeof( xstr ), "r%d", x); - outResourceData->SetString( "xpos", xstr ); - } - else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED) - { - x = (screenWide / 2) + x; - char xstr[32]; - Q_snprintf(xstr, sizeof( xstr ), "c%d", x); - outResourceData->SetString( "xpos", xstr ); - } - else - { - outResourceData->SetInt( "xpos", x ); - } - if (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED) - { - y = screenTall - y; - char ystr[32]; - Q_snprintf(ystr, sizeof( ystr ), "r%d", y); - outResourceData->SetString( "ypos", ystr ); - } - else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED) - { - y = (screenTall / 2) + y; - char ystr[32]; - Q_snprintf(ystr, sizeof( ystr ), "c%d", y); - outResourceData->SetString( "ypos", ystr ); - } - else - { - outResourceData->SetInt( "ypos", y ); - } - if (m_pTooltips) - { - if (strlen(m_pTooltips->GetText()) > 0) - { - outResourceData->SetString("tooltiptext", m_pTooltips->GetText()); - } - } - int wide, tall; - GetSize( wide, tall ); - if ( IsProportional() ) - { - wide = scheme()->GetProportionalNormalizedValueEx( GetScheme(), wide ); - tall = scheme()->GetProportionalNormalizedValueEx( GetScheme(), tall ); - } - - int z = ipanel()->GetZPos(GetVPanel()); - if (z) - { - outResourceData->SetInt("zpos", z); - } - - // Correct for alignment - if (_buildModeFlags & BUILDMODE_SAVE_WIDE_FULL ) - { - wide = screenWide - wide; - char wstr[32]; - Q_snprintf(wstr, sizeof( wstr ), "f%d", wide); - outResourceData->SetString( "wide", wstr ); - } - else - { - outResourceData->SetInt( "wide", wide ); - } - outResourceData->SetInt( "tall", tall ); - - outResourceData->SetInt("AutoResize", GetAutoResize()); - outResourceData->SetInt("PinCorner", GetPinCorner()); - - //============================================================================= - // HPE_BEGIN: - // [pfreese] Support for writing out rounded corner flags - //============================================================================= - outResourceData->SetInt("RoundedCorners", m_roundedCorners); - //============================================================================= - // HPE_END - //============================================================================= - - outResourceData->SetString( "pin_to_sibling", _pinToSibling ); - outResourceData->SetInt("pin_corner_to_sibling", _pinCornerToSibling ); - outResourceData->SetInt("pin_to_sibling_corner", _pinToSiblingCorner ); - - - // state - outResourceData->SetInt( "visible", IsVisible() ); - outResourceData->SetInt( "enabled", IsEnabled() ); - - outResourceData->SetInt( "tabPosition", GetTabPosition() ); - - for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) - { - if ( m_OverridableColorEntries[i].m_bOverridden ) - { - outResourceData->SetColor( m_OverridableColorEntries[i].m_pszScriptName, m_OverridableColorEntries[i].m_colFromScript ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: After applying settings, apply overridable colors. -// Done post apply settings, so that baseclass settings don't stomp -// the script specified override colors. -//----------------------------------------------------------------------------- -void Panel::ApplyOverridableColors( void ) -{ - for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) - { - if ( m_OverridableColorEntries[i].m_bOverridden ) - { - (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetOverridableColor( Color *pColor, const Color &newColor ) -{ - for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) - { - if ( m_OverridableColorEntries[i].m_bOverridden ) - { - if ( m_OverridableColorEntries[i].m_pColor == pColor ) - return; - } - } - - // Didn't find it, or it's not been overridden. - *pColor = newColor; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Color Panel::GetSchemeColor(const char *keyName, IScheme *pScheme) -{ - return pScheme->GetColor(keyName, Color(255, 255, 255, 255)); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Color Panel::GetSchemeColor(const char *keyName, Color defaultColor, IScheme *pScheme) -{ - return pScheme->GetColor(keyName, defaultColor); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a string description of the panel fields for use in the UI -//----------------------------------------------------------------------------- -const char *Panel::GetDescription( void ) -{ - static const char *panelDescription = "string fieldName, int xpos, int ypos, int wide, int tall, bool visible, bool enabled, int tabPosition, corner pinCorner, autoresize autoResize, string tooltiptext"; - return panelDescription; -} - -//----------------------------------------------------------------------------- -// Purpose: user configuration settings -// this is used for any control details the user wants saved between sessions -// eg. dialog positions, last directory opened, list column width -//----------------------------------------------------------------------------- -void Panel::ApplyUserConfigSettings(KeyValues *userConfig) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: returns user config settings for this control -//----------------------------------------------------------------------------- -void Panel::GetUserConfigSettings(KeyValues *userConfig) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: optimization, return true if this control has any user config settings -//----------------------------------------------------------------------------- -bool Panel::HasUserConfigSettings() -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::InternalInvalidateLayout() -{ - InvalidateLayout(false, false); -} - -//----------------------------------------------------------------------------- -// Purpose: called whenever the panel moves -//----------------------------------------------------------------------------- -void Panel::OnMove() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::InternalMove() -{ - OnMove(); - for(int i=0;iOnMove(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: empty function -//----------------------------------------------------------------------------- -void Panel::OnTick() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: versioning -//----------------------------------------------------------------------------- -void *Panel::QueryInterface(EInterfaceID id) -{ - if (id == ICLIENTPANEL_STANDARD_INTERFACE) - { - return this; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Map all the base messages to functions -// ordering from most -> least used improves speed -//----------------------------------------------------------------------------- -MessageMapItem_t Panel::m_MessageMap[] = -{ - MAP_MESSAGE_INT( Panel, "RequestFocus", RequestFocus, "direction" ) -}; - -// IMPLEMENT_PANELMAP( Panel, NULL ) -PanelMap_t Panel::m_PanelMap = { Panel::m_MessageMap, ARRAYSIZE(Panel::m_MessageMap), "Panel", NULL }; -PanelMap_t *Panel::GetPanelMap( void ) { return &m_PanelMap; } - -//----------------------------------------------------------------------------- -// Purpose: !! Soon to replace existing prepare panel map -//----------------------------------------------------------------------------- -void PreparePanelMessageMap(PanelMessageMap *panelMap) -{ - // iterate through the class hierarchy message maps - while ( panelMap != NULL && !panelMap->processed ) - { - // hash message map strings into symbols - for (int i = 0; i < panelMap->entries.Count(); i++) - { - MessageMapItem_t *item = &panelMap->entries[i]; - - if (item->name) - { - item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name); - } - else - { - item->nameSymbol = INVALID_KEY_SYMBOL; - } - if (item->firstParamName) - { - item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName); - } - else - { - item->firstParamSymbol = INVALID_KEY_SYMBOL; - } - if (item->secondParamName) - { - item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName); - } - else - { - item->secondParamSymbol = INVALID_KEY_SYMBOL; - } - } - - panelMap->processed = true; - panelMap = panelMap->baseMap; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Handles a message -// Dispatches the message to a set of message maps -//----------------------------------------------------------------------------- -void Panel::OnMessage(const KeyValues *params, VPANEL ifromPanel) -{ - PanelMessageMap *panelMap = GetMessageMap(); - bool bFound = false; - int iMessageName = params->GetNameSymbol(); - - if ( !panelMap->processed ) - { - PreparePanelMessageMap( panelMap ); - } - - // iterate through the class hierarchy message maps - for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap ) - { -#if defined( _DEBUG ) -// char const *className = panelMap->pfnClassName(); -// NOTE_UNUSED( className ); -#endif - - // iterate all the entries in the panel map - for ( int i = 0; i < panelMap->entries.Count(); i++ ) - { - MessageMapItem_t *pMap = &panelMap->entries[i]; - - if (iMessageName == pMap->nameSymbol) - { - bFound = true; - - switch (pMap->numParams) - { - case 0: - { - (this->*(pMap->func))(); - break; - } - - case 1: - { - KeyValues *param1 = params->FindKey(pMap->firstParamSymbol); - if (!param1) - { - param1 = const_cast(params); - } - - switch ( pMap->firstParamType ) - { - case DATATYPE_INT: - typedef void (Panel::*MessageFunc_Int_t)(int); - (this->*((MessageFunc_Int_t)pMap->func))( param1->GetInt() ); - break; - - case DATATYPE_UINT64: - typedef void (Panel::*MessageFunc_Uin64_t)(uint64); - (this->*((MessageFunc_Uin64_t)pMap->func))( param1->GetUint64() ); - break; - - case DATATYPE_PTR: - typedef void (Panel::*MessageFunc_Ptr_t)( void * ); - (this->*((MessageFunc_Ptr_t)pMap->func))( param1->GetPtr() ); - break; - - case DATATYPE_HANDLE: - { - typedef void (Panel::*MessageFunc_VPANEL_t)( VPANEL ); - VPANEL vpanel = ivgui()->HandleToPanel( param1->GetInt() ); - (this->*((MessageFunc_VPANEL_t)pMap->func))( vpanel ); - } - break; - - case DATATYPE_FLOAT: - typedef void (Panel::*MessageFunc_Float_t)( float ); - (this->*((MessageFunc_Float_t)pMap->func))( param1->GetFloat() ); - break; - - case DATATYPE_CONSTCHARPTR: - typedef void (Panel::*MessageFunc_CharPtr_t)( const char * ); - (this->*((MessageFunc_CharPtr_t)pMap->func))( param1->GetString() ); - break; - - case DATATYPE_CONSTWCHARPTR: - typedef void (Panel::*MessageFunc_WCharPtr_t)( const wchar_t * ); - (this->*((MessageFunc_WCharPtr_t)pMap->func))( param1->GetWString() ); - break; - - case DATATYPE_KEYVALUES: - typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *); - if ( pMap->firstParamName ) - { - (this->*((MessageFunc_KeyValues_t)pMap->func))( (KeyValues *)param1->GetPtr() ); - } - else - { - // no param set, so pass in the whole thing - (this->*((MessageFunc_KeyValues_t)pMap->func))( const_cast(params) ); - } - break; - - default: - Assert(!("No handler for vgui message function")); - break; - } - break; - } - - case 2: - { - KeyValues *param1 = params->FindKey(pMap->firstParamSymbol); - if (!param1) - { - param1 = const_cast(params); - } - KeyValues *param2 = params->FindKey(pMap->secondParamSymbol); - if (!param2) - { - param2 = const_cast(params); - } - - if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_IntInt_t)(int, int); - (this->*((MessageFunc_IntInt_t)pMap->func))( param1->GetInt(), param2->GetInt() ); - } - else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int); - (this->*((MessageFunc_PtrInt_t)pMap->func))( param1->GetPtr(), param2->GetInt() ); - } - else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int); - (this->*((MessageFunc_ConstCharPtrInt_t)pMap->func))( param1->GetString(), param2->GetInt() ); - } - else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *); - (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMap->func))( param1->GetString(), param2->GetString() ); - } - else if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *); - (this->*((MessageFunc_IntConstCharPtr_t)pMap->func))( param1->GetInt(), param2->GetString() ); - } - else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *); - (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetString() ); - } - else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *); - (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetWString() ); - } - else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *); - VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() ); - (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetString() ); - } - else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) ) - { - typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *); - VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() ); - (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetWString() ); - } - else - { - // the message isn't handled - ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() ); - } - break; - } - - default: - Assert(!("Invalid number of parameters")); - break; - } - - // break the loop - bFound = true; - break; - } - } - } - - if (!bFound) - { - OnOldMessage(const_cast(params), ifromPanel); - } -} - -void Panel::OnOldMessage(KeyValues *params, VPANEL ifromPanel) -{ - bool bFound = false; - // message map dispatch - int iMessageName = params->GetNameSymbol(); - - PanelMap_t *panelMap = GetPanelMap(); - if ( !panelMap->processed ) - { - PreparePanelMap( panelMap ); - } - - // iterate through the class hierarchy message maps - for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap ) - { - MessageMapItem_t *pMessageMap = panelMap->dataDesc; - - for ( int i = 0; i < panelMap->dataNumFields; i++ ) - { - if (iMessageName == pMessageMap[i].nameSymbol) - { - // call the mapped function - switch ( pMessageMap[i].numParams ) - { - case 2: - if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_IntInt_t)(int, int); - (this->*((MessageFunc_IntInt_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int); - (this->*((MessageFunc_PtrInt_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int); - (this->*((MessageFunc_ConstCharPtrInt_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *); - (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *); - (this->*((MessageFunc_IntConstCharPtr_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *); - (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *); - (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetWString(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR ==pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *); - VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) ); - (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetString(pMessageMap[i].secondParamName) ); - } - else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) ) - { - typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *); - VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) ); - (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetWString(pMessageMap[i].secondParamName) ); - } - else - { - // the message isn't handled - ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() ); - } - break; - - case 1: - switch ( pMessageMap[i].firstParamType ) - { - case DATATYPE_BOOL: - typedef void (Panel::*MessageFunc_Bool_t)(bool); - (this->*((MessageFunc_Bool_t)pMessageMap[i].func))( (bool)params->GetInt(pMessageMap[i].firstParamName) ); - break; - - case DATATYPE_CONSTCHARPTR: - typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *); - (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetString(pMessageMap[i].firstParamName) ); - break; - - case DATATYPE_CONSTWCHARPTR: - typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *); - (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetWString(pMessageMap[i].firstParamName) ); - break; - - case DATATYPE_INT: - typedef void (Panel::*MessageFunc_Int_t)(int); - (this->*((MessageFunc_Int_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName) ); - break; - - case DATATYPE_FLOAT: - typedef void (Panel::*MessageFunc_Float_t)(float); - (this->*((MessageFunc_Float_t)pMessageMap[i].func))( params->GetFloat(pMessageMap[i].firstParamName) ); - break; - - case DATATYPE_PTR: - typedef void (Panel::*MessageFunc_Ptr_t)(void *); - (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)params->GetPtr(pMessageMap[i].firstParamName) ); - break; - - case DATATYPE_HANDLE: - { - typedef void (Panel::*MessageFunc_Ptr_t)(void *); - VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) ); - Panel *panel = ipanel()->GetPanel( vp, GetModuleName() ); - (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)panel ); - } - break; - - case DATATYPE_KEYVALUES: - typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *); - if ( pMessageMap[i].firstParamName ) - { - (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( (KeyValues *)params->GetPtr(pMessageMap[i].firstParamName) ); - } - else - { - (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( params ); - } - break; - - default: - // the message isn't handled - ivgui()->DPrintf( "Message '%s', sent to '%s', has an invalid parameter type\n", params->GetName(), GetName() ); - break; - } - - break; - - default: - (this->*(pMessageMap[i].func))(); - break; - }; - - // break the loop - bFound = true; - break; - } - } - } - - // message not handled - // debug code - if ( !bFound ) - { - static int s_bDebugMessages = -1; - if ( s_bDebugMessages == -1 ) - { - s_bDebugMessages = CommandLine()->FindParm( "-vguimessages" ) ? 1 : 0; - } - if ( s_bDebugMessages == 1 ) - { - ivgui()->DPrintf( "Message '%s' not handled by panel '%s'\n", params->GetName(), GetName() ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Safe call to get info from child panel by name -//----------------------------------------------------------------------------- -bool Panel::RequestInfoFromChild(const char *childName, KeyValues *outputData) -{ - Panel *panel = FindChildByName(childName); - if (panel) - { - return panel->RequestInfo(outputData); - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Posts a message -//----------------------------------------------------------------------------- -void Panel::PostMessage(Panel *target, KeyValues *message, float delay) -{ - ivgui()->PostMessage(target->GetVPanel(), message, GetVPanel(), delay); -} - -void Panel::PostMessage(VPANEL target, KeyValues *message, float delaySeconds) -{ - ivgui()->PostMessage(target, message, GetVPanel(), delaySeconds); -} - -void Panel::PostMessageToAllSiblings( KeyValues *msg, float delaySeconds /*= 0.0f*/ ) -{ - VPANEL parent = GetVParent(); - if ( parent ) - { - VPANEL vpanel = GetVPanel(); - - CUtlVector< VPANEL > &children = ipanel()->GetChildren( parent ); - int nChildCount = children.Count(); - for ( int i = 0; i < nChildCount; ++i ) - { - VPANEL sibling = children[ i ]; - if ( sibling == vpanel ) - continue; - - if ( sibling ) - { - PostMessage( sibling, msg->MakeCopy(), delaySeconds ); - } - } - } - - msg->deleteThis(); -} - -//----------------------------------------------------------------------------- -// Purpose: Safe call to post a message to a child by name -//----------------------------------------------------------------------------- -void Panel::PostMessageToChild(const char *childName, KeyValues *message) -{ - Panel *panel = FindChildByName(childName); - if (panel) - { - ivgui()->PostMessage(panel->GetVPanel(), message, GetVPanel()); - } - else - { - message->deleteThis(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Requests some information from the panel -// Look through the message map for the handler -//----------------------------------------------------------------------------- -bool Panel::RequestInfo( KeyValues *outputData ) -{ - if ( InternalRequestInfo( GetAnimMap(), outputData ) ) - { - return true; - } - - if (GetVParent()) - { - return ipanel()->RequestInfo(GetVParent(), outputData); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: sets a specified value in the control - inverse of RequestInfo -//----------------------------------------------------------------------------- -bool Panel::SetInfo(KeyValues *inputData) -{ - if ( InternalSetInfo( GetAnimMap(), inputData ) ) - { - return true; - } - - // doesn't chain to parent - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: change the panel's silent mode; if silent, the panel will not post -// any action signals -//----------------------------------------------------------------------------- - -void Panel::SetSilentMode( bool bSilent ) -{ - m_bIsSilent = bSilent; -} - -//----------------------------------------------------------------------------- -// Purpose: mouse events will be send to handler panel instead of this panel -//----------------------------------------------------------------------------- -void Panel::InstallMouseHandler( Panel *pHandler ) -{ - m_hMouseEventHandler = pHandler; -} - -//----------------------------------------------------------------------------- -// Purpose: Prepares the hierarchy panel maps for use (with message maps etc) -//----------------------------------------------------------------------------- -void Panel::PreparePanelMap( PanelMap_t *panelMap ) -{ - // iterate through the class hierarchy message maps - while ( panelMap != NULL && !panelMap->processed ) - { - // fixup cross-dll boundary panel maps - if ( panelMap->baseMap == (PanelMap_t*)0x00000001 ) - { - panelMap->baseMap = &Panel::m_PanelMap; - } - - // hash message map strings into symbols - for (int i = 0; i < panelMap->dataNumFields; i++) - { - MessageMapItem_t *item = &panelMap->dataDesc[i]; - - if (item->name) - { - item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name); - } - else - { - item->nameSymbol = INVALID_KEY_SYMBOL; - } - if (item->firstParamName) - { - item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName); - } - else - { - item->firstParamSymbol = INVALID_KEY_SYMBOL; - } - if (item->secondParamName) - { - item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName); - } - else - { - item->secondParamSymbol = INVALID_KEY_SYMBOL; - } - } - - panelMap->processed = true; - panelMap = panelMap->baseMap; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called to delete the panel -//----------------------------------------------------------------------------- -void Panel::OnDelete() -{ -#ifdef WIN32 - Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) ); -#endif - delete this; -#ifdef WIN32 - Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Panel handle implementation -// Returns a pointer to a valid panel, NULL if the panel has been deleted -//----------------------------------------------------------------------------- -Panel *PHandle::Get() -{ - if (m_iPanelID != INVALID_PANEL) - { - VPANEL panel = ivgui()->HandleToPanel(m_iPanelID); - if (panel) - { - Panel *vguiPanel = ipanel()->GetPanel(panel, GetControlsModuleName()); - return vguiPanel; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: sets the smart pointer -//----------------------------------------------------------------------------- -Panel *PHandle::Set(Panel *pent) -{ - if (pent) - { - m_iPanelID = ivgui()->PanelToHandle(pent->GetVPanel()); - } - else - { - m_iPanelID = INVALID_PANEL; - } - return pent; -} - -Panel *PHandle::Set( HPanel hPanel ) -{ - m_iPanelID = hPanel; - return Get(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a handle to a valid panel, NULL if the panel has been deleted -//----------------------------------------------------------------------------- -VPANEL VPanelHandle::Get() -{ - if (m_iPanelID != INVALID_PANEL) - { - if (ivgui()) - { - return ivgui()->HandleToPanel(m_iPanelID); - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: sets the smart pointer -//----------------------------------------------------------------------------- -VPANEL VPanelHandle::Set(VPANEL pent) -{ - if (pent) - { - m_iPanelID = ivgui()->PanelToHandle(pent); - } - else - { - m_iPanelID = INVALID_PANEL; - } - return pent; -} - -//----------------------------------------------------------------------------- -// Purpose: returns a pointer to the tooltip object associated with the panel -//----------------------------------------------------------------------------- -BaseTooltip *Panel::GetTooltip() -{ - if (!m_pTooltips) - { - m_pTooltips = new TextTooltip(this, NULL); - m_bToolTipOverridden = false; - - if ( IsConsoleStylePanel() ) - { - m_pTooltips->SetEnabled( false ); - } - } - - return m_pTooltips; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetTooltip( BaseTooltip *pToolTip, const char *pszText ) -{ - if ( !m_bToolTipOverridden ) - { - // Remove the one we made, we're being overridden. - delete m_pTooltips; - } - - m_pTooltips = pToolTip; - m_bToolTipOverridden = true; - - if ( _tooltipText ) - { - delete [] _tooltipText; - _tooltipText = NULL; - } - - if ( pszText ) - { - int len = Q_strlen(pszText) + 1; - _tooltipText = new char[ len ]; - Q_strncpy( _tooltipText, pszText, len ); - } -} - -//----------------------------------------------------------------------------- -const char *Panel::GetEffectiveTooltipText() const -{ - if ( _tooltipText ) - { - return _tooltipText; - } - if ( m_pTooltips ) - { - const char *result = m_pTooltips->GetText(); - if ( result ) - { - return result; - } - } - return ""; -} - -//----------------------------------------------------------------------------- -// Purpose: sets the proportional flag on this panel and all it's children -//----------------------------------------------------------------------------- -void Panel::SetProportional(bool state) -{ - // only do something if the state changes - if( state != _flags.IsFlagSet( IS_PROPORTIONAL ) ) - { - _flags.SetFlag( IS_PROPORTIONAL, state ); - - for(int i=0;iSetProportional( IsProportional() ); - } - } - InvalidateLayout(); -} - - -void Panel::SetKeyBoardInputEnabled( bool state ) -{ - ipanel()->SetKeyBoardInputEnabled( GetVPanel(), state ); - for ( int i = 0; i < GetChildCount(); i++ ) - { - Panel *child = GetChild( i ); - if ( !child ) - { - continue; - } - child->SetKeyBoardInputEnabled( state ); - } - - // If turning off keyboard input enable, then make sure - // this panel is not the current key focus of a parent panel - if ( !state ) - { - Panel *pParent = GetParent(); - if ( pParent ) - { - if ( pParent->GetCurrentKeyFocus() == GetVPanel() ) - { - pParent->RequestFocusNext(); - } - } - } -} - -void Panel::SetMouseInputEnabled( bool state ) -{ - ipanel()->SetMouseInputEnabled( GetVPanel(), state ); - /* for(int i=0;iSetMouseInput(state); - }*/ - vgui::surface()->CalculateMouseVisible(); -} - -bool Panel::IsKeyBoardInputEnabled() -{ - return ipanel()->IsKeyBoardInputEnabled( GetVPanel() ); -} - -bool Panel::IsMouseInputEnabled() -{ - return ipanel()->IsMouseInputEnabled( GetVPanel() ); -} - -class CFloatProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - kv->SetFloat( entry->name(), *(float *)data ); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(float *)data = kv->GetFloat( entry->name() ); - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(float *)data = atof( entry->defaultvalue() ); - } -}; - -class CProportionalFloatProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - float f = *(float *)data; - f = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), f ); - kv->SetFloat( entry->name(), f ); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - float f = kv->GetFloat( entry->name() ); - f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f ); - *(float *)data = f; - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - float f = atof( entry->defaultvalue() ); - f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f ); - *(float *)data = f; - } -}; - -class CIntProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - kv->SetInt( entry->name(), *(int *)data ); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(int *)data = kv->GetInt( entry->name() ); - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(int *)data = atoi( entry->defaultvalue() ); - } -}; - -class CProportionalIntProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - int i = *(int *)data; - i = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), i ); - kv->SetInt( entry->name(), i ); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - int i = kv->GetInt( entry->name() ); - i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i ); - *(int *)data = i; - } - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - int i = atoi( entry->defaultvalue() ); - i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i ); - *(int *)data = i; - } -}; - -class CProportionalIntWithScreenspacePropertyX : public vgui::IPanelAnimationPropertyConverter -{ -public: - int ExtractValue( Panel *panel, const char *pszKey ) - { - int iValue = 0; - bool bRightAlign = false; - bool bCenterAlign = false; - if (pszKey[0] == 'r' || pszKey[0] == 'R') - { - bRightAlign = true; - pszKey++; - } - else if (pszKey[0] == 'c' || pszKey[0] == 'C') - { - bCenterAlign = true; - pszKey++; - } - - // get the value - iValue = atoi(pszKey); - iValue = scheme()->GetProportionalScaledValueEx(panel->GetScheme(), iValue); - - int screenSize = GetScreenSize(); - // now correct the alignment - if ( bRightAlign ) - { - iValue = screenSize - iValue; - } - else if ( bCenterAlign ) - { - iValue = (screenSize / 2) + iValue; - } - - return iValue; - } - - virtual int GetScreenSize( void ) - { - int screenWide, screenTall; - surface()->GetScreenSize(screenWide, screenTall); - return screenWide; - } - - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - // Won't work with this, don't use it. - Assert(0); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(int *)data = ExtractValue( panel, kv->GetString( entry->name() ) ); - } - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(int *)data = ExtractValue( panel, entry->defaultvalue() ); - } -}; - -class CProportionalIntWithScreenspacePropertyY : public CProportionalIntWithScreenspacePropertyX -{ -public: - virtual int GetScreenSize( void ) - { - int screenWide, screenTall; - surface()->GetScreenSize(screenWide, screenTall); - return screenTall; - } -}; - -class CColorProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - kv->SetColor( entry->name(), *(Color *)data ); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); - Assert( scheme ); - if ( scheme ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - - char const *colorName = kv->GetString( entry->name() ); - if ( !colorName || !colorName[0] ) - { - *(Color *)data = kv->GetColor( entry->name() ); - } - else - { - *(Color *)data = scheme->GetColor( colorName, Color( 0, 0, 0, 0 ) ); - } - } - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); - Assert( scheme ); - if ( scheme ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(Color *)data = scheme->GetColor( entry->defaultvalue(), Color( 0, 0, 0, 0 ) ); - } - } -}; - -class CBoolProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - kv->SetInt( entry->name(), *(bool *)data ? 1 : 0 ); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(bool *)data = kv->GetInt( entry->name() ) ? true : false; - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - bool b = false; - if ( !stricmp( entry->defaultvalue(), "true" )|| - atoi( entry->defaultvalue() )!= 0 ) - { - b = true; - } - - *(bool *)data = b; - } -}; - -class CStringProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - kv->SetString( entry->name(), (char *)data ); - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - strcpy( (char *)data, kv->GetString( entry->name() ) ); - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - strcpy( ( char * )data, entry->defaultvalue() ); - } -}; - -class CHFontProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); - Assert( scheme ); - if ( scheme ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - char const *fontName = scheme->GetFontName( *(HFont *)data ); - kv->SetString( entry->name(), fontName ); - } - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); - Assert( scheme ); - if ( scheme ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - char const *fontName = kv->GetString( entry->name() ); - *(HFont *)data = scheme->GetFont( fontName, panel->IsProportional() ); - } - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); - Assert( scheme ); - if ( scheme ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - *(HFont *)data = scheme->GetFont( entry->defaultvalue(), panel->IsProportional() ); - } - } -}; - -class CTextureIdProperty : public vgui::IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - int currentId = *(int *)data; - - // lookup texture name for id - char texturename[ 512 ]; - if ( currentId != -1 && - surface()->DrawGetTextureFile( currentId, texturename, sizeof( texturename ) ) ) - { - kv->SetString( entry->name(), texturename ); - } - else - { - kv->SetString( entry->name(), "" ); - } - } - - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - - int currentId = -1; - - char const *texturename = kv->GetString( entry->name() ); - if ( texturename && texturename[ 0 ] ) - { - currentId = surface()->DrawGetTextureId( texturename ); - if ( currentId == -1 ) - { - currentId = surface()->CreateNewTextureID(); - } - surface()->DrawSetTextureFile( currentId, texturename, false, true ); - } - - *(int *)data = currentId; - } - - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) - { - void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); - - int currentId = -1; - - char const *texturename = entry->defaultvalue(); - if ( texturename && texturename[ 0 ] ) - { - currentId = surface()->DrawGetTextureId( texturename ); - if ( currentId == -1 ) - { - currentId = surface()->CreateNewTextureID(); - } - surface()->DrawSetTextureFile( currentId, texturename, false, true ); - } - - *(int *)data = currentId; - } -}; - -static CFloatProperty floatconverter; -static CProportionalFloatProperty p_floatconverter; -static CIntProperty intconverter; -static CProportionalIntProperty p_intconverter; -static CProportionalIntWithScreenspacePropertyX p_screenspace_intconverter_X; -static CProportionalIntWithScreenspacePropertyY p_screenspace_intconverter_Y; -static CColorProperty colorconverter; -static CBoolProperty boolconverter; -static CStringProperty stringconverter; -static CHFontProperty fontconverter; -static CTextureIdProperty textureidconverter; -//static CProportionalXPosProperty xposconverter; -//static CProportionalYPosProperty yposconverter; - -static CUtlDict< IPanelAnimationPropertyConverter *, int > g_AnimationPropertyConverters; - -static IPanelAnimationPropertyConverter *FindConverter( char const *typeName ) -{ - int lookup = g_AnimationPropertyConverters.Find( typeName ); - if ( lookup == g_AnimationPropertyConverters.InvalidIndex() ) - return NULL; - - IPanelAnimationPropertyConverter *converter = g_AnimationPropertyConverters[ lookup ]; - return converter; -} - -void Panel::AddPropertyConverter( char const *typeName, IPanelAnimationPropertyConverter *converter ) -{ - int lookup = g_AnimationPropertyConverters.Find( typeName ); - if ( lookup != g_AnimationPropertyConverters.InvalidIndex() ) - { - Msg( "Already have converter for type %s, ignoring...\n", typeName ); - return; - } - - g_AnimationPropertyConverters.Insert( typeName, converter ); -} - -//----------------------------------------------------------------------------- -// Purpose: Static method to initialize all needed converters -//----------------------------------------------------------------------------- -void Panel::InitPropertyConverters( void ) -{ - static bool initialized = false; - if ( initialized ) - return; - initialized = true; - - AddPropertyConverter( "float", &floatconverter ); - AddPropertyConverter( "int", &intconverter ); - AddPropertyConverter( "Color", &colorconverter ); - //AddPropertyConverter( "vgui::Color", &colorconverter ); - AddPropertyConverter( "bool", &boolconverter ); - AddPropertyConverter( "char", &stringconverter ); - AddPropertyConverter( "string", &stringconverter ); - AddPropertyConverter( "HFont", &fontconverter ); - AddPropertyConverter( "vgui::HFont", &fontconverter ); - - // This is an aliased type for proportional float - AddPropertyConverter( "proportional_float", &p_floatconverter ); - AddPropertyConverter( "proportional_int", &p_intconverter ); - - AddPropertyConverter( "proportional_xpos", &p_screenspace_intconverter_X ); - AddPropertyConverter( "proportional_ypos", &p_screenspace_intconverter_Y ); - - AddPropertyConverter( "textureid", &textureidconverter ); -} - -bool Panel::InternalRequestInfo( PanelAnimationMap *map, KeyValues *outputData ) -{ - if ( !map ) - return false; - - Assert( outputData ); - - char const *name = outputData->GetName(); - - PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map ); - if ( e ) - { - IPanelAnimationPropertyConverter *converter = FindConverter( e->type() ); - if ( converter ) - { - converter->GetData( this, outputData, e ); - return true; - } - } - - return false; -} - -bool Panel::InternalSetInfo( PanelAnimationMap *map, KeyValues *inputData ) -{ - if ( !map ) - return false; - - Assert( inputData ); - - char const *name = inputData->GetName(); - - PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map ); - if ( e ) - { - IPanelAnimationPropertyConverter *converter = FindConverter( e->type() ); - if ( converter ) - { - converter->SetData( this, inputData, e ); - return true; - } - } - - return false; -} - -PanelAnimationMapEntry *Panel::FindPanelAnimationEntry( char const *scriptname, PanelAnimationMap *map ) -{ - if ( !map ) - return NULL; - - Assert( scriptname ); - - // Look through mapping for entry - int c = map->entries.Count(); - for ( int i = 0; i < c; i++ ) - { - PanelAnimationMapEntry *e = &map->entries[ i ]; - - if ( !stricmp( e->name(), scriptname ) ) - { - return e; - } - } - - // Recurse - if ( map->baseMap ) - { - return FindPanelAnimationEntry( scriptname, map->baseMap ); - } - - return NULL; -} - -// Recursively invoke settings for PanelAnimationVars -void Panel::InternalApplySettings( PanelAnimationMap *map, KeyValues *inResourceData) -{ - // Loop through keys - KeyValues *kv; - - for ( kv = inResourceData->GetFirstSubKey(); kv; kv = kv->GetNextKey() ) - { - char const *varname = kv->GetName(); - - PanelAnimationMapEntry *entry = FindPanelAnimationEntry( varname, GetAnimMap() ); - if ( entry ) - { - // Set value to value from script - IPanelAnimationPropertyConverter *converter = FindConverter( entry->type() ); - if ( converter ) - { - converter->SetData( this, inResourceData, entry ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: sets the default values of all CPanelAnimationVars -//----------------------------------------------------------------------------- -void Panel::InternalInitDefaultValues( PanelAnimationMap *map ) -{ - _flags.ClearFlag( NEEDS_DEFAULT_SETTINGS_APPLIED ); - - // Look through mapping for entry - int c = map->entries.Count(); - for ( int i = 0; i < c; i++ ) - { - PanelAnimationMapEntry *e = &map->entries[ i ]; - Assert( e ); - IPanelAnimationPropertyConverter *converter = FindConverter( e->type() ); - if ( !converter ) - continue; - - converter->InitFromDefault( this, e ); - } - - if ( map->baseMap ) - { - InternalInitDefaultValues( map->baseMap ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -int Panel::GetPaintBackgroundType() -{ - return m_nPaintBackgroundType; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : w - -// h - -//----------------------------------------------------------------------------- -void Panel::GetCornerTextureSize( int& w, int& h ) -{ - if ( m_nBgTextureId1 == -1 ) - { - w = h = 0; - return; - } - surface()->DrawGetTextureSize(m_nBgTextureId1, w, h); -} - -//----------------------------------------------------------------------------- -// Purpose: draws a selection box -//----------------------------------------------------------------------------- -void Panel::DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, bool hollow /*=false*/ ) -{ - if ( m_nBgTextureId1 == -1 || - m_nBgTextureId2 == -1 || - m_nBgTextureId3 == -1 || - m_nBgTextureId4 == -1 ) - { - return; - } - - color[3] *= normalizedAlpha; - - // work out our bounds - int cornerWide, cornerTall; - GetCornerTextureSize( cornerWide, cornerTall ); - - // draw the background in the areas not occupied by the corners - // draw it in three horizontal strips - surface()->DrawSetColor(color); - surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall); - if ( !hollow ) - { - surface()->DrawFilledRect(x, y + cornerTall, x + wide, y + tall - cornerTall); - } - else - { - surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall); - surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall); - } - surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall); - - // draw the corners - - //============================================================================= - // HPE_BEGIN: - // [tj] We now check each individual corner and decide whether to draw it straight or rounded - //============================================================================= - //TOP-LEFT - if (ShouldDrawTopLeftCornerRounded()) - { - surface()->DrawSetTexture(m_nBgTextureId1); - surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); - } - else - { - surface()->DrawFilledRect(x, y, x + cornerWide, y + cornerTall); - } - - - //TOP-RIGHT - if (ShouldDrawTopRightCornerRounded()) - { - surface()->DrawSetTexture(m_nBgTextureId2); - surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); - } - else - { - surface()->DrawFilledRect(x + wide - cornerWide, y, x + wide, y + cornerTall); - } - - //BOTTOM-LEFT - if (ShouldDrawBottomLeftCornerRounded()) - { - surface()->DrawSetTexture(m_nBgTextureId4); - surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); - } - else - { - surface()->DrawFilledRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); - } - - - //BOTTOM-RIGHT - if (ShouldDrawBottomRightCornerRounded()) - { - surface()->DrawSetTexture(m_nBgTextureId3); - surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); - } - else - { - surface()->DrawFilledRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); - } - //============================================================================= - // HPE_END - //============================================================================= -} - -void Panel::DrawBoxFade(int x, int y, int wide, int tall, Color color, float normalizedAlpha, unsigned int alpha0, unsigned int alpha1, bool bHorizontal, bool hollow /*=false*/ ) -{ - if ( m_nBgTextureId1 == -1 || - m_nBgTextureId2 == -1 || - m_nBgTextureId3 == -1 || - m_nBgTextureId4 == -1 || - surface()->DrawGetAlphaMultiplier() == 0 ) - { - return; - } - - color[3] *= normalizedAlpha; - - // work out our bounds - int cornerWide, cornerTall; - GetCornerTextureSize( cornerWide, cornerTall ); - - if ( !bHorizontal ) - { - // draw the background in the areas not occupied by the corners - // draw it in three horizontal strips - surface()->DrawSetColor(color); - surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + cornerTall, alpha0, alpha0, bHorizontal ); - if ( !hollow ) - { - surface()->DrawFilledRectFade(x, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); - } - else - { - surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); - surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); - } - surface()->DrawFilledRectFade(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall, alpha1, alpha1, bHorizontal); - } - else - { - // draw the background in the areas not occupied by the corners - // draw it in three horizontal strips - surface()->DrawSetColor(color); - surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha0, bHorizontal ); - if ( !hollow ) - { - surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + tall, alpha0, alpha1, bHorizontal); - } - else - { - // FIXME: Hollow horz version not implemented - //surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); - //surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); - } - surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha1, alpha1, bHorizontal); - } - - float fOldAlpha = color[ 3 ]; - int iAlpha0 = fOldAlpha * ( static_cast( alpha0 ) / 255.0f ); - int iAlpha1 = fOldAlpha * ( static_cast( alpha1 ) / 255.0f ); - - // draw the corners - if ( !bHorizontal ) - { - color[ 3 ] = iAlpha0; - surface()->DrawSetColor( color ); - surface()->DrawSetTexture(m_nBgTextureId1); - surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); - surface()->DrawSetTexture(m_nBgTextureId2); - surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); - - color[ 3 ] = iAlpha1; - surface()->DrawSetColor( color ); - surface()->DrawSetTexture(m_nBgTextureId3); - surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); - surface()->DrawSetTexture(m_nBgTextureId4); - surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); - } - else - { - color[ 3 ] = iAlpha0; - surface()->DrawSetColor( color ); - surface()->DrawSetTexture(m_nBgTextureId1); - surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); - surface()->DrawSetTexture(m_nBgTextureId4); - surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); - - color[ 3 ] = iAlpha1; - surface()->DrawSetColor( color ); - surface()->DrawSetTexture(m_nBgTextureId2); - surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); - surface()->DrawSetTexture(m_nBgTextureId3); - surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : x - -// y - -// wide - -// tall - -// color - -// normalizedAlpha - -//----------------------------------------------------------------------------- -void Panel::DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha ) -{ - DrawBox( x, y, wide, tall, color, normalizedAlpha, true ); -} - -//============================================================================= -// HPE_BEGIN: -// [menglish] Draws a hollow box similar to the already existing draw hollow box function, but takes the indents as params -//============================================================================= - -void Panel::DrawHollowBox( int x, int y, int wide, int tall, Color color, float normalizedAlpha, int cornerWide, int cornerTall ) -{ - if ( m_nBgTextureId1 == -1 || - m_nBgTextureId2 == -1 || - m_nBgTextureId3 == -1 || - m_nBgTextureId4 == -1 ) - { - return; - } - - color[3] *= normalizedAlpha; - - // draw the background in the areas not occupied by the corners - // draw it in three horizontal strips - surface()->DrawSetColor(color); - surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall); - surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall); - surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall); - surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall); - - // draw the corners - surface()->DrawSetTexture(m_nBgTextureId1); - surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); - surface()->DrawSetTexture(m_nBgTextureId2); - surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); - surface()->DrawSetTexture(m_nBgTextureId3); - surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); - surface()->DrawSetTexture(m_nBgTextureId4); - surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); -} - -//============================================================================= -// HPE_END -//============================================================================= - -//----------------------------------------------------------------------------- -// Purpose: draws a selection box -//----------------------------------------------------------------------------- -void Panel::DrawTexturedBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha ) -{ - if ( m_nBgTextureId1 == -1 ) - return; - - color[3] *= normalizedAlpha; - - surface()->DrawSetColor( color ); - surface()->DrawSetTexture(m_nBgTextureId1); - surface()->DrawTexturedRect(x, y, x + wide, y + tall); -} - -//----------------------------------------------------------------------------- -// Purpose: Marks this panel as draggable (note that children will chain to their parents to see if any parent is draggable) -// Input : enabled - -//----------------------------------------------------------------------------- -void Panel::SetDragEnabled( bool enabled ) -{ -#if defined( VGUI_USEDRAGDROP ) - // If turning it off, quit dragging if mid-drag - if ( !enabled && - m_pDragDrop->m_bDragging ) - { - OnFinishDragging( false, (MouseCode)-1 ); - } - m_pDragDrop->m_bDragEnabled = enabled; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsDragEnabled() const -{ -#if defined( VGUI_USEDRAGDROP ) - return m_pDragDrop->m_bDragEnabled; -#endif - return false; -} - -void Panel::SetShowDragHelper( bool enabled ) -{ -#if defined( VGUI_USEDRAGDROP ) - m_pDragDrop->m_bShowDragHelper = enabled; -#endif -} - -// Use this to prevent chaining up from a parent which can mess with mouse functionality if you don't want to chain up from a child panel to the best -// draggable parent. -void Panel::SetBlockDragChaining( bool block ) -{ -#if defined( VGUI_USEDRAGDROP ) - m_pDragDrop->m_bPreventChaining = block; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsBlockingDragChaining() const -{ -#if defined( VGUI_USEDRAGDROP ) - return m_pDragDrop->m_bPreventChaining; -#endif - return true; -} - - -//----------------------------------------------------------------------------- -// accessors for m_nDragStartTolerance -//----------------------------------------------------------------------------- -int Panel::GetDragStartTolerance() const -{ -#if defined( VGUI_USEDRAGDROP ) - return m_pDragDrop->m_nDragStartTolerance; -#endif - return 0; -} - -void Panel::SetDragSTartTolerance( int nTolerance ) -{ -#if defined( VGUI_USEDRAGDROP ) - m_pDragDrop->m_nDragStartTolerance = nTolerance; -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Marks this panel as droppable ( note that children will chain to their parents to see if any parent is droppable) -// Input : enabled - -//----------------------------------------------------------------------------- -void Panel::SetDropEnabled( bool enabled, float flHoverContextTime /* = 0.0f */ ) -{ -#if defined( VGUI_USEDRAGDROP ) - m_pDragDrop->m_bDropEnabled = enabled; - m_pDragDrop->m_flHoverContextTime = flHoverContextTime; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsDropEnabled() const -{ -#if defined( VGUI_USEDRAGDROP ) - return m_pDragDrop->m_bDropEnabled; -#endif - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Chains up to any parent -// 1) marked DropEnabled; and -// 2) willing to accept the drop payload -// Input : - -// Output : Panel -//----------------------------------------------------------------------------- -Panel *Panel::GetDropTarget( CUtlVector< KeyValues * >& msglist ) -{ -#if defined( VGUI_USEDRAGDROP ) - // Found one - if ( m_pDragDrop->m_bDropEnabled && - IsDroppable( msglist ) ) - { - return this; - } - - // Chain up - if ( GetParent() ) - { - return GetParent()->GetDropTarget( msglist ); - } -#endif - // No luck - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Chains up to first parent marked DragEnabled -// Input : - -// Output : Panel -//----------------------------------------------------------------------------- -Panel *Panel::GetDragPanel() -{ -#if defined( VGUI_USEDRAGDROP ) - // If we encounter a blocker, stop chaining - if ( m_pDragDrop->m_bPreventChaining ) - return NULL; - - if ( m_pDragDrop->m_bDragEnabled ) - return this; - - // Chain up - if ( GetParent() ) - { - return GetParent()->GetDragPanel(); - } -#endif - // No luck - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void Panel::OnStartDragging() -{ -#if defined( VGUI_USEDRAGDROP ) - // Only left mouse initiates drag/drop. - // FIXME: Revisit? - if ( !input()->IsMouseDown( MOUSE_LEFT ) ) - return; - - if ( !m_pDragDrop->m_bDragEnabled ) - return; - - if ( m_pDragDrop->m_bDragging ) - return; - - g_DragDropCapture = this; - - m_pDragDrop->m_bDragStarted = false; - m_pDragDrop->m_bDragging = true; - input()->GetCursorPos( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ] ); - m_pDragDrop->m_nLastPos[ 0 ] = m_pDragDrop->m_nStartPos[ 0 ]; - m_pDragDrop->m_nLastPos[ 1 ] = m_pDragDrop->m_nStartPos[ 1 ]; - - OnContinueDragging(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Called if drag drop is started but not dropped on top of droppable panel... -// Input : - -//----------------------------------------------------------------------------- -void Panel::OnDragFailed( CUtlVector< KeyValues * >& msglist ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void Panel::OnFinishDragging( bool mousereleased, MouseCode code, bool abort /*= false*/ ) -{ -#if defined( VGUI_USEDRAGDROP ) - g_DragDropCapture = NULL; - - if ( !m_pDragDrop->m_bDragEnabled ) - return; - - Assert( m_pDragDrop->m_bDragging ); - - if ( !m_pDragDrop->m_bDragging ) - return; - - int x, y; - input()->GetCursorPos( x, y ); - - m_pDragDrop->m_nLastPos[ 0 ] = x; - m_pDragDrop->m_nLastPos[ 1 ] = y; - - if ( s_DragDropHelper.Get() ) - { - s_DragDropHelper->RemovePanel( this ); - } - - m_pDragDrop->m_bDragging = false; - - CUtlVector< KeyValues * >& data = m_pDragDrop->m_DragData; - int c = data.Count(); - - Panel *target = NULL; - bool shouldDrop = false; - - if ( m_pDragDrop->m_bDragStarted ) - { - char cmd[ 256 ]; - Q_strncpy( cmd, "default", sizeof( cmd ) ); - - if ( mousereleased && - m_pDragDrop->m_hCurrentDrop != 0 && - m_pDragDrop->m_hDropContextMenu.Get() ) - { - Menu *menu = m_pDragDrop->m_hDropContextMenu; - - VPANEL hover = menu->IsWithinTraverse( x, y, false ); - if ( hover ) - { - Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() ); - if ( pHover ) - { - // Figure out if it's a menu item... - int c = menu->GetItemCount(); - for ( int i = 0; i < c; ++i ) - { - int id = menu->GetMenuID( i ); - MenuItem *item = menu->GetMenuItem( id ); - if ( item == pHover ) - { - KeyValues *command = item->GetCommand(); - if ( command ) - { - char const *p = command->GetString( "command", "" ); - if ( p && p[ 0 ] ) - { - Q_strncpy( cmd, p, sizeof( cmd ) ); - } - } - } - } - } - } - - delete menu; - m_pDragDrop->m_hDropContextMenu = NULL; - } - - for ( int i = 0 ; i < c; ++i ) - { - KeyValues *msg = data[ i ]; - - msg->SetString( "command", cmd ); - - msg->SetInt( "screenx", x ); - msg->SetInt( "screeny", y ); - } - - target = m_pDragDrop->m_hCurrentDrop.Get(); - if ( target && !abort ) - { - int localmousex = x, localmousey = y; - // Convert screen space coordintes to coordinates relative to drop window - target->ScreenToLocal( localmousex, localmousey ); - - for ( int i = 0 ; i < c; ++i ) - { - KeyValues *msg = data[ i ]; - - msg->SetInt( "x", localmousex ); - msg->SetInt( "y", localmousey ); - } - - shouldDrop = true; - } - - if ( !shouldDrop ) - { - OnDragFailed( data ); - } - } - - m_pDragDrop->m_bDragStarted = false; - m_pDragDrop->m_DragPanels.RemoveAll(); - m_pDragDrop->m_hCurrentDrop = NULL; - - // Copy data ptrs out of data because OnPanelDropped might cause this panel to be deleted - // and our this ptr will be hosed... - CUtlVector< KeyValues * > temp; - for ( int i = 0 ; i < c; ++i ) - { - temp.AddToTail( data[ i ] ); - } - data.RemoveAll(); - - if ( shouldDrop && target ) - { - target->OnPanelDropped( temp ); - } - for ( int i = 0 ; i < c ; ++i ) - { - temp[ i ]->deleteThis(); - } -#endif -} - -void Panel::OnDropContextHoverShow( CUtlVector< KeyValues * >& msglist ) -{ -} - -void Panel::OnDropContextHoverHide( CUtlVector< KeyValues * >& msglist ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *msg - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsDroppable( CUtlVector< KeyValues * >& msglist ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : startx - -// starty - -// mx - -// my - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::CanStartDragging( int startx, int starty, int mx, int my ) -{ -#if defined( VGUI_USEDRAGDROP ) - if ( IsStartDragWhenMouseExitsPanel() ) - { - ScreenToLocal( mx, my ); - if ( mx < 0 || my < 0 ) - return true; - if ( mx > GetWide() || my > GetTall() ) - return true; - - return false; - } - - int deltax = abs( mx - startx ); - int deltay = abs( my - starty ); - if ( deltax > m_pDragDrop->m_nDragStartTolerance || - deltay > m_pDragDrop->m_nDragStartTolerance ) - { - return true; - } -#endif - return false; -} - -HCursor Panel::GetDropCursor( CUtlVector< KeyValues * >& msglist ) -{ - return dc_arrow; -} - -bool IsSelfDroppable( CUtlVector< KeyValues * > &dragData ) -{ - if ( dragData.Count() == 0 ) - return false; - - KeyValues *pKeyValues( dragData[ 0 ] ); - if ( !pKeyValues ) - return false; - - return pKeyValues->GetInt( "selfDroppable" ) != 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void Panel::OnContinueDragging() -{ -#if defined( VGUI_USEDRAGDROP ) - if ( !m_pDragDrop->m_bDragEnabled ) - return; - - if ( !m_pDragDrop->m_bDragging ) - return; - - int x, y; - input()->GetCursorPos( x, y ); - - // Update last position - m_pDragDrop->m_nLastPos[ 0 ] = x; - m_pDragDrop->m_nLastPos[ 1 ] = y; - - if ( !m_pDragDrop->m_bDragStarted ) - { - if ( CanStartDragging( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ], x, y ) ) - { - m_pDragDrop->m_bDragStarted = true; - CreateDragData(); - } - else - { - return; - } - } - - if ( !s_DragDropHelper.Get() && m_pDragDrop->m_bShowDragHelper ) - { - s_DragDropHelper = new CDragDropHelperPanel(); - s_DragDropHelper->SetKeyBoardInputEnabled( false ); - s_DragDropHelper->SetMouseInputEnabled( false ); - Assert( s_DragDropHelper.Get() ); - } - - if ( !s_DragDropHelper.Get() ) - return; - - s_DragDropHelper->AddPanel( this ); - - Assert( m_pDragDrop->m_DragData.Count() ); - - vgui::PHandle oldDrop = m_pDragDrop->m_hCurrentDrop; - - // See what's under that - m_pDragDrop->m_hCurrentDrop = NULL; - - // Search under mouse pos... - Panel *dropTarget = FindDropTargetPanel(); - if ( dropTarget ) - { - dropTarget = dropTarget->GetDropTarget( m_pDragDrop->m_DragData ); - } - - // it's not okay until we find a droppable panel - surface()->SetCursor( dc_no ); - - if ( dropTarget ) - { - if ( dropTarget != this || IsSelfDroppable( m_pDragDrop->m_DragData ) ) - { - m_pDragDrop->m_hCurrentDrop = dropTarget; - surface()->SetCursor( dropTarget->GetDropCursor( m_pDragDrop->m_DragData ) ); - } - } - - if ( m_pDragDrop->m_hCurrentDrop.Get() != oldDrop.Get() ) - { - if ( oldDrop.Get() ) - { - oldDrop->OnPanelExitedDroppablePanel( m_pDragDrop->m_DragData ); - } - - if ( m_pDragDrop->m_hCurrentDrop.Get() ) - { - m_pDragDrop->m_hCurrentDrop->OnPanelEnteredDroppablePanel( m_pDragDrop->m_DragData ); - m_pDragDrop->m_hCurrentDrop->OnDropContextHoverHide( m_pDragDrop->m_DragData ); - - // Reset hover time - m_pDragDrop->m_lDropHoverTime = system()->GetTimeMillis(); - m_pDragDrop->m_bDropMenuShown = false; - } - - // Discard any stale context menu... - if ( m_pDragDrop->m_hDropContextMenu.Get() ) - { - delete m_pDragDrop->m_hDropContextMenu.Get(); - } - } - - if ( m_pDragDrop->m_hCurrentDrop != 0 && - m_pDragDrop->m_hDropContextMenu.Get() ) - { - Menu *menu = m_pDragDrop->m_hDropContextMenu; - - VPANEL hover = menu->IsWithinTraverse( x, y, false ); - if ( hover ) - { - Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() ); - if ( pHover ) - { - // Figure out if it's a menu item... - int c = menu->GetItemCount(); - for ( int i = 0; i < c; ++i ) - { - int id = menu->GetMenuID( i ); - MenuItem *item = menu->GetMenuItem( id ); - if ( item == pHover ) - { - menu->SetCurrentlyHighlightedItem( id ); - } - } - } - } - else - { - menu->ClearCurrentlyHighlightedItem(); - } - } -#endif -} - -#if defined( VGUI_USEDRAGDROP ) -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : DragDrop_t -//----------------------------------------------------------------------------- -DragDrop_t *Panel::GetDragDropInfo() -{ - Assert( m_pDragDrop ); - return m_pDragDrop; -} -#endif - -void Panel::OnGetAdditionalDragPanels( CUtlVector< Panel * >& dragabbles ) -{ - // Nothing here -} - -//----------------------------------------------------------------------------- -// Purpose: Virtual method to allow panels to add to the default values -// Input : *msg - -//----------------------------------------------------------------------------- -void Panel::OnCreateDragData( KeyValues *msg ) -{ - // These values are filled in for you: - // "panel" ptr to panel being dropped - // "screenx", "screeny" - drop cursor pos in screen space - // "x", "y" - drop coordinates relative to this window (the window being dropped upon) -} - -// Called if m_flHoverContextTime was non-zero, allows droppee to preview the drop data and show an appropriate menu -bool Panel::GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist ) -{ - return false; -} - -void Panel::CreateDragData() -{ -#if defined( VGUI_USEDRAGDROP ) - int i, c; - - if ( m_pDragDrop->m_DragData.Count() ) - { - return; - } - - PHandle h; - h = this; - m_pDragDrop->m_DragPanels.AddToTail( h ); - - CUtlVector< Panel * > temp; - OnGetAdditionalDragPanels( temp ); - c = temp.Count(); - for ( i = 0; i < c; ++i ) - { - h = temp[ i ]; - m_pDragDrop->m_DragPanels.AddToTail( h ); - } - - c = m_pDragDrop->m_DragPanels.Count(); - for ( i = 0 ; i < c; ++i ) - { - Panel *sibling = m_pDragDrop->m_DragPanels[ i ].Get(); - if ( !sibling ) - { - continue; - } - - KeyValues *msg = new KeyValues( "DragDrop" ); - msg->SetPtr( "panel", sibling ); - - sibling->OnCreateDragData( msg ); - - m_pDragDrop->m_DragData.AddToTail( msg ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : KeyValues -//----------------------------------------------------------------------------- -void Panel::GetDragData( CUtlVector< KeyValues * >& list ) -{ -#if defined( VGUI_USEDRAGDROP ) - int i, c; - - list.RemoveAll(); - - c = m_pDragDrop->m_DragData.Count(); - for ( i = 0 ; i < c; ++i ) - { - list.AddToTail( m_pDragDrop->m_DragData[ i ] ); - } -#endif -} - -#if defined( VGUI_USEDRAGDROP ) -CDragDropHelperPanel::CDragDropHelperPanel() : BaseClass( NULL, "DragDropHelper" ) -{ - SetVisible( true ); - SetPaintEnabled( false ); - SetPaintBackgroundEnabled( false ); - SetMouseInputEnabled( false ); - SetKeyBoardInputEnabled( false ); - // SetCursor( dc_none ); - ipanel()->SetTopmostPopup( GetVPanel(), true ); - int w, h; - surface()->GetScreenSize( w, h ); - SetBounds( 0, 0, w, h ); - - SetPostChildPaintEnabled( true ); - - MakePopup( false ); -} - -VPANEL CDragDropHelperPanel::IsWithinTraverse(int x, int y, bool traversePopups) -{ - return (VPANEL)0; -} - -void CDragDropHelperPanel::PostChildPaint() -{ - int c = m_PaintList.Count(); - for ( int i = c - 1; i >= 0 ; --i ) - { - DragHelperPanel_t& data = m_PaintList[ i ]; - - Panel *panel = data.m_hPanel.Get(); - if ( !panel ) - { - m_PaintList.Remove( i ); - continue; - } - - Panel *dropPanel = panel->GetDragDropInfo()->m_hCurrentDrop.Get(); - if ( panel ) - { - if ( !dropPanel ) - { - panel->OnDraggablePanelPaint(); - } - else - { - CUtlVector< Panel * > temp; - CUtlVector< PHandle >& data = panel->GetDragDropInfo()->m_DragPanels; - CUtlVector< KeyValues * >& msglist = panel->GetDragDropInfo()->m_DragData; - int i, c; - c = data.Count(); - for ( i = 0; i < c ; ++i ) - { - Panel *pPanel = data[ i ].Get(); - if ( pPanel ) - { - temp.AddToTail( pPanel ); - } - } - - dropPanel->OnDroppablePanelPaint( msglist, temp ); - } - } - } - - if ( c == 0 ) - { - MarkForDeletion(); - } -} - -void CDragDropHelperPanel::AddPanel( Panel *current ) -{ - if ( !current ) - return; - - Menu *hover = current->GetDragDropInfo()->m_hDropContextMenu.Get(); - - surface()->MovePopupToFront( GetVPanel() ); - if ( hover && hover->IsPopup() ) - { - surface()->MovePopupToFront( hover->GetVPanel() ); - } - - int c = m_PaintList.Count(); - for ( int i = 0; i < c; ++i ) - { - if ( m_PaintList[ i ].m_hPanel.Get() == current ) - return; - } - - DragHelperPanel_t data; - data.m_hPanel = current; - m_PaintList.AddToTail( data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *search - -//----------------------------------------------------------------------------- -void CDragDropHelperPanel::RemovePanel( Panel *search ) -{ - int c = m_PaintList.Count(); - for ( int i = c - 1 ; i >= 0; --i ) - { - if ( m_PaintList[ i ].m_hPanel.Get() == search ) - { - m_PaintList.Remove( i ); - return; - } - } -} -#endif -//----------------------------------------------------------------------------- -// Purpose: Enumerates panels under mouse x,y -// Input : panelList - -// x - -// y - -// check - -//----------------------------------------------------------------------------- -void Panel::FindDropTargetPanel_R( CUtlVector< VPANEL >& panelList, int x, int y, VPANEL check ) -{ -#if defined( VGUI_USEDRAGDROP ) - if ( !ipanel()->IsFullyVisible( check ) ) - return; - - if ( ::ShouldHandleInputMessage( check ) && ipanel()->IsWithinTraverse( check, x, y, false ) ) - { - panelList.AddToTail( check ); - } - - CUtlVector< VPANEL > &children = ipanel()->GetChildren( check ); - int childCount = children.Count(); - for ( int i = 0; i < childCount; i++ ) - { - VPANEL child = children[ i ]; - FindDropTargetPanel_R( panelList, x, y, child ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Panel -//----------------------------------------------------------------------------- -Panel *Panel::FindDropTargetPanel() -{ -#if defined( VGUI_USEDRAGDROP ) - if ( !s_DragDropHelper.Get() ) - return NULL; - - CUtlVector< VPANEL > hits; - - int x, y; - input()->GetCursorPos( x, y ); - - VPANEL embedded = surface()->GetEmbeddedPanel(); - VPANEL helper = s_DragDropHelper.Get()->GetVPanel(); - - if ( surface()->IsCursorVisible() && surface()->IsWithin(x, y) ) - { - // faster version of code below - // checks through each popup in order, top to bottom windows - int c = surface()->GetPopupCount(); - for (int i = c - 1; i >= 0 && hits.Count() == 0; i--) - { - VPANEL popup = surface()->GetPopup(i); - if ( popup == embedded ) - continue; - - // Don't return helper panel!!! - if ( popup == helper ) - continue; - - if ( !ipanel()->IsFullyVisible( popup ) ) - continue; - - FindDropTargetPanel_R( hits, x, y, popup ); - } - - // Check embedded - if ( !hits.Count() ) - { - FindDropTargetPanel_R( hits, x, y, embedded ); - } - } - - // Nothing under mouse... - if ( !hits.Count() ) - return NULL; - - // Return topmost panel under mouse, if it's visible to this .dll - Panel *panel = NULL; - int nCount = hits.Count(); - while ( --nCount >= 0 ) - { - panel = ipanel()->GetPanel( hits[ nCount ], GetModuleName() ); - if ( panel ) - return panel; - } -#endif - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Mouse is on draggable panel and has started moving, but is not over a droppable panel yet -// Input : - -//----------------------------------------------------------------------------- -void Panel::OnDraggablePanelPaint() -{ -#if defined( VGUI_USEDRAGDROP ) - int sw, sh; - GetSize( sw, sh ); - - int x, y; - input()->GetCursorPos( x, y ); - int w, h; - - w = min( sw, 80 ); - h = min( sh, 80 ); - x -= ( w >> 1 ); - y -= ( h >> 1 ); - - surface()->DrawSetColor( m_clrDragFrame ); - surface()->DrawOutlinedRect( x, y, x + w, y + h ); - - if ( m_pDragDrop->m_DragPanels.Count() > 1 ) - { - surface()->DrawSetTextColor( m_clrDragFrame ); - surface()->DrawSetTextFont( m_infoFont ); - surface()->DrawSetTextPos( x + 5, y + 2 ); - - wchar_t sz[ 64 ]; - V_swprintf_safe( sz, L"[ %i ]", m_pDragDrop->m_DragPanels.Count() ); - - surface()->DrawPrintText( sz, wcslen( sz ) ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Mouse is now over a droppable panel -// Input : *dragPanel - -//----------------------------------------------------------------------------- -void Panel::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels ) -{ -#if defined( VGUI_USEDRAGDROP ) - if ( !dragPanels.Count() ) - return; - - // Convert this panel's bounds to screen space - int w, h; - GetSize( w, h ); - - int x, y; - x = y = 0; - LocalToScreen( x, y ); - - surface()->DrawSetColor( m_clrDropFrame ); - // Draw 2 pixel frame - surface()->DrawOutlinedRect( x, y, x + w, y + h ); - surface()->DrawOutlinedRect( x+1, y+1, x + w-1, y + h-1 ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Color -//----------------------------------------------------------------------------- -Color Panel::GetDropFrameColor() -{ -#if defined( VGUI_USEDRAGDROP ) - return m_clrDropFrame; -#endif - return Color(0, 0, 0, 0); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Color -//----------------------------------------------------------------------------- -Color Panel::GetDragFrameColor() -{ -#if defined( VGUI_USEDRAGDROP ) - return m_clrDragFrame; -#endif - return Color(0, 0, 0, 0); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *data - -//----------------------------------------------------------------------------- -void Panel::OnPanelDropped( CUtlVector< KeyValues * >& data ) -{ - // Empty. Derived classes would implement handlers here -} - -//----------------------------------------------------------------------------- -// called on droptarget when draggable panel enters droptarget -//----------------------------------------------------------------------------- -void Panel::OnPanelEnteredDroppablePanel( CUtlVector< KeyValues * >& msglist ) -{ - // Empty. Derived classes would implement handlers here -} - -//----------------------------------------------------------------------------- -// called on droptarget when draggable panel exits droptarget -//----------------------------------------------------------------------------- -void Panel::OnPanelExitedDroppablePanel ( CUtlVector< KeyValues * >& msglist ) -{ - // Empty. Derived classes would implement handlers here -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void Panel::DragDropStartDragging() -{ -#if defined( VGUI_USEDRAGDROP ) - // We somehow missed a mouse release, cancel the previous drag - if ( g_DragDropCapture.Get() ) - { - if ( HasParent( g_DragDropCapture.Get()->GetVPanel() ) ) - return; - - bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted; - g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1 ); - if ( started ) - { - return; - } - } - - // Find actual target panel - Panel *panel = GetDragPanel(); - if ( !panel ) - return; - - DragDrop_t *data = panel->GetDragDropInfo(); - if ( !data ) - return; - - if ( !panel->IsDragEnabled() ) - return; - - if ( data->m_bDragging ) - return; - - panel->OnStartDragging(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Panel::IsBeingDragged() -{ -#if defined( VGUI_USEDRAGDROP ) - if ( !g_DragDropCapture.Get() ) - return false; - - if ( g_DragDropCapture.Get() == this ) - return true; - - // If we encounter a blocker, stop chaining - if ( m_pDragDrop->m_bPreventChaining ) - return false; - - // Chain up - if ( GetParent() ) - { - return GetParent()->IsBeingDragged(); - } -#endif - // No luck - return false; -} - -struct srect_t -{ - int x0, y0; - int x1, y1; - - bool IsDegenerate() - { - if ( x1 - x0 <= 0 ) - return true; - if ( y1 - y0 <= 0 ) - return true; - return false; - } -}; - -// Draws a filled rect of specified bounds, but omits the bounds of the skip panel from those bounds -void Panel::FillRectSkippingPanel( const Color &clr, int x, int y, int w, int h, Panel *skipPanel ) -{ - int sx = 0, sy = 0, sw, sh; - skipPanel->GetSize( sw, sh ); - skipPanel->LocalToScreen( sx, sy ); - ScreenToLocal( sx, sy ); - - surface()->DrawSetColor( clr ); - - srect_t r1; - r1.x0 = x; - r1.y0 = y; - r1.x1 = x + w; - r1.y1 = y + h; - - srect_t r2; - r2.x0 = sx; - r2.y0 = sy; - r2.x1 = sx + sw; - r2.y1 = sy + sh; - - int topy = r1.y0; - int bottomy = r1.y1; - - // We'll descend vertically and draw: - // 1 a possible bar across the top - // 2 a possible bar across the bottom - // 3 possible left bar - // 4 possible right bar - - // Room at top? - if ( r2.y0 > r1.y0 ) - { - topy = r2.y0; - - surface()->DrawFilledRect( r1.x0, r1.y0, r1.x1, topy ); - } - - // Room at bottom? - if ( r2.y1 < r1.y1 ) - { - bottomy = r2.y1; - - surface()->DrawFilledRect( r1.x0, bottomy, r1.x1, r1.y1 ); - } - - // Room on left side? - if ( r2.x0 > r1.x0 ) - { - int left = r2.x0; - - surface()->DrawFilledRect( r1.x0, topy, left, bottomy ); - } - - // Room on right side - if ( r2.x1 < r1.x1 ) - { - int right = r2.x1; - - surface()->DrawFilledRect( right, topy, r1.x1, bottomy ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *child - -//----------------------------------------------------------------------------- -void Panel::SetSkipChildDuringPainting( Panel *child ) -{ - m_SkipChild = child; -} - -HPanel Panel::ToHandle() const -{ - return ivgui()->PanelToHandle( _vpanel ); -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::NavigateUp() -{ - Panel *target = GetNavUp(); - if ( target ) - { - NavigateFrom(); - target->m_LastNavDirection = ND_UP; - target->NavigateTo(); - } - - return target; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::NavigateDown() -{ - Panel *target = GetNavDown(); - if ( target ) - { - NavigateFrom(); - target->m_LastNavDirection = ND_DOWN; - target->NavigateTo(); - } - - return target; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::NavigateLeft() -{ - Panel *target = GetNavLeft(); - if ( target ) - { - NavigateFrom(); - target->m_LastNavDirection = ND_LEFT; - target->NavigateTo(); - } - return target; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::NavigateRight() -{ - Panel *target = GetNavRight(); - if ( target ) - { - NavigateFrom(); - target->m_LastNavDirection = ND_RIGHT; - target->NavigateTo(); - } - return target; -} - -Panel* Panel::NavigateActivate() -{ - Panel *target = GetNavActivate(); - if ( target ) - { - NavigateFrom(); - target->m_LastNavDirection = ND_NONE; - target->NavigateTo(); - } - return target; -} - -Panel* Panel::NavigateBack() -{ - Panel *target = GetNavBack(); - if ( target ) - { - NavigateFrom(); - target->m_LastNavDirection = ND_NONE; - target->NavigateTo(); - } - return target; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::NavigateTo() -{ - if ( IsX360() ) - { - RequestFocus( 0 ); - } - - CallParentFunction( new KeyValues( "OnNavigateTo", "panelName", GetName() ) ); - - Panel *target = GetNavToRelay(); - if ( target ) - { - NavigateFrom(); - target->m_LastNavDirection = ND_NONE; - NavigateToChild( target ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::NavigateFrom() -{ - for ( int i = 0; i < GetChildCount(); ++i ) - { - Panel* currentNav = GetChild(i); - if ( currentNav != 0 ) - { - currentNav->NavigateFrom(); - } - } - - CallParentFunction( new KeyValues( "OnNavigateFrom", "panelName", GetName() ) ); - - if ( m_pTooltips ) - { - m_pTooltips->HideTooltip(); - } - - m_LastNavDirection = ND_NONE; -} - -void Panel::NavigateToChild( Panel *pNavigateTo ) -{ - for( int i = 0; i != GetChildCount(); ++i ) - { - vgui::Panel *pChild = GetChild(i); - if( pChild ) - pChild->NavigateFrom(); - } - pNavigateTo->NavigateTo(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::SetNavUp( Panel* navUp ) -{ - Panel* lastNav = m_NavUp; - m_NavUp = navUp; - - if( navUp ) - m_sNavUpName = navUp->GetName(); - else - m_sNavUpName.Clear(); - - return lastNav; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::SetNavDown( Panel* navDown ) -{ - Panel* lastNav = m_NavDown; - m_NavDown = navDown; - - if( navDown ) - m_sNavDownName = navDown->GetName(); - else - m_sNavDownName.Clear(); - - return lastNav; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::SetNavLeft( Panel* navLeft ) -{ - Panel* lastNav = m_NavLeft; - m_NavLeft = navLeft; - - if( navLeft ) - m_sNavLeftName = navLeft->GetName(); - else - m_sNavLeftName.Clear(); - - return lastNav; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel* Panel::SetNavRight( Panel* navRight ) -{ - Panel* lastNav = m_NavRight; - m_NavRight = navRight; - - if( navRight ) - m_sNavRightName = navRight->GetName(); - else - m_sNavRightName.Clear(); - - return lastNav; -} - -Panel* Panel::SetNavToRelay( Panel* navToRelay ) -{ - Panel* lastNav = m_NavToRelay; - m_NavToRelay = navToRelay; - - return lastNav; -} - -Panel* Panel::SetNavActivate( Panel* navActivate ) -{ - Panel* lastNav = m_NavActivate; - m_NavActivate = navActivate; - - return lastNav; -} - -Panel* Panel::SetNavBack( Panel* navBack ) -{ - Panel* lastNav = m_NavBack; - m_NavBack = navBack; - - return lastNav; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Panel::NAV_DIRECTION Panel::GetLastNavDirection() -{ - return m_LastNavDirection; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::OnNavigateTo( const char* panelName ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::OnNavigateFrom( const char* panelName ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetNavUp( const char* controlName ) -{ - if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) - { - m_NavUp = NULL; - m_sNavUpName = controlName; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetNavDown( const char* controlName ) -{ - if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) - { - m_NavDown = NULL; - m_sNavDownName = controlName; - } -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetNavLeft( const char* controlName ) -{ - if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) - { - m_NavLeft = NULL; - m_sNavLeftName = controlName; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Panel::SetNavRight( const char* controlName ) -{ - if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) - { - m_NavRight = NULL; - m_sNavRightName = controlName; - } -} - -void Panel::SetNavToRelay( const char* controlName ) -{ - if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) - { - m_NavToRelay = NULL; - m_sNavToRelayName = controlName; - } -} - -void Panel::SetNavActivate( const char* controlName ) -{ - if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) - { - m_NavActivate = NULL; - m_sNavActivateName = controlName; - } -} - -void Panel::SetNavBack( const char* controlName ) -{ - if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) - { - m_NavBack = NULL; - m_sNavBackName = controlName; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -vgui::Panel* Panel::GetNavUp( Panel *first ) -{ - if ( !m_NavUp && m_sNavUpName.Length() > 0 ) - { - Panel *pParent = GetParent(); - const char *pName = m_sNavUpName.String(); - while ( pParent && pName[ 0 ] == '<' ) - { - pParent = pParent->GetParent(); - pName++; - } - - if ( !pParent ) - { - return NULL; - } - - Panel *foundPanel = pParent->FindChildByName( pName, true ); - if ( foundPanel != 0 ) - { - m_NavUp = foundPanel; - } - } - - vgui::Panel* nextPanel = m_NavUp; - if( m_NavUp && m_NavUp != first && !m_NavUp->IsVisible() ) - { - Panel *firstPanel = first == NULL ? this : first; - nextPanel = nextPanel->GetNavUp( firstPanel ); - } - - return nextPanel; -} - -vgui::Panel* Panel::GetNavDown( Panel *first ) -{ - if ( !m_NavDown && m_sNavDownName.Length() > 0 ) - { - Panel *pParent = GetParent(); - const char *pName = m_sNavDownName.String(); - while ( pParent && pName[ 0 ] == '<' ) - { - pParent = pParent->GetParent(); - pName++; - } - - if ( !pParent ) - { - return NULL; - } - - Panel* foundPanel = pParent->FindChildByName( pName, true ); - if ( foundPanel != 0 ) - { - m_NavDown = foundPanel->GetPanel(); - } - } - - vgui::Panel* nextPanel = m_NavDown; - if( m_NavDown && m_NavDown != first && !m_NavDown->IsVisible() ) - { - Panel *firstPanel = first == NULL ? this : first; - nextPanel = nextPanel->GetNavDown( firstPanel ); - } - - return nextPanel; -} - -vgui::Panel* Panel::GetNavLeft( Panel *first ) -{ - if ( !m_NavLeft && m_sNavLeftName.Length() > 0 ) - { - Panel *pParent = GetParent(); - const char *pName = m_sNavLeftName.String(); - while ( pParent && pName[ 0 ] == '<' ) - { - pParent = pParent->GetParent(); - pName++; - } - - if ( !pParent ) - { - return NULL; - } - - Panel* foundPanel = pParent->FindChildByName( pName, true ); - if ( foundPanel != 0 ) - { - m_NavLeft = foundPanel->GetPanel(); - } - } - - vgui::Panel* nextPanel = m_NavLeft; - if( m_NavLeft && m_NavLeft != first && !m_NavLeft->IsVisible() ) - { - Panel *firstPanel = first == NULL ? this : first; - nextPanel = nextPanel->GetNavLeft( firstPanel ); - } - - return nextPanel; -} - -vgui::Panel* Panel::GetNavRight( Panel *first ) -{ - if ( !m_NavRight && m_sNavRightName.Length() > 0 ) - { - Panel *pParent = GetParent(); - const char *pName = m_sNavRightName.String(); - while ( pParent && pName[ 0 ] == '<' ) - { - pParent = pParent->GetParent(); - pName++; - } - - if ( !pParent ) - { - return NULL; - } - - Panel* foundPanel = pParent->FindChildByName( pName, true ); - if ( foundPanel != 0 ) - { - m_NavRight = foundPanel->GetPanel(); - } - } - - vgui::Panel* nextPanel = m_NavRight; - if( m_NavRight && m_NavRight != first && !m_NavRight->IsVisible() ) - { - Panel *firstPanel = first == NULL ? this : first; - nextPanel = nextPanel->GetNavRight( firstPanel ); - } - - return nextPanel; -} - -vgui::Panel* Panel::GetNavToRelay( Panel *first ) -{ - if ( !m_NavToRelay && m_sNavToRelayName.Length() > 0 ) - { - Panel *pParent = this; - const char *pName = m_sNavToRelayName.String(); - while ( pParent && pName[ 0 ] == '<' ) - { - pParent = pParent->GetParent(); - pName++; - } - - if ( !pParent ) - { - return NULL; - } - - Panel* foundPanel = pParent->FindChildByName( pName, true ); - if ( foundPanel != 0 ) - { - m_NavToRelay = foundPanel->GetPanel(); - } - } - - vgui::Panel* nextPanel = m_NavToRelay; - if ( m_NavToRelay && m_NavToRelay != first && !m_NavToRelay->IsVisible() ) - { - Panel *firstPanel = first == NULL ? this : first; - nextPanel = nextPanel->GetNavToRelay( firstPanel ); - } - - return nextPanel; -} - -vgui::Panel* Panel::GetNavActivate( Panel *first ) -{ - if ( !m_NavActivate && m_sNavActivateName.Length() > 0 ) - { - Panel *pParent = GetParent(); - const char *pName = m_sNavActivateName.String(); - while ( pParent && pName[ 0 ] == '<' ) - { - pParent = pParent->GetParent(); - pName++; - } - - if ( !pParent ) - { - return NULL; - } - - Panel* foundPanel = pParent->FindChildByName( pName, true ); - if ( foundPanel != 0 ) - { - m_NavActivate = foundPanel->GetPanel(); - } - } - - vgui::Panel* nextPanel = m_NavActivate; - if ( m_NavActivate && m_NavActivate != first && !m_NavActivate->IsVisible() ) - { - Panel *firstPanel = first == NULL ? this : first; - nextPanel = nextPanel->GetNavActivate( firstPanel ); - } - - return nextPanel; -} - -vgui::Panel* Panel::GetNavBack( Panel *first ) -{ - if ( !m_NavBack && m_sNavBackName.Length() > 0 ) - { - Panel *pParent = GetParent(); - const char *pName = m_sNavBackName.String(); - while ( pParent && pName[ 0 ] == '<' ) - { - pParent = pParent->GetParent(); - pName++; - } - - if ( !pParent ) - { - return NULL; - } - - Panel *foundPanel = pParent->FindChildByName( pName ); - if ( foundPanel ) - { - m_NavBack = foundPanel; - } - } - - vgui::Panel* nextPanel = m_NavBack; - if ( m_NavBack && m_NavBack != first && !m_NavBack->IsVisible() ) - { - Panel *firstPanel = first == NULL ? this : first; - nextPanel = nextPanel->GetNavBack( firstPanel ); - } - - return nextPanel; -} - -vgui::Panel* Panel::GetNavUpPanel() -{ - return m_NavUp; -} - -vgui::Panel* Panel::GetNavDownPanel() -{ - return m_NavDown; -} - -vgui::Panel* Panel::GetNavLeftPanel() -{ - return m_NavLeft; -} - -vgui::Panel* Panel::GetNavRightPanel() -{ - return m_NavRight; -} - -vgui::Panel* Panel::GetNavToRelayPanel() -{ - return m_NavToRelay; -} - -vgui::Panel* Panel::GetNavActivatePanel() -{ - return m_NavActivate; -} - -vgui::Panel* Panel::GetNavBackPanel() -{ - return m_NavBack; -} - -void Panel::SetConsoleStylePanel( bool bConsoleStyle ) -{ - m_bIsConsoleStylePanel = bConsoleStyle; -} - -bool Panel::IsConsoleStylePanel() const -{ - return m_bIsConsoleStylePanel; -} - -//----------------------------------------------------------------------------- -// Purpose: Utility class for handling message map allocation -//----------------------------------------------------------------------------- -class CPanelMessageMapDictionary -{ -public: - CPanelMessageMapDictionary() : m_PanelMessageMapPool( sizeof(PanelMessageMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelMessageMapDictionary::m_PanelMessageMapPool" ) - { - m_MessageMaps.RemoveAll(); - } - - PanelMessageMap *FindOrAddPanelMessageMap( char const *className ); - PanelMessageMap *FindPanelMessageMap( char const *className ); -private: - - struct PanelMessageMapDictionaryEntry - { - PanelMessageMap *map; - }; - - char const *StripNamespace( char const *className ); - - CUtlDict< PanelMessageMapDictionaryEntry, int > m_MessageMaps; - CUtlMemoryPool m_PanelMessageMapPool; -}; - - -char const *CPanelMessageMapDictionary::StripNamespace( char const *className ) -{ - if ( !strnicmp( className, "vgui::", 6 ) ) - { - return className + 6; - } - return className; -} - -//----------------------------------------------------------------------------- -// Purpose: Find but don't add mapping -//----------------------------------------------------------------------------- -PanelMessageMap *CPanelMessageMapDictionary::FindPanelMessageMap( char const *className ) -{ - int lookup = m_MessageMaps.Find( StripNamespace( className ) ); - if ( lookup != m_MessageMaps.InvalidIndex() ) - { - return m_MessageMaps[ lookup ].map; - } - return NULL; -} - -#include -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -PanelMessageMap *CPanelMessageMapDictionary::FindOrAddPanelMessageMap( char const *className ) -{ - PanelMessageMap *map = FindPanelMessageMap( className ); - if ( map ) - return map; - - PanelMessageMapDictionaryEntry entry; - // use the alloc in place method of new - entry.map = new (m_PanelMessageMapPool.Alloc(sizeof(PanelMessageMap))) PanelMessageMap; - Construct(entry.map); - m_MessageMaps.Insert( StripNamespace( className ), entry ); - return entry.map; -} -#include - -#if defined( VGUI_USEKEYBINDINGMAPS ) -//----------------------------------------------------------------------------- -// Purpose: Utility class for handling keybinding map allocation -//----------------------------------------------------------------------------- -class CPanelKeyBindingMapDictionary -{ -public: - CPanelKeyBindingMapDictionary() : m_PanelKeyBindingMapPool( sizeof(PanelKeyBindingMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelKeyBindingMapDictionary::m_PanelKeyBindingMapPool" ) - { - m_MessageMaps.RemoveAll(); - } - - PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className ); - PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className ); -private: - - struct PanelKeyBindingMapDictionaryEntry - { - PanelKeyBindingMap *map; - }; - - char const *StripNamespace( char const *className ); - - CUtlDict< PanelKeyBindingMapDictionaryEntry, int > m_MessageMaps; - CUtlMemoryPool m_PanelKeyBindingMapPool; -}; - - -char const *CPanelKeyBindingMapDictionary::StripNamespace( char const *className ) -{ - if ( !strnicmp( className, "vgui::", 6 ) ) - { - return className + 6; - } - return className; -} - -//----------------------------------------------------------------------------- -// Purpose: Find but don't add mapping -//----------------------------------------------------------------------------- -PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindPanelKeyBindingMap( char const *className ) -{ - int lookup = m_MessageMaps.Find( StripNamespace( className ) ); - if ( lookup != m_MessageMaps.InvalidIndex() ) - { - return m_MessageMaps[ lookup ].map; - } - return NULL; -} - -#include -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindOrAddPanelKeyBindingMap( char const *className ) -{ - PanelKeyBindingMap *map = FindPanelKeyBindingMap( className ); - if ( map ) - return map; - - PanelKeyBindingMapDictionaryEntry entry; - // use the alloc in place method of new - entry.map = new (m_PanelKeyBindingMapPool.Alloc(sizeof(PanelKeyBindingMap))) PanelKeyBindingMap; - Construct(entry.map); - m_MessageMaps.Insert( StripNamespace( className ), entry ); - return entry.map; -} - -#include - -CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary() -{ - static CPanelKeyBindingMapDictionary dictionary; - return dictionary; -} - -#endif // VGUI_USEKEYBINDINGMAPS - -CPanelMessageMapDictionary& GetPanelMessageMapDictionary() -{ - static CPanelMessageMapDictionary dictionary; - return dictionary; -} - -namespace vgui -{ - - //----------------------------------------------------------------------------- - // Purpose: - //----------------------------------------------------------------------------- - PanelMessageMap *FindOrAddPanelMessageMap( char const *className ) - { - return GetPanelMessageMapDictionary().FindOrAddPanelMessageMap( className ); - } - - //----------------------------------------------------------------------------- - // Purpose: Find but don't add mapping - //----------------------------------------------------------------------------- - PanelMessageMap *FindPanelMessageMap( char const *className ) - { - return GetPanelMessageMapDictionary().FindPanelMessageMap( className ); - } - -#if defined( VGUI_USEKEYBINDINGMAPS ) - CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary() - { - static CPanelKeyBindingMapDictionary dictionary; - return dictionary; - } - //----------------------------------------------------------------------------- - // Purpose: - //----------------------------------------------------------------------------- - PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className ) - { - return GetPanelKeyBindingMapDictionary().FindOrAddPanelKeyBindingMap( className ); - } - - //----------------------------------------------------------------------------- - // Purpose: Find but don't add mapping - //----------------------------------------------------------------------------- - PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className ) - { - return GetPanelKeyBindingMapDictionary().FindPanelKeyBindingMap( className ); - } -#endif // VGUI_USEKEYBINDINGMAPS - -SortedPanel_t::SortedPanel_t( Panel *panel ) -{ - pPanel = panel; pButton = dynamic_cast< Button* >( panel ); -} - - -void VguiPanelGetSortedChildPanelList( Panel *pParentPanel, void *pSortedPanels ) -{ - CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels ); - - for ( int i = 0; i < pParentPanel->GetChildCount(); i++ ) - { - // perform auto-layout on the child panel - Panel *pPanel = pParentPanel->GetChild( i ); - if ( !pPanel || !pPanel->IsVisible() ) - continue; - - pList->Insert( SortedPanel_t( static_cast< Panel* >( pPanel ) ) ); - } -} - -void VguiPanelGetSortedChildButtonList( Panel *pParentPanel, void *pSortedPanels, char *pchFilter /*= NULL*/, int nFilterType /*= 0*/ ) -{ - CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels ); - - for ( int i = 0; i < pParentPanel->GetChildCount(); i++ ) - { - // perform auto-layout on the child panel - Button *pPanel = dynamic_cast< Button* >( pParentPanel->GetChild( i ) ); - if ( !pPanel || !pPanel->IsVisible() ) - continue; - - if ( pchFilter && pchFilter[ 0 ] != '\0' ) - { - char szBuff[ 128 ]; - pPanel->GetText( szBuff, sizeof( szBuff ) ); - - // Prefix - if ( nFilterType == 0 ) - { - if ( !StringHasPrefix( szBuff, pchFilter ) ) - { - continue; - } - } - // Substring - else if ( nFilterType == 1 ) - { - if ( V_strstr( szBuff, pchFilter ) == NULL ) - { - continue; - } - } - } - - pList->Insert( SortedPanel_t( pPanel ) ); - } -} - -int VguiPanelNavigateSortedChildButtonList( void *pSortedPanels, int nDir ) -{ - CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels ); - - if ( pList->Count() <= 0 ) - return -1; - - if ( nDir != 0 ) - { - int nArmed = -1; - for ( int i = 0; i < pList->Count(); i++ ) - { - if ( (*pList)[ i ].pButton->IsArmed() ) - { - nArmed = i; - break; - } - } - - if ( nArmed == -1 ) - { - (*pList)[ 0 ].pButton->SetArmed( true ); - return 0; - } - else - { - int nNewArmed = clamp( nArmed + nDir, 0, pList->Count() - 1 ); - if ( nNewArmed != nArmed ) - { - (*pList)[ nArmed ].pButton->SetArmed( false ); - } - - (*pList)[ nNewArmed ].pButton->RequestFocus(); - (*pList)[ nNewArmed ].pButton->SetArmed( true ); - - return nNewArmed; - } - } - - return -1; -} - -} +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + + +#include +#include +#include +#include +#include // isdigit() + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "vgui_controls/Menu.h" +#include "vgui_controls/MenuItem.h" + +#include "UtlSortVector.h" + +#include "tier1/utldict.h" +#include "tier1/utlbuffer.h" +#include "mempool.h" +#include "filesystem.h" +#include "tier0/icommandline.h" + +#include "tier0/vprof.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include + +using namespace vgui; + +#define TRIPLE_PRESS_MSEC 300 + + +extern int GetBuildModeDialogCount(); + +static char *CopyString( const char *in ) +{ + if ( !in ) + return NULL; + + int len = strlen( in ); + char *n = new char[ len + 1 ]; + Q_strncpy( n, in, len + 1 ); + return n; +} + +#if defined( VGUI_USEDRAGDROP ) +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +struct vgui::DragDrop_t +{ + DragDrop_t() : + m_bDragEnabled( false ), + m_bShowDragHelper( true ), + m_bDropEnabled( false ), + m_bDragStarted( false ), + m_nDragStartTolerance( 8 ), + m_bDragging( false ), + m_lDropHoverTime( 0 ), + m_bDropMenuShown( false ), + m_bPreventChaining( false ) + { + m_nStartPos[ 0 ] = m_nStartPos[ 1 ] = 0; + m_nLastPos[ 0 ] = m_nLastPos[ 1 ] = 0; + } + + // Drag related data + bool m_bDragEnabled; + bool m_bShowDragHelper; + bool m_bDragging; + bool m_bDragStarted; + // How many pixels the dragged box must move before showing the outline rect... + int m_nDragStartTolerance; + int m_nStartPos[ 2 ]; + int m_nLastPos[ 2 ]; + CUtlVector< KeyValues * > m_DragData; + CUtlVector< PHandle > m_DragPanels; + + // Drop related data + bool m_bDropEnabled; + // A droppable panel can have a hover context menu, which will show up after m_flHoverContextTime of hovering + float m_flHoverContextTime; + + PHandle m_hCurrentDrop; + // Amount of time hovering over current drop target + long m_lDropHoverTime; + bool m_bDropMenuShown; + DHANDLE< Menu > m_hDropContextMenu; + + // Misc data + bool m_bPreventChaining; +}; + +//----------------------------------------------------------------------------- +// Purpose: Helper for painting to the full screen... +//----------------------------------------------------------------------------- +class CDragDropHelperPanel : public Panel +{ + DECLARE_CLASS_SIMPLE( CDragDropHelperPanel, Panel ); +public: + CDragDropHelperPanel(); + + virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups); + virtual void PostChildPaint(); + + void AddPanel( Panel *current ); + + void RemovePanel( Panel *search ); + +private: + struct DragHelperPanel_t + { + PHandle m_hPanel; + }; + + CUtlVector< DragHelperPanel_t > m_PaintList; +}; + +vgui::DHANDLE< CDragDropHelperPanel > s_DragDropHelper; +#endif + +#if defined( VGUI_USEKEYBINDINGMAPS ) + +BoundKey_t::BoundKey_t(): + isbuiltin( true ), + bindingname( 0 ), + keycode( KEY_NONE ), + modifiers( 0 ) +{ +} + +BoundKey_t::BoundKey_t( const BoundKey_t& src ) +{ + isbuiltin = src.isbuiltin; + bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname ); + keycode = src.keycode; + modifiers = src.modifiers; +} + +BoundKey_t& BoundKey_t::operator =( const BoundKey_t& src ) +{ + if ( this == &src ) + return *this; + isbuiltin = src.isbuiltin; + bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname ); + keycode = src.keycode; + modifiers = src.modifiers; + return *this; +} + + +BoundKey_t::~BoundKey_t() +{ + if ( !isbuiltin ) + { + delete[] bindingname; + } +} + +KeyBindingMap_t::KeyBindingMap_t() : + bindingname( 0 ), + func( 0 ), + helpstring( 0 ), + docstring( 0 ), + passive( false ) +{ +} + +KeyBindingMap_t::KeyBindingMap_t( const KeyBindingMap_t& src ) +{ + bindingname = src.bindingname; + helpstring = src.helpstring; + docstring = src.docstring; + + func = src.func; + passive = src.passive; +} + +KeyBindingMap_t::~KeyBindingMap_t() +{ +} + +class CKeyBindingsMgr +{ +public: + + CKeyBindingsMgr() : + m_Bindings( 0, 0, KeyBindingContextHandleLessFunc ), + m_nKeyBindingContexts( 0 ) + { + } + + struct KBContext_t + { + KBContext_t() : + m_KeyBindingsFile( UTL_INVAL_SYMBOL ), + m_KeyBindingsPathID( UTL_INVAL_SYMBOL ) + { + m_Handle = INVALID_KEYBINDINGCONTEXT_HANDLE; + } + + KBContext_t( const KBContext_t& src ) + { + m_Handle = src.m_Handle; + m_KeyBindingsFile = src.m_KeyBindingsFile; + m_KeyBindingsPathID = src.m_KeyBindingsPathID; + int c = src.m_Panels.Count(); + for ( int i = 0; i < c; ++i ) + { + m_Panels.AddToTail( src.m_Panels[ i ] ); + } + } + + KeyBindingContextHandle_t m_Handle; + CUtlSymbol m_KeyBindingsFile; + CUtlSymbol m_KeyBindingsPathID; + CUtlVector< Panel * > m_Panels; + }; + + static bool KeyBindingContextHandleLessFunc( const KBContext_t& lhs, const KBContext_t& rhs ) + { + return lhs.m_Handle < rhs.m_Handle; + } + + KeyBindingContextHandle_t CreateContext( char const *filename, char const *pathID ) + { + KBContext_t entry; + + entry.m_Handle = (KeyBindingContextHandle_t)++m_nKeyBindingContexts; + entry.m_KeyBindingsFile = filename; + if ( pathID ) + { + entry.m_KeyBindingsPathID = pathID; + } + else + { + entry.m_KeyBindingsPathID = UTL_INVAL_SYMBOL; + } + + m_Bindings.Insert( entry ); + + return entry.m_Handle; + } + + void AddPanelToContext( KeyBindingContextHandle_t handle, Panel *panel ) + { + if ( !panel->GetName() || !panel->GetName()[ 0 ] ) + { + Warning( "Can't add Keybindings Context for unnamed panels\n" ); + return; + } + + KBContext_t *entry = Find( handle ); + Assert( entry ); + if ( entry ) + { + int idx = entry->m_Panels.Find( panel ); + if ( idx == entry->m_Panels.InvalidIndex() ) + { + entry->m_Panels.AddToTail( panel ); + } + } + } + + void OnPanelDeleted( KeyBindingContextHandle_t handle, Panel *panel ) + { + KBContext_t *kb = Find( handle ); + if ( kb ) + { + kb->m_Panels.FindAndRemove( panel ); + } + } + + KBContext_t *Find( KeyBindingContextHandle_t handle ) + { + KBContext_t search; + search.m_Handle = handle; + int idx = m_Bindings.Find( search ); + if ( idx == m_Bindings.InvalidIndex() ) + { + return NULL; + } + return &m_Bindings[ idx ]; + } + + char const *GetKeyBindingsFile( KeyBindingContextHandle_t handle ) + { + KBContext_t *kb = Find( handle ); + if ( kb ) + { + return kb->m_KeyBindingsFile.String(); + } + Assert( 0 ); + return ""; + } + + char const *GetKeyBindingsFilePathID( KeyBindingContextHandle_t handle ) + { + KBContext_t *kb = Find( handle ); + if ( kb ) + { + return kb->m_KeyBindingsPathID.String(); + } + Assert( 0 ); + return NULL; + } + + int GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle ) + { + KBContext_t *kb = Find( handle ); + if ( kb ) + { + return kb->m_Panels.Count(); + } + Assert( 0 ); + return 0; + } + + //----------------------------------------------------------------------------- + // Purpose: static method + // Input : index - + // Output : Panel + //----------------------------------------------------------------------------- + Panel *GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index ) + { + KBContext_t *kb = Find( handle ); + if ( kb ) + { + Assert( index >= 0 && index < kb->m_Panels.Count() ); + return kb->m_Panels[ index ]; + } + Assert( 0 ); + return 0; + } + + CUtlRBTree< KBContext_t, int > m_Bindings; + int m_nKeyBindingContexts; +}; + +static CKeyBindingsMgr g_KBMgr; + +//----------------------------------------------------------------------------- +// Purpose: Static method to allocate a context +// Input : - +// Output : KeyBindingContextHandle_t +//----------------------------------------------------------------------------- +KeyBindingContextHandle_t Panel::CreateKeyBindingsContext( char const *filename, char const *pathID /*=0*/ ) +{ + return g_KBMgr.CreateContext( filename, pathID ); +} + + +//----------------------------------------------------------------------------- +// Purpose: static method +// Input : - +// Output : int +//----------------------------------------------------------------------------- +int Panel::GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle ) +{ + return g_KBMgr.GetPanelsWithKeyBindingsCount( handle ); +} + +//----------------------------------------------------------------------------- +// Purpose: static method +// Input : index - +// Output : Panel +//----------------------------------------------------------------------------- +Panel *Panel::GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index ) +{ + return g_KBMgr.GetPanelWithKeyBindings( handle, index ); +} + + +//----------------------------------------------------------------------------- +// Returns the number of keybindings +//----------------------------------------------------------------------------- +int Panel::GetKeyMappingCount( ) +{ + int nCount = 0; + PanelKeyBindingMap *map = GetKBMap(); + while ( map ) + { + nCount += map->entries.Count(); + map = map->baseMap; + } + return nCount; +} + + +//----------------------------------------------------------------------------- +// Purpose: static method. Reverts key bindings for all registered panels (panels with keybindings actually +// loaded from file +// Input : - +//----------------------------------------------------------------------------- +void Panel::RevertKeyBindings( KeyBindingContextHandle_t handle ) +{ + int c = GetPanelsWithKeyBindingsCount( handle ); + for ( int i = 0; i < c; ++i ) + { + Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); + Assert( kbPanel ); + kbPanel->RevertKeyBindingsToDefault(); + } +} + +static void BufPrint( CUtlBuffer& buf, int level, char const *fmt, ... ) +{ + char string[ 2048 ]; + va_list argptr; + va_start( argptr, fmt ); + _vsnprintf( string, sizeof( string ) - 1, fmt, argptr ); + va_end( argptr ); + string[ sizeof( string ) - 1 ] = 0; + + while ( --level >= 0 ) + { + buf.Printf( " " ); + } + buf.Printf( "%s", string ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : handle - +//----------------------------------------------------------------------------- +void Panel::SaveKeyBindings( KeyBindingContextHandle_t handle ) +{ + char const *filename = g_KBMgr.GetKeyBindingsFile( handle ); + char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle ); + + SaveKeyBindingsToFile( handle, filename, pathID ); +} + +//----------------------------------------------------------------------------- +// Purpose: static method. Saves key binding files out for all keybindings +// Input : - +//----------------------------------------------------------------------------- +void Panel::SaveKeyBindingsToFile( KeyBindingContextHandle_t handle, char const *filename, char const *pathID /*= 0*/ ) +{ + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + + BufPrint( buf, 0, "keybindings\n" ); + BufPrint( buf, 0, "{\n" ); + + int c = GetPanelsWithKeyBindingsCount( handle ); + for ( int i = 0; i < c; ++i ) + { + Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); + Assert( kbPanel ); + if ( !kbPanel ) + continue; + + Assert( kbPanel->GetName() ); + Assert( kbPanel->GetName()[ 0 ] ); + + if ( !kbPanel->GetName() || !kbPanel->GetName()[ 0 ] ) + continue; + + BufPrint( buf, 1, "\"%s\"\n", kbPanel->GetName() ); + BufPrint( buf, 1, "{\n" ); + + kbPanel->SaveKeyBindingsToBuffer( 2, buf ); + + BufPrint( buf, 1, "}\n" ); + } + + BufPrint( buf, 0, "}\n" ); + + if ( g_pFullFileSystem->FileExists( filename, pathID ) && + !g_pFullFileSystem->IsFileWritable( filename, pathID ) ) + { + Warning( "Panel::SaveKeyBindings '%s' is read-only!!!\n", filename ); + } + + FileHandle_t h = g_pFullFileSystem->Open( filename, "wb", pathID ); + if ( FILESYSTEM_INVALID_HANDLE != h ) + { + g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), h ); + g_pFullFileSystem->Close( h ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : handle - +// *panelOfInterest - +//----------------------------------------------------------------------------- +void Panel::LoadKeyBindingsForOnePanel( KeyBindingContextHandle_t handle, Panel *panelOfInterest ) +{ + if ( !panelOfInterest ) + return; + if ( !panelOfInterest->GetName() ) + return; + if ( !panelOfInterest->GetName()[ 0 ] ) + return; + + char const *filename = g_KBMgr.GetKeyBindingsFile( handle ); + char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle ); + + KeyValues *kv = new KeyValues( "keybindings" ); + if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) ) + { + int c = GetPanelsWithKeyBindingsCount( handle ); + for ( int i = 0; i < c; ++i ) + { + Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); + Assert( kbPanel ); + + char const *panelName = kbPanel->GetName(); + if ( !panelName ) + { + continue; + } + + if ( Q_stricmp( panelOfInterest->GetName(), panelName ) ) + continue; + + KeyValues *subKey = kv->FindKey( panelName, false ); + if ( !subKey ) + { + Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName ); + continue; + } + + kbPanel->ParseKeyBindings( subKey ); + } + } + kv->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: static method. Loads all key bindings again +// Input : - +//----------------------------------------------------------------------------- + +void Panel::ReloadKeyBindings( KeyBindingContextHandle_t handle ) +{ + char const *filename = g_KBMgr.GetKeyBindingsFile( handle ); + char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle ); + + KeyValues *kv = new KeyValues( "keybindings" ); + if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) ) + { + int c = GetPanelsWithKeyBindingsCount( handle ); + for ( int i = 0; i < c; ++i ) + { + Panel *kbPanel = GetPanelWithKeyBindings( handle, i ); + Assert( kbPanel ); + + char const *panelName = kbPanel->GetName(); + if ( !panelName ) + { + continue; + } + + KeyValues *subKey = kv->FindKey( panelName, false ); + if ( !subKey ) + { + Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName ); + continue; + } + + kbPanel->ParseKeyBindings( subKey ); + } + } + kv->deleteThis(); +} +#endif // VGUI_USEKEYBINDINGMAPS + +DECLARE_BUILD_FACTORY( Panel ); + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +Panel::Panel() +{ + Init(0, 0, 64, 24); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +Panel::Panel(Panel *parent) +{ + Init(0, 0, 64, 24); + SetParent(parent); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +Panel::Panel(Panel *parent, const char *panelName) +{ + Init(0, 0, 64, 24); + SetName(panelName); + SetParent(parent); + SetBuildModeEditable(true); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +Panel::Panel( Panel *parent, const char *panelName, HScheme scheme ) +{ + Init(0, 0, 64, 24); + SetName(panelName); + SetParent(parent); + SetBuildModeEditable(true); + SetScheme( scheme ); +} + +//----------------------------------------------------------------------------- +// Purpose: Setup +//----------------------------------------------------------------------------- +void Panel::Init( int x, int y, int wide, int tall ) +{ + _panelName = NULL; + _tooltipText = NULL; + _pinToSibling = NULL; + m_hMouseEventHandler = NULL; + _pinCornerToSibling = PIN_TOPLEFT; + _pinToSiblingCorner = PIN_TOPLEFT; + + // get ourselves an internal panel + _vpanel = ivgui()->AllocPanel(); + ipanel()->Init(_vpanel, this); + + SetPos(x, y); + SetSize(wide, tall); + _flags.SetFlag( NEEDS_LAYOUT | NEEDS_SCHEME_UPDATE | NEEDS_DEFAULT_SETTINGS_APPLIED ); + _flags.SetFlag( AUTODELETE_ENABLED | PAINT_BORDER_ENABLED | PAINT_BACKGROUND_ENABLED | PAINT_ENABLED ); +#if defined( VGUI_USEKEYBINDINGMAPS ) + _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT ); +#endif + m_nPinDeltaX = m_nPinDeltaY = 0; + m_nResizeDeltaX = m_nResizeDeltaY = 0; + _autoResizeDirection = AUTORESIZE_NO; + _pinCorner = PIN_TOPLEFT; + _cursor = dc_arrow; + _border = NULL; + _buildGroup = UTLHANDLE_INVALID; + _tabPosition = 0; + m_iScheme = 0; + m_bIsSilent = false; + m_bParentNeedsCursorMoveEvents = false; + + _buildModeFlags = 0; // not editable or deletable in buildmode dialog by default + + m_pTooltips = NULL; + m_bToolTipOverridden = false; + + m_flAlpha = 255.0f; + m_nPaintBackgroundType = 0; + + //============================================================================= + // HPE_BEGIN: + // [tj] Default to rounding all corners (for draw style 2) + //============================================================================= + m_roundedCorners = PANEL_ROUND_CORNER_ALL; + //============================================================================= + // HPE_END + //============================================================================= + + m_nBgTextureId1 = -1; + m_nBgTextureId2 = -1; + m_nBgTextureId3 = -1; + m_nBgTextureId4 = -1; +#if defined( VGUI_USEDRAGDROP ) + m_pDragDrop = new DragDrop_t; + +#endif + + m_lLastDoublePressTime = 0L; + +#if defined( VGUI_USEKEYBINDINGMAPS ) + m_hKeyBindingsContext = INVALID_KEYBINDINGCONTEXT_HANDLE; +#endif + + REGISTER_COLOR_AS_OVERRIDABLE( _fgColor, "fgcolor_override" ); + REGISTER_COLOR_AS_OVERRIDABLE( _bgColor, "bgcolor_override" ); + + m_bIsConsoleStylePanel = false; + m_NavUp = NULL; + m_NavDown = NULL; + m_NavLeft = NULL; + m_NavRight = NULL; + m_NavToRelay = NULL; + m_NavActivate = NULL; + m_NavBack = NULL; + m_sNavUpName = NULL; + m_sNavDownName = NULL; + m_sNavLeftName = NULL; + m_sNavRightName = NULL; + m_sNavToRelayName = NULL; + m_sNavActivateName = NULL; + m_sNavBackName = NULL; + + m_PassUnhandledInput = true; + m_LastNavDirection = ND_NONE; + m_bWorldPositionCurrentFrame = false; + m_bForceStereoRenderToFrameBuffer = false; +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +Panel::~Panel() +{ + // @note Tom Bui: only cleanup if we've created it + if ( !m_bToolTipOverridden ) + { + if ( m_pTooltips ) + { + delete m_pTooltips; + } + } +#if defined( VGUI_USEKEYBINDINGMAPS ) + if ( IsValidKeyBindingsContext() ) + { + g_KBMgr.OnPanelDeleted( m_hKeyBindingsContext, this ); + } +#endif // VGUI_USEKEYBINDINGMAPS +#if defined( VGUI_USEDRAGDROP ) + if ( m_pDragDrop->m_bDragging ) + { + OnFinishDragging( false, (MouseCode)-1 ); + } +#endif // VGUI_USEDRAGDROP + + _flags.ClearFlag( AUTODELETE_ENABLED ); + _flags.SetFlag( MARKED_FOR_DELETION ); + + // remove panel from any list + SetParent((VPANEL)NULL); + + // Stop our children from pointing at us, and delete them if possible + while (ipanel()->GetChildCount(GetVPanel())) + { + VPANEL child = ipanel()->GetChild(GetVPanel(), 0); + if (ipanel()->IsAutoDeleteSet(child)) + { + ipanel()->DeletePanel(child); + } + else + { + ipanel()->SetParent(child, NULL); + } + } + + // delete VPanel + ivgui()->FreePanel(_vpanel); + // free our name + delete [] _panelName; + + if ( _tooltipText && _tooltipText[0] ) + { + delete [] _tooltipText; + } + + delete [] _pinToSibling; + + _vpanel = NULL; +#if defined( VGUI_USEDRAGDROP ) + delete m_pDragDrop; +#endif // VGUI_USEDRAGDROP +} + +//----------------------------------------------------------------------------- +// Purpose: fully construct this panel so its ready for use right now (i.e fonts loaded, colors set, default label text set, ...) +//----------------------------------------------------------------------------- +void Panel::MakeReadyForUse() +{ +// PerformApplySchemeSettings(); + UpdateSiblingPin(); + surface()->SolveTraverse( GetVPanel(), true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetName( const char *panelName ) +{ + // No change? + if ( _panelName && + panelName && + !Q_strcmp( _panelName, panelName ) ) + { + return; + } + + if (_panelName) + { + delete [] _panelName; + _panelName = NULL; + } + + if (panelName) + { + int len = Q_strlen(panelName) + 1; + _panelName = new char[ len ]; + Q_strncpy( _panelName, panelName, len ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: returns the given name of the panel +//----------------------------------------------------------------------------- +const char *Panel::GetName() +{ + if (_panelName) + return _panelName; + + return ""; +} + +//----------------------------------------------------------------------------- +// Purpose: returns the name of the module that this instance of panel was compiled into +//----------------------------------------------------------------------------- +const char *Panel::GetModuleName() +{ + return vgui::GetControlsModuleName(); +} + +//----------------------------------------------------------------------------- +// Purpose: returns the classname of the panel (as specified in the panelmaps) +//----------------------------------------------------------------------------- +const char *Panel::GetClassName() +{ + // loop up the panel map name + PanelMessageMap *panelMap = GetMessageMap(); + if ( panelMap ) + { + return panelMap->pfnClassName(); + } + + return "Panel"; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetPos(int x, int y) +{ + if (!CommandLine()->FindParm("-hushasserts")) + { + Assert( abs(x) < 32768 && abs(y) < 32768 ); + } + ipanel()->SetPos(GetVPanel(), x, y); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::GetPos(int &x, int &y) +{ + ipanel()->GetPos(GetVPanel(), x, y); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetSize(int wide, int tall) +{ + Assert( abs(wide) < 32768 && abs(tall) < 32768 ); + ipanel()->SetSize(GetVPanel(), wide, tall); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::GetSize(int &wide, int &tall) +{ + ipanel()->GetSize(GetVPanel(), wide, tall); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetBounds(int x, int y, int wide, int tall) +{ + SetPos(x,y); + SetSize(wide,tall); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::GetBounds(int &x, int &y, int &wide, int &tall) +{ + GetPos(x, y); + GetSize(wide, tall); +} + +//----------------------------------------------------------------------------- +// Purpose: returns safe handle to parent +//----------------------------------------------------------------------------- +VPANEL Panel::GetVParent() +{ + if ( ipanel() ) + { + return ipanel()->GetParent(GetVPanel()); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: returns a pointer to a controls version of a Panel pointer +//----------------------------------------------------------------------------- +Panel *Panel::GetParent() +{ + // get the parent and convert it to a Panel * + // this is OK, the hierarchy is guaranteed to be all from the same module, except for the root node + // the root node always returns NULL when a GetParent() is done so everything is OK + if ( ipanel() ) + { + VPANEL parent = ipanel()->GetParent(GetVPanel()); + if (parent) + { + Panel *pParent = ipanel()->GetPanel(parent, GetControlsModuleName()); + Assert(!pParent || !strcmp(pParent->GetModuleName(), GetControlsModuleName())); + return pParent; + } + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Screen size change notification handler +//----------------------------------------------------------------------------- +void Panel::OnScreenSizeChanged(int nOldWide, int nOldTall) +{ + // post to all children + for (int i = 0; i < ipanel()->GetChildCount(GetVPanel()); i++) + { + VPANEL child = ipanel()->GetChild(GetVPanel(), i); + PostMessage(child, new KeyValues("OnScreenSizeChanged", "oldwide", nOldWide, "oldtall", nOldTall), NULL); + } + + // make any currently fullsize window stay fullsize + int x, y, wide, tall; + GetBounds(x, y, wide, tall); + int screenWide, screenTall; + surface()->GetScreenSize(screenWide, screenTall); + if (x == 0 && y == 0 && nOldWide == wide && tall == nOldTall) + { + // fullsize + surface()->GetScreenSize(wide, tall); + SetBounds(0, 0, wide, tall); + } + + // panel needs to re-get it's scheme settings + _flags.SetFlag( NEEDS_SCHEME_UPDATE ); + + // invalidate our settings + InvalidateLayout(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetVisible(bool state) +{ + ipanel()->SetVisible(GetVPanel(), state); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Panel::IsVisible() +{ + if (ipanel()) + { + return ipanel()->IsVisible(GetVPanel()); + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetEnabled(bool state) +{ + if (state != ipanel()->IsEnabled( GetVPanel())) + { + ipanel()->SetEnabled(GetVPanel(), state); + InvalidateLayout(false); + Repaint(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Panel::IsEnabled() +{ + return ipanel()->IsEnabled(GetVPanel()); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Panel::IsPopup() +{ + return ipanel()->IsPopup(GetVPanel()); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::Repaint() +{ + _flags.SetFlag( NEEDS_REPAINT ); + if (surface()) + { + surface()->Invalidate(GetVPanel()); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::Think() +{ + if (IsVisible()) + { + // update any tooltips + if (m_pTooltips) + { + m_pTooltips->PerformLayout(); + } + if ( _flags.IsFlagSet( NEEDS_LAYOUT ) ) + { + InternalPerformLayout(); + } + } + + OnThink(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::PaintTraverse( bool repaint, bool allowForce ) +{ + if ( m_bWorldPositionCurrentFrame ) + { + surface()->SolveTraverse( GetVPanel() ); + } + + if ( !IsVisible() ) + { + return; + } + + float oldAlphaMultiplier = surface()->DrawGetAlphaMultiplier(); + float newAlphaMultiplier = oldAlphaMultiplier * m_flAlpha * 1.0f/255.0f; + + if ( IsXbox() && !newAlphaMultiplier ) + { + // xbox optimization not suitable for pc + // xbox panels are compliant and can early out and not traverse their children + // when they have no opacity + return; + } + + if ( !repaint && + allowForce && + _flags.IsFlagSet( NEEDS_REPAINT ) ) + { + repaint = true; + _flags.ClearFlag( NEEDS_REPAINT ); + } + + VPANEL vpanel = GetVPanel(); + + bool bPushedViewport = false; + if( GetForceStereoRenderToFrameBuffer() ) + { + CMatRenderContextPtr pRenderContext( materials ); + if( pRenderContext->GetRenderTarget() ) + { + surface()->PushFullscreenViewport(); + bPushedViewport = true; + } + } + + int clipRect[4]; + ipanel()->GetClipRect( vpanel, clipRect[0], clipRect[1], clipRect[2], clipRect[3] ); + if ( ( clipRect[2] <= clipRect[0] ) || ( clipRect[3] <= clipRect[1] ) ) + { + repaint = false; + } + + // set global alpha + surface()->DrawSetAlphaMultiplier( newAlphaMultiplier ); + + bool bBorderPaintFirst = _border ? _border->PaintFirst() : false; + + // draw the border first if requested to + if ( bBorderPaintFirst && repaint && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != null ) ) + { + // Paint the border over the background with no inset + surface()->PushMakeCurrent( vpanel, false ); + PaintBorder(); + surface()->PopMakeCurrent( vpanel ); + } + + if ( repaint ) + { + // draw the background with no inset + if ( _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) ) + { + surface()->PushMakeCurrent( vpanel, false ); + PaintBackground(); + surface()->PopMakeCurrent( vpanel ); + } + + // draw the front of the panel with the inset + if ( _flags.IsFlagSet( PAINT_ENABLED ) ) + { + surface()->PushMakeCurrent( vpanel, true ); + Paint(); + surface()->PopMakeCurrent( vpanel ); + } + } + + // traverse and paint all our children + CUtlVector< VPANEL > &children = ipanel()->GetChildren( vpanel ); + int childCount = children.Count(); + for (int i = 0; i < childCount; i++) + { + VPANEL child = children[ i ]; + bool bVisible = ipanel()->IsVisible( child ); + + if ( surface()->ShouldPaintChildPanel( child ) ) + { + if ( bVisible ) + { + ipanel()->PaintTraverse( child, repaint, allowForce ); + } + } + else + { + // Invalidate the child panel so that it gets redrawn + surface()->Invalidate( child ); + + // keep traversing the tree, just don't allow anyone to paint after here + if ( bVisible ) + { + ipanel()->PaintTraverse( child, false, false ); + } + } + } + + // draw the border last + if ( repaint ) + { + if ( !bBorderPaintFirst && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != null ) ) + { + // Paint the border over the background with no inset + surface()->PushMakeCurrent( vpanel, false ); + PaintBorder(); + surface()->PopMakeCurrent( vpanel ); + } + +#ifdef _DEBUG + // IsBuildGroupEnabled recurses up all the parents and ends up being very expensive as it wanders all over memory + if ( GetBuildModeDialogCount() && IsBuildGroupEnabled() ) //&& HasFocus() ) + { + // outline all selected panels + CUtlVector *controlGroup = _buildGroup->GetControlGroup(); + for (int i=0; i < controlGroup->Size(); ++i) + { + // outline all selected panels + CUtlVector *controlGroup = _buildGroup->GetControlGroup(); + for (int i=0; i < controlGroup->Size(); ++i) + { + surface()->PushMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel(), false ); + ((*controlGroup)[i].Get())->PaintBuildOverlay(); + surface()->PopMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel() ); + } + + _buildGroup->DrawRulers(); + } + } +#endif + + // All of our children have painted, etc, now allow painting in top of them + if ( _flags.IsFlagSet( POST_CHILD_PAINT_ENABLED ) ) + { + surface()->PushMakeCurrent( vpanel, false ); + PostChildPaint(); + surface()->PopMakeCurrent( vpanel ); + } + } + + surface()->DrawSetAlphaMultiplier( oldAlphaMultiplier ); + + surface()->SwapBuffers( vpanel ); + + if( bPushedViewport ) + { + surface()->PopFullscreenViewport(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::PaintBorder() +{ + _border->Paint(GetVPanel()); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::PaintBackground() +{ + int wide, tall; + GetSize( wide, tall ); + if ( m_SkipChild.Get() && m_SkipChild->IsVisible() ) + { + if ( GetPaintBackgroundType() == 2 ) + { + int cornerWide, cornerTall; + GetCornerTextureSize( cornerWide, cornerTall ); + + Color col = GetBgColor(); + DrawHollowBox( 0, 0, wide, tall, col, 1.0f ); + + wide -= 2 * cornerWide; + tall -= 2 * cornerTall; + + FillRectSkippingPanel( GetBgColor(), cornerWide, cornerTall, wide, tall, m_SkipChild.Get() ); + } + else + { + FillRectSkippingPanel( GetBgColor(), 0, 0, wide, tall, m_SkipChild.Get() ); + } + } + else + { + Color col = GetBgColor(); + + switch ( m_nPaintBackgroundType ) + { + default: + case 0: + { + surface()->DrawSetColor(col); + surface()->DrawFilledRect(0, 0, wide, tall); + } + break; + case 1: + { + DrawTexturedBox( 0, 0, wide, tall, col, 1.0f ); + } + break; + case 2: + { + DrawBox( 0, 0, wide, tall, col, 1.0f ); + } + break; + case 3: + { + DrawBoxFade( 0, 0, wide, tall, col, 1.0f, 255, 0, true ); + } + break; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::Paint() +{ + // empty on purpose + // PaintBackground is painted and default behavior is for Paint to do nothing +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::PostChildPaint() +{ + // Empty on purpose + // This is called if _postChildPaintEnabled is true and allows painting to + // continue on the surface after all of the panel's children have painted + // themselves. Allows drawing an overlay on top of the children, etc. +} + +//----------------------------------------------------------------------------- +// Purpose: Draws a black rectangle around the panel. +//----------------------------------------------------------------------------- +void Panel::PaintBuildOverlay() +{ + int wide,tall; + GetSize(wide,tall); + surface()->DrawSetColor(0, 0, 0, 255); + + surface()->DrawFilledRect(0,0,wide,2); //top + surface()->DrawFilledRect(0,tall-2,wide,tall); //bottom + surface()->DrawFilledRect(0,2,2,tall-2); //left + surface()->DrawFilledRect(wide-2,2,wide,tall-2); //right +} + +//----------------------------------------------------------------------------- +// Purpose: Returns true if the panel's draw code will fully cover it's area +//----------------------------------------------------------------------------- +bool Panel::IsOpaque() +{ + // FIXME: Add code to account for the 'SkipChild' functionality in Frame + if ( IsVisible() && _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) && ( _bgColor[3] == 255 ) ) + return true; + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the settings are aligned to the right of the screen +//----------------------------------------------------------------------------- +bool Panel::IsRightAligned() +{ + return (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the settings are aligned to the bottom of the screen +//----------------------------------------------------------------------------- +bool Panel::IsBottomAligned() +{ + return (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED); +} + +//----------------------------------------------------------------------------- +// Purpose: sets the parent +//----------------------------------------------------------------------------- +void Panel::SetParent(Panel *newParent) +{ + // Assert that the parent is from the same module as the child + // FIXME: !!! work out how to handle this properly! + // Assert(!newParent || !strcmp(newParent->GetModuleName(), GetControlsModuleName())); + + if (newParent) + { + SetParent(newParent->GetVPanel()); + } + else + { + SetParent((VPANEL)NULL); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetParent(VPANEL newParent) +{ + if (newParent) + { + ipanel()->SetParent(GetVPanel(), newParent); + } + else + { + ipanel()->SetParent(GetVPanel(), NULL); + } + + if (GetVParent() && !IsPopup()) + { + SetProportional(ipanel()->IsProportional(GetVParent())); + + // most of the time KBInput == parents kbinput + if (ipanel()->IsKeyBoardInputEnabled(GetVParent()) != IsKeyBoardInputEnabled()) + { + SetKeyBoardInputEnabled(ipanel()->IsKeyBoardInputEnabled(GetVParent())); + } + + if (ipanel()->IsMouseInputEnabled(GetVParent()) != IsMouseInputEnabled()) + { + SetMouseInputEnabled(ipanel()->IsMouseInputEnabled(GetVParent())); + } + } + + UpdateSiblingPin(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::OnChildAdded(VPANEL child) +{ + Assert( !_flags.IsFlagSet( IN_PERFORM_LAYOUT ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: default message handler +//----------------------------------------------------------------------------- +void Panel::OnSizeChanged(int newWide, int newTall) +{ + InvalidateLayout(); // our size changed so force us to layout again +} + +//----------------------------------------------------------------------------- +// Purpose: sets Z ordering - lower numbers are always behind higher z's +//----------------------------------------------------------------------------- +void Panel::SetZPos(int z) +{ + ipanel()->SetZPos(GetVPanel(), z); +} + +//----------------------------------------------------------------------------- +// Purpose: sets Z ordering - lower numbers are always behind higher z's +//----------------------------------------------------------------------------- +int Panel::GetZPos() +{ + return ( ipanel()->GetZPos( GetVPanel() ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: sets alpha modifier for panel and all child panels [0..255] +//----------------------------------------------------------------------------- +void Panel::SetAlpha(int alpha) +{ + m_flAlpha = alpha; +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +int Panel::GetAlpha() +{ + return (int)m_flAlpha; +} + +//----------------------------------------------------------------------------- +// Purpose: Moves the panel to the front of the z-order +//----------------------------------------------------------------------------- +void Panel::MoveToFront(void) +{ + // FIXME: only use ipanel() as per src branch? + if (IsPopup()) + { + surface()->BringToFront(GetVPanel()); + } + else + { + ipanel()->MoveToFront(GetVPanel()); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Iterates up the hierarchy looking for a particular parent +//----------------------------------------------------------------------------- +bool Panel::HasParent(VPANEL potentialParent) +{ + if (!potentialParent) + return false; + + return ipanel()->HasParent(GetVPanel(), potentialParent); +} + +//----------------------------------------------------------------------------- +// Purpose: Finds the index of a child panel by string name +// Output : int - -1 if no panel of that name is found +//----------------------------------------------------------------------------- +int Panel::FindChildIndexByName(const char *childName) +{ + for (int i = 0; i < GetChildCount(); i++) + { + Panel *pChild = GetChild(i); + if (!pChild) + continue; + + if (!stricmp(pChild->GetName(), childName)) + { + return i; + } + } + + return -1; +} + +//----------------------------------------------------------------------------- +// Purpose: Finds a child panel by string name +// Output : Panel * - NULL if no panel of that name is found +//----------------------------------------------------------------------------- +Panel *Panel::FindChildByName(const char *childName, bool recurseDown) +{ + for (int i = 0; i < GetChildCount(); i++) + { + Panel *pChild = GetChild(i); + if (!pChild) + continue; + + if (!V_stricmp(pChild->GetName(), childName)) + { + return pChild; + } + + if (recurseDown) + { + Panel *panel = pChild->FindChildByName(childName, recurseDown); + if ( panel ) + { + return panel; + } + } + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Finds a sibling panel by name +//----------------------------------------------------------------------------- +Panel *Panel::FindSiblingByName(const char *siblingName) +{ + if ( !GetVParent() ) + return NULL; + + int siblingCount = ipanel()->GetChildCount(GetVParent()); + for (int i = 0; i < siblingCount; i++) + { + VPANEL sibling = ipanel()->GetChild(GetVParent(), i); + Panel *panel = ipanel()->GetPanel(sibling, GetControlsModuleName()); + if (!stricmp(panel->GetName(), siblingName)) + { + return panel; + } + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Dispatches immediately a message to the parent +//----------------------------------------------------------------------------- +void Panel::CallParentFunction(KeyValues *message) +{ + if (GetVParent()) + { + ipanel()->SendMessage(GetVParent(), message, GetVPanel()); + } + if (message) + { + message->deleteThis(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: if set to true, panel automatically frees itself when parent is deleted +//----------------------------------------------------------------------------- +void Panel::SetAutoDelete( bool state ) +{ + _flags.SetFlag( AUTODELETE_ENABLED, state ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Panel::IsAutoDeleteSet() +{ + return _flags.IsFlagSet( AUTODELETE_ENABLED ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Just calls 'delete this' +//----------------------------------------------------------------------------- +void Panel::DeletePanel() +{ + // Avoid re-entrancy + _flags.SetFlag( MARKED_FOR_DELETION ); + _flags.ClearFlag( AUTODELETE_ENABLED ); + delete this; +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +HScheme Panel::GetScheme() +{ + if (m_iScheme) + { + return m_iScheme; // return our internal scheme + } + + if (GetVParent()) // recurse down the heirarchy + { + return ipanel()->GetScheme(GetVParent()); + } + + return scheme()->GetDefaultScheme(); +} + +//----------------------------------------------------------------------------- +// Purpose: set the scheme to render this panel with by name +//----------------------------------------------------------------------------- +void Panel::SetScheme(const char *tag) +{ + if (strlen(tag) > 0 && scheme()->GetScheme(tag)) // check the scheme exists + { + SetScheme(scheme()->GetScheme(tag)); + } +} + +//----------------------------------------------------------------------------- +// Purpose: set the scheme to render this panel with +//----------------------------------------------------------------------------- +void Panel::SetScheme(HScheme scheme) +{ + if (scheme != m_iScheme) + { + m_iScheme = scheme; + + // This will cause the new scheme to be applied at a later point +// InvalidateLayout( false, true ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: returns the char of this panels hotkey +//----------------------------------------------------------------------------- +Panel *Panel::HasHotkey(wchar_t key) +{ + return NULL; +} + +#if defined( VGUI_USEDRAGDROP ) +static vgui::PHandle g_DragDropCapture; +#endif // VGUI_USEDRAGDROP + +void Panel::InternalCursorMoved(int x, int y) +{ +#if defined( VGUI_USEDRAGDROP ) + if ( g_DragDropCapture.Get() ) + { + bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted; + + g_DragDropCapture->OnContinueDragging(); + + if ( started ) + { + bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE ); + if ( isEscapeKeyDown ) + { + g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1, true ); + } + return; + } + } +#endif // VGUI_USEDRAGDROP + + if ( !ShouldHandleInputMessage() ) + return; + + if ( IsCursorNone() ) + return; + + if ( !IsMouseInputEnabled() ) + { + return; + } + + if (IsBuildGroupEnabled()) + { + if ( _buildGroup->CursorMoved(x, y, this) ) + { + return; + } + } + + if (m_pTooltips) + { + if ( _tooltipText ) + { + m_pTooltips->SetText( _tooltipText ); + } + m_pTooltips->ShowTooltip(this); + } + + ScreenToLocal(x, y); + + OnCursorMoved(x, y); +} + +void Panel::InternalCursorEntered() +{ + if (IsCursorNone() || !IsMouseInputEnabled()) + return; + + if (IsBuildGroupEnabled()) + return; + + if (m_pTooltips) + { + m_pTooltips->ResetDelay(); + + if ( _tooltipText ) + { + m_pTooltips->SetText( _tooltipText ); + } + m_pTooltips->ShowTooltip(this); + } + + OnCursorEntered(); +} + +void Panel::InternalCursorExited() +{ + if (IsCursorNone() || !IsMouseInputEnabled()) + return; + + if (IsBuildGroupEnabled()) + return; + + if (m_pTooltips) + { + m_pTooltips->HideTooltip(); + } + + OnCursorExited(); +} + +bool Panel::IsChildOfSurfaceModalPanel() +{ + VPANEL appModalPanel = input()->GetAppModalSurface(); + if ( !appModalPanel ) + return true; + + if ( ipanel()->HasParent( GetVPanel(), appModalPanel ) ) + return true; + + return false; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsChildOfModalSubTree() +{ + VPANEL subTree = input()->GetModalSubTree(); + if ( !subTree ) + return true; + + if ( HasParent( subTree ) ) + return true; + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Checks to see if message is being subverted due to modal subtree logic +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +static bool ShouldHandleInputMessage( VPANEL p ) +{ + // If there is not modal subtree, then always handle the msg + if ( !input()->GetModalSubTree() ) + return true; + + // What state are we in? + bool bChildOfModal = false; + VPANEL subTree = input()->GetModalSubTree(); + if ( !subTree ) + { + bChildOfModal = true; + } + else if ( ipanel()->HasParent( p, subTree ) ) + { + bChildOfModal = true; + } + + if ( input()->ShouldModalSubTreeReceiveMessages() ) + return bChildOfModal; + + return !bChildOfModal; +} + +bool Panel::ShouldHandleInputMessage() +{ + return ::ShouldHandleInputMessage( GetVPanel() ); +} + +void Panel::InternalMousePressed(int code) +{ + long curtime = system()->GetTimeMillis(); + if ( IsTriplePressAllowed() ) + { + long elapsed = curtime - m_lLastDoublePressTime; + if ( elapsed < TRIPLE_PRESS_MSEC ) + { + InternalMouseTriplePressed( code ); + return; + } + } + + // The menu system passively watches for mouse released messages so it + // can clear any open menus if the release is somewhere other than on a menu + Menu::OnInternalMousePressed( this, (MouseCode)code ); + + if ( !ShouldHandleInputMessage() ) + return; + + if ( IsCursorNone() ) + return; + + if ( !IsMouseInputEnabled()) + { +#if defined( VGUI_USEDRAGDROP ) + DragDropStartDragging(); +#endif + return; + } + + if (IsBuildGroupEnabled()) + { + if ( _buildGroup->MousePressed((MouseCode)code, this) ) + { + return; + } + } + + Panel *pMouseHandler = m_hMouseEventHandler.Get(); + if ( pMouseHandler ) + { + pMouseHandler->OnMousePressed( (MouseCode)code ); + } + else + { + OnMousePressed( (MouseCode)code ); + } + +#if defined( VGUI_USEDRAGDROP ) + DragDropStartDragging(); +#endif +} + +void Panel::InternalMouseDoublePressed(int code) +{ + m_lLastDoublePressTime = system()->GetTimeMillis(); + + if ( !ShouldHandleInputMessage() ) + return; + + if ( IsCursorNone() ) + return; + + if ( !IsMouseInputEnabled()) + { + return; + } + + if (IsBuildGroupEnabled()) + { + if ( _buildGroup->MouseDoublePressed((MouseCode)code, this) ) + { + return; + } + } + + Panel *pMouseHandler = m_hMouseEventHandler.Get(); + if ( pMouseHandler ) + { + pMouseHandler->OnMouseDoublePressed( (MouseCode)code ); + } + else + { + OnMouseDoublePressed( (MouseCode)code ); + } +} + +#if defined( VGUI_USEDRAGDROP ) +void Panel::SetStartDragWhenMouseExitsPanel( bool state ) +{ + _flags.SetFlag( DRAG_REQUIRES_PANEL_EXIT, state ); +} + +bool Panel::IsStartDragWhenMouseExitsPanel() const +{ + return _flags.IsFlagSet( DRAG_REQUIRES_PANEL_EXIT ); +} +#endif // VGUI_USEDRAGDROP + +void Panel::SetTriplePressAllowed( bool state ) +{ + _flags.SetFlag( TRIPLE_PRESS_ALLOWED, state ); +} + +bool Panel::IsTriplePressAllowed() const +{ + return _flags.IsFlagSet( TRIPLE_PRESS_ALLOWED ); +} + +void Panel::InternalMouseTriplePressed( int code ) +{ + Assert( IsTriplePressAllowed() ); + m_lLastDoublePressTime = 0L; + + if ( !ShouldHandleInputMessage() ) + return; + + if ( IsCursorNone() ) + return; + + if ( !IsMouseInputEnabled()) + { +#if defined( VGUI_USEDRAGDROP ) + DragDropStartDragging(); +#endif + return; + } + + if (IsBuildGroupEnabled()) + { + return; + } + + OnMouseTriplePressed((MouseCode)code); +#if defined( VGUI_USEDRAGDROP ) + DragDropStartDragging(); +#endif +} + +void Panel::InternalMouseReleased(int code) +{ +#if defined( VGUI_USEDRAGDROP ) + if ( g_DragDropCapture.Get() ) + { + bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted; + g_DragDropCapture->OnFinishDragging( true, (MouseCode)code ); + if ( started ) + { + return; + } + } +#endif + + if ( !ShouldHandleInputMessage() ) + return; + + if ( IsCursorNone() ) + return; + + if ( !IsMouseInputEnabled()) + { + return; + } + + if (IsBuildGroupEnabled()) + { + if ( _buildGroup->MouseReleased((MouseCode)code, this) ) + { + return; + } + } + + OnMouseReleased((MouseCode)code); +} + +void Panel::InternalMouseWheeled(int delta) +{ + if (IsBuildGroupEnabled() || !IsMouseInputEnabled()) + { + return; + } + + if ( !ShouldHandleInputMessage() ) + return; + + OnMouseWheeled(delta); +} + +void Panel::InternalKeyCodePressed(int code) +{ + if ( !ShouldHandleInputMessage() ) + return; + + if (IsKeyBoardInputEnabled()) + { + OnKeyCodePressed((KeyCode)code); + } + else + { + CallParentFunction(new KeyValues("KeyCodePressed", "code", code)); + } +} + +#if defined( VGUI_USEKEYBINDINGMAPS ) +//----------------------------------------------------------------------------- +// Purpose: +// Input : *bindingName - +// keycode - +// modifiers - +//----------------------------------------------------------------------------- +void Panel::AddKeyBinding( char const *bindingName, int keycode, int modifiers ) +{ + PanelKeyBindingMap *map = LookupMapForBinding( bindingName ); + if ( !map ) + { + Assert( 0 ); + return; + } + + BoundKey_t kb; + kb.isbuiltin = false; + kb.bindingname = CopyString( bindingName ); + kb.keycode = keycode; + kb.modifiers = modifiers; + + map->boundkeys.AddToTail( kb ); +} + +KeyBindingMap_t *Panel::LookupBinding( char const *bindingName ) +{ + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + int c = map->entries.Count(); + for( int i = 0; i < c ; ++i ) + { + KeyBindingMap_t *binding = &map->entries[ i ]; + if ( !Q_stricmp( binding->bindingname, bindingName ) ) + return binding; + } + + map = map->baseMap; + } + + return NULL; +} + +PanelKeyBindingMap *Panel::LookupMapForBinding( char const *bindingName ) +{ + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + int c = map->entries.Count(); + for( int i = 0; i < c ; ++i ) + { + KeyBindingMap_t *binding = &map->entries[ i ]; + if ( !Q_stricmp( binding->bindingname, bindingName ) ) + return map; + } + + map = map->baseMap; + } + + return NULL; +} + +KeyBindingMap_t *Panel::LookupBindingByKeyCode( KeyCode code, int modifiers ) +{ + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + int c = map->boundkeys.Count(); + for( int i = 0; i < c ; ++i ) + { + BoundKey_t *kb = &map->boundkeys[ i ]; + if ( kb->keycode == code && kb->modifiers == modifiers ) + { + KeyBindingMap_t *binding = LookupBinding( kb->bindingname ); + Assert( binding ); + if ( binding ) + { + return binding; + } + } + } + + map = map->baseMap; + } + + return NULL; +} + +BoundKey_t *Panel::LookupDefaultKey( char const *bindingName ) +{ + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + int c = map->defaultkeys.Count(); + for( int i = 0; i < c ; ++i ) + { + BoundKey_t *kb = &map->defaultkeys[ i ]; + if ( !Q_stricmp( kb->bindingname, bindingName ) ) + { + return kb; + } + } + + map = map->baseMap; + } + return NULL; +} + +void Panel::LookupBoundKeys( char const *bindingName, CUtlVector< BoundKey_t * >& list ) +{ + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + int c = map->boundkeys.Count(); + for( int i = 0; i < c ; ++i ) + { + BoundKey_t *kb = &map->boundkeys[ i ]; + if ( !Q_stricmp( kb->bindingname, bindingName ) ) + { + list.AddToTail( kb ); + } + } + + map = map->baseMap; + } +} + +void Panel::RevertKeyBindingsToDefault() +{ + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + map->boundkeys.RemoveAll(); + map->boundkeys = map->defaultkeys; + + map = map->baseMap; + } +} + +void Panel::RemoveAllKeyBindings() +{ + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + map->boundkeys.RemoveAll(); + map = map->baseMap; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void Panel::ReloadKeyBindings() +{ + RevertKeyBindingsToDefault(); + LoadKeyBindingsForOnePanel( GetKeyBindingsContext(), this ); +} + +#define MAKE_STRING( x ) #x +#define KEY_NAME( str, disp ) { KEY_##str, MAKE_STRING( KEY_##str ), disp } + +struct KeyNames_t +{ + KeyCode code; + char const *string; + char const *displaystring; +}; + +static KeyNames_t g_KeyNames[] = +{ +KEY_NAME( NONE, "None" ), +KEY_NAME( 0, "0" ), +KEY_NAME( 1, "1" ), +KEY_NAME( 2, "2" ), +KEY_NAME( 3, "3" ), +KEY_NAME( 4, "4" ), +KEY_NAME( 5, "5" ), +KEY_NAME( 6, "6" ), +KEY_NAME( 7, "7" ), +KEY_NAME( 8, "8" ), +KEY_NAME( 9, "9" ), +KEY_NAME( A, "A" ), +KEY_NAME( B, "B" ), +KEY_NAME( C, "C" ), +KEY_NAME( D, "D" ), +KEY_NAME( E, "E" ), +KEY_NAME( F, "F" ), +KEY_NAME( G, "G" ), +KEY_NAME( H, "H" ), +KEY_NAME( I, "I" ), +KEY_NAME( J, "J" ), +KEY_NAME( K, "K" ), +KEY_NAME( L, "L" ), +KEY_NAME( M, "M" ), +KEY_NAME( N, "N" ), +KEY_NAME( O, "O" ), +KEY_NAME( P, "P" ), +KEY_NAME( Q, "Q" ), +KEY_NAME( R, "R" ), +KEY_NAME( S, "S" ), +KEY_NAME( T, "T" ), +KEY_NAME( U, "U" ), +KEY_NAME( V, "V" ), +KEY_NAME( W, "W" ), +KEY_NAME( X, "X" ), +KEY_NAME( Y, "Y" ), +KEY_NAME( Z, "Z" ), +KEY_NAME( PAD_0, "Key Pad 0" ), +KEY_NAME( PAD_1, "Key Pad 1" ), +KEY_NAME( PAD_2, "Key Pad 2" ), +KEY_NAME( PAD_3, "Key Pad 3" ), +KEY_NAME( PAD_4, "Key Pad 4" ), +KEY_NAME( PAD_5, "Key Pad 5" ), +KEY_NAME( PAD_6, "Key Pad 6" ), +KEY_NAME( PAD_7, "Key Pad 7" ), +KEY_NAME( PAD_8, "Key Pad 8" ), +KEY_NAME( PAD_9, "Key Pad 9" ), +KEY_NAME( PAD_DIVIDE, "Key Pad /" ), +KEY_NAME( PAD_MULTIPLY, "Key Pad *" ), +KEY_NAME( PAD_MINUS, "Key Pad -" ), +KEY_NAME( PAD_PLUS, "Key Pad +" ), +KEY_NAME( PAD_ENTER, "Key Pad Enter" ), +KEY_NAME( PAD_DECIMAL, "Key Pad ." ), +KEY_NAME( LBRACKET, "[" ), +KEY_NAME( RBRACKET, "]" ), +KEY_NAME( SEMICOLON, "," ), +KEY_NAME( APOSTROPHE, "'" ), +KEY_NAME( BACKQUOTE, "`" ), +KEY_NAME( COMMA, "," ), +KEY_NAME( PERIOD, "." ), +KEY_NAME( SLASH, "/" ), +KEY_NAME( BACKSLASH, "\\" ), +KEY_NAME( MINUS, "-" ), +KEY_NAME( EQUAL, "=" ), +KEY_NAME( ENTER, "Enter" ), +KEY_NAME( SPACE, "Space" ), +KEY_NAME( BACKSPACE, "Backspace" ), +KEY_NAME( TAB, "Tab" ), +KEY_NAME( CAPSLOCK, "Caps Lock" ), +KEY_NAME( NUMLOCK, "Num Lock" ), +KEY_NAME( ESCAPE, "Escape" ), +KEY_NAME( SCROLLLOCK, "Scroll Lock" ), +KEY_NAME( INSERT, "Ins" ), +KEY_NAME( DELETE, "Del" ), +KEY_NAME( HOME, "Home" ), +KEY_NAME( END, "End" ), +KEY_NAME( PAGEUP, "PgUp" ), +KEY_NAME( PAGEDOWN, "PgDn" ), +KEY_NAME( BREAK, "Break" ), +KEY_NAME( LSHIFT, "Shift" ), +KEY_NAME( RSHIFT, "Shift" ), +KEY_NAME( LALT, "Alt" ), +KEY_NAME( RALT, "Alt" ), +KEY_NAME( LCONTROL, "Ctrl" ), +KEY_NAME( RCONTROL, "Ctrl" ), +KEY_NAME( LWIN, "Windows" ), +KEY_NAME( RWIN, "Windows" ), +KEY_NAME( APP, "App" ), +KEY_NAME( UP, "Up" ), +KEY_NAME( LEFT, "Left" ), +KEY_NAME( DOWN, "Down" ), +KEY_NAME( RIGHT, "Right" ), +KEY_NAME( F1, "F1" ), +KEY_NAME( F2, "F2" ), +KEY_NAME( F3, "F3" ), +KEY_NAME( F4, "F4" ), +KEY_NAME( F5, "F5" ), +KEY_NAME( F6, "F6" ), +KEY_NAME( F7, "F7" ), +KEY_NAME( F8, "F8" ), +KEY_NAME( F9, "F9" ), +KEY_NAME( F10, "F10" ), +KEY_NAME( F11, "F11" ), +KEY_NAME( F12, "F12" ), +KEY_NAME( CAPSLOCKTOGGLE, "Caps Lock Toggle" ), +KEY_NAME( NUMLOCKTOGGLE, "Num Lock Toggle" ), +KEY_NAME( SCROLLLOCKTOGGLE, "Scroll Lock Toggle" ), +}; + +char const *Panel::KeyCodeToString( KeyCode code ) +{ + int c = ARRAYSIZE( g_KeyNames ); + for ( int i = 0; i < c ; ++i ) + { + if ( g_KeyNames[ i ].code == code ) + return g_KeyNames[ i ].string; + } + + return ""; +} + +wchar_t const *Panel::KeyCodeToDisplayString( KeyCode code ) +{ + int c = ARRAYSIZE( g_KeyNames ); + for ( int i = 0; i < c ; ++i ) + { + if ( g_KeyNames[ i ].code == code ) + { + char const *str = g_KeyNames[ i ].displaystring; + wchar_t *wstr = g_pVGuiLocalize->Find( str ); + if ( wstr ) + { + return wstr; + } + + static wchar_t buf[ 64 ]; + g_pVGuiLocalize->ConvertANSIToUnicode( str, buf, sizeof( buf ) ); + return buf; + } + } + + return L""; +} + +static void AddModifierToString( char const *modifiername, char *buf, size_t bufsize ) +{ + char add[ 32 ]; + if ( Q_strlen( buf ) > 0 ) + { + Q_snprintf( add, sizeof( add ), "+%s", modifiername ); + } + else + { + Q_strncpy( add, modifiername, sizeof( add ) ); + } + + Q_strncat( buf, add, bufsize, COPY_ALL_CHARACTERS ); + +} + +wchar_t const *Panel::KeyCodeModifiersToDisplayString( KeyCode code, int modifiers ) +{ + char sz[ 256 ]; + sz[ 0 ] = 0; + + if ( modifiers & MODIFIER_SHIFT ) + { + AddModifierToString( "Shift", sz, sizeof( sz ) ); + } + if ( modifiers & MODIFIER_CONTROL ) + { + AddModifierToString( "Ctrl", sz, sizeof( sz ) ); + } + if ( modifiers & MODIFIER_ALT ) + { + AddModifierToString( "Alt", sz, sizeof( sz ) ); + } + + if ( Q_strlen( sz ) > 0 ) + { + Q_strncat( sz, "+", sizeof( sz ), COPY_ALL_CHARACTERS ); + } + + static wchar_t unicode[ 256 ]; + V_swprintf_safe( unicode, L"%S%s", sz, Panel::KeyCodeToDisplayString( (KeyCode)code ) ); + return unicode; +} + +KeyCode Panel::StringToKeyCode( char const *str ) +{ + int c = ARRAYSIZE( g_KeyNames ); + for ( int i = 0; i < c ; ++i ) + { + if ( !Q_stricmp( str, g_KeyNames[ i ].string ) ) + return g_KeyNames[ i ].code; + } + + return KEY_NONE; +} + +static void WriteKeyBindingToBuffer( CUtlBuffer& buf, int level, const BoundKey_t& binding ) +{ + BufPrint( buf, level, "\"keycode\"\t\"%s\"\n", Panel::KeyCodeToString( (KeyCode)binding.keycode ) ); + if ( binding.modifiers & MODIFIER_SHIFT ) + { + BufPrint( buf, level, "\"shift\"\t\"1\"\n" ); + } + if ( binding.modifiers & MODIFIER_CONTROL ) + { + BufPrint( buf, level, "\"ctrl\"\t\"1\"\n" ); + } + if ( binding.modifiers & MODIFIER_ALT ) + { + BufPrint( buf, level, "\"alt\"\t\"1\"\n" ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *filename - +// *pathID - +//----------------------------------------------------------------------------- +void Panel::SaveKeyBindingsToBuffer( int level, CUtlBuffer& buf ) +{ + Assert( IsValidKeyBindingsContext() ); + + Assert( buf.IsText() ); + + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + int c = map->boundkeys.Count(); + for( int i = 0; i < c ; ++i ) + { + const BoundKey_t& binding = map->boundkeys[ i ]; + + // Spew to file + BufPrint( buf, level, "\"%s\"\n", binding.bindingname ); + BufPrint( buf, level, "{\n" ); + + WriteKeyBindingToBuffer( buf, level + 1, binding ); + + BufPrint( buf, level, "}\n" ); + } + + map = map->baseMap; + } +} + +bool Panel::ParseKeyBindings( KeyValues *kv ) +{ + Assert( IsValidKeyBindingsContext() ); + if ( !IsValidKeyBindingsContext() ) + return false; + + // To have KB the panel must have a name + Assert( GetName() && GetName()[ 0 ] ); + if ( !GetName() || !GetName()[ 0 ] ) + return false; + + bool success = false; + + g_KBMgr.AddPanelToContext( GetKeyBindingsContext(), this ); + + RemoveAllKeyBindings(); + + // Walk through bindings + for ( KeyValues *binding = kv->GetFirstSubKey(); binding != NULL; binding = binding->GetNextKey() ) + { + char const *bindingName = binding->GetName(); + if ( !bindingName || !bindingName[ 0 ] ) + continue; + + KeyBindingMap_t *b = LookupBinding( bindingName ); + if ( b ) + { + success = true; + const char *keycode = binding->GetString( "keycode", "" ); + int modifiers = 0; + if ( binding->GetInt( "shift", 0 ) != 0 ) + { + modifiers |= MODIFIER_SHIFT; + } + if ( binding->GetInt( "ctrl", 0 ) != 0 ) + { + modifiers |= MODIFIER_CONTROL; + } + if ( binding->GetInt( "alt", 0 ) != 0 ) + { + modifiers |= MODIFIER_ALT; + } + + KeyBindingMap_t *bound = LookupBindingByKeyCode( StringToKeyCode( keycode ), modifiers ); + if ( !bound ) + { + AddKeyBinding( bindingName, StringToKeyCode( keycode ), modifiers ); + } + } + else + { + Warning( "KeyBinding for panel '%s' contained unknown binding '%s'\n", GetName() ? GetName() : "???", bindingName ); + } + } + + // Now for each binding which is currently "unbound" to any key, use the default binding + PanelKeyBindingMap *map = GetKBMap(); + while( map ) + { + int c = map->entries.Count(); + for( int i = 0; i < c ; ++i ) + { + KeyBindingMap_t *binding = &map->entries[ i ]; + + // See if there is a bound key + CUtlVector< BoundKey_t * > list; + LookupBoundKeys( binding->bindingname, list ); + if ( list.Count() == 0 ) + { + // Assign the default binding to this key + BoundKey_t *defaultKey = LookupDefaultKey( binding->bindingname ); + if ( defaultKey ) + { + KeyBindingMap_t *alreadyBound = LookupBindingByKeyCode( (KeyCode)defaultKey->keycode, defaultKey->modifiers ); + if ( alreadyBound ) + { + Warning( "No binding for '%s', defautl key already bound to '%s'\n", binding->bindingname, alreadyBound->bindingname ); + } + else + { + AddKeyBinding( defaultKey->bindingname, defaultKey->keycode, defaultKey->modifiers ); + } + } + } + } + + map = map->baseMap; + } + + return success; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : handle - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +void Panel::SetKeyBindingsContext( KeyBindingContextHandle_t handle ) +{ + Assert( !IsValidKeyBindingsContext() || handle == GetKeyBindingsContext() ); + g_KBMgr.AddPanelToContext( handle, this ); + m_hKeyBindingsContext = handle; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : KeyBindingContextHandle_t +//----------------------------------------------------------------------------- +KeyBindingContextHandle_t Panel::GetKeyBindingsContext() const +{ + return m_hKeyBindingsContext; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsValidKeyBindingsContext() const +{ + return GetKeyBindingsContext() != INVALID_KEYBINDINGCONTEXT_HANDLE; +} + +char const *Panel::GetKeyBindingsFile() const +{ + Assert( IsValidKeyBindingsContext() ); + return g_KBMgr.GetKeyBindingsFile( GetKeyBindingsContext() ); +} + +char const *Panel::GetKeyBindingsFilePathID() const +{ + Assert( IsValidKeyBindingsContext() ); + return g_KBMgr.GetKeyBindingsFilePathID( GetKeyBindingsContext() ); +} + +void Panel::EditKeyBindings() +{ + Assert( 0 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Set this to false to disallow IsKeyRebound chaining to GetParent() Panels... +// Input : state - +//----------------------------------------------------------------------------- +void Panel::SetAllowKeyBindingChainToParent( bool state ) +{ + _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT, state ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsKeyBindingChainToParentAllowed() const +{ + return _flags.IsFlagSet( ALLOW_CHAIN_KEYBINDING_TO_PARENT ); +} + +bool Panel::IsKeyOverridden( KeyCode code, int modifiers ) +{ + // By default assume all keys should pass through binding system + return false; +} + +bool Panel::IsKeyRebound( KeyCode code, int modifiers ) +{ + if ( IsKeyBoardInputEnabled() ) + { + KeyBindingMap_t* binding = LookupBindingByKeyCode( code, modifiers ); + // Only dispatch if we're part of the current modal subtree + if ( binding && IsChildOfSurfaceModalPanel() ) + { + // Found match, post message to panel + if ( binding->func ) + { + // dispatch the func + (this->*binding->func)(); + } + else + { + Assert( 0 ); + } + + if ( !binding->passive ) + { + // Exit this function... + return true; + } + } + } + + // Chain to parent + Panel* pParent = GetParent(); + if ( IsKeyBindingChainToParentAllowed() && pParent && !IsKeyOverridden( code, modifiers ) ) + return pParent->IsKeyRebound( code, modifiers ); + + // No suitable binding found + return false; +} + +static bool s_bSuppressRebindChecks = false; +#endif // VGUI_USEKEYBINDINGMAPS + +void Panel::InternalKeyCodeTyped( int code ) +{ + if ( !ShouldHandleInputMessage() ) + { + input()->OnKeyCodeUnhandled( code ); + return; + } + + if (IsKeyBoardInputEnabled()) + { + 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; + } + + // Things in build mode don't have accelerators + if (IsBuildGroupEnabled()) + { + _buildGroup->KeyCodeTyped((KeyCode)code, this); + return; + } + + if ( !s_bSuppressRebindChecks && IsKeyRebound( (KeyCode)code, modifiers ) ) + { + return; + } + + bool oldVal = s_bSuppressRebindChecks; + s_bSuppressRebindChecks = true; + OnKeyCodeTyped((KeyCode)code); + s_bSuppressRebindChecks = oldVal; + } + else + { + if ( GetVPanel() == surface()->GetEmbeddedPanel() ) + { + input()->OnKeyCodeUnhandled( code ); + } + CallParentFunction(new KeyValues("KeyCodeTyped", "code", code)); + } +} + +void Panel::InternalKeyTyped(int unichar) +{ + if ( !ShouldHandleInputMessage() ) + return; + + if (IsKeyBoardInputEnabled()) + { + if ( IsBuildGroupEnabled() ) + { + if ( _buildGroup->KeyTyped( (wchar_t)unichar, this ) ) + { + return; + } + } + + OnKeyTyped((wchar_t)unichar); + } + else + { + CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar)); + } +} + +void Panel::InternalKeyCodeReleased(int code) +{ + if ( !ShouldHandleInputMessage() ) + return; + + if (IsKeyBoardInputEnabled()) + { + if (IsBuildGroupEnabled()) + { + if ( _buildGroup->KeyCodeReleased((KeyCode)code, this) ) + { + return; + } + } + + OnKeyCodeReleased((KeyCode)code); + } + else + { + CallParentFunction(new KeyValues("KeyCodeReleased", "code", code)); + } +} + +void Panel::InternalKeyFocusTicked() +{ + if (IsBuildGroupEnabled()) + return; + + OnKeyFocusTicked(); +} + +void Panel::InternalMouseFocusTicked() +{ + if (IsBuildGroupEnabled()) + { + // must repaint so the numbers will be accurate + if (_buildGroup->HasRulersOn()) + { + PaintTraverse(true); + } + return; + } + + // update cursor + InternalSetCursor(); + OnMouseFocusTicked(); +} + + +void Panel::InternalSetCursor() +{ + bool visible = IsVisible(); + + if (visible) + { +#if defined( VGUI_USEDRAGDROP ) + // Drag drop is overriding cursor? + if ( m_pDragDrop->m_bDragging || + g_DragDropCapture.Get() != NULL ) + return; +#endif + // chain up and make sure all our parents are also visible + VPANEL p = GetVParent(); + while (p) + { + visible &= ipanel()->IsVisible(p); + p = ipanel()->GetParent(p); + } + + // only change the cursor if this panel is visible, and if its part of the main VGUI tree + if (visible && HasParent(surface()->GetEmbeddedPanel())) + { + HCursor cursor = GetCursor(); + + if (IsBuildGroupEnabled()) + { + cursor = _buildGroup->GetCursor(this); + } + + if (input()->GetCursorOveride()) + { + cursor = input()->GetCursorOveride(); + } + + surface()->SetCursor(cursor); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Called every frame the panel is visible, designed to be overridden +//----------------------------------------------------------------------------- +void Panel::OnThink() +{ +#if defined( VGUI_USEDRAGDROP ) + if ( IsPC() && + m_pDragDrop->m_bDragEnabled && + m_pDragDrop->m_bDragging && + m_pDragDrop->m_bDragStarted ) + { + bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE ); + if ( isEscapeKeyDown ) + { + OnContinueDragging(); + OnFinishDragging( true, (MouseCode)-1, true ); + return; + } + + if ( m_pDragDrop->m_hCurrentDrop != 0 ) + { + if ( !input()->IsMouseDown( MOUSE_LEFT ) ) + { + OnContinueDragging(); + OnFinishDragging( true, (MouseCode)-1 ); + return; + } + + // allow the cursor to change based upon things like changing keystate, etc. + surface()->SetCursor( m_pDragDrop->m_hCurrentDrop->GetDropCursor( m_pDragDrop->m_DragData ) ); + + if ( !m_pDragDrop->m_bDropMenuShown ) + { + // See if the hover time has gotten larger + float hoverSeconds = ( system()->GetTimeMillis() - m_pDragDrop->m_lDropHoverTime ) * 0.001f; + DragDrop_t *dropInfo = m_pDragDrop->m_hCurrentDrop->GetDragDropInfo(); + + if ( dropInfo->m_flHoverContextTime != 0.0f ) + { + if ( hoverSeconds >= dropInfo->m_flHoverContextTime ) + { + m_pDragDrop->m_bDropMenuShown = true; + + CUtlVector< KeyValues * > data; + + GetDragData( data ); + + int x, y; + input()->GetCursorPos( x, y ); + + if ( m_pDragDrop->m_hDropContextMenu.Get() ) + { + delete m_pDragDrop->m_hDropContextMenu.Get(); + } + + Menu *menu = new Menu( m_pDragDrop->m_hCurrentDrop.Get(), "DropContext" ); + + bool useMenu = m_pDragDrop->m_hCurrentDrop->GetDropContextMenu( menu, data ); + if ( useMenu ) + { + m_pDragDrop->m_hDropContextMenu = menu; + + menu->SetPos( x, y ); + menu->SetVisible( true ); + menu->MakePopup(); + surface()->MovePopupToFront( menu->GetVPanel() ); + if ( menu->GetItemCount() > 0 ) + { + int id = menu->GetMenuID( 0 ); + menu->SetCurrentlyHighlightedItem( id ); + MenuItem *item = menu->GetMenuItem( id ); + item->SetArmed( true ); + } + } + else + { + delete menu; + } + + m_pDragDrop->m_hCurrentDrop->OnDropContextHoverShow( data ); + } + } + } + } + } +#endif +} + +// input messages handlers (designed for override) +void Panel::OnCursorMoved(int x, int y) +{ + if( ParentNeedsCursorMoveEvents() ) + { + // figure out x and y in parent space + int thisX, thisY; + ipanel()->GetPos( GetVPanel(), thisX, thisY ); + CallParentFunction( new KeyValues( "OnCursorMoved", "x", x + thisX, "y", y + thisY ) ); + } +} + +void Panel::OnCursorEntered() +{ +} + +void Panel::OnCursorExited() +{ +} + +void Panel::OnMousePressed(MouseCode code) +{ +} + +void Panel::OnMouseDoublePressed(MouseCode code) +{ +} + +void Panel::OnMouseTriplePressed(MouseCode code) +{ +} + +void Panel::OnMouseReleased(MouseCode code) +{ +} + +void Panel::OnMouseWheeled(int delta) +{ + CallParentFunction(new KeyValues("MouseWheeled", "delta", delta)); +} + +// base implementation forwards Key messages to the Panel's parent - override to 'swallow' the input +void Panel::OnKeyCodePressed(KeyCode code) +{ + static ConVarRef vgui_nav_lock( "vgui_nav_lock" ); + + bool handled = false; + switch( GetBaseButtonCode( code ) ) + { + case KEY_XBUTTON_UP: + case KEY_XSTICK1_UP: + case KEY_XSTICK2_UP: + case KEY_UP: + if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateUp() ) + { + vgui_nav_lock.SetValue( 1 ); + vgui::surface()->PlaySound( "UI/menu_focus.wav" ); + handled = true; + } + break; + case KEY_XBUTTON_DOWN: + case KEY_XSTICK1_DOWN: + case KEY_XSTICK2_DOWN: + case KEY_DOWN: + if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateDown() ) + { + vgui_nav_lock.SetValue( 1 ); + vgui::surface()->PlaySound( "UI/menu_focus.wav" ); + handled = true; + } + break; + case KEY_XBUTTON_LEFT: + case KEY_XSTICK1_LEFT: + case KEY_XSTICK2_LEFT: + case KEY_LEFT: + if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateLeft() ) + { + vgui_nav_lock.SetValue( 1 ); + vgui::surface()->PlaySound( "UI/menu_focus.wav" ); + handled = true; + } + break; + case KEY_XBUTTON_RIGHT: + case KEY_XSTICK1_RIGHT: + case KEY_XSTICK2_RIGHT: + case KEY_RIGHT: + if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateRight() ) + { + vgui_nav_lock.SetValue( 1 ); + vgui::surface()->PlaySound( "UI/menu_focus.wav" ); + handled = true; + } + break; + case KEY_XBUTTON_B: + if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateBack() ) + { + vgui_nav_lock.SetValue( 1 ); + vgui::surface()->PlaySound( "UI/menu_focus.wav" ); + handled = true; + } + break; + } + + if( !handled && !m_PassUnhandledInput ) + return; + + CallParentFunction(new KeyValues("KeyCodePressed", "code", code)); +} + +void Panel::OnKeyCodeTyped(KeyCode keycode) +{ + vgui::KeyCode code = GetBaseButtonCode( keycode ); + + // handle focus change + if ( IsX360() || IsConsoleStylePanel() ) + { + // eat these typed codes, will get handled in OnKeyCodePressed + switch ( code ) + { + case KEY_XBUTTON_UP: + case KEY_XSTICK1_UP: + case KEY_XSTICK2_UP: + case KEY_XBUTTON_DOWN: + case KEY_XSTICK1_DOWN: + case KEY_XSTICK2_DOWN: + case KEY_XBUTTON_LEFT: + case KEY_XSTICK1_LEFT: + case KEY_XSTICK2_LEFT: + case KEY_XBUTTON_RIGHT: + case KEY_XSTICK1_RIGHT: + case KEY_XSTICK2_RIGHT: + case KEY_XBUTTON_A: + case KEY_XBUTTON_B: + case KEY_XBUTTON_X: + case KEY_XBUTTON_Y: + case KEY_XBUTTON_LEFT_SHOULDER: + case KEY_XBUTTON_RIGHT_SHOULDER: + case KEY_XBUTTON_BACK: + case KEY_XBUTTON_START: + case KEY_XBUTTON_STICK1: + case KEY_XBUTTON_STICK2: + case KEY_XBUTTON_LTRIGGER: + case KEY_XBUTTON_RTRIGGER: + + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + return; + } + + // legacy handling - need to re-enable for older apps? + /* + if ( code == KEY_XSTICK1_RIGHT || code == KEY_XBUTTON_RIGHT ) + { + RequestFocusNext(); + return; + } + else if ( code == KEY_XSTICK1_LEFT || code == KEY_XBUTTON_LEFT ) + { + RequestFocusPrev(); + return; + } + */ + } + + if (code == KEY_TAB) + { + bool bShiftDown = input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT); + + if ( IsConsoleStylePanel() ) + { + if ( bShiftDown ) + { + NavigateUp(); + } + else + { + NavigateDown(); + } + } + else + { + // if shift is down goto previous tab position, otherwise goto next + if ( bShiftDown ) + { + RequestFocusPrev(); + } + else + { + RequestFocusNext(); + } + } + } + else + { + // forward up + if ( GetVPanel() == surface()->GetEmbeddedPanel() ) + { + input()->OnKeyCodeUnhandled( keycode ); + } + CallParentFunction(new KeyValues("KeyCodeTyped", "code", keycode)); + } +} + +void Panel::OnKeyTyped(wchar_t unichar) +{ + CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar)); +} + +void Panel::OnKeyCodeReleased(KeyCode code) +{ + CallParentFunction(new KeyValues("KeyCodeReleased", "code", code)); +} + +void Panel::OnKeyFocusTicked() +{ + CallParentFunction(new KeyValues("KeyFocusTicked")); +} + +void Panel::OnMouseFocusTicked() +{ + CallParentFunction(new KeyValues("OnMouseFocusTicked")); +} + +bool Panel::IsWithin(int x,int y) +{ + // check against our clip rect + int clipRect[4]; + ipanel()->GetClipRect(GetVPanel(), clipRect[0], clipRect[1], clipRect[2], clipRect[3]); + + if (x < clipRect[0]) + { + return false; + } + + if (y < clipRect[1]) + { + return false; + } + + if (x >= clipRect[2]) + { + return false; + } + + if (y >= clipRect[3]) + { + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: determines which is the topmost panel under the coordinates (x, y) +//----------------------------------------------------------------------------- +VPANEL Panel::IsWithinTraverse(int x, int y, bool traversePopups) +{ + // if this one is not visible, its children won't be either + // also if it doesn't want mouse input its children can't get it either + if (!IsVisible() || !IsMouseInputEnabled()) + return NULL; + + if (traversePopups) + { + // check popups first + int i; + CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() ); + int childCount = children.Count(); + for (i = childCount - 1; i >= 0; i--) + { + VPANEL panel = children[ i ]; + if (ipanel()->IsPopup(panel)) + { + panel = ipanel()->IsWithinTraverse(panel, x, y, true); + if (panel != null) + { + return panel; + } + } + } + + // check children recursive, if you find one, just return first one + // this checks in backwards order so the last child drawn for this panel is chosen which + // coincides to how it would be visibly displayed + for (i = childCount - 1; i >= 0; i--) + { + VPANEL panel = children[ i ]; + // we've already checked popups so ignore + if (!ipanel()->IsPopup(panel)) + { + panel = ipanel()->IsWithinTraverse(panel, x, y, true); + if (panel != 0) + { + return panel; + } + } + } + + // check ourself + if ( !IsMouseInputDisabledForThisPanel() && IsWithin(x, y) ) + { + return GetVPanel(); + } + } + else + { + // since we're not checking popups, it must be within us, so we can check ourself first + if (IsWithin(x, y)) + { + // check children recursive, if you find one, just return first one + // this checks in backwards order so the last child drawn for this panel is chosen which + // coincides to how it would be visibly displayed + CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() ); + int childCount = children.Count(); + for (int i = childCount - 1; i >= 0; i--) + { + VPANEL panel = children[ i ]; + // ignore popups + if (!ipanel()->IsPopup(panel)) + { + panel = ipanel()->IsWithinTraverse(panel, x, y, false); + if (panel != 0) + { + return panel; + } + } + } + + // not a child, must be us + if ( !IsMouseInputDisabledForThisPanel() ) + return GetVPanel(); + } + } + + return NULL; +} + +void Panel::LocalToScreen(int& x,int& y) +{ + int px, py; + ipanel()->GetAbsPos(GetVPanel(), px, py); + + x = x + px; + y = y + py; +} + +void Panel::ScreenToLocal(int& x,int& y) +{ + int px, py; + ipanel()->GetAbsPos(GetVPanel(), px, py); + + x = x - px; + y = y - py; +} + +void Panel::ParentLocalToScreen(int &x, int &y) +{ + int px, py; + ipanel()->GetAbsPos(GetVParent(), px, py); + + x = x + px; + y = y + py; +} + +void Panel::MakePopup(bool showTaskbarIcon,bool disabled) +{ + surface()->CreatePopup(GetVPanel(), false, showTaskbarIcon,disabled); +} + +void Panel::SetCursor(HCursor cursor) +{ + _cursor = cursor; +} + +HCursor Panel::GetCursor() +{ + return _cursor; +} + +void Panel::SetCursorAlwaysVisible( bool visible ) +{ + surface()->SetCursorAlwaysVisible( visible ); +} + +void Panel::SetMinimumSize(int wide,int tall) +{ + ipanel()->SetMinimumSize(GetVPanel(), wide, tall); +} + +void Panel::GetMinimumSize(int& wide,int &tall) +{ + ipanel()->GetMinimumSize(GetVPanel(), wide, tall); +} + +bool Panel::IsBuildModeEditable() +{ + return true; +} + +void Panel::SetBuildModeEditable(bool state) +{ + if (state) + { + _buildModeFlags |= BUILDMODE_EDITABLE; + } + else + { + _buildModeFlags &= ~BUILDMODE_EDITABLE; + } +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +bool Panel::IsBuildModeDeletable() +{ + return (_buildModeFlags & BUILDMODE_DELETABLE); +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +void Panel::SetBuildModeDeletable(bool state) +{ + if (state) + { + _buildModeFlags |= BUILDMODE_DELETABLE; + } + else + { + _buildModeFlags &= ~BUILDMODE_DELETABLE; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Panel::IsBuildModeActive() +{ + return _buildGroup ? _buildGroup->IsEnabled() : false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::GetClipRect(int& x0,int& y0,int& x1,int& y1) +{ + ipanel()->GetClipRect(GetVPanel(), x0, y0, x1, y1); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int Panel::GetChildCount() +{ + if (ipanel()) + { + return ipanel()->GetChildCount(GetVPanel()); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: returns a child by the specified index +//----------------------------------------------------------------------------- +Panel *Panel::GetChild(int index) +{ + // get the child and cast it to a panel + // this assumes that the child is from the same module as the this (precondition) + return ipanel()->GetPanel(ipanel()->GetChild(GetVPanel(), index), GetControlsModuleName()); +} + +CUtlVector< VPANEL > &Panel::GetChildren() +{ + return ipanel()->GetChildren(GetVPanel()); +} + +//----------------------------------------------------------------------------- +// Purpose: moves the key focus back +//----------------------------------------------------------------------------- +bool Panel::RequestFocusPrev(VPANEL panel) +{ + // chain to parent + if (GetVParent()) + { + return ipanel()->RequestFocusPrev(GetVParent(), GetVPanel()); + } + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Panel::RequestFocusNext(VPANEL panel) +{ + // chain to parent + if (GetVParent()) + { + return ipanel()->RequestFocusNext(GetVParent(), GetVPanel()); + } + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the panel to have the current sub focus +// Input : direction - the direction in which focus travelled to arrive at this panel; forward = 1, back = -1 +//----------------------------------------------------------------------------- +void Panel::RequestFocus(int direction) +{ + // NOTE: This doesn't make any sense if we don't have keyboard input enabled + Assert( ( IsX360() || IsConsoleStylePanel() ) || IsKeyBoardInputEnabled() ); + // ivgui()->DPrintf2("RequestFocus(%s, %s)\n", GetName(), GetClassName()); + OnRequestFocus(GetVPanel(), NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: Called after a panel requests focus to fix up the whole chain +//----------------------------------------------------------------------------- +void Panel::OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel) +{ + CallParentFunction(new KeyValues("OnRequestFocus", "subFocus", subFocus, "defaultPanel", defaultPanel)); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +VPANEL Panel::GetCurrentKeyFocus() +{ + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the panel has focus +//----------------------------------------------------------------------------- +bool Panel::HasFocus() +{ + if (input()->GetFocus() == GetVPanel()) + { + return true; + } + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetTabPosition(int position) +{ + _tabPosition = position; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int Panel::GetTabPosition() +{ + return _tabPosition; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::InternalFocusChanged(bool lost) +{ + /* + //if focus is gained tell the focusNavGroup about it so its current can be correct + if( (!lost) && (_focusNavGroup!=null) ) + { + _focusNavGroup->setCurrentPanel(this); + } + */ +} + +//----------------------------------------------------------------------------- +// Purpose: Called when a panel loses it's mouse capture +//----------------------------------------------------------------------------- +void Panel::OnMouseCaptureLost() +{ + if (m_pTooltips) + { + m_pTooltips->ResetDelay(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::AddActionSignalTarget(Panel *messageTarget) +{ + HPanel target = ivgui()->PanelToHandle(messageTarget->GetVPanel()); + if (!_actionSignalTargetDar.HasElement(target)) + { + _actionSignalTargetDar.AddElement(target); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::AddActionSignalTarget(VPANEL messageTarget) +{ + HPanel target = ivgui()->PanelToHandle(messageTarget); + if (!_actionSignalTargetDar.HasElement(target)) + { + _actionSignalTargetDar.AddElement(target); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::RemoveActionSignalTarget(Panel *oldTarget) +{ + _actionSignalTargetDar.RemoveElement(ivgui()->PanelToHandle(oldTarget->GetVPanel())); +} + +//----------------------------------------------------------------------------- +// Purpose: Sends a message to all the panels that have requested action signals +//----------------------------------------------------------------------------- +void Panel::PostActionSignal( KeyValues *message ) +{ + if ( m_bIsSilent != true ) + { + // add who it was from the message + message->SetPtr("panel", this); + int i; + for (i = _actionSignalTargetDar.GetCount() - 1; i > 0; i--) + { + VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]); + if (panel) + { + ivgui()->PostMessage(panel, message->MakeCopy(), GetVPanel()); + } + } + + // do this so we can save on one MakeCopy() call + if (i == 0) + { + VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]); + if (panel) + { + ivgui()->PostMessage(panel, message, GetVPanel()); + return; + } + } + } + message->deleteThis(); +} + +void Panel::SetBorder(IBorder *border) +{ + _border = border; + + if (border) + { + int x, y, x2, y2; + border->GetInset(x, y, x2, y2); + ipanel()->SetInset(GetVPanel(), x, y, x2, y2); + + // update our background type based on the bord + SetPaintBackgroundType(border->GetBackgroundType()); + } + else + { + ipanel()->SetInset(GetVPanel(), 0, 0, 0, 0); + } +} + +IBorder *Panel::GetBorder() +{ + return _border; +} + + +void Panel::SetPaintBorderEnabled(bool state) +{ + _flags.SetFlag( PAINT_BORDER_ENABLED, state ); +} + +void Panel::SetPaintBackgroundEnabled(bool state) +{ + _flags.SetFlag( PAINT_BACKGROUND_ENABLED, state ); +} + +void Panel::SetPaintBackgroundType( int type ) +{ + // HACK only 0 through 2 supported for now + m_nPaintBackgroundType = clamp( type, 0, 2 ); +} + +void Panel::SetPaintEnabled(bool state) +{ + _flags.SetFlag( PAINT_ENABLED, state ); +} + +void Panel::SetPostChildPaintEnabled(bool state) +{ + _flags.SetFlag( POST_CHILD_PAINT_ENABLED, state ); +} + +void Panel::GetInset(int& left,int& top,int& right,int& bottom) +{ + ipanel()->GetInset(GetVPanel(), left, top, right, bottom); +} + +void Panel::GetPaintSize(int& wide,int& tall) +{ + GetSize(wide, tall); + if (_border != null) + { + int left,top,right,bottom; + _border->GetInset(left,top,right,bottom); + + wide -= (left+right); + tall -= (top+bottom); + } +} + +int Panel::GetWide() +{ + int wide, tall; + ipanel()->GetSize(GetVPanel(), wide, tall); + return wide; +} + +void Panel::SetWide(int wide) +{ + ipanel()->SetSize(GetVPanel(), wide, GetTall()); +} + +int Panel::GetTall() +{ + int wide, tall; + ipanel()->GetSize(GetVPanel(), wide, tall); + return tall; +} + +void Panel::SetTall(int tall) +{ + ipanel()->SetSize(GetVPanel(), GetWide(), tall); +} + +void Panel::SetBuildGroup(BuildGroup* buildGroup) +{ + //TODO: remove from old group + + Assert(buildGroup != NULL); + + _buildGroup = buildGroup; + + _buildGroup->PanelAdded(this); +} + +bool Panel::IsBuildGroupEnabled() +{ + if ( !_buildGroup.IsValid() ) + return false; + + bool enabled = _buildGroup->IsEnabled(); + if ( enabled ) + return enabled; + + if ( GetParent() && GetParent()->IsBuildGroupEnabled() ) + return true; + + return false; +} + +void Panel::SetBgColor(Color color) +{ + _bgColor = color; +} + +void Panel::SetFgColor(Color color) +{ + _fgColor = color; +} + +Color Panel::GetBgColor() +{ + return _bgColor; +} + +Color Panel::GetFgColor() +{ + return _fgColor; +} + +void Panel::InternalPerformLayout() +{ + // Don't layout if we're still waiting for our scheme to be applied. + // At worst, it leads to crashes, at best it does work that we'll redo as soon as the scheme has been applied. + if ( _flags.IsFlagSet( NEEDS_SCHEME_UPDATE ) ) + return; + + _flags.SetFlag( IN_PERFORM_LAYOUT ); + // make sure the scheme has been applied + _flags.ClearFlag( NEEDS_LAYOUT ); + PerformLayout(); + _flags.ClearFlag( IN_PERFORM_LAYOUT ); +} + +void Panel::PerformLayout() +{ + // this should be overridden to relayout controls +} + +void Panel::InvalidateLayout( bool layoutNow, bool reloadScheme ) +{ + _flags.SetFlag( NEEDS_LAYOUT ); + + if (reloadScheme) + { + // make all our children reload the scheme + _flags.SetFlag( NEEDS_SCHEME_UPDATE ); + + for (int i = 0; i < GetChildCount(); i++) + { + vgui::Panel* panel = GetChild(i); + if( panel ) + { + panel->InvalidateLayout(layoutNow, true); + } + } + + PerformApplySchemeSettings(); + } + + if (layoutNow) + { + InternalPerformLayout(); + Repaint(); + } +} + +bool Panel::IsCursorNone() +{ + HCursor cursor = GetCursor(); + + if (!cursor) + { + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the cursor is currently over the panel +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsCursorOver(void) +{ + int x, y; + input()->GetCursorPos(x, y); + return IsWithin(x, y); +} + +//----------------------------------------------------------------------------- +// Purpose: Called when a panel receives a command message from another panel +//----------------------------------------------------------------------------- +void Panel::OnCommand(const char *command) +{ + if ( !Q_stricmp( "performlayout", command ) ) + { + InvalidateLayout(); + } + else if ( !Q_stricmp( "reloadscheme", command ) ) + { + InvalidateLayout( false, true ); + } + else + { + // if noone else caught this, pass along to the listeners + // (this is useful for generic dialogs - otherwise, commands just get ignored) + KeyValues *msg = new KeyValues( command ); + PostActionSignal( msg ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: panel gained focus message +//----------------------------------------------------------------------------- +void Panel::OnSetFocus() +{ + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: panel lost focus message +//----------------------------------------------------------------------------- +void Panel::OnKillFocus() +{ + Repaint(); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the object up to be deleted next frame +//----------------------------------------------------------------------------- +void Panel::MarkForDeletion() +{ + if ( _flags.IsFlagSet( MARKED_FOR_DELETION ) ) + return; + + _flags.SetFlag( MARKED_FOR_DELETION ); + _flags.ClearFlag( AUTODELETE_ENABLED ); + + if (ivgui()->IsRunning()) + { + ivgui()->MarkPanelForDeletion(GetVPanel()); + } + // direct delete is never safe because even if ivgui is shutdown we manually do RunFrame() + // and we can enter here in a think traverse and then delete from underneath ourselves + /*else + { + delete this; + }*/ +} + +//----------------------------------------------------------------------------- +// Purpose: return true if this object require a perform layout +//----------------------------------------------------------------------------- +bool Panel::IsLayoutInvalid() +{ + return _flags.IsFlagSet( NEEDS_LAYOUT ); +} + + +//----------------------------------------------------------------------------- +// Sets the pin corner + resize mode for resizing panels +//----------------------------------------------------------------------------- +void Panel::SetAutoResize( PinCorner_e pinCorner, AutoResize_e resizeDir, + int nPinOffsetX, int nPinOffsetY, int nUnpinnedCornerOffsetX, int nUnpinnedCornerOffsetY ) +{ + _pinCorner = pinCorner; + _autoResizeDirection = resizeDir; + m_nPinDeltaX = nPinOffsetX; + m_nPinDeltaY = nPinOffsetY; + m_nResizeDeltaX = nUnpinnedCornerOffsetX; + m_nResizeDeltaY = nUnpinnedCornerOffsetY; +} + + +//----------------------------------------------------------------------------- +// Sets the pin corner for non-resizing panels +//----------------------------------------------------------------------------- +void Panel::SetPinCorner( PinCorner_e pinCorner, int nOffsetX, int nOffsetY ) +{ + _pinCorner = pinCorner; + _autoResizeDirection = AUTORESIZE_NO; + m_nPinDeltaX = nOffsetX; + m_nPinDeltaY = nOffsetY; + m_nResizeDeltaX = 0; + m_nResizeDeltaY = 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +Panel::PinCorner_e Panel::GetPinCorner() +{ + return (PinCorner_e)_pinCorner; +} + + +//----------------------------------------------------------------------------- +// Gets the relative offset of the control from the pin corner +//----------------------------------------------------------------------------- +void Panel::GetPinOffset( int &dx, int &dy ) +{ + dx = m_nPinDeltaX; + dy = m_nPinDeltaY; +} + + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +Panel::AutoResize_e Panel::GetAutoResize() +{ + return (AutoResize_e)_autoResizeDirection; +} + + +//----------------------------------------------------------------------------- +// Gets the relative offset of the control from the pin corner +//----------------------------------------------------------------------------- +void Panel::GetResizeOffset( int &dx, int &dy ) +{ + dx = m_nResizeDeltaX; + dy = m_nResizeDeltaY; +} + +//----------------------------------------------------------------------------- +// Tells this panel that it should pin itself to the corner of a specified sibling panel +//----------------------------------------------------------------------------- +void Panel::PinToSibling( const char *pszSibling, PinCorner_e pinOurCorner, PinCorner_e pinSibling ) +{ + _pinCornerToSibling = pinOurCorner; + _pinToSiblingCorner = pinSibling; + + if ( _pinToSibling && pszSibling && !Q_strcmp( _pinToSibling, pszSibling ) ) + return; + + if (_pinToSibling) + { + delete [] _pinToSibling; + _pinToSibling = NULL; + } + + if (pszSibling) + { + int len = Q_strlen(pszSibling) + 1; + _pinToSibling = new char[ len ]; + Q_strncpy( _pinToSibling, pszSibling, len ); + } + m_pinSibling = NULL; + + UpdateSiblingPin(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::UpdateSiblingPin( void ) +{ + if ( !_pinToSibling ) + { + ipanel()->SetSiblingPin(GetVPanel(), NULL); + return; + } + + if ( !m_pinSibling.Get() ) + { + // Resolve our sibling now + m_pinSibling = FindSiblingByName( _pinToSibling ); + } + + if ( m_pinSibling.Get() ) + { + ipanel()->SetSiblingPin( GetVPanel(), m_pinSibling->GetVPanel(), _pinCornerToSibling, _pinToSiblingCorner ); + } + else + { + ipanel()->SetSiblingPin(GetVPanel(), NULL); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::ApplySchemeSettings(IScheme *pScheme) +{ + // get colors + SetFgColor(GetSchemeColor("Panel.FgColor", pScheme)); + SetBgColor(GetSchemeColor("Panel.BgColor", pScheme)); + +#if defined( VGUI_USEDRAGDROP ) + m_clrDragFrame = pScheme->GetColor("DragDrop.DragFrame", Color(255, 255, 255, 192)); + m_clrDropFrame = pScheme->GetColor("DragDrop.DropFrame", Color(150, 255, 150, 255)); + + m_infoFont = pScheme->GetFont( "DefaultVerySmall" ); +#endif + // mark us as no longer needing scheme settings applied + _flags.ClearFlag( NEEDS_SCHEME_UPDATE ); + + if ( IsBuildGroupEnabled() ) + { + _buildGroup->ApplySchemeSettings(pScheme); + return; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Checks to see if the panel needs it's scheme info setup +//----------------------------------------------------------------------------- +void Panel::PerformApplySchemeSettings() +{ + if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) ) + { + InternalInitDefaultValues( GetAnimMap() ); + } + + if ( _flags.IsFlagSet( NEEDS_SCHEME_UPDATE ) ) + { + VPROF( "ApplySchemeSettings" ); + IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + AssertOnce( pScheme ); + if ( pScheme ) // this should NEVER be null, but if it is bad things would happen in ApplySchemeSettings... + { + ApplySchemeSettings( pScheme ); + //_needsSchemeUpdate = false; + + ApplyOverridableColors(); + + UpdateSiblingPin(); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Loads panel details related to autoresize from the resource info +//----------------------------------------------------------------------------- +#if defined( _DEBUG ) +static Panel *lastWarningParent = 0; +#endif + +void Panel::ApplyAutoResizeSettings(KeyValues *inResourceData) +{ + int x, y; + GetPos(x, y); + + int wide, tall; + GetSize( wide, tall ); + + AutoResize_e autoResize = (AutoResize_e)inResourceData->GetInt( "AutoResize", AUTORESIZE_NO ); + PinCorner_e pinCorner = (PinCorner_e)inResourceData->GetInt( "PinCorner", PIN_TOPLEFT ); + + // By default, measure unpinned corner for the offset + int pw = wide, pt = tall; + if ( GetParent() ) + { + GetParent()->GetSize( pw, pt ); +#if defined( _DEBUG ) + if ( pw == 64 && pt == 24 ) + { + if ( GetParent() != lastWarningParent ) + { + lastWarningParent = GetParent(); + Warning( "Resize parent (panel(%s) -> parent(%s)) not sized yet!!!\n", GetName(), GetParent()->GetName() ); + } + } +#endif + } + + int nPinnedCornerOffsetX = 0, nPinnedCornerOffsetY = 0; + int nUnpinnedCornerOffsetX = 0, nUnpinnedCornerOffsetY = 0; + switch( pinCorner ) + { + case PIN_TOPLEFT: + nPinnedCornerOffsetX = x; + nPinnedCornerOffsetY = y; + nUnpinnedCornerOffsetX = (x + wide) - pw; + nUnpinnedCornerOffsetY = (y + tall) - pt; + break; + + case PIN_TOPRIGHT: + nPinnedCornerOffsetX = (x + wide) - pw; + nPinnedCornerOffsetY = y; + nUnpinnedCornerOffsetX = x; + nUnpinnedCornerOffsetY = (y + tall) - pt; + break; + + case PIN_BOTTOMLEFT: + nPinnedCornerOffsetX = x; + nPinnedCornerOffsetY = (y + tall) - pt; + nUnpinnedCornerOffsetX = (x + wide) - pw; + nUnpinnedCornerOffsetY = y; + break; + + case PIN_BOTTOMRIGHT: + nPinnedCornerOffsetX = (x + wide) - pw; + nPinnedCornerOffsetY = (y + tall) - pt; + nUnpinnedCornerOffsetX = x; + nUnpinnedCornerOffsetY = y; + break; + } + + // Allow specific overrides in the resource file + if ( IsProportional() ) + { + if ( inResourceData->FindKey( "PinnedCornerOffsetX" ) ) + { + nPinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetX" ) ); + } + if ( inResourceData->FindKey( "PinnedCornerOffsetY" ) ) + { + nPinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetY" ) ); + } + if ( inResourceData->FindKey( "UnpinnedCornerOffsetX" ) ) + { + nUnpinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetX" ) ); + } + if ( inResourceData->FindKey( "UnpinnedCornerOffsetY" ) ) + { + nUnpinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetY" ) ); + } + } + else + { + nPinnedCornerOffsetX = inResourceData->GetInt( "PinnedCornerOffsetX", nPinnedCornerOffsetX ); + nPinnedCornerOffsetY = inResourceData->GetInt( "PinnedCornerOffsetY", nPinnedCornerOffsetY ); + nUnpinnedCornerOffsetX = inResourceData->GetInt( "UnpinnedCornerOffsetX", nUnpinnedCornerOffsetX ); + nUnpinnedCornerOffsetY = inResourceData->GetInt( "UnpinnedCornerOffsetY", nUnpinnedCornerOffsetY ); + } + + if ( autoResize == AUTORESIZE_NO ) + { + nUnpinnedCornerOffsetX = nUnpinnedCornerOffsetY = 0; + } + + SetAutoResize( pinCorner, autoResize, nPinnedCornerOffsetX, nPinnedCornerOffsetY, nUnpinnedCornerOffsetX, nUnpinnedCornerOffsetY ); +} + +ConVar panel_test_title_safe( "panel_test_title_safe", "0", FCVAR_CHEAT, "Test vgui panel positioning with title safe indentation" ); + + + +//----------------------------------------------------------------------------- +// Purpose: Loads panel details from the resource info +//----------------------------------------------------------------------------- +void Panel::ApplySettings(KeyValues *inResourceData) +{ + // First restore to default values + if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) ) + { + InternalInitDefaultValues( GetAnimMap() ); + } + + // Let PanelAnimationVars auto-retrieve settings (we restore defaults above + // since a script might be missing certain values) + InternalApplySettings( GetAnimMap(), inResourceData ); + + // clear any alignment flags + _buildModeFlags &= ~(BUILDMODE_SAVE_XPOS_RIGHTALIGNED | BUILDMODE_SAVE_XPOS_CENTERALIGNED | BUILDMODE_SAVE_YPOS_BOTTOMALIGNED | BUILDMODE_SAVE_YPOS_CENTERALIGNED | BUILDMODE_SAVE_WIDE_FULL | BUILDMODE_SAVE_TALL_FULL | BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT); + + // get the position + int alignScreenWide, alignScreenTall; // screen dimensions used for pinning in splitscreen + surface()->GetScreenSize( alignScreenWide, alignScreenTall ); + + int screenWide = alignScreenWide; + int screenTall = alignScreenTall; + + // temporarily remove the override to get the fullscreen dimensions + if ( surface()->IsScreenSizeOverrideActive() ) + { + surface()->ForceScreenSizeOverride( false, 0, 0 ); + surface()->GetScreenSize( screenWide, screenTall ); + + // restore the override + surface()->ForceScreenSizeOverride( true, alignScreenWide, alignScreenTall ); + } + + int parentX = 0; + int parentY = 0; + + // flag to cause windows to get screenWide and screenTall from their parents, + // this allows children windows to use fill and right/bottom alignment even + // if their parent does not use the full screen. + if ( inResourceData->GetInt( "proportionalToParent", 0 ) == 1 ) + { + _buildModeFlags |= BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT; + if ( GetParent() != NULL ) + { + GetParent()->GetBounds( parentX, parentY, alignScreenWide, alignScreenTall ); + } + } + + int x, y; + GetPos(x, y); + const char *xstr = inResourceData->GetString( "xpos", NULL ); + const char *ystr = inResourceData->GetString( "ypos", NULL ); + + if (xstr) + { + // look for alignment flags + if (xstr[0] == 'r' || xstr[0] == 'R') + { + _buildModeFlags |= BUILDMODE_SAVE_XPOS_RIGHTALIGNED; + xstr++; + } + else if (xstr[0] == 'c' || xstr[0] == 'C') + { + _buildModeFlags |= BUILDMODE_SAVE_XPOS_CENTERALIGNED; + xstr++; + } + + // get the value + x = atoi(xstr); + // scale the x up to our screen co-ords + if ( IsProportional() ) + { + x = scheme()->GetProportionalScaledValueEx(GetScheme(), x); + } + // now correct the alignment + if (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED) + { + x = alignScreenWide - x; + } + else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED) + { + x = (alignScreenWide / 2) + x; + } + } + + if (ystr) + { + // look for alignment flags + if (ystr[0] == 'r' || ystr[0] == 'R') + { + _buildModeFlags |= BUILDMODE_SAVE_YPOS_BOTTOMALIGNED; + ystr++; + } + else if (ystr[0] == 'c' || ystr[0] == 'C') + { + _buildModeFlags |= BUILDMODE_SAVE_YPOS_CENTERALIGNED; + ystr++; + } + y = atoi(ystr); + if (IsProportional()) + { + // scale the y up to our screen co-ords + y = scheme()->GetProportionalScaledValueEx(GetScheme(), y); + } + // now correct the alignment + if (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED) + { + y = alignScreenTall - y; + } + else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED) + { + y = (alignScreenTall / 2) + y; + } + } + + bool bUsesTitleSafeArea = false; + int titleSafeWide = 0; + int titleSafeTall = 0; + + Rect_t excludeEdgeFromTitleSafe; // if a side is set to != 0, don't title safe relative to that edge + excludeEdgeFromTitleSafe.x = 0; + excludeEdgeFromTitleSafe.y = 0; + excludeEdgeFromTitleSafe.width = 0; + excludeEdgeFromTitleSafe.height = 0; + + if ( IsX360() || panel_test_title_safe.GetBool() ) + { + // "usetitlesafe" "1" - required inner 90% + // "usetitlesafe" "2" - suggested inner 85% + + int iUseTitleSafeValue = 0; + if ( inResourceData->FindKey( "usetitlesafe" ) ) + { + iUseTitleSafeValue = inResourceData->GetInt( "usetitlesafe" ); + bUsesTitleSafeArea = ( iUseTitleSafeValue > 0 ); + } + + if( bUsesTitleSafeArea ) + { + titleSafeWide = screenWide * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f ); + titleSafeTall = screenTall * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f ); + + // Don't title safe internal boundaries for split screen viewports + int splitX = 0; + int splitY = 0; + vgui::surface()->OffsetAbsPos( splitX, splitY ); + + bool bHorizontalSplit = ( alignScreenTall != screenTall ); + bool bVerticalSplit = ( alignScreenWide != screenWide ); + + if ( bHorizontalSplit ) + { + // top or bottom? + if ( splitY != parentY ) + { + excludeEdgeFromTitleSafe.y = 1; + } + else + { + excludeEdgeFromTitleSafe.height = 1; + } + } + + if ( bVerticalSplit ) + { + // left or right + if ( splitX != parentX ) + { + excludeEdgeFromTitleSafe.x = 1; + } + else + { + excludeEdgeFromTitleSafe.width = 1; + } + } + + if ( _buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED ) + { + if ( !excludeEdgeFromTitleSafe.width ) + { + x -= titleSafeWide; // right edge + } + } + else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED) + { + } + else if ( !excludeEdgeFromTitleSafe.x ) + { + x += titleSafeWide; // left edge + } + + if ( _buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED ) + { + if ( !excludeEdgeFromTitleSafe.height ) + { + y -= titleSafeTall; // bottom edge + } + } + else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED) + { + } + else if ( !excludeEdgeFromTitleSafe.y ) + { + y += titleSafeTall; // top edge + } + } + } + SetNavUp( inResourceData->GetString("navUp") ); + SetNavDown( inResourceData->GetString("navDown") ); + SetNavLeft( inResourceData->GetString("navLeft") ); + SetNavRight( inResourceData->GetString("navRight") ); + SetNavToRelay( inResourceData->GetString("navToRelay") ); + SetNavActivate( inResourceData->GetString("navActivate") ); + SetNavBack( inResourceData->GetString("navBack") ); + + SetPos(x, y); + + if (inResourceData->FindKey( "zpos" )) + { + SetZPos( inResourceData->GetInt( "zpos" ) ); + } + + // size + int wide, tall; + GetSize( wide, tall ); + + const char *wstr = inResourceData->GetString( "wide", NULL ); + if ( wstr ) + { + if (wstr[0] == 'f' || wstr[0] == 'F') + { + _buildModeFlags |= BUILDMODE_SAVE_WIDE_FULL; + wstr++; + } + wide = atoi(wstr); + if ( IsProportional() ) + { + // scale the width up to our screen co-ords + wide = scheme()->GetProportionalScaledValueEx(GetScheme(), wide); + } + // now correct the alignment + if (_buildModeFlags & BUILDMODE_SAVE_WIDE_FULL) + { + wide = alignScreenWide - wide; + } + } + + // allow tall to be use the "fill" option, set to the height of the parent/screen + wstr = inResourceData->GetString( "tall", NULL ); + if ( wstr ) + { + if (wstr[0] == 'f' || wstr[0] == 'F') + { + _buildModeFlags |= BUILDMODE_SAVE_TALL_FULL; + wstr++; + } + tall = atoi(wstr); + if ( IsProportional() ) + { + // scale the height up to our screen co-ords + tall = scheme()->GetProportionalScaledValueEx(GetScheme(), tall); + } + // now correct the alignment + if (_buildModeFlags & BUILDMODE_SAVE_TALL_FULL) + { + tall = alignScreenTall - tall; + } + } + + if( bUsesTitleSafeArea ) + { + if ( _buildModeFlags & BUILDMODE_SAVE_WIDE_FULL ) + { + if ( !excludeEdgeFromTitleSafe.x ) + wide -= titleSafeWide; + + if ( !excludeEdgeFromTitleSafe.width ) + wide -= titleSafeWide; + } + + if ( _buildModeFlags & BUILDMODE_SAVE_TALL_FULL ) + { + if ( !excludeEdgeFromTitleSafe.y ) + tall -= titleSafeTall; + + if ( !excludeEdgeFromTitleSafe.height ) + tall -= titleSafeTall; + } + } + + SetSize( wide, tall ); + + // NOTE: This has to happen after pos + size is set + ApplyAutoResizeSettings( inResourceData ); + + // only get colors if we're ignoring the scheme + if (inResourceData->GetInt("IgnoreScheme", 0)) + { + PerformApplySchemeSettings(); + } + + // state + int state = inResourceData->GetInt("visible", 1); + if (state == 0) + { + SetVisible(false); + } + else if (state == 1) + { + SetVisible(true); + } + + SetEnabled( inResourceData->GetInt("enabled", true) ); + + bool bMouseEnabled = inResourceData->GetInt( "mouseinputenabled", true ); + if ( !bMouseEnabled ) + { + SetMouseInputEnabled( false ); + } + + // tab order + SetTabPosition(inResourceData->GetInt("tabPosition", 0)); + + const char *tooltip = inResourceData->GetString("tooltiptext", NULL); + if (tooltip && *tooltip) + { + GetTooltip()->SetText(tooltip); + } + + // paint background? + int nPaintBackground = inResourceData->GetInt("paintbackground", -1); + if (nPaintBackground >= 0) + { + SetPaintBackgroundEnabled( nPaintBackground != 0 ); + } + + // paint border? + int nPaintBorder = inResourceData->GetInt("paintborder", -1); + if (nPaintBorder >= 0) + { + SetPaintBorderEnabled( nPaintBorder != 0 ); + } + + // border? + const char *pBorder = inResourceData->GetString( "border", "" ); + if ( *pBorder ) + { + IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + SetBorder( pScheme->GetBorder( pBorder ) ); + } + + // check to see if we have a new name assigned + const char *newName = inResourceData->GetString("fieldName", NULL); + if ( newName ) + { + // Only slam the name if the new one differs... + SetName(newName); + } + + // check to see if we need to render to the frame buffer even if + // stereo mode is trying to render all of the ui to a render target + m_bForceStereoRenderToFrameBuffer = inResourceData->GetBool( "ForceStereoRenderToFrameBuffer", false ); + + //============================================================================= + // HPE_BEGIN: + // [pfreese] Support for reading rounded corner flags + //============================================================================= + int roundedCorners = inResourceData->GetInt( "RoundedCorners", -1 ); + if ( roundedCorners >= 0 ) + { + m_roundedCorners = roundedCorners; + } + //============================================================================= + // HPE_END + //============================================================================= + + const char *pszSiblingName = inResourceData->GetString("pin_to_sibling", NULL); + PinCorner_e pinOurCornerToSibling = (PinCorner_e)inResourceData->GetInt( "pin_corner_to_sibling", PIN_TOPLEFT ); + PinCorner_e pinSiblingCorner = (PinCorner_e)inResourceData->GetInt( "pin_to_sibling_corner", PIN_TOPLEFT ); + PinToSibling( pszSiblingName, pinOurCornerToSibling, pinSiblingCorner ); + + + // Allow overriding of colors. Used mostly by HUD elements, where scheme color usage is often undesired. + IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); + for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) + { + // Need to ensure the key exists, so we don't overwrite existing colors when it's not set. + if ( inResourceData->FindKey( m_OverridableColorEntries[i].m_pszScriptName, false ) ) + { + // Get the color as a string - test whether it is an actual color or a reference to a scheme color + const char *pColorStr = inResourceData->GetString( m_OverridableColorEntries[i].m_pszScriptName ); + Color &clrDest = m_OverridableColorEntries[i].m_colFromScript; + if ( pColorStr[0] == '.' || isdigit( pColorStr[0] ) ) + { + float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f; + sscanf( pColorStr, "%f %f %f %f", &r, &g, &b, &a ); + clrDest[0] = (unsigned char)r; + clrDest[1] = (unsigned char)g; + clrDest[2] = (unsigned char)b; + clrDest[3] = (unsigned char)a; + } + else + { + // First character wasn't a digit or a decimal - do a scheme color lookup + clrDest = pScheme->GetColor( pColorStr, Color( 255, 255, 255, 255 ) ); + } + + (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript; + m_OverridableColorEntries[i].m_bOverridden = true; + } + } + + const char *pKeyboardInputEnabled = inResourceData->GetString( "keyboardinputenabled", NULL ); + if ( pKeyboardInputEnabled && pKeyboardInputEnabled[0] ) + { + SetKeyBoardInputEnabled( atoi( pKeyboardInputEnabled ) ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Saves out a resource description of this panel +//----------------------------------------------------------------------------- +void Panel::GetSettings( KeyValues *outResourceData ) +{ + // control class name (so it can be recreated later if needed) + outResourceData->SetString( "ControlName", GetClassName() ); + + // name + outResourceData->SetString( "fieldName", _panelName ); + + // positioning + int screenWide, screenTall; + surface()->GetScreenSize(screenWide, screenTall); + int x, y; + GetPos( x, y ); + if ( IsProportional() ) + { + x = scheme()->GetProportionalNormalizedValueEx( GetScheme(), x ); + y = scheme()->GetProportionalNormalizedValueEx( GetScheme(), y ); + } + // correct for alignment + if (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED) + { + x = screenWide - x; + char xstr[32]; + Q_snprintf(xstr, sizeof( xstr ), "r%d", x); + outResourceData->SetString( "xpos", xstr ); + } + else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED) + { + x = (screenWide / 2) + x; + char xstr[32]; + Q_snprintf(xstr, sizeof( xstr ), "c%d", x); + outResourceData->SetString( "xpos", xstr ); + } + else + { + outResourceData->SetInt( "xpos", x ); + } + if (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED) + { + y = screenTall - y; + char ystr[32]; + Q_snprintf(ystr, sizeof( ystr ), "r%d", y); + outResourceData->SetString( "ypos", ystr ); + } + else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED) + { + y = (screenTall / 2) + y; + char ystr[32]; + Q_snprintf(ystr, sizeof( ystr ), "c%d", y); + outResourceData->SetString( "ypos", ystr ); + } + else + { + outResourceData->SetInt( "ypos", y ); + } + if (m_pTooltips) + { + if (strlen(m_pTooltips->GetText()) > 0) + { + outResourceData->SetString("tooltiptext", m_pTooltips->GetText()); + } + } + int wide, tall; + GetSize( wide, tall ); + if ( IsProportional() ) + { + wide = scheme()->GetProportionalNormalizedValueEx( GetScheme(), wide ); + tall = scheme()->GetProportionalNormalizedValueEx( GetScheme(), tall ); + } + + int z = ipanel()->GetZPos(GetVPanel()); + if (z) + { + outResourceData->SetInt("zpos", z); + } + + // Correct for alignment + if (_buildModeFlags & BUILDMODE_SAVE_WIDE_FULL ) + { + wide = screenWide - wide; + char wstr[32]; + Q_snprintf(wstr, sizeof( wstr ), "f%d", wide); + outResourceData->SetString( "wide", wstr ); + } + else + { + outResourceData->SetInt( "wide", wide ); + } + outResourceData->SetInt( "tall", tall ); + + outResourceData->SetInt("AutoResize", GetAutoResize()); + outResourceData->SetInt("PinCorner", GetPinCorner()); + + //============================================================================= + // HPE_BEGIN: + // [pfreese] Support for writing out rounded corner flags + //============================================================================= + outResourceData->SetInt("RoundedCorners", m_roundedCorners); + //============================================================================= + // HPE_END + //============================================================================= + + outResourceData->SetString( "pin_to_sibling", _pinToSibling ); + outResourceData->SetInt("pin_corner_to_sibling", _pinCornerToSibling ); + outResourceData->SetInt("pin_to_sibling_corner", _pinToSiblingCorner ); + + + // state + outResourceData->SetInt( "visible", IsVisible() ); + outResourceData->SetInt( "enabled", IsEnabled() ); + + outResourceData->SetInt( "tabPosition", GetTabPosition() ); + + for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) + { + if ( m_OverridableColorEntries[i].m_bOverridden ) + { + outResourceData->SetColor( m_OverridableColorEntries[i].m_pszScriptName, m_OverridableColorEntries[i].m_colFromScript ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: After applying settings, apply overridable colors. +// Done post apply settings, so that baseclass settings don't stomp +// the script specified override colors. +//----------------------------------------------------------------------------- +void Panel::ApplyOverridableColors( void ) +{ + for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) + { + if ( m_OverridableColorEntries[i].m_bOverridden ) + { + (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetOverridableColor( Color *pColor, const Color &newColor ) +{ + for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ ) + { + if ( m_OverridableColorEntries[i].m_bOverridden ) + { + if ( m_OverridableColorEntries[i].m_pColor == pColor ) + return; + } + } + + // Didn't find it, or it's not been overridden. + *pColor = newColor; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Color Panel::GetSchemeColor(const char *keyName, IScheme *pScheme) +{ + return pScheme->GetColor(keyName, Color(255, 255, 255, 255)); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Color Panel::GetSchemeColor(const char *keyName, Color defaultColor, IScheme *pScheme) +{ + return pScheme->GetColor(keyName, defaultColor); +} + +//----------------------------------------------------------------------------- +// Purpose: Returns a string description of the panel fields for use in the UI +//----------------------------------------------------------------------------- +const char *Panel::GetDescription( void ) +{ + static const char *panelDescription = "string fieldName, int xpos, int ypos, int wide, int tall, bool visible, bool enabled, int tabPosition, corner pinCorner, autoresize autoResize, string tooltiptext"; + return panelDescription; +} + +//----------------------------------------------------------------------------- +// Purpose: user configuration settings +// this is used for any control details the user wants saved between sessions +// eg. dialog positions, last directory opened, list column width +//----------------------------------------------------------------------------- +void Panel::ApplyUserConfigSettings(KeyValues *userConfig) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: returns user config settings for this control +//----------------------------------------------------------------------------- +void Panel::GetUserConfigSettings(KeyValues *userConfig) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: optimization, return true if this control has any user config settings +//----------------------------------------------------------------------------- +bool Panel::HasUserConfigSettings() +{ + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::InternalInvalidateLayout() +{ + InvalidateLayout(false, false); +} + +//----------------------------------------------------------------------------- +// Purpose: called whenever the panel moves +//----------------------------------------------------------------------------- +void Panel::OnMove() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::InternalMove() +{ + OnMove(); + for(int i=0;iOnMove(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: empty function +//----------------------------------------------------------------------------- +void Panel::OnTick() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: versioning +//----------------------------------------------------------------------------- +void *Panel::QueryInterface(EInterfaceID id) +{ + if (id == ICLIENTPANEL_STANDARD_INTERFACE) + { + return this; + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: Map all the base messages to functions +// ordering from most -> least used improves speed +//----------------------------------------------------------------------------- +MessageMapItem_t Panel::m_MessageMap[] = +{ + MAP_MESSAGE_INT( Panel, "RequestFocus", RequestFocus, "direction" ) +}; + +// IMPLEMENT_PANELMAP( Panel, NULL ) +PanelMap_t Panel::m_PanelMap = { Panel::m_MessageMap, ARRAYSIZE(Panel::m_MessageMap), "Panel", NULL }; +PanelMap_t *Panel::GetPanelMap( void ) { return &m_PanelMap; } + +//----------------------------------------------------------------------------- +// Purpose: !! Soon to replace existing prepare panel map +//----------------------------------------------------------------------------- +void PreparePanelMessageMap(PanelMessageMap *panelMap) +{ + // iterate through the class hierarchy message maps + while ( panelMap != NULL && !panelMap->processed ) + { + // hash message map strings into symbols + for (int i = 0; i < panelMap->entries.Count(); i++) + { + MessageMapItem_t *item = &panelMap->entries[i]; + + if (item->name) + { + item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name); + } + else + { + item->nameSymbol = INVALID_KEY_SYMBOL; + } + if (item->firstParamName) + { + item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName); + } + else + { + item->firstParamSymbol = INVALID_KEY_SYMBOL; + } + if (item->secondParamName) + { + item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName); + } + else + { + item->secondParamSymbol = INVALID_KEY_SYMBOL; + } + } + + panelMap->processed = true; + panelMap = panelMap->baseMap; + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: Handles a message +// Dispatches the message to a set of message maps +//----------------------------------------------------------------------------- +void Panel::OnMessage(const KeyValues *params, VPANEL ifromPanel) +{ + PanelMessageMap *panelMap = GetMessageMap(); + bool bFound = false; + int iMessageName = params->GetNameSymbol(); + + if ( !panelMap->processed ) + { + PreparePanelMessageMap( panelMap ); + } + + // iterate through the class hierarchy message maps + for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap ) + { +#if defined( _DEBUG ) +// char const *className = panelMap->pfnClassName(); +// NOTE_UNUSED( className ); +#endif + + // iterate all the entries in the panel map + for ( int i = 0; i < panelMap->entries.Count(); i++ ) + { + MessageMapItem_t *pMap = &panelMap->entries[i]; + + if (iMessageName == pMap->nameSymbol) + { + bFound = true; + + switch (pMap->numParams) + { + case 0: + { + (this->*(pMap->func))(); + break; + } + + case 1: + { + KeyValues *param1 = params->FindKey(pMap->firstParamSymbol); + if (!param1) + { + param1 = const_cast(params); + } + + switch ( pMap->firstParamType ) + { + case DATATYPE_INT: + typedef void (Panel::*MessageFunc_Int_t)(int); + (this->*((MessageFunc_Int_t)pMap->func))( param1->GetInt() ); + break; + + case DATATYPE_UINT64: + typedef void (Panel::*MessageFunc_Uin64_t)(uint64); + (this->*((MessageFunc_Uin64_t)pMap->func))( param1->GetUint64() ); + break; + + case DATATYPE_PTR: + typedef void (Panel::*MessageFunc_Ptr_t)( void * ); + (this->*((MessageFunc_Ptr_t)pMap->func))( param1->GetPtr() ); + break; + + case DATATYPE_HANDLE: + { + typedef void (Panel::*MessageFunc_VPANEL_t)( VPANEL ); + VPANEL vpanel = ivgui()->HandleToPanel( param1->GetInt() ); + (this->*((MessageFunc_VPANEL_t)pMap->func))( vpanel ); + } + break; + + case DATATYPE_FLOAT: + typedef void (Panel::*MessageFunc_Float_t)( float ); + (this->*((MessageFunc_Float_t)pMap->func))( param1->GetFloat() ); + break; + + case DATATYPE_CONSTCHARPTR: + typedef void (Panel::*MessageFunc_CharPtr_t)( const char * ); + (this->*((MessageFunc_CharPtr_t)pMap->func))( param1->GetString() ); + break; + + case DATATYPE_CONSTWCHARPTR: + typedef void (Panel::*MessageFunc_WCharPtr_t)( const wchar_t * ); + (this->*((MessageFunc_WCharPtr_t)pMap->func))( param1->GetWString() ); + break; + + case DATATYPE_KEYVALUES: + typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *); + if ( pMap->firstParamName ) + { + (this->*((MessageFunc_KeyValues_t)pMap->func))( (KeyValues *)param1->GetPtr() ); + } + else + { + // no param set, so pass in the whole thing + (this->*((MessageFunc_KeyValues_t)pMap->func))( const_cast(params) ); + } + break; + + default: + Assert(!("No handler for vgui message function")); + break; + } + break; + } + + case 2: + { + KeyValues *param1 = params->FindKey(pMap->firstParamSymbol); + if (!param1) + { + param1 = const_cast(params); + } + KeyValues *param2 = params->FindKey(pMap->secondParamSymbol); + if (!param2) + { + param2 = const_cast(params); + } + + if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_IntInt_t)(int, int); + (this->*((MessageFunc_IntInt_t)pMap->func))( param1->GetInt(), param2->GetInt() ); + } + else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int); + (this->*((MessageFunc_PtrInt_t)pMap->func))( param1->GetPtr(), param2->GetInt() ); + } + else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int); + (this->*((MessageFunc_ConstCharPtrInt_t)pMap->func))( param1->GetString(), param2->GetInt() ); + } + else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *); + (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMap->func))( param1->GetString(), param2->GetString() ); + } + else if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *); + (this->*((MessageFunc_IntConstCharPtr_t)pMap->func))( param1->GetInt(), param2->GetString() ); + } + else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *); + (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetString() ); + } + else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *); + (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetWString() ); + } + else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *); + VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() ); + (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetString() ); + } + else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) ) + { + typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *); + VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() ); + (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetWString() ); + } + else + { + // the message isn't handled + ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() ); + } + break; + } + + default: + Assert(!("Invalid number of parameters")); + break; + } + + // break the loop + bFound = true; + break; + } + } + } + + if (!bFound) + { + OnOldMessage(const_cast(params), ifromPanel); + } +} + +void Panel::OnOldMessage(KeyValues *params, VPANEL ifromPanel) +{ + bool bFound = false; + // message map dispatch + int iMessageName = params->GetNameSymbol(); + + PanelMap_t *panelMap = GetPanelMap(); + if ( !panelMap->processed ) + { + PreparePanelMap( panelMap ); + } + + // iterate through the class hierarchy message maps + for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap ) + { + MessageMapItem_t *pMessageMap = panelMap->dataDesc; + + for ( int i = 0; i < panelMap->dataNumFields; i++ ) + { + if (iMessageName == pMessageMap[i].nameSymbol) + { + // call the mapped function + switch ( pMessageMap[i].numParams ) + { + case 2: + if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_IntInt_t)(int, int); + (this->*((MessageFunc_IntInt_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int); + (this->*((MessageFunc_PtrInt_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int); + (this->*((MessageFunc_ConstCharPtrInt_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *); + (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *); + (this->*((MessageFunc_IntConstCharPtr_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *); + (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *); + (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetWString(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR ==pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *); + VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) ); + (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetString(pMessageMap[i].secondParamName) ); + } + else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) ) + { + typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *); + VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) ); + (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetWString(pMessageMap[i].secondParamName) ); + } + else + { + // the message isn't handled + ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() ); + } + break; + + case 1: + switch ( pMessageMap[i].firstParamType ) + { + case DATATYPE_BOOL: + typedef void (Panel::*MessageFunc_Bool_t)(bool); + (this->*((MessageFunc_Bool_t)pMessageMap[i].func))( (bool)params->GetInt(pMessageMap[i].firstParamName) ); + break; + + case DATATYPE_CONSTCHARPTR: + typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *); + (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetString(pMessageMap[i].firstParamName) ); + break; + + case DATATYPE_CONSTWCHARPTR: + typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *); + (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetWString(pMessageMap[i].firstParamName) ); + break; + + case DATATYPE_INT: + typedef void (Panel::*MessageFunc_Int_t)(int); + (this->*((MessageFunc_Int_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName) ); + break; + + case DATATYPE_FLOAT: + typedef void (Panel::*MessageFunc_Float_t)(float); + (this->*((MessageFunc_Float_t)pMessageMap[i].func))( params->GetFloat(pMessageMap[i].firstParamName) ); + break; + + case DATATYPE_PTR: + typedef void (Panel::*MessageFunc_Ptr_t)(void *); + (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)params->GetPtr(pMessageMap[i].firstParamName) ); + break; + + case DATATYPE_HANDLE: + { + typedef void (Panel::*MessageFunc_Ptr_t)(void *); + VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) ); + Panel *panel = ipanel()->GetPanel( vp, GetModuleName() ); + (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)panel ); + } + break; + + case DATATYPE_KEYVALUES: + typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *); + if ( pMessageMap[i].firstParamName ) + { + (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( (KeyValues *)params->GetPtr(pMessageMap[i].firstParamName) ); + } + else + { + (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( params ); + } + break; + + default: + // the message isn't handled + ivgui()->DPrintf( "Message '%s', sent to '%s', has an invalid parameter type\n", params->GetName(), GetName() ); + break; + } + + break; + + default: + (this->*(pMessageMap[i].func))(); + break; + }; + + // break the loop + bFound = true; + break; + } + } + } + + // message not handled + // debug code + if ( !bFound ) + { + static int s_bDebugMessages = -1; + if ( s_bDebugMessages == -1 ) + { + s_bDebugMessages = CommandLine()->FindParm( "-vguimessages" ) ? 1 : 0; + } + if ( s_bDebugMessages == 1 ) + { + ivgui()->DPrintf( "Message '%s' not handled by panel '%s'\n", params->GetName(), GetName() ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Safe call to get info from child panel by name +//----------------------------------------------------------------------------- +bool Panel::RequestInfoFromChild(const char *childName, KeyValues *outputData) +{ + Panel *panel = FindChildByName(childName); + if (panel) + { + return panel->RequestInfo(outputData); + } + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Posts a message +//----------------------------------------------------------------------------- +void Panel::PostMessage(Panel *target, KeyValues *message, float delay) +{ + ivgui()->PostMessage(target->GetVPanel(), message, GetVPanel(), delay); +} + +void Panel::PostMessage(VPANEL target, KeyValues *message, float delaySeconds) +{ + ivgui()->PostMessage(target, message, GetVPanel(), delaySeconds); +} + +void Panel::PostMessageToAllSiblings( KeyValues *msg, float delaySeconds /*= 0.0f*/ ) +{ + VPANEL parent = GetVParent(); + if ( parent ) + { + VPANEL vpanel = GetVPanel(); + + CUtlVector< VPANEL > &children = ipanel()->GetChildren( parent ); + int nChildCount = children.Count(); + for ( int i = 0; i < nChildCount; ++i ) + { + VPANEL sibling = children[ i ]; + if ( sibling == vpanel ) + continue; + + if ( sibling ) + { + PostMessage( sibling, msg->MakeCopy(), delaySeconds ); + } + } + } + + msg->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: Safe call to post a message to a child by name +//----------------------------------------------------------------------------- +void Panel::PostMessageToChild(const char *childName, KeyValues *message) +{ + Panel *panel = FindChildByName(childName); + if (panel) + { + ivgui()->PostMessage(panel->GetVPanel(), message, GetVPanel()); + } + else + { + message->deleteThis(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Requests some information from the panel +// Look through the message map for the handler +//----------------------------------------------------------------------------- +bool Panel::RequestInfo( KeyValues *outputData ) +{ + if ( InternalRequestInfo( GetAnimMap(), outputData ) ) + { + return true; + } + + if (GetVParent()) + { + return ipanel()->RequestInfo(GetVParent(), outputData); + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: sets a specified value in the control - inverse of RequestInfo +//----------------------------------------------------------------------------- +bool Panel::SetInfo(KeyValues *inputData) +{ + if ( InternalSetInfo( GetAnimMap(), inputData ) ) + { + return true; + } + + // doesn't chain to parent + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: change the panel's silent mode; if silent, the panel will not post +// any action signals +//----------------------------------------------------------------------------- + +void Panel::SetSilentMode( bool bSilent ) +{ + m_bIsSilent = bSilent; +} + +//----------------------------------------------------------------------------- +// Purpose: mouse events will be send to handler panel instead of this panel +//----------------------------------------------------------------------------- +void Panel::InstallMouseHandler( Panel *pHandler ) +{ + m_hMouseEventHandler = pHandler; +} + +//----------------------------------------------------------------------------- +// Purpose: Prepares the hierarchy panel maps for use (with message maps etc) +//----------------------------------------------------------------------------- +void Panel::PreparePanelMap( PanelMap_t *panelMap ) +{ + // iterate through the class hierarchy message maps + while ( panelMap != NULL && !panelMap->processed ) + { + // fixup cross-dll boundary panel maps + if ( panelMap->baseMap == (PanelMap_t*)0x00000001 ) + { + panelMap->baseMap = &Panel::m_PanelMap; + } + + // hash message map strings into symbols + for (int i = 0; i < panelMap->dataNumFields; i++) + { + MessageMapItem_t *item = &panelMap->dataDesc[i]; + + if (item->name) + { + item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name); + } + else + { + item->nameSymbol = INVALID_KEY_SYMBOL; + } + if (item->firstParamName) + { + item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName); + } + else + { + item->firstParamSymbol = INVALID_KEY_SYMBOL; + } + if (item->secondParamName) + { + item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName); + } + else + { + item->secondParamSymbol = INVALID_KEY_SYMBOL; + } + } + + panelMap->processed = true; + panelMap = panelMap->baseMap; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Called to delete the panel +//----------------------------------------------------------------------------- +void Panel::OnDelete() +{ +#ifdef WIN32 + Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) ); +#endif + delete this; +#ifdef WIN32 + Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Panel handle implementation +// Returns a pointer to a valid panel, NULL if the panel has been deleted +//----------------------------------------------------------------------------- +Panel *PHandle::Get() +{ + if (m_iPanelID != INVALID_PANEL) + { + VPANEL panel = ivgui()->HandleToPanel(m_iPanelID); + if (panel) + { + Panel *vguiPanel = ipanel()->GetPanel(panel, GetControlsModuleName()); + return vguiPanel; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: sets the smart pointer +//----------------------------------------------------------------------------- +Panel *PHandle::Set(Panel *pent) +{ + if (pent) + { + m_iPanelID = ivgui()->PanelToHandle(pent->GetVPanel()); + } + else + { + m_iPanelID = INVALID_PANEL; + } + return pent; +} + +Panel *PHandle::Set( HPanel hPanel ) +{ + m_iPanelID = hPanel; + return Get(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns a handle to a valid panel, NULL if the panel has been deleted +//----------------------------------------------------------------------------- +VPANEL VPanelHandle::Get() +{ + if (m_iPanelID != INVALID_PANEL) + { + if (ivgui()) + { + return ivgui()->HandleToPanel(m_iPanelID); + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: sets the smart pointer +//----------------------------------------------------------------------------- +VPANEL VPanelHandle::Set(VPANEL pent) +{ + if (pent) + { + m_iPanelID = ivgui()->PanelToHandle(pent); + } + else + { + m_iPanelID = INVALID_PANEL; + } + return pent; +} + +//----------------------------------------------------------------------------- +// Purpose: returns a pointer to the tooltip object associated with the panel +//----------------------------------------------------------------------------- +BaseTooltip *Panel::GetTooltip() +{ + if (!m_pTooltips) + { + m_pTooltips = new TextTooltip(this, NULL); + m_bToolTipOverridden = false; + + if ( IsConsoleStylePanel() ) + { + m_pTooltips->SetEnabled( false ); + } + } + + return m_pTooltips; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetTooltip( BaseTooltip *pToolTip, const char *pszText ) +{ + if ( !m_bToolTipOverridden ) + { + // Remove the one we made, we're being overridden. + delete m_pTooltips; + } + + m_pTooltips = pToolTip; + m_bToolTipOverridden = true; + + if ( _tooltipText ) + { + delete [] _tooltipText; + _tooltipText = NULL; + } + + if ( pszText ) + { + int len = Q_strlen(pszText) + 1; + _tooltipText = new char[ len ]; + Q_strncpy( _tooltipText, pszText, len ); + } +} + +//----------------------------------------------------------------------------- +const char *Panel::GetEffectiveTooltipText() const +{ + if ( _tooltipText ) + { + return _tooltipText; + } + if ( m_pTooltips ) + { + const char *result = m_pTooltips->GetText(); + if ( result ) + { + return result; + } + } + return ""; +} + +//----------------------------------------------------------------------------- +// Purpose: sets the proportional flag on this panel and all it's children +//----------------------------------------------------------------------------- +void Panel::SetProportional(bool state) +{ + // only do something if the state changes + if( state != _flags.IsFlagSet( IS_PROPORTIONAL ) ) + { + _flags.SetFlag( IS_PROPORTIONAL, state ); + + for(int i=0;iSetProportional( IsProportional() ); + } + } + InvalidateLayout(); +} + + +void Panel::SetKeyBoardInputEnabled( bool state ) +{ + ipanel()->SetKeyBoardInputEnabled( GetVPanel(), state ); + for ( int i = 0; i < GetChildCount(); i++ ) + { + Panel *child = GetChild( i ); + if ( !child ) + { + continue; + } + child->SetKeyBoardInputEnabled( state ); + } + + // If turning off keyboard input enable, then make sure + // this panel is not the current key focus of a parent panel + if ( !state ) + { + Panel *pParent = GetParent(); + if ( pParent ) + { + if ( pParent->GetCurrentKeyFocus() == GetVPanel() ) + { + pParent->RequestFocusNext(); + } + } + } +} + +void Panel::SetMouseInputEnabled( bool state ) +{ + ipanel()->SetMouseInputEnabled( GetVPanel(), state ); + /* for(int i=0;iSetMouseInput(state); + }*/ + vgui::surface()->CalculateMouseVisible(); +} + +bool Panel::IsKeyBoardInputEnabled() +{ + return ipanel()->IsKeyBoardInputEnabled( GetVPanel() ); +} + +bool Panel::IsMouseInputEnabled() +{ + return ipanel()->IsMouseInputEnabled( GetVPanel() ); +} + +class CFloatProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + kv->SetFloat( entry->name(), *(float *)data ); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(float *)data = kv->GetFloat( entry->name() ); + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(float *)data = atof( entry->defaultvalue() ); + } +}; + +class CProportionalFloatProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + float f = *(float *)data; + f = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), f ); + kv->SetFloat( entry->name(), f ); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + float f = kv->GetFloat( entry->name() ); + f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f ); + *(float *)data = f; + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + float f = atof( entry->defaultvalue() ); + f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f ); + *(float *)data = f; + } +}; + +class CIntProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + kv->SetInt( entry->name(), *(int *)data ); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(int *)data = kv->GetInt( entry->name() ); + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(int *)data = atoi( entry->defaultvalue() ); + } +}; + +class CProportionalIntProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + int i = *(int *)data; + i = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), i ); + kv->SetInt( entry->name(), i ); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + int i = kv->GetInt( entry->name() ); + i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i ); + *(int *)data = i; + } + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + int i = atoi( entry->defaultvalue() ); + i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i ); + *(int *)data = i; + } +}; + +class CProportionalIntWithScreenspacePropertyX : public vgui::IPanelAnimationPropertyConverter +{ +public: + int ExtractValue( Panel *panel, const char *pszKey ) + { + int iValue = 0; + bool bRightAlign = false; + bool bCenterAlign = false; + if (pszKey[0] == 'r' || pszKey[0] == 'R') + { + bRightAlign = true; + pszKey++; + } + else if (pszKey[0] == 'c' || pszKey[0] == 'C') + { + bCenterAlign = true; + pszKey++; + } + + // get the value + iValue = atoi(pszKey); + iValue = scheme()->GetProportionalScaledValueEx(panel->GetScheme(), iValue); + + int screenSize = GetScreenSize(); + // now correct the alignment + if ( bRightAlign ) + { + iValue = screenSize - iValue; + } + else if ( bCenterAlign ) + { + iValue = (screenSize / 2) + iValue; + } + + return iValue; + } + + virtual int GetScreenSize( void ) + { + int screenWide, screenTall; + surface()->GetScreenSize(screenWide, screenTall); + return screenWide; + } + + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + // Won't work with this, don't use it. + Assert(0); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(int *)data = ExtractValue( panel, kv->GetString( entry->name() ) ); + } + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(int *)data = ExtractValue( panel, entry->defaultvalue() ); + } +}; + +class CProportionalIntWithScreenspacePropertyY : public CProportionalIntWithScreenspacePropertyX +{ +public: + virtual int GetScreenSize( void ) + { + int screenWide, screenTall; + surface()->GetScreenSize(screenWide, screenTall); + return screenTall; + } +}; + +class CColorProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + kv->SetColor( entry->name(), *(Color *)data ); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); + Assert( scheme ); + if ( scheme ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + + char const *colorName = kv->GetString( entry->name() ); + if ( !colorName || !colorName[0] ) + { + *(Color *)data = kv->GetColor( entry->name() ); + } + else + { + *(Color *)data = scheme->GetColor( colorName, Color( 0, 0, 0, 0 ) ); + } + } + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); + Assert( scheme ); + if ( scheme ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(Color *)data = scheme->GetColor( entry->defaultvalue(), Color( 0, 0, 0, 0 ) ); + } + } +}; + +class CBoolProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + kv->SetInt( entry->name(), *(bool *)data ? 1 : 0 ); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(bool *)data = kv->GetInt( entry->name() ) ? true : false; + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + bool b = false; + if ( !stricmp( entry->defaultvalue(), "true" )|| + atoi( entry->defaultvalue() )!= 0 ) + { + b = true; + } + + *(bool *)data = b; + } +}; + +class CStringProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + kv->SetString( entry->name(), (char *)data ); + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + strcpy( (char *)data, kv->GetString( entry->name() ) ); + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + strcpy( ( char * )data, entry->defaultvalue() ); + } +}; + +class CHFontProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); + Assert( scheme ); + if ( scheme ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + char const *fontName = scheme->GetFontName( *(HFont *)data ); + kv->SetString( entry->name(), fontName ); + } + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); + Assert( scheme ); + if ( scheme ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + char const *fontName = kv->GetString( entry->name() ); + *(HFont *)data = scheme->GetFont( fontName, panel->IsProportional() ); + } + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() ); + Assert( scheme ); + if ( scheme ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + *(HFont *)data = scheme->GetFont( entry->defaultvalue(), panel->IsProportional() ); + } + } +}; + +class CTextureIdProperty : public vgui::IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + int currentId = *(int *)data; + + // lookup texture name for id + char texturename[ 512 ]; + if ( currentId != -1 && + surface()->DrawGetTextureFile( currentId, texturename, sizeof( texturename ) ) ) + { + kv->SetString( entry->name(), texturename ); + } + else + { + kv->SetString( entry->name(), "" ); + } + } + + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + + int currentId = -1; + + char const *texturename = kv->GetString( entry->name() ); + if ( texturename && texturename[ 0 ] ) + { + currentId = surface()->DrawGetTextureId( texturename ); + if ( currentId == -1 ) + { + currentId = surface()->CreateNewTextureID(); + } + surface()->DrawSetTextureFile( currentId, texturename, false, true ); + } + + *(int *)data = currentId; + } + + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) + { + void *data = ( void * )( (*entry->m_pfnLookup)( panel ) ); + + int currentId = -1; + + char const *texturename = entry->defaultvalue(); + if ( texturename && texturename[ 0 ] ) + { + currentId = surface()->DrawGetTextureId( texturename ); + if ( currentId == -1 ) + { + currentId = surface()->CreateNewTextureID(); + } + surface()->DrawSetTextureFile( currentId, texturename, false, true ); + } + + *(int *)data = currentId; + } +}; + +static CFloatProperty floatconverter; +static CProportionalFloatProperty p_floatconverter; +static CIntProperty intconverter; +static CProportionalIntProperty p_intconverter; +static CProportionalIntWithScreenspacePropertyX p_screenspace_intconverter_X; +static CProportionalIntWithScreenspacePropertyY p_screenspace_intconverter_Y; +static CColorProperty colorconverter; +static CBoolProperty boolconverter; +static CStringProperty stringconverter; +static CHFontProperty fontconverter; +static CTextureIdProperty textureidconverter; +//static CProportionalXPosProperty xposconverter; +//static CProportionalYPosProperty yposconverter; + +static CUtlDict< IPanelAnimationPropertyConverter *, int > g_AnimationPropertyConverters; + +static IPanelAnimationPropertyConverter *FindConverter( char const *typeName ) +{ + int lookup = g_AnimationPropertyConverters.Find( typeName ); + if ( lookup == g_AnimationPropertyConverters.InvalidIndex() ) + return NULL; + + IPanelAnimationPropertyConverter *converter = g_AnimationPropertyConverters[ lookup ]; + return converter; +} + +void Panel::AddPropertyConverter( char const *typeName, IPanelAnimationPropertyConverter *converter ) +{ + int lookup = g_AnimationPropertyConverters.Find( typeName ); + if ( lookup != g_AnimationPropertyConverters.InvalidIndex() ) + { + Msg( "Already have converter for type %s, ignoring...\n", typeName ); + return; + } + + g_AnimationPropertyConverters.Insert( typeName, converter ); +} + +//----------------------------------------------------------------------------- +// Purpose: Static method to initialize all needed converters +//----------------------------------------------------------------------------- +void Panel::InitPropertyConverters( void ) +{ + static bool initialized = false; + if ( initialized ) + return; + initialized = true; + + AddPropertyConverter( "float", &floatconverter ); + AddPropertyConverter( "int", &intconverter ); + AddPropertyConverter( "Color", &colorconverter ); + //AddPropertyConverter( "vgui::Color", &colorconverter ); + AddPropertyConverter( "bool", &boolconverter ); + AddPropertyConverter( "char", &stringconverter ); + AddPropertyConverter( "string", &stringconverter ); + AddPropertyConverter( "HFont", &fontconverter ); + AddPropertyConverter( "vgui::HFont", &fontconverter ); + + // This is an aliased type for proportional float + AddPropertyConverter( "proportional_float", &p_floatconverter ); + AddPropertyConverter( "proportional_int", &p_intconverter ); + + AddPropertyConverter( "proportional_xpos", &p_screenspace_intconverter_X ); + AddPropertyConverter( "proportional_ypos", &p_screenspace_intconverter_Y ); + + AddPropertyConverter( "textureid", &textureidconverter ); +} + +bool Panel::InternalRequestInfo( PanelAnimationMap *map, KeyValues *outputData ) +{ + if ( !map ) + return false; + + Assert( outputData ); + + char const *name = outputData->GetName(); + + PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map ); + if ( e ) + { + IPanelAnimationPropertyConverter *converter = FindConverter( e->type() ); + if ( converter ) + { + converter->GetData( this, outputData, e ); + return true; + } + } + + return false; +} + +bool Panel::InternalSetInfo( PanelAnimationMap *map, KeyValues *inputData ) +{ + if ( !map ) + return false; + + Assert( inputData ); + + char const *name = inputData->GetName(); + + PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map ); + if ( e ) + { + IPanelAnimationPropertyConverter *converter = FindConverter( e->type() ); + if ( converter ) + { + converter->SetData( this, inputData, e ); + return true; + } + } + + return false; +} + +PanelAnimationMapEntry *Panel::FindPanelAnimationEntry( char const *scriptname, PanelAnimationMap *map ) +{ + if ( !map ) + return NULL; + + Assert( scriptname ); + + // Look through mapping for entry + int c = map->entries.Count(); + for ( int i = 0; i < c; i++ ) + { + PanelAnimationMapEntry *e = &map->entries[ i ]; + + if ( !stricmp( e->name(), scriptname ) ) + { + return e; + } + } + + // Recurse + if ( map->baseMap ) + { + return FindPanelAnimationEntry( scriptname, map->baseMap ); + } + + return NULL; +} + +// Recursively invoke settings for PanelAnimationVars +void Panel::InternalApplySettings( PanelAnimationMap *map, KeyValues *inResourceData) +{ + // Loop through keys + KeyValues *kv; + + for ( kv = inResourceData->GetFirstSubKey(); kv; kv = kv->GetNextKey() ) + { + char const *varname = kv->GetName(); + + PanelAnimationMapEntry *entry = FindPanelAnimationEntry( varname, GetAnimMap() ); + if ( entry ) + { + // Set value to value from script + IPanelAnimationPropertyConverter *converter = FindConverter( entry->type() ); + if ( converter ) + { + converter->SetData( this, inResourceData, entry ); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: sets the default values of all CPanelAnimationVars +//----------------------------------------------------------------------------- +void Panel::InternalInitDefaultValues( PanelAnimationMap *map ) +{ + _flags.ClearFlag( NEEDS_DEFAULT_SETTINGS_APPLIED ); + + // Look through mapping for entry + int c = map->entries.Count(); + for ( int i = 0; i < c; i++ ) + { + PanelAnimationMapEntry *e = &map->entries[ i ]; + Assert( e ); + IPanelAnimationPropertyConverter *converter = FindConverter( e->type() ); + if ( !converter ) + continue; + + converter->InitFromDefault( this, e ); + } + + if ( map->baseMap ) + { + InternalInitDefaultValues( map->baseMap ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +int Panel::GetPaintBackgroundType() +{ + return m_nPaintBackgroundType; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : w - +// h - +//----------------------------------------------------------------------------- +void Panel::GetCornerTextureSize( int& w, int& h ) +{ + if ( m_nBgTextureId1 == -1 ) + { + w = h = 0; + return; + } + surface()->DrawGetTextureSize(m_nBgTextureId1, w, h); +} + +//----------------------------------------------------------------------------- +// Purpose: draws a selection box +//----------------------------------------------------------------------------- +void Panel::DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, bool hollow /*=false*/ ) +{ + if ( m_nBgTextureId1 == -1 || + m_nBgTextureId2 == -1 || + m_nBgTextureId3 == -1 || + m_nBgTextureId4 == -1 ) + { + return; + } + + color[3] *= normalizedAlpha; + + // work out our bounds + int cornerWide, cornerTall; + GetCornerTextureSize( cornerWide, cornerTall ); + + // draw the background in the areas not occupied by the corners + // draw it in three horizontal strips + surface()->DrawSetColor(color); + surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall); + if ( !hollow ) + { + surface()->DrawFilledRect(x, y + cornerTall, x + wide, y + tall - cornerTall); + } + else + { + surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall); + surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall); + } + surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall); + + // draw the corners + + //============================================================================= + // HPE_BEGIN: + // [tj] We now check each individual corner and decide whether to draw it straight or rounded + //============================================================================= + //TOP-LEFT + if (ShouldDrawTopLeftCornerRounded()) + { + surface()->DrawSetTexture(m_nBgTextureId1); + surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); + } + else + { + surface()->DrawFilledRect(x, y, x + cornerWide, y + cornerTall); + } + + + //TOP-RIGHT + if (ShouldDrawTopRightCornerRounded()) + { + surface()->DrawSetTexture(m_nBgTextureId2); + surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); + } + else + { + surface()->DrawFilledRect(x + wide - cornerWide, y, x + wide, y + cornerTall); + } + + //BOTTOM-LEFT + if (ShouldDrawBottomLeftCornerRounded()) + { + surface()->DrawSetTexture(m_nBgTextureId4); + surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); + } + else + { + surface()->DrawFilledRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); + } + + + //BOTTOM-RIGHT + if (ShouldDrawBottomRightCornerRounded()) + { + surface()->DrawSetTexture(m_nBgTextureId3); + surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); + } + else + { + surface()->DrawFilledRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); + } + //============================================================================= + // HPE_END + //============================================================================= +} + +void Panel::DrawBoxFade(int x, int y, int wide, int tall, Color color, float normalizedAlpha, unsigned int alpha0, unsigned int alpha1, bool bHorizontal, bool hollow /*=false*/ ) +{ + if ( m_nBgTextureId1 == -1 || + m_nBgTextureId2 == -1 || + m_nBgTextureId3 == -1 || + m_nBgTextureId4 == -1 || + surface()->DrawGetAlphaMultiplier() == 0 ) + { + return; + } + + color[3] *= normalizedAlpha; + + // work out our bounds + int cornerWide, cornerTall; + GetCornerTextureSize( cornerWide, cornerTall ); + + if ( !bHorizontal ) + { + // draw the background in the areas not occupied by the corners + // draw it in three horizontal strips + surface()->DrawSetColor(color); + surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + cornerTall, alpha0, alpha0, bHorizontal ); + if ( !hollow ) + { + surface()->DrawFilledRectFade(x, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); + } + else + { + surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); + surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); + } + surface()->DrawFilledRectFade(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall, alpha1, alpha1, bHorizontal); + } + else + { + // draw the background in the areas not occupied by the corners + // draw it in three horizontal strips + surface()->DrawSetColor(color); + surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha0, bHorizontal ); + if ( !hollow ) + { + surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + tall, alpha0, alpha1, bHorizontal); + } + else + { + // FIXME: Hollow horz version not implemented + //surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); + //surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal); + } + surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha1, alpha1, bHorizontal); + } + + float fOldAlpha = color[ 3 ]; + int iAlpha0 = fOldAlpha * ( static_cast( alpha0 ) / 255.0f ); + int iAlpha1 = fOldAlpha * ( static_cast( alpha1 ) / 255.0f ); + + // draw the corners + if ( !bHorizontal ) + { + color[ 3 ] = iAlpha0; + surface()->DrawSetColor( color ); + surface()->DrawSetTexture(m_nBgTextureId1); + surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); + surface()->DrawSetTexture(m_nBgTextureId2); + surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); + + color[ 3 ] = iAlpha1; + surface()->DrawSetColor( color ); + surface()->DrawSetTexture(m_nBgTextureId3); + surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); + surface()->DrawSetTexture(m_nBgTextureId4); + surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); + } + else + { + color[ 3 ] = iAlpha0; + surface()->DrawSetColor( color ); + surface()->DrawSetTexture(m_nBgTextureId1); + surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); + surface()->DrawSetTexture(m_nBgTextureId4); + surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); + + color[ 3 ] = iAlpha1; + surface()->DrawSetColor( color ); + surface()->DrawSetTexture(m_nBgTextureId2); + surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); + surface()->DrawSetTexture(m_nBgTextureId3); + surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : x - +// y - +// wide - +// tall - +// color - +// normalizedAlpha - +//----------------------------------------------------------------------------- +void Panel::DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha ) +{ + DrawBox( x, y, wide, tall, color, normalizedAlpha, true ); +} + +//============================================================================= +// HPE_BEGIN: +// [menglish] Draws a hollow box similar to the already existing draw hollow box function, but takes the indents as params +//============================================================================= + +void Panel::DrawHollowBox( int x, int y, int wide, int tall, Color color, float normalizedAlpha, int cornerWide, int cornerTall ) +{ + if ( m_nBgTextureId1 == -1 || + m_nBgTextureId2 == -1 || + m_nBgTextureId3 == -1 || + m_nBgTextureId4 == -1 ) + { + return; + } + + color[3] *= normalizedAlpha; + + // draw the background in the areas not occupied by the corners + // draw it in three horizontal strips + surface()->DrawSetColor(color); + surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall); + surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall); + surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall); + surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall); + + // draw the corners + surface()->DrawSetTexture(m_nBgTextureId1); + surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall); + surface()->DrawSetTexture(m_nBgTextureId2); + surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall); + surface()->DrawSetTexture(m_nBgTextureId3); + surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall); + surface()->DrawSetTexture(m_nBgTextureId4); + surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall); +} + +//============================================================================= +// HPE_END +//============================================================================= + +//----------------------------------------------------------------------------- +// Purpose: draws a selection box +//----------------------------------------------------------------------------- +void Panel::DrawTexturedBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha ) +{ + if ( m_nBgTextureId1 == -1 ) + return; + + color[3] *= normalizedAlpha; + + surface()->DrawSetColor( color ); + surface()->DrawSetTexture(m_nBgTextureId1); + surface()->DrawTexturedRect(x, y, x + wide, y + tall); +} + +//----------------------------------------------------------------------------- +// Purpose: Marks this panel as draggable (note that children will chain to their parents to see if any parent is draggable) +// Input : enabled - +//----------------------------------------------------------------------------- +void Panel::SetDragEnabled( bool enabled ) +{ +#if defined( VGUI_USEDRAGDROP ) + // If turning it off, quit dragging if mid-drag + if ( !enabled && + m_pDragDrop->m_bDragging ) + { + OnFinishDragging( false, (MouseCode)-1 ); + } + m_pDragDrop->m_bDragEnabled = enabled; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsDragEnabled() const +{ +#if defined( VGUI_USEDRAGDROP ) + return m_pDragDrop->m_bDragEnabled; +#endif + return false; +} + +void Panel::SetShowDragHelper( bool enabled ) +{ +#if defined( VGUI_USEDRAGDROP ) + m_pDragDrop->m_bShowDragHelper = enabled; +#endif +} + +// Use this to prevent chaining up from a parent which can mess with mouse functionality if you don't want to chain up from a child panel to the best +// draggable parent. +void Panel::SetBlockDragChaining( bool block ) +{ +#if defined( VGUI_USEDRAGDROP ) + m_pDragDrop->m_bPreventChaining = block; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsBlockingDragChaining() const +{ +#if defined( VGUI_USEDRAGDROP ) + return m_pDragDrop->m_bPreventChaining; +#endif + return true; +} + + +//----------------------------------------------------------------------------- +// accessors for m_nDragStartTolerance +//----------------------------------------------------------------------------- +int Panel::GetDragStartTolerance() const +{ +#if defined( VGUI_USEDRAGDROP ) + return m_pDragDrop->m_nDragStartTolerance; +#endif + return 0; +} + +void Panel::SetDragSTartTolerance( int nTolerance ) +{ +#if defined( VGUI_USEDRAGDROP ) + m_pDragDrop->m_nDragStartTolerance = nTolerance; +#endif +} + + +//----------------------------------------------------------------------------- +// Purpose: Marks this panel as droppable ( note that children will chain to their parents to see if any parent is droppable) +// Input : enabled - +//----------------------------------------------------------------------------- +void Panel::SetDropEnabled( bool enabled, float flHoverContextTime /* = 0.0f */ ) +{ +#if defined( VGUI_USEDRAGDROP ) + m_pDragDrop->m_bDropEnabled = enabled; + m_pDragDrop->m_flHoverContextTime = flHoverContextTime; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsDropEnabled() const +{ +#if defined( VGUI_USEDRAGDROP ) + return m_pDragDrop->m_bDropEnabled; +#endif + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Chains up to any parent +// 1) marked DropEnabled; and +// 2) willing to accept the drop payload +// Input : - +// Output : Panel +//----------------------------------------------------------------------------- +Panel *Panel::GetDropTarget( CUtlVector< KeyValues * >& msglist ) +{ +#if defined( VGUI_USEDRAGDROP ) + // Found one + if ( m_pDragDrop->m_bDropEnabled && + IsDroppable( msglist ) ) + { + return this; + } + + // Chain up + if ( GetParent() ) + { + return GetParent()->GetDropTarget( msglist ); + } +#endif + // No luck + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Chains up to first parent marked DragEnabled +// Input : - +// Output : Panel +//----------------------------------------------------------------------------- +Panel *Panel::GetDragPanel() +{ +#if defined( VGUI_USEDRAGDROP ) + // If we encounter a blocker, stop chaining + if ( m_pDragDrop->m_bPreventChaining ) + return NULL; + + if ( m_pDragDrop->m_bDragEnabled ) + return this; + + // Chain up + if ( GetParent() ) + { + return GetParent()->GetDragPanel(); + } +#endif + // No luck + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void Panel::OnStartDragging() +{ +#if defined( VGUI_USEDRAGDROP ) + // Only left mouse initiates drag/drop. + // FIXME: Revisit? + if ( !input()->IsMouseDown( MOUSE_LEFT ) ) + return; + + if ( !m_pDragDrop->m_bDragEnabled ) + return; + + if ( m_pDragDrop->m_bDragging ) + return; + + g_DragDropCapture = this; + + m_pDragDrop->m_bDragStarted = false; + m_pDragDrop->m_bDragging = true; + input()->GetCursorPos( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ] ); + m_pDragDrop->m_nLastPos[ 0 ] = m_pDragDrop->m_nStartPos[ 0 ]; + m_pDragDrop->m_nLastPos[ 1 ] = m_pDragDrop->m_nStartPos[ 1 ]; + + OnContinueDragging(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Called if drag drop is started but not dropped on top of droppable panel... +// Input : - +//----------------------------------------------------------------------------- +void Panel::OnDragFailed( CUtlVector< KeyValues * >& msglist ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void Panel::OnFinishDragging( bool mousereleased, MouseCode code, bool abort /*= false*/ ) +{ +#if defined( VGUI_USEDRAGDROP ) + g_DragDropCapture = NULL; + + if ( !m_pDragDrop->m_bDragEnabled ) + return; + + Assert( m_pDragDrop->m_bDragging ); + + if ( !m_pDragDrop->m_bDragging ) + return; + + int x, y; + input()->GetCursorPos( x, y ); + + m_pDragDrop->m_nLastPos[ 0 ] = x; + m_pDragDrop->m_nLastPos[ 1 ] = y; + + if ( s_DragDropHelper.Get() ) + { + s_DragDropHelper->RemovePanel( this ); + } + + m_pDragDrop->m_bDragging = false; + + CUtlVector< KeyValues * >& data = m_pDragDrop->m_DragData; + int c = data.Count(); + + Panel *target = NULL; + bool shouldDrop = false; + + if ( m_pDragDrop->m_bDragStarted ) + { + char cmd[ 256 ]; + Q_strncpy( cmd, "default", sizeof( cmd ) ); + + if ( mousereleased && + m_pDragDrop->m_hCurrentDrop != 0 && + m_pDragDrop->m_hDropContextMenu.Get() ) + { + Menu *menu = m_pDragDrop->m_hDropContextMenu; + + VPANEL hover = menu->IsWithinTraverse( x, y, false ); + if ( hover ) + { + Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() ); + if ( pHover ) + { + // Figure out if it's a menu item... + int c = menu->GetItemCount(); + for ( int i = 0; i < c; ++i ) + { + int id = menu->GetMenuID( i ); + MenuItem *item = menu->GetMenuItem( id ); + if ( item == pHover ) + { + KeyValues *command = item->GetCommand(); + if ( command ) + { + char const *p = command->GetString( "command", "" ); + if ( p && p[ 0 ] ) + { + Q_strncpy( cmd, p, sizeof( cmd ) ); + } + } + } + } + } + } + + delete menu; + m_pDragDrop->m_hDropContextMenu = NULL; + } + + for ( int i = 0 ; i < c; ++i ) + { + KeyValues *msg = data[ i ]; + + msg->SetString( "command", cmd ); + + msg->SetInt( "screenx", x ); + msg->SetInt( "screeny", y ); + } + + target = m_pDragDrop->m_hCurrentDrop.Get(); + if ( target && !abort ) + { + int localmousex = x, localmousey = y; + // Convert screen space coordintes to coordinates relative to drop window + target->ScreenToLocal( localmousex, localmousey ); + + for ( int i = 0 ; i < c; ++i ) + { + KeyValues *msg = data[ i ]; + + msg->SetInt( "x", localmousex ); + msg->SetInt( "y", localmousey ); + } + + shouldDrop = true; + } + + if ( !shouldDrop ) + { + OnDragFailed( data ); + } + } + + m_pDragDrop->m_bDragStarted = false; + m_pDragDrop->m_DragPanels.RemoveAll(); + m_pDragDrop->m_hCurrentDrop = NULL; + + // Copy data ptrs out of data because OnPanelDropped might cause this panel to be deleted + // and our this ptr will be hosed... + CUtlVector< KeyValues * > temp; + for ( int i = 0 ; i < c; ++i ) + { + temp.AddToTail( data[ i ] ); + } + data.RemoveAll(); + + if ( shouldDrop && target ) + { + target->OnPanelDropped( temp ); + } + for ( int i = 0 ; i < c ; ++i ) + { + temp[ i ]->deleteThis(); + } +#endif +} + +void Panel::OnDropContextHoverShow( CUtlVector< KeyValues * >& msglist ) +{ +} + +void Panel::OnDropContextHoverHide( CUtlVector< KeyValues * >& msglist ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *msg - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsDroppable( CUtlVector< KeyValues * >& msglist ) +{ + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : startx - +// starty - +// mx - +// my - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::CanStartDragging( int startx, int starty, int mx, int my ) +{ +#if defined( VGUI_USEDRAGDROP ) + if ( IsStartDragWhenMouseExitsPanel() ) + { + ScreenToLocal( mx, my ); + if ( mx < 0 || my < 0 ) + return true; + if ( mx > GetWide() || my > GetTall() ) + return true; + + return false; + } + + int deltax = abs( mx - startx ); + int deltay = abs( my - starty ); + if ( deltax > m_pDragDrop->m_nDragStartTolerance || + deltay > m_pDragDrop->m_nDragStartTolerance ) + { + return true; + } +#endif + return false; +} + +HCursor Panel::GetDropCursor( CUtlVector< KeyValues * >& msglist ) +{ + return dc_arrow; +} + +bool IsSelfDroppable( CUtlVector< KeyValues * > &dragData ) +{ + if ( dragData.Count() == 0 ) + return false; + + KeyValues *pKeyValues( dragData[ 0 ] ); + if ( !pKeyValues ) + return false; + + return pKeyValues->GetInt( "selfDroppable" ) != 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void Panel::OnContinueDragging() +{ +#if defined( VGUI_USEDRAGDROP ) + if ( !m_pDragDrop->m_bDragEnabled ) + return; + + if ( !m_pDragDrop->m_bDragging ) + return; + + int x, y; + input()->GetCursorPos( x, y ); + + // Update last position + m_pDragDrop->m_nLastPos[ 0 ] = x; + m_pDragDrop->m_nLastPos[ 1 ] = y; + + if ( !m_pDragDrop->m_bDragStarted ) + { + if ( CanStartDragging( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ], x, y ) ) + { + m_pDragDrop->m_bDragStarted = true; + CreateDragData(); + } + else + { + return; + } + } + + if ( !s_DragDropHelper.Get() && m_pDragDrop->m_bShowDragHelper ) + { + s_DragDropHelper = new CDragDropHelperPanel(); + s_DragDropHelper->SetKeyBoardInputEnabled( false ); + s_DragDropHelper->SetMouseInputEnabled( false ); + Assert( s_DragDropHelper.Get() ); + } + + if ( !s_DragDropHelper.Get() ) + return; + + s_DragDropHelper->AddPanel( this ); + + Assert( m_pDragDrop->m_DragData.Count() ); + + vgui::PHandle oldDrop = m_pDragDrop->m_hCurrentDrop; + + // See what's under that + m_pDragDrop->m_hCurrentDrop = NULL; + + // Search under mouse pos... + Panel *dropTarget = FindDropTargetPanel(); + if ( dropTarget ) + { + dropTarget = dropTarget->GetDropTarget( m_pDragDrop->m_DragData ); + } + + // it's not okay until we find a droppable panel + surface()->SetCursor( dc_no ); + + if ( dropTarget ) + { + if ( dropTarget != this || IsSelfDroppable( m_pDragDrop->m_DragData ) ) + { + m_pDragDrop->m_hCurrentDrop = dropTarget; + surface()->SetCursor( dropTarget->GetDropCursor( m_pDragDrop->m_DragData ) ); + } + } + + if ( m_pDragDrop->m_hCurrentDrop.Get() != oldDrop.Get() ) + { + if ( oldDrop.Get() ) + { + oldDrop->OnPanelExitedDroppablePanel( m_pDragDrop->m_DragData ); + } + + if ( m_pDragDrop->m_hCurrentDrop.Get() ) + { + m_pDragDrop->m_hCurrentDrop->OnPanelEnteredDroppablePanel( m_pDragDrop->m_DragData ); + m_pDragDrop->m_hCurrentDrop->OnDropContextHoverHide( m_pDragDrop->m_DragData ); + + // Reset hover time + m_pDragDrop->m_lDropHoverTime = system()->GetTimeMillis(); + m_pDragDrop->m_bDropMenuShown = false; + } + + // Discard any stale context menu... + if ( m_pDragDrop->m_hDropContextMenu.Get() ) + { + delete m_pDragDrop->m_hDropContextMenu.Get(); + } + } + + if ( m_pDragDrop->m_hCurrentDrop != 0 && + m_pDragDrop->m_hDropContextMenu.Get() ) + { + Menu *menu = m_pDragDrop->m_hDropContextMenu; + + VPANEL hover = menu->IsWithinTraverse( x, y, false ); + if ( hover ) + { + Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() ); + if ( pHover ) + { + // Figure out if it's a menu item... + int c = menu->GetItemCount(); + for ( int i = 0; i < c; ++i ) + { + int id = menu->GetMenuID( i ); + MenuItem *item = menu->GetMenuItem( id ); + if ( item == pHover ) + { + menu->SetCurrentlyHighlightedItem( id ); + } + } + } + } + else + { + menu->ClearCurrentlyHighlightedItem(); + } + } +#endif +} + +#if defined( VGUI_USEDRAGDROP ) +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : DragDrop_t +//----------------------------------------------------------------------------- +DragDrop_t *Panel::GetDragDropInfo() +{ + Assert( m_pDragDrop ); + return m_pDragDrop; +} +#endif + +void Panel::OnGetAdditionalDragPanels( CUtlVector< Panel * >& dragabbles ) +{ + // Nothing here +} + +//----------------------------------------------------------------------------- +// Purpose: Virtual method to allow panels to add to the default values +// Input : *msg - +//----------------------------------------------------------------------------- +void Panel::OnCreateDragData( KeyValues *msg ) +{ + // These values are filled in for you: + // "panel" ptr to panel being dropped + // "screenx", "screeny" - drop cursor pos in screen space + // "x", "y" - drop coordinates relative to this window (the window being dropped upon) +} + +// Called if m_flHoverContextTime was non-zero, allows droppee to preview the drop data and show an appropriate menu +bool Panel::GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist ) +{ + return false; +} + +void Panel::CreateDragData() +{ +#if defined( VGUI_USEDRAGDROP ) + int i, c; + + if ( m_pDragDrop->m_DragData.Count() ) + { + return; + } + + PHandle h; + h = this; + m_pDragDrop->m_DragPanels.AddToTail( h ); + + CUtlVector< Panel * > temp; + OnGetAdditionalDragPanels( temp ); + c = temp.Count(); + for ( i = 0; i < c; ++i ) + { + h = temp[ i ]; + m_pDragDrop->m_DragPanels.AddToTail( h ); + } + + c = m_pDragDrop->m_DragPanels.Count(); + for ( i = 0 ; i < c; ++i ) + { + Panel *sibling = m_pDragDrop->m_DragPanels[ i ].Get(); + if ( !sibling ) + { + continue; + } + + KeyValues *msg = new KeyValues( "DragDrop" ); + msg->SetPtr( "panel", sibling ); + + sibling->OnCreateDragData( msg ); + + m_pDragDrop->m_DragData.AddToTail( msg ); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : KeyValues +//----------------------------------------------------------------------------- +void Panel::GetDragData( CUtlVector< KeyValues * >& list ) +{ +#if defined( VGUI_USEDRAGDROP ) + int i, c; + + list.RemoveAll(); + + c = m_pDragDrop->m_DragData.Count(); + for ( i = 0 ; i < c; ++i ) + { + list.AddToTail( m_pDragDrop->m_DragData[ i ] ); + } +#endif +} + +#if defined( VGUI_USEDRAGDROP ) +CDragDropHelperPanel::CDragDropHelperPanel() : BaseClass( NULL, "DragDropHelper" ) +{ + SetVisible( true ); + SetPaintEnabled( false ); + SetPaintBackgroundEnabled( false ); + SetMouseInputEnabled( false ); + SetKeyBoardInputEnabled( false ); + // SetCursor( dc_none ); + ipanel()->SetTopmostPopup( GetVPanel(), true ); + int w, h; + surface()->GetScreenSize( w, h ); + SetBounds( 0, 0, w, h ); + + SetPostChildPaintEnabled( true ); + + MakePopup( false ); +} + +VPANEL CDragDropHelperPanel::IsWithinTraverse(int x, int y, bool traversePopups) +{ + return (VPANEL)0; +} + +void CDragDropHelperPanel::PostChildPaint() +{ + int c = m_PaintList.Count(); + for ( int i = c - 1; i >= 0 ; --i ) + { + DragHelperPanel_t& data = m_PaintList[ i ]; + + Panel *panel = data.m_hPanel.Get(); + if ( !panel ) + { + m_PaintList.Remove( i ); + continue; + } + + Panel *dropPanel = panel->GetDragDropInfo()->m_hCurrentDrop.Get(); + if ( panel ) + { + if ( !dropPanel ) + { + panel->OnDraggablePanelPaint(); + } + else + { + CUtlVector< Panel * > temp; + CUtlVector< PHandle >& data = panel->GetDragDropInfo()->m_DragPanels; + CUtlVector< KeyValues * >& msglist = panel->GetDragDropInfo()->m_DragData; + int i, c; + c = data.Count(); + for ( i = 0; i < c ; ++i ) + { + Panel *pPanel = data[ i ].Get(); + if ( pPanel ) + { + temp.AddToTail( pPanel ); + } + } + + dropPanel->OnDroppablePanelPaint( msglist, temp ); + } + } + } + + if ( c == 0 ) + { + MarkForDeletion(); + } +} + +void CDragDropHelperPanel::AddPanel( Panel *current ) +{ + if ( !current ) + return; + + Menu *hover = current->GetDragDropInfo()->m_hDropContextMenu.Get(); + + surface()->MovePopupToFront( GetVPanel() ); + if ( hover && hover->IsPopup() ) + { + surface()->MovePopupToFront( hover->GetVPanel() ); + } + + int c = m_PaintList.Count(); + for ( int i = 0; i < c; ++i ) + { + if ( m_PaintList[ i ].m_hPanel.Get() == current ) + return; + } + + DragHelperPanel_t data; + data.m_hPanel = current; + m_PaintList.AddToTail( data ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *search - +//----------------------------------------------------------------------------- +void CDragDropHelperPanel::RemovePanel( Panel *search ) +{ + int c = m_PaintList.Count(); + for ( int i = c - 1 ; i >= 0; --i ) + { + if ( m_PaintList[ i ].m_hPanel.Get() == search ) + { + m_PaintList.Remove( i ); + return; + } + } +} +#endif +//----------------------------------------------------------------------------- +// Purpose: Enumerates panels under mouse x,y +// Input : panelList - +// x - +// y - +// check - +//----------------------------------------------------------------------------- +void Panel::FindDropTargetPanel_R( CUtlVector< VPANEL >& panelList, int x, int y, VPANEL check ) +{ +#if defined( VGUI_USEDRAGDROP ) + if ( !ipanel()->IsFullyVisible( check ) ) + return; + + if ( ::ShouldHandleInputMessage( check ) && ipanel()->IsWithinTraverse( check, x, y, false ) ) + { + panelList.AddToTail( check ); + } + + CUtlVector< VPANEL > &children = ipanel()->GetChildren( check ); + int childCount = children.Count(); + for ( int i = 0; i < childCount; i++ ) + { + VPANEL child = children[ i ]; + FindDropTargetPanel_R( panelList, x, y, child ); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Panel +//----------------------------------------------------------------------------- +Panel *Panel::FindDropTargetPanel() +{ +#if defined( VGUI_USEDRAGDROP ) + if ( !s_DragDropHelper.Get() ) + return NULL; + + CUtlVector< VPANEL > hits; + + int x, y; + input()->GetCursorPos( x, y ); + + VPANEL embedded = surface()->GetEmbeddedPanel(); + VPANEL helper = s_DragDropHelper.Get()->GetVPanel(); + + if ( surface()->IsCursorVisible() && surface()->IsWithin(x, y) ) + { + // faster version of code below + // checks through each popup in order, top to bottom windows + int c = surface()->GetPopupCount(); + for (int i = c - 1; i >= 0 && hits.Count() == 0; i--) + { + VPANEL popup = surface()->GetPopup(i); + if ( popup == embedded ) + continue; + + // Don't return helper panel!!! + if ( popup == helper ) + continue; + + if ( !ipanel()->IsFullyVisible( popup ) ) + continue; + + FindDropTargetPanel_R( hits, x, y, popup ); + } + + // Check embedded + if ( !hits.Count() ) + { + FindDropTargetPanel_R( hits, x, y, embedded ); + } + } + + // Nothing under mouse... + if ( !hits.Count() ) + return NULL; + + // Return topmost panel under mouse, if it's visible to this .dll + Panel *panel = NULL; + int nCount = hits.Count(); + while ( --nCount >= 0 ) + { + panel = ipanel()->GetPanel( hits[ nCount ], GetModuleName() ); + if ( panel ) + return panel; + } +#endif + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Mouse is on draggable panel and has started moving, but is not over a droppable panel yet +// Input : - +//----------------------------------------------------------------------------- +void Panel::OnDraggablePanelPaint() +{ +#if defined( VGUI_USEDRAGDROP ) + int sw, sh; + GetSize( sw, sh ); + + int x, y; + input()->GetCursorPos( x, y ); + int w, h; + + w = min( sw, 80 ); + h = min( sh, 80 ); + x -= ( w >> 1 ); + y -= ( h >> 1 ); + + surface()->DrawSetColor( m_clrDragFrame ); + surface()->DrawOutlinedRect( x, y, x + w, y + h ); + + if ( m_pDragDrop->m_DragPanels.Count() > 1 ) + { + surface()->DrawSetTextColor( m_clrDragFrame ); + surface()->DrawSetTextFont( m_infoFont ); + surface()->DrawSetTextPos( x + 5, y + 2 ); + + wchar_t sz[ 64 ]; + V_swprintf_safe( sz, L"[ %i ]", m_pDragDrop->m_DragPanels.Count() ); + + surface()->DrawPrintText( sz, wcslen( sz ) ); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Mouse is now over a droppable panel +// Input : *dragPanel - +//----------------------------------------------------------------------------- +void Panel::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels ) +{ +#if defined( VGUI_USEDRAGDROP ) + if ( !dragPanels.Count() ) + return; + + // Convert this panel's bounds to screen space + int w, h; + GetSize( w, h ); + + int x, y; + x = y = 0; + LocalToScreen( x, y ); + + surface()->DrawSetColor( m_clrDropFrame ); + // Draw 2 pixel frame + surface()->DrawOutlinedRect( x, y, x + w, y + h ); + surface()->DrawOutlinedRect( x+1, y+1, x + w-1, y + h-1 ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Color +//----------------------------------------------------------------------------- +Color Panel::GetDropFrameColor() +{ +#if defined( VGUI_USEDRAGDROP ) + return m_clrDropFrame; +#endif + return Color(0, 0, 0, 0); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Color +//----------------------------------------------------------------------------- +Color Panel::GetDragFrameColor() +{ +#if defined( VGUI_USEDRAGDROP ) + return m_clrDragFrame; +#endif + return Color(0, 0, 0, 0); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *data - +//----------------------------------------------------------------------------- +void Panel::OnPanelDropped( CUtlVector< KeyValues * >& data ) +{ + // Empty. Derived classes would implement handlers here +} + +//----------------------------------------------------------------------------- +// called on droptarget when draggable panel enters droptarget +//----------------------------------------------------------------------------- +void Panel::OnPanelEnteredDroppablePanel( CUtlVector< KeyValues * >& msglist ) +{ + // Empty. Derived classes would implement handlers here +} + +//----------------------------------------------------------------------------- +// called on droptarget when draggable panel exits droptarget +//----------------------------------------------------------------------------- +void Panel::OnPanelExitedDroppablePanel ( CUtlVector< KeyValues * >& msglist ) +{ + // Empty. Derived classes would implement handlers here +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void Panel::DragDropStartDragging() +{ +#if defined( VGUI_USEDRAGDROP ) + // We somehow missed a mouse release, cancel the previous drag + if ( g_DragDropCapture.Get() ) + { + if ( HasParent( g_DragDropCapture.Get()->GetVPanel() ) ) + return; + + bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted; + g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1 ); + if ( started ) + { + return; + } + } + + // Find actual target panel + Panel *panel = GetDragPanel(); + if ( !panel ) + return; + + DragDrop_t *data = panel->GetDragDropInfo(); + if ( !data ) + return; + + if ( !panel->IsDragEnabled() ) + return; + + if ( data->m_bDragging ) + return; + + panel->OnStartDragging(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool Panel::IsBeingDragged() +{ +#if defined( VGUI_USEDRAGDROP ) + if ( !g_DragDropCapture.Get() ) + return false; + + if ( g_DragDropCapture.Get() == this ) + return true; + + // If we encounter a blocker, stop chaining + if ( m_pDragDrop->m_bPreventChaining ) + return false; + + // Chain up + if ( GetParent() ) + { + return GetParent()->IsBeingDragged(); + } +#endif + // No luck + return false; +} + +struct srect_t +{ + int x0, y0; + int x1, y1; + + bool IsDegenerate() + { + if ( x1 - x0 <= 0 ) + return true; + if ( y1 - y0 <= 0 ) + return true; + return false; + } +}; + +// Draws a filled rect of specified bounds, but omits the bounds of the skip panel from those bounds +void Panel::FillRectSkippingPanel( const Color &clr, int x, int y, int w, int h, Panel *skipPanel ) +{ + int sx = 0, sy = 0, sw, sh; + skipPanel->GetSize( sw, sh ); + skipPanel->LocalToScreen( sx, sy ); + ScreenToLocal( sx, sy ); + + surface()->DrawSetColor( clr ); + + srect_t r1; + r1.x0 = x; + r1.y0 = y; + r1.x1 = x + w; + r1.y1 = y + h; + + srect_t r2; + r2.x0 = sx; + r2.y0 = sy; + r2.x1 = sx + sw; + r2.y1 = sy + sh; + + int topy = r1.y0; + int bottomy = r1.y1; + + // We'll descend vertically and draw: + // 1 a possible bar across the top + // 2 a possible bar across the bottom + // 3 possible left bar + // 4 possible right bar + + // Room at top? + if ( r2.y0 > r1.y0 ) + { + topy = r2.y0; + + surface()->DrawFilledRect( r1.x0, r1.y0, r1.x1, topy ); + } + + // Room at bottom? + if ( r2.y1 < r1.y1 ) + { + bottomy = r2.y1; + + surface()->DrawFilledRect( r1.x0, bottomy, r1.x1, r1.y1 ); + } + + // Room on left side? + if ( r2.x0 > r1.x0 ) + { + int left = r2.x0; + + surface()->DrawFilledRect( r1.x0, topy, left, bottomy ); + } + + // Room on right side + if ( r2.x1 < r1.x1 ) + { + int right = r2.x1; + + surface()->DrawFilledRect( right, topy, r1.x1, bottomy ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *child - +//----------------------------------------------------------------------------- +void Panel::SetSkipChildDuringPainting( Panel *child ) +{ + m_SkipChild = child; +} + +HPanel Panel::ToHandle() const +{ + return ivgui()->PanelToHandle( _vpanel ); +} +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::NavigateUp() +{ + Panel *target = GetNavUp(); + if ( target ) + { + NavigateFrom(); + target->m_LastNavDirection = ND_UP; + target->NavigateTo(); + } + + return target; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::NavigateDown() +{ + Panel *target = GetNavDown(); + if ( target ) + { + NavigateFrom(); + target->m_LastNavDirection = ND_DOWN; + target->NavigateTo(); + } + + return target; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::NavigateLeft() +{ + Panel *target = GetNavLeft(); + if ( target ) + { + NavigateFrom(); + target->m_LastNavDirection = ND_LEFT; + target->NavigateTo(); + } + return target; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::NavigateRight() +{ + Panel *target = GetNavRight(); + if ( target ) + { + NavigateFrom(); + target->m_LastNavDirection = ND_RIGHT; + target->NavigateTo(); + } + return target; +} + +Panel* Panel::NavigateActivate() +{ + Panel *target = GetNavActivate(); + if ( target ) + { + NavigateFrom(); + target->m_LastNavDirection = ND_NONE; + target->NavigateTo(); + } + return target; +} + +Panel* Panel::NavigateBack() +{ + Panel *target = GetNavBack(); + if ( target ) + { + NavigateFrom(); + target->m_LastNavDirection = ND_NONE; + target->NavigateTo(); + } + return target; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::NavigateTo() +{ + if ( IsX360() ) + { + RequestFocus( 0 ); + } + + CallParentFunction( new KeyValues( "OnNavigateTo", "panelName", GetName() ) ); + + Panel *target = GetNavToRelay(); + if ( target ) + { + NavigateFrom(); + target->m_LastNavDirection = ND_NONE; + NavigateToChild( target ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::NavigateFrom() +{ + for ( int i = 0; i < GetChildCount(); ++i ) + { + Panel* currentNav = GetChild(i); + if ( currentNav != 0 ) + { + currentNav->NavigateFrom(); + } + } + + CallParentFunction( new KeyValues( "OnNavigateFrom", "panelName", GetName() ) ); + + if ( m_pTooltips ) + { + m_pTooltips->HideTooltip(); + } + + m_LastNavDirection = ND_NONE; +} + +void Panel::NavigateToChild( Panel *pNavigateTo ) +{ + for( int i = 0; i != GetChildCount(); ++i ) + { + vgui::Panel *pChild = GetChild(i); + if( pChild ) + pChild->NavigateFrom(); + } + pNavigateTo->NavigateTo(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::SetNavUp( Panel* navUp ) +{ + Panel* lastNav = m_NavUp; + m_NavUp = navUp; + + if( navUp ) + m_sNavUpName = navUp->GetName(); + else + m_sNavUpName.Clear(); + + return lastNav; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::SetNavDown( Panel* navDown ) +{ + Panel* lastNav = m_NavDown; + m_NavDown = navDown; + + if( navDown ) + m_sNavDownName = navDown->GetName(); + else + m_sNavDownName.Clear(); + + return lastNav; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::SetNavLeft( Panel* navLeft ) +{ + Panel* lastNav = m_NavLeft; + m_NavLeft = navLeft; + + if( navLeft ) + m_sNavLeftName = navLeft->GetName(); + else + m_sNavLeftName.Clear(); + + return lastNav; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel* Panel::SetNavRight( Panel* navRight ) +{ + Panel* lastNav = m_NavRight; + m_NavRight = navRight; + + if( navRight ) + m_sNavRightName = navRight->GetName(); + else + m_sNavRightName.Clear(); + + return lastNav; +} + +Panel* Panel::SetNavToRelay( Panel* navToRelay ) +{ + Panel* lastNav = m_NavToRelay; + m_NavToRelay = navToRelay; + + return lastNav; +} + +Panel* Panel::SetNavActivate( Panel* navActivate ) +{ + Panel* lastNav = m_NavActivate; + m_NavActivate = navActivate; + + return lastNav; +} + +Panel* Panel::SetNavBack( Panel* navBack ) +{ + Panel* lastNav = m_NavBack; + m_NavBack = navBack; + + return lastNav; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Panel::NAV_DIRECTION Panel::GetLastNavDirection() +{ + return m_LastNavDirection; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::OnNavigateTo( const char* panelName ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::OnNavigateFrom( const char* panelName ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetNavUp( const char* controlName ) +{ + if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) + { + m_NavUp = NULL; + m_sNavUpName = controlName; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetNavDown( const char* controlName ) +{ + if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) + { + m_NavDown = NULL; + m_sNavDownName = controlName; + } +} +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetNavLeft( const char* controlName ) +{ + if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) + { + m_NavLeft = NULL; + m_sNavLeftName = controlName; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetNavRight( const char* controlName ) +{ + if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) + { + m_NavRight = NULL; + m_sNavRightName = controlName; + } +} + +void Panel::SetNavToRelay( const char* controlName ) +{ + if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) + { + m_NavToRelay = NULL; + m_sNavToRelayName = controlName; + } +} + +void Panel::SetNavActivate( const char* controlName ) +{ + if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) + { + m_NavActivate = NULL; + m_sNavActivateName = controlName; + } +} + +void Panel::SetNavBack( const char* controlName ) +{ + if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 ) + { + m_NavBack = NULL; + m_sNavBackName = controlName; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +vgui::Panel* Panel::GetNavUp( Panel *first ) +{ + if ( !m_NavUp && m_sNavUpName.Length() > 0 ) + { + Panel *pParent = GetParent(); + const char *pName = m_sNavUpName.String(); + while ( pParent && pName[ 0 ] == '<' ) + { + pParent = pParent->GetParent(); + pName++; + } + + if ( !pParent ) + { + return NULL; + } + + Panel *foundPanel = pParent->FindChildByName( pName, true ); + if ( foundPanel != 0 ) + { + m_NavUp = foundPanel; + } + } + + vgui::Panel* nextPanel = m_NavUp; + if( m_NavUp && m_NavUp != first && !m_NavUp->IsVisible() ) + { + Panel *firstPanel = first == NULL ? this : first; + nextPanel = nextPanel->GetNavUp( firstPanel ); + } + + return nextPanel; +} + +vgui::Panel* Panel::GetNavDown( Panel *first ) +{ + if ( !m_NavDown && m_sNavDownName.Length() > 0 ) + { + Panel *pParent = GetParent(); + const char *pName = m_sNavDownName.String(); + while ( pParent && pName[ 0 ] == '<' ) + { + pParent = pParent->GetParent(); + pName++; + } + + if ( !pParent ) + { + return NULL; + } + + Panel* foundPanel = pParent->FindChildByName( pName, true ); + if ( foundPanel != 0 ) + { + m_NavDown = foundPanel->GetPanel(); + } + } + + vgui::Panel* nextPanel = m_NavDown; + if( m_NavDown && m_NavDown != first && !m_NavDown->IsVisible() ) + { + Panel *firstPanel = first == NULL ? this : first; + nextPanel = nextPanel->GetNavDown( firstPanel ); + } + + return nextPanel; +} + +vgui::Panel* Panel::GetNavLeft( Panel *first ) +{ + if ( !m_NavLeft && m_sNavLeftName.Length() > 0 ) + { + Panel *pParent = GetParent(); + const char *pName = m_sNavLeftName.String(); + while ( pParent && pName[ 0 ] == '<' ) + { + pParent = pParent->GetParent(); + pName++; + } + + if ( !pParent ) + { + return NULL; + } + + Panel* foundPanel = pParent->FindChildByName( pName, true ); + if ( foundPanel != 0 ) + { + m_NavLeft = foundPanel->GetPanel(); + } + } + + vgui::Panel* nextPanel = m_NavLeft; + if( m_NavLeft && m_NavLeft != first && !m_NavLeft->IsVisible() ) + { + Panel *firstPanel = first == NULL ? this : first; + nextPanel = nextPanel->GetNavLeft( firstPanel ); + } + + return nextPanel; +} + +vgui::Panel* Panel::GetNavRight( Panel *first ) +{ + if ( !m_NavRight && m_sNavRightName.Length() > 0 ) + { + Panel *pParent = GetParent(); + const char *pName = m_sNavRightName.String(); + while ( pParent && pName[ 0 ] == '<' ) + { + pParent = pParent->GetParent(); + pName++; + } + + if ( !pParent ) + { + return NULL; + } + + Panel* foundPanel = pParent->FindChildByName( pName, true ); + if ( foundPanel != 0 ) + { + m_NavRight = foundPanel->GetPanel(); + } + } + + vgui::Panel* nextPanel = m_NavRight; + if( m_NavRight && m_NavRight != first && !m_NavRight->IsVisible() ) + { + Panel *firstPanel = first == NULL ? this : first; + nextPanel = nextPanel->GetNavRight( firstPanel ); + } + + return nextPanel; +} + +vgui::Panel* Panel::GetNavToRelay( Panel *first ) +{ + if ( !m_NavToRelay && m_sNavToRelayName.Length() > 0 ) + { + Panel *pParent = this; + const char *pName = m_sNavToRelayName.String(); + while ( pParent && pName[ 0 ] == '<' ) + { + pParent = pParent->GetParent(); + pName++; + } + + if ( !pParent ) + { + return NULL; + } + + Panel* foundPanel = pParent->FindChildByName( pName, true ); + if ( foundPanel != 0 ) + { + m_NavToRelay = foundPanel->GetPanel(); + } + } + + vgui::Panel* nextPanel = m_NavToRelay; + if ( m_NavToRelay && m_NavToRelay != first && !m_NavToRelay->IsVisible() ) + { + Panel *firstPanel = first == NULL ? this : first; + nextPanel = nextPanel->GetNavToRelay( firstPanel ); + } + + return nextPanel; +} + +vgui::Panel* Panel::GetNavActivate( Panel *first ) +{ + if ( !m_NavActivate && m_sNavActivateName.Length() > 0 ) + { + Panel *pParent = GetParent(); + const char *pName = m_sNavActivateName.String(); + while ( pParent && pName[ 0 ] == '<' ) + { + pParent = pParent->GetParent(); + pName++; + } + + if ( !pParent ) + { + return NULL; + } + + Panel* foundPanel = pParent->FindChildByName( pName, true ); + if ( foundPanel != 0 ) + { + m_NavActivate = foundPanel->GetPanel(); + } + } + + vgui::Panel* nextPanel = m_NavActivate; + if ( m_NavActivate && m_NavActivate != first && !m_NavActivate->IsVisible() ) + { + Panel *firstPanel = first == NULL ? this : first; + nextPanel = nextPanel->GetNavActivate( firstPanel ); + } + + return nextPanel; +} + +vgui::Panel* Panel::GetNavBack( Panel *first ) +{ + if ( !m_NavBack && m_sNavBackName.Length() > 0 ) + { + Panel *pParent = GetParent(); + const char *pName = m_sNavBackName.String(); + while ( pParent && pName[ 0 ] == '<' ) + { + pParent = pParent->GetParent(); + pName++; + } + + if ( !pParent ) + { + return NULL; + } + + Panel *foundPanel = pParent->FindChildByName( pName ); + if ( foundPanel ) + { + m_NavBack = foundPanel; + } + } + + vgui::Panel* nextPanel = m_NavBack; + if ( m_NavBack && m_NavBack != first && !m_NavBack->IsVisible() ) + { + Panel *firstPanel = first == NULL ? this : first; + nextPanel = nextPanel->GetNavBack( firstPanel ); + } + + return nextPanel; +} + +vgui::Panel* Panel::GetNavUpPanel() +{ + return m_NavUp; +} + +vgui::Panel* Panel::GetNavDownPanel() +{ + return m_NavDown; +} + +vgui::Panel* Panel::GetNavLeftPanel() +{ + return m_NavLeft; +} + +vgui::Panel* Panel::GetNavRightPanel() +{ + return m_NavRight; +} + +vgui::Panel* Panel::GetNavToRelayPanel() +{ + return m_NavToRelay; +} + +vgui::Panel* Panel::GetNavActivatePanel() +{ + return m_NavActivate; +} + +vgui::Panel* Panel::GetNavBackPanel() +{ + return m_NavBack; +} + +void Panel::SetConsoleStylePanel( bool bConsoleStyle ) +{ + m_bIsConsoleStylePanel = bConsoleStyle; +} + +bool Panel::IsConsoleStylePanel() const +{ + return m_bIsConsoleStylePanel; +} + +//----------------------------------------------------------------------------- +// Purpose: Utility class for handling message map allocation +//----------------------------------------------------------------------------- +class CPanelMessageMapDictionary +{ +public: + CPanelMessageMapDictionary() : m_PanelMessageMapPool( sizeof(PanelMessageMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelMessageMapDictionary::m_PanelMessageMapPool" ) + { + m_MessageMaps.RemoveAll(); + } + + PanelMessageMap *FindOrAddPanelMessageMap( char const *className ); + PanelMessageMap *FindPanelMessageMap( char const *className ); +private: + + struct PanelMessageMapDictionaryEntry + { + PanelMessageMap *map; + }; + + char const *StripNamespace( char const *className ); + + CUtlDict< PanelMessageMapDictionaryEntry, int > m_MessageMaps; + CUtlMemoryPool m_PanelMessageMapPool; +}; + + +char const *CPanelMessageMapDictionary::StripNamespace( char const *className ) +{ + if ( !strnicmp( className, "vgui::", 6 ) ) + { + return className + 6; + } + return className; +} + +//----------------------------------------------------------------------------- +// Purpose: Find but don't add mapping +//----------------------------------------------------------------------------- +PanelMessageMap *CPanelMessageMapDictionary::FindPanelMessageMap( char const *className ) +{ + int lookup = m_MessageMaps.Find( StripNamespace( className ) ); + if ( lookup != m_MessageMaps.InvalidIndex() ) + { + return m_MessageMaps[ lookup ].map; + } + return NULL; +} + +#include +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +PanelMessageMap *CPanelMessageMapDictionary::FindOrAddPanelMessageMap( char const *className ) +{ + PanelMessageMap *map = FindPanelMessageMap( className ); + if ( map ) + return map; + + PanelMessageMapDictionaryEntry entry; + // use the alloc in place method of new + entry.map = new (m_PanelMessageMapPool.Alloc(sizeof(PanelMessageMap))) PanelMessageMap; + Construct(entry.map); + m_MessageMaps.Insert( StripNamespace( className ), entry ); + return entry.map; +} +#include + +#if defined( VGUI_USEKEYBINDINGMAPS ) +//----------------------------------------------------------------------------- +// Purpose: Utility class for handling keybinding map allocation +//----------------------------------------------------------------------------- +class CPanelKeyBindingMapDictionary +{ +public: + CPanelKeyBindingMapDictionary() : m_PanelKeyBindingMapPool( sizeof(PanelKeyBindingMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelKeyBindingMapDictionary::m_PanelKeyBindingMapPool" ) + { + m_MessageMaps.RemoveAll(); + } + + PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className ); + PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className ); +private: + + struct PanelKeyBindingMapDictionaryEntry + { + PanelKeyBindingMap *map; + }; + + char const *StripNamespace( char const *className ); + + CUtlDict< PanelKeyBindingMapDictionaryEntry, int > m_MessageMaps; + CUtlMemoryPool m_PanelKeyBindingMapPool; +}; + + +char const *CPanelKeyBindingMapDictionary::StripNamespace( char const *className ) +{ + if ( !strnicmp( className, "vgui::", 6 ) ) + { + return className + 6; + } + return className; +} + +//----------------------------------------------------------------------------- +// Purpose: Find but don't add mapping +//----------------------------------------------------------------------------- +PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindPanelKeyBindingMap( char const *className ) +{ + int lookup = m_MessageMaps.Find( StripNamespace( className ) ); + if ( lookup != m_MessageMaps.InvalidIndex() ) + { + return m_MessageMaps[ lookup ].map; + } + return NULL; +} + +#include +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindOrAddPanelKeyBindingMap( char const *className ) +{ + PanelKeyBindingMap *map = FindPanelKeyBindingMap( className ); + if ( map ) + return map; + + PanelKeyBindingMapDictionaryEntry entry; + // use the alloc in place method of new + entry.map = new (m_PanelKeyBindingMapPool.Alloc(sizeof(PanelKeyBindingMap))) PanelKeyBindingMap; + Construct(entry.map); + m_MessageMaps.Insert( StripNamespace( className ), entry ); + return entry.map; +} + +#include + +CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary() +{ + static CPanelKeyBindingMapDictionary dictionary; + return dictionary; +} + +#endif // VGUI_USEKEYBINDINGMAPS + +CPanelMessageMapDictionary& GetPanelMessageMapDictionary() +{ + static CPanelMessageMapDictionary dictionary; + return dictionary; +} + +namespace vgui +{ + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + PanelMessageMap *FindOrAddPanelMessageMap( char const *className ) + { + return GetPanelMessageMapDictionary().FindOrAddPanelMessageMap( className ); + } + + //----------------------------------------------------------------------------- + // Purpose: Find but don't add mapping + //----------------------------------------------------------------------------- + PanelMessageMap *FindPanelMessageMap( char const *className ) + { + return GetPanelMessageMapDictionary().FindPanelMessageMap( className ); + } + +#if defined( VGUI_USEKEYBINDINGMAPS ) + CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary() + { + static CPanelKeyBindingMapDictionary dictionary; + return dictionary; + } + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className ) + { + return GetPanelKeyBindingMapDictionary().FindOrAddPanelKeyBindingMap( className ); + } + + //----------------------------------------------------------------------------- + // Purpose: Find but don't add mapping + //----------------------------------------------------------------------------- + PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className ) + { + return GetPanelKeyBindingMapDictionary().FindPanelKeyBindingMap( className ); + } +#endif // VGUI_USEKEYBINDINGMAPS + +SortedPanel_t::SortedPanel_t( Panel *panel ) +{ + pPanel = panel; pButton = dynamic_cast< Button* >( panel ); +} + + +void VguiPanelGetSortedChildPanelList( Panel *pParentPanel, void *pSortedPanels ) +{ + CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels ); + + for ( int i = 0; i < pParentPanel->GetChildCount(); i++ ) + { + // perform auto-layout on the child panel + Panel *pPanel = pParentPanel->GetChild( i ); + if ( !pPanel || !pPanel->IsVisible() ) + continue; + + pList->Insert( SortedPanel_t( static_cast< Panel* >( pPanel ) ) ); + } +} + +void VguiPanelGetSortedChildButtonList( Panel *pParentPanel, void *pSortedPanels, char *pchFilter /*= NULL*/, int nFilterType /*= 0*/ ) +{ + CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels ); + + for ( int i = 0; i < pParentPanel->GetChildCount(); i++ ) + { + // perform auto-layout on the child panel + Button *pPanel = dynamic_cast< Button* >( pParentPanel->GetChild( i ) ); + if ( !pPanel || !pPanel->IsVisible() ) + continue; + + if ( pchFilter && pchFilter[ 0 ] != '\0' ) + { + char szBuff[ 128 ]; + pPanel->GetText( szBuff, sizeof( szBuff ) ); + + // Prefix + if ( nFilterType == 0 ) + { + if ( !StringHasPrefix( szBuff, pchFilter ) ) + { + continue; + } + } + // Substring + else if ( nFilterType == 1 ) + { + if ( V_strstr( szBuff, pchFilter ) == NULL ) + { + continue; + } + } + } + + pList->Insert( SortedPanel_t( pPanel ) ); + } +} + +int VguiPanelNavigateSortedChildButtonList( void *pSortedPanels, int nDir ) +{ + CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels ); + + if ( pList->Count() <= 0 ) + return -1; + + if ( nDir != 0 ) + { + int nArmed = -1; + for ( int i = 0; i < pList->Count(); i++ ) + { + if ( (*pList)[ i ].pButton->IsArmed() ) + { + nArmed = i; + break; + } + } + + if ( nArmed == -1 ) + { + (*pList)[ 0 ].pButton->SetArmed( true ); + return 0; + } + else + { + int nNewArmed = clamp( nArmed + nDir, 0, pList->Count() - 1 ); + if ( nNewArmed != nArmed ) + { + (*pList)[ nArmed ].pButton->SetArmed( false ); + } + + (*pList)[ nNewArmed ].pButton->RequestFocus(); + (*pList)[ nNewArmed ].pButton->SetArmed( true ); + + return nNewArmed; + } + } + + return -1; +} + +} -- cgit v1.2.3