Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

8653 lines
226 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdio.h>
  8. #include <assert.h>
  9. #include <utlvector.h>
  10. #include <vstdlib/ikeyvaluessystem.h>
  11. #include <vgui/IBorder.h>
  12. #include <vgui/IInput.h>
  13. #include <vgui/IPanel.h>
  14. #include <vgui/IScheme.h>
  15. #include <vgui/ISurface.h>
  16. #include <vgui/ISystem.h>
  17. #include <vgui/ILocalize.h>
  18. #include <vgui/IVGui.h>
  19. #include <keyvalues.h>
  20. #include <vgui/MouseCode.h>
  21. #include <vgui_controls/Panel.h>
  22. #include <vgui_controls/BuildGroup.h>
  23. #include <vgui_controls/Tooltip.h>
  24. #include <vgui_controls/PHandle.h>
  25. #include <vgui_controls/Controls.h>
  26. #include "vgui_controls/Menu.h"
  27. #include "vgui_controls/MenuItem.h"
  28. #include "utldict.h"
  29. #include "utlbuffer.h"
  30. #include "mempool.h"
  31. #include "filesystem.h"
  32. #include "tier0/icommandline.h"
  33. #include "tier0/vprof.h"
  34. // memdbgon must be the last include file in a .cpp file!!!
  35. #include <tier0/memdbgon.h>
  36. using namespace vgui;
  37. // DMX serializer fields.
  38. BEGIN_DMXELEMENT_UNPACK_NAMESPACE_SIMPLE_NO_BASE( vgui, Panel )
  39. DMXELEMENT_UNPACK_FIELD_UTLSTRING( "panel name", "NONE", _panelName )
  40. DMXELEMENT_UNPACK_FIELD( "foreground color", "255 255 255 255", Color, _fgColor )
  41. DMXELEMENT_UNPACK_FIELD( "background color", "255 255 255 255", Color, _bgColor )
  42. DMXELEMENT_UNPACK_SHORT( "pin delta x", "0", m_nPinDeltaX )
  43. DMXELEMENT_UNPACK_SHORT( "pin delta y", "0", m_nPinDeltaY )
  44. DMXELEMENT_UNPACK_SHORT( "resize delta x", "0", m_nResizeDeltaX )
  45. DMXELEMENT_UNPACK_SHORT( "resize delta y", "0", m_nResizeDeltaY )
  46. DMXELEMENT_UNPACK_SHORT( "build mode flags", "0", _buildModeFlags )
  47. DMXELEMENT_UNPACK_BITFIELD( "pin corner", "4", BITFIELD_TYPE_BYTE, _pinCorner )
  48. DMXELEMENT_UNPACK_BITFIELD( "auto resize direction", "0", BITFIELD_TYPE_BYTE, _autoResizeDirection )
  49. DMXELEMENT_UNPACK_CHAR( "tab position", "0", _tabPosition )
  50. DMXELEMENT_UNPACK_BITFIELD( "use scheme colors", "0", BITFIELD_TYPE_BOOL, m_bUseSchemeColors )
  51. DMXELEMENT_UNPACK_BITFIELD( "should PostActionSignals", "0", BITFIELD_TYPE_BOOL, m_bIsSilent )
  52. END_DMXELEMENT_UNPACK_NAMESPACE( vgui, Panel, s_pUnpackParams )
  53. #define TRIPLE_PRESS_MSEC 300
  54. static CUtlSymbolTable g_OverridenColorSymbols(0, 128, true); // symbol table for caching scheme color names
  55. int vgui::Panel::s_NavLock = 0;
  56. extern int GetBuildModeDialogCount();
  57. static char *CopyString( const char *in )
  58. {
  59. if ( !in )
  60. return NULL;
  61. int len = strlen( in );
  62. char *n = new char[ len + 1 ];
  63. Q_strncpy( n, in, len + 1 );
  64. return n;
  65. }
  66. #define SAFE_DELETE( x ) if ( (x) != NULL ) { delete (x); }
  67. #if defined( VGUI_USEDRAGDROP )
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. struct vgui::DragDrop_t
  72. {
  73. DragDrop_t() :
  74. m_bDragEnabled( false ),
  75. m_bShowDragHelper( true ),
  76. m_bDropEnabled( false ),
  77. m_bDragStarted( false ),
  78. m_nDragStartTolerance( 8 ),
  79. m_bDragging( false ),
  80. m_lDropHoverTime( 0 ),
  81. m_bDropMenuShown( false ),
  82. m_bPreventChaining( false )
  83. {
  84. m_nStartPos[ 0 ] = m_nStartPos[ 1 ] = 0;
  85. m_nLastPos[ 0 ] = m_nLastPos[ 1 ] = 0;
  86. }
  87. // Drag related data
  88. bool m_bDragEnabled;
  89. bool m_bShowDragHelper;
  90. bool m_bDragging;
  91. bool m_bDragStarted;
  92. // How many pixels the dragged box must move before showing the outline rect...
  93. int m_nDragStartTolerance;
  94. int m_nStartPos[ 2 ];
  95. int m_nLastPos[ 2 ];
  96. CUtlVector< KeyValues * > m_DragData;
  97. CUtlVector< PHandle > m_DragPanels;
  98. // Drop related data
  99. bool m_bDropEnabled;
  100. // A droppable panel can have a hover context menu, which will show up after m_flHoverContextTime of hovering
  101. float m_flHoverContextTime;
  102. PHandle m_hCurrentDrop;
  103. // Amount of time hovering over current drop target
  104. long m_lDropHoverTime;
  105. bool m_bDropMenuShown;
  106. DHANDLE< Menu > m_hDropContextMenu;
  107. // Misc data
  108. bool m_bPreventChaining;
  109. };
  110. //-----------------------------------------------------------------------------
  111. // Purpose: Helper for painting to the full screen...
  112. //-----------------------------------------------------------------------------
  113. class CDragDropHelperPanel : public Panel
  114. {
  115. DECLARE_CLASS_SIMPLE( CDragDropHelperPanel, Panel );
  116. public:
  117. CDragDropHelperPanel();
  118. virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups);
  119. virtual void PostChildPaint();
  120. void AddPanel( Panel *current );
  121. void RemovePanel( Panel *search );
  122. private:
  123. struct DragHelperPanel_t
  124. {
  125. PHandle m_hPanel;
  126. };
  127. CUtlVector< DragHelperPanel_t > m_PaintList;
  128. };
  129. vgui::DHANDLE< CDragDropHelperPanel > s_DragDropHelper;
  130. #endif
  131. #if defined( VGUI_USEKEYBINDINGMAPS )
  132. BoundKey_t::BoundKey_t():
  133. isbuiltin( true ),
  134. bindingname( 0 ),
  135. keycode( KEY_NONE ),
  136. modifiers( 0 )
  137. {
  138. }
  139. BoundKey_t::BoundKey_t( const BoundKey_t& src )
  140. {
  141. isbuiltin = src.isbuiltin;
  142. bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname );
  143. keycode = src.keycode;
  144. modifiers = src.modifiers;
  145. }
  146. BoundKey_t& BoundKey_t::operator =( const BoundKey_t& src )
  147. {
  148. if ( this == &src )
  149. return *this;
  150. isbuiltin = src.isbuiltin;
  151. bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname );
  152. keycode = src.keycode;
  153. modifiers = src.modifiers;
  154. return *this;
  155. }
  156. BoundKey_t::~BoundKey_t()
  157. {
  158. if ( !isbuiltin )
  159. {
  160. delete[] bindingname;
  161. }
  162. }
  163. KeyBindingMap_t::KeyBindingMap_t() :
  164. bindingname( 0 ),
  165. func( 0 ),
  166. helpstring( 0 ),
  167. docstring( 0 ),
  168. passive( false )
  169. {
  170. }
  171. KeyBindingMap_t::KeyBindingMap_t( const KeyBindingMap_t& src )
  172. {
  173. bindingname = src.bindingname;
  174. helpstring = src.helpstring;
  175. docstring = src.docstring;
  176. func = src.func;
  177. passive = src.passive;
  178. }
  179. KeyBindingMap_t::~KeyBindingMap_t()
  180. {
  181. }
  182. class CKeyBindingsMgr
  183. {
  184. public:
  185. CKeyBindingsMgr() :
  186. m_Bindings( 0, 0, KeyBindingContextHandleLessFunc ),
  187. m_nKeyBindingContexts( 0 )
  188. {
  189. }
  190. struct KBContext_t
  191. {
  192. KBContext_t() :
  193. m_KeyBindingsFile( UTL_INVAL_SYMBOL ),
  194. m_KeyBindingsPathID( UTL_INVAL_SYMBOL )
  195. {
  196. m_Handle = INVALID_KEYBINDINGCONTEXT_HANDLE;
  197. }
  198. KBContext_t( const KBContext_t& src )
  199. {
  200. m_Handle = src.m_Handle;
  201. m_KeyBindingsFile = src.m_KeyBindingsFile;
  202. m_KeyBindingsPathID = src.m_KeyBindingsPathID;
  203. int c = src.m_Panels.Count();
  204. for ( int i = 0; i < c; ++i )
  205. {
  206. m_Panels.AddToTail( src.m_Panels[ i ] );
  207. }
  208. }
  209. KeyBindingContextHandle_t m_Handle;
  210. CUtlSymbol m_KeyBindingsFile;
  211. CUtlSymbol m_KeyBindingsPathID;
  212. CUtlVector< Panel * > m_Panels;
  213. };
  214. static bool KeyBindingContextHandleLessFunc( const KBContext_t& lhs, const KBContext_t& rhs )
  215. {
  216. return lhs.m_Handle < rhs.m_Handle;
  217. }
  218. KeyBindingContextHandle_t CreateContext( char const *filename, char const *pathID )
  219. {
  220. KBContext_t entry;
  221. entry.m_Handle = (KeyBindingContextHandle_t)++m_nKeyBindingContexts;
  222. entry.m_KeyBindingsFile = filename;
  223. if ( pathID )
  224. {
  225. entry.m_KeyBindingsPathID = pathID;
  226. }
  227. else
  228. {
  229. entry.m_KeyBindingsPathID = UTL_INVAL_SYMBOL;
  230. }
  231. m_Bindings.Insert( entry );
  232. return entry.m_Handle;
  233. }
  234. void AddPanelToContext( KeyBindingContextHandle_t handle, Panel *panel )
  235. {
  236. if ( !panel->GetName() || !panel->GetName()[ 0 ] )
  237. {
  238. Warning( "Can't add Keybindings Context for unnamed panels\n" );
  239. return;
  240. }
  241. KBContext_t *entry = Find( handle );
  242. Assert( entry );
  243. if ( entry )
  244. {
  245. int idx = entry->m_Panels.Find( panel );
  246. if ( idx == entry->m_Panels.InvalidIndex() )
  247. {
  248. entry->m_Panels.AddToTail( panel );
  249. }
  250. }
  251. }
  252. void OnPanelDeleted( KeyBindingContextHandle_t handle, Panel *panel )
  253. {
  254. KBContext_t *kb = Find( handle );
  255. if ( kb )
  256. {
  257. kb->m_Panels.FindAndRemove( panel );
  258. }
  259. }
  260. KBContext_t *Find( KeyBindingContextHandle_t handle )
  261. {
  262. KBContext_t search;
  263. search.m_Handle = handle;
  264. int idx = m_Bindings.Find( search );
  265. if ( idx == m_Bindings.InvalidIndex() )
  266. {
  267. return NULL;
  268. }
  269. return &m_Bindings[ idx ];
  270. }
  271. char const *GetKeyBindingsFile( KeyBindingContextHandle_t handle )
  272. {
  273. KBContext_t *kb = Find( handle );
  274. if ( kb )
  275. {
  276. return kb->m_KeyBindingsFile.String();
  277. }
  278. Assert( 0 );
  279. return "";
  280. }
  281. char const *GetKeyBindingsFilePathID( KeyBindingContextHandle_t handle )
  282. {
  283. KBContext_t *kb = Find( handle );
  284. if ( kb )
  285. {
  286. return kb->m_KeyBindingsPathID.String();
  287. }
  288. Assert( 0 );
  289. return NULL;
  290. }
  291. int GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle )
  292. {
  293. KBContext_t *kb = Find( handle );
  294. if ( kb )
  295. {
  296. return kb->m_Panels.Count();
  297. }
  298. Assert( 0 );
  299. return 0;
  300. }
  301. //-----------------------------------------------------------------------------
  302. // Purpose: static method
  303. // Input : index -
  304. // Output : Panel
  305. //-----------------------------------------------------------------------------
  306. Panel *GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index )
  307. {
  308. KBContext_t *kb = Find( handle );
  309. if ( kb )
  310. {
  311. Assert( index >= 0 && index < kb->m_Panels.Count() );
  312. return kb->m_Panels[ index ];
  313. }
  314. Assert( 0 );
  315. return 0;
  316. }
  317. CUtlRBTree< KBContext_t, int > m_Bindings;
  318. int m_nKeyBindingContexts;
  319. };
  320. static CKeyBindingsMgr g_KBMgr;
  321. //-----------------------------------------------------------------------------
  322. // Purpose: Static method to allocate a context
  323. // Input : -
  324. // Output : KeyBindingContextHandle_t
  325. //-----------------------------------------------------------------------------
  326. KeyBindingContextHandle_t Panel::CreateKeyBindingsContext( char const *filename, char const *pathID /*=0*/ )
  327. {
  328. return g_KBMgr.CreateContext( filename, pathID );
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Purpose: static method
  332. // Input : -
  333. // Output : int
  334. //-----------------------------------------------------------------------------
  335. int Panel::GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle )
  336. {
  337. return g_KBMgr.GetPanelsWithKeyBindingsCount( handle );
  338. }
  339. //-----------------------------------------------------------------------------
  340. // Purpose: static method
  341. // Input : index -
  342. // Output : Panel
  343. //-----------------------------------------------------------------------------
  344. Panel *Panel::GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index )
  345. {
  346. return g_KBMgr.GetPanelWithKeyBindings( handle, index );
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Returns the number of keybindings
  350. //-----------------------------------------------------------------------------
  351. int Panel::GetKeyMappingCount( )
  352. {
  353. int nCount = 0;
  354. PanelKeyBindingMap *map = GetKBMap();
  355. while ( map )
  356. {
  357. nCount += map->entries.Count();
  358. map = map->baseMap;
  359. }
  360. return nCount;
  361. }
  362. //-----------------------------------------------------------------------------
  363. // Purpose: static method. Reverts key bindings for all registered panels (panels with keybindings actually
  364. // loaded from file
  365. // Input : -
  366. //-----------------------------------------------------------------------------
  367. void Panel::RevertKeyBindings( KeyBindingContextHandle_t handle )
  368. {
  369. int c = GetPanelsWithKeyBindingsCount( handle );
  370. for ( int i = 0; i < c; ++i )
  371. {
  372. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  373. Assert( kbPanel );
  374. kbPanel->RevertKeyBindingsToDefault();
  375. }
  376. }
  377. static void BufPrint( CUtlBuffer& buf, int level, char const *fmt, ... )
  378. {
  379. char string[ 2048 ];
  380. va_list argptr;
  381. va_start( argptr, fmt );
  382. _vsnprintf( string, sizeof( string ) - 1, fmt, argptr );
  383. va_end( argptr );
  384. string[ sizeof( string ) - 1 ] = 0;
  385. while ( --level >= 0 )
  386. {
  387. buf.Printf( " " );
  388. }
  389. buf.Printf( "%s", string );
  390. }
  391. //-----------------------------------------------------------------------------
  392. // Purpose:
  393. // Input : handle -
  394. //-----------------------------------------------------------------------------
  395. void Panel::SaveKeyBindings( KeyBindingContextHandle_t handle )
  396. {
  397. char const *filename = g_KBMgr.GetKeyBindingsFile( handle );
  398. char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle );
  399. SaveKeyBindingsToFile( handle, filename, pathID );
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Purpose: static method. Saves key binding files out for all keybindings
  403. // Input : -
  404. //-----------------------------------------------------------------------------
  405. void Panel::SaveKeyBindingsToFile( KeyBindingContextHandle_t handle, char const *filename, char const *pathID /*= 0*/ )
  406. {
  407. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  408. BufPrint( buf, 0, "keybindings\n" );
  409. BufPrint( buf, 0, "{\n" );
  410. int c = GetPanelsWithKeyBindingsCount( handle );
  411. for ( int i = 0; i < c; ++i )
  412. {
  413. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  414. Assert( kbPanel );
  415. if ( !kbPanel )
  416. continue;
  417. Assert( kbPanel->GetName() );
  418. Assert( kbPanel->GetName()[ 0 ] );
  419. if ( !kbPanel->GetName() || !kbPanel->GetName()[ 0 ] )
  420. continue;
  421. BufPrint( buf, 1, "\"%s\"\n", kbPanel->GetName() );
  422. BufPrint( buf, 1, "{\n" );
  423. kbPanel->SaveKeyBindingsToBuffer( 2, buf );
  424. BufPrint( buf, 1, "}\n" );
  425. }
  426. BufPrint( buf, 0, "}\n" );
  427. if ( g_pFullFileSystem->FileExists( filename, pathID ) &&
  428. !g_pFullFileSystem->IsFileWritable( filename, pathID ) )
  429. {
  430. Warning( "Panel::SaveKeyBindings '%s' is read-only!!!\n", filename );
  431. }
  432. FileHandle_t h = g_pFullFileSystem->Open( filename, "wb", pathID );
  433. if ( FILESYSTEM_INVALID_HANDLE != h )
  434. {
  435. g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), h );
  436. g_pFullFileSystem->Close( h );
  437. }
  438. }
  439. //-----------------------------------------------------------------------------
  440. // Purpose:
  441. // Input : handle -
  442. // *panelOfInterest -
  443. //-----------------------------------------------------------------------------
  444. void Panel::LoadKeyBindingsForOnePanel( KeyBindingContextHandle_t handle, Panel *panelOfInterest )
  445. {
  446. if ( !panelOfInterest )
  447. return;
  448. if ( !panelOfInterest->GetName() )
  449. return;
  450. if ( !panelOfInterest->GetName()[ 0 ] )
  451. return;
  452. char const *filename = g_KBMgr.GetKeyBindingsFile( handle );
  453. char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle );
  454. KeyValues *kv = new KeyValues( "keybindings" );
  455. if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) )
  456. {
  457. int c = GetPanelsWithKeyBindingsCount( handle );
  458. for ( int i = 0; i < c; ++i )
  459. {
  460. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  461. Assert( kbPanel );
  462. char const *panelName = kbPanel->GetName();
  463. if ( !panelName )
  464. {
  465. continue;
  466. }
  467. if ( Q_stricmp( panelOfInterest->GetName(), panelName ) )
  468. continue;
  469. KeyValues *subKey = kv->FindKey( panelName, false );
  470. if ( !subKey )
  471. {
  472. Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName );
  473. continue;
  474. }
  475. kbPanel->ParseKeyBindings( subKey );
  476. }
  477. }
  478. kv->deleteThis();
  479. }
  480. //-----------------------------------------------------------------------------
  481. // Purpose: static method. Loads all key bindings again
  482. // Input : -
  483. //-----------------------------------------------------------------------------
  484. void Panel::ReloadKeyBindings( KeyBindingContextHandle_t handle )
  485. {
  486. char const *filename = g_KBMgr.GetKeyBindingsFile( handle );
  487. char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle );
  488. KeyValues *kv = new KeyValues( "keybindings" );
  489. if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) )
  490. {
  491. int c = GetPanelsWithKeyBindingsCount( handle );
  492. for ( int i = 0; i < c; ++i )
  493. {
  494. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  495. Assert( kbPanel );
  496. char const *panelName = kbPanel->GetName();
  497. if ( !panelName )
  498. {
  499. continue;
  500. }
  501. KeyValues *subKey = kv->FindKey( panelName, false );
  502. if ( !subKey )
  503. {
  504. Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName );
  505. continue;
  506. }
  507. kbPanel->ParseKeyBindings( subKey );
  508. }
  509. }
  510. kv->deleteThis();
  511. }
  512. #endif // VGUI_USEKEYBINDINGMAPS
  513. DECLARE_BUILD_FACTORY( Panel );
  514. //-----------------------------------------------------------------------------
  515. // Purpose: Constructor
  516. //-----------------------------------------------------------------------------
  517. Panel::Panel()
  518. {
  519. Init(0, 0, 64, 24);
  520. }
  521. //-----------------------------------------------------------------------------
  522. // Purpose: Constructor
  523. //-----------------------------------------------------------------------------
  524. Panel::Panel(Panel *parent)
  525. {
  526. Init(0, 0, 64, 24);
  527. SetParent(parent);
  528. }
  529. //-----------------------------------------------------------------------------
  530. // Purpose: Constructor
  531. //-----------------------------------------------------------------------------
  532. Panel::Panel(Panel *parent, const char *panelName)
  533. {
  534. Init(0, 0, 64, 24);
  535. SetName(panelName);
  536. SetParent(parent);
  537. SetBuildModeEditable(true);
  538. }
  539. //-----------------------------------------------------------------------------
  540. // Purpose: Constructor
  541. //-----------------------------------------------------------------------------
  542. Panel::Panel( Panel *parent, const char *panelName, HScheme scheme )
  543. {
  544. Init(0, 0, 64, 24);
  545. SetName(panelName);
  546. SetParent(parent);
  547. SetBuildModeEditable(true);
  548. SetScheme( scheme );
  549. }
  550. //-----------------------------------------------------------------------------
  551. // Purpose: Setup
  552. //-----------------------------------------------------------------------------
  553. void Panel::Init( int x, int y, int wide, int tall )
  554. {
  555. SetName("");
  556. _tooltipText = NULL;
  557. _pinToSibling = NULL;
  558. _pinCornerToSibling = PIN_TOPLEFT;
  559. _pinToSiblingCorner = PIN_TOPLEFT;
  560. // get ourselves an internal panel
  561. _vpanel = ivgui()->AllocPanel();
  562. ipanel()->Init(_vpanel, this);
  563. SetPos(x, y);
  564. SetSize(wide, tall);
  565. _flags.SetFlag( NEEDS_LAYOUT | NEEDS_SCHEME_UPDATE | NEEDS_DEFAULT_SETTINGS_APPLIED );
  566. _flags.SetFlag( AUTODELETE_ENABLED | PAINT_BORDER_ENABLED | PAINT_BACKGROUND_ENABLED | PAINT_ENABLED );
  567. #if defined( VGUI_USEKEYBINDINGMAPS )
  568. _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT );
  569. #endif
  570. m_nPinDeltaX = m_nPinDeltaY = 0;
  571. m_nResizeDeltaX = m_nResizeDeltaY = 0;
  572. _autoResizeDirection = AUTORESIZE_NO;
  573. _pinCorner = PIN_NO;
  574. _cursor = dc_arrow;
  575. _border = NULL;
  576. _buildGroup = UTLHANDLE_INVALID;
  577. _tabPosition = 0;
  578. m_iScheme = 0;
  579. m_bIsSilent = false;
  580. _buildModeFlags = 0; // not editable or deletable in buildmode dialog by default
  581. m_pTooltips = NULL;
  582. m_bToolTipOverridden = false;
  583. m_flAlpha = 255.0f;
  584. m_nPaintBackgroundType = 0;
  585. //=============================================================================
  586. // HPE_BEGIN:
  587. // [tj] Default to rounding all corners (for draw style 2)
  588. //=============================================================================
  589. m_roundedCorners = PANEL_ROUND_CORNER_ALL;
  590. //=============================================================================
  591. // HPE_END
  592. //=============================================================================
  593. m_nBgTextureId1 = -1;
  594. m_nBgTextureId2 = -1;
  595. m_nBgTextureId3 = -1;
  596. m_nBgTextureId4 = -1;
  597. #if defined( VGUI_USEDRAGDROP )
  598. m_pDragDrop = new DragDrop_t;
  599. #endif
  600. m_lLastDoublePressTime = 0L;
  601. #if defined( VGUI_USEKEYBINDINGMAPS )
  602. m_hKeyBindingsContext = INVALID_KEYBINDINGCONTEXT_HANDLE;
  603. #endif
  604. m_bUseSchemeColors = true;
  605. m_bIsDMXSerialized = false;
  606. REGISTER_COLOR_AS_OVERRIDABLE( _fgColor, "fgcolor_override" );
  607. REGISTER_COLOR_AS_OVERRIDABLE( _bgColor, "bgcolor_override" );
  608. m_bIsConsoleStylePanel = false;
  609. m_NavUp = NULL;
  610. m_NavDown = NULL;
  611. m_NavLeft = NULL;
  612. m_NavRight = NULL;
  613. m_sNavUpName = NULL;
  614. m_sNavDownName = NULL;
  615. m_sNavLeftName = NULL;
  616. m_sNavRightName = NULL;
  617. m_PassUnhandledInput = true;
  618. m_LastNavDirection = ND_NONE;
  619. m_pSizer = NULL;
  620. m_bWorldPositionCurrentFrame = false;
  621. }
  622. //-----------------------------------------------------------------------------
  623. // Purpose: Destructor
  624. //-----------------------------------------------------------------------------
  625. Panel::~Panel()
  626. {
  627. // @note Tom Bui: can only delete this if we haven't overridden it
  628. if ( !m_bToolTipOverridden )
  629. {
  630. delete m_pTooltips;
  631. m_pTooltips = NULL;
  632. }
  633. #if defined( VGUI_USEKEYBINDINGMAPS )
  634. if ( IsValidKeyBindingsContext() )
  635. {
  636. g_KBMgr.OnPanelDeleted( m_hKeyBindingsContext, this );
  637. }
  638. #endif // VGUI_USEKEYBINDINGMAPS
  639. #if defined( VGUI_USEDRAGDROP )
  640. if ( m_pDragDrop->m_bDragging )
  641. {
  642. OnFinishDragging( false, (MouseCode)-1 );
  643. }
  644. #endif // VGUI_USEDRAGDROP
  645. _flags.ClearFlag( AUTODELETE_ENABLED );
  646. _flags.SetFlag( MARKED_FOR_DELETION );
  647. // remove panel from any list
  648. SetParent((VPANEL)NULL);
  649. // Stop our children from pointing at us, and delete them if possible
  650. while (ipanel()->GetChildCount(GetVPanel()))
  651. {
  652. VPANEL child = ipanel()->GetChild(GetVPanel(), 0);
  653. if (ipanel()->IsAutoDeleteSet(child))
  654. {
  655. ipanel()->DeletePanel(child);
  656. }
  657. else
  658. {
  659. ipanel()->SetParent(child, NULL);
  660. }
  661. }
  662. // delete VPanel
  663. ivgui()->FreePanel(_vpanel);
  664. delete [] _pinToSibling;
  665. _vpanel = NULL;
  666. #if defined( VGUI_USEDRAGDROP )
  667. delete m_pDragDrop;
  668. #endif // VGUI_USEDRAGDROP
  669. delete m_pSizer;
  670. }
  671. //-----------------------------------------------------------------------------
  672. // Purpose: fully construct this panel so its ready for use right now (i.e fonts loaded, colors set, default label text set, ...)
  673. //-----------------------------------------------------------------------------
  674. void Panel::MakeReadyForUse()
  675. {
  676. // PerformApplySchemeSettings();
  677. UpdateSiblingPin();
  678. surface()->SolveTraverse( GetVPanel(), true );
  679. }
  680. //-----------------------------------------------------------------------------
  681. // Purpose:
  682. //-----------------------------------------------------------------------------
  683. void Panel::SetName( const char *panelName )
  684. {
  685. _panelName = panelName;
  686. }
  687. //-----------------------------------------------------------------------------
  688. // Purpose: returns the given name of the panel
  689. //-----------------------------------------------------------------------------
  690. const char *Panel::GetName()
  691. {
  692. return _panelName.Get();
  693. }
  694. //-----------------------------------------------------------------------------
  695. // Purpose: returns the name of the module that this instance of panel was compiled into
  696. //-----------------------------------------------------------------------------
  697. const char *Panel::GetModuleName()
  698. {
  699. return vgui::GetControlsModuleName();
  700. }
  701. //-----------------------------------------------------------------------------
  702. // Purpose: returns the classname of the panel (as specified in the panelmaps)
  703. //-----------------------------------------------------------------------------
  704. const char *Panel::GetClassName()
  705. {
  706. // loop up the panel map name
  707. PanelMessageMap *panelMap = GetMessageMap();
  708. if ( panelMap )
  709. {
  710. return panelMap->pfnClassName();
  711. }
  712. return "Panel";
  713. }
  714. //-----------------------------------------------------------------------------
  715. // Purpose:
  716. //-----------------------------------------------------------------------------
  717. void Panel::SetPos(int x, int y)
  718. {
  719. Assert( abs(x) < 32768 && abs(y) < 32768 );
  720. ipanel()->SetPos(GetVPanel(), x, y);
  721. }
  722. //-----------------------------------------------------------------------------
  723. // Purpose:
  724. //-----------------------------------------------------------------------------
  725. void Panel::GetPos(int &x, int &y)
  726. {
  727. ipanel()->GetPos(GetVPanel(), x, y);
  728. }
  729. //-----------------------------------------------------------------------------
  730. // Purpose:
  731. //-----------------------------------------------------------------------------
  732. void Panel::SetSize(int wide, int tall)
  733. {
  734. Assert( abs(wide) < 32768 && abs(tall) < 32768 );
  735. ipanel()->SetSize(GetVPanel(), wide, tall);
  736. }
  737. //-----------------------------------------------------------------------------
  738. // Purpose:
  739. //-----------------------------------------------------------------------------
  740. void Panel::GetSize(int &wide, int &tall)
  741. {
  742. ipanel()->GetSize(GetVPanel(), wide, tall);
  743. }
  744. //-----------------------------------------------------------------------------
  745. // Purpose:
  746. //-----------------------------------------------------------------------------
  747. void Panel::SetBounds(int x, int y, int wide, int tall)
  748. {
  749. SetPos(x,y);
  750. SetSize(wide,tall);
  751. }
  752. //-----------------------------------------------------------------------------
  753. // Purpose:
  754. //-----------------------------------------------------------------------------
  755. void Panel::GetBounds(int &x, int &y, int &wide, int &tall)
  756. {
  757. GetPos(x, y);
  758. GetSize(wide, tall);
  759. }
  760. //-----------------------------------------------------------------------------
  761. // Purpose: returns safe handle to parent
  762. //-----------------------------------------------------------------------------
  763. VPANEL Panel::GetVParent()
  764. {
  765. if ( ipanel() )
  766. {
  767. return ipanel()->GetParent(GetVPanel());
  768. }
  769. return 0;
  770. }
  771. //-----------------------------------------------------------------------------
  772. // Purpose: returns a pointer to a controls version of a Panel pointer
  773. //-----------------------------------------------------------------------------
  774. Panel *Panel::GetParent()
  775. {
  776. // get the parent and convert it to a Panel *
  777. // this is OK, the hierarchy is guaranteed to be all from the same module, except for the root node
  778. // the root node always returns NULL when a GetParent() is done so everything is OK
  779. if ( ipanel() )
  780. {
  781. VPANEL parent = ipanel()->GetParent(GetVPanel());
  782. if (parent)
  783. {
  784. Panel *pParent = ipanel()->GetPanel(parent, GetControlsModuleName());
  785. Assert(!pParent || !strcmp(pParent->GetModuleName(), GetControlsModuleName()));
  786. return pParent;
  787. }
  788. }
  789. return NULL;
  790. }
  791. //-----------------------------------------------------------------------------
  792. // Purpose: Screen size change notification handler
  793. //-----------------------------------------------------------------------------
  794. void Panel::OnScreenSizeChanged(int nOldWide, int nOldTall)
  795. {
  796. // post to all children
  797. for (int i = 0; i < ipanel()->GetChildCount(GetVPanel()); i++)
  798. {
  799. VPANEL child = ipanel()->GetChild(GetVPanel(), i);
  800. PostMessage(child, new KeyValues("OnScreenSizeChanged", "oldwide", nOldWide, "oldtall", nOldTall), NULL);
  801. }
  802. // make any currently fullsize window stay fullsize
  803. int x, y, wide, tall;
  804. GetBounds(x, y, wide, tall);
  805. int screenWide, screenTall;
  806. surface()->GetScreenSize(screenWide, screenTall);
  807. if (x == 0 && y == 0 && nOldWide == wide && tall == nOldTall)
  808. {
  809. // fullsize
  810. surface()->GetScreenSize(wide, tall);
  811. SetBounds(0, 0, wide, tall);
  812. }
  813. // panel needs to re-get it's scheme settings
  814. _flags.SetFlag( NEEDS_SCHEME_UPDATE );
  815. // invalidate our settings
  816. InvalidateLayout();
  817. }
  818. //-----------------------------------------------------------------------------
  819. // Purpose:
  820. //-----------------------------------------------------------------------------
  821. void Panel::SetVisible(bool state)
  822. {
  823. ipanel()->SetVisible(GetVPanel(), state);
  824. }
  825. //-----------------------------------------------------------------------------
  826. // Purpose:
  827. //-----------------------------------------------------------------------------
  828. bool Panel::IsVisible()
  829. {
  830. if (ipanel())
  831. {
  832. return ipanel()->IsVisible(GetVPanel());
  833. }
  834. return false;
  835. }
  836. //-----------------------------------------------------------------------------
  837. // Purpose:
  838. //-----------------------------------------------------------------------------
  839. bool Panel::IsFullyVisible()
  840. {
  841. return ipanel()->IsFullyVisible(GetVPanel());
  842. }
  843. //-----------------------------------------------------------------------------
  844. // Purpose:
  845. //-----------------------------------------------------------------------------
  846. void Panel::SetEnabled(bool state)
  847. {
  848. if (state != ipanel()->IsEnabled( GetVPanel()))
  849. {
  850. ipanel()->SetEnabled(GetVPanel(), state);
  851. InvalidateLayout(false);
  852. Repaint();
  853. }
  854. }
  855. //-----------------------------------------------------------------------------
  856. // Purpose:
  857. //-----------------------------------------------------------------------------
  858. bool Panel::IsEnabled()
  859. {
  860. return ipanel()->IsEnabled(GetVPanel());
  861. }
  862. //-----------------------------------------------------------------------------
  863. // Purpose:
  864. //-----------------------------------------------------------------------------
  865. bool Panel::IsPopup()
  866. {
  867. return ipanel()->IsPopup(GetVPanel());
  868. }
  869. //-----------------------------------------------------------------------------
  870. // Purpose:
  871. //-----------------------------------------------------------------------------
  872. void Panel::Repaint()
  873. {
  874. _flags.SetFlag( NEEDS_REPAINT );
  875. if (surface())
  876. {
  877. surface()->Invalidate(GetVPanel());
  878. }
  879. }
  880. //-----------------------------------------------------------------------------
  881. // Purpose:
  882. //-----------------------------------------------------------------------------
  883. void Panel::Think()
  884. {
  885. if (IsVisible())
  886. {
  887. // update any tooltips
  888. if (m_pTooltips)
  889. {
  890. m_pTooltips->PerformLayout();
  891. }
  892. if ( _flags.IsFlagSet( NEEDS_LAYOUT ) )
  893. {
  894. InternalPerformLayout();
  895. }
  896. }
  897. OnThink();
  898. }
  899. //-----------------------------------------------------------------------------
  900. // Purpose:
  901. //-----------------------------------------------------------------------------
  902. void Panel::PaintTraverse( bool repaint, bool allowForce )
  903. {
  904. if ( m_bWorldPositionCurrentFrame )
  905. {
  906. surface()->SolveTraverse( GetVPanel() );
  907. }
  908. if ( !IsVisible() )
  909. {
  910. return;
  911. }
  912. float oldAlphaMultiplier = surface()->DrawGetAlphaMultiplier();
  913. float newAlphaMultiplier = oldAlphaMultiplier * m_flAlpha * 1.0f/255.0f;
  914. if ( !repaint &&
  915. allowForce &&
  916. _flags.IsFlagSet( NEEDS_REPAINT ) )
  917. {
  918. repaint = true;
  919. _flags.ClearFlag( NEEDS_REPAINT );
  920. }
  921. VPANEL vpanel = GetVPanel();
  922. int clipRect[4];
  923. ipanel()->GetClipRect( vpanel, clipRect[0], clipRect[1], clipRect[2], clipRect[3] );
  924. if ( ( clipRect[2] <= clipRect[0] ) || ( clipRect[3] <= clipRect[1] ) )
  925. {
  926. repaint = false;
  927. }
  928. // set global alpha
  929. surface()->DrawSetAlphaMultiplier( newAlphaMultiplier );
  930. bool bBorderPaintFirst = _border ? _border->PaintFirst() : false;
  931. // draw the border first if requested to
  932. if ( bBorderPaintFirst && repaint && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != 0 ) )
  933. {
  934. // Paint the border over the background with no inset
  935. surface()->PushMakeCurrent( vpanel, false );
  936. PaintBorder();
  937. surface()->PopMakeCurrent( vpanel );
  938. }
  939. if ( repaint )
  940. {
  941. // draw the background with no inset
  942. if ( _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) )
  943. {
  944. surface()->PushMakeCurrent( vpanel, false );
  945. PaintBackground();
  946. surface()->PopMakeCurrent( vpanel );
  947. }
  948. // draw the front of the panel with the inset
  949. if ( _flags.IsFlagSet( PAINT_ENABLED ) )
  950. {
  951. surface()->PushMakeCurrent( vpanel, true );
  952. Paint();
  953. surface()->PopMakeCurrent( vpanel );
  954. }
  955. }
  956. // traverse and paint all our children
  957. CUtlVector< VPANEL > &children = ipanel()->GetChildren( vpanel );
  958. int childCount = children.Count();
  959. for (int i = 0; i < childCount; i++)
  960. {
  961. VPANEL child = children[ i ];
  962. bool bVisible = ipanel()->IsVisible( child );
  963. if ( bVisible && surface()->ShouldPaintChildPanel( child ) )
  964. {
  965. ipanel()->PaintTraverse( child, repaint, allowForce );
  966. }
  967. else
  968. {
  969. // Invalidate the child panel so that it gets redrawn
  970. surface()->Invalidate( child );
  971. // keep traversing the tree, just don't allow anyone to paint after here
  972. if ( bVisible )
  973. {
  974. ipanel()->PaintTraverse( child, false, false );
  975. }
  976. }
  977. }
  978. // draw the border last
  979. if ( repaint )
  980. {
  981. if ( !bBorderPaintFirst && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != 0 ) )
  982. {
  983. // Paint the border over the background with no inset
  984. surface()->PushMakeCurrent( vpanel, false );
  985. PaintBorder();
  986. surface()->PopMakeCurrent( vpanel );
  987. }
  988. #ifdef _DEBUG
  989. // IsBuildGroupEnabled() is a recursive call up the parent chain, so don't do this in release
  990. if ( GetBuildModeDialogCount() && IsBuildGroupEnabled() )
  991. {
  992. // outline all selected panels
  993. CUtlVector<PHandle> *controlGroup = _buildGroup->GetControlGroup();
  994. for (int i=0; i < controlGroup->Count(); ++i)
  995. {
  996. surface()->PushMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel(), false );
  997. ((*controlGroup)[i].Get())->PaintBuildOverlay();
  998. surface()->PopMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel() );
  999. }
  1000. _buildGroup->DrawRulers();
  1001. }
  1002. #endif
  1003. // All of our children have painted, etc, now allow painting in top of them
  1004. if ( _flags.IsFlagSet( POST_CHILD_PAINT_ENABLED ) )
  1005. {
  1006. surface()->PushMakeCurrent( vpanel, false );
  1007. PostChildPaint();
  1008. surface()->PopMakeCurrent( vpanel );
  1009. }
  1010. }
  1011. surface()->DrawSetAlphaMultiplier( oldAlphaMultiplier );
  1012. surface()->SwapBuffers( vpanel );
  1013. }
  1014. //-----------------------------------------------------------------------------
  1015. // Purpose:
  1016. //-----------------------------------------------------------------------------
  1017. void Panel::PaintBorder()
  1018. {
  1019. _border->Paint(GetVPanel());
  1020. }
  1021. //-----------------------------------------------------------------------------
  1022. // Purpose:
  1023. //-----------------------------------------------------------------------------
  1024. void Panel::PaintBackground()
  1025. {
  1026. int wide, tall;
  1027. GetSize( wide, tall );
  1028. if ( m_SkipChild.Get() && m_SkipChild->IsVisible() )
  1029. {
  1030. if ( GetPaintBackgroundType() == 2 )
  1031. {
  1032. int cornerWide, cornerTall;
  1033. GetCornerTextureSize( cornerWide, cornerTall );
  1034. Color col = GetBgColor();
  1035. DrawHollowBox( 0, 0, wide, tall, col, 1.0f );
  1036. wide -= 2 * cornerWide;
  1037. tall -= 2 * cornerTall;
  1038. FillRectSkippingPanel( GetBgColor(), cornerWide, cornerTall, wide, tall, m_SkipChild.Get() );
  1039. }
  1040. else
  1041. {
  1042. FillRectSkippingPanel( GetBgColor(), 0, 0, wide, tall, m_SkipChild.Get() );
  1043. }
  1044. }
  1045. else
  1046. {
  1047. Color col = GetBgColor();
  1048. switch ( m_nPaintBackgroundType )
  1049. {
  1050. default:
  1051. case 0:
  1052. {
  1053. surface()->DrawSetColor(col);
  1054. surface()->DrawFilledRect(0, 0, wide, tall);
  1055. }
  1056. break;
  1057. case 1:
  1058. {
  1059. DrawTexturedBox( 0, 0, wide, tall, col, 1.0f );
  1060. }
  1061. break;
  1062. case 2:
  1063. {
  1064. DrawBox( 0, 0, wide, tall, col, 1.0f );
  1065. }
  1066. break;
  1067. case 3:
  1068. {
  1069. DrawBoxFade( 0, 0, wide, tall, col, 1.0f, 255, 0, true );
  1070. }
  1071. break;
  1072. }
  1073. }
  1074. }
  1075. //-----------------------------------------------------------------------------
  1076. // Purpose:
  1077. //-----------------------------------------------------------------------------
  1078. void Panel::Paint()
  1079. {
  1080. // empty on purpose
  1081. // PaintBackground is painted and default behavior is for Paint to do nothing
  1082. }
  1083. //-----------------------------------------------------------------------------
  1084. // Purpose:
  1085. //-----------------------------------------------------------------------------
  1086. void Panel::PostChildPaint()
  1087. {
  1088. // Empty on purpose
  1089. // This is called if _postChildPaintEnabled is true and allows painting to
  1090. // continue on the surface after all of the panel's children have painted
  1091. // themselves. Allows drawing an overlay on top of the children, etc.
  1092. }
  1093. //-----------------------------------------------------------------------------
  1094. // Purpose: Draws a black rectangle around the panel.
  1095. //-----------------------------------------------------------------------------
  1096. void Panel::PaintBuildOverlay()
  1097. {
  1098. int wide,tall;
  1099. GetSize(wide,tall);
  1100. surface()->DrawSetColor(0, 0, 0, 255);
  1101. surface()->DrawFilledRect(0,0,wide,2); //top
  1102. surface()->DrawFilledRect(0,tall-2,wide,tall); //bottom
  1103. surface()->DrawFilledRect(0,2,2,tall-2); //left
  1104. surface()->DrawFilledRect(wide-2,2,wide,tall-2); //right
  1105. }
  1106. //-----------------------------------------------------------------------------
  1107. // Purpose: Returns true if the panel's draw code will fully cover it's area
  1108. //-----------------------------------------------------------------------------
  1109. bool Panel::IsOpaque()
  1110. {
  1111. // FIXME: Add code to account for the 'SkipChild' functionality in Frame
  1112. if ( IsVisible() && _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) && ( _bgColor[3] == 255 ) )
  1113. return true;
  1114. return false;
  1115. }
  1116. //-----------------------------------------------------------------------------
  1117. // Purpose: returns true if the settings are aligned to the right of the screen
  1118. //-----------------------------------------------------------------------------
  1119. bool Panel::IsRightAligned()
  1120. {
  1121. return (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED) ? true : false;
  1122. }
  1123. //-----------------------------------------------------------------------------
  1124. // Purpose: returns true if the settings are aligned to the bottom of the screen
  1125. //-----------------------------------------------------------------------------
  1126. bool Panel::IsBottomAligned()
  1127. {
  1128. return (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED) ? true : false;
  1129. }
  1130. //-----------------------------------------------------------------------------
  1131. // Purpose: returns true if the settings are a percentage of screen size
  1132. //-----------------------------------------------------------------------------
  1133. bool Panel::IsPercentage()
  1134. {
  1135. return ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE ) ? true : false;
  1136. }
  1137. //-----------------------------------------------------------------------------
  1138. // Purpose: sets the parent
  1139. //-----------------------------------------------------------------------------
  1140. void Panel::SetParent(Panel *newParent)
  1141. {
  1142. // Assert that the parent is from the same module as the child
  1143. // FIXME: !!! work out how to handle this properly!
  1144. // Assert(!newParent || !strcmp(newParent->GetModuleName(), GetControlsModuleName()));
  1145. if (newParent)
  1146. {
  1147. SetParent(newParent->GetVPanel());
  1148. }
  1149. else
  1150. {
  1151. SetParent((VPANEL)NULL);
  1152. }
  1153. }
  1154. //-----------------------------------------------------------------------------
  1155. // Purpose:
  1156. //-----------------------------------------------------------------------------
  1157. void Panel::SetParent(VPANEL newParent)
  1158. {
  1159. if (newParent)
  1160. {
  1161. ipanel()->SetParent(GetVPanel(), newParent);
  1162. }
  1163. else
  1164. {
  1165. ipanel()->SetParent(GetVPanel(), NULL);
  1166. }
  1167. if (GetVParent() && !IsPopup())
  1168. {
  1169. SetProportional(ipanel()->IsProportional(GetVParent()));
  1170. // most of the time KBInput == parents kbinput
  1171. if (ipanel()->IsKeyBoardInputEnabled(GetVParent()) != IsKeyBoardInputEnabled())
  1172. {
  1173. SetKeyBoardInputEnabled(ipanel()->IsKeyBoardInputEnabled(GetVParent()));
  1174. }
  1175. if (ipanel()->IsMouseInputEnabled(GetVParent()) != IsMouseInputEnabled())
  1176. {
  1177. SetMouseInputEnabled(ipanel()->IsMouseInputEnabled(GetVParent()));
  1178. }
  1179. }
  1180. // Our children inherit our context ID marker
  1181. if ( GetVParent() )
  1182. {
  1183. SetMessageContextId_R( ipanel()->GetMessageContextId( GetVParent() ) );
  1184. }
  1185. UpdateSiblingPin();
  1186. }
  1187. // Forces context ID for this panel and all children below it
  1188. void Panel::SetMessageContextId_R( int nContextID )
  1189. {
  1190. ipanel()->SetMessageContextId( GetVPanel(), nContextID );
  1191. for ( int i = 0; i < GetChildCount(); ++i )
  1192. {
  1193. Panel *child = GetChild( i );
  1194. if ( child )
  1195. {
  1196. child->SetMessageContextId_R( nContextID );
  1197. }
  1198. }
  1199. }
  1200. //-----------------------------------------------------------------------------
  1201. // Purpose:
  1202. //-----------------------------------------------------------------------------
  1203. void Panel::OnChildAdded(VPANEL child)
  1204. {
  1205. Assert( !_flags.IsFlagSet( IN_PERFORM_LAYOUT ) );
  1206. }
  1207. //-----------------------------------------------------------------------------
  1208. // Purpose: default message handler
  1209. //-----------------------------------------------------------------------------
  1210. void Panel::OnSizeChanged(int newWide, int newTall)
  1211. {
  1212. InvalidateLayout(); // our size changed so force us to layout again
  1213. }
  1214. //-----------------------------------------------------------------------------
  1215. // Purpose: sets Z ordering - lower numbers are always behind higher z's
  1216. //-----------------------------------------------------------------------------
  1217. void Panel::SetZPos(int z)
  1218. {
  1219. ipanel()->SetZPos(GetVPanel(), z);
  1220. }
  1221. //-----------------------------------------------------------------------------
  1222. // Purpose: sets Z ordering - lower numbers are always behind higher z's
  1223. //-----------------------------------------------------------------------------
  1224. int Panel::GetZPos()
  1225. {
  1226. return ( ipanel()->GetZPos( GetVPanel() ) );
  1227. }
  1228. //-----------------------------------------------------------------------------
  1229. // Purpose: sets alpha modifier for panel and all child panels [0..255]
  1230. //-----------------------------------------------------------------------------
  1231. void Panel::SetAlpha(int alpha)
  1232. {
  1233. m_flAlpha = alpha;
  1234. }
  1235. //-----------------------------------------------------------------------------
  1236. // Purpose: data accessor
  1237. //-----------------------------------------------------------------------------
  1238. int Panel::GetAlpha()
  1239. {
  1240. return (int)m_flAlpha;
  1241. }
  1242. //-----------------------------------------------------------------------------
  1243. // Purpose: Moves the panel to the front of the z-order
  1244. //-----------------------------------------------------------------------------
  1245. void Panel::MoveToFront(void)
  1246. {
  1247. // FIXME: only use ipanel() as per src branch?
  1248. if (IsPopup())
  1249. {
  1250. surface()->BringToFront(GetVPanel());
  1251. }
  1252. else
  1253. {
  1254. ipanel()->MoveToFront(GetVPanel());
  1255. }
  1256. }
  1257. //-----------------------------------------------------------------------------
  1258. // Purpose: Iterates up the hierarchy looking for a particular parent
  1259. //-----------------------------------------------------------------------------
  1260. bool Panel::HasParent(VPANEL potentialParent)
  1261. {
  1262. if (!potentialParent)
  1263. return false;
  1264. return ipanel()->HasParent(GetVPanel(), potentialParent);
  1265. }
  1266. //-----------------------------------------------------------------------------
  1267. // Purpose: Finds the index of a child panel by string name
  1268. // Output : int - -1 if no panel of that name is found
  1269. //-----------------------------------------------------------------------------
  1270. int Panel::FindChildIndexByName(const char *childName)
  1271. {
  1272. for (int i = 0; i < GetChildCount(); i++)
  1273. {
  1274. Panel *pChild = GetChild(i);
  1275. if (!pChild)
  1276. continue;
  1277. if (!stricmp(pChild->GetName(), childName))
  1278. {
  1279. return i;
  1280. }
  1281. }
  1282. return -1;
  1283. }
  1284. //-----------------------------------------------------------------------------
  1285. // Purpose: Finds a child panel by string name
  1286. // Output : Panel * - NULL if no panel of that name is found
  1287. //-----------------------------------------------------------------------------
  1288. Panel *Panel::FindChildByName(const char *childName, bool recurseDown)
  1289. {
  1290. for (int i = 0; i < GetChildCount(); i++)
  1291. {
  1292. Panel *pChild = GetChild(i);
  1293. if (!pChild)
  1294. continue;
  1295. if (!stricmp(pChild->GetName(), childName))
  1296. {
  1297. return pChild;
  1298. }
  1299. if (recurseDown)
  1300. {
  1301. Panel *panel = pChild->FindChildByName(childName, recurseDown);
  1302. if ( panel )
  1303. {
  1304. return panel;
  1305. }
  1306. }
  1307. }
  1308. return NULL;
  1309. }
  1310. //-----------------------------------------------------------------------------
  1311. // Purpose: Finds a sibling panel by name
  1312. //-----------------------------------------------------------------------------
  1313. Panel *Panel::FindSiblingByName(const char *siblingName)
  1314. {
  1315. if ( !GetVParent() )
  1316. return NULL;
  1317. int siblingCount = ipanel()->GetChildCount(GetVParent());
  1318. for (int i = 0; i < siblingCount; i++)
  1319. {
  1320. VPANEL sibling = ipanel()->GetChild(GetVParent(), i);
  1321. Panel *panel = ipanel()->GetPanel(sibling, GetControlsModuleName());
  1322. if (!stricmp(panel->GetName(), siblingName))
  1323. {
  1324. return panel;
  1325. }
  1326. }
  1327. return NULL;
  1328. }
  1329. //-----------------------------------------------------------------------------
  1330. // Purpose: Dispatches immediately a message to the parent
  1331. //-----------------------------------------------------------------------------
  1332. void Panel::CallParentFunction(KeyValues *message)
  1333. {
  1334. if (GetVParent())
  1335. {
  1336. ipanel()->SendMessage(GetVParent(), message, GetVPanel());
  1337. }
  1338. if (message)
  1339. {
  1340. message->deleteThis();
  1341. }
  1342. }
  1343. //-----------------------------------------------------------------------------
  1344. // Purpose: if set to true, panel automatically frees itself when parent is deleted
  1345. //-----------------------------------------------------------------------------
  1346. void Panel::SetAutoDelete( bool state )
  1347. {
  1348. _flags.SetFlag( AUTODELETE_ENABLED, state );
  1349. }
  1350. //-----------------------------------------------------------------------------
  1351. // Purpose:
  1352. //-----------------------------------------------------------------------------
  1353. bool Panel::IsAutoDeleteSet()
  1354. {
  1355. return _flags.IsFlagSet( AUTODELETE_ENABLED );
  1356. }
  1357. //-----------------------------------------------------------------------------
  1358. // Purpose: Just calls 'delete this'
  1359. //-----------------------------------------------------------------------------
  1360. void Panel::DeletePanel()
  1361. {
  1362. // Avoid re-entrancy
  1363. _flags.SetFlag( MARKED_FOR_DELETION );
  1364. _flags.ClearFlag( AUTODELETE_ENABLED );
  1365. delete this;
  1366. }
  1367. //-----------------------------------------------------------------------------
  1368. // Purpose: data accessor
  1369. //-----------------------------------------------------------------------------
  1370. HScheme Panel::GetScheme()
  1371. {
  1372. if (m_iScheme)
  1373. {
  1374. return m_iScheme; // return our internal scheme
  1375. }
  1376. if (GetVParent()) // recurse down the heirarchy
  1377. {
  1378. return ipanel()->GetScheme(GetVParent());
  1379. }
  1380. return scheme()->GetDefaultScheme();
  1381. }
  1382. //-----------------------------------------------------------------------------
  1383. // Purpose: set the scheme to render this panel with by name
  1384. //-----------------------------------------------------------------------------
  1385. void Panel::SetScheme(const char *tag)
  1386. {
  1387. if (strlen(tag) > 0 && scheme()->GetScheme(tag)) // check the scheme exists
  1388. {
  1389. SetScheme(scheme()->GetScheme(tag));
  1390. }
  1391. }
  1392. //-----------------------------------------------------------------------------
  1393. // Purpose: set the scheme to render this panel with
  1394. //-----------------------------------------------------------------------------
  1395. void Panel::SetScheme(HScheme scheme)
  1396. {
  1397. if (scheme != m_iScheme)
  1398. {
  1399. m_iScheme = scheme;
  1400. // This will cause the new scheme to be applied at a later point
  1401. // InvalidateLayout( false, true );
  1402. }
  1403. }
  1404. //-----------------------------------------------------------------------------
  1405. // Purpose: returns the char of this panels hotkey
  1406. //-----------------------------------------------------------------------------
  1407. Panel *Panel::HasHotkey(wchar_t key)
  1408. {
  1409. return NULL;
  1410. }
  1411. #if defined( VGUI_USEDRAGDROP )
  1412. static vgui::PHandle g_DragDropCapture;
  1413. #endif // VGUI_USEDRAGDROP
  1414. void Panel::InternalCursorMoved(int x, int y)
  1415. {
  1416. #if defined( VGUI_USEDRAGDROP )
  1417. if ( g_DragDropCapture.Get() )
  1418. {
  1419. bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted;
  1420. g_DragDropCapture->OnContinueDragging();
  1421. if ( started )
  1422. {
  1423. bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE );
  1424. if ( isEscapeKeyDown )
  1425. {
  1426. g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1, true );
  1427. }
  1428. return;
  1429. }
  1430. }
  1431. #endif // VGUI_USEDRAGDROP
  1432. if ( !ShouldHandleInputMessage() )
  1433. return;
  1434. if ( IsCursorNone() )
  1435. return;
  1436. if ( !IsMouseInputEnabled() )
  1437. {
  1438. return;
  1439. }
  1440. if (IsBuildGroupEnabled())
  1441. {
  1442. if ( _buildGroup->CursorMoved(x, y, this) )
  1443. {
  1444. return;
  1445. }
  1446. }
  1447. if (m_pTooltips)
  1448. {
  1449. if ( _tooltipText )
  1450. {
  1451. m_pTooltips->SetText( _tooltipText );
  1452. }
  1453. m_pTooltips->ShowTooltip(this);
  1454. }
  1455. ScreenToLocal(x, y);
  1456. OnCursorMoved(x, y);
  1457. }
  1458. void Panel::InternalCursorEntered()
  1459. {
  1460. if (IsCursorNone() || !IsMouseInputEnabled())
  1461. return;
  1462. if (IsBuildGroupEnabled())
  1463. return;
  1464. if (m_pTooltips)
  1465. {
  1466. m_pTooltips->ResetDelay();
  1467. if ( _tooltipText )
  1468. {
  1469. m_pTooltips->SetText( _tooltipText );
  1470. }
  1471. m_pTooltips->ShowTooltip(this);
  1472. }
  1473. OnCursorEntered();
  1474. }
  1475. void Panel::InternalCursorExited()
  1476. {
  1477. if (IsCursorNone() || !IsMouseInputEnabled())
  1478. return;
  1479. if (IsBuildGroupEnabled())
  1480. return;
  1481. if (m_pTooltips)
  1482. {
  1483. m_pTooltips->HideTooltip();
  1484. }
  1485. OnCursorExited();
  1486. }
  1487. bool Panel::IsChildOfSurfaceModalPanel()
  1488. {
  1489. VPANEL appModalPanel = input()->GetAppModalSurface();
  1490. if ( !appModalPanel )
  1491. return true;
  1492. if ( ipanel()->HasParent( GetVPanel(), appModalPanel ) )
  1493. return true;
  1494. return false;
  1495. }
  1496. //-----------------------------------------------------------------------------
  1497. // Purpose:
  1498. // Input : -
  1499. // Output : Returns true on success, false on failure.
  1500. //-----------------------------------------------------------------------------
  1501. bool Panel::IsChildOfModalSubTree()
  1502. {
  1503. VPANEL subTree = input()->GetModalSubTree();
  1504. if ( !subTree )
  1505. return true;
  1506. if ( HasParent( subTree ) )
  1507. return true;
  1508. return false;
  1509. }
  1510. //-----------------------------------------------------------------------------
  1511. // Purpose: Checks to see if message is being subverted due to modal subtree logic
  1512. // Input : -
  1513. // Output : Returns true on success, false on failure.
  1514. //-----------------------------------------------------------------------------
  1515. static bool ShouldHandleInputMessage( VPANEL p )
  1516. {
  1517. // If there is not modal subtree, then always handle the msg
  1518. if ( !input()->GetModalSubTree() )
  1519. return true;
  1520. // What state are we in?
  1521. bool bChildOfModal = false;
  1522. VPANEL subTree = input()->GetModalSubTree();
  1523. if ( !subTree )
  1524. {
  1525. bChildOfModal = true;
  1526. }
  1527. else if ( ipanel()->HasParent( p, subTree ) )
  1528. {
  1529. bChildOfModal = true;
  1530. }
  1531. if ( input()->ShouldModalSubTreeReceiveMessages() )
  1532. return bChildOfModal;
  1533. return !bChildOfModal;
  1534. }
  1535. bool Panel::ShouldHandleInputMessage()
  1536. {
  1537. return ::ShouldHandleInputMessage( GetVPanel() );
  1538. }
  1539. void Panel::InternalMousePressed(int code)
  1540. {
  1541. long curtime = system()->GetTimeMillis();
  1542. if ( IsTriplePressAllowed() )
  1543. {
  1544. long elapsed = curtime - m_lLastDoublePressTime;
  1545. if ( elapsed < TRIPLE_PRESS_MSEC )
  1546. {
  1547. InternalMouseTriplePressed( code );
  1548. return;
  1549. }
  1550. }
  1551. // The menu system passively watches for mouse released messages so it
  1552. // can clear any open menus if the release is somewhere other than on a menu
  1553. Menu::OnInternalMousePressed( this, (MouseCode)code );
  1554. if ( !ShouldHandleInputMessage() )
  1555. return;
  1556. if ( IsCursorNone() )
  1557. return;
  1558. if ( IsKeyBoardInputEnabled() )
  1559. {
  1560. RequestFocus();
  1561. }
  1562. if ( !IsMouseInputEnabled())
  1563. {
  1564. #if defined( VGUI_USEDRAGDROP )
  1565. DragDropStartDragging();
  1566. #endif
  1567. return;
  1568. }
  1569. if (IsBuildGroupEnabled())
  1570. {
  1571. if ( _buildGroup->MousePressed((MouseCode)code, this) )
  1572. {
  1573. return;
  1574. }
  1575. }
  1576. OnMousePressed((MouseCode)code);
  1577. #if defined( VGUI_USEDRAGDROP )
  1578. DragDropStartDragging();
  1579. #endif
  1580. }
  1581. void Panel::InternalMouseDoublePressed(int code)
  1582. {
  1583. m_lLastDoublePressTime = system()->GetTimeMillis();
  1584. if ( !ShouldHandleInputMessage() )
  1585. return;
  1586. if ( IsCursorNone() )
  1587. return;
  1588. if ( !IsMouseInputEnabled())
  1589. {
  1590. return;
  1591. }
  1592. if (IsBuildGroupEnabled())
  1593. {
  1594. if ( _buildGroup->MouseDoublePressed((MouseCode)code, this) )
  1595. {
  1596. return;
  1597. }
  1598. }
  1599. Panel *pMouseHandler = m_hMouseEventHandler.Get();
  1600. if ( pMouseHandler )
  1601. {
  1602. pMouseHandler->OnMouseDoublePressed( (MouseCode)code );
  1603. }
  1604. else
  1605. {
  1606. OnMouseDoublePressed( (MouseCode)code );
  1607. }
  1608. }
  1609. #if defined( VGUI_USEDRAGDROP )
  1610. void Panel::SetStartDragWhenMouseExitsPanel( bool state )
  1611. {
  1612. _flags.SetFlag( DRAG_REQUIRES_PANEL_EXIT, state );
  1613. }
  1614. bool Panel::IsStartDragWhenMouseExitsPanel() const
  1615. {
  1616. return _flags.IsFlagSet( DRAG_REQUIRES_PANEL_EXIT );
  1617. }
  1618. #endif // VGUI_USEDRAGDROP
  1619. void Panel::SetTriplePressAllowed( bool state )
  1620. {
  1621. _flags.SetFlag( TRIPLE_PRESS_ALLOWED, state );
  1622. }
  1623. bool Panel::IsTriplePressAllowed() const
  1624. {
  1625. return _flags.IsFlagSet( TRIPLE_PRESS_ALLOWED );
  1626. }
  1627. void Panel::InternalMouseTriplePressed( int code )
  1628. {
  1629. Assert( IsTriplePressAllowed() );
  1630. m_lLastDoublePressTime = 0L;
  1631. if ( !ShouldHandleInputMessage() )
  1632. return;
  1633. if ( IsCursorNone() )
  1634. return;
  1635. if ( !IsMouseInputEnabled())
  1636. {
  1637. #if defined( VGUI_USEDRAGDROP )
  1638. DragDropStartDragging();
  1639. #endif
  1640. return;
  1641. }
  1642. if (IsBuildGroupEnabled())
  1643. {
  1644. return;
  1645. }
  1646. OnMouseTriplePressed((MouseCode)code);
  1647. #if defined( VGUI_USEDRAGDROP )
  1648. DragDropStartDragging();
  1649. #endif
  1650. }
  1651. void Panel::InternalMouseReleased(int code)
  1652. {
  1653. #if defined( VGUI_USEDRAGDROP )
  1654. if ( g_DragDropCapture.Get() )
  1655. {
  1656. bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted;
  1657. g_DragDropCapture->OnFinishDragging( true, (MouseCode)code );
  1658. if ( started )
  1659. {
  1660. return;
  1661. }
  1662. }
  1663. #endif
  1664. if ( !ShouldHandleInputMessage() )
  1665. return;
  1666. if ( IsCursorNone() )
  1667. return;
  1668. if ( !IsMouseInputEnabled())
  1669. {
  1670. return;
  1671. }
  1672. if (IsBuildGroupEnabled())
  1673. {
  1674. if ( _buildGroup->MouseReleased((MouseCode)code, this) )
  1675. {
  1676. return;
  1677. }
  1678. }
  1679. OnMouseReleased((MouseCode)code);
  1680. }
  1681. void Panel::InternalMouseWheeled(int delta)
  1682. {
  1683. if (IsBuildGroupEnabled() || !IsMouseInputEnabled())
  1684. {
  1685. return;
  1686. }
  1687. if ( !ShouldHandleInputMessage() )
  1688. return;
  1689. OnMouseWheeled(delta);
  1690. }
  1691. void Panel::InternalKeyCodePressed(int code)
  1692. {
  1693. if ( !ShouldHandleInputMessage() )
  1694. return;
  1695. if (IsKeyBoardInputEnabled())
  1696. {
  1697. OnKeyCodePressed((KeyCode)code);
  1698. }
  1699. else
  1700. {
  1701. CallParentFunction(new KeyValues("KeyCodePressed", "code", code));
  1702. }
  1703. }
  1704. #if defined( VGUI_USEKEYBINDINGMAPS )
  1705. //-----------------------------------------------------------------------------
  1706. // Purpose:
  1707. // Input : *bindingName -
  1708. // keycode -
  1709. // modifiers -
  1710. //-----------------------------------------------------------------------------
  1711. void Panel::AddKeyBinding( char const *bindingName, int keycode, int modifiers )
  1712. {
  1713. PanelKeyBindingMap *map = LookupMapForBinding( bindingName );
  1714. if ( !map )
  1715. {
  1716. Assert( 0 );
  1717. return;
  1718. }
  1719. BoundKey_t kb;
  1720. kb.isbuiltin = false;
  1721. kb.bindingname = CopyString( bindingName );
  1722. kb.keycode = keycode;
  1723. kb.modifiers = modifiers;
  1724. map->boundkeys.AddToTail( kb );
  1725. }
  1726. KeyBindingMap_t *Panel::LookupBinding( char const *bindingName )
  1727. {
  1728. PanelKeyBindingMap *map = GetKBMap();
  1729. while( map )
  1730. {
  1731. int c = map->entries.Count();
  1732. for( int i = 0; i < c ; ++i )
  1733. {
  1734. KeyBindingMap_t *binding = &map->entries[ i ];
  1735. if ( !Q_stricmp( binding->bindingname, bindingName ) )
  1736. return binding;
  1737. }
  1738. map = map->baseMap;
  1739. }
  1740. return NULL;
  1741. }
  1742. PanelKeyBindingMap *Panel::LookupMapForBinding( char const *bindingName )
  1743. {
  1744. PanelKeyBindingMap *map = GetKBMap();
  1745. while( map )
  1746. {
  1747. int c = map->entries.Count();
  1748. for( int i = 0; i < c ; ++i )
  1749. {
  1750. KeyBindingMap_t *binding = &map->entries[ i ];
  1751. if ( !Q_stricmp( binding->bindingname, bindingName ) )
  1752. return map;
  1753. }
  1754. map = map->baseMap;
  1755. }
  1756. return NULL;
  1757. }
  1758. KeyBindingMap_t *Panel::LookupBindingByKeyCode( KeyCode code, int modifiers )
  1759. {
  1760. PanelKeyBindingMap *map = GetKBMap();
  1761. while( map )
  1762. {
  1763. int c = map->boundkeys.Count();
  1764. for( int i = 0; i < c ; ++i )
  1765. {
  1766. BoundKey_t *kb = &map->boundkeys[ i ];
  1767. if ( kb->keycode == code && kb->modifiers == modifiers )
  1768. {
  1769. KeyBindingMap_t *binding = LookupBinding( kb->bindingname );
  1770. Assert( binding );
  1771. if ( binding )
  1772. {
  1773. return binding;
  1774. }
  1775. }
  1776. }
  1777. map = map->baseMap;
  1778. }
  1779. return NULL;
  1780. }
  1781. BoundKey_t *Panel::LookupDefaultKey( char const *bindingName )
  1782. {
  1783. PanelKeyBindingMap *map = GetKBMap();
  1784. while( map )
  1785. {
  1786. int c = map->defaultkeys.Count();
  1787. for( int i = 0; i < c ; ++i )
  1788. {
  1789. BoundKey_t *kb = &map->defaultkeys[ i ];
  1790. if ( !Q_stricmp( kb->bindingname, bindingName ) )
  1791. {
  1792. return kb;
  1793. }
  1794. }
  1795. map = map->baseMap;
  1796. }
  1797. return NULL;
  1798. }
  1799. void Panel::LookupBoundKeys( char const *bindingName, CUtlVector< BoundKey_t * >& list )
  1800. {
  1801. PanelKeyBindingMap *map = GetKBMap();
  1802. while( map )
  1803. {
  1804. int c = map->boundkeys.Count();
  1805. for( int i = 0; i < c ; ++i )
  1806. {
  1807. BoundKey_t *kb = &map->boundkeys[ i ];
  1808. if ( !Q_stricmp( kb->bindingname, bindingName ) )
  1809. {
  1810. list.AddToTail( kb );
  1811. }
  1812. }
  1813. map = map->baseMap;
  1814. }
  1815. }
  1816. void Panel::RevertKeyBindingsToDefault()
  1817. {
  1818. PanelKeyBindingMap *map = GetKBMap();
  1819. while( map )
  1820. {
  1821. map->boundkeys.RemoveAll();
  1822. map->boundkeys = map->defaultkeys;
  1823. map = map->baseMap;
  1824. }
  1825. }
  1826. void Panel::RemoveAllKeyBindings()
  1827. {
  1828. PanelKeyBindingMap *map = GetKBMap();
  1829. while( map )
  1830. {
  1831. map->boundkeys.RemoveAll();
  1832. map = map->baseMap;
  1833. }
  1834. }
  1835. //-----------------------------------------------------------------------------
  1836. // Purpose:
  1837. // Input : -
  1838. //-----------------------------------------------------------------------------
  1839. void Panel::ReloadKeyBindings()
  1840. {
  1841. RevertKeyBindingsToDefault();
  1842. LoadKeyBindingsForOnePanel( GetKeyBindingsContext(), this );
  1843. }
  1844. #define MAKE_STRING( x ) #x
  1845. #define KEY_NAME( str, disp ) { KEY_##str, MAKE_STRING( KEY_##str ), disp }
  1846. struct KeyNames_t
  1847. {
  1848. KeyCode code;
  1849. char const *string;
  1850. char const *displaystring;
  1851. };
  1852. static KeyNames_t g_KeyNames[] =
  1853. {
  1854. KEY_NAME( NONE, "None" ),
  1855. KEY_NAME( 0, "0" ),
  1856. KEY_NAME( 1, "1" ),
  1857. KEY_NAME( 2, "2" ),
  1858. KEY_NAME( 3, "3" ),
  1859. KEY_NAME( 4, "4" ),
  1860. KEY_NAME( 5, "5" ),
  1861. KEY_NAME( 6, "6" ),
  1862. KEY_NAME( 7, "7" ),
  1863. KEY_NAME( 8, "8" ),
  1864. KEY_NAME( 9, "9" ),
  1865. KEY_NAME( A, "A" ),
  1866. KEY_NAME( B, "B" ),
  1867. KEY_NAME( C, "C" ),
  1868. KEY_NAME( D, "D" ),
  1869. KEY_NAME( E, "E" ),
  1870. KEY_NAME( F, "F" ),
  1871. KEY_NAME( G, "G" ),
  1872. KEY_NAME( H, "H" ),
  1873. KEY_NAME( I, "I" ),
  1874. KEY_NAME( J, "J" ),
  1875. KEY_NAME( K, "K" ),
  1876. KEY_NAME( L, "L" ),
  1877. KEY_NAME( M, "M" ),
  1878. KEY_NAME( N, "N" ),
  1879. KEY_NAME( O, "O" ),
  1880. KEY_NAME( P, "P" ),
  1881. KEY_NAME( Q, "Q" ),
  1882. KEY_NAME( R, "R" ),
  1883. KEY_NAME( S, "S" ),
  1884. KEY_NAME( T, "T" ),
  1885. KEY_NAME( U, "U" ),
  1886. KEY_NAME( V, "V" ),
  1887. KEY_NAME( W, "W" ),
  1888. KEY_NAME( X, "X" ),
  1889. KEY_NAME( Y, "Y" ),
  1890. KEY_NAME( Z, "Z" ),
  1891. KEY_NAME( PAD_0, "Key Pad 0" ),
  1892. KEY_NAME( PAD_1, "Key Pad 1" ),
  1893. KEY_NAME( PAD_2, "Key Pad 2" ),
  1894. KEY_NAME( PAD_3, "Key Pad 3" ),
  1895. KEY_NAME( PAD_4, "Key Pad 4" ),
  1896. KEY_NAME( PAD_5, "Key Pad 5" ),
  1897. KEY_NAME( PAD_6, "Key Pad 6" ),
  1898. KEY_NAME( PAD_7, "Key Pad 7" ),
  1899. KEY_NAME( PAD_8, "Key Pad 8" ),
  1900. KEY_NAME( PAD_9, "Key Pad 9" ),
  1901. KEY_NAME( PAD_DIVIDE, "Key Pad /" ),
  1902. KEY_NAME( PAD_MULTIPLY, "Key Pad *" ),
  1903. KEY_NAME( PAD_MINUS, "Key Pad -" ),
  1904. KEY_NAME( PAD_PLUS, "Key Pad +" ),
  1905. KEY_NAME( PAD_ENTER, "Key Pad Enter" ),
  1906. KEY_NAME( PAD_DECIMAL, "Key Pad ." ),
  1907. KEY_NAME( LBRACKET, "[" ),
  1908. KEY_NAME( RBRACKET, "]" ),
  1909. KEY_NAME( SEMICOLON, "," ),
  1910. KEY_NAME( APOSTROPHE, "'" ),
  1911. KEY_NAME( BACKQUOTE, "`" ),
  1912. KEY_NAME( COMMA, "," ),
  1913. KEY_NAME( PERIOD, "." ),
  1914. KEY_NAME( SLASH, "/" ),
  1915. KEY_NAME( BACKSLASH, "\\" ),
  1916. KEY_NAME( MINUS, "-" ),
  1917. KEY_NAME( EQUAL, "=" ),
  1918. KEY_NAME( ENTER, "Enter" ),
  1919. KEY_NAME( SPACE, "Space" ),
  1920. KEY_NAME( BACKSPACE, "Backspace" ),
  1921. KEY_NAME( TAB, "Tab" ),
  1922. KEY_NAME( CAPSLOCK, "Caps Lock" ),
  1923. KEY_NAME( NUMLOCK, "Num Lock" ),
  1924. KEY_NAME( ESCAPE, "Escape" ),
  1925. KEY_NAME( SCROLLLOCK, "Scroll Lock" ),
  1926. KEY_NAME( INSERT, "Ins" ),
  1927. KEY_NAME( DELETE, "Del" ),
  1928. KEY_NAME( HOME, "Home" ),
  1929. KEY_NAME( END, "End" ),
  1930. KEY_NAME( PAGEUP, "PgUp" ),
  1931. KEY_NAME( PAGEDOWN, "PgDn" ),
  1932. KEY_NAME( BREAK, "Break" ),
  1933. KEY_NAME( LSHIFT, "Shift" ),
  1934. KEY_NAME( RSHIFT, "Shift" ),
  1935. KEY_NAME( LALT, "Alt" ),
  1936. KEY_NAME( RALT, "Alt" ),
  1937. KEY_NAME( LCONTROL, "Ctrl" ),
  1938. KEY_NAME( RCONTROL, "Ctrl" ),
  1939. KEY_NAME( LWIN, "Windows" ),
  1940. KEY_NAME( RWIN, "Windows" ),
  1941. KEY_NAME( APP, "App" ),
  1942. KEY_NAME( UP, "Up" ),
  1943. KEY_NAME( LEFT, "Left" ),
  1944. KEY_NAME( DOWN, "Down" ),
  1945. KEY_NAME( RIGHT, "Right" ),
  1946. KEY_NAME( F1, "F1" ),
  1947. KEY_NAME( F2, "F2" ),
  1948. KEY_NAME( F3, "F3" ),
  1949. KEY_NAME( F4, "F4" ),
  1950. KEY_NAME( F5, "F5" ),
  1951. KEY_NAME( F6, "F6" ),
  1952. KEY_NAME( F7, "F7" ),
  1953. KEY_NAME( F8, "F8" ),
  1954. KEY_NAME( F9, "F9" ),
  1955. KEY_NAME( F10, "F10" ),
  1956. KEY_NAME( F11, "F11" ),
  1957. KEY_NAME( F12, "F12" ),
  1958. KEY_NAME( CAPSLOCKTOGGLE, "Caps Lock Toggle" ),
  1959. KEY_NAME( NUMLOCKTOGGLE, "Num Lock Toggle" ),
  1960. KEY_NAME( SCROLLLOCKTOGGLE, "Scroll Lock Toggle" ),
  1961. };
  1962. char const *Panel::KeyCodeToString( KeyCode code )
  1963. {
  1964. int c = ARRAYSIZE( g_KeyNames );
  1965. for ( int i = 0; i < c ; ++i )
  1966. {
  1967. if ( g_KeyNames[ i ].code == code )
  1968. return g_KeyNames[ i ].string;
  1969. }
  1970. return "";
  1971. }
  1972. wchar_t const *Panel::KeyCodeToDisplayString( KeyCode code )
  1973. {
  1974. int c = ARRAYSIZE( g_KeyNames );
  1975. for ( int i = 0; i < c ; ++i )
  1976. {
  1977. if ( g_KeyNames[ i ].code == code )
  1978. {
  1979. char const *str = g_KeyNames[ i ].displaystring;
  1980. wchar_t *wstr = g_pVGuiLocalize->Find( str );
  1981. if ( wstr )
  1982. {
  1983. return wstr;
  1984. }
  1985. static wchar_t buf[ 64 ];
  1986. g_pVGuiLocalize->ConvertANSIToUnicode( str, buf, sizeof( buf ) );
  1987. return buf;
  1988. }
  1989. }
  1990. return L"";
  1991. }
  1992. static void AddModifierToString( char const *modifiername, char *buf, size_t bufsize )
  1993. {
  1994. char add[ 32 ];
  1995. if ( Q_strlen( buf ) > 0 )
  1996. {
  1997. Q_snprintf( add, sizeof( add ), "+%s", modifiername );
  1998. }
  1999. else
  2000. {
  2001. Q_strncpy( add, modifiername, sizeof( add ) );
  2002. }
  2003. Q_strncat( buf, add, bufsize, COPY_ALL_CHARACTERS );
  2004. }
  2005. wchar_t const *Panel::KeyCodeModifiersToDisplayString( KeyCode code, int modifiers )
  2006. {
  2007. char sz[ 256 ];
  2008. sz[ 0 ] = 0;
  2009. if ( modifiers & MODIFIER_SHIFT )
  2010. {
  2011. AddModifierToString( "Shift", sz, sizeof( sz ) );
  2012. }
  2013. if ( modifiers & MODIFIER_CONTROL )
  2014. {
  2015. AddModifierToString( "Ctrl", sz, sizeof( sz ) );
  2016. }
  2017. if ( modifiers & MODIFIER_ALT )
  2018. {
  2019. AddModifierToString( "Alt", sz, sizeof( sz ) );
  2020. }
  2021. if ( Q_strlen( sz ) > 0 )
  2022. {
  2023. Q_strncat( sz, "+", sizeof( sz ), COPY_ALL_CHARACTERS );
  2024. }
  2025. static wchar_t unicode[ 256 ];
  2026. #ifdef WIN32
  2027. V_snwprintf( unicode, 255, L"%S%s", sz, Panel::KeyCodeToDisplayString( (KeyCode)code ) );
  2028. #else
  2029. V_snwprintf( unicode, 255, L"%s%S", sz, Panel::KeyCodeToDisplayString( (KeyCode)code ) );
  2030. #endif
  2031. return unicode;
  2032. }
  2033. KeyCode Panel::StringToKeyCode( char const *str )
  2034. {
  2035. int c = ARRAYSIZE( g_KeyNames );
  2036. for ( int i = 0; i < c ; ++i )
  2037. {
  2038. if ( !Q_stricmp( str, g_KeyNames[ i ].string ) )
  2039. return g_KeyNames[ i ].code;
  2040. }
  2041. return KEY_NONE;
  2042. }
  2043. static void WriteKeyBindingToBuffer( CUtlBuffer& buf, int level, const BoundKey_t& binding )
  2044. {
  2045. BufPrint( buf, level, "\"keycode\"\t\"%s\"\n", Panel::KeyCodeToString( (KeyCode)binding.keycode ) );
  2046. if ( binding.modifiers & MODIFIER_SHIFT )
  2047. {
  2048. BufPrint( buf, level, "\"shift\"\t\"1\"\n" );
  2049. }
  2050. if ( binding.modifiers & MODIFIER_CONTROL )
  2051. {
  2052. BufPrint( buf, level, "\"ctrl\"\t\"1\"\n" );
  2053. }
  2054. if ( binding.modifiers & MODIFIER_ALT )
  2055. {
  2056. BufPrint( buf, level, "\"alt\"\t\"1\"\n" );
  2057. }
  2058. }
  2059. //-----------------------------------------------------------------------------
  2060. // Purpose:
  2061. // Input : *filename -
  2062. // *pathID -
  2063. //-----------------------------------------------------------------------------
  2064. void Panel::SaveKeyBindingsToBuffer( int level, CUtlBuffer& buf )
  2065. {
  2066. Assert( IsValidKeyBindingsContext() );
  2067. Assert( buf.IsText() );
  2068. PanelKeyBindingMap *map = GetKBMap();
  2069. while( map )
  2070. {
  2071. int c = map->boundkeys.Count();
  2072. for( int i = 0; i < c ; ++i )
  2073. {
  2074. const BoundKey_t& binding = map->boundkeys[ i ];
  2075. // Spew to file
  2076. BufPrint( buf, level, "\"%s\"\n", binding.bindingname );
  2077. BufPrint( buf, level, "{\n" );
  2078. WriteKeyBindingToBuffer( buf, level + 1, binding );
  2079. BufPrint( buf, level, "}\n" );
  2080. }
  2081. map = map->baseMap;
  2082. }
  2083. }
  2084. bool Panel::ParseKeyBindings( KeyValues *kv )
  2085. {
  2086. Assert( IsValidKeyBindingsContext() );
  2087. if ( !IsValidKeyBindingsContext() )
  2088. return false;
  2089. // To have KB the panel must have a name
  2090. Assert( GetName() && GetName()[ 0 ] );
  2091. if ( !GetName() || !GetName()[ 0 ] )
  2092. return false;
  2093. bool success = false;
  2094. g_KBMgr.AddPanelToContext( GetKeyBindingsContext(), this );
  2095. RemoveAllKeyBindings();
  2096. // Walk through bindings
  2097. for ( KeyValues *binding = kv->GetFirstSubKey(); binding != NULL; binding = binding->GetNextKey() )
  2098. {
  2099. char const *bindingName = binding->GetName();
  2100. if ( !bindingName || !bindingName[ 0 ] )
  2101. continue;
  2102. KeyBindingMap_t *b = LookupBinding( bindingName );
  2103. if ( b )
  2104. {
  2105. success = true;
  2106. const char *keycode = binding->GetString( "keycode", "" );
  2107. int modifiers = 0;
  2108. if ( binding->GetInt( "shift", 0 ) != 0 )
  2109. {
  2110. modifiers |= MODIFIER_SHIFT;
  2111. }
  2112. if ( binding->GetInt( "ctrl", 0 ) != 0 )
  2113. {
  2114. modifiers |= MODIFIER_CONTROL;
  2115. }
  2116. if ( binding->GetInt( "alt", 0 ) != 0 )
  2117. {
  2118. modifiers |= MODIFIER_ALT;
  2119. }
  2120. KeyBindingMap_t *bound = LookupBindingByKeyCode( StringToKeyCode( keycode ), modifiers );
  2121. if ( !bound )
  2122. {
  2123. AddKeyBinding( bindingName, StringToKeyCode( keycode ), modifiers );
  2124. }
  2125. }
  2126. else
  2127. {
  2128. Warning( "KeyBinding for panel '%s' contained unknown binding '%s'\n", GetName() ? GetName() : "???", bindingName );
  2129. }
  2130. }
  2131. // Now for each binding which is currently "unbound" to any key, use the default binding
  2132. PanelKeyBindingMap *map = GetKBMap();
  2133. while( map )
  2134. {
  2135. int c = map->entries.Count();
  2136. for( int i = 0; i < c ; ++i )
  2137. {
  2138. KeyBindingMap_t *binding = &map->entries[ i ];
  2139. // See if there is a bound key
  2140. CUtlVector< BoundKey_t * > list;
  2141. LookupBoundKeys( binding->bindingname, list );
  2142. if ( list.Count() == 0 )
  2143. {
  2144. // Assign the default binding to this key
  2145. BoundKey_t *defaultKey = LookupDefaultKey( binding->bindingname );
  2146. if ( defaultKey )
  2147. {
  2148. KeyBindingMap_t *alreadyBound = LookupBindingByKeyCode( (KeyCode)defaultKey->keycode, defaultKey->modifiers );
  2149. if ( alreadyBound )
  2150. {
  2151. Warning( "No binding for '%s', defautl key already bound to '%s'\n", binding->bindingname, alreadyBound->bindingname );
  2152. }
  2153. else
  2154. {
  2155. AddKeyBinding( defaultKey->bindingname, defaultKey->keycode, defaultKey->modifiers );
  2156. }
  2157. }
  2158. }
  2159. }
  2160. map = map->baseMap;
  2161. }
  2162. return success;
  2163. }
  2164. //-----------------------------------------------------------------------------
  2165. // Purpose:
  2166. // Input : handle -
  2167. // Output : Returns true on success, false on failure.
  2168. //-----------------------------------------------------------------------------
  2169. void Panel::SetKeyBindingsContext( KeyBindingContextHandle_t handle )
  2170. {
  2171. Assert( !IsValidKeyBindingsContext() || handle == GetKeyBindingsContext() );
  2172. g_KBMgr.AddPanelToContext( handle, this );
  2173. m_hKeyBindingsContext = handle;
  2174. }
  2175. //-----------------------------------------------------------------------------
  2176. // Purpose:
  2177. // Input : -
  2178. // Output : KeyBindingContextHandle_t
  2179. //-----------------------------------------------------------------------------
  2180. KeyBindingContextHandle_t Panel::GetKeyBindingsContext() const
  2181. {
  2182. return m_hKeyBindingsContext;
  2183. }
  2184. //-----------------------------------------------------------------------------
  2185. // Purpose:
  2186. // Input : -
  2187. // Output : Returns true on success, false on failure.
  2188. //-----------------------------------------------------------------------------
  2189. bool Panel::IsValidKeyBindingsContext() const
  2190. {
  2191. return GetKeyBindingsContext() != INVALID_KEYBINDINGCONTEXT_HANDLE;
  2192. }
  2193. char const *Panel::GetKeyBindingsFile() const
  2194. {
  2195. Assert( IsValidKeyBindingsContext() );
  2196. return g_KBMgr.GetKeyBindingsFile( GetKeyBindingsContext() );
  2197. }
  2198. char const *Panel::GetKeyBindingsFilePathID() const
  2199. {
  2200. Assert( IsValidKeyBindingsContext() );
  2201. return g_KBMgr.GetKeyBindingsFilePathID( GetKeyBindingsContext() );
  2202. }
  2203. void Panel::EditKeyBindings()
  2204. {
  2205. Assert( 0 );
  2206. }
  2207. //-----------------------------------------------------------------------------
  2208. // Purpose: Set this to false to disallow IsKeyRebound chaining to GetParent() Panels...
  2209. // Input : state -
  2210. //-----------------------------------------------------------------------------
  2211. void Panel::SetAllowKeyBindingChainToParent( bool state )
  2212. {
  2213. _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT, state );
  2214. }
  2215. //-----------------------------------------------------------------------------
  2216. // Purpose:
  2217. // Input : -
  2218. // Output : Returns true on success, false on failure.
  2219. //-----------------------------------------------------------------------------
  2220. bool Panel::IsKeyBindingChainToParentAllowed() const
  2221. {
  2222. return _flags.IsFlagSet( ALLOW_CHAIN_KEYBINDING_TO_PARENT );
  2223. }
  2224. bool Panel::IsKeyOverridden( KeyCode code, int modifiers )
  2225. {
  2226. // By default assume all keys should pass through binding system
  2227. return false;
  2228. }
  2229. bool Panel::IsKeyRebound( KeyCode code, int modifiers )
  2230. {
  2231. if ( IsKeyBoardInputEnabled() )
  2232. {
  2233. KeyBindingMap_t* binding = LookupBindingByKeyCode( code, modifiers );
  2234. // Only dispatch if we're part of the current modal subtree
  2235. if ( binding && IsChildOfSurfaceModalPanel() )
  2236. {
  2237. // Found match, post message to panel
  2238. if ( binding->func )
  2239. {
  2240. // dispatch the func
  2241. (this->*binding->func)();
  2242. }
  2243. else
  2244. {
  2245. Assert( 0 );
  2246. }
  2247. if ( !binding->passive )
  2248. {
  2249. // Exit this function...
  2250. return true;
  2251. }
  2252. }
  2253. }
  2254. // Chain to parent
  2255. Panel* pParent = GetParent();
  2256. if ( IsKeyBindingChainToParentAllowed() && pParent && !IsKeyOverridden( code, modifiers ) )
  2257. return pParent->IsKeyRebound( code, modifiers );
  2258. // No suitable binding found
  2259. return false;
  2260. }
  2261. static bool s_bSuppressRebindChecks = false;
  2262. #endif // VGUI_USEKEYBINDINGMAPS
  2263. void Panel::InternalKeyCodeTyped( int code )
  2264. {
  2265. if ( !ShouldHandleInputMessage() )
  2266. {
  2267. input()->OnKeyCodeUnhandled( code );
  2268. return;
  2269. }
  2270. if (IsKeyBoardInputEnabled())
  2271. {
  2272. bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
  2273. bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
  2274. bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
  2275. int modifiers = 0;
  2276. if ( shift )
  2277. {
  2278. modifiers |= MODIFIER_SHIFT;
  2279. }
  2280. if ( ctrl )
  2281. {
  2282. modifiers |= MODIFIER_CONTROL;
  2283. }
  2284. if ( alt )
  2285. {
  2286. modifiers |= MODIFIER_ALT;
  2287. }
  2288. // Things in build mode don't have accelerators
  2289. if (IsBuildGroupEnabled())
  2290. {
  2291. _buildGroup->KeyCodeTyped((KeyCode)code, this);
  2292. return;
  2293. }
  2294. if ( !s_bSuppressRebindChecks && IsKeyRebound( (KeyCode)code, modifiers ) )
  2295. {
  2296. return;
  2297. }
  2298. bool oldVal = s_bSuppressRebindChecks;
  2299. s_bSuppressRebindChecks = true;
  2300. OnKeyCodeTyped((KeyCode)code);
  2301. s_bSuppressRebindChecks = oldVal;
  2302. }
  2303. else
  2304. {
  2305. if ( GetVPanel() == surface()->GetEmbeddedPanel() )
  2306. {
  2307. input()->OnKeyCodeUnhandled( code );
  2308. }
  2309. CallParentFunction(new KeyValues("KeyCodeTyped", "code", code));
  2310. }
  2311. }
  2312. void Panel::InternalKeyTyped(int unichar)
  2313. {
  2314. if ( !ShouldHandleInputMessage() )
  2315. return;
  2316. if (IsKeyBoardInputEnabled())
  2317. {
  2318. if ( IsBuildGroupEnabled() )
  2319. {
  2320. if ( _buildGroup->KeyTyped( (wchar_t)unichar, this ) )
  2321. {
  2322. return;
  2323. }
  2324. }
  2325. OnKeyTyped((wchar_t)unichar);
  2326. }
  2327. else
  2328. {
  2329. CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar));
  2330. }
  2331. }
  2332. void Panel::InternalKeyCodeReleased(int code)
  2333. {
  2334. if ( !ShouldHandleInputMessage() )
  2335. return;
  2336. if (IsKeyBoardInputEnabled())
  2337. {
  2338. if (IsBuildGroupEnabled())
  2339. {
  2340. if ( _buildGroup->KeyCodeReleased((KeyCode)code, this) )
  2341. {
  2342. return;
  2343. }
  2344. }
  2345. OnKeyCodeReleased((KeyCode)code);
  2346. }
  2347. else
  2348. {
  2349. CallParentFunction(new KeyValues("KeyCodeReleased", "code", code));
  2350. }
  2351. }
  2352. void Panel::InternalKeyFocusTicked()
  2353. {
  2354. if (IsBuildGroupEnabled())
  2355. return;
  2356. OnKeyFocusTicked();
  2357. }
  2358. void Panel::InternalMouseFocusTicked()
  2359. {
  2360. if (IsBuildGroupEnabled())
  2361. {
  2362. // must repaint so the numbers will be accurate
  2363. if (_buildGroup->HasRulersOn())
  2364. {
  2365. PaintTraverse(true);
  2366. }
  2367. return;
  2368. }
  2369. // update cursor
  2370. InternalSetCursor();
  2371. OnMouseFocusTicked();
  2372. }
  2373. void Panel::InternalSetCursor()
  2374. {
  2375. bool visible = IsVisible();
  2376. if (visible)
  2377. {
  2378. #if defined( VGUI_USEDRAGDROP )
  2379. // Drag drop is overriding cursor?
  2380. if ( m_pDragDrop->m_bDragging ||
  2381. g_DragDropCapture.Get() != NULL )
  2382. return;
  2383. #endif
  2384. // chain up and make sure all our parents are also visible
  2385. VPANEL p = GetVParent();
  2386. while (p)
  2387. {
  2388. visible &= ipanel()->IsVisible(p);
  2389. p = ipanel()->GetParent(p);
  2390. }
  2391. // only change the cursor if this panel is visible, and if its part of the main VGUI tree
  2392. if (visible && HasParent(surface()->GetEmbeddedPanel()))
  2393. {
  2394. HCursor cursor = GetCursor();
  2395. if (IsBuildGroupEnabled())
  2396. {
  2397. cursor = _buildGroup->GetCursor(this);
  2398. }
  2399. if (input()->GetCursorOveride())
  2400. {
  2401. cursor = input()->GetCursorOveride();
  2402. }
  2403. surface()->SetCursor(cursor);
  2404. }
  2405. }
  2406. }
  2407. //-----------------------------------------------------------------------------
  2408. // Purpose: Called every frame the panel is visible, designed to be overridden
  2409. //-----------------------------------------------------------------------------
  2410. void Panel::OnThink()
  2411. {
  2412. #if defined( VGUI_USEDRAGDROP )
  2413. if ( IsPC() &&
  2414. m_pDragDrop->m_bDragEnabled &&
  2415. m_pDragDrop->m_bDragging &&
  2416. m_pDragDrop->m_bDragStarted )
  2417. {
  2418. bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE );
  2419. if ( isEscapeKeyDown )
  2420. {
  2421. OnContinueDragging();
  2422. OnFinishDragging( true, (MouseCode)-1, true );
  2423. return;
  2424. }
  2425. if ( m_pDragDrop->m_hCurrentDrop != NULL )
  2426. {
  2427. if ( !input()->IsMouseDown( MOUSE_LEFT ) )
  2428. {
  2429. OnContinueDragging();
  2430. OnFinishDragging( true, (MouseCode)-1 );
  2431. return;
  2432. }
  2433. // allow the cursor to change based upon things like changing keystate, etc.
  2434. surface()->SetCursor( m_pDragDrop->m_hCurrentDrop->GetDropCursor( m_pDragDrop->m_DragData ) );
  2435. if ( !m_pDragDrop->m_bDropMenuShown )
  2436. {
  2437. // See if the hover time has gotten larger
  2438. float hoverSeconds = ( system()->GetTimeMillis() - m_pDragDrop->m_lDropHoverTime ) * 0.001f;
  2439. DragDrop_t *dropInfo = m_pDragDrop->m_hCurrentDrop->GetDragDropInfo();
  2440. if ( dropInfo->m_flHoverContextTime != 0.0f )
  2441. {
  2442. if ( hoverSeconds >= dropInfo->m_flHoverContextTime )
  2443. {
  2444. m_pDragDrop->m_bDropMenuShown = true;
  2445. CUtlVector< KeyValues * > data;
  2446. GetDragData( data );
  2447. int x, y;
  2448. input()->GetCursorPos( x, y );
  2449. if ( m_pDragDrop->m_hDropContextMenu.Get() )
  2450. {
  2451. delete m_pDragDrop->m_hDropContextMenu.Get();
  2452. }
  2453. Menu *menu = new Menu( m_pDragDrop->m_hCurrentDrop.Get(), "DropContext" );
  2454. bool useMenu = m_pDragDrop->m_hCurrentDrop->GetDropContextMenu( menu, data );
  2455. if ( useMenu )
  2456. {
  2457. m_pDragDrop->m_hDropContextMenu = menu;
  2458. menu->SetPos( x, y );
  2459. menu->SetVisible( true );
  2460. menu->MakePopup();
  2461. surface()->MovePopupToFront( menu->GetVPanel() );
  2462. if ( menu->GetItemCount() > 0 )
  2463. {
  2464. int id = menu->GetMenuID( 0 );
  2465. menu->SetCurrentlyHighlightedItem( id );
  2466. MenuItem *item = menu->GetMenuItem( id );
  2467. item->SetArmed( true );
  2468. }
  2469. }
  2470. else
  2471. {
  2472. delete menu;
  2473. }
  2474. m_pDragDrop->m_hCurrentDrop->OnDropContextHoverShow( data );
  2475. }
  2476. }
  2477. }
  2478. }
  2479. }
  2480. #endif
  2481. }
  2482. // input messages handlers (designed for override)
  2483. void Panel::OnCursorMoved(int x, int y)
  2484. {
  2485. }
  2486. void Panel::OnCursorEntered()
  2487. {
  2488. }
  2489. void Panel::OnCursorExited()
  2490. {
  2491. }
  2492. void Panel::OnMousePressed(MouseCode code)
  2493. {
  2494. }
  2495. void Panel::OnMouseDoublePressed(MouseCode code)
  2496. {
  2497. }
  2498. void Panel::OnMouseTriplePressed(MouseCode code)
  2499. {
  2500. }
  2501. void Panel::OnMouseReleased(MouseCode code)
  2502. {
  2503. }
  2504. void Panel::OnMouseWheeled(int delta)
  2505. {
  2506. CallParentFunction(new KeyValues("MouseWheeled", "delta", delta));
  2507. }
  2508. // base implementation forwards Key messages to the Panel's parent - override to 'swallow' the input
  2509. void Panel::OnKeyCodePressed(KeyCode code)
  2510. {
  2511. bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
  2512. ctrl; // needed for X360 warning C4189: 'ctrl' : local variable is initialized but not referenced
  2513. if ( IsGameConsole() || ( IsConsoleStylePanel() && !ctrl ) )
  2514. {
  2515. bool handled = false;
  2516. switch( GetBaseButtonCode( code ) )
  2517. {
  2518. case KEY_XBUTTON_UP:
  2519. case KEY_XSTICK1_UP:
  2520. case KEY_XSTICK2_UP:
  2521. case KEY_UP:
  2522. if ( !s_NavLock && NavigateUp() )
  2523. {
  2524. s_NavLock = 1;
  2525. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2526. handled = true;
  2527. }
  2528. break;
  2529. case KEY_XBUTTON_DOWN:
  2530. case KEY_XSTICK1_DOWN:
  2531. case KEY_XSTICK2_DOWN:
  2532. case KEY_DOWN:
  2533. if ( !s_NavLock && NavigateDown() )
  2534. {
  2535. s_NavLock = 1;
  2536. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2537. handled = true;
  2538. }
  2539. break;
  2540. case KEY_XBUTTON_LEFT:
  2541. case KEY_XSTICK1_LEFT:
  2542. case KEY_XSTICK2_LEFT:
  2543. case KEY_LEFT:
  2544. if ( !s_NavLock && NavigateLeft() )
  2545. {
  2546. s_NavLock = 1;
  2547. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2548. handled = true;
  2549. }
  2550. break;
  2551. case KEY_XBUTTON_RIGHT:
  2552. case KEY_XSTICK1_RIGHT:
  2553. case KEY_XSTICK2_RIGHT:
  2554. case KEY_RIGHT:
  2555. if ( !s_NavLock && NavigateRight() )
  2556. {
  2557. s_NavLock = 1;
  2558. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2559. handled = true;
  2560. }
  2561. break;
  2562. }
  2563. if( !handled && !m_PassUnhandledInput )
  2564. return;
  2565. }
  2566. CallParentFunction(new KeyValues("KeyCodePressed", "code", code));
  2567. }
  2568. void Panel::OnKeyCodeTyped(KeyCode keycode)
  2569. {
  2570. vgui::KeyCode code = GetBaseButtonCode( keycode );
  2571. // handle focus change
  2572. if ( IsGameConsole() || IsConsoleStylePanel() )
  2573. {
  2574. // eat these typed codes, will get handled in OnKeyCodePressed
  2575. if ( IsJoystickCode( keycode ) )
  2576. return;
  2577. switch ( code )
  2578. {
  2579. case KEY_UP:
  2580. case KEY_DOWN:
  2581. case KEY_LEFT:
  2582. case KEY_RIGHT:
  2583. return;
  2584. }
  2585. // legacy handling - need to re-enable for older apps?
  2586. /*
  2587. if ( code == KEY_XSTICK1_RIGHT || code == KEY_XBUTTON_RIGHT )
  2588. {
  2589. RequestFocusNext();
  2590. return;
  2591. }
  2592. else if ( code == KEY_XSTICK1_LEFT || code == KEY_XBUTTON_LEFT )
  2593. {
  2594. RequestFocusPrev();
  2595. return;
  2596. }
  2597. */
  2598. }
  2599. if (code == KEY_TAB)
  2600. {
  2601. bool bShiftDown = input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT);
  2602. if ( IsConsoleStylePanel() )
  2603. {
  2604. if ( bShiftDown )
  2605. {
  2606. NavigateUp();
  2607. }
  2608. else
  2609. {
  2610. NavigateDown();
  2611. }
  2612. }
  2613. else
  2614. {
  2615. // if shift is down goto previous tab position, otherwise goto next
  2616. if ( bShiftDown )
  2617. {
  2618. RequestFocusPrev();
  2619. }
  2620. else
  2621. {
  2622. RequestFocusNext();
  2623. }
  2624. }
  2625. }
  2626. else
  2627. {
  2628. // forward up
  2629. if ( GetVPanel() == surface()->GetEmbeddedPanel() )
  2630. {
  2631. input()->OnKeyCodeUnhandled( keycode );
  2632. }
  2633. CallParentFunction(new KeyValues("KeyCodeTyped", "code", keycode));
  2634. }
  2635. }
  2636. void Panel::OnKeyTyped(wchar_t unichar)
  2637. {
  2638. CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar));
  2639. }
  2640. void Panel::OnKeyCodeReleased(KeyCode code)
  2641. {
  2642. CallParentFunction(new KeyValues("KeyCodeReleased", "code", code));
  2643. }
  2644. void Panel::OnKeyFocusTicked()
  2645. {
  2646. CallParentFunction(new KeyValues("KeyFocusTicked"));
  2647. }
  2648. void Panel::OnMouseFocusTicked()
  2649. {
  2650. CallParentFunction(new KeyValues("OnMouseFocusTicked"));
  2651. }
  2652. bool Panel::IsWithin(int x,int y)
  2653. {
  2654. // check against our clip rect
  2655. int clipRect[4];
  2656. ipanel()->GetClipRect(GetVPanel(), clipRect[0], clipRect[1], clipRect[2], clipRect[3]);
  2657. if (x < clipRect[0])
  2658. {
  2659. return false;
  2660. }
  2661. if (y < clipRect[1])
  2662. {
  2663. return false;
  2664. }
  2665. if (x >= clipRect[2])
  2666. {
  2667. return false;
  2668. }
  2669. if (y >= clipRect[3])
  2670. {
  2671. return false;
  2672. }
  2673. return true;
  2674. }
  2675. //-----------------------------------------------------------------------------
  2676. // Purpose: determines which is the topmost panel under the coordinates (x, y)
  2677. //-----------------------------------------------------------------------------
  2678. VPANEL Panel::IsWithinTraverse(int x, int y, bool traversePopups)
  2679. {
  2680. // if this one is not visible, its children won't be either
  2681. // also if it doesn't want mouse input its children can't get it either
  2682. if (!IsVisible() || !IsMouseInputEnabled())
  2683. return NULL;
  2684. if (traversePopups)
  2685. {
  2686. // check popups first
  2687. int i;
  2688. CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() );
  2689. int childCount = children.Count();
  2690. for (i = childCount - 1; i >= 0; i--)
  2691. {
  2692. VPANEL panel = children[ i ];
  2693. if (ipanel()->IsPopup(panel))
  2694. {
  2695. panel = ipanel()->IsWithinTraverse(panel, x, y, true);
  2696. if (panel != 0)
  2697. {
  2698. return panel;
  2699. }
  2700. }
  2701. }
  2702. // check children recursive, if you find one, just return first one
  2703. // this checks in backwards order so the last child drawn for this panel is chosen which
  2704. // coincides to how it would be visibly displayed
  2705. for (i = childCount - 1; i >= 0; i--)
  2706. {
  2707. VPANEL panel = children[ i ];
  2708. // we've already checked popups so ignore
  2709. if (!ipanel()->IsPopup(panel))
  2710. {
  2711. panel = ipanel()->IsWithinTraverse(panel, x, y, true);
  2712. if (panel != NULL)
  2713. {
  2714. return panel;
  2715. }
  2716. }
  2717. }
  2718. // check ourself
  2719. if ( !IsMouseInputDisabledForThisPanel() && IsWithin(x, y) )
  2720. {
  2721. return GetVPanel();
  2722. }
  2723. }
  2724. else
  2725. {
  2726. // since we're not checking popups, it must be within us, so we can check ourself first
  2727. if (IsWithin(x, y))
  2728. {
  2729. // check children recursive, if you find one, just return first one
  2730. // this checks in backwards order so the last child drawn for this panel is chosen which
  2731. // coincides to how it would be visibly displayed
  2732. CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() );
  2733. int childCount = children.Count();
  2734. for (int i = childCount - 1; i >= 0; i--)
  2735. {
  2736. VPANEL panel = children[ i ];
  2737. // ignore popups
  2738. if (!ipanel()->IsPopup(panel))
  2739. {
  2740. panel = ipanel()->IsWithinTraverse(panel, x, y, false);
  2741. if (panel != NULL)
  2742. {
  2743. return panel;
  2744. }
  2745. }
  2746. }
  2747. // not a child, must be us
  2748. if ( !IsMouseInputDisabledForThisPanel() )
  2749. return GetVPanel();
  2750. }
  2751. }
  2752. return NULL;
  2753. }
  2754. void Panel::LocalToScreen(int& x,int& y)
  2755. {
  2756. int px, py;
  2757. ipanel()->GetAbsPos(GetVPanel(), px, py);
  2758. x = x + px;
  2759. y = y + py;
  2760. }
  2761. void Panel::ScreenToLocal(int& x,int& y)
  2762. {
  2763. int px, py;
  2764. ipanel()->GetAbsPos(GetVPanel(), px, py);
  2765. x = x - px;
  2766. y = y - py;
  2767. }
  2768. void Panel::ParentLocalToScreen(int &x, int &y)
  2769. {
  2770. int px, py;
  2771. ipanel()->GetAbsPos(GetVParent(), px, py);
  2772. x = x + px;
  2773. y = y + py;
  2774. }
  2775. void Panel::MakePopup(bool showTaskbarIcon,bool disabled)
  2776. {
  2777. surface()->CreatePopup(GetVPanel(), false, showTaskbarIcon,disabled);
  2778. }
  2779. void Panel::SetCursor(HCursor cursor)
  2780. {
  2781. _cursor = cursor;
  2782. }
  2783. HCursor Panel::GetCursor()
  2784. {
  2785. return _cursor;
  2786. }
  2787. void Panel::SetMinimumSize(int wide,int tall)
  2788. {
  2789. ipanel()->SetMinimumSize(GetVPanel(), wide, tall);
  2790. }
  2791. void Panel::GetMinimumSize(int& wide,int &tall)
  2792. {
  2793. ipanel()->GetMinimumSize(GetVPanel(), wide, tall);
  2794. }
  2795. bool Panel::IsBuildModeEditable()
  2796. {
  2797. return true;
  2798. }
  2799. void Panel::SetBuildModeEditable(bool state)
  2800. {
  2801. if (state)
  2802. {
  2803. _buildModeFlags |= BUILDMODE_EDITABLE;
  2804. }
  2805. else
  2806. {
  2807. _buildModeFlags &= ~BUILDMODE_EDITABLE;
  2808. }
  2809. }
  2810. //-----------------------------------------------------------------------------
  2811. // Purpose: data accessor
  2812. //-----------------------------------------------------------------------------
  2813. bool Panel::IsBuildModeDeletable()
  2814. {
  2815. return (_buildModeFlags & BUILDMODE_DELETABLE) ? true : false;
  2816. }
  2817. //-----------------------------------------------------------------------------
  2818. // Purpose: data accessor
  2819. //-----------------------------------------------------------------------------
  2820. void Panel::SetBuildModeDeletable(bool state)
  2821. {
  2822. if (state)
  2823. {
  2824. _buildModeFlags |= BUILDMODE_DELETABLE;
  2825. }
  2826. else
  2827. {
  2828. _buildModeFlags &= ~BUILDMODE_DELETABLE;
  2829. }
  2830. }
  2831. //-----------------------------------------------------------------------------
  2832. // Purpose:
  2833. //-----------------------------------------------------------------------------
  2834. bool Panel::IsBuildModeActive()
  2835. {
  2836. return _buildGroup ? _buildGroup->IsEnabled() : false;
  2837. }
  2838. //-----------------------------------------------------------------------------
  2839. // Purpose:
  2840. //-----------------------------------------------------------------------------
  2841. void Panel::GetClipRect(int& x0,int& y0,int& x1,int& y1)
  2842. {
  2843. ipanel()->GetClipRect(GetVPanel(), x0, y0, x1, y1);
  2844. }
  2845. //-----------------------------------------------------------------------------
  2846. // Purpose:
  2847. //-----------------------------------------------------------------------------
  2848. int Panel::GetChildCount()
  2849. {
  2850. if (ipanel())
  2851. {
  2852. return ipanel()->GetChildCount(GetVPanel());
  2853. }
  2854. return 0;
  2855. }
  2856. //-----------------------------------------------------------------------------
  2857. // Purpose: returns a child by the specified index
  2858. //-----------------------------------------------------------------------------
  2859. Panel *Panel::GetChild(int index)
  2860. {
  2861. // get the child and cast it to a panel
  2862. // this assumes that the child is from the same module as the this (precondition)
  2863. return ipanel()->GetPanel(ipanel()->GetChild(GetVPanel(), index), GetControlsModuleName());
  2864. }
  2865. //-----------------------------------------------------------------------------
  2866. // Purpose: moves the key focus back
  2867. //-----------------------------------------------------------------------------
  2868. bool Panel::RequestFocusPrev(VPANEL panel)
  2869. {
  2870. // chain to parent
  2871. if (GetVParent())
  2872. {
  2873. return ipanel()->RequestFocusPrev(GetVParent(), GetVPanel());
  2874. }
  2875. return false;
  2876. }
  2877. //-----------------------------------------------------------------------------
  2878. // Purpose:
  2879. //-----------------------------------------------------------------------------
  2880. bool Panel::RequestFocusNext(VPANEL panel)
  2881. {
  2882. // chain to parent
  2883. if (GetVParent())
  2884. {
  2885. return ipanel()->RequestFocusNext(GetVParent(), GetVPanel());
  2886. }
  2887. return false;
  2888. }
  2889. //-----------------------------------------------------------------------------
  2890. // Purpose: Sets the panel to have the current sub focus
  2891. // Input : direction - the direction in which focus travelled to arrive at this panel; forward = 1, back = -1
  2892. //-----------------------------------------------------------------------------
  2893. void Panel::RequestFocus(int direction)
  2894. {
  2895. // NOTE: This doesn't make any sense if we don't have keyboard input enabled
  2896. Assert( ( IsGameConsole() || IsConsoleStylePanel() ) || IsKeyBoardInputEnabled() );
  2897. // ivgui()->DPrintf2("RequestFocus(%s, %s)\n", GetName(), GetClassName());
  2898. OnRequestFocus(GetVPanel(), NULL);
  2899. }
  2900. //-----------------------------------------------------------------------------
  2901. // Purpose: Called after a panel requests focus to fix up the whole chain
  2902. //-----------------------------------------------------------------------------
  2903. void Panel::OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel)
  2904. {
  2905. KeyValues* p = new KeyValues("OnRequestFocus");
  2906. p->SetPtr("subFocus", (void*)subFocus);
  2907. p->SetPtr("defaultPanel", (void*)defaultPanel);
  2908. CallParentFunction(p);
  2909. }
  2910. //-----------------------------------------------------------------------------
  2911. // Purpose:
  2912. //-----------------------------------------------------------------------------
  2913. VPANEL Panel::GetCurrentKeyFocus()
  2914. {
  2915. return NULL;
  2916. }
  2917. //-----------------------------------------------------------------------------
  2918. // Purpose: returns true if the panel has focus
  2919. //-----------------------------------------------------------------------------
  2920. bool Panel::HasFocus()
  2921. {
  2922. if (input()->GetFocus() == GetVPanel())
  2923. {
  2924. return true;
  2925. }
  2926. return false;
  2927. }
  2928. //-----------------------------------------------------------------------------
  2929. // Purpose:
  2930. //-----------------------------------------------------------------------------
  2931. void Panel::SetTabPosition(int position)
  2932. {
  2933. _tabPosition = position;
  2934. }
  2935. //-----------------------------------------------------------------------------
  2936. // Purpose:
  2937. //-----------------------------------------------------------------------------
  2938. int Panel::GetTabPosition()
  2939. {
  2940. return _tabPosition;
  2941. }
  2942. //-----------------------------------------------------------------------------
  2943. // Purpose:
  2944. //-----------------------------------------------------------------------------
  2945. void Panel::InternalFocusChanged(bool lost)
  2946. {
  2947. /*
  2948. //if focus is gained tell the focusNavGroup about it so its current can be correct
  2949. if( (!lost) && (_focusNavGroup!=0) )
  2950. {
  2951. _focusNavGroup->setCurrentPanel(this);
  2952. }
  2953. */
  2954. }
  2955. //-----------------------------------------------------------------------------
  2956. // Purpose: Called when a panel loses it's mouse capture
  2957. //-----------------------------------------------------------------------------
  2958. void Panel::OnMouseCaptureLost()
  2959. {
  2960. if (m_pTooltips)
  2961. {
  2962. m_pTooltips->ResetDelay();
  2963. }
  2964. }
  2965. //-----------------------------------------------------------------------------
  2966. // Purpose:
  2967. //-----------------------------------------------------------------------------
  2968. void Panel::AddActionSignalTarget(Panel *messageTarget)
  2969. {
  2970. HPanel target = ivgui()->PanelToHandle(messageTarget->GetVPanel());
  2971. if (!_actionSignalTargetDar.HasElement(target))
  2972. {
  2973. _actionSignalTargetDar.AddElement(target);
  2974. }
  2975. }
  2976. //-----------------------------------------------------------------------------
  2977. // Purpose:
  2978. //-----------------------------------------------------------------------------
  2979. void Panel::AddActionSignalTarget(VPANEL messageTarget)
  2980. {
  2981. HPanel target = ivgui()->PanelToHandle(messageTarget);
  2982. if (!_actionSignalTargetDar.HasElement(target))
  2983. {
  2984. _actionSignalTargetDar.AddElement(target);
  2985. }
  2986. }
  2987. //-----------------------------------------------------------------------------
  2988. // Purpose:
  2989. //-----------------------------------------------------------------------------
  2990. void Panel::RemoveActionSignalTarget(Panel *oldTarget)
  2991. {
  2992. _actionSignalTargetDar.RemoveElement(ivgui()->PanelToHandle(oldTarget->GetVPanel()));
  2993. }
  2994. //-----------------------------------------------------------------------------
  2995. // Purpose: Sends a message to all the panels that have requested action signals
  2996. //-----------------------------------------------------------------------------
  2997. void Panel::PostActionSignal( KeyValues *message )
  2998. {
  2999. if ( m_bIsSilent != true )
  3000. {
  3001. // add who it was from the message
  3002. message->SetPtr("panel", this);
  3003. int i;
  3004. for (i = _actionSignalTargetDar.GetCount() - 1; i > 0; i--)
  3005. {
  3006. VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]);
  3007. if (panel)
  3008. {
  3009. ivgui()->PostMessage(panel, message->MakeCopy(), GetVPanel());
  3010. }
  3011. }
  3012. // do this so we can save on one MakeCopy() call
  3013. if (i == 0)
  3014. {
  3015. VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]);
  3016. if (panel)
  3017. {
  3018. ivgui()->PostMessage(panel, message, GetVPanel());
  3019. return;
  3020. }
  3021. }
  3022. }
  3023. message->deleteThis();
  3024. }
  3025. void Panel::SetBorder(IBorder *border)
  3026. {
  3027. _border = border;
  3028. if (border)
  3029. {
  3030. m_sBorderName = border->GetName();
  3031. int x, y, x2, y2;
  3032. border->GetInset(x, y, x2, y2);
  3033. ipanel()->SetInset(GetVPanel(), x, y, x2, y2);
  3034. // update our background type based on the bord
  3035. SetPaintBackgroundType(border->GetBackgroundType());
  3036. }
  3037. else
  3038. {
  3039. m_sBorderName = UTL_INVAL_SYMBOL;
  3040. ipanel()->SetInset(GetVPanel(), 0, 0, 0, 0);
  3041. }
  3042. }
  3043. IBorder *Panel::GetBorder()
  3044. {
  3045. return _border;
  3046. }
  3047. void Panel::SetPaintBorderEnabled(bool state)
  3048. {
  3049. _flags.SetFlag( PAINT_BORDER_ENABLED, state );
  3050. }
  3051. void Panel::SetPaintBackgroundEnabled(bool state)
  3052. {
  3053. _flags.SetFlag( PAINT_BACKGROUND_ENABLED, state );
  3054. }
  3055. void Panel::SetPaintBackgroundType( int type )
  3056. {
  3057. // HACK only 0 through 2 supported for now
  3058. m_nPaintBackgroundType = clamp( type, 0, 2 );
  3059. }
  3060. void Panel::SetPaintEnabled(bool state)
  3061. {
  3062. _flags.SetFlag( PAINT_ENABLED, state );
  3063. }
  3064. void Panel::SetPostChildPaintEnabled(bool state)
  3065. {
  3066. _flags.SetFlag( POST_CHILD_PAINT_ENABLED, state );
  3067. }
  3068. void Panel::GetInset(int& left,int& top,int& right,int& bottom)
  3069. {
  3070. ipanel()->GetInset(GetVPanel(), left, top, right, bottom);
  3071. }
  3072. void Panel::GetPaintSize(int& wide,int& tall)
  3073. {
  3074. GetSize(wide, tall);
  3075. if (_border != NULL )
  3076. {
  3077. int left,top,right,bottom;
  3078. _border->GetInset(left,top,right,bottom);
  3079. wide -= (left+right);
  3080. tall -= (top+bottom);
  3081. }
  3082. }
  3083. int Panel::GetWide()
  3084. {
  3085. int wide, tall;
  3086. ipanel()->GetSize(GetVPanel(), wide, tall);
  3087. return wide;
  3088. }
  3089. void Panel::SetWide(int wide)
  3090. {
  3091. ipanel()->SetSize(GetVPanel(), wide, GetTall());
  3092. }
  3093. int Panel::GetTall()
  3094. {
  3095. int wide, tall;
  3096. ipanel()->GetSize(GetVPanel(), wide, tall);
  3097. return tall;
  3098. }
  3099. void Panel::SetTall(int tall)
  3100. {
  3101. ipanel()->SetSize(GetVPanel(), GetWide(), tall);
  3102. }
  3103. void Panel::GetSizerClientArea(int &x, int &y, int &wide, int &tall)
  3104. {
  3105. x = 0;
  3106. y = 0;
  3107. wide = GetWide();
  3108. tall = GetTall();
  3109. }
  3110. void Panel::GetSizerMinimumSize(int &wide, int &tall)
  3111. {
  3112. if( m_pSizer )
  3113. {
  3114. m_pSizer->GetMinSize(wide,tall);
  3115. }
  3116. else
  3117. {
  3118. wide = 5;
  3119. tall = 5;
  3120. }
  3121. }
  3122. CSizerBase* Panel::GetSizer()
  3123. {
  3124. return m_pSizer;
  3125. }
  3126. void Panel::SetSizer( CSizerBase* pSizer )
  3127. {
  3128. delete m_pSizer;
  3129. m_pSizer = pSizer;
  3130. }
  3131. CSizerBase::CSizerBase( )
  3132. {
  3133. m_nMinXSize = -1;
  3134. m_nMinYSize = -1;
  3135. }
  3136. CSizerBase::~CSizerBase( )
  3137. {
  3138. for( int i = 0; i < m_Members.Count(); ++i )
  3139. {
  3140. CSizerMember &member = m_Members[i];
  3141. member.DiscardOwnedSizer();
  3142. }
  3143. }
  3144. SizerElementType_t CSizerBase::GetElementType( int i )
  3145. {
  3146. return m_Members[i].GetElementType();
  3147. }
  3148. Panel *CSizerBase::GetPanel( int i )
  3149. {
  3150. Assert( m_Members[i].GetElementType() == ESET_PANEL );
  3151. return m_Members[i].GetPanel();
  3152. }
  3153. void CSizerBase::InsertPanel( int nIndex, Panel *pPanel, const SizerAddArgs_t& args )
  3154. {
  3155. CSizerMember sizerMember;
  3156. sizerMember.m_pPanel = pPanel;
  3157. sizerMember.m_pSizer = NULL;
  3158. sizerMember.Fill( args );
  3159. m_Members.InsertBefore( nIndex, sizerMember );
  3160. RecursiveInvalidateCachedSize();
  3161. }
  3162. void CSizerBase::InsertSizer( int nIndex, CSizerBase *pSizer, const SizerAddArgs_t& args )
  3163. {
  3164. CSizerMember sizerMember;
  3165. sizerMember.m_pPanel = NULL;
  3166. sizerMember.m_pSizer = pSizer;
  3167. sizerMember.Fill( args );
  3168. m_Members.InsertBefore( nIndex, sizerMember );
  3169. RecursiveInvalidateCachedSize();
  3170. }
  3171. void CSizerBase::InsertSpacer( int nIndex, const SizerAddArgs_t& args )
  3172. {
  3173. CSizerMember sizerMember;
  3174. sizerMember.m_pPanel = NULL;
  3175. sizerMember.m_pSizer = NULL;
  3176. sizerMember.Fill( args );
  3177. m_Members.InsertBefore( nIndex, sizerMember );
  3178. RecursiveInvalidateCachedSize();
  3179. }
  3180. void CSizerBase::RemoveAllMembers( bool bDelete )
  3181. {
  3182. for ( int i = 0; i < m_Members.Count(); ++i )
  3183. {
  3184. m_Members[i].RecursiveRemove( bDelete );
  3185. }
  3186. m_Members.RemoveAll();
  3187. m_nMinXSize = -1;
  3188. m_nMinYSize = -1;
  3189. }
  3190. void CSizerBase::GetMinSize( int &OutX, int &OutY )
  3191. {
  3192. if( m_nMinXSize == -1 || m_nMinYSize == -1 )
  3193. {
  3194. CalculateSize();
  3195. }
  3196. OutX = m_nMinXSize;
  3197. OutY = m_nMinYSize;
  3198. }
  3199. void CSizerBase::RecursiveInvalidateCachedSize()
  3200. {
  3201. m_nMinXSize = -1;
  3202. m_nMinYSize = -1;
  3203. for ( int i = 0; i < m_Members.Count(); ++ i )
  3204. {
  3205. m_Members[i].RecursiveInvalidateCachedSize();
  3206. }
  3207. }
  3208. SizerElementType_t CSizerBase::CSizerMember::GetElementType() const
  3209. {
  3210. if ( m_pPanel != NULL )
  3211. {
  3212. return ESET_PANEL;
  3213. }
  3214. else if ( m_pSizer != NULL )
  3215. {
  3216. return ESET_SIZER;
  3217. }
  3218. else
  3219. {
  3220. return ESET_SPACER;
  3221. }
  3222. }
  3223. Panel *CSizerBase::CSizerMember::GetPanel() const
  3224. {
  3225. return m_pPanel;
  3226. }
  3227. void CSizerBase::CSizerMember::Fill( const SizerAddArgs_t& args )
  3228. {
  3229. m_nPadding = args.m_nPadding;
  3230. m_flExpandFactor = args.m_flExpandFactor;
  3231. m_bMinorExpand = args.m_bMinorExpand;
  3232. m_nMinX = args.m_nMinX;
  3233. m_nMinY = args.m_nMinY;
  3234. m_bIgnoreMemberMin = args.m_bIgnoreMemberMin;
  3235. }
  3236. void CSizerBase::CSizerMember::RecursiveRemove( bool bDelete )
  3237. {
  3238. if ( m_pSizer )
  3239. {
  3240. m_pSizer->RemoveAllMembers(bDelete);
  3241. delete m_pSizer;
  3242. m_pSizer = NULL;
  3243. }
  3244. if ( m_pPanel )
  3245. {
  3246. if ( bDelete )
  3247. {
  3248. delete m_pPanel;
  3249. }
  3250. m_pPanel = NULL;
  3251. }
  3252. }
  3253. void CSizerBase::CSizerMember::DiscardOwnedSizer( )
  3254. {
  3255. if( m_pSizer )
  3256. {
  3257. // this is a sizer that is owned by the containing sizer, not another panel somewhere
  3258. delete m_pSizer;
  3259. m_pSizer = NULL;
  3260. }
  3261. }
  3262. void CSizerBase::CSizerMember::GetMemberMinSize( int &OutX, int &OutY )
  3263. {
  3264. int x = 0;
  3265. int y = 0;
  3266. if( m_pSizer )
  3267. {
  3268. m_pSizer->GetMinSize(x,y);
  3269. }
  3270. else if( m_pPanel )
  3271. {
  3272. m_pPanel->GetSizerMinimumSize(x,y);
  3273. }
  3274. else
  3275. {
  3276. // special case for spacers
  3277. OutX = MAX( m_nMinX, m_nPadding );
  3278. OutY = MAX( m_nMinY, m_nPadding );
  3279. return;
  3280. }
  3281. if ( m_bIgnoreMemberMin )
  3282. {
  3283. OutX = ( m_nMinX != -1 ? m_nMinX : x ) + m_nPadding*2;
  3284. OutY = ( m_nMinY != -1 ? m_nMinY : y ) + m_nPadding*2;
  3285. }
  3286. else
  3287. {
  3288. OutX = MAX( m_nMinX, x ) + m_nPadding*2;
  3289. OutY = MAX( m_nMinY, y ) + m_nPadding*2;
  3290. }
  3291. }
  3292. void CSizerBase::CSizerMember::RecursiveInvalidateCachedSize()
  3293. {
  3294. if ( m_pSizer )
  3295. {
  3296. m_pSizer->RecursiveInvalidateCachedSize();
  3297. }
  3298. else if ( m_pPanel && m_pPanel->GetSizer() )
  3299. {
  3300. m_pPanel->GetSizer()->RecursiveInvalidateCachedSize();
  3301. }
  3302. }
  3303. void CSizerBase::CSizerMember::Place( int BaseX, int BaseY, int SizeX, int SizeY )
  3304. {
  3305. if( m_pSizer )
  3306. {
  3307. m_pSizer->DoLayout( BaseX+m_nPadding, BaseY+m_nPadding, SizeX-m_nPadding*2, SizeY-m_nPadding*2 );
  3308. }
  3309. else if( m_pPanel )
  3310. {
  3311. m_pPanel->SetPos( BaseX+m_nPadding, BaseY+m_nPadding );
  3312. m_pPanel->SetSize( SizeX-m_nPadding*2, SizeY-m_nPadding*2 );
  3313. m_pPanel->InvalidateLayout();
  3314. }
  3315. else
  3316. {
  3317. // nothing to do for a spacer
  3318. }
  3319. }
  3320. bool CSizerBase::CSizerMember::IsVisible( )
  3321. {
  3322. if( m_pPanel )
  3323. {
  3324. return m_pPanel->IsVisible();
  3325. }
  3326. else
  3327. {
  3328. // sub-sizers and spacers are always visible
  3329. return true;
  3330. }
  3331. }
  3332. CBoxSizer::CBoxSizer( SizerLayoutDirection_t LayoutDirection )
  3333. {
  3334. m_LayoutDirection = LayoutDirection;
  3335. }
  3336. void CBoxSizer::CalculateSize()
  3337. {
  3338. int sumMajor = 0;
  3339. int maxMinor = 0;
  3340. for( int i = 0; i < m_Members.Count(); ++i )
  3341. {
  3342. CSizerMember &member = m_Members[i];
  3343. if ( !member.IsVisible() )
  3344. continue;
  3345. int x = 0;
  3346. int y = 0;
  3347. member.GetMemberMinSize(x,y);
  3348. maxMinor = MAX( maxMinor, SizerMinorAxis(m_LayoutDirection,x,y) );
  3349. sumMajor += SizerMajorAxis(m_LayoutDirection,x,y);
  3350. }
  3351. m_nMinXSize = SizerXAxis( m_LayoutDirection, sumMajor, maxMinor );
  3352. m_nMinYSize = SizerYAxis( m_LayoutDirection, sumMajor, maxMinor );
  3353. }
  3354. void CBoxSizer::DoLayout( int BaseX, int BaseY, int SizeX, int SizeY )
  3355. {
  3356. int nMinX = 0;
  3357. int nMinY = 0;
  3358. GetMinSize(nMinX,nMinY);
  3359. int nMajorRemainder = SizerMajorAxis(m_LayoutDirection,SizeX,SizeY) - SizerMajorAxis(m_LayoutDirection,nMinX,nMinY);
  3360. int nMinorSize = SizerMinorAxis(m_LayoutDirection,SizeX,SizeY);
  3361. float flExpandSum = 0;
  3362. for( int i = 0; i < m_Members.Count(); ++i )
  3363. {
  3364. CSizerMember &member = m_Members[i];
  3365. if ( !member.IsVisible() )
  3366. continue;
  3367. flExpandSum += member.GetExpandFactor();
  3368. }
  3369. int nCurrentX = BaseX;
  3370. int nCurrentY = BaseY;
  3371. for( int i = 0; i < m_Members.Count(); ++i )
  3372. {
  3373. CSizerMember &member = m_Members[i];
  3374. if ( !member.IsVisible() )
  3375. continue;
  3376. float flMemberExpand = member.GetExpandFactor();
  3377. int nExpansion = 0;
  3378. if( flMemberExpand > 0.f )
  3379. {
  3380. nExpansion = MAX( 0, (flMemberExpand/flExpandSum) * nMajorRemainder );
  3381. }
  3382. int nMemberXSize = 0;
  3383. int nMemberYSize = 0;
  3384. member.GetMemberMinSize(nMemberXSize,nMemberYSize);
  3385. int nMemberMajor = SizerMajorAxis(m_LayoutDirection,nMemberXSize,nMemberYSize);
  3386. int nMemberMinor = SizerMinorAxis(m_LayoutDirection,nMemberXSize,nMemberYSize);
  3387. nMemberMajor += nExpansion;
  3388. if( member.GetMinorExpand() )
  3389. {
  3390. nMemberMinor = nMinorSize;
  3391. }
  3392. nMemberXSize = SizerXAxis(m_LayoutDirection,nMemberMajor,nMemberMinor);
  3393. nMemberYSize = SizerYAxis(m_LayoutDirection,nMemberMajor,nMemberMinor);
  3394. member.Place( nCurrentX, nCurrentY, nMemberXSize, nMemberYSize );
  3395. // TODO: Padding
  3396. if( m_LayoutDirection == ESLD_HORIZONTAL )
  3397. {
  3398. nCurrentX += nMemberXSize;
  3399. }
  3400. else
  3401. {
  3402. nCurrentY += nMemberYSize;
  3403. }
  3404. nMajorRemainder -= nExpansion;
  3405. flExpandSum -= flMemberExpand;
  3406. }
  3407. }
  3408. void Panel::SetBuildGroup(BuildGroup* buildGroup)
  3409. {
  3410. if ( _buildGroup == buildGroup )
  3411. return;
  3412. if ( _buildGroup.Get() )
  3413. {
  3414. _buildGroup->PanelRemoved( this );
  3415. }
  3416. _buildGroup = buildGroup;
  3417. if ( _buildGroup.Get() )
  3418. {
  3419. _buildGroup->PanelAdded(this);
  3420. }
  3421. }
  3422. bool Panel::IsBuildGroupEnabled()
  3423. {
  3424. if ( !_buildGroup.IsValid() )
  3425. return false;
  3426. bool enabled = _buildGroup->IsEnabled();
  3427. if ( enabled )
  3428. return enabled;
  3429. if ( GetParent() && GetParent()->IsBuildGroupEnabled() )
  3430. return true;
  3431. return false;
  3432. }
  3433. void Panel::SetBgColor(Color color)
  3434. {
  3435. _bgColor = color;
  3436. }
  3437. void Panel::SetFgColor(Color color)
  3438. {
  3439. _fgColor = color;
  3440. }
  3441. Color Panel::GetBgColor()
  3442. {
  3443. return _bgColor;
  3444. }
  3445. Color Panel::GetFgColor()
  3446. {
  3447. return _fgColor;
  3448. }
  3449. void Panel::InternalPerformLayout()
  3450. {
  3451. _flags.SetFlag( IN_PERFORM_LAYOUT );
  3452. // make sure the scheme has been applied
  3453. _flags.ClearFlag( NEEDS_LAYOUT );
  3454. PerformLayout();
  3455. _flags.ClearFlag( IN_PERFORM_LAYOUT );
  3456. }
  3457. void Panel::PerformLayout()
  3458. {
  3459. // this should be overridden to relayout controls
  3460. if( m_pSizer )
  3461. {
  3462. // Re-layout all child panels
  3463. m_pSizer->RecursiveInvalidateCachedSize();
  3464. int x, y, wide, tall;
  3465. GetSizerClientArea( x, y, wide, tall );
  3466. m_pSizer->DoLayout( x, y, wide, tall );
  3467. int min_wide, min_tall;
  3468. m_pSizer->GetMinSize(min_wide,min_tall);
  3469. }
  3470. }
  3471. void Panel::InvalidateLayout( bool layoutNow, bool reloadScheme )
  3472. {
  3473. _flags.SetFlag( NEEDS_LAYOUT );
  3474. if (reloadScheme)
  3475. {
  3476. // make all our children reload the scheme
  3477. _flags.SetFlag( NEEDS_SCHEME_UPDATE );
  3478. for (int i = 0; i < GetChildCount(); i++)
  3479. {
  3480. vgui::Panel* panel = GetChild(i);
  3481. if( panel )
  3482. {
  3483. panel->InvalidateLayout(layoutNow, true);
  3484. }
  3485. }
  3486. PerformApplySchemeSettings();
  3487. }
  3488. if (layoutNow)
  3489. {
  3490. InternalPerformLayout();
  3491. Repaint();
  3492. }
  3493. }
  3494. bool Panel::IsCursorNone()
  3495. {
  3496. HCursor cursor = GetCursor();
  3497. if (!cursor)
  3498. {
  3499. return true;
  3500. }
  3501. return false;
  3502. }
  3503. //-----------------------------------------------------------------------------
  3504. // Purpose: returns true if the cursor is currently over the panel
  3505. // Output : Returns true on success, false on failure.
  3506. //-----------------------------------------------------------------------------
  3507. bool Panel::IsCursorOver(void)
  3508. {
  3509. int x, y;
  3510. input()->GetCursorPos(x, y);
  3511. return IsWithin(x, y);
  3512. }
  3513. //-----------------------------------------------------------------------------
  3514. // Purpose: Called when a panel receives a command message from another panel
  3515. //-----------------------------------------------------------------------------
  3516. void Panel::OnCommand(const char *command)
  3517. {
  3518. // if noone else caught this, pass along to the listeners
  3519. // (this is useful for generic dialogs - otherwise, commands just get ignored)
  3520. KeyValues *msg = new KeyValues( command );
  3521. PostActionSignal( msg );
  3522. }
  3523. //-----------------------------------------------------------------------------
  3524. // Purpose: panel gained focus message
  3525. //-----------------------------------------------------------------------------
  3526. void Panel::OnSetFocus()
  3527. {
  3528. Repaint();
  3529. }
  3530. //-----------------------------------------------------------------------------
  3531. // Purpose: panel lost focus message
  3532. //-----------------------------------------------------------------------------
  3533. void Panel::OnKillFocus()
  3534. {
  3535. Repaint();
  3536. }
  3537. //-----------------------------------------------------------------------------
  3538. // Purpose: Sets the object up to be deleted next frame
  3539. //-----------------------------------------------------------------------------
  3540. void Panel::MarkForDeletion()
  3541. {
  3542. if ( _flags.IsFlagSet( MARKED_FOR_DELETION ) )
  3543. return;
  3544. _flags.SetFlag( MARKED_FOR_DELETION );
  3545. _flags.ClearFlag( AUTODELETE_ENABLED );
  3546. if (ivgui()->IsRunning())
  3547. {
  3548. ivgui()->MarkPanelForDeletion(GetVPanel());
  3549. }
  3550. else
  3551. {
  3552. delete this;
  3553. }
  3554. }
  3555. //-----------------------------------------------------------------------------
  3556. // Purpose: return true if this object require a perform layout
  3557. //-----------------------------------------------------------------------------
  3558. bool Panel::IsLayoutInvalid()
  3559. {
  3560. return _flags.IsFlagSet( NEEDS_LAYOUT );
  3561. }
  3562. //-----------------------------------------------------------------------------
  3563. // Sets the pin corner + resize mode for resizing panels
  3564. //-----------------------------------------------------------------------------
  3565. void Panel::SetAutoResize( PinCorner_e pinCorner, AutoResize_e resizeDir,
  3566. int nPinOffsetX, int nPinOffsetY, int nUnpinnedCornerOffsetX, int nUnpinnedCornerOffsetY )
  3567. {
  3568. _pinCorner = pinCorner;
  3569. _autoResizeDirection = resizeDir;
  3570. m_nPinDeltaX = nPinOffsetX;
  3571. m_nPinDeltaY = nPinOffsetY;
  3572. m_nResizeDeltaX = nUnpinnedCornerOffsetX;
  3573. m_nResizeDeltaY = nUnpinnedCornerOffsetY;
  3574. }
  3575. //-----------------------------------------------------------------------------
  3576. // Sets the pin corner for non-resizing panels
  3577. //-----------------------------------------------------------------------------
  3578. void Panel::SetPinCorner( PinCorner_e pinCorner, int nOffsetX, int nOffsetY )
  3579. {
  3580. _pinCorner = pinCorner;
  3581. _autoResizeDirection = AUTORESIZE_NO;
  3582. m_nPinDeltaX = nOffsetX;
  3583. m_nPinDeltaY = nOffsetY;
  3584. m_nResizeDeltaX = 0;
  3585. m_nResizeDeltaY = 0;
  3586. }
  3587. //-----------------------------------------------------------------------------
  3588. // Purpose: data accessor
  3589. //-----------------------------------------------------------------------------
  3590. Panel::PinCorner_e Panel::GetPinCorner()
  3591. {
  3592. return (PinCorner_e)_pinCorner;
  3593. }
  3594. //-----------------------------------------------------------------------------
  3595. // Gets the relative offset of the control from the pin corner
  3596. //-----------------------------------------------------------------------------
  3597. void Panel::GetPinOffset( int &dx, int &dy )
  3598. {
  3599. dx = m_nPinDeltaX;
  3600. dy = m_nPinDeltaY;
  3601. }
  3602. //-----------------------------------------------------------------------------
  3603. // Purpose: data accessor
  3604. //-----------------------------------------------------------------------------
  3605. Panel::AutoResize_e Panel::GetAutoResize()
  3606. {
  3607. return (AutoResize_e)_autoResizeDirection;
  3608. }
  3609. //-----------------------------------------------------------------------------
  3610. // Gets the relative offset of the control from the pin corner
  3611. //-----------------------------------------------------------------------------
  3612. void Panel::GetResizeOffset( int &dx, int &dy )
  3613. {
  3614. dx = m_nResizeDeltaX;
  3615. dy = m_nResizeDeltaY;
  3616. }
  3617. //-----------------------------------------------------------------------------
  3618. // Tells this panel that it should pin itself to the corner of a specified sibling panel
  3619. //-----------------------------------------------------------------------------
  3620. void Panel::PinToSibling( const char *pszSibling, PinCorner_e pinOurCorner, PinCorner_e pinSibling )
  3621. {
  3622. _pinCornerToSibling = pinOurCorner;
  3623. _pinToSiblingCorner = pinSibling;
  3624. if ( _pinToSibling && pszSibling && !Q_strcmp( _pinToSibling, pszSibling ) )
  3625. return;
  3626. if (_pinToSibling)
  3627. {
  3628. delete [] _pinToSibling;
  3629. _pinToSibling = NULL;
  3630. }
  3631. if (pszSibling)
  3632. {
  3633. int len = Q_strlen(pszSibling) + 1;
  3634. _pinToSibling = new char[ len ];
  3635. Q_strncpy( _pinToSibling, pszSibling, len );
  3636. }
  3637. m_pinSibling = NULL;
  3638. UpdateSiblingPin();
  3639. }
  3640. //-----------------------------------------------------------------------------
  3641. // Purpose:
  3642. //-----------------------------------------------------------------------------
  3643. void Panel::UpdateSiblingPin( void )
  3644. {
  3645. if ( !_pinToSibling )
  3646. {
  3647. ipanel()->SetSiblingPin(GetVPanel(), NULL);
  3648. return;
  3649. }
  3650. if ( !m_pinSibling.Get() )
  3651. {
  3652. // Resolve our sibling now
  3653. m_pinSibling = FindSiblingByName( _pinToSibling );
  3654. }
  3655. if ( m_pinSibling.Get() )
  3656. {
  3657. ipanel()->SetSiblingPin( GetVPanel(), m_pinSibling->GetVPanel(), _pinCornerToSibling, _pinToSiblingCorner );
  3658. }
  3659. else
  3660. {
  3661. ipanel()->SetSiblingPin(GetVPanel(), NULL);
  3662. }
  3663. }
  3664. //-----------------------------------------------------------------------------
  3665. // Purpose:
  3666. //-----------------------------------------------------------------------------
  3667. void Panel::ApplySchemeSettings(IScheme *pScheme)
  3668. {
  3669. if ( m_bUseSchemeColors )
  3670. {
  3671. // get colors
  3672. SetFgColor(GetSchemeColor("Panel.FgColor", pScheme));
  3673. SetBgColor(GetSchemeColor("Panel.BgColor", pScheme));
  3674. }
  3675. #if defined( VGUI_USEDRAGDROP )
  3676. m_clrDragFrame = pScheme->GetColor("DragDrop.DragFrame", Color(255, 255, 255, 192));
  3677. m_clrDropFrame = pScheme->GetColor("DragDrop.DropFrame", Color(150, 255, 150, 255));
  3678. m_infoFont = pScheme->GetFont( "DefaultVerySmall" );
  3679. #endif
  3680. if ( m_sBorderName.IsValid() )
  3681. {
  3682. // re-get the border pointer in case the scheme reloaded underneath us
  3683. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  3684. SetBorder( pScheme->GetBorder( m_sBorderName.String() ) );
  3685. }
  3686. // mark us as no longer needing scheme settings applied
  3687. _flags.ClearFlag( NEEDS_SCHEME_UPDATE );
  3688. if ( IsBuildGroupEnabled() )
  3689. {
  3690. _buildGroup->ApplySchemeSettings(pScheme);
  3691. return;
  3692. }
  3693. }
  3694. //-----------------------------------------------------------------------------
  3695. // Purpose: Checks to see if the panel needs it's scheme info setup
  3696. //-----------------------------------------------------------------------------
  3697. void Panel::PerformApplySchemeSettings()
  3698. {
  3699. if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) )
  3700. {
  3701. InternalInitDefaultValues( GetAnimMap() );
  3702. }
  3703. if ( _flags.IsFlagSet( NEEDS_SCHEME_UPDATE ) )
  3704. {
  3705. VPROF( "ApplySchemeSettings" );
  3706. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  3707. AssertOnce( pScheme );
  3708. if ( pScheme ) // this should NEVER be null, but if it is bad things would happen in ApplySchemeSettings...
  3709. {
  3710. // Save any overridden colors before the scheme has been loaded
  3711. CUtlVector< Color > savedColors;
  3712. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  3713. {
  3714. savedColors.AddToTail( *m_OverridableColorEntries[i].m_pColor );
  3715. }
  3716. ApplySchemeSettings( pScheme );
  3717. //_needsSchemeUpdate = false;
  3718. // Re-apply any overridden colors after the scheme has been loaded
  3719. ApplyOverridableColors( pScheme );
  3720. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  3721. {
  3722. if ( m_OverridableColorEntries[i].m_bOverridden )
  3723. {
  3724. *m_OverridableColorEntries[i].m_pColor = savedColors[i];
  3725. }
  3726. }
  3727. UpdateSiblingPin();
  3728. }
  3729. }
  3730. }
  3731. //-----------------------------------------------------------------------------
  3732. // Purpose: Loads panel details related to autoresize from the resource info
  3733. //-----------------------------------------------------------------------------
  3734. #if defined( _DEBUG )
  3735. static Panel *lastWarningParent = 0;
  3736. #endif
  3737. void Panel::ApplyAutoResizeSettings(KeyValues *inResourceData)
  3738. {
  3739. int x, y;
  3740. GetPos(x, y);
  3741. int wide, tall;
  3742. GetSize( wide, tall );
  3743. AutoResize_e autoResize = (AutoResize_e)inResourceData->GetInt( "AutoResize", AUTORESIZE_NO );
  3744. PinCorner_e pinCorner = (PinCorner_e)inResourceData->GetInt( "PinCorner", PIN_NO );
  3745. // By default, measure unpinned corner for the offset
  3746. int pw = wide, pt = tall;
  3747. if ( GetParent() )
  3748. {
  3749. GetParent()->GetSize( pw, pt );
  3750. #if defined( _DEBUG )
  3751. if ( pw == 64 && pt == 24 )
  3752. {
  3753. if ( GetParent() != lastWarningParent )
  3754. {
  3755. lastWarningParent = GetParent();
  3756. Warning( "Resize parent (panel(%s) -> parent(%s)) not sized yet!!!\n", GetName(), GetParent()->GetName() );
  3757. }
  3758. }
  3759. #endif
  3760. }
  3761. int nPinnedCornerOffsetX = 0, nPinnedCornerOffsetY = 0;
  3762. int nUnpinnedCornerOffsetX = 0, nUnpinnedCornerOffsetY = 0;
  3763. switch( pinCorner )
  3764. {
  3765. case PIN_TOPLEFT:
  3766. nPinnedCornerOffsetX = x;
  3767. nPinnedCornerOffsetY = y;
  3768. nUnpinnedCornerOffsetX = (x + wide) - pw;
  3769. nUnpinnedCornerOffsetY = (y + tall) - pt;
  3770. break;
  3771. case PIN_TOPRIGHT:
  3772. nPinnedCornerOffsetX = (x + wide) - pw;
  3773. nPinnedCornerOffsetY = y;
  3774. nUnpinnedCornerOffsetX = x;
  3775. nUnpinnedCornerOffsetY = (y + tall) - pt;
  3776. break;
  3777. case PIN_BOTTOMLEFT:
  3778. nPinnedCornerOffsetX = x;
  3779. nPinnedCornerOffsetY = (y + tall) - pt;
  3780. nUnpinnedCornerOffsetX = (x + wide) - pw;
  3781. nUnpinnedCornerOffsetY = y;
  3782. break;
  3783. case PIN_BOTTOMRIGHT:
  3784. nPinnedCornerOffsetX = (x + wide) - pw;
  3785. nPinnedCornerOffsetY = (y + tall) - pt;
  3786. nUnpinnedCornerOffsetX = x;
  3787. nUnpinnedCornerOffsetY = y;
  3788. break;
  3789. }
  3790. // Allow specific overrides in the resource file
  3791. if ( IsProportional() )
  3792. {
  3793. if ( inResourceData->FindKey( "PinnedCornerOffsetX" ) )
  3794. {
  3795. nPinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetX" ) );
  3796. }
  3797. if ( inResourceData->FindKey( "PinnedCornerOffsetY" ) )
  3798. {
  3799. nPinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetY" ) );
  3800. }
  3801. if ( inResourceData->FindKey( "UnpinnedCornerOffsetX" ) )
  3802. {
  3803. nUnpinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetX" ) );
  3804. }
  3805. if ( inResourceData->FindKey( "UnpinnedCornerOffsetY" ) )
  3806. {
  3807. nUnpinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetY" ) );
  3808. }
  3809. }
  3810. else
  3811. {
  3812. nPinnedCornerOffsetX = inResourceData->GetInt( "PinnedCornerOffsetX", nPinnedCornerOffsetX );
  3813. nPinnedCornerOffsetY = inResourceData->GetInt( "PinnedCornerOffsetY", nPinnedCornerOffsetY );
  3814. nUnpinnedCornerOffsetX = inResourceData->GetInt( "UnpinnedCornerOffsetX", nUnpinnedCornerOffsetX );
  3815. nUnpinnedCornerOffsetY = inResourceData->GetInt( "UnpinnedCornerOffsetY", nUnpinnedCornerOffsetY );
  3816. }
  3817. if ( autoResize == AUTORESIZE_NO )
  3818. {
  3819. nUnpinnedCornerOffsetX = nUnpinnedCornerOffsetY = 0;
  3820. }
  3821. SetAutoResize( pinCorner, autoResize, nPinnedCornerOffsetX, nPinnedCornerOffsetY, nUnpinnedCornerOffsetX, nUnpinnedCornerOffsetY );
  3822. }
  3823. ConVar panel_test_title_safe( "panel_test_title_safe", "0", FCVAR_CHEAT, "Test vgui panel positioning with title safe indentation" );
  3824. //-----------------------------------------------------------------------------
  3825. // Purpose: Loads panel details from the resource info
  3826. //-----------------------------------------------------------------------------
  3827. void Panel::ApplySettings(KeyValues *inResourceData)
  3828. {
  3829. if ( m_bIsDMXSerialized )
  3830. return;
  3831. // First restore to default values
  3832. if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) )
  3833. {
  3834. InternalInitDefaultValues( GetAnimMap() );
  3835. }
  3836. // Let PanelAnimationVars auto-retrieve settings (we restore defaults above
  3837. // since a script might be missing certain values)
  3838. InternalApplySettings( GetAnimMap(), inResourceData );
  3839. // clear any alignment flags
  3840. _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 | BUILDMODE_SAVE_PERCENTAGE);
  3841. // get the position
  3842. int alignScreenWide, alignScreenTall; // screen dimensions used for pinning in splitscreen
  3843. surface()->GetScreenSize( alignScreenWide, alignScreenTall );
  3844. int screenWide = alignScreenWide;
  3845. int screenTall = alignScreenTall;
  3846. // temporarily remove the override to get the fullscreen dimensions
  3847. if ( surface()->IsScreenSizeOverrideActive() )
  3848. {
  3849. surface()->ForceScreenSizeOverride( false, 0, 0 );
  3850. surface()->GetScreenSize( screenWide, screenTall );
  3851. // restore the override
  3852. surface()->ForceScreenSizeOverride( true, alignScreenWide, alignScreenTall );
  3853. }
  3854. int parentX = 0;
  3855. int parentY = 0;
  3856. // flag to cause windows to get screenWide and screenTall from their parents,
  3857. // this allows children windows to use fill and right/bottom alignment even
  3858. // if their parent does not use the full screen.
  3859. if ( inResourceData->GetInt( "proportionalToParent", 0 ) == 1 )
  3860. {
  3861. _buildModeFlags |= BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT;
  3862. if ( GetParent() != NULL )
  3863. {
  3864. GetParent()->GetBounds( parentX, parentY, alignScreenWide, alignScreenTall );
  3865. }
  3866. }
  3867. int x, y;
  3868. GetPos(x, y);
  3869. const char *xstr = inResourceData->GetString( "xpos", NULL );
  3870. const char *ystr = inResourceData->GetString( "ypos", NULL );
  3871. if (xstr)
  3872. {
  3873. // look for alignment flags
  3874. if (xstr[0] == 'r' || xstr[0] == 'R')
  3875. {
  3876. _buildModeFlags |= BUILDMODE_SAVE_XPOS_RIGHTALIGNED;
  3877. xstr++;
  3878. }
  3879. else if (xstr[0] == 'c' || xstr[0] == 'C')
  3880. {
  3881. _buildModeFlags |= BUILDMODE_SAVE_XPOS_CENTERALIGNED;
  3882. xstr++;
  3883. }
  3884. else if ( xstr[0] == '%' )
  3885. {
  3886. _buildModeFlags |= BUILDMODE_SAVE_PERCENTAGE;
  3887. xstr++;
  3888. }
  3889. // get the value
  3890. x = atoi(xstr);
  3891. // scale the x up to our screen coords
  3892. if ( IsProportional() && ( ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE ) == 0 ) )
  3893. {
  3894. x = scheme()->GetProportionalScaledValueEx(GetScheme(), x);
  3895. }
  3896. // now correct the alignment
  3897. if (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED)
  3898. {
  3899. x = alignScreenWide - x;
  3900. }
  3901. else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED)
  3902. {
  3903. x = (alignScreenWide / 2) + x;
  3904. }
  3905. else if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  3906. {
  3907. float flX = atof( xstr );
  3908. x = ( screenWide * ( flX / 100.0f ) );
  3909. }
  3910. }
  3911. if (ystr)
  3912. {
  3913. // look for alignment flags
  3914. if (ystr[0] == 'r' || ystr[0] == 'R')
  3915. {
  3916. _buildModeFlags |= BUILDMODE_SAVE_YPOS_BOTTOMALIGNED;
  3917. ystr++;
  3918. }
  3919. else if (ystr[0] == 'c' || ystr[0] == 'C')
  3920. {
  3921. _buildModeFlags |= BUILDMODE_SAVE_YPOS_CENTERALIGNED;
  3922. ystr++;
  3923. }
  3924. else if ( ystr[0] == '%' )
  3925. {
  3926. _buildModeFlags |= BUILDMODE_SAVE_PERCENTAGE;
  3927. ystr++;
  3928. }
  3929. y = atoi(ystr);
  3930. if ( IsProportional() && ( ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE ) == 0 ) )
  3931. {
  3932. // scale the y up to our screen co-ords
  3933. y = scheme()->GetProportionalScaledValueEx(GetScheme(), y);
  3934. }
  3935. // now correct the alignment
  3936. if (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED)
  3937. {
  3938. y = alignScreenTall - y;
  3939. }
  3940. else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED)
  3941. {
  3942. y = (alignScreenTall / 2) + y;
  3943. }
  3944. else if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  3945. {
  3946. float flY = atof( ystr );
  3947. y = ( screenTall * ( flY / 100.0f ) );
  3948. }
  3949. }
  3950. bool bUsesTitleSafeArea = false;
  3951. int titleSafeWide = 0;
  3952. int titleSafeTall = 0;
  3953. Rect_t excludeEdgeFromTitleSafe; // if a side is set to != 0, don't title safe relative to that edge
  3954. excludeEdgeFromTitleSafe.x = 0;
  3955. excludeEdgeFromTitleSafe.y = 0;
  3956. excludeEdgeFromTitleSafe.width = 0;
  3957. excludeEdgeFromTitleSafe.height = 0;
  3958. if ( IsGameConsole() || panel_test_title_safe.GetBool() )
  3959. {
  3960. // "usetitlesafe" "1" - required inner 90%
  3961. // "usetitlesafe" "2" - suggested inner 85%
  3962. int iUseTitleSafeValue = 0;
  3963. if ( inResourceData->FindKey( "usetitlesafe" ) )
  3964. {
  3965. iUseTitleSafeValue = inResourceData->GetInt( "usetitlesafe" );
  3966. if ( IsPS3() && iUseTitleSafeValue > 0 )
  3967. {
  3968. // per PS3 Cert, R030 - required is 85%
  3969. // xbox is more reasonable and only requires 90%
  3970. iUseTitleSafeValue = 2;
  3971. }
  3972. bUsesTitleSafeArea = ( iUseTitleSafeValue > 0 );
  3973. }
  3974. if ( bUsesTitleSafeArea )
  3975. {
  3976. titleSafeWide = screenWide * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f );
  3977. titleSafeTall = screenTall * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f );
  3978. // Don't title safe internal boundaries for split screen viewports
  3979. int splitX = 0;
  3980. int splitY = 0;
  3981. vgui::surface()->OffsetAbsPos( splitX, splitY );
  3982. bool bHorizontalSplit = ( alignScreenTall != screenTall );
  3983. bool bVerticalSplit = ( alignScreenWide != screenWide );
  3984. if ( bHorizontalSplit )
  3985. {
  3986. // top or bottom?
  3987. if ( splitY != parentY )
  3988. {
  3989. excludeEdgeFromTitleSafe.y = 1;
  3990. }
  3991. else
  3992. {
  3993. excludeEdgeFromTitleSafe.height = 1;
  3994. }
  3995. }
  3996. if ( bVerticalSplit )
  3997. {
  3998. // left or right
  3999. if ( splitX != parentX )
  4000. {
  4001. excludeEdgeFromTitleSafe.x = 1;
  4002. }
  4003. else
  4004. {
  4005. excludeEdgeFromTitleSafe.width = 1;
  4006. }
  4007. }
  4008. if ( _buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED )
  4009. {
  4010. if ( !excludeEdgeFromTitleSafe.width )
  4011. {
  4012. x -= titleSafeWide; // right edge
  4013. }
  4014. }
  4015. else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED)
  4016. {
  4017. }
  4018. else if ( !excludeEdgeFromTitleSafe.x )
  4019. {
  4020. x += titleSafeWide; // left edge
  4021. }
  4022. if ( _buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED )
  4023. {
  4024. if ( !excludeEdgeFromTitleSafe.height )
  4025. {
  4026. y -= titleSafeTall; // bottom edge
  4027. }
  4028. }
  4029. else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED)
  4030. {
  4031. }
  4032. else if ( !excludeEdgeFromTitleSafe.y )
  4033. {
  4034. y += titleSafeTall; // top edge
  4035. }
  4036. }
  4037. }
  4038. SetNavUp( inResourceData->GetString("navUp") );
  4039. SetNavDown( inResourceData->GetString("navDown") );
  4040. SetNavLeft( inResourceData->GetString("navLeft") );
  4041. SetNavRight( inResourceData->GetString("navRight") );
  4042. SetPos(x, y);
  4043. if (inResourceData->FindKey( "zpos" ))
  4044. {
  4045. SetZPos( inResourceData->GetInt( "zpos" ) );
  4046. }
  4047. // size
  4048. int wide, tall;
  4049. GetSize( wide, tall );
  4050. const char *wstr = inResourceData->GetString( "wide", NULL );
  4051. if ( wstr )
  4052. {
  4053. if (wstr[0] == 'f' || wstr[0] == 'F')
  4054. {
  4055. _buildModeFlags |= BUILDMODE_SAVE_WIDE_FULL;
  4056. wstr++;
  4057. }
  4058. else if ( wstr[0] == '%' )
  4059. {
  4060. _buildModeFlags |= BUILDMODE_SAVE_PERCENTAGE;
  4061. wstr++;
  4062. }
  4063. wide = atoi(wstr);
  4064. if ( IsProportional() && ( ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE ) == 0 ) )
  4065. {
  4066. // scale the width up to our screen co-ords
  4067. wide = scheme()->GetProportionalScaledValueEx(GetScheme(), wide);
  4068. }
  4069. // now correct the alignment
  4070. if (_buildModeFlags & BUILDMODE_SAVE_WIDE_FULL)
  4071. {
  4072. wide = alignScreenWide - wide;
  4073. }
  4074. else if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  4075. {
  4076. float flWide = atof( wstr );
  4077. wide = ( screenWide * ( flWide / 100.0f ) );
  4078. }
  4079. }
  4080. // allow tall to be use the "fill" option, set to the height of the parent/screen
  4081. wstr = inResourceData->GetString( "tall", NULL );
  4082. if ( wstr )
  4083. {
  4084. if (wstr[0] == 'f' || wstr[0] == 'F')
  4085. {
  4086. _buildModeFlags |= BUILDMODE_SAVE_TALL_FULL;
  4087. wstr++;
  4088. }
  4089. else if ( wstr[0] == '%' )
  4090. {
  4091. _buildModeFlags |= BUILDMODE_SAVE_PERCENTAGE;
  4092. wstr++;
  4093. }
  4094. tall = atoi(wstr);
  4095. if ( IsProportional() && ( ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE ) == 0 ) )
  4096. {
  4097. // scale the height up to our screen co-ords
  4098. tall = scheme()->GetProportionalScaledValueEx(GetScheme(), tall);
  4099. }
  4100. // now correct the alignment
  4101. if (_buildModeFlags & BUILDMODE_SAVE_TALL_FULL)
  4102. {
  4103. tall = alignScreenTall - tall;
  4104. }
  4105. else if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  4106. {
  4107. float flTall = atof( wstr );
  4108. tall = ( screenTall * ( flTall / 100.0f ) );
  4109. }
  4110. }
  4111. if( bUsesTitleSafeArea )
  4112. {
  4113. if ( _buildModeFlags & BUILDMODE_SAVE_WIDE_FULL )
  4114. {
  4115. if ( !excludeEdgeFromTitleSafe.x )
  4116. wide -= titleSafeWide;
  4117. if ( !excludeEdgeFromTitleSafe.width )
  4118. wide -= titleSafeWide;
  4119. }
  4120. if ( _buildModeFlags & BUILDMODE_SAVE_TALL_FULL )
  4121. {
  4122. if ( !excludeEdgeFromTitleSafe.y )
  4123. tall -= titleSafeTall;
  4124. if ( !excludeEdgeFromTitleSafe.height )
  4125. tall -= titleSafeTall;
  4126. }
  4127. }
  4128. SetSize( wide, tall );
  4129. // NOTE: This has to happen after pos + size is set
  4130. ApplyAutoResizeSettings( inResourceData );
  4131. // only get colors if we're ignoring the scheme
  4132. if (inResourceData->GetInt("IgnoreScheme", 0))
  4133. {
  4134. PerformApplySchemeSettings();
  4135. }
  4136. // state
  4137. int state = inResourceData->GetInt("visible", 1);
  4138. if (state == 0)
  4139. {
  4140. SetVisible(false);
  4141. }
  4142. else if (state == 1)
  4143. {
  4144. SetVisible(true);
  4145. }
  4146. SetEnabled( inResourceData->GetBool("enabled", true) );
  4147. // tab order
  4148. SetTabPosition(inResourceData->GetInt("tabPosition", 0));
  4149. const char *tooltip = inResourceData->GetString("tooltiptext", NULL);
  4150. if (tooltip && *tooltip)
  4151. {
  4152. GetTooltip()->SetText(tooltip);
  4153. }
  4154. // paint background?
  4155. int nPaintBackground = inResourceData->GetInt("paintbackground", -1);
  4156. if (nPaintBackground >= 0)
  4157. {
  4158. SetPaintBackgroundEnabled( nPaintBackground != 0 );
  4159. }
  4160. // paint border?
  4161. int nPaintBorder = inResourceData->GetInt("paintborder", -1);
  4162. if (nPaintBorder >= 0)
  4163. {
  4164. SetPaintBorderEnabled( nPaintBorder != 0 );
  4165. }
  4166. // border?
  4167. const char *pBorder = inResourceData->GetString( "border", "" );
  4168. if ( *pBorder )
  4169. {
  4170. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  4171. SetBorder( pScheme->GetBorder( pBorder ) );
  4172. }
  4173. // check to see if we have a new name assigned
  4174. const char *newName = inResourceData->GetString("fieldName", NULL);
  4175. if ( newName )
  4176. {
  4177. // Only slam the name if the new one differs...
  4178. SetName(newName);
  4179. }
  4180. //=============================================================================
  4181. // HPE_BEGIN:
  4182. // [pfreese] Support for reading rounded corner flags
  4183. //=============================================================================
  4184. int roundedCorners = inResourceData->GetInt( "RoundedCorners", -1 );
  4185. if ( roundedCorners >= 0 )
  4186. {
  4187. m_roundedCorners = roundedCorners;
  4188. }
  4189. //=============================================================================
  4190. // HPE_END
  4191. //=============================================================================
  4192. const char *pszSiblingName = inResourceData->GetString("pin_to_sibling", NULL);
  4193. PinCorner_e pinOurCornerToSibling = (PinCorner_e)inResourceData->GetInt( "pin_corner_to_sibling", PIN_TOPLEFT );
  4194. PinCorner_e pinSiblingCorner = (PinCorner_e)inResourceData->GetInt( "pin_to_sibling_corner", PIN_TOPLEFT );
  4195. PinToSibling( pszSiblingName, pinOurCornerToSibling, pinSiblingCorner );
  4196. // Allow overriding of colors. Used mostly by HUD elements, where scheme color usage is often undesired.
  4197. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4198. {
  4199. // Need to ensure the key exists, so we don't overwrite existing colors when it's not set.
  4200. KeyValues *colorKey = inResourceData->FindKey( m_OverridableColorEntries[i].m_pszScriptName, false );
  4201. if ( colorKey != NULL )
  4202. {
  4203. m_OverridableColorEntries[i].m_colFromScript = inResourceData->GetColor( m_OverridableColorEntries[i].m_pszScriptName );
  4204. (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript;
  4205. m_OverridableColorEntries[i].m_bOverridden = true;
  4206. const char *pszColorString = inResourceData->GetString( m_OverridableColorEntries[i].m_pszScriptName, "" );
  4207. if ( *pszColorString < '0' || *pszColorString > '9' ) // non-numeric strings are color references in the scheme file
  4208. {
  4209. m_OverridableColorEntries[i].m_sColorNameFromScript = g_OverridenColorSymbols.AddString( pszColorString );
  4210. }
  4211. else
  4212. {
  4213. m_OverridableColorEntries[i].m_sColorNameFromScript = UTL_INVAL_SYMBOL;
  4214. }
  4215. }
  4216. }
  4217. }
  4218. // Purpose: Get a proportional value with a specific rootpanel height
  4219. //-----------------------------------------------------------------------------
  4220. int Panel::GetProportionalScaledValue( int rootTall, int normalizedValue )
  4221. {
  4222. int proH, proW;
  4223. surface()->GetProportionalBase( proW, proH );
  4224. double scale = (double)rootTall / (double)proH;
  4225. return (int)( normalizedValue * scale );
  4226. }
  4227. //-----------------------------------------------------------------------------
  4228. // Purpose:
  4229. //-----------------------------------------------------------------------------
  4230. void Panel::OnUnserialized( CDmxElement *pElement )
  4231. {
  4232. ipanel()->OnUnserialized(GetVPanel(), pElement);
  4233. m_bIsDMXSerialized = true;
  4234. /*
  4235. // get the position
  4236. int x, y;
  4237. GetPos(x, y);
  4238. // scale the x,y up to our screen coords
  4239. if ( IsProportional() )
  4240. {
  4241. x = scheme()->GetProportionalScaledValueEx(GetScheme(), x);
  4242. y = scheme()->GetProportionalScaledValueEx(GetScheme(), y);
  4243. }
  4244. SetPos(x, y);
  4245. // size
  4246. int wide, tall;
  4247. GetSize( wide, tall );
  4248. // scale the wide and tall up to our screen co-ords
  4249. if ( IsProportional() )
  4250. {
  4251. // scale the x and y up to our screen co-ords
  4252. wide = scheme()->GetProportionalScaledValueEx(GetScheme(), wide);
  4253. tall = scheme()->GetProportionalScaledValueEx(GetScheme(), tall);
  4254. }
  4255. SetSize( wide, tall );
  4256. // NOTE: This has to happen after pos + size is set
  4257. ApplyAutoResizeSettings( inResourceData );
  4258. // only get colors if we're ignoring the scheme
  4259. if (inResourceData->GetInt("IgnoreScheme", 0))
  4260. {
  4261. //PerformApplySchemeSettings();
  4262. }
  4263. // state
  4264. int state = inResourceData->GetInt("visible", 1);
  4265. if (state == 0)
  4266. {
  4267. SetVisible(false);
  4268. }
  4269. else if (state == 1)
  4270. {
  4271. SetVisible(true);
  4272. }
  4273. SetEnabled( inResourceData->GetBool("enabled", true) );
  4274. // tab order
  4275. SetTabPosition(inResourceData->GetInt("tabPosition", 0));
  4276. const char *tooltip = inResourceData->GetString("tooltiptext", NULL);
  4277. if (tooltip && *tooltip)
  4278. {
  4279. GetTooltip()->SetText(tooltip);
  4280. }
  4281. // paint background?
  4282. int nPaintBackground = inResourceData->GetInt("paintbackground", -1);
  4283. if (nPaintBackground >= 0)
  4284. {
  4285. SetPaintBackgroundEnabled( nPaintBackground != 0 );
  4286. }
  4287. // paint border?
  4288. int nPaintBorder = inResourceData->GetInt("paintborder", -1);
  4289. if (nPaintBorder >= 0)
  4290. {
  4291. SetPaintBorderEnabled( nPaintBorder != 0 );
  4292. }
  4293. // check to see if we have a new name assigned
  4294. const char *newName = inResourceData->GetString("fieldName", NULL);
  4295. if ( newName )
  4296. {
  4297. // Only slam the name if the new one differs...
  4298. SetName(newName);
  4299. }
  4300. // Allow overriding of colors. Used mostly by HUD elements, where scheme color usage is often undesired.
  4301. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4302. {
  4303. // Need to ensure the key exists, so we don't overwrite existing colors when it's not set.
  4304. if ( inResourceData->FindKey( m_OverridableColorEntries[i].m_pszScriptName, false ) )
  4305. {
  4306. m_OverridableColorEntries[i].m_colFromScript = inResourceData->GetColor( m_OverridableColorEntries[i].m_pszScriptName );
  4307. (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript;
  4308. m_OverridableColorEntries[i].m_bOverridden = true;
  4309. }
  4310. }
  4311. */
  4312. }
  4313. //-----------------------------------------------------------------------------
  4314. // Purpose: Saves out a resource description of this panel
  4315. //-----------------------------------------------------------------------------
  4316. void Panel::GetSettings( KeyValues *outResourceData )
  4317. {
  4318. // control class name (so it can be recreated later if needed)
  4319. outResourceData->SetString( "ControlName", GetClassName() );
  4320. // name
  4321. outResourceData->SetString( "fieldName", _panelName.Get() );
  4322. // positioning
  4323. int screenWide, screenTall;
  4324. surface()->GetScreenSize(screenWide, screenTall);
  4325. int x, y;
  4326. GetPos( x, y );
  4327. if ( IsProportional() )
  4328. {
  4329. x = scheme()->GetProportionalNormalizedValueEx( GetScheme(), x );
  4330. y = scheme()->GetProportionalNormalizedValueEx( GetScheme(), y );
  4331. }
  4332. // correct for alignment
  4333. if (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED)
  4334. {
  4335. x = screenWide - x;
  4336. char xstr[32];
  4337. Q_snprintf(xstr, sizeof( xstr ), "r%d", x);
  4338. outResourceData->SetString( "xpos", xstr );
  4339. }
  4340. else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED)
  4341. {
  4342. x = (screenWide / 2) + x;
  4343. char xstr[32];
  4344. Q_snprintf(xstr, sizeof( xstr ), "c%d", x);
  4345. outResourceData->SetString( "xpos", xstr );
  4346. }
  4347. else if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  4348. {
  4349. x = x / screenWide;
  4350. char xstr[32];
  4351. V_snprintf( xstr, sizeof( xstr ), "%%%d", x );
  4352. outResourceData->SetString( "xpos", xstr );
  4353. }
  4354. else
  4355. {
  4356. outResourceData->SetInt( "xpos", x );
  4357. }
  4358. if (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED)
  4359. {
  4360. y = screenTall - y;
  4361. char ystr[32];
  4362. Q_snprintf(ystr, sizeof( ystr ), "r%d", y);
  4363. outResourceData->SetString( "ypos", ystr );
  4364. }
  4365. else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED)
  4366. {
  4367. y = (screenTall / 2) + y;
  4368. char ystr[32];
  4369. Q_snprintf(ystr, sizeof( ystr ), "c%d", y);
  4370. outResourceData->SetString( "ypos", ystr );
  4371. }
  4372. else if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  4373. {
  4374. y = y / screenTall;
  4375. char ystr[32];
  4376. V_snprintf( ystr, sizeof( ystr ), "%%%d", y );
  4377. outResourceData->SetString( "ypos", ystr );
  4378. }
  4379. else
  4380. {
  4381. outResourceData->SetInt( "ypos", y );
  4382. }
  4383. if (m_pTooltips)
  4384. {
  4385. if (strlen(m_pTooltips->GetText()) > 0)
  4386. {
  4387. outResourceData->SetString("tooltiptext", m_pTooltips->GetText());
  4388. }
  4389. }
  4390. int wide, tall;
  4391. GetSize( wide, tall );
  4392. if ( IsProportional() )
  4393. {
  4394. wide = scheme()->GetProportionalNormalizedValueEx( GetScheme(), wide );
  4395. tall = scheme()->GetProportionalNormalizedValueEx( GetScheme(), tall );
  4396. }
  4397. int z = ipanel()->GetZPos(GetVPanel());
  4398. if (z)
  4399. {
  4400. outResourceData->SetInt("zpos", z);
  4401. }
  4402. // Correct for alignment
  4403. if (_buildModeFlags & BUILDMODE_SAVE_WIDE_FULL )
  4404. {
  4405. wide = screenWide - wide;
  4406. char wstr[32];
  4407. Q_snprintf(wstr, sizeof( wstr ), "f%d", wide);
  4408. outResourceData->SetString( "wide", wstr );
  4409. }
  4410. else if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  4411. {
  4412. wide = wide / screenWide;
  4413. char wstr[32];
  4414. V_snprintf( wstr, sizeof( wstr ), "%%%d", wide );
  4415. outResourceData->SetString( "wide", wstr );
  4416. }
  4417. else
  4418. {
  4419. outResourceData->SetInt( "wide", wide );
  4420. }
  4421. if ( _buildModeFlags & BUILDMODE_SAVE_PERCENTAGE )
  4422. {
  4423. tall = tall / screenTall;
  4424. char tstr[32];
  4425. V_snprintf( tstr, sizeof( tstr ), "%%%d", tall );
  4426. outResourceData->SetString( "tall", tstr );
  4427. }
  4428. else
  4429. {
  4430. outResourceData->SetInt( "tall", tall );
  4431. }
  4432. outResourceData->SetInt("AutoResize", GetAutoResize());
  4433. outResourceData->SetInt("PinCorner", GetPinCorner());
  4434. //=============================================================================
  4435. // HPE_BEGIN:
  4436. // [pfreese] Support for writing out rounded corner flags
  4437. //=============================================================================
  4438. outResourceData->SetInt("RoundedCorners", m_roundedCorners);
  4439. //=============================================================================
  4440. // HPE_END
  4441. //=============================================================================
  4442. outResourceData->SetString( "pin_to_sibling", _pinToSibling );
  4443. outResourceData->SetInt("pin_corner_to_sibling", _pinCornerToSibling );
  4444. outResourceData->SetInt("pin_to_sibling_corner", _pinToSiblingCorner );
  4445. // state
  4446. outResourceData->SetBool( "visible", IsVisible() );
  4447. outResourceData->SetBool( "enabled", IsEnabled() );
  4448. outResourceData->SetInt( "tabPosition", GetTabPosition() );
  4449. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4450. {
  4451. if ( m_OverridableColorEntries[i].m_bOverridden )
  4452. {
  4453. if ( m_OverridableColorEntries[i].m_sColorNameFromScript != UTL_INVAL_SYMBOL )
  4454. {
  4455. outResourceData->SetString( m_OverridableColorEntries[i].m_pszScriptName, g_OverridenColorSymbols.String( m_OverridableColorEntries[i].m_sColorNameFromScript ) );
  4456. }
  4457. else
  4458. {
  4459. outResourceData->SetColor( m_OverridableColorEntries[i].m_pszScriptName, m_OverridableColorEntries[i].m_colFromScript );
  4460. }
  4461. }
  4462. }
  4463. }
  4464. //-----------------------------------------------------------------------------
  4465. // Purpose: After applying settings, apply overridable colors.
  4466. // Done post apply settings, so that baseclass settings don't stomp
  4467. // the script specified override colors.
  4468. //-----------------------------------------------------------------------------
  4469. void Panel::ApplyOverridableColors( IScheme *pScheme )
  4470. {
  4471. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4472. {
  4473. if ( m_OverridableColorEntries[i].m_bOverridden )
  4474. {
  4475. if ( m_OverridableColorEntries[i].m_sColorNameFromScript != UTL_INVAL_SYMBOL )
  4476. {
  4477. const char *colorName = g_OverridenColorSymbols.String( m_OverridableColorEntries[i].m_sColorNameFromScript );
  4478. (*m_OverridableColorEntries[i].m_pColor) = pScheme->GetColor( colorName, (*m_OverridableColorEntries[i].m_pColor) );
  4479. }
  4480. else
  4481. {
  4482. (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript;
  4483. }
  4484. }
  4485. }
  4486. }
  4487. //-----------------------------------------------------------------------------
  4488. // Purpose:
  4489. //-----------------------------------------------------------------------------
  4490. void Panel::SetOverridableColor( Color *pColor, const Color &newColor )
  4491. {
  4492. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4493. {
  4494. if ( m_OverridableColorEntries[i].m_bOverridden )
  4495. {
  4496. if ( m_OverridableColorEntries[i].m_pColor == pColor )
  4497. return;
  4498. }
  4499. }
  4500. // Didn't find it, or it's not been overridden.
  4501. *pColor = newColor;
  4502. }
  4503. //-----------------------------------------------------------------------------
  4504. // Purpose:
  4505. //-----------------------------------------------------------------------------
  4506. Color Panel::GetSchemeColor(const char *keyName, IScheme *pScheme)
  4507. {
  4508. return pScheme->GetColor(keyName, Color(255, 255, 255, 255));
  4509. }
  4510. //-----------------------------------------------------------------------------
  4511. // Purpose:
  4512. //-----------------------------------------------------------------------------
  4513. Color Panel::GetSchemeColor(const char *keyName, Color defaultColor, IScheme *pScheme)
  4514. {
  4515. return pScheme->GetColor(keyName, defaultColor);
  4516. }
  4517. //-----------------------------------------------------------------------------
  4518. // Purpose: Returns a string description of the panel fields for use in the UI
  4519. //-----------------------------------------------------------------------------
  4520. const char *Panel::GetDescription( void )
  4521. {
  4522. 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";
  4523. return panelDescription;
  4524. }
  4525. //-----------------------------------------------------------------------------
  4526. // Purpose: user configuration settings
  4527. // this is used for any control details the user wants saved between sessions
  4528. // eg. dialog positions, last directory opened, list column width
  4529. //-----------------------------------------------------------------------------
  4530. void Panel::ApplyUserConfigSettings(KeyValues *userConfig)
  4531. {
  4532. }
  4533. //-----------------------------------------------------------------------------
  4534. // Purpose: returns user config settings for this control
  4535. //-----------------------------------------------------------------------------
  4536. void Panel::GetUserConfigSettings(KeyValues *userConfig)
  4537. {
  4538. }
  4539. //-----------------------------------------------------------------------------
  4540. // Purpose: optimization, return true if this control has any user config settings
  4541. //-----------------------------------------------------------------------------
  4542. bool Panel::HasUserConfigSettings()
  4543. {
  4544. return false;
  4545. }
  4546. //-----------------------------------------------------------------------------
  4547. // Purpose:
  4548. //-----------------------------------------------------------------------------
  4549. void Panel::InternalInvalidateLayout()
  4550. {
  4551. InvalidateLayout(false, false);
  4552. }
  4553. //-----------------------------------------------------------------------------
  4554. // Purpose: called whenever the panel moves
  4555. //-----------------------------------------------------------------------------
  4556. void Panel::OnMove()
  4557. {
  4558. }
  4559. //-----------------------------------------------------------------------------
  4560. // Purpose:
  4561. //-----------------------------------------------------------------------------
  4562. void Panel::InternalMove()
  4563. {
  4564. OnMove();
  4565. for(int i=0;i<GetChildCount();i++)
  4566. {
  4567. // recursively apply to all children
  4568. GetChild(i)->OnMove();
  4569. }
  4570. }
  4571. //-----------------------------------------------------------------------------
  4572. // Purpose: empty function
  4573. //-----------------------------------------------------------------------------
  4574. void Panel::OnTick()
  4575. {
  4576. }
  4577. //-----------------------------------------------------------------------------
  4578. // Purpose: versioning
  4579. //-----------------------------------------------------------------------------
  4580. void *Panel::QueryInterface(EInterfaceID id)
  4581. {
  4582. if (id == ICLIENTPANEL_STANDARD_INTERFACE)
  4583. {
  4584. return this;
  4585. }
  4586. return NULL;
  4587. }
  4588. //-----------------------------------------------------------------------------
  4589. // Purpose: Map all the base messages to functions
  4590. // ordering from most -> least used improves speed
  4591. //-----------------------------------------------------------------------------
  4592. MessageMapItem_t Panel::m_MessageMap[] =
  4593. {
  4594. MAP_MESSAGE_INT( Panel, "RequestFocus", RequestFocus, "direction" )
  4595. };
  4596. // IMPLEMENT_PANELMAP( Panel, NULL )
  4597. PanelMap_t Panel::m_PanelMap = { Panel::m_MessageMap, ARRAYSIZE(Panel::m_MessageMap), "Panel", NULL };
  4598. PanelMap_t *Panel::GetPanelMap( void ) { return &m_PanelMap; }
  4599. //-----------------------------------------------------------------------------
  4600. // Purpose: !! Soon to replace existing prepare panel map
  4601. //-----------------------------------------------------------------------------
  4602. void PreparePanelMessageMap(PanelMessageMap *panelMap)
  4603. {
  4604. // iterate through the class hierarchy message maps
  4605. while ( panelMap != NULL && !panelMap->processed )
  4606. {
  4607. // hash message map strings into symbols
  4608. for (int i = 0; i < panelMap->entries.Count(); i++)
  4609. {
  4610. MessageMapItem_t *item = &panelMap->entries[i];
  4611. if (item->name)
  4612. {
  4613. item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name);
  4614. }
  4615. else
  4616. {
  4617. item->nameSymbol = INVALID_KEY_SYMBOL;
  4618. }
  4619. if (item->firstParamName)
  4620. {
  4621. item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName);
  4622. }
  4623. else
  4624. {
  4625. item->firstParamSymbol = INVALID_KEY_SYMBOL;
  4626. }
  4627. if (item->secondParamName)
  4628. {
  4629. item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName);
  4630. }
  4631. else
  4632. {
  4633. item->secondParamSymbol = INVALID_KEY_SYMBOL;
  4634. }
  4635. }
  4636. panelMap->processed = true;
  4637. panelMap = panelMap->baseMap;
  4638. }
  4639. }
  4640. //-----------------------------------------------------------------------------
  4641. // Purpose: Handles a message
  4642. // Dispatches the message to a set of message maps
  4643. //-----------------------------------------------------------------------------
  4644. void Panel::OnMessage(const KeyValues *params, VPANEL ifromPanel)
  4645. {
  4646. PanelMessageMap *panelMap = GetMessageMap();
  4647. bool bFound = false;
  4648. int iMessageName = params->GetNameSymbol();
  4649. if ( !panelMap->processed )
  4650. {
  4651. PreparePanelMessageMap( panelMap );
  4652. }
  4653. // iterate through the class hierarchy message maps
  4654. for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap )
  4655. {
  4656. #if defined( _DEBUG )
  4657. // char const *className = panelMap->pfnClassName();
  4658. // NOTE_UNUSED( className );
  4659. #endif
  4660. // iterate all the entries in the panel map
  4661. for ( int i = 0; i < panelMap->entries.Count(); i++ )
  4662. {
  4663. MessageMapItem_t *pMap = &panelMap->entries[i];
  4664. if (iMessageName == pMap->nameSymbol)
  4665. {
  4666. bFound = true;
  4667. switch (pMap->numParams)
  4668. {
  4669. case 0:
  4670. {
  4671. (this->*(pMap->func))();
  4672. break;
  4673. }
  4674. case 1:
  4675. {
  4676. KeyValues *param1 = params->FindKey(pMap->firstParamSymbol);
  4677. if (!param1)
  4678. {
  4679. param1 = const_cast<KeyValues *>(params);
  4680. }
  4681. switch ( pMap->firstParamType )
  4682. {
  4683. case DATATYPE_INT:
  4684. typedef void (Panel::*MessageFunc_Int_t)(int);
  4685. (this->*((MessageFunc_Int_t)pMap->func))( param1->GetInt() );
  4686. break;
  4687. case DATATYPE_UINT64:
  4688. typedef void (Panel::*MessageFunc_Uin64_t)(uint64);
  4689. (this->*((MessageFunc_Uin64_t)pMap->func))( param1->GetUint64() );
  4690. break;
  4691. case DATATYPE_PTR:
  4692. typedef void (Panel::*MessageFunc_Ptr_t)( void * );
  4693. (this->*((MessageFunc_Ptr_t)pMap->func))( param1->GetPtr() );
  4694. break;
  4695. case DATATYPE_HANDLE:
  4696. {
  4697. typedef void (Panel::*MessageFunc_VPANEL_t)( VPANEL );
  4698. VPANEL vpanel = ivgui()->HandleToPanel( param1->GetInt() );
  4699. (this->*((MessageFunc_VPANEL_t)pMap->func))( vpanel );
  4700. }
  4701. break;
  4702. case DATATYPE_FLOAT:
  4703. typedef void (Panel::*MessageFunc_Float_t)( float );
  4704. (this->*((MessageFunc_Float_t)pMap->func))( param1->GetFloat() );
  4705. break;
  4706. case DATATYPE_CONSTCHARPTR:
  4707. typedef void (Panel::*MessageFunc_CharPtr_t)( const char * );
  4708. (this->*((MessageFunc_CharPtr_t)pMap->func))( param1->GetString() );
  4709. break;
  4710. case DATATYPE_CONSTWCHARPTR:
  4711. typedef void (Panel::*MessageFunc_WCharPtr_t)( const wchar_t * );
  4712. (this->*((MessageFunc_WCharPtr_t)pMap->func))( param1->GetWString() );
  4713. break;
  4714. case DATATYPE_KEYVALUES:
  4715. typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *);
  4716. if ( pMap->firstParamName )
  4717. {
  4718. (this->*((MessageFunc_KeyValues_t)pMap->func))( (KeyValues *)param1->GetPtr() );
  4719. }
  4720. else
  4721. {
  4722. // no param set, so pass in the whole thing
  4723. (this->*((MessageFunc_KeyValues_t)pMap->func))( const_cast<KeyValues *>(params) );
  4724. }
  4725. break;
  4726. default:
  4727. Assert(!("No handler for vgui message function"));
  4728. break;
  4729. }
  4730. break;
  4731. }
  4732. case 2:
  4733. {
  4734. KeyValues *param1 = params->FindKey(pMap->firstParamSymbol);
  4735. if (!param1)
  4736. {
  4737. param1 = const_cast<KeyValues *>(params);
  4738. }
  4739. KeyValues *param2 = params->FindKey(pMap->secondParamSymbol);
  4740. if (!param2)
  4741. {
  4742. param2 = const_cast<KeyValues *>(params);
  4743. }
  4744. if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) )
  4745. {
  4746. typedef void (Panel::*MessageFunc_IntInt_t)(int, int);
  4747. (this->*((MessageFunc_IntInt_t)pMap->func))( param1->GetInt(), param2->GetInt() );
  4748. }
  4749. else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) )
  4750. {
  4751. typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int);
  4752. (this->*((MessageFunc_PtrInt_t)pMap->func))( param1->GetPtr(), param2->GetInt() );
  4753. }
  4754. else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_PTR == pMap->secondParamType) )
  4755. {
  4756. typedef void (Panel::*MessageFunc_PtrPtr_t)(void *, void *);
  4757. (this->*((MessageFunc_PtrPtr_t)pMap->func))( param1->GetPtr(), param2->GetPtr() );
  4758. }
  4759. else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) )
  4760. {
  4761. typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int);
  4762. (this->*((MessageFunc_ConstCharPtrInt_t)pMap->func))( param1->GetString(), param2->GetInt() );
  4763. }
  4764. else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4765. {
  4766. typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *);
  4767. (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMap->func))( param1->GetString(), param2->GetString() );
  4768. }
  4769. else if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4770. {
  4771. typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *);
  4772. (this->*((MessageFunc_IntConstCharPtr_t)pMap->func))( param1->GetInt(), param2->GetString() );
  4773. }
  4774. else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4775. {
  4776. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *);
  4777. (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetString() );
  4778. }
  4779. else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) )
  4780. {
  4781. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *);
  4782. (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetWString() );
  4783. }
  4784. else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4785. {
  4786. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *);
  4787. VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() );
  4788. (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetString() );
  4789. }
  4790. else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) )
  4791. {
  4792. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *);
  4793. VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() );
  4794. (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetWString() );
  4795. }
  4796. else
  4797. {
  4798. // the message isn't handled
  4799. ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() );
  4800. }
  4801. break;
  4802. }
  4803. default:
  4804. Assert(!("Invalid number of parameters"));
  4805. break;
  4806. }
  4807. // break the loop
  4808. bFound = true;
  4809. break;
  4810. }
  4811. }
  4812. }
  4813. if (!bFound)
  4814. {
  4815. OnOldMessage(const_cast<KeyValues *>(params), ifromPanel);
  4816. }
  4817. }
  4818. void Panel::OnOldMessage(KeyValues *params, VPANEL ifromPanel)
  4819. {
  4820. bool bFound = false;
  4821. // message map dispatch
  4822. int iMessageName = params->GetNameSymbol();
  4823. PanelMap_t *panelMap = GetPanelMap();
  4824. if ( !panelMap->processed )
  4825. {
  4826. PreparePanelMap( panelMap );
  4827. }
  4828. // iterate through the class hierarchy message maps
  4829. for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap )
  4830. {
  4831. MessageMapItem_t *pMessageMap = panelMap->dataDesc;
  4832. for ( int i = 0; i < panelMap->dataNumFields; i++ )
  4833. {
  4834. if (iMessageName == pMessageMap[i].nameSymbol)
  4835. {
  4836. // call the mapped function
  4837. switch ( pMessageMap[i].numParams )
  4838. {
  4839. case 2:
  4840. if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) )
  4841. {
  4842. typedef void (Panel::*MessageFunc_IntInt_t)(int, int);
  4843. (this->*((MessageFunc_IntInt_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) );
  4844. }
  4845. else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) )
  4846. {
  4847. typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int);
  4848. (this->*((MessageFunc_PtrInt_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) );
  4849. }
  4850. else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) )
  4851. {
  4852. typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int);
  4853. (this->*((MessageFunc_ConstCharPtrInt_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) );
  4854. }
  4855. else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) )
  4856. {
  4857. typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *);
  4858. (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) );
  4859. }
  4860. else if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) )
  4861. {
  4862. typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *);
  4863. (this->*((MessageFunc_IntConstCharPtr_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) );
  4864. }
  4865. else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) )
  4866. {
  4867. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *);
  4868. (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) );
  4869. }
  4870. else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) )
  4871. {
  4872. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *);
  4873. (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetWString(pMessageMap[i].secondParamName) );
  4874. }
  4875. else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR ==pMessageMap[i].secondParamType) )
  4876. {
  4877. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *);
  4878. VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) );
  4879. (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetString(pMessageMap[i].secondParamName) );
  4880. }
  4881. else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) )
  4882. {
  4883. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *);
  4884. VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) );
  4885. (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetWString(pMessageMap[i].secondParamName) );
  4886. }
  4887. else
  4888. {
  4889. // the message isn't handled
  4890. ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() );
  4891. }
  4892. break;
  4893. case 1:
  4894. switch ( pMessageMap[i].firstParamType )
  4895. {
  4896. case DATATYPE_BOOL:
  4897. typedef void (Panel::*MessageFunc_Bool_t)(bool);
  4898. (this->*((MessageFunc_Bool_t)pMessageMap[i].func))( params->GetBool(pMessageMap[i].firstParamName) );
  4899. break;
  4900. case DATATYPE_CONSTCHARPTR:
  4901. typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *);
  4902. (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetString(pMessageMap[i].firstParamName) );
  4903. break;
  4904. case DATATYPE_CONSTWCHARPTR:
  4905. typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *);
  4906. (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetWString(pMessageMap[i].firstParamName) );
  4907. break;
  4908. case DATATYPE_INT:
  4909. typedef void (Panel::*MessageFunc_Int_t)(int);
  4910. (this->*((MessageFunc_Int_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName) );
  4911. break;
  4912. case DATATYPE_FLOAT:
  4913. typedef void (Panel::*MessageFunc_Float_t)(float);
  4914. (this->*((MessageFunc_Float_t)pMessageMap[i].func))( params->GetFloat(pMessageMap[i].firstParamName) );
  4915. break;
  4916. case DATATYPE_PTR:
  4917. typedef void (Panel::*MessageFunc_Ptr_t)(void *);
  4918. (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)params->GetPtr(pMessageMap[i].firstParamName) );
  4919. break;
  4920. case DATATYPE_HANDLE:
  4921. {
  4922. typedef void (Panel::*MessageFunc_Ptr_t)(void *);
  4923. VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) );
  4924. Panel *panel = ipanel()->GetPanel( vp, GetModuleName() );
  4925. (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)panel );
  4926. }
  4927. break;
  4928. case DATATYPE_KEYVALUES:
  4929. typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *);
  4930. if ( pMessageMap[i].firstParamName )
  4931. {
  4932. (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( (KeyValues *)params->GetPtr(pMessageMap[i].firstParamName) );
  4933. }
  4934. else
  4935. {
  4936. (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( params );
  4937. }
  4938. break;
  4939. default:
  4940. // the message isn't handled
  4941. ivgui()->DPrintf( "Message '%s', sent to '%s', has an invalid parameter type\n", params->GetName(), GetName() );
  4942. break;
  4943. }
  4944. break;
  4945. default:
  4946. (this->*(pMessageMap[i].func))();
  4947. break;
  4948. };
  4949. // break the loop
  4950. bFound = true;
  4951. break;
  4952. }
  4953. }
  4954. }
  4955. // message not handled
  4956. // debug code
  4957. if ( !bFound )
  4958. {
  4959. static int s_bDebugMessages = -1;
  4960. if ( s_bDebugMessages == -1 )
  4961. {
  4962. s_bDebugMessages = CommandLine()->FindParm( "-vguimessages" ) ? 1 : 0;
  4963. }
  4964. if ( s_bDebugMessages == 1 )
  4965. {
  4966. ivgui()->DPrintf( "Message '%s' not handled by panel '%s'\n", params->GetName(), GetName() );
  4967. }
  4968. }
  4969. }
  4970. //-----------------------------------------------------------------------------
  4971. // Purpose: Safe call to get info from child panel by name
  4972. //-----------------------------------------------------------------------------
  4973. bool Panel::RequestInfoFromChild(const char *childName, KeyValues *outputData)
  4974. {
  4975. Panel *panel = FindChildByName(childName);
  4976. if (panel)
  4977. {
  4978. return panel->RequestInfo(outputData);
  4979. }
  4980. return false;
  4981. }
  4982. //-----------------------------------------------------------------------------
  4983. // Purpose: Posts a message
  4984. //-----------------------------------------------------------------------------
  4985. void Panel::PostMessage(Panel *target, KeyValues *message, float delay)
  4986. {
  4987. ivgui()->PostMessage(target->GetVPanel(), message, GetVPanel(), delay);
  4988. }
  4989. void Panel::PostMessage(VPANEL target, KeyValues *message, float delaySeconds)
  4990. {
  4991. ivgui()->PostMessage(target, message, GetVPanel(), delaySeconds);
  4992. }
  4993. void Panel::PostMessageToAllSiblings( KeyValues *msg, float delaySeconds /*= 0.0f*/ )
  4994. {
  4995. VPANEL parent = GetVParent();
  4996. if ( parent )
  4997. {
  4998. VPANEL vpanel = GetVPanel();
  4999. CUtlVector< VPANEL > &children = ipanel()->GetChildren( parent );
  5000. int nChildCount = children.Count();
  5001. for ( int i = 0; i < nChildCount; ++i )
  5002. {
  5003. VPANEL sibling = children[ i ];
  5004. if ( sibling == vpanel )
  5005. continue;
  5006. if ( sibling )
  5007. {
  5008. PostMessage( sibling, msg->MakeCopy(), delaySeconds );
  5009. }
  5010. }
  5011. }
  5012. msg->deleteThis();
  5013. }
  5014. //-----------------------------------------------------------------------------
  5015. // Purpose: Safe call to post a message to a child by name
  5016. //-----------------------------------------------------------------------------
  5017. void Panel::PostMessageToChild(const char *childName, KeyValues *message)
  5018. {
  5019. Panel *panel = FindChildByName(childName);
  5020. if (panel)
  5021. {
  5022. ivgui()->PostMessage(panel->GetVPanel(), message, GetVPanel());
  5023. }
  5024. else
  5025. {
  5026. message->deleteThis();
  5027. }
  5028. }
  5029. //-----------------------------------------------------------------------------
  5030. // Purpose: Requests some information from the panel
  5031. // Look through the message map for the handler
  5032. //-----------------------------------------------------------------------------
  5033. bool Panel::RequestInfo( KeyValues *outputData )
  5034. {
  5035. if ( InternalRequestInfo( GetAnimMap(), outputData ) )
  5036. {
  5037. return true;
  5038. }
  5039. if (GetVParent())
  5040. {
  5041. return ipanel()->RequestInfo(GetVParent(), outputData);
  5042. }
  5043. return false;
  5044. }
  5045. //-----------------------------------------------------------------------------
  5046. // Purpose: sets a specified value in the control - inverse of RequestInfo
  5047. //-----------------------------------------------------------------------------
  5048. bool Panel::SetInfo(KeyValues *inputData)
  5049. {
  5050. if ( InternalSetInfo( GetAnimMap(), inputData ) )
  5051. {
  5052. return true;
  5053. }
  5054. // doesn't chain to parent
  5055. return false;
  5056. }
  5057. //-----------------------------------------------------------------------------
  5058. // Purpose: change the panel's silent mode; if silent, the panel will not post
  5059. // any action signals
  5060. //-----------------------------------------------------------------------------
  5061. void Panel::SetSilentMode( bool bSilent )
  5062. {
  5063. m_bIsSilent = bSilent;
  5064. }
  5065. //-----------------------------------------------------------------------------
  5066. // Purpose: mouse events will be send to handler panel instead of this panel
  5067. //-----------------------------------------------------------------------------
  5068. void Panel::InstallMouseHandler( Panel *pHandler )
  5069. {
  5070. m_hMouseEventHandler = pHandler;
  5071. }
  5072. //-----------------------------------------------------------------------------
  5073. // Purpose: Prepares the hierarchy panel maps for use (with message maps etc)
  5074. //-----------------------------------------------------------------------------
  5075. void Panel::PreparePanelMap( PanelMap_t *panelMap )
  5076. {
  5077. // iterate through the class hierarchy message maps
  5078. while ( panelMap != NULL && !panelMap->processed )
  5079. {
  5080. // fixup cross-dll boundary panel maps
  5081. if ( panelMap->baseMap == (PanelMap_t*)0x00000001 )
  5082. {
  5083. panelMap->baseMap = &Panel::m_PanelMap;
  5084. }
  5085. // hash message map strings into symbols
  5086. for (int i = 0; i < panelMap->dataNumFields; i++)
  5087. {
  5088. MessageMapItem_t *item = &panelMap->dataDesc[i];
  5089. if (item->name)
  5090. {
  5091. item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name);
  5092. }
  5093. else
  5094. {
  5095. item->nameSymbol = INVALID_KEY_SYMBOL;
  5096. }
  5097. if (item->firstParamName)
  5098. {
  5099. item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName);
  5100. }
  5101. else
  5102. {
  5103. item->firstParamSymbol = INVALID_KEY_SYMBOL;
  5104. }
  5105. if (item->secondParamName)
  5106. {
  5107. item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName);
  5108. }
  5109. else
  5110. {
  5111. item->secondParamSymbol = INVALID_KEY_SYMBOL;
  5112. }
  5113. }
  5114. panelMap->processed = true;
  5115. panelMap = panelMap->baseMap;
  5116. }
  5117. }
  5118. //-----------------------------------------------------------------------------
  5119. // Purpose: Called to delete the panel
  5120. //-----------------------------------------------------------------------------
  5121. void Panel::OnDelete()
  5122. {
  5123. #ifdef WIN32
  5124. Assert( IsGameConsole() || ( IsPC() && _heapchk() == _HEAPOK ) );
  5125. #endif
  5126. delete this;
  5127. #ifdef WIN32
  5128. Assert( IsGameConsole() || ( IsPC() && _heapchk() == _HEAPOK ) );
  5129. #endif
  5130. }
  5131. //-----------------------------------------------------------------------------
  5132. // Purpose: Panel handle implementation
  5133. // Returns a pointer to a valid panel, NULL if the panel has been deleted
  5134. //-----------------------------------------------------------------------------
  5135. Panel *PHandle::Get()
  5136. {
  5137. if (m_iPanelID != INVALID_PANEL)
  5138. {
  5139. VPANEL panel = ivgui()->HandleToPanel(m_iPanelID);
  5140. if (panel)
  5141. {
  5142. Panel *vguiPanel = ipanel()->GetPanel(panel, GetControlsModuleName());
  5143. return vguiPanel;
  5144. }
  5145. }
  5146. return NULL;
  5147. }
  5148. //-----------------------------------------------------------------------------
  5149. // Purpose: sets the smart pointer
  5150. //-----------------------------------------------------------------------------
  5151. Panel *PHandle::Set(Panel *pent)
  5152. {
  5153. if (pent)
  5154. {
  5155. m_iPanelID = ivgui()->PanelToHandle(pent->GetVPanel());
  5156. }
  5157. else
  5158. {
  5159. m_iPanelID = INVALID_PANEL;
  5160. }
  5161. return pent;
  5162. }
  5163. Panel *PHandle::Set( HPanel hPanel )
  5164. {
  5165. m_iPanelID = hPanel;
  5166. return Get();
  5167. }
  5168. //-----------------------------------------------------------------------------
  5169. // Purpose: Returns a handle to a valid panel, NULL if the panel has been deleted
  5170. //-----------------------------------------------------------------------------
  5171. VPANEL VPanelHandle::Get()
  5172. {
  5173. if (m_iPanelID != INVALID_PANEL)
  5174. {
  5175. if (ivgui())
  5176. {
  5177. return ivgui()->HandleToPanel(m_iPanelID);
  5178. }
  5179. }
  5180. return NULL;
  5181. }
  5182. //-----------------------------------------------------------------------------
  5183. // Purpose: sets the smart pointer
  5184. //-----------------------------------------------------------------------------
  5185. VPANEL VPanelHandle::Set(VPANEL pent)
  5186. {
  5187. if (pent)
  5188. {
  5189. m_iPanelID = ivgui()->PanelToHandle(pent);
  5190. }
  5191. else
  5192. {
  5193. m_iPanelID = INVALID_PANEL;
  5194. }
  5195. return pent;
  5196. }
  5197. //-----------------------------------------------------------------------------
  5198. // Purpose: returns a pointer to the tooltip object associated with the panel
  5199. //-----------------------------------------------------------------------------
  5200. BaseTooltip *Panel::GetTooltip()
  5201. {
  5202. if (!m_pTooltips)
  5203. {
  5204. m_pTooltips = new TextTooltip(this, NULL);
  5205. m_bToolTipOverridden = false;
  5206. if ( IsConsoleStylePanel() )
  5207. {
  5208. m_pTooltips->SetEnabled( false );
  5209. }
  5210. }
  5211. return m_pTooltips;
  5212. }
  5213. //-----------------------------------------------------------------------------
  5214. // Purpose:
  5215. //-----------------------------------------------------------------------------
  5216. void Panel::SetTooltip( BaseTooltip *pToolTip, const char *pszText )
  5217. {
  5218. if ( !m_bToolTipOverridden )
  5219. {
  5220. // Remove the one we made, we're being overridden.
  5221. delete m_pTooltips;
  5222. }
  5223. m_pTooltips = pToolTip;
  5224. m_bToolTipOverridden = true;
  5225. if ( _tooltipText )
  5226. {
  5227. delete [] _tooltipText;
  5228. _tooltipText = NULL;
  5229. }
  5230. if ( pszText )
  5231. {
  5232. int len = Q_strlen(pszText) + 1;
  5233. _tooltipText = new char[ len ];
  5234. Q_strncpy( _tooltipText, pszText, len );
  5235. }
  5236. }
  5237. //-----------------------------------------------------------------------------
  5238. // Purpose: sets the proportional flag on this panel and all it's children
  5239. //-----------------------------------------------------------------------------
  5240. void Panel::SetProportional(bool state)
  5241. {
  5242. // only do something if the state changes
  5243. if( state != _flags.IsFlagSet( IS_PROPORTIONAL ) )
  5244. {
  5245. _flags.SetFlag( IS_PROPORTIONAL, state );
  5246. for(int i=0;i<GetChildCount();i++)
  5247. {
  5248. // recursively apply to all children
  5249. GetChild(i)->SetProportional( IsProportional() );
  5250. }
  5251. }
  5252. InvalidateLayout();
  5253. }
  5254. void Panel::SetKeyBoardInputEnabled( bool state )
  5255. {
  5256. ipanel()->SetKeyBoardInputEnabled( GetVPanel(), state );
  5257. for ( int i = 0; i < GetChildCount(); i++ )
  5258. {
  5259. Panel *child = GetChild( i );
  5260. if ( !child )
  5261. {
  5262. continue;
  5263. }
  5264. child->SetKeyBoardInputEnabled( state );
  5265. }
  5266. // If turning off keyboard input enable, then make sure
  5267. // this panel is not the current key focus of a parent panel
  5268. if ( !state )
  5269. {
  5270. Panel *pParent = GetParent();
  5271. if ( pParent )
  5272. {
  5273. if ( pParent->GetCurrentKeyFocus() == GetVPanel() )
  5274. {
  5275. pParent->RequestFocusNext();
  5276. }
  5277. }
  5278. }
  5279. }
  5280. void Panel::SetMouseInputEnabled( bool state )
  5281. {
  5282. ipanel()->SetMouseInputEnabled( GetVPanel(), state );
  5283. /* for(int i=0;i<GetChildCount();i++)
  5284. {
  5285. GetChild(i)->SetMouseInput(state);
  5286. }*/
  5287. vgui::surface()->CalculateMouseVisible();
  5288. }
  5289. bool Panel::IsKeyBoardInputEnabled()
  5290. {
  5291. return ipanel()->IsKeyBoardInputEnabled( GetVPanel() );
  5292. }
  5293. bool Panel::IsMouseInputEnabled()
  5294. {
  5295. return ipanel()->IsMouseInputEnabled( GetVPanel() );
  5296. }
  5297. class CFloatProperty : public vgui::IPanelAnimationPropertyConverter
  5298. {
  5299. public:
  5300. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5301. {
  5302. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5303. kv->SetFloat( entry->name(), *(float *)data );
  5304. }
  5305. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5306. {
  5307. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5308. *(float *)data = kv->GetFloat( entry->name() );
  5309. }
  5310. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5311. {
  5312. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5313. *(float *)data = atof( entry->defaultvalue() );
  5314. }
  5315. };
  5316. class CProportionalFloatProperty : public vgui::IPanelAnimationPropertyConverter
  5317. {
  5318. public:
  5319. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5320. {
  5321. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5322. float f = *(float *)data;
  5323. f = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), f );
  5324. kv->SetFloat( entry->name(), f );
  5325. }
  5326. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5327. {
  5328. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5329. float f = kv->GetFloat( entry->name() );
  5330. f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f );
  5331. *(float *)data = f;
  5332. }
  5333. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5334. {
  5335. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5336. float f = atof( entry->defaultvalue() );
  5337. f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f );
  5338. *(float *)data = f;
  5339. }
  5340. };
  5341. class CIntProperty : public vgui::IPanelAnimationPropertyConverter
  5342. {
  5343. public:
  5344. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5345. {
  5346. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5347. kv->SetInt( entry->name(), *(int *)data );
  5348. }
  5349. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5350. {
  5351. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5352. *(int *)data = kv->GetInt( entry->name() );
  5353. }
  5354. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5355. {
  5356. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5357. *(int *)data = atoi( entry->defaultvalue() );
  5358. }
  5359. };
  5360. class CProportionalIntProperty : public vgui::IPanelAnimationPropertyConverter
  5361. {
  5362. public:
  5363. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5364. {
  5365. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5366. int i = *(int *)data;
  5367. i = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), i );
  5368. kv->SetInt( entry->name(), i );
  5369. }
  5370. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5371. {
  5372. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5373. int i = kv->GetInt( entry->name() );
  5374. i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i );
  5375. *(int *)data = i;
  5376. }
  5377. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5378. {
  5379. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5380. int i = atoi( entry->defaultvalue() );
  5381. i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i );
  5382. *(int *)data = i;
  5383. }
  5384. };
  5385. //-----------------------------------------------------------------------------
  5386. // Purpose: Handles "100", "c100", and "r100" style of specifying positions
  5387. //-----------------------------------------------------------------------------
  5388. static int ConvertPosition( int val, const char *str, int screenSize, bool bIsProportional, vgui::HScheme hScheme )
  5389. {
  5390. bool rightAligned = false;
  5391. bool centerAligned = false;
  5392. if ( str )
  5393. {
  5394. // look for alignment flags
  5395. if (str[0] == 'r' || str[0] == 'R')
  5396. {
  5397. rightAligned = true;
  5398. str++;
  5399. }
  5400. else if (str[0] == 'c' || str[0] == 'C')
  5401. {
  5402. centerAligned = true;
  5403. str++;
  5404. }
  5405. // get the value
  5406. val = atoi(str);
  5407. // scale the x up to our screen co-ords
  5408. if ( bIsProportional )
  5409. {
  5410. val = scheme()->GetProportionalScaledValueEx(hScheme, val);
  5411. }
  5412. // now correct the alignment
  5413. if ( rightAligned )
  5414. {
  5415. val = screenSize - val;
  5416. }
  5417. else if ( centerAligned )
  5418. {
  5419. val = (screenSize / 2) + val;
  5420. }
  5421. }
  5422. return val;
  5423. }
  5424. class CProportionalXPosProperty : public vgui::IPanelAnimationPropertyConverter
  5425. {
  5426. public:
  5427. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5428. {
  5429. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5430. int i = *(int *)data;
  5431. i = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), i );
  5432. kv->SetInt( entry->name(), i );
  5433. }
  5434. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5435. {
  5436. //int width, height;
  5437. //surface()->GetScreenSize(width, height);
  5438. int width = panel->GetWide();
  5439. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5440. const char *val = kv->GetString( entry->name() );
  5441. int i = ConvertPosition( atoi( val ), val, width, panel->IsProportional(), panel->GetScheme() );
  5442. *(int *)data = i;
  5443. }
  5444. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5445. {
  5446. //int width, height;
  5447. //surface()->GetScreenSize(width, height);
  5448. int width = panel->GetWide();
  5449. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5450. const char *val = entry->defaultvalue();
  5451. int i = ConvertPosition( atoi( val ), val, width, panel->IsProportional(), panel->GetScheme() );
  5452. *(int *)data = i;
  5453. }
  5454. };
  5455. class CProportionalYPosProperty : public vgui::IPanelAnimationPropertyConverter
  5456. {
  5457. public:
  5458. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5459. {
  5460. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5461. int i = *(int *)data;
  5462. i = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), i );
  5463. kv->SetInt( entry->name(), i );
  5464. }
  5465. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5466. {
  5467. //int width, height;
  5468. //surface()->GetScreenSize(width, height);
  5469. int height = panel->GetTall();
  5470. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5471. const char *val = kv->GetString( entry->name() );
  5472. int i = ConvertPosition( atoi( val ), val, height, panel->IsProportional(), panel->GetScheme() );
  5473. *(int *)data = i;
  5474. }
  5475. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5476. {
  5477. //int width, height;
  5478. //surface()->GetScreenSize(width, height);
  5479. int height = panel->GetTall();
  5480. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5481. const char *val = entry->defaultvalue();
  5482. int i = ConvertPosition( atoi( val ), val, height, panel->IsProportional(), panel->GetScheme() );
  5483. *(int *)data = i;
  5484. }
  5485. };
  5486. class CColorProperty : public vgui::IPanelAnimationPropertyConverter
  5487. {
  5488. public:
  5489. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5490. {
  5491. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5492. kv->SetColor( entry->name(), *(Color *)data );
  5493. }
  5494. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5495. {
  5496. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5497. Assert( scheme );
  5498. if ( scheme )
  5499. {
  5500. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5501. char const *colorName = kv->GetString( entry->name() );
  5502. if ( !colorName || !colorName[0] )
  5503. {
  5504. *(Color *)data = kv->GetColor( entry->name() );
  5505. }
  5506. else
  5507. {
  5508. *(Color *)data = scheme->GetColor( colorName, Color( 0, 0, 0, 0 ) );
  5509. }
  5510. }
  5511. }
  5512. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5513. {
  5514. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5515. Assert( scheme );
  5516. if ( scheme )
  5517. {
  5518. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5519. *(Color *)data = scheme->GetColor( entry->defaultvalue(), Color( 0, 0, 0, 0 ) );
  5520. }
  5521. }
  5522. };
  5523. class CBoolProperty : public vgui::IPanelAnimationPropertyConverter
  5524. {
  5525. public:
  5526. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5527. {
  5528. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5529. kv->SetInt( entry->name(), *(bool *)data ? 1 : 0 );
  5530. }
  5531. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5532. {
  5533. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5534. *(bool *)data = kv->GetBool( entry->name() );
  5535. }
  5536. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5537. {
  5538. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5539. bool b = false;
  5540. if ( !stricmp( entry->defaultvalue(), "true" )||
  5541. atoi( entry->defaultvalue() )!= 0 )
  5542. {
  5543. b = true;
  5544. }
  5545. *(bool *)data = b;
  5546. }
  5547. };
  5548. class CStringProperty : public vgui::IPanelAnimationPropertyConverter
  5549. {
  5550. public:
  5551. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5552. {
  5553. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5554. kv->SetString( entry->name(), (char *)data );
  5555. }
  5556. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5557. {
  5558. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5559. strcpy( (char *)data, kv->GetString( entry->name() ) );
  5560. }
  5561. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5562. {
  5563. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5564. strcpy( ( char * )data, entry->defaultvalue() );
  5565. }
  5566. };
  5567. class CHFontProperty : public vgui::IPanelAnimationPropertyConverter
  5568. {
  5569. public:
  5570. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5571. {
  5572. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5573. Assert( scheme );
  5574. if ( scheme )
  5575. {
  5576. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5577. char const *fontName = scheme->GetFontName( *(HFont *)data );
  5578. kv->SetString( entry->name(), fontName );
  5579. }
  5580. }
  5581. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5582. {
  5583. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5584. Assert( scheme );
  5585. if ( scheme )
  5586. {
  5587. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5588. char const *fontName = kv->GetString( entry->name() );
  5589. *(HFont *)data = scheme->GetFont( fontName, panel->IsProportional() );
  5590. }
  5591. }
  5592. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5593. {
  5594. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5595. Assert( scheme );
  5596. if ( scheme )
  5597. {
  5598. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5599. *(HFont *)data = scheme->GetFont( entry->defaultvalue(), panel->IsProportional() );
  5600. }
  5601. }
  5602. };
  5603. class CTextureIdProperty : public vgui::IPanelAnimationPropertyConverter
  5604. {
  5605. public:
  5606. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5607. {
  5608. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5609. int currentId = *(int *)data;
  5610. // lookup texture name for id
  5611. char texturename[ 512 ];
  5612. if ( currentId != -1 &&
  5613. surface()->DrawGetTextureFile( currentId, texturename, sizeof( texturename ) ) )
  5614. {
  5615. kv->SetString( entry->name(), texturename );
  5616. }
  5617. else
  5618. {
  5619. kv->SetString( entry->name(), "" );
  5620. }
  5621. }
  5622. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5623. {
  5624. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5625. int currentId = -1;
  5626. char const *texturename = kv->GetString( entry->name() );
  5627. if ( texturename && texturename[ 0 ] )
  5628. {
  5629. currentId = surface()->DrawGetTextureId( texturename );
  5630. if ( currentId == -1 )
  5631. {
  5632. currentId = surface()->CreateNewTextureID();
  5633. }
  5634. surface()->DrawSetTextureFile( currentId, texturename, false, true );
  5635. }
  5636. *(int *)data = currentId;
  5637. }
  5638. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5639. {
  5640. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5641. int currentId = -1;
  5642. char const *texturename = entry->defaultvalue();
  5643. if ( texturename && texturename[ 0 ] )
  5644. {
  5645. currentId = surface()->DrawGetTextureId( texturename );
  5646. if ( currentId == -1 )
  5647. {
  5648. currentId = surface()->CreateNewTextureID();
  5649. }
  5650. surface()->DrawSetTextureFile( currentId, texturename, false, true );
  5651. }
  5652. *(int *)data = currentId;
  5653. }
  5654. };
  5655. static CFloatProperty floatconverter;
  5656. static CProportionalFloatProperty p_floatconverter;
  5657. static CIntProperty intconverter;
  5658. static CProportionalIntProperty p_intconverter;
  5659. static CColorProperty colorconverter;
  5660. static CBoolProperty boolconverter;
  5661. static CStringProperty stringconverter;
  5662. static CHFontProperty fontconverter;
  5663. static CTextureIdProperty textureidconverter;
  5664. static CProportionalXPosProperty xposconverter;
  5665. static CProportionalYPosProperty yposconverter;
  5666. static CUtlDict< IPanelAnimationPropertyConverter *, int > &GetPropertyConverters()
  5667. {
  5668. static CUtlDict< IPanelAnimationPropertyConverter *, int > g_AnimationPropertyConverters;
  5669. return g_AnimationPropertyConverters;
  5670. }
  5671. static IPanelAnimationPropertyConverter *FindConverter( char const *typeName )
  5672. {
  5673. int lookup = GetPropertyConverters().Find( typeName );
  5674. if ( lookup == GetPropertyConverters().InvalidIndex() )
  5675. return NULL;
  5676. IPanelAnimationPropertyConverter *converter = GetPropertyConverters()[ lookup ];
  5677. return converter;
  5678. }
  5679. void Panel::AddPropertyConverter( char const *typeName, IPanelAnimationPropertyConverter *converter )
  5680. {
  5681. int lookup = GetPropertyConverters().Find( typeName );
  5682. if ( lookup != GetPropertyConverters().InvalidIndex() )
  5683. {
  5684. Msg( "Already have converter for type %s, ignoring...\n", typeName );
  5685. return;
  5686. }
  5687. GetPropertyConverters().Insert( typeName, converter );
  5688. }
  5689. //-----------------------------------------------------------------------------
  5690. // Purpose: Static method to initialize all needed converters
  5691. //-----------------------------------------------------------------------------
  5692. void Panel::InitPropertyConverters( void )
  5693. {
  5694. static bool initialized = false;
  5695. if ( initialized )
  5696. return;
  5697. initialized = true;
  5698. AddPropertyConverter( "float", &floatconverter );
  5699. AddPropertyConverter( "int", &intconverter );
  5700. AddPropertyConverter( "Color", &colorconverter );
  5701. // AddPropertyConverter( "vgui::Color", &colorconverter );
  5702. AddPropertyConverter( "bool", &boolconverter );
  5703. AddPropertyConverter( "char", &stringconverter );
  5704. AddPropertyConverter( "string", &stringconverter );
  5705. AddPropertyConverter( "HFont", &fontconverter );
  5706. AddPropertyConverter( "vgui::HFont", &fontconverter );
  5707. // This is an aliased type for proportional float
  5708. AddPropertyConverter( "proportional_float", &p_floatconverter );
  5709. AddPropertyConverter( "proportional_int", &p_intconverter );
  5710. AddPropertyConverter( "proportional_xpos", &xposconverter );
  5711. AddPropertyConverter( "proportional_ypos", &yposconverter );
  5712. AddPropertyConverter( "textureid", &textureidconverter );
  5713. }
  5714. bool Panel::InternalRequestInfo( PanelAnimationMap *map, KeyValues *outputData )
  5715. {
  5716. if ( !map )
  5717. return false;
  5718. Assert( outputData );
  5719. char const *name = outputData->GetName();
  5720. PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map );
  5721. if ( e )
  5722. {
  5723. IPanelAnimationPropertyConverter *converter = FindConverter( e->type() );
  5724. if ( converter )
  5725. {
  5726. converter->GetData( this, outputData, e );
  5727. return true;
  5728. }
  5729. }
  5730. return false;
  5731. }
  5732. bool Panel::InternalSetInfo( PanelAnimationMap *map, KeyValues *inputData )
  5733. {
  5734. if ( !map )
  5735. return false;
  5736. Assert( inputData );
  5737. char const *name = inputData->GetName();
  5738. PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map );
  5739. if ( e )
  5740. {
  5741. IPanelAnimationPropertyConverter *converter = FindConverter( e->type() );
  5742. if ( converter )
  5743. {
  5744. converter->SetData( this, inputData, e );
  5745. return true;
  5746. }
  5747. }
  5748. return false;
  5749. }
  5750. PanelAnimationMapEntry *Panel::FindPanelAnimationEntry( char const *scriptname, PanelAnimationMap *map )
  5751. {
  5752. if ( !map )
  5753. return NULL;
  5754. Assert( scriptname );
  5755. // Look through mapping for entry
  5756. int c = map->entries.Count();
  5757. for ( int i = 0; i < c; i++ )
  5758. {
  5759. PanelAnimationMapEntry *e = &map->entries[ i ];
  5760. if ( !stricmp( e->name(), scriptname ) )
  5761. {
  5762. return e;
  5763. }
  5764. }
  5765. // Recurse
  5766. if ( map->baseMap )
  5767. {
  5768. return FindPanelAnimationEntry( scriptname, map->baseMap );
  5769. }
  5770. return NULL;
  5771. }
  5772. // Recursively invoke settings for PanelAnimationVars
  5773. void Panel::InternalApplySettings( PanelAnimationMap *map, KeyValues *inResourceData)
  5774. {
  5775. // Loop through keys
  5776. KeyValues *kv;
  5777. for ( kv = inResourceData->GetFirstSubKey(); kv; kv = kv->GetNextKey() )
  5778. {
  5779. char const *varname = kv->GetName();
  5780. PanelAnimationMapEntry *entry = FindPanelAnimationEntry( varname, GetAnimMap() );
  5781. if ( entry )
  5782. {
  5783. // Set value to value from script
  5784. IPanelAnimationPropertyConverter *converter = FindConverter( entry->type() );
  5785. if ( converter )
  5786. {
  5787. converter->SetData( this, inResourceData, entry );
  5788. }
  5789. }
  5790. }
  5791. }
  5792. //-----------------------------------------------------------------------------
  5793. // Purpose: sets the default values of all CPanelAnimationVars
  5794. //-----------------------------------------------------------------------------
  5795. void Panel::InternalInitDefaultValues( PanelAnimationMap *map )
  5796. {
  5797. _flags.ClearFlag( NEEDS_DEFAULT_SETTINGS_APPLIED );
  5798. // Look through mapping for entry
  5799. int c = map->entries.Count();
  5800. for ( int i = 0; i < c; i++ )
  5801. {
  5802. PanelAnimationMapEntry *e = &map->entries[ i ];
  5803. Assert( e );
  5804. IPanelAnimationPropertyConverter *converter = FindConverter( e->type() );
  5805. if ( !converter )
  5806. continue;
  5807. converter->InitFromDefault( this, e );
  5808. }
  5809. if ( map->baseMap )
  5810. {
  5811. InternalInitDefaultValues( map->baseMap );
  5812. }
  5813. }
  5814. //-----------------------------------------------------------------------------
  5815. // Purpose:
  5816. // Input : -
  5817. //-----------------------------------------------------------------------------
  5818. int Panel::GetPaintBackgroundType()
  5819. {
  5820. return m_nPaintBackgroundType;
  5821. }
  5822. //-----------------------------------------------------------------------------
  5823. // Purpose:
  5824. // Input : w -
  5825. // h -
  5826. //-----------------------------------------------------------------------------
  5827. void Panel::GetCornerTextureSize( int& w, int& h )
  5828. {
  5829. if ( m_nBgTextureId1 == -1 )
  5830. {
  5831. w = h = 0;
  5832. return;
  5833. }
  5834. surface()->DrawGetTextureSize(m_nBgTextureId1, w, h);
  5835. }
  5836. //-----------------------------------------------------------------------------
  5837. // Purpose: draws a selection box
  5838. //-----------------------------------------------------------------------------
  5839. void Panel::DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, bool hollow /*=false*/ )
  5840. {
  5841. if ( m_nBgTextureId1 == -1 ||
  5842. m_nBgTextureId2 == -1 ||
  5843. m_nBgTextureId3 == -1 ||
  5844. m_nBgTextureId4 == -1 )
  5845. {
  5846. return;
  5847. }
  5848. color[3] *= normalizedAlpha;
  5849. // work out our bounds
  5850. int cornerWide, cornerTall;
  5851. GetCornerTextureSize( cornerWide, cornerTall );
  5852. // draw the background in the areas not occupied by the corners
  5853. // draw it in three horizontal strips
  5854. surface()->DrawSetColor(color);
  5855. surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall);
  5856. if ( !hollow )
  5857. {
  5858. surface()->DrawFilledRect(x, y + cornerTall, x + wide, y + tall - cornerTall);
  5859. }
  5860. else
  5861. {
  5862. surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall);
  5863. surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall);
  5864. }
  5865. surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall);
  5866. // draw the corners
  5867. //=============================================================================
  5868. // HPE_BEGIN:
  5869. // [tj] We now check each individual corner and decide whether to draw it straight or rounded
  5870. //=============================================================================
  5871. //TOP-LEFT
  5872. if (ShouldDrawTopLeftCornerRounded())
  5873. {
  5874. surface()->DrawSetTexture(m_nBgTextureId1);
  5875. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  5876. }
  5877. else
  5878. {
  5879. surface()->DrawFilledRect(x, y, x + cornerWide, y + cornerTall);
  5880. }
  5881. //TOP-RIGHT
  5882. if (ShouldDrawTopRightCornerRounded())
  5883. {
  5884. surface()->DrawSetTexture(m_nBgTextureId2);
  5885. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5886. }
  5887. else
  5888. {
  5889. surface()->DrawFilledRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5890. }
  5891. //BOTTOM-LEFT
  5892. if (ShouldDrawBottomLeftCornerRounded())
  5893. {
  5894. surface()->DrawSetTexture(m_nBgTextureId4);
  5895. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5896. }
  5897. else
  5898. {
  5899. surface()->DrawFilledRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5900. }
  5901. //BOTTOM-RIGHT
  5902. if (ShouldDrawBottomRightCornerRounded())
  5903. {
  5904. surface()->DrawSetTexture(m_nBgTextureId3);
  5905. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5906. }
  5907. else
  5908. {
  5909. surface()->DrawFilledRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5910. }
  5911. //=============================================================================
  5912. // HPE_END
  5913. //=============================================================================
  5914. }
  5915. 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*/ )
  5916. {
  5917. if ( m_nBgTextureId1 == -1 ||
  5918. m_nBgTextureId2 == -1 ||
  5919. m_nBgTextureId3 == -1 ||
  5920. m_nBgTextureId4 == -1 ||
  5921. surface()->DrawGetAlphaMultiplier() == 0 )
  5922. {
  5923. return;
  5924. }
  5925. color[3] *= normalizedAlpha;
  5926. // work out our bounds
  5927. int cornerWide, cornerTall;
  5928. GetCornerTextureSize( cornerWide, cornerTall );
  5929. if ( !bHorizontal )
  5930. {
  5931. // draw the background in the areas not occupied by the corners
  5932. // draw it in three horizontal strips
  5933. surface()->DrawSetColor(color);
  5934. surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + cornerTall, alpha0, alpha0, bHorizontal );
  5935. if ( !hollow )
  5936. {
  5937. surface()->DrawFilledRectFade(x, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5938. }
  5939. else
  5940. {
  5941. surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5942. surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5943. }
  5944. surface()->DrawFilledRectFade(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall, alpha1, alpha1, bHorizontal);
  5945. }
  5946. else
  5947. {
  5948. // draw the background in the areas not occupied by the corners
  5949. // draw it in three horizontal strips
  5950. surface()->DrawSetColor(color);
  5951. surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha0, bHorizontal );
  5952. if ( !hollow )
  5953. {
  5954. surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + tall, alpha0, alpha1, bHorizontal);
  5955. }
  5956. else
  5957. {
  5958. // FIXME: Hollow horz version not implemented
  5959. //surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5960. //surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5961. }
  5962. surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha1, alpha1, bHorizontal);
  5963. }
  5964. float fOldAlpha = color[ 3 ];
  5965. int iAlpha0 = fOldAlpha * ( static_cast<float>( alpha0 ) / 255.0f );
  5966. int iAlpha1 = fOldAlpha * ( static_cast<float>( alpha1 ) / 255.0f );
  5967. // draw the corners
  5968. if ( !bHorizontal )
  5969. {
  5970. color[ 3 ] = iAlpha0;
  5971. surface()->DrawSetColor( color );
  5972. surface()->DrawSetTexture(m_nBgTextureId1);
  5973. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  5974. surface()->DrawSetTexture(m_nBgTextureId2);
  5975. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5976. color[ 3 ] = iAlpha1;
  5977. surface()->DrawSetColor( color );
  5978. surface()->DrawSetTexture(m_nBgTextureId3);
  5979. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5980. surface()->DrawSetTexture(m_nBgTextureId4);
  5981. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5982. }
  5983. else
  5984. {
  5985. color[ 3 ] = iAlpha0;
  5986. surface()->DrawSetColor( color );
  5987. surface()->DrawSetTexture(m_nBgTextureId1);
  5988. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  5989. surface()->DrawSetTexture(m_nBgTextureId4);
  5990. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5991. color[ 3 ] = iAlpha1;
  5992. surface()->DrawSetColor( color );
  5993. surface()->DrawSetTexture(m_nBgTextureId2);
  5994. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5995. surface()->DrawSetTexture(m_nBgTextureId3);
  5996. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5997. }
  5998. }
  5999. //-----------------------------------------------------------------------------
  6000. // Purpose:
  6001. // Input : x -
  6002. // y -
  6003. // wide -
  6004. // tall -
  6005. // color -
  6006. // normalizedAlpha -
  6007. //-----------------------------------------------------------------------------
  6008. void Panel::DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha )
  6009. {
  6010. DrawBox( x, y, wide, tall, color, normalizedAlpha, true );
  6011. }
  6012. //=============================================================================
  6013. // HPE_BEGIN:
  6014. // [menglish] Draws a hollow box similar to the already existing draw hollow box function, but takes the indents as params
  6015. //=============================================================================
  6016. void Panel::DrawHollowBox( int x, int y, int wide, int tall, Color color, float normalizedAlpha, int cornerWide, int cornerTall )
  6017. {
  6018. if ( m_nBgTextureId1 == -1 ||
  6019. m_nBgTextureId2 == -1 ||
  6020. m_nBgTextureId3 == -1 ||
  6021. m_nBgTextureId4 == -1 )
  6022. {
  6023. return;
  6024. }
  6025. color[3] *= normalizedAlpha;
  6026. // draw the background in the areas not occupied by the corners
  6027. // draw it in three horizontal strips
  6028. surface()->DrawSetColor(color);
  6029. surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall);
  6030. surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall);
  6031. surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall);
  6032. surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall);
  6033. // draw the corners
  6034. surface()->DrawSetTexture(m_nBgTextureId1);
  6035. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  6036. surface()->DrawSetTexture(m_nBgTextureId2);
  6037. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  6038. surface()->DrawSetTexture(m_nBgTextureId3);
  6039. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  6040. surface()->DrawSetTexture(m_nBgTextureId4);
  6041. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  6042. }
  6043. //=============================================================================
  6044. // HPE_END
  6045. //=============================================================================
  6046. //-----------------------------------------------------------------------------
  6047. // Purpose: draws a selection box
  6048. //-----------------------------------------------------------------------------
  6049. void Panel::DrawTexturedBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha )
  6050. {
  6051. if ( m_nBgTextureId1 == -1 )
  6052. return;
  6053. color[3] *= normalizedAlpha;
  6054. surface()->DrawSetColor( color );
  6055. surface()->DrawSetTexture(m_nBgTextureId1);
  6056. surface()->DrawTexturedRect(x, y, x + wide, y + tall);
  6057. }
  6058. //-----------------------------------------------------------------------------
  6059. // Purpose: Marks this panel as draggable (note that children will chain to their parents to see if any parent is draggable)
  6060. // Input : enabled -
  6061. //-----------------------------------------------------------------------------
  6062. void Panel::SetDragEnabled( bool enabled )
  6063. {
  6064. #if defined( VGUI_USEDRAGDROP )
  6065. // If turning it off, quit dragging if mid-drag
  6066. if ( !enabled &&
  6067. m_pDragDrop->m_bDragging )
  6068. {
  6069. OnFinishDragging( false, (MouseCode)-1 );
  6070. }
  6071. m_pDragDrop->m_bDragEnabled = enabled;
  6072. #endif
  6073. }
  6074. //-----------------------------------------------------------------------------
  6075. // Purpose:
  6076. // Input : -
  6077. // Output : Returns true on success, false on failure.
  6078. //-----------------------------------------------------------------------------
  6079. bool Panel::IsDragEnabled() const
  6080. {
  6081. #if defined( VGUI_USEDRAGDROP )
  6082. return m_pDragDrop->m_bDragEnabled;
  6083. #endif
  6084. return false;
  6085. }
  6086. void Panel::SetShowDragHelper( bool enabled )
  6087. {
  6088. #if defined( VGUI_USEDRAGDROP )
  6089. m_pDragDrop->m_bShowDragHelper = enabled;
  6090. #endif
  6091. }
  6092. // 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
  6093. // draggable parent.
  6094. void Panel::SetBlockDragChaining( bool block )
  6095. {
  6096. #if defined( VGUI_USEDRAGDROP )
  6097. m_pDragDrop->m_bPreventChaining = block;
  6098. #endif
  6099. }
  6100. //-----------------------------------------------------------------------------
  6101. // Purpose:
  6102. // Input : -
  6103. // Output : Returns true on success, false on failure.
  6104. //-----------------------------------------------------------------------------
  6105. bool Panel::IsBlockingDragChaining() const
  6106. {
  6107. #if defined( VGUI_USEDRAGDROP )
  6108. return m_pDragDrop->m_bPreventChaining;
  6109. #endif
  6110. return true;
  6111. }
  6112. //-----------------------------------------------------------------------------
  6113. // accessors for m_nDragStartTolerance
  6114. //-----------------------------------------------------------------------------
  6115. int Panel::GetDragStartTolerance() const
  6116. {
  6117. #if defined( VGUI_USEDRAGDROP )
  6118. return m_pDragDrop->m_nDragStartTolerance;
  6119. #endif
  6120. return 0;
  6121. }
  6122. void Panel::SetDragSTartTolerance( int nTolerance )
  6123. {
  6124. #if defined( VGUI_USEDRAGDROP )
  6125. m_pDragDrop->m_nDragStartTolerance = nTolerance;
  6126. #endif
  6127. }
  6128. //-----------------------------------------------------------------------------
  6129. // Purpose: Marks this panel as droppable ( note that children will chain to their parents to see if any parent is droppable)
  6130. // Input : enabled -
  6131. //-----------------------------------------------------------------------------
  6132. void Panel::SetDropEnabled( bool enabled, float flHoverContextTime /* = 0.0f */ )
  6133. {
  6134. #if defined( VGUI_USEDRAGDROP )
  6135. m_pDragDrop->m_bDropEnabled = enabled;
  6136. m_pDragDrop->m_flHoverContextTime = flHoverContextTime;
  6137. #endif
  6138. }
  6139. //-----------------------------------------------------------------------------
  6140. // Purpose:
  6141. // Input : -
  6142. // Output : Returns true on success, false on failure.
  6143. //-----------------------------------------------------------------------------
  6144. bool Panel::IsDropEnabled() const
  6145. {
  6146. #if defined( VGUI_USEDRAGDROP )
  6147. return m_pDragDrop->m_bDropEnabled;
  6148. #endif
  6149. return false;
  6150. }
  6151. //-----------------------------------------------------------------------------
  6152. // Purpose: Chains up to any parent
  6153. // 1) marked DropEnabled; and
  6154. // 2) willing to accept the drop payload
  6155. // Input : -
  6156. // Output : Panel
  6157. //-----------------------------------------------------------------------------
  6158. Panel *Panel::GetDropTarget( CUtlVector< KeyValues * >& msglist )
  6159. {
  6160. #if defined( VGUI_USEDRAGDROP )
  6161. // Found one
  6162. if ( m_pDragDrop->m_bDropEnabled &&
  6163. IsDroppable( msglist ) )
  6164. {
  6165. return this;
  6166. }
  6167. // Chain up
  6168. if ( GetParent() )
  6169. {
  6170. return GetParent()->GetDropTarget( msglist );
  6171. }
  6172. #endif
  6173. // No luck
  6174. return NULL;
  6175. }
  6176. //-----------------------------------------------------------------------------
  6177. // Purpose: Chains up to first parent marked DragEnabled
  6178. // Input : -
  6179. // Output : Panel
  6180. //-----------------------------------------------------------------------------
  6181. Panel *Panel::GetDragPanel()
  6182. {
  6183. #if defined( VGUI_USEDRAGDROP )
  6184. // If we encounter a blocker, stop chaining
  6185. if ( m_pDragDrop->m_bPreventChaining )
  6186. return NULL;
  6187. if ( m_pDragDrop->m_bDragEnabled )
  6188. return this;
  6189. // Chain up
  6190. if ( GetParent() )
  6191. {
  6192. return GetParent()->GetDragPanel();
  6193. }
  6194. #endif
  6195. // No luck
  6196. return NULL;
  6197. }
  6198. //-----------------------------------------------------------------------------
  6199. // Purpose:
  6200. // Input : -
  6201. //-----------------------------------------------------------------------------
  6202. void Panel::OnStartDragging()
  6203. {
  6204. #if defined( VGUI_USEDRAGDROP )
  6205. // Only left mouse initiates drag/drop.
  6206. // FIXME: Revisit?
  6207. if ( !input()->IsMouseDown( MOUSE_LEFT ) )
  6208. return;
  6209. if ( !m_pDragDrop->m_bDragEnabled )
  6210. return;
  6211. if ( m_pDragDrop->m_bDragging )
  6212. return;
  6213. g_DragDropCapture = this;
  6214. m_pDragDrop->m_bDragStarted = false;
  6215. m_pDragDrop->m_bDragging = true;
  6216. input()->GetCursorPos( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ] );
  6217. m_pDragDrop->m_nLastPos[ 0 ] = m_pDragDrop->m_nStartPos[ 0 ];
  6218. m_pDragDrop->m_nLastPos[ 1 ] = m_pDragDrop->m_nStartPos[ 1 ];
  6219. OnContinueDragging();
  6220. #endif
  6221. }
  6222. //-----------------------------------------------------------------------------
  6223. // Purpose: Called if drag drop is started but not dropped on top of droppable panel...
  6224. // Input : -
  6225. //-----------------------------------------------------------------------------
  6226. void Panel::OnDragFailed( CUtlVector< KeyValues * >& msglist )
  6227. {
  6228. }
  6229. //-----------------------------------------------------------------------------
  6230. // Purpose:
  6231. // Input : -
  6232. //-----------------------------------------------------------------------------
  6233. void Panel::OnFinishDragging( bool mousereleased, MouseCode code, bool abort /*= false*/ )
  6234. {
  6235. #if defined( VGUI_USEDRAGDROP )
  6236. g_DragDropCapture = NULL;
  6237. if ( !m_pDragDrop->m_bDragEnabled )
  6238. return;
  6239. Assert( m_pDragDrop->m_bDragging );
  6240. if ( !m_pDragDrop->m_bDragging )
  6241. return;
  6242. int x, y;
  6243. input()->GetCursorPos( x, y );
  6244. m_pDragDrop->m_nLastPos[ 0 ] = x;
  6245. m_pDragDrop->m_nLastPos[ 1 ] = y;
  6246. if ( s_DragDropHelper.Get() )
  6247. {
  6248. s_DragDropHelper->RemovePanel( this );
  6249. }
  6250. m_pDragDrop->m_bDragging = false;
  6251. CUtlVector< KeyValues * >& data = m_pDragDrop->m_DragData;
  6252. int c = data.Count();
  6253. Panel *target = NULL;
  6254. bool shouldDrop = false;
  6255. if ( m_pDragDrop->m_bDragStarted )
  6256. {
  6257. char cmd[ 256 ];
  6258. Q_strncpy( cmd, "default", sizeof( cmd ) );
  6259. if ( mousereleased &&
  6260. m_pDragDrop->m_hCurrentDrop != NULL &&
  6261. m_pDragDrop->m_hDropContextMenu.Get() )
  6262. {
  6263. Menu *menu = m_pDragDrop->m_hDropContextMenu;
  6264. VPANEL hover = menu->IsWithinTraverse( x, y, false );
  6265. if ( hover )
  6266. {
  6267. Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() );
  6268. if ( pHover )
  6269. {
  6270. // Figure out if it's a menu item...
  6271. int c = menu->GetItemCount();
  6272. for ( int i = 0; i < c; ++i )
  6273. {
  6274. int id = menu->GetMenuID( i );
  6275. MenuItem *item = menu->GetMenuItem( id );
  6276. if ( item == pHover )
  6277. {
  6278. KeyValues *command = item->GetCommand();
  6279. if ( command )
  6280. {
  6281. char const *p = command->GetString( "command", "" );
  6282. if ( p && p[ 0 ] )
  6283. {
  6284. Q_strncpy( cmd, p, sizeof( cmd ) );
  6285. }
  6286. }
  6287. }
  6288. }
  6289. }
  6290. }
  6291. delete menu;
  6292. m_pDragDrop->m_hDropContextMenu = NULL;
  6293. }
  6294. for ( int i = 0 ; i < c; ++i )
  6295. {
  6296. KeyValues *msg = data[ i ];
  6297. msg->SetString( "command", cmd );
  6298. msg->SetInt( "screenx", x );
  6299. msg->SetInt( "screeny", y );
  6300. }
  6301. target = m_pDragDrop->m_hCurrentDrop.Get();
  6302. if ( target && !abort )
  6303. {
  6304. int localmousex = x, localmousey = y;
  6305. // Convert screen space coordintes to coordinates relative to drop window
  6306. target->ScreenToLocal( localmousex, localmousey );
  6307. for ( int i = 0 ; i < c; ++i )
  6308. {
  6309. KeyValues *msg = data[ i ];
  6310. msg->SetInt( "x", localmousex );
  6311. msg->SetInt( "y", localmousey );
  6312. }
  6313. shouldDrop = true;
  6314. }
  6315. if ( !shouldDrop )
  6316. {
  6317. OnDragFailed( data );
  6318. }
  6319. }
  6320. m_pDragDrop->m_bDragStarted = false;
  6321. m_pDragDrop->m_DragPanels.RemoveAll();
  6322. m_pDragDrop->m_hCurrentDrop = NULL;
  6323. // Copy data ptrs out of data because OnPanelDropped might cause this panel to be deleted
  6324. // and our this ptr will be hosed...
  6325. CUtlVector< KeyValues * > temp;
  6326. for ( int i = 0 ; i < c; ++i )
  6327. {
  6328. temp.AddToTail( data[ i ] );
  6329. }
  6330. data.RemoveAll();
  6331. if ( shouldDrop && target )
  6332. {
  6333. target->OnPanelDropped( temp );
  6334. }
  6335. for ( int i = 0 ; i < c ; ++i )
  6336. {
  6337. temp[ i ]->deleteThis();
  6338. }
  6339. #endif
  6340. }
  6341. void Panel::OnDropContextHoverShow( CUtlVector< KeyValues * >& msglist )
  6342. {
  6343. }
  6344. void Panel::OnDropContextHoverHide( CUtlVector< KeyValues * >& msglist )
  6345. {
  6346. }
  6347. //-----------------------------------------------------------------------------
  6348. // Purpose:
  6349. // Input : *msg -
  6350. // Output : Returns true on success, false on failure.
  6351. //-----------------------------------------------------------------------------
  6352. bool Panel::IsDroppable( CUtlVector< KeyValues * >& msglist )
  6353. {
  6354. return false;
  6355. }
  6356. //-----------------------------------------------------------------------------
  6357. // Purpose:
  6358. // Input : startx -
  6359. // starty -
  6360. // mx -
  6361. // my -
  6362. // Output : Returns true on success, false on failure.
  6363. //-----------------------------------------------------------------------------
  6364. bool Panel::CanStartDragging( int startx, int starty, int mx, int my )
  6365. {
  6366. #if defined( VGUI_USEDRAGDROP )
  6367. if ( IsStartDragWhenMouseExitsPanel() )
  6368. {
  6369. ScreenToLocal( mx, my );
  6370. if ( mx < 0 || my < 0 )
  6371. return true;
  6372. if ( mx > GetWide() || my > GetTall() )
  6373. return true;
  6374. return false;
  6375. }
  6376. int deltax = abs( mx - startx );
  6377. int deltay = abs( my - starty );
  6378. if ( deltax > m_pDragDrop->m_nDragStartTolerance ||
  6379. deltay > m_pDragDrop->m_nDragStartTolerance )
  6380. {
  6381. return true;
  6382. }
  6383. #endif
  6384. return false;
  6385. }
  6386. HCursor Panel::GetDropCursor( CUtlVector< KeyValues * >& msglist )
  6387. {
  6388. return dc_arrow;
  6389. }
  6390. bool IsSelfDroppable( CUtlVector< KeyValues * > &dragData )
  6391. {
  6392. if ( dragData.Count() == 0 )
  6393. return false;
  6394. KeyValues *pKeyValues( dragData[ 0 ] );
  6395. if ( !pKeyValues )
  6396. return false;
  6397. return pKeyValues->GetInt( "selfDroppable" ) != 0;
  6398. }
  6399. //-----------------------------------------------------------------------------
  6400. // Purpose:
  6401. // Input : -
  6402. //-----------------------------------------------------------------------------
  6403. void Panel::OnContinueDragging()
  6404. {
  6405. #if defined( VGUI_USEDRAGDROP )
  6406. if ( !m_pDragDrop->m_bDragEnabled )
  6407. return;
  6408. if ( !m_pDragDrop->m_bDragging )
  6409. return;
  6410. int x, y;
  6411. input()->GetCursorPos( x, y );
  6412. // Update last position
  6413. m_pDragDrop->m_nLastPos[ 0 ] = x;
  6414. m_pDragDrop->m_nLastPos[ 1 ] = y;
  6415. if ( !m_pDragDrop->m_bDragStarted )
  6416. {
  6417. if ( CanStartDragging( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ], x, y ) )
  6418. {
  6419. m_pDragDrop->m_bDragStarted = true;
  6420. CreateDragData();
  6421. }
  6422. else
  6423. {
  6424. return;
  6425. }
  6426. }
  6427. if ( !s_DragDropHelper.Get() && m_pDragDrop->m_bShowDragHelper )
  6428. {
  6429. s_DragDropHelper = new CDragDropHelperPanel();
  6430. s_DragDropHelper->SetKeyBoardInputEnabled( false );
  6431. s_DragDropHelper->SetMouseInputEnabled( false );
  6432. Assert( s_DragDropHelper.Get() );
  6433. }
  6434. if ( !s_DragDropHelper.Get() )
  6435. return;
  6436. s_DragDropHelper->AddPanel( this );
  6437. Assert( m_pDragDrop->m_DragData.Count() );
  6438. vgui::PHandle oldDrop = m_pDragDrop->m_hCurrentDrop;
  6439. // See what's under that
  6440. m_pDragDrop->m_hCurrentDrop = NULL;
  6441. // Search under mouse pos...
  6442. Panel *dropTarget = FindDropTargetPanel();
  6443. if ( dropTarget )
  6444. {
  6445. dropTarget = dropTarget->GetDropTarget( m_pDragDrop->m_DragData );
  6446. }
  6447. // it's not okay until we find a droppable panel
  6448. surface()->SetCursor( GetDragFailCursor( m_pDragDrop->m_DragData ) );
  6449. if ( dropTarget )
  6450. {
  6451. if ( dropTarget != this || IsSelfDroppable( m_pDragDrop->m_DragData ) )
  6452. {
  6453. m_pDragDrop->m_hCurrentDrop = dropTarget;
  6454. surface()->SetCursor( dropTarget->GetDropCursor( m_pDragDrop->m_DragData ) );
  6455. }
  6456. }
  6457. if ( m_pDragDrop->m_hCurrentDrop.Get() != oldDrop.Get() )
  6458. {
  6459. if ( oldDrop.Get() )
  6460. {
  6461. oldDrop->OnPanelExitedDroppablePanel( m_pDragDrop->m_DragData );
  6462. }
  6463. if ( m_pDragDrop->m_hCurrentDrop.Get() )
  6464. {
  6465. m_pDragDrop->m_hCurrentDrop->OnPanelEnteredDroppablePanel( m_pDragDrop->m_DragData );
  6466. m_pDragDrop->m_hCurrentDrop->OnDropContextHoverHide( m_pDragDrop->m_DragData );
  6467. // Reset hover time
  6468. m_pDragDrop->m_lDropHoverTime = system()->GetTimeMillis();
  6469. m_pDragDrop->m_bDropMenuShown = false;
  6470. }
  6471. // Discard any stale context menu...
  6472. if ( m_pDragDrop->m_hDropContextMenu.Get() )
  6473. {
  6474. delete m_pDragDrop->m_hDropContextMenu.Get();
  6475. }
  6476. }
  6477. if ( m_pDragDrop->m_hCurrentDrop != NULL &&
  6478. m_pDragDrop->m_hDropContextMenu.Get() )
  6479. {
  6480. Menu *menu = m_pDragDrop->m_hDropContextMenu;
  6481. VPANEL hover = menu->IsWithinTraverse( x, y, false );
  6482. if ( hover )
  6483. {
  6484. Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() );
  6485. if ( pHover )
  6486. {
  6487. // Figure out if it's a menu item...
  6488. int c = menu->GetItemCount();
  6489. for ( int i = 0; i < c; ++i )
  6490. {
  6491. int id = menu->GetMenuID( i );
  6492. MenuItem *item = menu->GetMenuItem( id );
  6493. if ( item == pHover )
  6494. {
  6495. menu->SetCurrentlyHighlightedItem( id );
  6496. }
  6497. }
  6498. }
  6499. }
  6500. else
  6501. {
  6502. menu->ClearCurrentlyHighlightedItem();
  6503. }
  6504. }
  6505. #endif
  6506. }
  6507. #if defined( VGUI_USEDRAGDROP )
  6508. //-----------------------------------------------------------------------------
  6509. // Purpose:
  6510. // Input : -
  6511. // Output : DragDrop_t
  6512. //-----------------------------------------------------------------------------
  6513. DragDrop_t *Panel::GetDragDropInfo()
  6514. {
  6515. Assert( m_pDragDrop );
  6516. return m_pDragDrop;
  6517. }
  6518. #endif
  6519. void Panel::OnGetAdditionalDragPanels( CUtlVector< Panel * >& dragabbles )
  6520. {
  6521. // Nothing here
  6522. }
  6523. //-----------------------------------------------------------------------------
  6524. // Purpose: Virtual method to allow panels to add to the default values
  6525. // Input : *msg -
  6526. //-----------------------------------------------------------------------------
  6527. void Panel::OnCreateDragData( KeyValues *msg )
  6528. {
  6529. // These values are filled in for you:
  6530. // "panel" ptr to panel being dropped
  6531. // "screenx", "screeny" - drop cursor pos in screen space
  6532. // "x", "y" - drop coordinates relative to this window (the window being dropped upon)
  6533. }
  6534. // Called if m_flHoverContextTime was non-zero, allows droppee to preview the drop data and show an appropriate menu
  6535. bool Panel::GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist )
  6536. {
  6537. return false;
  6538. }
  6539. void Panel::CreateDragData()
  6540. {
  6541. #if defined( VGUI_USEDRAGDROP )
  6542. int i, c;
  6543. if ( m_pDragDrop->m_DragData.Count() )
  6544. {
  6545. return;
  6546. }
  6547. PHandle h;
  6548. h = this;
  6549. m_pDragDrop->m_DragPanels.AddToTail( h );
  6550. CUtlVector< Panel * > temp;
  6551. OnGetAdditionalDragPanels( temp );
  6552. c = temp.Count();
  6553. for ( i = 0; i < c; ++i )
  6554. {
  6555. if ( temp[ i ] == this )
  6556. continue;
  6557. h = temp[ i ];
  6558. m_pDragDrop->m_DragPanels.AddToTail( h );
  6559. }
  6560. c = m_pDragDrop->m_DragPanels.Count();
  6561. for ( i = 0 ; i < c; ++i )
  6562. {
  6563. Panel *sibling = m_pDragDrop->m_DragPanels[ i ].Get();
  6564. if ( !sibling )
  6565. {
  6566. continue;
  6567. }
  6568. KeyValues *msg = new KeyValues( "DragDrop" );
  6569. msg->SetPtr( "panel", sibling );
  6570. sibling->OnCreateDragData( msg );
  6571. m_pDragDrop->m_DragData.AddToTail( msg );
  6572. }
  6573. #endif
  6574. }
  6575. //-----------------------------------------------------------------------------
  6576. // Purpose:
  6577. // Input : -
  6578. // Output : KeyValues
  6579. //-----------------------------------------------------------------------------
  6580. void Panel::GetDragData( CUtlVector< KeyValues * >& list )
  6581. {
  6582. #if defined( VGUI_USEDRAGDROP )
  6583. int i, c;
  6584. list.RemoveAll();
  6585. c = m_pDragDrop->m_DragData.Count();
  6586. for ( i = 0 ; i < c; ++i )
  6587. {
  6588. list.AddToTail( m_pDragDrop->m_DragData[ i ] );
  6589. }
  6590. #endif
  6591. }
  6592. #if defined( VGUI_USEDRAGDROP )
  6593. CDragDropHelperPanel::CDragDropHelperPanel() : BaseClass( NULL, "DragDropHelper" )
  6594. {
  6595. SetVisible( true );
  6596. SetPaintEnabled( false );
  6597. SetPaintBackgroundEnabled( false );
  6598. SetMouseInputEnabled( false );
  6599. SetKeyBoardInputEnabled( false );
  6600. // SetCursor( dc_none );
  6601. ipanel()->SetTopmostPopup( GetVPanel(), true );
  6602. int w, h;
  6603. surface()->GetScreenSize( w, h );
  6604. SetBounds( 0, 0, w, h );
  6605. SetPostChildPaintEnabled( true );
  6606. MakePopup( false );
  6607. }
  6608. VPANEL CDragDropHelperPanel::IsWithinTraverse(int x, int y, bool traversePopups)
  6609. {
  6610. return (VPANEL)0;
  6611. }
  6612. void CDragDropHelperPanel::PostChildPaint()
  6613. {
  6614. int c = m_PaintList.Count();
  6615. for ( int i = c - 1; i >= 0 ; --i )
  6616. {
  6617. DragHelperPanel_t& data = m_PaintList[ i ];
  6618. Panel *panel = data.m_hPanel.Get();
  6619. if ( !panel )
  6620. {
  6621. m_PaintList.Remove( i );
  6622. continue;
  6623. }
  6624. Panel *dropPanel = panel->GetDragDropInfo()->m_hCurrentDrop.Get();
  6625. if ( panel )
  6626. {
  6627. if ( !dropPanel )
  6628. {
  6629. panel->OnDraggablePanelPaint();
  6630. }
  6631. else
  6632. {
  6633. CUtlVector< Panel * > temp;
  6634. CUtlVector< PHandle >& data = panel->GetDragDropInfo()->m_DragPanels;
  6635. CUtlVector< KeyValues * >& msglist = panel->GetDragDropInfo()->m_DragData;
  6636. int i, c;
  6637. c = data.Count();
  6638. for ( i = 0; i < c ; ++i )
  6639. {
  6640. Panel *pPanel = data[ i ].Get();
  6641. if ( pPanel )
  6642. {
  6643. temp.AddToTail( pPanel );
  6644. }
  6645. }
  6646. dropPanel->OnDroppablePanelPaint( msglist, temp );
  6647. }
  6648. }
  6649. }
  6650. if ( c == 0 )
  6651. {
  6652. MarkForDeletion();
  6653. }
  6654. }
  6655. void CDragDropHelperPanel::AddPanel( Panel *current )
  6656. {
  6657. if ( !current )
  6658. return;
  6659. Menu *hover = current->GetDragDropInfo()->m_hDropContextMenu.Get();
  6660. surface()->MovePopupToFront( GetVPanel() );
  6661. if ( hover && hover->IsPopup() )
  6662. {
  6663. surface()->MovePopupToFront( hover->GetVPanel() );
  6664. }
  6665. int c = m_PaintList.Count();
  6666. for ( int i = 0; i < c; ++i )
  6667. {
  6668. if ( m_PaintList[ i ].m_hPanel.Get() == current )
  6669. return;
  6670. }
  6671. DragHelperPanel_t data;
  6672. data.m_hPanel = current;
  6673. m_PaintList.AddToTail( data );
  6674. }
  6675. //-----------------------------------------------------------------------------
  6676. // Purpose:
  6677. // Input : *search -
  6678. //-----------------------------------------------------------------------------
  6679. void CDragDropHelperPanel::RemovePanel( Panel *search )
  6680. {
  6681. int c = m_PaintList.Count();
  6682. for ( int i = c - 1 ; i >= 0; --i )
  6683. {
  6684. if ( m_PaintList[ i ].m_hPanel.Get() == search )
  6685. {
  6686. m_PaintList.Remove( i );
  6687. return;
  6688. }
  6689. }
  6690. }
  6691. #endif
  6692. //-----------------------------------------------------------------------------
  6693. // Purpose: Enumerates panels under mouse x,y
  6694. // Input : panelList -
  6695. // x -
  6696. // y -
  6697. // check -
  6698. //-----------------------------------------------------------------------------
  6699. void Panel::FindDropTargetPanel_R( CUtlVector< VPANEL >& panelList, int x, int y, VPANEL check )
  6700. {
  6701. #if defined( VGUI_USEDRAGDROP )
  6702. if ( !ipanel()->IsFullyVisible( check ) )
  6703. return;
  6704. if ( ::ShouldHandleInputMessage( check ) && ipanel()->IsWithinTraverse( check, x, y, false ) )
  6705. {
  6706. panelList.AddToTail( check );
  6707. }
  6708. CUtlVector< VPANEL > &children = ipanel()->GetChildren( check );
  6709. int childCount = children.Count();
  6710. for ( int i = 0; i < childCount; i++ )
  6711. {
  6712. VPANEL child = children[ i ];
  6713. FindDropTargetPanel_R( panelList, x, y, child );
  6714. }
  6715. #endif
  6716. }
  6717. //-----------------------------------------------------------------------------
  6718. // Purpose:
  6719. // Input : -
  6720. // Output : Panel
  6721. //-----------------------------------------------------------------------------
  6722. Panel *Panel::FindDropTargetPanel()
  6723. {
  6724. #if defined( VGUI_USEDRAGDROP )
  6725. if ( !s_DragDropHelper.Get() )
  6726. return NULL;
  6727. CUtlVector< VPANEL > hits;
  6728. int x, y;
  6729. input()->GetCursorPos( x, y );
  6730. VPANEL embedded = surface()->GetEmbeddedPanel();
  6731. VPANEL helper = s_DragDropHelper.Get()->GetVPanel();
  6732. if ( surface()->IsCursorVisible() && surface()->IsWithin(x, y) )
  6733. {
  6734. // faster version of code below
  6735. // checks through each popup in order, top to bottom windows
  6736. int c = surface()->GetPopupCount();
  6737. for (int i = c - 1; i >= 0 && hits.Count() == 0; i--)
  6738. {
  6739. VPANEL popup = surface()->GetPopup(i);
  6740. if ( popup == embedded )
  6741. continue;
  6742. // Don't return helper panel!!!
  6743. if ( popup == helper )
  6744. continue;
  6745. if ( !ipanel()->IsFullyVisible( popup ) )
  6746. continue;
  6747. FindDropTargetPanel_R( hits, x, y, popup );
  6748. }
  6749. // Check embedded
  6750. if ( !hits.Count() )
  6751. {
  6752. FindDropTargetPanel_R( hits, x, y, embedded );
  6753. }
  6754. }
  6755. // Nothing under mouse...
  6756. if ( !hits.Count() )
  6757. return NULL;
  6758. // Return topmost panel under mouse, if it's visible to this .dll
  6759. Panel *panel = NULL;
  6760. int nCount = hits.Count();
  6761. while ( --nCount >= 0 )
  6762. {
  6763. panel = ipanel()->GetPanel( hits[ nCount ], GetModuleName() );
  6764. if ( panel )
  6765. return panel;
  6766. }
  6767. #endif
  6768. return NULL;
  6769. }
  6770. //-----------------------------------------------------------------------------
  6771. // Purpose: Mouse is on draggable panel and has started moving, but is not over a droppable panel yet
  6772. // Input : -
  6773. //-----------------------------------------------------------------------------
  6774. void Panel::OnDraggablePanelPaint()
  6775. {
  6776. #if defined( VGUI_USEDRAGDROP )
  6777. int sw, sh;
  6778. GetSize( sw, sh );
  6779. int x, y;
  6780. input()->GetCursorPos( x, y );
  6781. int w, h;
  6782. w = MIN( sw, 80 );
  6783. h = MIN( sh, 80 );
  6784. x -= ( w >> 1 );
  6785. y -= ( h >> 1 );
  6786. surface()->DrawSetColor( m_clrDragFrame );
  6787. surface()->DrawOutlinedRect( x, y, x + w, y + h );
  6788. if ( m_pDragDrop->m_DragPanels.Count() > 1 )
  6789. {
  6790. surface()->DrawSetTextColor( m_clrDragFrame );
  6791. surface()->DrawSetTextFont( m_infoFont );
  6792. surface()->DrawSetTextPos( x + 5, y + 2 );
  6793. wchar_t sz[ 64 ];
  6794. Q_snwprintf( sz, 64, L"[ %i ]", m_pDragDrop->m_DragPanels.Count() );
  6795. surface()->DrawPrintText( sz, wcslen( sz ) );
  6796. }
  6797. #endif
  6798. }
  6799. //-----------------------------------------------------------------------------
  6800. // Purpose: Mouse is now over a droppable panel
  6801. // Input : *dragPanel -
  6802. //-----------------------------------------------------------------------------
  6803. void Panel::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
  6804. {
  6805. #if defined( VGUI_USEDRAGDROP )
  6806. if ( !dragPanels.Count() )
  6807. return;
  6808. // Convert this panel's bounds to screen space
  6809. int w, h;
  6810. GetSize( w, h );
  6811. int x, y;
  6812. x = y = 0;
  6813. LocalToScreen( x, y );
  6814. surface()->DrawSetColor( m_clrDropFrame );
  6815. // Draw 2 pixel frame
  6816. surface()->DrawOutlinedRect( x, y, x + w, y + h );
  6817. surface()->DrawOutlinedRect( x+1, y+1, x + w-1, y + h-1 );
  6818. #endif
  6819. }
  6820. //-----------------------------------------------------------------------------
  6821. // Purpose:
  6822. // Input : -
  6823. // Output : Color
  6824. //-----------------------------------------------------------------------------
  6825. Color Panel::GetDropFrameColor()
  6826. {
  6827. #if defined( VGUI_USEDRAGDROP )
  6828. return m_clrDropFrame;
  6829. #endif
  6830. return Color(0, 0, 0, 0);
  6831. }
  6832. //-----------------------------------------------------------------------------
  6833. // Purpose:
  6834. // Input : -
  6835. // Output : Color
  6836. //-----------------------------------------------------------------------------
  6837. Color Panel::GetDragFrameColor()
  6838. {
  6839. #if defined( VGUI_USEDRAGDROP )
  6840. return m_clrDragFrame;
  6841. #endif
  6842. return Color(0, 0, 0, 0);
  6843. }
  6844. //-----------------------------------------------------------------------------
  6845. // Purpose:
  6846. // Input : *data -
  6847. //-----------------------------------------------------------------------------
  6848. void Panel::OnPanelDropped( CUtlVector< KeyValues * >& data )
  6849. {
  6850. // Empty. Derived classes would implement handlers here
  6851. }
  6852. //-----------------------------------------------------------------------------
  6853. // called on droptarget when draggable panel enters droptarget
  6854. //-----------------------------------------------------------------------------
  6855. void Panel::OnPanelEnteredDroppablePanel( CUtlVector< KeyValues * >& msglist )
  6856. {
  6857. // Empty. Derived classes would implement handlers here
  6858. }
  6859. //-----------------------------------------------------------------------------
  6860. // called on droptarget when draggable panel exits droptarget
  6861. //-----------------------------------------------------------------------------
  6862. void Panel::OnPanelExitedDroppablePanel ( CUtlVector< KeyValues * >& msglist )
  6863. {
  6864. // Empty. Derived classes would implement handlers here
  6865. }
  6866. //-----------------------------------------------------------------------------
  6867. // Purpose:
  6868. // Input : -
  6869. //-----------------------------------------------------------------------------
  6870. void Panel::DragDropStartDragging()
  6871. {
  6872. #if defined( VGUI_USEDRAGDROP )
  6873. // We somehow missed a mouse release, cancel the previous drag
  6874. if ( g_DragDropCapture.Get() )
  6875. {
  6876. if ( HasParent( g_DragDropCapture.Get()->GetVPanel() ) )
  6877. return;
  6878. bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted;
  6879. g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1 );
  6880. if ( started )
  6881. {
  6882. return;
  6883. }
  6884. }
  6885. // Find actual target panel
  6886. Panel *panel = GetDragPanel();
  6887. if ( !panel )
  6888. return;
  6889. DragDrop_t *data = panel->GetDragDropInfo();
  6890. if ( !data )
  6891. return;
  6892. if ( !panel->IsDragEnabled() )
  6893. return;
  6894. if ( data->m_bDragging )
  6895. return;
  6896. panel->OnStartDragging();
  6897. #endif
  6898. }
  6899. //-----------------------------------------------------------------------------
  6900. // Purpose:
  6901. // Input : -
  6902. // Output : Returns true on success, false on failure.
  6903. //-----------------------------------------------------------------------------
  6904. bool Panel::IsBeingDragged()
  6905. {
  6906. #if defined( VGUI_USEDRAGDROP )
  6907. if ( !g_DragDropCapture.Get() )
  6908. return false;
  6909. if ( g_DragDropCapture.Get() == this )
  6910. return true;
  6911. // If we encounter a blocker, stop chaining
  6912. if ( m_pDragDrop->m_bPreventChaining )
  6913. return false;
  6914. // Chain up
  6915. if ( GetParent() )
  6916. {
  6917. return GetParent()->IsBeingDragged();
  6918. }
  6919. #endif
  6920. // No luck
  6921. return false;
  6922. }
  6923. struct srect_t
  6924. {
  6925. int x0, y0;
  6926. int x1, y1;
  6927. bool IsDegenerate()
  6928. {
  6929. if ( x1 - x0 <= 0 )
  6930. return true;
  6931. if ( y1 - y0 <= 0 )
  6932. return true;
  6933. return false;
  6934. }
  6935. };
  6936. // Draws a filled rect of specified bounds, but omits the bounds of the skip panel from those bounds
  6937. void Panel::FillRectSkippingPanel( const Color clr, int x, int y, int w, int h, Panel *skipPanel )
  6938. {
  6939. int sx = 0, sy = 0, sw, sh;
  6940. skipPanel->GetSize( sw, sh );
  6941. skipPanel->LocalToScreen( sx, sy );
  6942. ScreenToLocal( sx, sy );
  6943. surface()->DrawSetColor( clr );
  6944. srect_t r1;
  6945. r1.x0 = x;
  6946. r1.y0 = y;
  6947. r1.x1 = x + w;
  6948. r1.y1 = y + h;
  6949. srect_t r2;
  6950. r2.x0 = sx;
  6951. r2.y0 = sy;
  6952. r2.x1 = sx + sw;
  6953. r2.y1 = sy + sh;
  6954. int topy = r1.y0;
  6955. int bottomy = r1.y1;
  6956. // We'll descend vertically and draw:
  6957. // 1 a possible bar across the top
  6958. // 2 a possible bar across the bottom
  6959. // 3 possible left bar
  6960. // 4 possible right bar
  6961. // Room at top?
  6962. if ( r2.y0 > r1.y0 )
  6963. {
  6964. topy = r2.y0;
  6965. surface()->DrawFilledRect( r1.x0, r1.y0, r1.x1, topy );
  6966. }
  6967. // Room at bottom?
  6968. if ( r2.y1 < r1.y1 )
  6969. {
  6970. bottomy = r2.y1;
  6971. surface()->DrawFilledRect( r1.x0, bottomy, r1.x1, r1.y1 );
  6972. }
  6973. // Room on left side?
  6974. if ( r2.x0 > r1.x0 )
  6975. {
  6976. int left = r2.x0;
  6977. surface()->DrawFilledRect( r1.x0, topy, left, bottomy );
  6978. }
  6979. // Room on right side
  6980. if ( r2.x1 < r1.x1 )
  6981. {
  6982. int right = r2.x1;
  6983. surface()->DrawFilledRect( right, topy, r1.x1, bottomy );
  6984. }
  6985. }
  6986. //-----------------------------------------------------------------------------
  6987. // Purpose:
  6988. // Input : *child -
  6989. //-----------------------------------------------------------------------------
  6990. void Panel::SetSkipChildDuringPainting( Panel *child )
  6991. {
  6992. m_SkipChild = child;
  6993. }
  6994. HPanel Panel::ToHandle() const
  6995. {
  6996. return ivgui()->PanelToHandle( _vpanel );
  6997. }
  6998. //-----------------------------------------------------------------------------
  6999. // Purpose:
  7000. //-----------------------------------------------------------------------------
  7001. Panel* Panel::NavigateUp()
  7002. {
  7003. Panel *target = GetNavUp();
  7004. if ( target )
  7005. {
  7006. NavigateFrom();
  7007. target->m_LastNavDirection = ND_UP;
  7008. target->NavigateTo();
  7009. }
  7010. return target;
  7011. }
  7012. //-----------------------------------------------------------------------------
  7013. // Purpose:
  7014. //-----------------------------------------------------------------------------
  7015. Panel* Panel::NavigateDown()
  7016. {
  7017. Panel *target = GetNavDown();
  7018. if ( target )
  7019. {
  7020. NavigateFrom();
  7021. target->m_LastNavDirection = ND_DOWN;
  7022. target->NavigateTo();
  7023. }
  7024. return target;
  7025. }
  7026. //-----------------------------------------------------------------------------
  7027. // Purpose:
  7028. //-----------------------------------------------------------------------------
  7029. Panel* Panel::NavigateLeft()
  7030. {
  7031. Panel *target = GetNavLeft();
  7032. if ( target )
  7033. {
  7034. NavigateFrom();
  7035. target->m_LastNavDirection = ND_LEFT;
  7036. target->NavigateTo();
  7037. }
  7038. return target;
  7039. }
  7040. //-----------------------------------------------------------------------------
  7041. // Purpose:
  7042. //-----------------------------------------------------------------------------
  7043. Panel* Panel::NavigateRight()
  7044. {
  7045. Panel *target = GetNavRight();
  7046. if ( target )
  7047. {
  7048. NavigateFrom();
  7049. target->m_LastNavDirection = ND_RIGHT;
  7050. target->NavigateTo();
  7051. }
  7052. return target;
  7053. }
  7054. //-----------------------------------------------------------------------------
  7055. // Purpose:
  7056. //-----------------------------------------------------------------------------
  7057. void Panel::NavigateTo()
  7058. {
  7059. if ( IsGameConsole() )
  7060. {
  7061. RequestFocus( 0 );
  7062. }
  7063. CallParentFunction( new KeyValues( "OnNavigateTo", "panelName", GetName() ) );
  7064. /*
  7065. if( m_pTooltips )
  7066. {
  7067. m_pTooltips->ResetDelay();
  7068. m_pTooltips->ShowTooltip( this );
  7069. }
  7070. */
  7071. }
  7072. //-----------------------------------------------------------------------------
  7073. // Purpose:
  7074. //-----------------------------------------------------------------------------
  7075. void Panel::NavigateFrom()
  7076. {
  7077. for ( int i = 0; i < GetChildCount(); ++i )
  7078. {
  7079. Panel* currentNav = GetChild(i);
  7080. if ( currentNav != 0 )
  7081. {
  7082. currentNav->NavigateFrom();
  7083. }
  7084. }
  7085. CallParentFunction( new KeyValues( "OnNavigateFrom", "panelName", GetName() ) );
  7086. if ( m_pTooltips )
  7087. {
  7088. m_pTooltips->HideTooltip();
  7089. }
  7090. m_LastNavDirection = ND_NONE;
  7091. }
  7092. void Panel::NavigateToChild( Panel *pNavigateTo )
  7093. {
  7094. for( int i = 0; i != GetChildCount(); ++i )
  7095. {
  7096. vgui::Panel *pChild = GetChild(i);
  7097. if( pChild )
  7098. pChild->NavigateFrom();
  7099. }
  7100. pNavigateTo->NavigateTo();
  7101. }
  7102. //-----------------------------------------------------------------------------
  7103. // Purpose:
  7104. //-----------------------------------------------------------------------------
  7105. Panel* Panel::SetNavUp( Panel* navUp )
  7106. {
  7107. Panel* lastNav = m_NavUp;
  7108. m_NavUp = navUp;
  7109. return lastNav;
  7110. }
  7111. //-----------------------------------------------------------------------------
  7112. // Purpose:
  7113. //-----------------------------------------------------------------------------
  7114. Panel* Panel::SetNavDown( Panel* navDown )
  7115. {
  7116. Panel* lastNav = m_NavDown;
  7117. m_NavDown = navDown;
  7118. return lastNav;
  7119. }
  7120. //-----------------------------------------------------------------------------
  7121. // Purpose:
  7122. //-----------------------------------------------------------------------------
  7123. Panel* Panel::SetNavLeft( Panel* navLeft )
  7124. {
  7125. Panel* lastNav = m_NavLeft;
  7126. m_NavLeft = navLeft;
  7127. return lastNav;
  7128. }
  7129. //-----------------------------------------------------------------------------
  7130. // Purpose:
  7131. //-----------------------------------------------------------------------------
  7132. Panel* Panel::SetNavRight( Panel* navRight )
  7133. {
  7134. Panel* lastNav = m_NavRight;
  7135. m_NavRight = navRight;
  7136. return lastNav;
  7137. }
  7138. //-----------------------------------------------------------------------------
  7139. // Purpose:
  7140. //-----------------------------------------------------------------------------
  7141. Panel::NAV_DIRECTION Panel::GetLastNavDirection()
  7142. {
  7143. return m_LastNavDirection;
  7144. }
  7145. //-----------------------------------------------------------------------------
  7146. // Purpose:
  7147. //-----------------------------------------------------------------------------
  7148. void Panel::OnNavigateTo( const char* panelName )
  7149. {
  7150. }
  7151. //-----------------------------------------------------------------------------
  7152. // Purpose:
  7153. //-----------------------------------------------------------------------------
  7154. void Panel::OnNavigateFrom( const char* panelName )
  7155. {
  7156. }
  7157. //-----------------------------------------------------------------------------
  7158. // Purpose:
  7159. //-----------------------------------------------------------------------------
  7160. void Panel::SetNavUp( const char* controlName )
  7161. {
  7162. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  7163. {
  7164. m_NavUp = NULL;
  7165. m_sNavUpName = controlName;
  7166. }
  7167. }
  7168. //-----------------------------------------------------------------------------
  7169. // Purpose:
  7170. //-----------------------------------------------------------------------------
  7171. void Panel::SetNavDown( const char* controlName )
  7172. {
  7173. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  7174. {
  7175. m_NavDown = NULL;
  7176. m_sNavDownName = controlName;
  7177. }
  7178. }
  7179. //-----------------------------------------------------------------------------
  7180. // Purpose:
  7181. //-----------------------------------------------------------------------------
  7182. void Panel::SetNavLeft( const char* controlName )
  7183. {
  7184. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  7185. {
  7186. m_NavLeft = NULL;
  7187. m_sNavLeftName = controlName;
  7188. }
  7189. }
  7190. //-----------------------------------------------------------------------------
  7191. // Purpose:
  7192. //-----------------------------------------------------------------------------
  7193. void Panel::SetNavRight( const char* controlName )
  7194. {
  7195. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  7196. {
  7197. m_NavRight = NULL;
  7198. m_sNavRightName = controlName;
  7199. }
  7200. }
  7201. //-----------------------------------------------------------------------------
  7202. // Purpose:
  7203. //-----------------------------------------------------------------------------
  7204. vgui::Panel* Panel::GetNavUp( Panel *first )
  7205. {
  7206. if ( !m_NavUp && m_sNavUpName.Length() > 0 )
  7207. {
  7208. Panel* foundPanel = GetParent()->FindChildByName( m_sNavUpName , true );
  7209. if ( foundPanel != 0 )
  7210. {
  7211. m_NavUp = foundPanel;
  7212. }
  7213. }
  7214. vgui::Panel* nextPanel = m_NavUp;
  7215. if( m_NavUp && m_NavUp != first && !m_NavUp->IsVisible() )
  7216. {
  7217. Panel *firstPanel = first == NULL ? this : first;
  7218. nextPanel = nextPanel->GetNavUp( firstPanel );
  7219. }
  7220. return nextPanel;
  7221. }
  7222. vgui::Panel* Panel::GetNavDown( Panel *first )
  7223. {
  7224. if ( !m_NavDown && m_sNavDownName.Length() > 0 )
  7225. {
  7226. Panel* foundPanel = GetParent()->FindChildByName( m_sNavDownName , true );
  7227. if ( foundPanel != 0 )
  7228. {
  7229. m_NavDown = foundPanel->GetPanel();
  7230. }
  7231. }
  7232. vgui::Panel* nextPanel = m_NavDown;
  7233. if( m_NavDown && m_NavDown != first && !m_NavDown->IsVisible() )
  7234. {
  7235. Panel *firstPanel = first == NULL ? this : first;
  7236. nextPanel = nextPanel->GetNavDown( firstPanel );
  7237. }
  7238. return nextPanel;
  7239. }
  7240. vgui::Panel* Panel::GetNavLeft( Panel *first )
  7241. {
  7242. if ( !m_NavLeft && m_sNavLeftName.Length() > 0 )
  7243. {
  7244. Panel* foundPanel = GetParent()->FindChildByName( m_sNavLeftName , true );
  7245. if ( foundPanel != 0 )
  7246. {
  7247. m_NavLeft = foundPanel->GetPanel();
  7248. }
  7249. }
  7250. vgui::Panel* nextPanel = m_NavLeft;
  7251. if( m_NavLeft && m_NavLeft != first && !m_NavLeft->IsVisible() )
  7252. {
  7253. Panel *firstPanel = first == NULL ? this : first;
  7254. nextPanel = nextPanel->GetNavLeft( firstPanel );
  7255. }
  7256. return nextPanel;
  7257. }
  7258. vgui::Panel* Panel::GetNavRight( Panel *first )
  7259. {
  7260. if ( !m_NavRight && m_sNavRightName.Length() > 0 )
  7261. {
  7262. Panel* foundPanel = GetParent()->FindChildByName( m_sNavRightName , true );
  7263. if ( foundPanel != 0 )
  7264. {
  7265. m_NavRight = foundPanel->GetPanel();
  7266. }
  7267. }
  7268. vgui::Panel* nextPanel = m_NavRight;
  7269. if( m_NavRight && m_NavRight != first && !m_NavRight->IsVisible() )
  7270. {
  7271. Panel *firstPanel = first == NULL ? this : first;
  7272. nextPanel = nextPanel->GetNavRight( firstPanel );
  7273. }
  7274. return nextPanel;
  7275. }
  7276. vgui::Panel* Panel::GetNavUpPanel()
  7277. {
  7278. return m_NavUp;
  7279. }
  7280. vgui::Panel* Panel::GetNavDownPanel()
  7281. {
  7282. return m_NavDown;
  7283. }
  7284. vgui::Panel* Panel::GetNavLeftPanel()
  7285. {
  7286. return m_NavLeft;
  7287. }
  7288. vgui::Panel* Panel::GetNavRightPanel()
  7289. {
  7290. return m_NavRight;
  7291. }
  7292. void Panel::SetConsoleStylePanel( bool bConsoleStyle )
  7293. {
  7294. m_bIsConsoleStylePanel = bConsoleStyle;
  7295. }
  7296. bool Panel::IsConsoleStylePanel() const
  7297. {
  7298. return m_bIsConsoleStylePanel;
  7299. }
  7300. //-----------------------------------------------------------------------------
  7301. // Purpose: Utility class for handling message map allocation
  7302. //-----------------------------------------------------------------------------
  7303. class CPanelMessageMapDictionary
  7304. {
  7305. public:
  7306. CPanelMessageMapDictionary() : m_PanelMessageMapPool( sizeof(PanelMessageMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelMessageMapDictionary::m_PanelMessageMapPool" )
  7307. {
  7308. m_MessageMaps.RemoveAll();
  7309. }
  7310. PanelMessageMap *FindOrAddPanelMessageMap( char const *className );
  7311. PanelMessageMap *FindPanelMessageMap( char const *className );
  7312. private:
  7313. struct PanelMessageMapDictionaryEntry
  7314. {
  7315. PanelMessageMap *map;
  7316. };
  7317. char const *StripNamespace( char const *className );
  7318. CUtlDict< PanelMessageMapDictionaryEntry, int > m_MessageMaps;
  7319. CUtlMemoryPool m_PanelMessageMapPool;
  7320. };
  7321. char const *CPanelMessageMapDictionary::StripNamespace( char const *className )
  7322. {
  7323. if ( !strnicmp( className, "vgui::", 6 ) )
  7324. {
  7325. return className + 6;
  7326. }
  7327. return className;
  7328. }
  7329. //-----------------------------------------------------------------------------
  7330. // Purpose: Find but don't add mapping
  7331. //-----------------------------------------------------------------------------
  7332. PanelMessageMap *CPanelMessageMapDictionary::FindPanelMessageMap( char const *className )
  7333. {
  7334. int lookup = m_MessageMaps.Find( StripNamespace( className ) );
  7335. if ( lookup != m_MessageMaps.InvalidIndex() )
  7336. {
  7337. return m_MessageMaps[ lookup ].map;
  7338. }
  7339. return NULL;
  7340. }
  7341. #include <tier0/memdbgoff.h>
  7342. //-----------------------------------------------------------------------------
  7343. // Purpose:
  7344. //-----------------------------------------------------------------------------
  7345. PanelMessageMap *CPanelMessageMapDictionary::FindOrAddPanelMessageMap( char const *className )
  7346. {
  7347. PanelMessageMap *map = FindPanelMessageMap( className );
  7348. if ( map )
  7349. return map;
  7350. PanelMessageMapDictionaryEntry entry;
  7351. // use the alloc in place method of new
  7352. entry.map = new (m_PanelMessageMapPool.Alloc(sizeof(PanelMessageMap))) PanelMessageMap;
  7353. Construct(entry.map);
  7354. m_MessageMaps.Insert( StripNamespace( className ), entry );
  7355. return entry.map;
  7356. }
  7357. #include <tier0/memdbgon.h>
  7358. #if defined( VGUI_USEKEYBINDINGMAPS )
  7359. //-----------------------------------------------------------------------------
  7360. // Purpose: Utility class for handling keybinding map allocation
  7361. //-----------------------------------------------------------------------------
  7362. class CPanelKeyBindingMapDictionary
  7363. {
  7364. public:
  7365. CPanelKeyBindingMapDictionary() : m_PanelKeyBindingMapPool( sizeof(PanelKeyBindingMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelKeyBindingMapDictionary::m_PanelKeyBindingMapPool" )
  7366. {
  7367. m_MessageMaps.RemoveAll();
  7368. }
  7369. PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className );
  7370. PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className );
  7371. private:
  7372. struct PanelKeyBindingMapDictionaryEntry
  7373. {
  7374. PanelKeyBindingMap *map;
  7375. };
  7376. char const *StripNamespace( char const *className );
  7377. CUtlDict< PanelKeyBindingMapDictionaryEntry, int > m_MessageMaps;
  7378. CUtlMemoryPool m_PanelKeyBindingMapPool;
  7379. };
  7380. char const *CPanelKeyBindingMapDictionary::StripNamespace( char const *className )
  7381. {
  7382. if ( !strnicmp( className, "vgui::", 6 ) )
  7383. {
  7384. return className + 6;
  7385. }
  7386. return className;
  7387. }
  7388. //-----------------------------------------------------------------------------
  7389. // Purpose: Find but don't add mapping
  7390. //-----------------------------------------------------------------------------
  7391. PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindPanelKeyBindingMap( char const *className )
  7392. {
  7393. int lookup = m_MessageMaps.Find( StripNamespace( className ) );
  7394. if ( lookup != m_MessageMaps.InvalidIndex() )
  7395. {
  7396. return m_MessageMaps[ lookup ].map;
  7397. }
  7398. return NULL;
  7399. }
  7400. #include <tier0/memdbgoff.h>
  7401. //-----------------------------------------------------------------------------
  7402. // Purpose:
  7403. //-----------------------------------------------------------------------------
  7404. PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindOrAddPanelKeyBindingMap( char const *className )
  7405. {
  7406. PanelKeyBindingMap *map = FindPanelKeyBindingMap( className );
  7407. if ( map )
  7408. return map;
  7409. PanelKeyBindingMapDictionaryEntry entry;
  7410. // use the alloc in place method of new
  7411. entry.map = new (m_PanelKeyBindingMapPool.Alloc(sizeof(PanelKeyBindingMap))) PanelKeyBindingMap;
  7412. Construct(entry.map);
  7413. m_MessageMaps.Insert( StripNamespace( className ), entry );
  7414. return entry.map;
  7415. }
  7416. #include <tier0/memdbgon.h>
  7417. CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary()
  7418. {
  7419. static CPanelKeyBindingMapDictionary dictionary;
  7420. return dictionary;
  7421. }
  7422. #endif // VGUI_USEKEYBINDINGMAPS
  7423. CPanelMessageMapDictionary& GetPanelMessageMapDictionary()
  7424. {
  7425. static CPanelMessageMapDictionary dictionary;
  7426. return dictionary;
  7427. }
  7428. namespace vgui
  7429. {
  7430. //-----------------------------------------------------------------------------
  7431. // Purpose:
  7432. //-----------------------------------------------------------------------------
  7433. PanelMessageMap *FindOrAddPanelMessageMap( char const *className )
  7434. {
  7435. return GetPanelMessageMapDictionary().FindOrAddPanelMessageMap( className );
  7436. }
  7437. //-----------------------------------------------------------------------------
  7438. // Purpose: Find but don't add mapping
  7439. //-----------------------------------------------------------------------------
  7440. PanelMessageMap *FindPanelMessageMap( char const *className )
  7441. {
  7442. return GetPanelMessageMapDictionary().FindPanelMessageMap( className );
  7443. }
  7444. #if defined( VGUI_USEKEYBINDINGMAPS )
  7445. CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary()
  7446. {
  7447. static CPanelKeyBindingMapDictionary dictionary;
  7448. return dictionary;
  7449. }
  7450. //-----------------------------------------------------------------------------
  7451. // Purpose:
  7452. //-----------------------------------------------------------------------------
  7453. PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className )
  7454. {
  7455. return GetPanelKeyBindingMapDictionary().FindOrAddPanelKeyBindingMap( className );
  7456. }
  7457. //-----------------------------------------------------------------------------
  7458. // Purpose: Find but don't add mapping
  7459. //-----------------------------------------------------------------------------
  7460. PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className )
  7461. {
  7462. return GetPanelKeyBindingMapDictionary().FindPanelKeyBindingMap( className );
  7463. }
  7464. #endif // VGUI_USEKEYBINDINGMAPS
  7465. }